public inbox for linux-acpi@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] Add ACPI C4 support
@ 2025-09-15 20:43 Mario Limonciello (AMD)
  2025-09-15 20:43 ` [PATCH 1/2] x86/acpi/cstate: Remove open coded check for cpu_feature_enabled() Mario Limonciello (AMD)
  2025-09-15 20:43 ` [PATCH 2/2] ACPI: processor: Add support for ACPI C4 state Mario Limonciello (AMD)
  0 siblings, 2 replies; 6+ messages in thread
From: Mario Limonciello (AMD) @ 2025-09-15 20:43 UTC (permalink / raw)
  To: Rafael J . Wysocki, linux-acpi; +Cc: Mario Limonciello (AMD)

Some AMD systems have introduced support for ACPI C4.  Systems that
support ACPI C4 will enter CPU OFF at ACPI C3 and VDD OFF at ACPI C4.

VDD OFF is a requirement for s0i3, and thus if C4 isn't supported then
a system can't enter s0i3.

Add support for ACPI C4 to the processor idle driver, following similar
semantics of ACPI C3.

Mario Limonciello (AMD) (2):
  x86/acpi/cstate: Remove open coded check for cpu_feature_enabled()
  ACPI: processor: Add support for ACPI C4 state

 arch/x86/kernel/acpi/cstate.c |  2 +-
 drivers/acpi/processor_idle.c | 10 +++++++---
 include/acpi/actypes.h        |  5 +++--
 3 files changed, 11 insertions(+), 6 deletions(-)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/2] x86/acpi/cstate: Remove open coded check for cpu_feature_enabled()
  2025-09-15 20:43 [PATCH 0/2] Add ACPI C4 support Mario Limonciello (AMD)
@ 2025-09-15 20:43 ` Mario Limonciello (AMD)
  2025-09-22 17:17   ` Rafael J. Wysocki
  2025-09-15 20:43 ` [PATCH 2/2] ACPI: processor: Add support for ACPI C4 state Mario Limonciello (AMD)
  1 sibling, 1 reply; 6+ messages in thread
From: Mario Limonciello (AMD) @ 2025-09-15 20:43 UTC (permalink / raw)
  To: Rafael J . Wysocki, linux-acpi; +Cc: Mario Limonciello (AMD)

acpi_processor_power_init_bm_check() has an open coded implementation
of cpu_feature_enabled() to detect X86_FEATURE_ZEN.
Switch to using cpu_feature_enabled().

Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>
---
 arch/x86/kernel/acpi/cstate.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/kernel/acpi/cstate.c b/arch/x86/kernel/acpi/cstate.c
index 8698d66563ed6..0281703da5e26 100644
--- a/arch/x86/kernel/acpi/cstate.c
+++ b/arch/x86/kernel/acpi/cstate.c
@@ -89,7 +89,7 @@ void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags,
 		 */
 		flags->bm_control = 0;
 	}
-	if (c->x86_vendor == X86_VENDOR_AMD && c->x86 >= 0x17) {
+	if (cpu_feature_enabled(X86_FEATURE_ZEN)) {
 		/*
 		 * For all AMD Zen or newer CPUs that support C3, caches
 		 * should not be flushed by software while entering C3
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/2] ACPI: processor: Add support for ACPI C4 state
  2025-09-15 20:43 [PATCH 0/2] Add ACPI C4 support Mario Limonciello (AMD)
  2025-09-15 20:43 ` [PATCH 1/2] x86/acpi/cstate: Remove open coded check for cpu_feature_enabled() Mario Limonciello (AMD)
@ 2025-09-15 20:43 ` Mario Limonciello (AMD)
  2025-09-16 11:24   ` Rafael J. Wysocki
  1 sibling, 1 reply; 6+ messages in thread
From: Mario Limonciello (AMD) @ 2025-09-15 20:43 UTC (permalink / raw)
  To: Rafael J . Wysocki, linux-acpi; +Cc: Mario Limonciello (AMD)

