From: Christian Loehle <christian.loehle@arm.com>
To: "Rafael J. Wysocki (Intel)" <rafael@kernel.org>
Cc: Viresh Kumar <viresh.kumar@linaro.org>,
linux-pm@vger.kernel.org, linux-acpi@vger.kernel.org,
linux-kernel@vger.kernel.org, Jie Zhan <zhanjie9@hisilicon.com>,
Lifeng Zheng <zhenglifeng1@huawei.com>,
Pierre Gondois <pierre.gondois@arm.com>,
Sumit Gupta <sumitg@nvidia.com>,
Sudeep Holla <sudeep.holla@arm.com>,
Ionela Voinescu <ionela.voinescu@arm.com>,
zhongqiu.han@oss.qualcomm.com, Sashiko <sashiko-bot@kernel.org>
Subject: Re: [PATCH v6 02/15] ACPI: CPPC: Validate _CPC entry and control semantics
Date: Mon, 14 Sep 2026 10:29:35 +0100 [thread overview]
Message-ID: <92b9c67b-677c-4cfe-8055-13f8e3e9c2cf@arm.com> (raw)
In-Reply-To: <CAJZ5v0ieZt_FSM4e=F_UjvN_oZbbiU_aHQgfFk2jifqW2Un5rw@mail.gmail.com>
On 9/10/26 18:13, Rafael J. Wysocki (Intel) wrote:
> On Fri, Sep 4, 2026 at 6:57 PM Rafael J. Wysocki (Intel)
> <rafael@kernel.org> wrote:
>>
>> On Thu, Sep 3, 2026 at 10:02 PM Christian Loehle
>> <christian.loehle@arm.com> wrote:
>>>
>>> On 9/3/26 20:44, Rafael J. Wysocki (Intel) wrote:
>>>> On Thu, Sep 3, 2026 at 9:27 PM Rafael J. Wysocki (Intel)
>>>> <rafael@kernel.org> wrote:
>>>>>
>>>>> On Sun, Aug 30, 2026 at 3:32 PM Christian Loehle
>>>>> <christian.loehle@arm.com> wrote:
>>>>>>
>>>>>> On 8/30/26 12:56, Christian Loehle wrote:
>>>>>>> Writable _CPC controls are Register descriptors encoded as Buffer objects.
>>>>>>> Integer entries represent fixed values or unsupported optional registers;
>>>>>>> Autonomous Selection Integer 1 is the special immutable form which enables
>>>>>>> operation without Desired Performance.
>>>>>>>
>>>>>>> The parser accepts arbitrary object types and cpc_write() assumes that its
>>>>>>> argument contains a GAS. Malformed firmware can therefore make it interpret
>>>>>>> an Integer union member as a register.
>>>>>>>
>>>>>>> Validate the portion of each encoding consumed by the driver: bound Integer
>>>>>>> DWORD forms to 32 bits, and require Buffer entries to start with a complete
>>>>>>> Generic Register descriptor with the expected header. Continue tolerating
>>>>>>> Integer 0 for an absent optional register and retain type checks in
>>>>>>> cpc_write() as defense in depth. Reject an attempt to disable immutable
>>>>>>> Autonomous Selection instead of silently applying only the EPP part of the
>>>>>>> request.
>>>>>>>
>>>>>>> Capability registers are read into u64 temporaries but exposed through u32
>>>>>>> fields. Reject values above U32_MAX instead of allowing them to be
>>>>>>> truncated. In particular, a truncated Highest Performance value can become
>>>>>>> a zero divisor in the performance-to-frequency conversion. Enforce the
>>>>>>> required ordering from Highest through Nominal, Lowest Nonlinear, and
>>>>>>> Lowest Performance, and constrain a present Guaranteed Performance to the
>>>>>>> inclusive Lowest-to-Nominal range. Also reject reversed frequency anchors
>>>>>>> and unequal frequency anchors with identical performance anchors. Those
>>>>>>> invalid tuples otherwise make affine-conversion differences wrap or divide
>>>>>>> by zero.
>>>>>>>
>>>>>>> Check mandatory object presence separately from the Integer-zero convention
>>>>>>> for absent optional fields. ACPI does not reserve zero in the abstract
>>>>>>> Lowest Performance scale, so accept a present Lowest Performance DWORD of
>>>>>>> zero when distinct frequency anchors provide a usable nonzero physical
>>>>>>> minimum. Retain the old rejection when that mapping is unavailable and the
>>>>>>> fallback conversion would expose a 0 kHz cpufreq endpoint.
>>>>>>>
>>>>>>> Minimum Performance also defines zero as a real no-limit value, but the
>>>>>>> exported cppc_set_perf() interface historically used zero to omit a bound.
>>>>>>> Add explicit validity flags so callers can request zero without changing
>>>>>>> that legacy convention. Populate the flags when reading the controls and
>>>>>>> mark the bounds supplied by amd-pstate explicitly.
>>>>>>>
>>>>>>> Performance Limited is listed as a required Buffer, but the interface does
>>>>>>> not depend on it to control performance and the specification permits a
>>>>>>> platform with no limiting indication to always report zero. Preserve
>>>>>>> the compatibility with firmware that represents that case using a NULL
>>>>>>> register descriptor instead of disabling CPPC entirely.
>>>>>>>
>>>>>>> Emit an error when a present _CPC package fails parsing or initialization
>>>>>>> so such firmware and resource failures no longer silently suppress cpufreq.
>>>>>>> Initialize malformed-package failures to -EINVAL and preserve specific
>>>>>>> allocation, mapping, and unsupported-access errors in that diagnostic.
>>>>>>>
>>>>>>> Fixes: 337aadff8e45 ("ACPI: Introduce CPU performance controls using CPPC")
>>>>>>> Reported-by: Sashiko <sashiko-bot@kernel.org>
>>>>>>> Link: https://sashiko.dev/#/patchset/20260724134251.1632824-1-christian.loehle%40arm.com
>>>>>>> Signed-off-by: Christian Loehle <christian.loehle@arm.com>
>>>>>>> ---
>>>>>>> drivers/acpi/cppc_acpi.c | 172 ++++++++++++++++++++++++++++++-----
>>>>>>> drivers/cpufreq/amd-pstate.c | 12 ++-
>>>>>>> include/acpi/cppc_acpi.h | 2 +
>>>>>>> 3 files changed, 159 insertions(+), 27 deletions(-)
>>>>>>>
>>>>>>> diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
>>>>>>> index 3b8cdf88e31d..6f3ffa4a1845 100644
>>>>>>> --- a/drivers/acpi/cppc_acpi.c
>>>>>>> +++ b/drivers/acpi/cppc_acpi.c
>>>>>>> @@ -129,6 +129,21 @@ static DEFINE_PER_CPU(struct cpc_desc *, cpc_desc_ptr);
>>>>>>> !!(cpc)->cpc_entry.int_value : \
>>>>>>> !IS_NULL_REG(&(cpc)->cpc_entry.reg))
>>>>>>>
>>>>>>> +static bool cpc_is_writable(const struct cpc_register_resource *cpc)
>>>>>>> +{
>>>>>>> + return cpc->type == ACPI_TYPE_BUFFER &&
>>>>>>> + !IS_NULL_REG(&cpc->cpc_entry.reg);
>>>>>>> +}
>>>>>>> +
>>>>>>> +static bool cpc_entry_present(const struct cpc_register_resource *cpc)
>>>>>>> +{
>>>>>>> + if (cpc->type == ACPI_TYPE_INTEGER)
>>>>>>> + return true;
>>>>>>> +
>>>>>>> + return cpc->type == ACPI_TYPE_BUFFER &&
>>>>>>> + !IS_NULL_REG(&cpc->cpc_entry.reg);
>>>>>>> +}
>>>>>>> +
>>>>>>> /*
>>>>>>> * Each bit indicates the optionality of the register in per-cpu
>>>>>>> * cpc_regs[] with the corresponding index. 0 means mandatory and 1
>>>>>>> @@ -142,6 +157,29 @@ static DEFINE_PER_CPU(struct cpc_desc *, cpc_desc_ptr);
>>>>>>> */
>>>>>>> #define IS_OPTIONAL_CPC_REG(reg_idx) (REG_OPTIONAL & (1U << (reg_idx)))
>>>>>>>
>>>>>>> +static bool cpc_integer_entry_valid(unsigned int reg_idx, u64 value)
>>>>>>> +{
>>>>>>> + switch (reg_idx) {
>>>>>>> + case HIGHEST_PERF:
>>>>>>> + case NOMINAL_PERF:
>>>>>>> + case LOW_NON_LINEAR_PERF:
>>>>>>> + case LOWEST_PERF:
>>>>>>> + case CTR_WRAP_TIME:
>>>>>>> + case REFERENCE_PERF:
>>>>>>> + case LOWEST_FREQ:
>>>>>>> + case NOMINAL_FREQ:
>>>>>>> + return value <= U32_MAX;
>>>>>>
>>>>>>
>>>>>> Sashiko:
>>>>>> "Does this incorrectly restrict the counter wraparound time to 32 bits?
>>>>>> The ACPI specification allows firmware to provide a 64-bit QWord integer
>>>>>> for the Counter Wraparound Time. The cppc_perf_fb_ctrs structure already
>>>>>> models this as a 64-bit value internally
>>>>>> If firmware provides a valid 64-bit integer exceeding U32_MAX for this
>>>>>> register, cpc_integer_entry_valid() will return false and completely abort
>>>>>> CPPC initialization for the CPU. Can we remove this restriction for
>>>>>> CTR_WRAP_TIME?"
>>>>>
>>>>>> This is true. ACPI spec 6.6 and 6.5 (Table 8.23) describe it as
>>>>>> Integer (DWORD) or Buffer
>>>>>> The 64-bit internal representation is only for the case of firmware
>>>>>> providing it as Buffer.
>>>>
>>>> Sashiko is right, the table in the spec is wrong. If it is Integer,
>>>> it is 64-bit.
>>>>
>>>> The size of an Integer in ASL cannot be restricted.
>>>
>>> Duh, thanks!
>>>
>>>>
>>>>>>
>>>>>>> + case AUTO_SEL_ENABLE:
>>>>>>> + return value <= 1;
>>>>>>> + case DESIRED_PERF:
>>>>>>> + /* Validated against Autonomous Selection after parsing. */
>>>>>>> + return value == 0;
>>>>>>> + default:
>>>>>>> + /* Tolerate the customary Integer 0 for an absent option. */
>>>>>>> + return value == 0 && IS_OPTIONAL_CPC_REG(reg_idx);
>>>>>>> + }
>>>>>>> +}
>>>>>>> +
>>>>>> Sashiko:
>>>>>> "Does this incorrectly restrict the counter wraparound time to 32 bits?
>>>>>> The ACPI specification allows firmware to provide a 64-bit QWord integer
>>>>>> for the Counter Wraparound Time. The cppc_perf_fb_ctrs structure already
>>>>>> models this as a 64-bit value internally.
>>>>>> If firmware provides a valid 64-bit integer exceeding U32_MAX for this
>>>>>> register, cpc_integer_entry_valid() will return false and completely abort
>>>>>> CPPC initialization for the CPU. Can we remove this restriction for
>>>>>> CTR_WRAP_TIME?"
>>>>>
>>>>> It looks like you pasted the same comment twice. Or did Sashiko hallucinate?
>>>>
>>>> Well, its other comment is actually different from the first one. Let
>>>> me paste it:
>>>
>>> Apparently I hallucinated :)
>>>
>>>>
>>>> Will this strict rejection break CPPC initialization on compliant firmware
>>>> that provides non-zero integers for other optional capabilities?
>>>> For capability registers not explicitly listed in the switch statement
>>>> above, such as GUARANTEED_PERF or TIME_WINDOW, the ACPI 6.5 specification
>>>> explicitly allows platforms to provide fixed non-zero values encoded as
>>>> Integer objects.
>>>>
>>>> When firmware provides a valid non-zero integer for these optional
>>>> registers, this default case enforces that the value must be zero. Since
>>>> acpi_cppc_processor_probe() fails and returns -EINVAL when this returns
>>>> false, it will completely disable cpufreq and CPPC support for the CPU.
>>>> Should we allow non-zero integer values for these other optional registers?
>>>>
>>>>>> GUARANTEED_PERF and TIME_WINDOW: both are Buffer-only Register descriptors.
>>>>>> Nonzero Integer encodings are invalid and Integer 0 is tolerated because
>>>>>> the previous parser allowed it too. I don't know of any platform describing
>>>>>> this myself.
>>>>
>>>> Strictly speaking Integer 0 is not allowed, see
>>>>
>>>> https://uefi.org/specs/ACPI/6.6/08_Processor_Configuration_and_Control.html#cpc-continuous-performance-control
>>>
>>> I'm happy to reject it too, I was just being careful here because I only have
>>> a tiny subset of ACPI platforms to test this on with and it's for -fixes
>>
>> Instead of rejecting it entirely, you may log an FW_BUG message when
>> it is used, to avoid breaking legacy platforms that possibly used it.
>
> Still waiting for an update here and reviews from folks.
>
> If this is the only patch that needs to be updated, please just send
> an update of it alone.
I know, unfortunately I had to update some of the later patches, too.
I'll send the entire series shortly.
Thanks!
next prev parent reply other threads:[~2026-09-14 9:29 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-30 11:56 [PATCH v6 0/15] ACPI: CPPC: Fix register access and lifetime bugs Christian Loehle
2026-08-30 11:56 ` [PATCH v6 01/15] ACPI: CPPC: Validate the _CPC package header Christian Loehle
2026-08-30 11:56 ` [PATCH v6 02/15] ACPI: CPPC: Validate _CPC entry and control semantics Christian Loehle
2026-08-30 13:32 ` Christian Loehle
2026-09-03 19:27 ` Rafael J. Wysocki (Intel)
2026-09-03 19:44 ` Rafael J. Wysocki (Intel)
2026-09-03 20:02 ` Christian Loehle
2026-09-04 16:57 ` Rafael J. Wysocki (Intel)
2026-09-10 17:13 ` Rafael J. Wysocki (Intel)
2026-09-14 9:29 ` Christian Loehle [this message]
2026-08-30 11:56 ` [PATCH v6 03/15] ACPI: CPPC: Propagate performance-control write errors Christian Loehle
2026-08-30 11:56 ` [PATCH v6 04/15] ACPI: CPPC: Use 64-bit masks for register fields Christian Loehle
2026-08-30 11:56 ` [PATCH v6 05/15] ACPI: CPPC: Serialize PCC single-register payload updates Christian Loehle
2026-08-30 11:56 ` [PATCH v6 06/15] ACPI: CPPC: Serialize PCC EPP " Christian Loehle
2026-08-30 11:56 ` [PATCH v6 07/15] ACPI: CPPC: Release CPC descriptors through kobject Christian Loehle
2026-08-30 11:56 ` [PATCH v6 08/15] ACPI: CPPC: Release PCC data after probe failures Christian Loehle
2026-08-30 11:56 ` [PATCH v6 09/15] ACPI: CPPC: Reject unsafe cross-CPU SystemMemory RMW Christian Loehle
2026-08-30 11:56 ` [PATCH v6 10/15] ACPI: CPPC: Reject direct reads of write-only controls Christian Loehle
2026-08-30 11:56 ` [PATCH v6 11/15] ACPI: CPPC: Validate and access PCC register layouts Christian Loehle
2026-08-30 11:56 ` [PATCH v6 12/15] ACPI: CPPC: Validate SystemIO " Christian Loehle
2026-08-30 11:56 ` [PATCH v6 13/15] ACPI: CPPC: Validate PCC overlaps across processors Christian Loehle
2026-08-30 11:56 ` [PATCH v6 14/15] ACPI: CPPC: Validate SystemIO " Christian Loehle
2026-08-30 11:56 ` [PATCH v6 15/15] ACPI: CPPC: Clear Performance Limited without a stale read Christian Loehle
2026-09-07 10:33 ` Sumit Gupta
2026-09-07 12:37 ` Christian Loehle
2026-09-07 18:14 ` Sumit Gupta
2026-09-01 6:24 ` [PATCH v6 0/15] ACPI: CPPC: Fix register access and lifetime bugs Christian Loehle
2026-09-01 20:10 ` Mario Limonciello
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=92b9c67b-677c-4cfe-8055-13f8e3e9c2cf@arm.com \
--to=christian.loehle@arm.com \
--cc=ionela.voinescu@arm.com \
--cc=linux-acpi@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=pierre.gondois@arm.com \
--cc=rafael@kernel.org \
--cc=sashiko-bot@kernel.org \
--cc=sudeep.holla@arm.com \
--cc=sumitg@nvidia.com \
--cc=viresh.kumar@linaro.org \
--cc=zhanjie9@hisilicon.com \
--cc=zhenglifeng1@huawei.com \
--cc=zhongqiu.han@oss.qualcomm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®