OpenBSD Journal

Developer blog: marco

Contributed by marco on from the ACPI-interrupts-are-more-complex-than-they-should-be dept.

More ACPI excitement! Jordan has been steadily improving the AML interpreter and by now it is stable enough for the device drivers. On that note in my previous blog I displayed some of the debug functionality I built into them. Although that is awesome, it is not the reason for this blog. This one is dedicated to GPEs or General Purpose Events. I can't tell you how awful ACPI does this! Jordan had been working off and on on this and we were blaming the interpreter being not far enough alongfor them not working. Well that was only part of the truth. It required a lot of magic sequences to make this work. To top this all of we really needed process context to handle the interrupts (context during interrupts? HELLO!!) due to the unpredictable nature of the AML code. So what we did is the following: we created a kernel thread that sleeps until it gets woken up by the actual ACPI ISR. In the kernel thread we determine the source and call into the, if registered, callback in the device driver. Sounds complicated? Nah it was a piece of cake compared to the hellish interrupt magic we had to go through. The sequence of events to handle interrupts is:
1. During autoconf create a deferred thread to deal with interrupts while retaining context.
2. In the kernel thread initialize the GPEs by writing all zeros to the GPE_ENABLE register and ones to GPE_STATUS.
3. In the kernel thread initialize which GPEs you want, we for now only care about 0x1d events (button events)
4. Go to sleep waiting for an event
... a while later ...
5. We receive an event in the ACPI ISR.
6. Disable all ACPI interrupts (shit you not)
7. Wakeup the kernel thread
8. In the kernel thread figure out who gets the interrupt
9. In the kernel thread execute the AML code associated with the interrupt
10. In the kernel thread acknowledge the interrupt
11. Re-enable the interrupts and go to step 4
Phew, that's a lot of work for a stupid power or sleep button event. Besides the amount of code it is quite unforgiving too. The only positive news here is that the device drivers that gets these events are extremely simple since a lot of the magic was handled in the kernel thread. Anyway after this started working it was simple to rig the ACPI button driver with for example the power down code. So why in the world isn't it working while we are receiving the interrupts?

This is a screamer... Some boxes were powering down and some were not. Since our laptops were working we had not yet gotten around to figure out why some people's computers were acting up. Alexander (grange@) just committed some code to clean up the set state code so he immediately got blamed :-) Jordan and I started debugging this, went back and forth with old and new code but it was unreliable and Alex's code really seemed good. Many reboots later we figure out that the values we are sending to the power down function is garbage. Hmmm so how did it get corrupted? Ah a good old struct sleeptype[5] that should have been struct sleeptype[6]; crap an off by one in the array declaration. So tons of debug code later it all makes sense suddenly and a 1 line commit. HA! and now we have powerdown when we hit the button, schaweet!!

(Comments are closed)


Comments
  1. By Brad (216.138.195.228) brad at comstyle dot com on

    It is a good thing proper shutdown code was commited by Alexander for ACPI to do soft power off. You know how annoying it is having to actually get up to turn off that new fangled server ;))

  2. By Bernhard (128.130.39.94) on

    Sounds great! Can't wait to actually test this on my laptop. Keep up the good work!

  3. By Anonymous Coward (142.166.105.108) on

    I had read (here and other places) that ACPI was poorly designed and -- often as not -- badly implemented. It sounds like the rumours were, if anything, understated. Congrats on (apparently) getting this one to work fellas! I hear that some of these hair-thicking creams can work wonders ...

  4. By Anonymous Coward (128.171.90.200) on

    So if you are using kernel threads, are these the new rthreads I have been hearing about ( sorry I have not been keeping up recently ) ?

    Comments
    1. By Anonymous Coward (71.145.208.228) on

      Kernel threads and rthreads have less than nothing to do with each other...

      Comments
      1. By Anonymous Coward (128.171.90.200) on

        of course because rthreads are user level, but I thought there was no threading in the kernel ? I'm not sure why ....

        Comments
        1. By tedu (69.12.168.114) on

          man 9 kthread

Credits

Copyright © - Daniel Hartmeier. All rights reserved. Articles and comments are copyright their respective authors, submission implies license to publish on this web site. Contents of the archive prior to as well as images and HTML templates were copied from the fabulous original deadly.org with Jose's and Jim's kind permission. This journal runs as CGI with httpd(8) on OpenBSD, the source code is BSD licensed. undeadly \Un*dead"ly\, a. Not subject to death; immortal. [Obs.]