The _CST object described in the ACPI specification [1] allows processors
to support any arbitrary number of power states that are described by
a package describing the register used, the type of C-state, latency
and the power consumption.

Currently the Linux kernel supports up to ACPI C3, and if a system
supports any further states they are ignored.  This causes problems on
some AMD hardware which can support up to ACPI C4.

AMD systems that support up to C3 will enter CPUOFF and VDDOFF
when entering C3. Systems that support up to C4 will enter CPUOFF
when going to C3 and will enter VDDOFF when entering into C4.

The existing semantics for bus mastering around C3 are also valid for C4,
so instead of hardcoding to C3, map then >= C3. In the case of s2idle
detect the deepest C-state supported and enter the deepest.

Link: https://uefi.org/htmlspecs/ACPI_Spec_6_4_html/08_Processor_Configuration_and_Control/declaring-processors.html?#cst-c-states [1]
Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>
---
 drivers/acpi/processor_idle.c | 10 +++++++---
 include/acpi/actypes.h        |  5 +++--
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 5dacf41d7cc0a..537b0119535ea 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -444,6 +444,10 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
 		case ACPI_STATE_C3:
 			acpi_processor_power_verify_c3(pr, cx);
 			break;
+		case ACPI_STATE_C4:
+			if (!cx->latency || !cx->address)
+				break;
+			cx->valid = 1;
 		}
 		if (!cx->valid)
 			continue;
