PIIX4 chipset: (non-)exit from CPU states C2, C3 on interrupt

Andriy Gapon avg at icyb.net.ua
Wed Feb 20 22:55:44 UTC 2008


This is a report on an issue that I had with using C2 CPU power state on
a system based on PIIX4E chipset. I think that other users of the
chipsets from PIIX4 family might be affected as well.
Also, this might be an informative reading for hackers chasing similar
problems.

Reference material:
Intel(R) 82371AB PCI-TO-ISA/IDE Xcelerator (PIIX4) Datasheet
http://www.intel.com/design/intarch/datashts/290562.htm

Intel® 82371AB PIIX4, Intel® 82371EB PIIX4E and Intel® 82371MB PIIX4M
Specification Update
http://www.intel.com/design/chipsets/specupdt/297738.htm

Intel® 82371EB (PIIX4E) Specification Update
http://www.intel.com/design/chipsets/specupdt/290635.htm

Relevant information can be found in the following sections of the
original document and in updates/corrections/errata for them:
11.2. Clock Control
7.2.3. PMCNTRL—POWER MANAGEMENT CONTROL REGISTER (IO)
7.1.16. DEVACTB—DEVICE ACTIVITY B (FUNCTION 3)

My summarized understanding:
To behave in ACPI-compliant way with respect to C2 and C3 states the
chipset must generate "Stop Break" events on any interrupt.
This is because ACPI specification says the following about C2 state:
"The hardware can exit this state for any reason, but must always exit
this state whenever an interrupt is to be presented to the processor."
For C3 it repeats the same and adds the following:
"or when BM_RLD is set and a bus master is attempting to gain access to
memory."
According to PIIX4 documents the chipset exits "clock control state"
either on "Stop Break" event or on "Burst" event. I leave the latter out
of consideration because it is not ACPI compliant, CPU state is
controlled by hardware, not by OS.

Here's an excerpt from description of DEVACTB register, 6 lower bits are
described:
5 IRQ8# Clock Event Enable (BRLD_EN_IRQ8)—R/W. 1=Enable an unmasked
IRQ8# to, when asserted, generate a Fast Burst Timer reload or Stop
Break event. 0=Disable.

4 PME Clock Event Enable (BRLD_EN_PME)—R/W. 1=Enable an asserted SMI#,
GPI1#, PWRBTN#, or LID signal to generate a Fast Burst Timer reload or
Stop Break event. 0=Disable.

3 Undefined. Must be written as a 0.

2 Keyboard/Mouse Global Reload Enable (GRLD_EN_KBC_MS)—R/W. 1=Enable an
assertion of IRQ1 or IRQ12/M to reload the Global Standby Timer. 0=Disable.

1 IRQ Clock Event Enable (BRLD_EN_IRQ)—R/W. 1=Enable an unmasked
IRQ[1,3:7,9:15], NMI, or INIT to generate a Burst event or Stop Break
event. 0=Disable.

0 IRQ0 Clock Event Enable (BRLD_EN_IRQ0)—R/W. 1=Enable an unmasked IRQ0
to generate a Burst event or Stop Break event. 0=Disable.

In order for the hardware to behave in ACPI-compliant way, that is to
generate "Stop Break" events on all interrupts, the following bits of
this register must be set:
0 - for IRQ0,
5 - for IRQ8,
1 - for the rest of the maskable interrupts

You can read a saga about my investigation of a C2 behavior of a FreeBSD
7.0-RC1 system installed on a hardware based on PIIX4E chipset:
http://docs.FreeBSD.org/cgi/mid.cgi?479F0ED4.9030709
This is a long thread with a couple of side-branches that keeps you in
suspense until the very end. For those without time to waste, the
following link is a pointer to where the most interesting details appear:
http://docs.FreeBSD.org/cgi/mid.cgi?47BB375C.5010208

In short: on this system bit 5 of the mentioned above register was reset
(i.e. 0), so RTC/IRQ8 didn't cause exit from C2 state. Thus, with
cx_lowest=C2, RTC interrupt was handled at the predictable times,
usually back-to-back after IRQ0 handler. As a result statclock()
gathered CPU usage information (user:nice:system:interrupt:idle) at
quite deterministic moments, so the statics was very biased in favor of
interrupt usage.

This is what the register had after boot:
$ pciconf -r pci0:0:7:3 0x58
03040c07

After doing the following CPU statics became reasonable:
pciconf -w pci0:0:7:3 0x58 0x03040c27

>From pciconf -lv:
intsmb0 at pci0:0:7:3:     class=0x068000 card=0x00000000 chip=0x71138086
rev=0x02 hdr=0x00
    vendor     = 'Intel Corporation'
    device     = '82371AB/EB/MB PIIX4/4E/4M Power Management Controller'
    class      = bridge

In the end, my suggestion is that acpi_cpu code should check value of
those 3 bits and set them if necessary.

I am not actually sure why I have bit 5 reset to 0. Maybe because this
is a fault of a vendor of my motherboard/BIOS. Maybe I unwittingly
caused this by changing some BIOS setting, but if this is the case, then
the setting must appear under a name and description that I would never
relate to this issue.
Another possible resolution is to check the bits, but instead of
changing them just refuse to use anything lower than C1.


-- 
Andriy Gapon


More information about the freebsd-hackers mailing list