linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/9] intel_idle: More assorted cleanups
@ 2020-02-13 21:58 Rafael J. Wysocki
  2020-02-13 21:59 ` [PATCH 1/9] intel_idle: Simplify LAPIC timer reliability checks Rafael J. Wysocki
                   ` (8 more replies)
  0 siblings, 9 replies; 11+ messages in thread
From: Rafael J. Wysocki @ 2020-02-13 21:58 UTC (permalink / raw)
  To: Linux PM; +Cc: Len Brown, LKML, Zhang Rui, Rafael J. Wysocki, Chen Yu

Hi All,

This series of intel_idle cleanups (on top of 5.6-rc1) simplifies the code,
improves kerneldoc comments, reduces the post-initialization memory footprint
of the driver and makes some cosmetic changes, including bumping up the version
number which deserves that due to the recent significant changes.

Please refer to the changelogs of individual patches for details.

For easier access the series is available as a git branch at:

 git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git \
 intel_idle-cleanup

Thanks!




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

* [PATCH 1/9] intel_idle: Simplify LAPIC timer reliability checks
  2020-02-13 21:58 [PATCH 0/9] intel_idle: More assorted cleanups Rafael J. Wysocki
@ 2020-02-13 21:59 ` Rafael J. Wysocki
  2020-02-13 21:59 ` [PATCH 2/9] intel_idle: Clean up definitions of cpuidle callbacks Rafael J. Wysocki
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Rafael J. Wysocki @ 2020-02-13 21:59 UTC (permalink / raw)
  To: Linux PM; +Cc: Len Brown, LKML, Zhang Rui, Rafael J. Wysocki, Chen Yu

From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>

The lapic_timer_always_reliable variable really takes only two values
and some arithmetic in intel_idle() related to comparing it with the
target C-state's MWAIT hint value is unnecessary.

Simplify the code by replacing lapic_timer_always_reliable with
a bool variable lapic_timer_always_reliable and dropping the
LAPIC_TIMER_ALWAYS_RELIABLE symbol along with the excess
computations in intel_idle().

While at it, add a comment explaining the branch taken in intel_idle()
if the LAPIC timer is only reliable in C1 and modify the related debug
message in intel_idle_init() accordingly (the modification of this
message in the only expected functional impact of the change made
here).

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/idle/intel_idle.c | 27 +++++++++++++--------------
 1 file changed, 13 insertions(+), 14 deletions(-)

diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index d55606608ac8..8d66efc53b89 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -66,10 +66,7 @@ static int max_cstate = CPUIDLE_STATE_MAX - 1;
 static unsigned int disabled_states_mask;
 
 static unsigned int mwait_substates;
-
-#define LAPIC_TIMER_ALWAYS_RELIABLE 0xFFFFFFFF
-/* Reliable LAPIC Timer States, bit 1 for C1 etc.  */
-static unsigned int lapic_timer_reliable_states = (1 << 1);	 /* Default to only C1 */
+static bool lapic_timer_always_reliable;
 
 struct idle_cpu {
 	struct cpuidle_state *state_table;
@@ -908,7 +905,6 @@ static __cpuidle int intel_idle(struct cpuidle_device *dev,
 	unsigned long ecx = 1; /* break on interrupt flag */
 	struct cpuidle_state *state = &drv->states[index];
 	unsigned long eax = flg2MWAIT(state->flags);
-	unsigned int cstate;
 	bool uninitialized_var(tick);
 	int cpu = smp_processor_id();
 
@@ -919,13 +915,16 @@ static __cpuidle int intel_idle(struct cpuidle_device *dev,
 	if (state->flags & CPUIDLE_FLAG_TLB_FLUSHED)
 		leave_mm(cpu);
 
-	if (!static_cpu_has(X86_FEATURE_ARAT)) {
-		cstate = (((eax) >> MWAIT_SUBSTATE_SIZE) &
-				MWAIT_CSTATE_MASK) + 1;
-		tick = false;
-		if (!(lapic_timer_reliable_states & (1 << (cstate)))) {
+	if (!static_cpu_has(X86_FEATURE_ARAT) && !lapic_timer_always_reliable) {
+		/*
+		 * Switch over to one-shot tick broadcast if the target C-state
+		 * is deeper than C1.
+		 */
+		if ((eax >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK) {
 			tick = true;
 			tick_broadcast_enter();
+		} else {
+			tick = false;
 		}
 	}
 
@@ -1555,7 +1554,7 @@ static int intel_idle_cpu_online(unsigned int cpu)
 {
 	struct cpuidle_device *dev;
 
-	if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE)
+	if (!lapic_timer_always_reliable)
 		tick_broadcast_enable();
 
 	/*
@@ -1647,15 +1646,15 @@ static int __init intel_idle_init(void)
 	}
 
 	if (boot_cpu_has(X86_FEATURE_ARAT))	/* Always Reliable APIC Timer */
-		lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE;
+		lapic_timer_always_reliable = true;
 
 	retval = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "idle/intel:online",
 				   intel_idle_cpu_online, NULL);
 	if (retval < 0)
 		goto hp_setup_fail;
 
-	pr_debug("lapic_timer_reliable_states 0x%x\n",
-		 lapic_timer_reliable_states);
+	pr_debug("Local APIC timer is reliable in %s\n",
+		 lapic_timer_always_reliable ? "all C-states" : "C1");
 
 	return 0;
 
-- 
2.16.4






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

* [PATCH 2/9] intel_idle: Clean up definitions of cpuidle callbacks
  2020-02-13 21:58 [PATCH 0/9] intel_idle: More assorted cleanups Rafael J. Wysocki
  2020-02-13 21:59 ` [PATCH 1/9] intel_idle: Simplify LAPIC timer reliability checks Rafael J. Wysocki
@ 2020-02-13 21:59 ` Rafael J. Wysocki
  2020-02-13 22:00 ` [PATCH 3/9] intel_idle: Relocate " Rafael J. Wysocki
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Rafael J. Wysocki @ 2020-02-13 21:59 UTC (permalink / raw)
  To: Linux PM; +Cc: Len Brown, LKML, Zhang Rui, Rafael J. Wysocki, Chen Yu

From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>

Add proper kerneldoc descriptions to intel_idle() and
intel_idle_s2idle(), annotate the latter with __cpuidle and
reorder the declarations of local variables in both of them to
reflect the mwait_idle_with_hints() arguments order.

No intentional functional impact.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/idle/intel_idle.c | 39 +++++++++++++++++++++++++++------------
 1 file changed, 27 insertions(+), 12 deletions(-)

diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 8d66efc53b89..5adc058c705d 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -892,19 +892,28 @@ static struct cpuidle_state dnv_cstates[] = {
 };
 
 /**
- * intel_idle
- * @dev: cpuidle_device
- * @drv: cpuidle driver
- * @index: index of cpuidle state
+ * intel_idle - Ask the processor to enter the given idle state.
+ * @dev: cpuidle device of the target CPU.
+ * @drv: cpuidle driver (assumed to point to intel_idle_driver).
+ * @index: Target idle state index.
+ *
+ * Use the MWAIT instruction to notify the processor that the CPU represented by
+ * @dev is idle and it can try to enter the idle state corresponding to @index.
+ *
+ * If the local APIC timer is not known to be reliable in the target idle state,
+ * enable one-shot tick broadcasting for the target CPU before executing MWAIT.
+ *
+ * Optionally call leave_mm() for the target CPU upfront to avoid wakeups due to
+ * flushing user TLBs.
  *
  * Must be called under local_irq_disable().
  */
 static __cpuidle int intel_idle(struct cpuidle_device *dev,
 				struct cpuidle_driver *drv, int index)
 {
-	unsigned long ecx = 1; /* break on interrupt flag */
 	struct cpuidle_state *state = &drv->states[index];
 	unsigned long eax = flg2MWAIT(state->flags);
+	unsigned long ecx = 1; /* break on interrupt flag */
 	bool uninitialized_var(tick);
 	int cpu = smp_processor_id();
 
@@ -937,16 +946,22 @@ static __cpuidle int intel_idle(struct cpuidle_device *dev,
 }
 
 /**
- * intel_idle_s2idle - simplified "enter" callback routine for suspend-to-idle
- * @dev: cpuidle_device
- * @drv: cpuidle driver
- * @index: state index
+ * intel_idle_s2idle - Ask the processor to enter the given idle state.
+ * @dev: cpuidle device of the target CPU.
+ * @drv: cpuidle driver (assumed to point to intel_idle_driver).
+ * @index: Target idle state index.
+ *
+ * Use the MWAIT instruction to notify the processor that the CPU represented by
+ * @dev is idle and it can try to enter the idle state corresponding to @index.
+ *
+ * Invoked as a suspend-to-idle callback routine with frozen user space, frozen
+ * scheduler tick and suspended scheduler clock on the target CPU.
  */
-static void intel_idle_s2idle(struct cpuidle_device *dev,
-			     struct cpuidle_driver *drv, int index)
+static __cpuidle void intel_idle_s2idle(struct cpuidle_device *dev,
+					struct cpuidle_driver *drv, int index)
 {
-	unsigned long ecx = 1; /* break on interrupt flag */
 	unsigned long eax = flg2MWAIT(drv->states[index].flags);
+	unsigned long ecx = 1; /* break on interrupt flag */
 
 	mwait_idle_with_hints(eax, ecx);
 }
-- 
2.16.4






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

* [PATCH 3/9] intel_idle: Relocate definitions of cpuidle callbacks
  2020-02-13 21:58 [PATCH 0/9] intel_idle: More assorted cleanups Rafael J. Wysocki
  2020-02-13 21:59 ` [PATCH 1/9] intel_idle: Simplify LAPIC timer reliability checks Rafael J. Wysocki
  2020-02-13 21:59 ` [PATCH 2/9] intel_idle: Clean up definitions of cpuidle callbacks Rafael J. Wysocki
@ 2020-02-13 22:00 ` Rafael J. Wysocki
  2020-05-23  0:04   ` Qian Cai
  2020-02-13 22:01 ` [PATCH 4/9] intel_idle: Add __initdata annotations to init time variables Rafael J. Wysocki
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 11+ messages in thread
From: Rafael J. Wysocki @ 2020-02-13 22:00 UTC (permalink / raw)
  To: Linux PM; +Cc: Len Brown, LKML, Zhang Rui, Rafael J. Wysocki, Chen Yu

From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>

Move the definitions of intel_idle() and intel_idle_s2idle() before
the definitions of cpuidle_state structures referring to them to
avoid having to use additional declarations of them (and drop those
declarations).

No functional impact.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/idle/intel_idle.c | 154 ++++++++++++++++++++++------------------------
 1 file changed, 75 insertions(+), 79 deletions(-)

diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 5adc058c705d..e0332d567735 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -83,10 +83,6 @@ struct idle_cpu {
 
 static const struct idle_cpu *icpu;
 static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
-static int intel_idle(struct cpuidle_device *dev,
-			struct cpuidle_driver *drv, int index);
-static void intel_idle_s2idle(struct cpuidle_device *dev,
-			      struct cpuidle_driver *drv, int index);
 static struct cpuidle_state *cpuidle_state_table;
 
 /*
@@ -112,6 +108,81 @@ static struct cpuidle_state *cpuidle_state_table;
 #define flg2MWAIT(flags) (((flags) >> 24) & 0xFF)
 #define MWAIT2flg(eax) ((eax & 0xFF) << 24)
 
+/**
+ * intel_idle - Ask the processor to enter the given idle state.
+ * @dev: cpuidle device of the target CPU.
+ * @drv: cpuidle driver (assumed to point to intel_idle_driver).
+ * @index: Target idle state index.
+ *
+ * Use the MWAIT instruction to notify the processor that the CPU represented by
+ * @dev is idle and it can try to enter the idle state corresponding to @index.
+ *
+ * If the local APIC timer is not known to be reliable in the target idle state,
+ * enable one-shot tick broadcasting for the target CPU before executing MWAIT.
+ *
+ * Optionally call leave_mm() for the target CPU upfront to avoid wakeups due to
+ * flushing user TLBs.
+ *
+ * Must be called under local_irq_disable().
+ */
+static __cpuidle int intel_idle(struct cpuidle_device *dev,
+				struct cpuidle_driver *drv, int index)
+{
+	struct cpuidle_state *state = &drv->states[index];
+	unsigned long eax = flg2MWAIT(state->flags);
+	unsigned long ecx = 1; /* break on interrupt flag */
+	bool uninitialized_var(tick);
+	int cpu = smp_processor_id();
+
+	/*
+	 * leave_mm() to avoid costly and often unnecessary wakeups
+	 * for flushing the user TLB's associated with the active mm.
+	 */
+	if (state->flags & CPUIDLE_FLAG_TLB_FLUSHED)
+		leave_mm(cpu);
+
+	if (!static_cpu_has(X86_FEATURE_ARAT) && !lapic_timer_always_reliable) {
+		/*
+		 * Switch over to one-shot tick broadcast if the target C-state
+		 * is deeper than C1.
+		 */
+		if ((eax >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK) {
+			tick = true;
+			tick_broadcast_enter();
+		} else {
+			tick = false;
+		}
+	}
+
+	mwait_idle_with_hints(eax, ecx);
+
+	if (!static_cpu_has(X86_FEATURE_ARAT) && tick)
+		tick_broadcast_exit();
+
+	return index;
+}
+
+/**
+ * intel_idle_s2idle - Ask the processor to enter the given idle state.
+ * @dev: cpuidle device of the target CPU.
+ * @drv: cpuidle driver (assumed to point to intel_idle_driver).
+ * @index: Target idle state index.
+ *
+ * Use the MWAIT instruction to notify the processor that the CPU represented by
+ * @dev is idle and it can try to enter the idle state corresponding to @index.
+ *
+ * Invoked as a suspend-to-idle callback routine with frozen user space, frozen
+ * scheduler tick and suspended scheduler clock on the target CPU.
+ */
+static __cpuidle void intel_idle_s2idle(struct cpuidle_device *dev,
+					struct cpuidle_driver *drv, int index)
+{
+	unsigned long eax = flg2MWAIT(drv->states[index].flags);
+	unsigned long ecx = 1; /* break on interrupt flag */
+
+	mwait_idle_with_hints(eax, ecx);
+}
+
 /*
  * States are indexed by the cstate number,
  * which is also the index into the MWAIT hint array.
@@ -891,81 +962,6 @@ static struct cpuidle_state dnv_cstates[] = {
 		.enter = NULL }
 };
 
-/**
- * intel_idle - Ask the processor to enter the given idle state.
- * @dev: cpuidle device of the target CPU.
- * @drv: cpuidle driver (assumed to point to intel_idle_driver).
- * @index: Target idle state index.
- *
- * Use the MWAIT instruction to notify the processor that the CPU represented by
- * @dev is idle and it can try to enter the idle state corresponding to @index.
- *
- * If the local APIC timer is not known to be reliable in the target idle state,
- * enable one-shot tick broadcasting for the target CPU before executing MWAIT.
- *
- * Optionally call leave_mm() for the target CPU upfront to avoid wakeups due to
- * flushing user TLBs.
- *
- * Must be called under local_irq_disable().
- */
-static __cpuidle int intel_idle(struct cpuidle_device *dev,
-				struct cpuidle_driver *drv, int index)
-{
-	struct cpuidle_state *state = &drv->states[index];
-	unsigned long eax = flg2MWAIT(state->flags);
-	unsigned long ecx = 1; /* break on interrupt flag */
-	bool uninitialized_var(tick);
-	int cpu = smp_processor_id();
-
-	/*
-	 * leave_mm() to avoid costly and often unnecessary wakeups
-	 * for flushing the user TLB's associated with the active mm.
-	 */
-	if (state->flags & CPUIDLE_FLAG_TLB_FLUSHED)
-		leave_mm(cpu);
-
-	if (!static_cpu_has(X86_FEATURE_ARAT) && !lapic_timer_always_reliable) {
-		/*
-		 * Switch over to one-shot tick broadcast if the target C-state
-		 * is deeper than C1.
-		 */
-		if ((eax >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK) {
-			tick = true;
-			tick_broadcast_enter();
-		} else {
-			tick = false;
-		}
-	}
-
-	mwait_idle_with_hints(eax, ecx);
-
-	if (!static_cpu_has(X86_FEATURE_ARAT) && tick)
-		tick_broadcast_exit();
-
-	return index;
-}
-
-/**
- * intel_idle_s2idle - Ask the processor to enter the given idle state.
- * @dev: cpuidle device of the target CPU.
- * @drv: cpuidle driver (assumed to point to intel_idle_driver).
- * @index: Target idle state index.
- *
- * Use the MWAIT instruction to notify the processor that the CPU represented by
- * @dev is idle and it can try to enter the idle state corresponding to @index.
- *
- * Invoked as a suspend-to-idle callback routine with frozen user space, frozen
- * scheduler tick and suspended scheduler clock on the target CPU.
- */
-static __cpuidle void intel_idle_s2idle(struct cpuidle_device *dev,
-					struct cpuidle_driver *drv, int index)
-{
-	unsigned long eax = flg2MWAIT(drv->states[index].flags);
-	unsigned long ecx = 1; /* break on interrupt flag */
-
-	mwait_idle_with_hints(eax, ecx);
-}
-
 static const struct idle_cpu idle_cpu_nehalem = {
 	.state_table = nehalem_cstates,
 	.auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE,
-- 
2.16.4






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

* [PATCH 4/9] intel_idle: Add __initdata annotations to init time variables
  2020-02-13 21:58 [PATCH 0/9] intel_idle: More assorted cleanups Rafael J. Wysocki
                   ` (2 preceding siblings ...)
  2020-02-13 22:00 ` [PATCH 3/9] intel_idle: Relocate " Rafael J. Wysocki
@ 2020-02-13 22:01 ` Rafael J. Wysocki
  2020-02-13 22:01 ` [PATCH 5/9] intel_idle: Annotate init time data structures Rafael J. Wysocki
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Rafael J. Wysocki @ 2020-02-13 22:01 UTC (permalink / raw)
  To: Linux PM; +Cc: Len Brown, LKML, Zhang Rui, Rafael J. Wysocki, Chen Yu

From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>

Annotate static variables cpuidle_state_table and mwait_substates
with __initdata, because they are only used during the initialization
of the driver.

Also notice that static variable icpu could be annotated analogously
and the structure pointed to by it could be __initconst, but two of
its fields are accessed via icpu in intel_idle_cpu_init() and
auto_demotion_disable(), so introduce two new static variables,
auto_demotion_disable_flags and disable_promotion_to_c1e, to hold
the values of these fields, set them during the initialization and
use them in those functions instead of accessing the source data
structure via icpu.

That allows icpu to be annotated with __initdata, so do that,
and it will also allow some __initconst annotations to be added
subsequently.

No intentional functional impact.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/idle/intel_idle.c | 21 ++++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index e0332d567735..b7341e0b910a 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -65,7 +65,11 @@ static struct cpuidle_driver intel_idle_driver = {
 static int max_cstate = CPUIDLE_STATE_MAX - 1;
 static unsigned int disabled_states_mask;
 
-static unsigned int mwait_substates;
+static unsigned int mwait_substates __initdata;
+
+static unsigned long auto_demotion_disable_flags;
+static bool disable_promotion_to_c1e;
+
 static bool lapic_timer_always_reliable;
 
 struct idle_cpu {
@@ -81,9 +85,9 @@ struct idle_cpu {
 	bool use_acpi;
 };
 
-static const struct idle_cpu *icpu;
+static const struct idle_cpu *icpu __initdata;
 static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
-static struct cpuidle_state *cpuidle_state_table;
+static struct cpuidle_state *cpuidle_state_table __initdata;
 
 /*
  * Enable this state by default even if the ACPI _CST does not list it.
@@ -1519,7 +1523,7 @@ static void auto_demotion_disable(void)
 	unsigned long long msr_bits;
 
 	rdmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr_bits);
-	msr_bits &= ~(icpu->auto_demotion_disable_flags);
+	msr_bits &= ~auto_demotion_disable_flags;
 	wrmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr_bits);
 }
 
@@ -1549,13 +1553,10 @@ static int intel_idle_cpu_init(unsigned int cpu)
 		return -EIO;
 	}
 
-	if (!icpu)
-		return 0;
-
-	if (icpu->auto_demotion_disable_flags)
+	if (auto_demotion_disable_flags)
 		auto_demotion_disable();
 
-	if (icpu->disable_promotion_to_c1e)
+	if (disable_promotion_to_c1e)
 		c1e_promotion_disable();
 
 	return 0;
@@ -1633,6 +1634,8 @@ static int __init intel_idle_init(void)
 	icpu = (const struct idle_cpu *)id->driver_data;
 	if (icpu) {
 		cpuidle_state_table = icpu->state_table;
+		auto_demotion_disable_flags = icpu->auto_demotion_disable_flags;
+		disable_promotion_to_c1e = icpu->disable_promotion_to_c1e;
 		if (icpu->use_acpi || force_use_acpi)
 			intel_idle_acpi_cst_extract();
 	} else if (!intel_idle_acpi_cst_extract()) {
-- 
2.16.4






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

* [PATCH 5/9] intel_idle: Annotate init time data structures
  2020-02-13 21:58 [PATCH 0/9] intel_idle: More assorted cleanups Rafael J. Wysocki
                   ` (3 preceding siblings ...)
  2020-02-13 22:01 ` [PATCH 4/9] intel_idle: Add __initdata annotations to init time variables Rafael J. Wysocki
@ 2020-02-13 22:01 ` Rafael J. Wysocki
  2020-02-13 22:02 ` [PATCH 6/9] intel_idle: Reorder declarations of static variables Rafael J. Wysocki
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Rafael J. Wysocki @ 2020-02-13 22:01 UTC (permalink / raw)
  To: Linux PM; +Cc: Len Brown, LKML, Zhang Rui, Rafael J. Wysocki, Chen Yu

From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>

Add __initdata or __initconst annotations to the static data
structures that are only used during the initialization of the
driver.

No intentional functional impact.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/idle/intel_idle.c | 78 +++++++++++++++++++++++------------------------
 1 file changed, 39 insertions(+), 39 deletions(-)

diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index b7341e0b910a..5e627c40f6b0 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -192,7 +192,7 @@ static __cpuidle void intel_idle_s2idle(struct cpuidle_device *dev,
  * which is also the index into the MWAIT hint array.
  * Thus C0 is a dummy.
  */
-static struct cpuidle_state nehalem_cstates[] = {
+static struct cpuidle_state nehalem_cstates[] __initdata = {
 	{
 		.name = "C1",
 		.desc = "MWAIT 0x00",
@@ -229,7 +229,7 @@ static struct cpuidle_state nehalem_cstates[] = {
 		.enter = NULL }
 };
 
-static struct cpuidle_state snb_cstates[] = {
+static struct cpuidle_state snb_cstates[] __initdata = {
 	{
 		.name = "C1",
 		.desc = "MWAIT 0x00",
@@ -274,7 +274,7 @@ static struct cpuidle_state snb_cstates[] = {
 		.enter = NULL }
 };
 
-static struct cpuidle_state byt_cstates[] = {
+static struct cpuidle_state byt_cstates[] __initdata = {
 	{
 		.name = "C1",
 		.desc = "MWAIT 0x00",
@@ -319,7 +319,7 @@ static struct cpuidle_state byt_cstates[] = {
 		.enter = NULL }
 };
 
-static struct cpuidle_state cht_cstates[] = {
+static struct cpuidle_state cht_cstates[] __initdata = {
 	{
 		.name = "C1",
 		.desc = "MWAIT 0x00",
@@ -364,7 +364,7 @@ static struct cpuidle_state cht_cstates[] = {
 		.enter = NULL }
 };
 
-static struct cpuidle_state ivb_cstates[] = {
+static struct cpuidle_state ivb_cstates[] __initdata = {
 	{
 		.name = "C1",
 		.desc = "MWAIT 0x00",
@@ -409,7 +409,7 @@ static struct cpuidle_state ivb_cstates[] = {
 		.enter = NULL }
 };
 
-static struct cpuidle_state ivt_cstates[] = {
+static struct cpuidle_state ivt_cstates[] __initdata = {
 	{
 		.name = "C1",
 		.desc = "MWAIT 0x00",
@@ -446,7 +446,7 @@ static struct cpuidle_state ivt_cstates[] = {
 		.enter = NULL }
 };
 
-static struct cpuidle_state ivt_cstates_4s[] = {
+static struct cpuidle_state ivt_cstates_4s[] __initdata = {
 	{
 		.name = "C1",
 		.desc = "MWAIT 0x00",
@@ -483,7 +483,7 @@ static struct cpuidle_state ivt_cstates_4s[] = {
 		.enter = NULL }
 };
 
-static struct cpuidle_state ivt_cstates_8s[] = {
+static struct cpuidle_state ivt_cstates_8s[] __initdata = {
 	{
 		.name = "C1",
 		.desc = "MWAIT 0x00",
@@ -520,7 +520,7 @@ static struct cpuidle_state ivt_cstates_8s[] = {
 		.enter = NULL }
 };
 
-static struct cpuidle_state hsw_cstates[] = {
+static struct cpuidle_state hsw_cstates[] __initdata = {
 	{
 		.name = "C1",
 		.desc = "MWAIT 0x00",
@@ -588,7 +588,7 @@ static struct cpuidle_state hsw_cstates[] = {
 	{
 		.enter = NULL }
 };
-static struct cpuidle_state bdw_cstates[] = {
+static struct cpuidle_state bdw_cstates[] __initdata = {
 	{
 		.name = "C1",
 		.desc = "MWAIT 0x00",
@@ -657,7 +657,7 @@ static struct cpuidle_state bdw_cstates[] = {
 		.enter = NULL }
 };
 
-static struct cpuidle_state skl_cstates[] = {
+static struct cpuidle_state skl_cstates[] __initdata = {
 	{
 		.name = "C1",
 		.desc = "MWAIT 0x00",
@@ -726,7 +726,7 @@ static struct cpuidle_state skl_cstates[] = {
 		.enter = NULL }
 };
 
-static struct cpuidle_state skx_cstates[] = {
+static struct cpuidle_state skx_cstates[] __initdata = {
 	{
 		.name = "C1",
 		.desc = "MWAIT 0x00",
@@ -755,7 +755,7 @@ static struct cpuidle_state skx_cstates[] = {
 		.enter = NULL }
 };
 
-static struct cpuidle_state atom_cstates[] = {
+static struct cpuidle_state atom_cstates[] __initdata = {
 	{
 		.name = "C1E",
 		.desc = "MWAIT 0x00",
@@ -791,7 +791,7 @@ static struct cpuidle_state atom_cstates[] = {
 	{
 		.enter = NULL }
 };
-static struct cpuidle_state tangier_cstates[] = {
+static struct cpuidle_state tangier_cstates[] __initdata = {
 	{
 		.name = "C1",
 		.desc = "MWAIT 0x00",
@@ -835,7 +835,7 @@ static struct cpuidle_state tangier_cstates[] = {
 	{
 		.enter = NULL }
 };
-static struct cpuidle_state avn_cstates[] = {
+static struct cpuidle_state avn_cstates[] __initdata = {
 	{
 		.name = "C1",
 		.desc = "MWAIT 0x00",
@@ -855,7 +855,7 @@ static struct cpuidle_state avn_cstates[] = {
 	{
 		.enter = NULL }
 };
-static struct cpuidle_state knl_cstates[] = {
+static struct cpuidle_state knl_cstates[] __initdata = {
 	{
 		.name = "C1",
 		.desc = "MWAIT 0x00",
@@ -876,7 +876,7 @@ static struct cpuidle_state knl_cstates[] = {
 		.enter = NULL }
 };
 
-static struct cpuidle_state bxt_cstates[] = {
+static struct cpuidle_state bxt_cstates[] __initdata = {
 	{
 		.name = "C1",
 		.desc = "MWAIT 0x00",
@@ -937,7 +937,7 @@ static struct cpuidle_state bxt_cstates[] = {
 		.enter = NULL }
 };
 
-static struct cpuidle_state dnv_cstates[] = {
+static struct cpuidle_state dnv_cstates[] __initdata = {
 	{
 		.name = "C1",
 		.desc = "MWAIT 0x00",
@@ -966,116 +966,116 @@ static struct cpuidle_state dnv_cstates[] = {
 		.enter = NULL }
 };
 
-static const struct idle_cpu idle_cpu_nehalem = {
+static const struct idle_cpu idle_cpu_nehalem __initconst = {
 	.state_table = nehalem_cstates,
 	.auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE,
 	.disable_promotion_to_c1e = true,
 };
 
-static const struct idle_cpu idle_cpu_nhx = {
+static const struct idle_cpu idle_cpu_nhx __initconst = {
 	.state_table = nehalem_cstates,
 	.auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE,
 	.disable_promotion_to_c1e = true,
 	.use_acpi = true,
 };
 
-static const struct idle_cpu idle_cpu_atom = {
+static const struct idle_cpu idle_cpu_atom __initconst = {
 	.state_table = atom_cstates,
 };
 
-static const struct idle_cpu idle_cpu_tangier = {
+static const struct idle_cpu idle_cpu_tangier __initconst = {
 	.state_table = tangier_cstates,
 };
 
-static const struct idle_cpu idle_cpu_lincroft = {
+static const struct idle_cpu idle_cpu_lincroft __initconst = {
 	.state_table = atom_cstates,
 	.auto_demotion_disable_flags = ATM_LNC_C6_AUTO_DEMOTE,
 };
 
-static const struct idle_cpu idle_cpu_snb = {
+static const struct idle_cpu idle_cpu_snb __initconst = {
 	.state_table = snb_cstates,
 	.disable_promotion_to_c1e = true,
 };
 
-static const struct idle_cpu idle_cpu_snx = {
+static const struct idle_cpu idle_cpu_snx __initconst = {
 	.state_table = snb_cstates,
 	.disable_promotion_to_c1e = true,
 	.use_acpi = true,
 };
 
-static const struct idle_cpu idle_cpu_byt = {
+static const struct idle_cpu idle_cpu_byt __initconst = {
 	.state_table = byt_cstates,
 	.disable_promotion_to_c1e = true,
 	.byt_auto_demotion_disable_flag = true,
 };
 
-static const struct idle_cpu idle_cpu_cht = {
+static const struct idle_cpu idle_cpu_cht __initconst = {
 	.state_table = cht_cstates,
 	.disable_promotion_to_c1e = true,
 	.byt_auto_demotion_disable_flag = true,
 };
 
-static const struct idle_cpu idle_cpu_ivb = {
+static const struct idle_cpu idle_cpu_ivb __initconst = {
 	.state_table = ivb_cstates,
 	.disable_promotion_to_c1e = true,
 };
 
-static const struct idle_cpu idle_cpu_ivt = {
+static const struct idle_cpu idle_cpu_ivt __initconst = {
 	.state_table = ivt_cstates,
 	.disable_promotion_to_c1e = true,
 	.use_acpi = true,
 };
 
-static const struct idle_cpu idle_cpu_hsw = {
+static const struct idle_cpu idle_cpu_hsw __initconst = {
 	.state_table = hsw_cstates,
 	.disable_promotion_to_c1e = true,
 };
 
-static const struct idle_cpu idle_cpu_hsx = {
+static const struct idle_cpu idle_cpu_hsx __initconst = {
 	.state_table = hsw_cstates,
 	.disable_promotion_to_c1e = true,
 	.use_acpi = true,
 };
 
-static const struct idle_cpu idle_cpu_bdw = {
+static const struct idle_cpu idle_cpu_bdw __initconst = {
 	.state_table = bdw_cstates,
 	.disable_promotion_to_c1e = true,
 };
 
-static const struct idle_cpu idle_cpu_bdx = {
+static const struct idle_cpu idle_cpu_bdx __initconst = {
 	.state_table = bdw_cstates,
 	.disable_promotion_to_c1e = true,
 	.use_acpi = true,
 };
 
-static const struct idle_cpu idle_cpu_skl = {
+static const struct idle_cpu idle_cpu_skl __initconst = {
 	.state_table = skl_cstates,
 	.disable_promotion_to_c1e = true,
 };
 
-static const struct idle_cpu idle_cpu_skx = {
+static const struct idle_cpu idle_cpu_skx __initconst = {
 	.state_table = skx_cstates,
 	.disable_promotion_to_c1e = true,
 	.use_acpi = true,
 };
 
-static const struct idle_cpu idle_cpu_avn = {
+static const struct idle_cpu idle_cpu_avn __initconst = {
 	.state_table = avn_cstates,
 	.disable_promotion_to_c1e = true,
 	.use_acpi = true,
 };
 
-static const struct idle_cpu idle_cpu_knl = {
+static const struct idle_cpu idle_cpu_knl __initconst = {
 	.state_table = knl_cstates,
 	.use_acpi = true,
 };
 
-static const struct idle_cpu idle_cpu_bxt = {
+static const struct idle_cpu idle_cpu_bxt __initconst = {
 	.state_table = bxt_cstates,
 	.disable_promotion_to_c1e = true,
 };
 
-static const struct idle_cpu idle_cpu_dnv = {
+static const struct idle_cpu idle_cpu_dnv __initconst = {
 	.state_table = dnv_cstates,
 	.disable_promotion_to_c1e = true,
 	.use_acpi = true,
-- 
2.16.4






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

* [PATCH 6/9] intel_idle: Reorder declarations of static variables
  2020-02-13 21:58 [PATCH 0/9] intel_idle: More assorted cleanups Rafael J. Wysocki
                   ` (4 preceding siblings ...)
  2020-02-13 22:01 ` [PATCH 5/9] intel_idle: Annotate init time data structures Rafael J. Wysocki
@ 2020-02-13 22:02 ` Rafael J. Wysocki
  2020-02-13 22:03 ` [PATCH 7/9] intel_idle: Clean up kerneldoc comments of multiple functions Rafael J. Wysocki
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Rafael J. Wysocki @ 2020-02-13 22:02 UTC (permalink / raw)
  To: Linux PM; +Cc: Len Brown, LKML, Zhang Rui, Rafael J. Wysocki, Chen Yu

From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>

Reorder declarations of static variables so that the __initdata ones
are declared together.

No functional impact.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/idle/intel_idle.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 5e627c40f6b0..3a93cd1036fb 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -65,7 +65,7 @@ static struct cpuidle_driver intel_idle_driver = {
 static int max_cstate = CPUIDLE_STATE_MAX - 1;
 static unsigned int disabled_states_mask;
 
-static unsigned int mwait_substates __initdata;
+static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
 
 static unsigned long auto_demotion_disable_flags;
 static bool disable_promotion_to_c1e;
@@ -86,9 +86,10 @@ struct idle_cpu {
 };
 
 static const struct idle_cpu *icpu __initdata;
-static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
 static struct cpuidle_state *cpuidle_state_table __initdata;
 
+static unsigned int mwait_substates __initdata;
+
 /*
  * Enable this state by default even if the ACPI _CST does not list it.
  */
-- 
2.16.4






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

* [PATCH 7/9] intel_idle: Clean up kerneldoc comments of multiple functions
  2020-02-13 21:58 [PATCH 0/9] intel_idle: More assorted cleanups Rafael J. Wysocki
                   ` (5 preceding siblings ...)
  2020-02-13 22:02 ` [PATCH 6/9] intel_idle: Reorder declarations of static variables Rafael J. Wysocki
@ 2020-02-13 22:03 ` Rafael J. Wysocki
  2020-02-13 22:03 ` [PATCH 8/9] intel_idle: Define CPUIDLE_FLAG_TLB_FLUSHED as BIT(16) Rafael J. Wysocki
  2020-02-13 22:04 ` [PATCH 9/9] intel_idle: Update copyright notice, known limitations and version Rafael J. Wysocki
  8 siblings, 0 replies; 11+ messages in thread
From: Rafael J. Wysocki @ 2020-02-13 22:03 UTC (permalink / raw)
  To: Linux PM; +Cc: Len Brown, LKML, Zhang Rui, Rafael J. Wysocki, Chen Yu

From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>

Turn the description comments of some functions in the intel_idle
driver into proper kerneldoc ones and clean them up.

No functional impact.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/idle/intel_idle.c | 40 +++++++++++++++++++++-------------------
 1 file changed, 21 insertions(+), 19 deletions(-)

diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 3a93cd1036fb..9575615c8f4a 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -1288,11 +1288,11 @@ static inline void intel_idle_init_cstates_acpi(struct cpuidle_driver *drv) { }
 static inline bool intel_idle_off_by_default(u32 mwait_hint) { return false; }
 #endif /* !CONFIG_ACPI_PROCESSOR_CSTATE */
 
-/*
- * ivt_idle_state_table_update(void)
+/**
+ * ivt_idle_state_table_update - Tune the idle states table for Ivy Town.
  *
- * Tune IVT multi-socket targets
- * Assumption: num_sockets == (max_package_num + 1)
+ * Tune IVT multi-socket targets.
+ * Assumption: num_sockets == (max_package_num + 1).
  */
 static void __init ivt_idle_state_table_update(void)
 {
@@ -1338,11 +1338,11 @@ static unsigned long long __init irtl_2_usec(unsigned long long irtl)
 	return div_u64((irtl & 0x3FF) * ns, NSEC_PER_USEC);
 }
 
-/*
- * bxt_idle_state_table_update(void)
+/**
+ * bxt_idle_state_table_update - Fix up the Broxton idle states table.
  *
- * On BXT, we trust the IRTL to show the definitive maximum latency
- * We use the same value for target_residency.
+ * On BXT, trust the IRTL (Interrupt Response Time Limit) MSR to show the
+ * definitive maximum latency and use the same value for target_residency.
  */
 static void __init bxt_idle_state_table_update(void)
 {
@@ -1385,11 +1385,11 @@ static void __init bxt_idle_state_table_update(void)
 	}
 
 }
-/*
- * sklh_idle_state_table_update(void)
+
+/**
+ * sklh_idle_state_table_update - Fix up the Sky Lake idle states table.
  *
- * On SKL-H (model 0x5e) disable C8 and C9 if:
- * C10 is enabled and SGX disabled
+ * On SKL-H (model 0x5e) skip C8 and C9 if C10 is enabled and SGX disabled.
  */
 static void __init sklh_idle_state_table_update(void)
 {
@@ -1500,9 +1500,9 @@ static void __init intel_idle_init_cstates_icpu(struct cpuidle_driver *drv)
 	}
 }
 
-/*
- * intel_idle_cpuidle_driver_init()
- * allocate, initialize cpuidle_states
+/**
+ * intel_idle_cpuidle_driver_init - Create the list of available idle states.
+ * @drv: cpuidle driver structure to initialize.
  */
 static void __init intel_idle_cpuidle_driver_init(struct cpuidle_driver *drv)
 {
@@ -1537,10 +1537,12 @@ static void c1e_promotion_disable(void)
 	wrmsrl(MSR_IA32_POWER_CTL, msr_bits);
 }
 
-/*
- * intel_idle_cpu_init()
- * allocate, initialize, register cpuidle_devices
- * @cpu: cpu/core to initialize
+/**
+ * intel_idle_cpu_init - Register the target CPU with the cpuidle core.
+ * @cpu: CPU to initialize.
+ *
+ * Register a cpuidle device object for @cpu and update its MSRs in accordance
+ * with the processor model flags.
  */
 static int intel_idle_cpu_init(unsigned int cpu)
 {
-- 
2.16.4






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

* [PATCH 8/9] intel_idle: Define CPUIDLE_FLAG_TLB_FLUSHED as BIT(16)
  2020-02-13 21:58 [PATCH 0/9] intel_idle: More assorted cleanups Rafael J. Wysocki
                   ` (6 preceding siblings ...)
  2020-02-13 22:03 ` [PATCH 7/9] intel_idle: Clean up kerneldoc comments of multiple functions Rafael J. Wysocki
@ 2020-02-13 22:03 ` Rafael J. Wysocki
  2020-02-13 22:04 ` [PATCH 9/9] intel_idle: Update copyright notice, known limitations and version Rafael J. Wysocki
  8 siblings, 0 replies; 11+ messages in thread
From: Rafael J. Wysocki @ 2020-02-13 22:03 UTC (permalink / raw)
  To: Linux PM; +Cc: Len Brown, LKML, Zhang Rui, Rafael J. Wysocki, Chen Yu

From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>

Use the BIT() macro for defining CPUIDLE_FLAG_TLB_FLUSHED instead of
the hex bit encoding of the same value.

No intentional functional impact.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/idle/intel_idle.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 9575615c8f4a..de1367d996c5 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -101,7 +101,7 @@ static unsigned int mwait_substates __initdata;
  * If this flag is set, SW flushes the TLB, so even if the
  * HW doesn't do the flushing, this flag is safe to use.
  */
-#define CPUIDLE_FLAG_TLB_FLUSHED	0x10000
+#define CPUIDLE_FLAG_TLB_FLUSHED	BIT(16)
 
 /*
  * MWAIT takes an 8-bit "hint" in EAX "suggesting"
-- 
2.16.4






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

* [PATCH 9/9] intel_idle: Update copyright notice, known limitations and version
  2020-02-13 21:58 [PATCH 0/9] intel_idle: More assorted cleanups Rafael J. Wysocki
                   ` (7 preceding siblings ...)
  2020-02-13 22:03 ` [PATCH 8/9] intel_idle: Define CPUIDLE_FLAG_TLB_FLUSHED as BIT(16) Rafael J. Wysocki
@ 2020-02-13 22:04 ` Rafael J. Wysocki
  8 siblings, 0 replies; 11+ messages in thread
From: Rafael J. Wysocki @ 2020-02-13 22:04 UTC (permalink / raw)
  To: Linux PM; +Cc: Len Brown, LKML, Zhang Rui, Rafael J. Wysocki, Chen Yu

From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>

Update the copyright notice in intel_idle.c to cover the recent
changes, drop the description of a "known limitation" that is not
a limitation any more and bump up the driver version number.

No functional impact.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/idle/intel_idle.c | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index de1367d996c5..65b84d5dc457 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -2,8 +2,9 @@
 /*
  * intel_idle.c - native hardware idle loop for modern Intel processors
  *
- * Copyright (c) 2013, Intel Corporation.
+ * Copyright (c) 2013 - 2020, Intel Corporation.
  * Len Brown <len.brown@intel.com>
+ * Rafael J. Wysocki <rafael.j.wysocki@intel.com>
  */
 
 /*
@@ -25,11 +26,6 @@
 /*
  * Known limitations
  *
- * The driver currently initializes for_each_online_cpu() upon modprobe.
- * It it unaware of subsequent processors hot-added to the system.
- * This means that if you boot with maxcpus=n and later online
- * processors above n, those processors will use C1 only.
- *
  * ACPI has a .suspend hack to turn off deep c-statees during suspend
  * to avoid complications with the lapic timer workaround.
  * Have not seen issues with suspend, but may need same workaround here.
@@ -55,7 +51,7 @@
 #include <asm/mwait.h>
 #include <asm/msr.h>
 
-#define INTEL_IDLE_VERSION "0.4.1"
+#define INTEL_IDLE_VERSION "0.5.1"
 
 static struct cpuidle_driver intel_idle_driver = {
 	.name = "intel_idle",
-- 
2.16.4






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

* Re: [PATCH 3/9] intel_idle: Relocate definitions of cpuidle callbacks
  2020-02-13 22:00 ` [PATCH 3/9] intel_idle: Relocate " Rafael J. Wysocki
@ 2020-05-23  0:04   ` Qian Cai
  0 siblings, 0 replies; 11+ messages in thread
From: Qian Cai @ 2020-05-23  0:04 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Linux PM, Len Brown, LKML, Zhang Rui, Rafael J. Wysocki, Chen Yu,
	clang-built-linux

On Thu, Feb 13, 2020 at 11:00:26PM +0100, Rafael J. Wysocki wrote:
> From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
> 
> Move the definitions of intel_idle() and intel_idle_s2idle() before
> the definitions of cpuidle_state structures referring to them to
> avoid having to use additional declarations of them (and drop those
> declarations).
> 
> No functional impact.
> 
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---
>  drivers/idle/intel_idle.c | 154 ++++++++++++++++++++++------------------------
>  1 file changed, 75 insertions(+), 79 deletions(-)
> 
> diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
> index 5adc058c705d..e0332d567735 100644
> --- a/drivers/idle/intel_idle.c
> +++ b/drivers/idle/intel_idle.c
[]
> +/**
> + * intel_idle - Ask the processor to enter the given idle state.
> + * @dev: cpuidle device of the target CPU.
> + * @drv: cpuidle driver (assumed to point to intel_idle_driver).
> + * @index: Target idle state index.
> + *
> + * Use the MWAIT instruction to notify the processor that the CPU represented by
> + * @dev is idle and it can try to enter the idle state corresponding to @index.
> + *
> + * If the local APIC timer is not known to be reliable in the target idle state,
> + * enable one-shot tick broadcasting for the target CPU before executing MWAIT.
> + *
> + * Optionally call leave_mm() for the target CPU upfront to avoid wakeups due to
> + * flushing user TLBs.
> + *
> + * Must be called under local_irq_disable().
> + */
> +static __cpuidle int intel_idle(struct cpuidle_device *dev,
> +				struct cpuidle_driver *drv, int index)
> +{
> +	struct cpuidle_state *state = &drv->states[index];
> +	unsigned long eax = flg2MWAIT(state->flags);
> +	unsigned long ecx = 1; /* break on interrupt flag */
> +	bool uninitialized_var(tick);

This will generate an UBSAN warning because Clang could poison all
uninitialized stack variables to 0xAA due to CONFIG_INIT_STACK_ALL=y, so one
issue is that,

bool uninitialized_var(x);

would always broken on Clang like this,

[   92.140611] UBSAN: invalid-load in drivers/idle/intel_idle.c:135:7
[   92.143111] load of value 170 is not a valid value for type 'bool' (aka '_Bool')
[   92.145657] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.7.0-rc6-next-20200522+ #3
[   92.147424] Hardware name: HP ProLiant BL660c Gen9, BIOS I38 10/17/2018
[   92.149869] Call Trace:
[   92.149869]  dump_stack+0x10b/0x17f
[   92.149869]  __ubsan_handle_load_invalid_value+0xd2/0x110
[   92.149869]  intel_idle+0x54/0xf0
[   92.156202]  cpuidle_enter_state+0x120/0x4f0
[   92.156202]  cpuidle_enter+0x5b/0xa0
[   92.156202]  call_cpuidle+0x25/0x50
[   92.156202]  do_idle+0x1eb/0x2c0
[   92.156202]  cpu_startup_entry+0x25/0x30
[   92.156202]  rest_init+0x26f/0x280
[   92.156202]  arch_call_rest_init+0x17/0x1e
[   92.156202]  start_kernel+0x598/0x633
[   92.156202]  x86_64_start_reservations+0x24/0x26
[   92.156202]  x86_64_start_kernel+0x116/0x1c1
[   92.156202]  secondary_startup_64+0xb6/0xc0

However, I am wondering if it is correct to let "tick" uninitialized to begin
with. If this condition is true,

!static_cpu_has(X86_FEATURE_ARAT) && lapic_timer_always_reliable

Then, we could in the final branch to use the uninitialized value.

if (!static_cpu_has(X86_FEATURE_ARAT) && tick)

Isn't that possible?

> +	int cpu = smp_processor_id();
> +
> +	/*
> +	 * leave_mm() to avoid costly and often unnecessary wakeups
> +	 * for flushing the user TLB's associated with the active mm.
> +	 */
> +	if (state->flags & CPUIDLE_FLAG_TLB_FLUSHED)
> +		leave_mm(cpu);
> +
> +	if (!static_cpu_has(X86_FEATURE_ARAT) && !lapic_timer_always_reliable) {
> +		/*
> +		 * Switch over to one-shot tick broadcast if the target C-state
> +		 * is deeper than C1.
> +		 */
> +		if ((eax >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK) {
> +			tick = true;
> +			tick_broadcast_enter();
> +		} else {
> +			tick = false;
> +		}
> +	}
> +
> +	mwait_idle_with_hints(eax, ecx);
> +
> +	if (!static_cpu_has(X86_FEATURE_ARAT) && tick)
> +		tick_broadcast_exit();
> +
> +	return index;
> +}

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

end of thread, other threads:[~2020-05-23  0:04 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-13 21:58 [PATCH 0/9] intel_idle: More assorted cleanups Rafael J. Wysocki
2020-02-13 21:59 ` [PATCH 1/9] intel_idle: Simplify LAPIC timer reliability checks Rafael J. Wysocki
2020-02-13 21:59 ` [PATCH 2/9] intel_idle: Clean up definitions of cpuidle callbacks Rafael J. Wysocki
2020-02-13 22:00 ` [PATCH 3/9] intel_idle: Relocate " Rafael J. Wysocki
2020-05-23  0:04   ` Qian Cai
2020-02-13 22:01 ` [PATCH 4/9] intel_idle: Add __initdata annotations to init time variables Rafael J. Wysocki
2020-02-13 22:01 ` [PATCH 5/9] intel_idle: Annotate init time data structures Rafael J. Wysocki
2020-02-13 22:02 ` [PATCH 6/9] intel_idle: Reorder declarations of static variables Rafael J. Wysocki
2020-02-13 22:03 ` [PATCH 7/9] intel_idle: Clean up kerneldoc comments of multiple functions Rafael J. Wysocki
2020-02-13 22:03 ` [PATCH 8/9] intel_idle: Define CPUIDLE_FLAG_TLB_FLUSHED as BIT(16) Rafael J. Wysocki
2020-02-13 22:04 ` [PATCH 9/9] intel_idle: Update copyright notice, known limitations and version Rafael J. Wysocki

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).