@@ -685,7 +689,7 @@ static int __cpuidle acpi_idle_enter(struct cpuidle_device *dev,
 		return -EINVAL;
 
 	if (cx->type != ACPI_STATE_C1) {
-		if (cx->type == ACPI_STATE_C3 && pr->flags.bm_check)
+		if (cx->type >= ACPI_STATE_C3 && pr->flags.bm_check)
 			return acpi_idle_enter_bm(drv, pr, cx, index);
 
 		/* C2 to C1 demotion. */
@@ -708,7 +712,7 @@ static int __cpuidle acpi_idle_enter_s2idle(struct cpuidle_device *dev,
 {
 	struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu);
 
-	if (cx->type == ACPI_STATE_C3) {
+	if (cx->index == drv->state_count - 1) {
 		struct acpi_processor *pr = __this_cpu_read(processors);
 
 		if (unlikely(!pr))
@@ -754,7 +758,7 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr,
 		if (lapic_timer_needs_broadcast(pr, cx))
 			state->flags |= CPUIDLE_FLAG_TIMER_STOP;
 
-		if (cx->type == ACPI_STATE_C3) {
+		if (cx->type >= ACPI_STATE_C3) {
 			state->flags |= CPUIDLE_FLAG_TLB_FLUSHED;
 			if (pr->flags.bm_check)
 				state->flags |= CPUIDLE_FLAG_RCU_IDLE;
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index 8fe893d776dde..6c9f472af482c 100644
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
@@ -600,8 +600,9 @@ typedef u64 acpi_integer;
 #define ACPI_STATE_C1                   (u8) 1
 #define ACPI_STATE_C2                   (u8) 2
 #define ACPI_STATE_C3                   (u8) 3
-#define ACPI_C_STATES_MAX               ACPI_STATE_C3
-#define ACPI_C_STATE_COUNT              4
+#define ACPI_STATE_C4                   (u8) 4
+#define ACPI_C_STATES_MAX               ACPI_STATE_C4
+#define ACPI_C_STATE_COUNT              5
 
 /*
  * Sleep type invalid value
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 2/2] ACPI: processor: Add support for ACPI C4 state
  2025-09-15 20:43 ` [PATCH 2/2] ACPI: processor: Add support for ACPI C4 state Mario Limonciello (AMD)
@ 2025-09-16 11:24   ` Rafael J. Wysocki
  2025-09-16 18:55     ` Mario Limonciello
  0 siblings, 1 reply; 6+ messages in thread
From: Rafael J. Wysocki @ 2025-09-16 11:24 UTC (permalink / raw)
  To: Mario Limonciello (AMD); +Cc: Rafael J . Wysocki, linux-acpi

On Mon, Sep 15, 2025 at 10:43 PM Mario Limonciello (AMD)
<superm1@kernel.org> wrote:
>
> The _CST object described in the ACPI specification [1] allows processors
> to support any arbitrary number of power states that are described by
> a package describing the register used, the type of C-state, latency
> and the power consumption.
>
> Currently the Linux kernel supports up to ACPI C3, and if a system
> supports any further states they are ignored.  This causes problems on
> some AMD hardware which can support up to ACPI C4.
>
> AMD systems that support up to C3 will enter CPUOFF and VDDOFF
> when entering C3. Systems that support up to C4 will enter CPUOFF
> when going to C3 and will enter VDDOFF when entering into C4.
>
> The existing semantics for bus mastering around C3 are also valid for C4,
> so instead of hardcoding to C3, map then >= C3. In the case of s2idle
> detect the deepest C-state supported and enter the deepest.
>
> Link: https://uefi.org/htmlspecs/ACPI_Spec_6_4_html/08_Processor_Configuration_and_Control/declaring-processors.html?#cst-c-states [1]
> Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>
> ---
>  drivers/acpi/processor_idle.c | 10 +++++++---
>  include/acpi/actypes.h        |  5 +++--
>  2 files changed, 10 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
> index 5dacf41d7cc0a..537b0119535ea 100644
> --- a/drivers/acpi/processor_idle.c
> +++ b/drivers/acpi/processor_idle.c
> @@ -444,6 +444,10 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
>                 case ACPI_STATE_C3:
>                         acpi_processor_power_verify_c3(pr, cx);
>                         break;
> +               case ACPI_STATE_C4:
> +                       if (!cx->latency || !cx->address)
> +                               break;
> +                       cx->valid = 1;
>                 }
>                 if (!cx->valid)
>                         continue;
> @@ -685,7 +689,7 @@ static int __cpuidle acpi_idle_enter(struct cpuidle_device *dev,
>                 return -EINVAL;
>
>         if (cx->type != ACPI_STATE_C1) {
> -               if (cx->type == ACPI_STATE_C3 && pr->flags.bm_check)
> +               if (cx->type >= ACPI_STATE_C3 && pr->flags.bm_check)
>                         return acpi_idle_enter_bm(drv, pr, cx, index);
>
>                 /* C2 to C1 demotion. */
> @@ -708,7 +712,7 @@ static int __cpuidle acpi_idle_enter_s2idle(struct cpuidle_device *dev,
>  {
>         struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu);
>
> -       if (cx->type == ACPI_STATE_C3) {
> +       if (cx->index == drv->state_count - 1) {
>                 struct acpi_processor *pr = __this_cpu_read(processors);
>
>                 if (unlikely(!pr))
> @@ -754,7 +758,7 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr,
>                 if (lapic_timer_needs_broadcast(pr, cx))
>                         state->flags |= CPUIDLE_FLAG_TIMER_STOP;
>
> -               if (cx->type == ACPI_STATE_C3) {
> +               if (cx->type >= ACPI_STATE_C3) {
>                         state->flags |= CPUIDLE_FLAG_TLB_FLUSHED;
>                         if (pr->flags.bm_check)
>                                 state->flags |= CPUIDLE_FLAG_RCU_IDLE;
> diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
> index 8fe893d776dde..6c9f472af482c 100644
> --- a/include/acpi/actypes.h
> +++ b/include/acpi/actypes.h
> @@ -600,8 +600,9 @@ typedef u64 acpi_integer;
>  #define ACPI_STATE_C1                   (u8) 1
>  #define ACPI_STATE_C2                   (u8) 2
>  #define ACPI_STATE_C3                   (u8) 3
> -#define ACPI_C_STATES_MAX               ACPI_STATE_C3
> -#define ACPI_C_STATE_COUNT              4
> +#define ACPI_STATE_C4                   (u8) 4
> +#define ACPI_C_STATES_MAX               ACPI_STATE_C4
> +#define ACPI_C_STATE_COUNT              5

Don't you need to update ACPICA accordingly?

>
>  /*
>   * Sleep type invalid value
> --

The current point in the cycle is kind of unsuitable for changes like
this.  I'd prefer to revisit it after 6.18-rc1.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 2/2] ACPI: processor: Add support for ACPI C4 state
  2025-09-16 11:24   ` Rafael J. Wysocki
@ 2025-09-16 18:55     ` Mario Limonciello
  0 siblings, 0 replies; 6+ messages in thread
From: Mario Limonciello @ 2025-09-16 18:55 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: Rafael J . Wysocki, linux-acpi

On 9/16/25 6:24 AM, Rafael J. Wysocki wrote:
> On Mon, Sep 15, 2025 at 10:43 PM Mario Limonciello (AMD)
> <superm1@kernel.org> wrote:
>>
>> The _CST object described in the ACPI specification [1] allows processors
>> to support any arbitrary number of power states that are described by
>> a package describing the register used, the type of C-state, latency
>> and the power consumption.
>>
>> Currently the Linux kernel supports up to ACPI C3, and if a system
>> supports any further states they are ignored.  This causes problems on
>> some AMD hardware which can support up to ACPI C4.
>>
>> AMD systems that support up to C3 will enter CPUOFF and VDDOFF
>> when entering C3. Systems that support up to C4 will enter CPUOFF
>> when going to C3 and will enter VDDOFF when entering into C4.
>>
>> The existing semantics for bus mastering around C3 are also valid for C4,
>> so instead of hardcoding to C3, map then >= C3. In the case of s2idle
>> detect the deepest C-state supported and enter the deepest.
>>
>> Link: https://uefi.org/htmlspecs/ACPI_Spec_6_4_html/08_Processor_Configuration_and_Control/declaring-processors.html?#cst-c-states [1]
>> Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>
>> ---
>>   drivers/acpi/processor_idle.c | 10 +++++++---
>>   include/acpi/actypes.h        |  5 +++--
>>   2 files changed, 10 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
>> index 5dacf41d7cc0a..537b0119535ea 100644
>> --- a/drivers/acpi/processor_idle.c
>> +++ b/drivers/acpi/processor_idle.c
>> @@ -444,6 +444,10 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
>>                  case ACPI_STATE_C3:
>>                          acpi_processor_power_verify_c3(pr, cx);
>>                          break;
>> +               case ACPI_STATE_C4:
>> +                       if (!cx->latency || !cx->address)
>> +                               break;
>> +                       cx->valid = 1;
>>                  }
>>                  if (!cx->valid)
>>                          continue;
>> @@ -685,7 +689,7 @@ static int __cpuidle acpi_idle_enter(struct cpuidle_device *dev,
>>                  return -EINVAL;
>>
>>          if (cx->type != ACPI_STATE_C1) {
>> -               if (cx->type == ACPI_STATE_C3 && pr->flags.bm_check)
>> +               if (cx->type >= ACPI_STATE_C3 && pr->flags.bm_check)
>>                          return acpi_idle_enter_bm(drv, pr, cx, index);
>>
>>                  /* C2 to C1 demotion. */
>> @@ -708,7 +712,7 @@ static int __cpuidle acpi_idle_enter_s2idle(struct cpuidle_device *dev,
>>   {
>>          struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu);
>>
>> -       if (cx->type == ACPI_STATE_C3) {
>> +       if (cx->index == drv->state_count - 1) {
>>                  struct acpi_processor *pr = __this_cpu_read(processors);
>>
>>                  if (unlikely(!pr))
>> @@ -754,7 +758,7 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr,
>>                  if (lapic_timer_needs_broadcast(pr, cx))
>>                          state->flags |= CPUIDLE_FLAG_TIMER_STOP;
>>
>> -               if (cx->type == ACPI_STATE_C3) {
>> +               if (cx->type >= ACPI_STATE_C3) {
>>                          state->flags |= CPUIDLE_FLAG_TLB_FLUSHED;
>>                          if (pr->flags.bm_check)
>>                                  state->flags |= CPUIDLE_FLAG_RCU_IDLE;
>> diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
>> index 8fe893d776dde..6c9f472af482c 100644
>> --- a/include/acpi/actypes.h
>> +++ b/include/acpi/actypes.h
>> @@ -600,8 +600,9 @@ typedef u64 acpi_integer;
>>   #define ACPI_STATE_C1                   (u8) 1
>>   #define ACPI_STATE_C2                   (u8) 2
>>   #define ACPI_STATE_C3                   (u8) 3
>> -#define ACPI_C_STATES_MAX               ACPI_STATE_C3
>> -#define ACPI_C_STATE_COUNT              4
>> +#define ACPI_STATE_C4                   (u8) 4
>> +#define ACPI_C_STATES_MAX               ACPI_STATE_C4
>> +#define ACPI_C_STATE_COUNT              5
> 
> Don't you need to update ACPICA accordingly?

Thanks, I've got a PR opened.

> 
>>
>>   /*
>>    * Sleep type invalid value
>> --
> 
> The current point in the cycle is kind of unsuitable for changes like
> this.  I'd prefer to revisit it after 6.18-rc1.

OK! I wanted this out a few weeks ago but was waiting for positive Q/A 
results.

I'll rebase/resend after 6.18-rc1.


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/2] x86/acpi/cstate: Remove open coded check for cpu_feature_enabled()
  2025-09-15 20:43 ` [PATCH 1/2] x86/acpi/cstate: Remove open coded check for cpu_feature_enabled() Mario Limonciello (AMD)
@ 2025-09-22 17:17   ` Rafael J. Wysocki
  0 siblings, 0 replies; 6+ messages in thread
From: Rafael J. Wysocki @ 2025-09-22 17:17 UTC (permalink / raw)
  To: Mario Limonciello (AMD); +Cc: Rafael J . Wysocki, linux-acpi

On Mon, Sep 15, 2025 at 10:43 PM Mario Limonciello (AMD)
<superm1@kernel.org> wrote:
>
> acpi_processor_power_init_bm_check() has an open coded implementation
> of cpu_feature_enabled() to detect X86_FEATURE_ZEN.
> Switch to using cpu_feature_enabled().
>
> Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>
> ---
>  arch/x86/kernel/acpi/cstate.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/x86/kernel/acpi/cstate.c b/arch/x86/kernel/acpi/cstate.c
> index 8698d66563ed6..0281703da5e26 100644
> --- a/arch/x86/kernel/acpi/cstate.c
> +++ b/arch/x86/kernel/acpi/cstate.c
> @@ -89,7 +89,7 @@ void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags,
>                  */
>                 flags->bm_control = 0;
>         }
> -       if (c->x86_vendor == X86_VENDOR_AMD && c->x86 >= 0x17) {
> +       if (cpu_feature_enabled(X86_FEATURE_ZEN)) {
>                 /*
>                  * For all AMD Zen or newer CPUs that support C3, caches
>                  * should not be flushed by software while entering C3
> --

Applied as 6.18 material, thanks!

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2025-09-22 17:18 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-15 20:43 [PATCH 0/2] Add ACPI C4 support Mario Limonciello (AMD)
2025-09-15 20:43 ` [PATCH 1/2] x86/acpi/cstate: Remove open coded check for cpu_feature_enabled() Mario Limonciello (AMD)
2025-09-22 17:17   ` Rafael J. Wysocki
2025-09-15 20:43 ` [PATCH 2/2] ACPI: processor: Add support for ACPI C4 state Mario Limonciello (AMD)
2025-09-16 11:24   ` Rafael J. Wysocki
2025-09-16 18:55     ` Mario Limonciello

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox