Power management timer and ACPI interrupt setup

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
LiamT
Posts: 9
Joined: Sun Jul 12, 2015 2:21 am
Contact:

Power management timer and ACPI interrupt setup

Post by LiamT »

Hello, this is my first post on the OSDev forum, so I'll do my best to follow the guidelines!

So i've been developing my latest kernel project for a while now, and this is the furthest i've ever gotten with writing a kernel. I'm at the stage where i'm trying to implement a concrete timing source to help in managing my SMP multitasking environment. As most OSDever's seem to do, i started out using the PIT and the TSC as the basis for my kernel timing. This worked wonderfully for me to implement a task Sleep() call, but now that i've moved from UP to SMP, as well as finding out that the TSC is usually variant, I want to implement a better clock source. My choice for this was the ACPI management timer.

My problem now is that I cannot seem to get the PM Timer's overflow event to trigger correctly. According to the ACPI specification, when I have the TMR_EN bit set in the PM1a/b_EVT_BLK ACPI register, and the TMR_STS bit is set in the corresponding status register, it should trigger a System Control Interrupt, which I do receive, but unfortunately, this only happens once. The specification doesn't seem to specify as to whether or not the TMR_STS bit needs to be cleared to receive the interrupt again, but that's what i've assumed tentatively, trying both clearing it and leaving it, and still nothing. I should note that I have verified that the timer is counting on all of my test platforms, and about as accurately as i can test using the PIT. Interestingly, when I test in VirtualBox, about twenty minutes later, I begin to receive a storm of these events for no reason i can fathom. This only seems to happen in VirtualBox, and i suspect it might be some quirk with whatever i'm doing wrong in the ACPI interrupt handler? I really am stuck on this.

I've searched through the forums and googled relentlessly, to no avail. It seems there aren't a lot of people besides Microsoft and Ubuntu developers who are super interested in the PM Timer's protocol. I've even resorted to looking at the linux code for the PM Timer, but it doesn't seem to implement the interrupt, relying instead on the fact that it's update code should be called at least once between the (minimum) 24 bit overflow of the counter, or at least once every four seconds. I've been toying with the idea of just leaving my kernel's timing service free-running so it can keep semi-accurate track of system uptime, but that seems wasteful and unnecessary to me when the timer interrupt has been specifically provided to simulate a larger timer.

Here is the code I use to parse the FADT. I'm pretty sure that this is working correctly, as i'm able to set up the ACPI interrupt properly, and it's header verifies correctly.
FADT.h
FADT.cpp

This is where I set up the ACPI interrupt, as well as it's hooking mechanism. This is also the base namespace for all ACPI stuff, and includes a definition of the Generic Address Structure used in the FADT
ACPI.h
ACPI.cpp

Finally, here is where i initialize the PM Timer, install it's interrupt hook, read it's actual value, and update the emulated 64-bit timer.
PMTimer.h
PMTimer.cpp

Additionally, points of interest might be how the timer is used in timing code:
TaskSleep.h
TaskSleep.cpp

Or the main kernel initialization, where i'm testing it all:
kinit.cpp
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Power management timer and ACPI interrupt setup

Post by Brendan »

Hi,
LiamT wrote:My problem now is that I cannot seem to get the PM Timer's overflow event to trigger correctly. According to the ACPI specification, when I have the TMR_EN bit set in the PM1a/b_EVT_BLK ACPI register, and the TMR_STS bit is set in the corresponding status register, it should trigger a System Control Interrupt, which I do receive, but unfortunately, this only happens once.
For ACPI there's an embedded controller. Various things (power button, temperature sensors, lid switches, etc) send signals to the embedded controller. When ACPI is in "legacy mode" the embedded controller sends an SMI which is handed by the firmware's SMM code. When ACPI is in "ACPI mode" the embedded controller sends an SCI and the OS passes it to the firmware's AML code to handle it; and the AML code sends events to the OS. Of course the OS should never switch from "legacy mode" to "ACPI mode" until it has a full AML interpreter ready to handle the events.

Now, from what you've described, it sounds like you've completely screwed everything up by trying to handle the SCI yourself with no AML interpreter. This means that (e.g.) if the motherboard is overheating and is desperately trying to get the AML to increase fan speed and/or reduce CPU speed to cope, you ignore all that and just assume the SCI was caused by timer overflow and let the motherboard melt.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
LiamT
Posts: 9
Joined: Sun Jul 12, 2015 2:21 am
Contact:

Re: Power management timer and ACPI interrupt setup

Post by LiamT »

Ah, alright! I was really hoping that wasn't the case. I guess before I try to take advantage of ACPI, I should really have a thorough understanding of what it is it's requiring of me. How embarrassing! I have only been running in an isolated, cheap (and emulated, for any case in which i fully enabled ACPI) environment for just this reason, so thankfully no melted motherboards. Kryten can spend another day out of silicon heaven.

Thank you for saving me from doing something really really dumb.

Still, it's too bad that you have to have a whole bytecode interpreter just to do the equivalent of an EOI.
jnc100
Member
Member
Posts: 775
Joined: Mon Apr 09, 2007 12:10 pm
Location: London, UK
Contact:

Re: Power management timer and ACPI interrupt setup

Post by jnc100 »

As an aside, it is probably better to use a per-CPU timing source for scheduling and short sleeps (e.g. usleep and friends). For this, the local APIC timer takes some beating and is well documented in the Intel CPU docs. For a system wide one for keeping track of clock time and longer sleeps (e.g. seconds onwards) you would want to use something with a predictable tick rate e.g. the HPET (which you can detect just by parsing ACPI tables, without the need for an AML interpreter) or PIT if not available.

Regards,
John.
Post Reply