We have an arm64 server which encounters an acpi_ged event (APEI Corrected Error) on boot, as soon as the driver loads and the interrupt is unmasked by virtue of it being registered.
With the current code, on a platform like arm64 where EARLY_AP_STARTUP is not in use, this means we encounter the interrupt when running on just the base CPU. The interrupt fires, AcpiOsExecute queues the event, and then the isr exits and the interrupt is unmasked. This leads to another interrupt immediately, which causes the same event to be read and queued again, and we eventually livelock with the console spewing "AcpiOsExecute: failed to enqueue task, consider increasing the debug.acpi.max_tasks tunable".
I first attempted to fix this by deferring acpi_ged interrupt setup until after the APs were running (https://reviews.freebsd.org/D42141). This "works", but has several problems. First, several duplicate events are queued on the CPU handling the interrupt before another core can parse the event and eventually ack the interrupt. Second, this does not help in the case of a single CPU.
On that review, @jhb pointed out that according to the spec (5.6.4: General Purpose Event Handling), the OS must leave the interrupt source disabled until EOI. This is not a good fit for our method of queuing the work (including the EOI ack of the interrupt), since when the ithread is done, the interrupt will be unmasked.
The only solution I can see is to simply handle the event directly, which is what this patch does. With it, I've seen no complaints about sleeping in the wrong context, etc, and I see just a single interrupt on acpi_ged (rather than the 3-5 I'd see with the previous attempt in https://reviews.freebsd.org/D42141)