2020-02-13 22:05:55

by Rafael J. Wysocki

[permalink] [raw]
Subject: [PATCH 0/9] intel_idle: More assorted cleanups

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!




2020-02-13 22:06:05

by Rafael J. Wysocki

[permalink] [raw]
Subject: [PATCH 4/9] intel_idle: Add __initdata annotations to init time variables

From: "Rafael J. Wysocki" <[email protected]>

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 <[email protected]>
---
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





2020-02-13 22:06:32

by Rafael J. Wysocki

[permalink] [raw]
Subject: [PATCH 7/9] intel_idle: Clean up kerneldoc comments of multiple functions

From: "Rafael J. Wysocki" <[email protected]>

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 <[email protected]>
---
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





2020-02-13 22:06:41

by Rafael J. Wysocki

[permalink] [raw]
Subject: [PATCH 2/9] intel_idle: Clean up definitions of cpuidle callbacks

From: "Rafael J. Wysocki" <[email protected]>

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 <[email protected]>
---
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





2020-02-13 22:06:47

by Rafael J. Wysocki

[permalink] [raw]
Subject: [PATCH 3/9] intel_idle: Relocate definitions of cpuidle callbacks

From: "Rafael J. Wysocki" <[email protected]>

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 <[email protected]>
---
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





2020-02-13 22:07:08

by Rafael J. Wysocki

[permalink] [raw]
Subject: [PATCH 8/9] intel_idle: Define CPUIDLE_FLAG_TLB_FLUSHED as BIT(16)

From: "Rafael J. Wysocki" <[email protected]>

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 <[email protected]>
---
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





2020-02-13 22:07:31

by Rafael J. Wysocki

[permalink] [raw]
Subject: [PATCH 6/9] intel_idle: Reorder declarations of static variables

From: "Rafael J. Wysocki" <[email protected]>

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

No functional impact.

Signed-off-by: Rafael J. Wysocki <[email protected]>
---
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





2020-05-23 00:07:58

by Qian Cai

[permalink] [raw]
Subject: Re: [PATCH 3/9] intel_idle: Relocate definitions of cpuidle callbacks

On Thu, Feb 13, 2020 at 11:00:26PM +0100, Rafael J. Wysocki wrote:
> From: "Rafael J. Wysocki" <[email protected]>
>
> 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 <[email protected]>
> ---
> 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;
> +}