DF-3640 / trigger.c
/* * DF-3640 โ bnx(4) bnx_reset() acquires the NVRAM software-arbitration * lock and never releases it * * Trigger (HARDWARE REQUIRED โ cannot run on the audit guest): * * sys/dev/netif/bnx/if_bnx.c: * 2585: CSR_WRITE_4(sc, BGE_NVRAM_SWARB, BGE_NVRAMSWARB_SET1); * 2586: for (i = 0; i < 8000; i++) { * 2587: if (CSR_READ_4(sc, BGE_NVRAM_SWARB) & * BGE_NVRAMSWARB_GNT1) * 2588: break; * 2589: DELAY(20); * 2590: } * 2591: if (i == 8000) * 2592: if_printf(..., "NVRAM lock timedout!\n"); * * ...and nowhere in if_bnx.c does BGE_NVRAMSWARB_CLR1 ever appear * (grep -c NVRAMSWARB_CLR1 sys/dev/netif/bnx/if_bnx.c == 0). * * bnx_reset() is called on every bnx_attach(), bnx_init() (ifconfig up, * MTU change, watchdog reset, error recovery via bnx_handle_status) and * bnx_stop(). Once granted, the host driver's NVRAM arbitration bit * (SET1/GNT1) stays asserted for the lifetime of the driver โ the * on-chip NVRAM/flash arbiter is permanently held by the host. * * Contrast with the code this driver was derived from: * - bge(4) pairs acquire/release around every NVRAM access * (sys/dev/netif/bge/if_bge.c:551-590: SET1 ... CLR1), and * - upstream tg3/FreeBSD bge release the arbitration after chip * reset ("Release NVRAM arbitration" in tg3_chip_reset / * FreeBSD bge_reset), because the reset does NOT give back the * grant. * bce(4) had the same class of bug filed as DF-3605 (lock held on an * error path). * * Consequence: other agents of the NVRAM arbiter โ principally the APE * management firmware (NC-SI/DASH) that these chips run for * out-of-band management โ can never win arbitration while the host * driver is loaded. Management-plane NVRAM access (persistent * configuration) breaks from boot until power cycle. No kernel memory * corruption; availability/interop impact on the management plane. * * The audit QEMU guest has no Broadcom NIC (run.log: * NO_BROADCOM_DEVICE), so bnx_reset() is unreachable there. */ #include <sys/types.h> #include <stdio.h> int main(void) { fprintf(stderr, "DF-3640: requires bnx(4) hardware. On such a system, after the\n" "driver loads, read BGE_NVRAM_SWARB (dev.bnx.0 regs via kgdb or\n" "pciconf): the GNT1 grant bit stays set forever because bnx_reset\n" "never writes BGE_NVRAMSWARB_CLR1 (grep: 0 occurrences in\n" "if_bnx.c; bge releases at if_bge.c:588).\n"); return 0; } |