> From: Theo de Raadt <dera...@cvs.openbsd.org>
> Date: Sat, 22 Feb 2014 09:55:41 -0700
> 
> This menas the acpitz bug must be found, and fixed.  You need to reach
> out to an acpi hacker, like pirofti, to help diagnose the AML issue
> which underlies this.

I had a quick look at the AML and it looks is if the embedded
controller is involved in reading the temperature.  Perhaps SMM is
touching it behind our back, so I looked at the global lock code again
that is supposed to protect against that happening.

Noticed that acpiec(4) tries to acquire the global lock, but doesn't
actually check whether it got it.  The diff below fixes this by
unifying the code that checks for recursion and does the spinning.
Might fix things, or might lock up the machine solidly.  Only one way
to find out...

If this doesn't help, you should check whether memory at the following
addresses:

0xDAF7CE18
0xDAF9EF18
0xDAF7ADC0
0xDAF79F98

isn't actually marked as available by the BIOS.  ACPI apparently
stored important data at those addresses, but if OpenBSD thinks that
memory is available and overwrites things, bad things will happen.

I believe the easiest way to find out is to type "machine memory" at
the boot> prompt.


Index: dsdt.c
===================================================================
RCS file: /cvs/src/sys/dev/acpi/dsdt.c,v
retrieving revision 1.205
diff -u -p -r1.205 dsdt.c
--- dsdt.c      12 Dec 2013 20:56:01 -0000      1.205
+++ dsdt.c      22 Feb 2014 18:03:16 -0000
@@ -736,72 +736,58 @@ static long global_lock_count = 0;
 void
 acpi_glk_enter(void)
 {
-       acpi_acquire_glk(&acpi_softc->sc_facs->global_lock);
-}
-
-void
-acpi_glk_leave(void)
-{
-       int x;
-
-       if (acpi_release_glk(&acpi_softc->sc_facs->global_lock)) {
-               /*
-                * If pending, notify the BIOS that the lock was released
-                * by the OSPM. No locking is needed because nobody outside
-                * the ACPI thread is touching this register.
-                */
-               x = acpi_read_pmreg(acpi_softc, ACPIREG_PM1_CNT, 0);
-               x |= ACPI_PM1_GBL_RLS;
-               acpi_write_pmreg(acpi_softc, ACPIREG_PM1_CNT, 0, x);
-       }
-}
-
-void
-aml_lockfield(struct aml_scope *scope, struct aml_value *field)
-{
        int st = 0;
 
-       if (AML_FIELD_LOCK(field->v_field.flags) != AML_FIELD_LOCK_ON)
-               return;
-
-       /* If lock is already ours, just continue */
+       /* If lock is already ours, just continue. */
        if (global_lock_count++)
                return;
 
-       /* Spin to acquire lock */
+       /* Spin to acquire the lock. */
        while (!st) {
                st = acpi_acquire_glk(&acpi_softc->sc_facs->global_lock);
                /* XXX - yield/delay? */
        }
-
-       return;
 }
 
 void
-aml_unlockfield(struct aml_scope *scope, struct aml_value *field)
+acpi_glk_leave(void)
 {
-       int st, x, s;
+       int st, x;
 
-       if (AML_FIELD_LOCK(field->v_field.flags) != AML_FIELD_LOCK_ON)
-               return;
-
-       /* If we are the last ones, turn out the lights */
+       /* If we are the last one, turn out the lights. */
        if (--global_lock_count)
                return;
 
-       /* Release lock */
        st = acpi_release_glk(&acpi_softc->sc_facs->global_lock);
        if (!st)
                return;
 
-       /* Signal others if someone waiting */
-       s = spltty();
+       /*
+        * If pending, notify the BIOS that the lock was released by
+        * OSPM.  No locking is needed because nobody outside the ACPI
+        * thread is supposed to touch this register.
+        */
        x = acpi_read_pmreg(acpi_softc, ACPIREG_PM1_CNT, 0);
        x |= ACPI_PM1_GBL_RLS;
        acpi_write_pmreg(acpi_softc, ACPIREG_PM1_CNT, 0, x);
-       splx(s);
+}
+
+void
+aml_lockfield(struct aml_scope *scope, struct aml_value *field)
+{
+       if (AML_FIELD_LOCK(field->v_field.flags) != AML_FIELD_LOCK_ON)
+               return;
+
+       acpi_glk_enter();
+}
+
+void
+aml_unlockfield(struct aml_scope *scope, struct aml_value *field)
+{
+       if (AML_FIELD_LOCK(field->v_field.flags) != AML_FIELD_LOCK_ON)
+               return;
 
-       return;
+       acpi_glk_leave();
 }
 
 /*

Reply via email to