Reset register flag versus the actual register

From: Alexander Sack <pisymbol_at_gmail.com>
Date: Sun, 25 Jan 2009 20:35:40 -0500
Hi Everybody:

I've ran into the quintessential "it works on Linux but does not work
on FreeBSD" vendor comment regarding the boxes ability to reboot
successfully.  I'm running FreeBSD-6.1 but this also applies the
FreeBSD-CURRENT as well.  The problem boils down to the fact that the
BIOS does set the ResetRegister bit in the FADT feature flags.
However, I've noticed that latest stable Linux kernel has the
following logic with respect to the reset register:

acpi_reboot():

  18        /* Is the reset register supported? */
  19        if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) ||
  20            rr->bit_width != 8 || rr->bit_offset != 0)
  21                return;

http://lxr.linux.no/linux+v2.6.28/drivers/acpi/reboot.c

CURRENT looks like this via the shutdown_final EVENTHANDLE:

acpi_shutdown_final():

1821     } else if ((howto & RB_HALT) == 0 &&
1822         (AcpiGbl_FADT.Flags & ACPI_FADT_RESET_REGISTER) &&
1823         sc->acpi_handle_reboot) {
1824         /* Reboot using the reset register. */

http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/dev/acpica/acpi.c?rev=1.254

Two questions:

1)  Why is the sysctl acpi_handle_reboot zero by default?  Shouldn't
it be more prudent to rely on the ACPI reboot hook than the legacy
keyboard controller methods?  I realize there is some history here but
it would seem to me that the "&&" should be an "||" which would allow
me to override the ACPI_FADT_RESET_REGISTER flag and force an ACPI
reset?

2)  Is there something to be said for a patch like this:

-- acpi.c.0	2009-01-25 19:56:48.000000000 -0500
+++ acpi.c	2009-01-25 20:10:34.000000000 -0500
_at__at_ -1818,18 +1818,20 _at__at_
 	    DELAY(1000000);
 	    printf("ACPI power-off failed - timeout\n");
 	}
-    } else if ((howto & RB_HALT) == 0 &&
-	(AcpiGbl_FADT.Flags & ACPI_FADT_RESET_REGISTER) &&
-	sc->acpi_handle_reboot) {
-	/* Reboot using the reset register. */
-	status = AcpiHwLowLevelWrite(
-	    AcpiGbl_FADT.ResetRegister.BitWidth,
-	    AcpiGbl_FADT.ResetValue, &AcpiGbl_FADT.ResetRegister);
-	if (ACPI_FAILURE(status)) {
-	    printf("ACPI reset failed - %s\n", AcpiFormatException(status));
-	} else {
-	    DELAY(1000000);
-	    printf("ACPI reset failed - timeout\n");
+    } else if ((howto & RB_HALT) == 0 && sc->acpi_handle_reboot) {
+	if ((AcpiGbl_FADT.Flags & ACPI_FADT_RESET_REGISTER) ||
+	    (AcpiGbl_FADT.ResetRegister.BitWidth != 8) ||
+	    (AcpiGbl_FADT.ResetRegister.BitOffset != 0)) {
+	    /* Reboot using the reset register. */
+	    status = AcpiHwLowLevelWrite(
+		    AcpiGbl_FADT.ResetRegister.BitWidth,
+		    AcpiGbl_FADT.ResetValue, &AcpiGbl_FADT.ResetRegister);
+	    if (ACPI_FAILURE(status)) {
+		printf("ACPI reset failed - %s\n", AcpiFormatException(status));
+	    } else {
+		DELAY(1000000);
+		printf("ACPI reset failed - timeout\n");
+	    }
 	}
     } else if (sc->acpi_do_disable && panicstr == NULL) {
 	/*

Basically, if the ResetRegister is filled in despite the FADT feature
flags bit, trust it and move forward (Linux logic).  That's the reason
why my box reboots correctly on Linux and utterly hangs miserably on
FreeBSD.  I understand this is a BIOS/ACPI bug, I understand the
keyboard controller reboot method should probably be emulated in the
BIOS (though the vendor could argue they no longer support legacy
methods which is to me not necessarily a bad thing), and I understand
that FreeBSD is not Linux.  With that all said, I don't see the
downside here with respect to reboot with respect to either points
(allow the user to force the issue or believe the ResetRegister values
themselves as a test for validity).

Feedback most appreciated!

Thanks!

-aps
Received on Mon Jan 26 2009 - 01:00:23 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:39:41 UTC