Issue #623 has been updated by felix sanchez.
Machine: ThinkPad T480 (i7-8650U), currently running Libreboot/coreboot
1d8755f2425 (2026-09-28). Before flashing I took a full 16 MiB dump of the
Lenovo factory firmware (BIOS version N24RE03WL), so I could compare the vendor
ACPI tables against what coreboot emits.
== How the vendor tables were extracted (reproducible) ==
The ACPI tables are not stored in clear in the Lenovo image, so plain grep/iasl
on the dump finds nothing:
* UEFIExtract on the 16 MiB dump parses the firmware volumes but yields no
ACPI tables and no ACPI table GUIDs (EB9D2D30-... for DSDT, etc.).
* The DXE volume is stored as an LZMA-compressed blob. Decompressing it
(FORMAT_ALONE) yields ~14.9 MiB containing the real tables.
* Locating tables by signature + valid header length + valid checksum finds
1 DSDT (140807 bytes, OEM ID "INTEL", table ID "SKL") and 34 SSDTs.
* iasl -d on those gives readable ASL.
== What the vendor firmware actually contains ==
The DSDT only declares the processors and defers to an SSDT:
External (_PR_.PR00, DeviceObj)
External (_PR_.PR00.LPSS, PkgObj)
External (_PR_.PR00.TPSS, PkgObj)
If (CondRefOf (\_PR.PR00._PPC))
If ((CondRefOf (\_PR.PR00._PSS) && CondRefOf (\_PR.PR00._PPC)))
SSDT "Cpu0Ist" (OEM ID "PmRef") implements the interface on PR00:
Method (_PPC, 0) { Return (\_PR.CPPC) }
Name (_PCT, Package (0x02)
{
ResourceTemplate () { Register (FFixedHW, 0x00, 0x00,
0x0000000000000000, ,) },
ResourceTemplate () { Register (FFixedHW, 0x00, 0x00,
0x0000000000000000, ,) }
})
Method (_PSS, 0)
{
If ((\_SB.OSCP & 0x0400)) // OS supports CPPC
{
Return (TPSS)
}
Else
{
Return (LPSS)
}
}
SSDT "ApIst" covers the remaining CPUs by delegating to PR00:
Scope (\_PR.PR01)
{
Method (_PPC) { Return (\_PR.PR00._PPC ()) }
Method (_PCT) { Return (\_PR.PR00._PCT ()) }
Method (_PSS) { Return (\_PR.PR00._PSS ()) }
}
... repeated up to PR15.
== The important part ==
Every entry in both packages is the placeholder 0x80000000:
Name (LPSS, Package (0x10) // 16 states
{
Package (0x06) { 0x80000000, 0x80000000, 0x80000000,
0x80000000, 0x80000000, 0x80000000 },
...
})
Name (TPSS, Package (0x28) // 40 states
{
Package (0x06) { 0x80000000, 0x80000000, 0x80000000,
0x80000000, 0x80000000, 0x80000000 },
...
})
Unique values found in LPSS: 0x80000000. Unique values in TPSS: 0x80000000.
No real frequency (800/1900/4200 MHz) appears anywhere in the 34 SSDTs.
Likewise _PCT is a pair of FFixedHW registers with Address 0x0, Bit Width 0x00
and Bit Offset 0x00, i.e. also a placeholder.
This is consistent with the SSDT name ("Cpu0Ist" = CPU0 Initialization State
Table): the vendor firmware fills these tables in at runtime, presumably from
the CPU's own MSRs, and the ROM only carries the template.
== Why this matters for the fix ==
The reference .dsl files requested earlier in this ticket have been provided,
but they cannot be used to simply copy values into coreboot: there are no
values in them to copy. Implementing this in coreboot means generating
_PSS/_PCT/_PPC (and _PSD) at runtime, computing the state list from the CPU
(MSR_PLATFORM_INFO for the max non-turbo ratio, MSR_TURBO_RATIO_LIMIT for the
turbo bins), not backporting a static table.
Current state of coreboot, for reference (checked on 1d8755f2425): searching
src/mainboard/lenovo/sklkbl_thinkpad/ and src/soc/intel/sklake/ for _PCT, _PPC,
_PSS and Processor returns 0 matches. The only related symbol left in
src/arch/x86/acpi/statdef.asl is the unused #define NOTIFY_CPU_PPCCHG. So there
is no existing infrastructure to enable - it would be new code.
== Relation to Xen ==
Worth noting for anyone following this: Qubes' Xen already has HWP support
(QubesOS/qubes-vmm-xen#158, merged Feb 2023, which closed
QubesOS/qubes-issues#4604). But the HWP driver still needs the ACPI P-state
data to initialise its policy, so with no _PSS/_PPC/_PCT present,
cpufreq=xen:hwp
has nothing to work with and the CPU stays pinned. Hence the firmware side is
the blocker, and it is the one that has not moved.
----------------------------------------
Bug #623: On T480/S, missing P-state data from ACPI tables prevents Xen from
performing frequency scaling
https://ticket.coreboot.org/issues/623#change-2411
* Author: herme herme
* Status: New
* Priority: Normal
* Target version: none
* Start date: 2026-01-16
* Affected versions: main
* Affected hardware: T480/S
* Affected OS: QubesOS
----------------------------------------
Hello
Currently, P-state data is missing from ACPI tables on T480/S. On my T480S
running libreboot, this was confirmed by using the iasl command to decompile
the tables at `/sys/firmware/acpi/tables/`; grepping for `_PSS`, `_PCT` and
`_PPC` didn't return any results. [Another
user](https://codeberg.org/libreboot/lbmk/issues/394) has confirmed that this
is also the case for the similar T480 device, with latest release build of
libreboot (26.01 RC1).
Meanwhile, in the vendor T480S BIOS, this data is present (contributed by @henk
on #coreboot IRC channel):
```
# grep -r -e _PCT -e _PPC -e _PSS *.dsl
DSDT.dsl: If (CondRefOf (\_PR.PR00._PPC))
DSDT.dsl: If ((CondRefOf (\_PR.PR00._PSS) && CondRefOf
(\_PR.PR00._PPC)))
SSDT1.dsl: External (_PR_.PR00._PSS, MethodObj) // 0 Arguments
SSDT1.dsl: Name (_PPC, Zero) // _PPC: Performance Present Capabilities
SSDT1.dsl: If (CondRefOf (\_PR.PR00._PSS))
SSDT1.dsl: Method (_PSS, 0, NotSerialized) // _PSS: Performance
Supported States
SSDT1.dsl: If (CondRefOf (\_PR.PR00._PSS))
SSDT1.dsl: Return (\_PR.PR00._PSS ())
SSDT1.dsl: If (CondRefOf (\_PR.PR00._PSS))
SSDT8.dsl: If (CondRefOf (\_PR.PR00._PSS))
```
The Linux kernel doesn't rely on this data to perform frequency scaling,
because native support is provided by the intel_pstate driver. However, the Xen
kernel lacks this native support. When the data is missing, as in my case, the
Xen-based QubesOS runs underclocked and is only barely usable.
--
You have received this notification because you have either subscribed to it,
or are involved in it.
To change your notification preferences, please click here:
https://ticket.coreboot.org/my/account
_______________________________________________
coreboot mailing list -- [email protected]
To unsubscribe send an email to [email protected]