Skip to content

Instantly share code, notes, and snippets.

@joemiller
Created October 20, 2022 18:55
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joemiller/9f5698c5634d4a93d101985dc5238365 to your computer and use it in GitHub Desktop.
Save joemiller/9f5698c5634d4a93d101985dc5238365 to your computer and use it in GitHub Desktop.
openbsd 7.1 kernel patch to stop a GFE L6F ACPI interrupt storm
--- /usr/src/sys/dev/acpi/acpi.c.orig Mon Oct 3 16:26:55 2022
+++ /usr/src/sys/dev/acpi/acpi.c Mon Oct 3 16:30:29 2022
@@ -2269,6 +2269,18 @@
{
struct aml_node *node = arg;
uint8_t mask, en;
+
+ /* bad bios. mask/ignore the GPE _L6F (0x6f) interrupt */
+ if (gpe == 0x6f && (sc->gpe_table[gpe].flags & GPE_LEVEL)) {
+ static unsigned short i;
+ if (i == 0) {
+ i++;
+ printf("acpi_gpe %d %s IGNORING\n", gpe, node->name);
+ }
+ return (0);
+ }
+
+ printf("acpi_gpe %d %s\n", gpe, node->name);
dnprintf(10, "handling GPE %.2x\n", gpe);
aml_evalnode(sc, node, 0, NULL, NULL);
@joemiller
Copy link
Author

more details about this here: https://news.ycombinator.com/item?id=33279037

@bconway
Copy link

bconway commented Feb 24, 2023

This definitely works, but I don't think it's necessary to push the logic all the way down to the ACPI thread's task function. If you have a known-bad GPE, you can filter it at enable time, and no interrupts will ever be fielded. This covers both boot and resume paths:

--- acpi.c.orig	2023-02-23 12:34:25.000000000 -0600
+++ acpi.c	2023-02-23 12:35:29.000000000 -0600
@@ -2221,12 +2221,17 @@ acpi_add_device(struct aml_node *node, v
 void
 acpi_enable_onegpe(struct acpi_softc *sc, int gpe)
 {
+	if (gpe == 0x6f) {
+		printf("skipping buggy GPE %.2x\n", gpe);
+		return;
+	}
+
 	uint8_t mask, en;
 
 	/* Read enabled register */
 	mask = (1L << (gpe & 7));
 	en = acpi_read_pmreg(sc, ACPIREG_GPE_EN, gpe>>3);
-	dnprintf(50, "enabling GPE %.2x (current: %sabled) %.2x\n",
+	printf("enabling GPE %.2x (current: %sabled) %.2x\n",
 	    gpe, (en & mask) ? "en" : "dis", en);
 	acpi_write_pmreg(sc, ACPIREG_GPE_EN, gpe>>3, en | mask);
 }

As an alternative approach, I'm currently using a diff to detect and stomp on buggy/misbehaving GPEs, so it's safe to deploy to any system without fear of disabling a GPE that is otherwise behaving:

https://gist.github.com/bconway/4ce1748461eb28f2b7c68ddb05dba571

Unsolicited $0.02.

@joemiller
Copy link
Author

@bconway thank you!! that's great

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment