Skip to content

Commit 6e1d2bc

Browse files
author
Peter Zijlstra
committed
intel_idle: Fix intel_idle() vs tracing
cpuidle->enter() callbacks should not call into tracing because RCU has already been disabled. Instead of doing the broadcast thing itself, simply advertise to the cpuidle core that those states stop the timer. Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Acked-by: Rafael J. Wysocki <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent 58c644b commit 6e1d2bc

File tree

1 file changed

+20
-17
lines changed

1 file changed

+20
-17
lines changed

drivers/idle/intel_idle.c

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -126,26 +126,9 @@ static __cpuidle int intel_idle(struct cpuidle_device *dev,
126126
struct cpuidle_state *state = &drv->states[index];
127127
unsigned long eax = flg2MWAIT(state->flags);
128128
unsigned long ecx = 1; /* break on interrupt flag */
129-
bool tick;
130-
131-
if (!static_cpu_has(X86_FEATURE_ARAT)) {
132-
/*
133-
* Switch over to one-shot tick broadcast if the target C-state
134-
* is deeper than C1.
135-
*/
136-
if ((eax >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK) {
137-
tick = true;
138-
tick_broadcast_enter();
139-
} else {
140-
tick = false;
141-
}
142-
}
143129

144130
mwait_idle_with_hints(eax, ecx);
145131

146-
if (!static_cpu_has(X86_FEATURE_ARAT) && tick)
147-
tick_broadcast_exit();
148-
149132
return index;
150133
}
151134

@@ -1227,6 +1210,20 @@ static bool __init intel_idle_acpi_cst_extract(void)
12271210
return false;
12281211
}
12291212

1213+
static bool __init intel_idle_state_needs_timer_stop(struct cpuidle_state *state)
1214+
{
1215+
unsigned long eax = flg2MWAIT(state->flags);
1216+
1217+
if (boot_cpu_has(X86_FEATURE_ARAT))
1218+
return false;
1219+
1220+
/*
1221+
* Switch over to one-shot tick broadcast if the target C-state
1222+
* is deeper than C1.
1223+
*/
1224+
return !!((eax >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK);
1225+
}
1226+
12301227
static void __init intel_idle_init_cstates_acpi(struct cpuidle_driver *drv)
12311228
{
12321229
int cstate, limit = min_t(int, CPUIDLE_STATE_MAX, acpi_state_table.count);
@@ -1269,6 +1266,9 @@ static void __init intel_idle_init_cstates_acpi(struct cpuidle_driver *drv)
12691266
if (disabled_states_mask & BIT(cstate))
12701267
state->flags |= CPUIDLE_FLAG_OFF;
12711268

1269+
if (intel_idle_state_needs_timer_stop(state))
1270+
state->flags |= CPUIDLE_FLAG_TIMER_STOP;
1271+
12721272
state->enter = intel_idle;
12731273
state->enter_s2idle = intel_idle_s2idle;
12741274
}
@@ -1507,6 +1507,9 @@ static void __init intel_idle_init_cstates_icpu(struct cpuidle_driver *drv)
15071507
!(cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_ALWAYS_ENABLE)))
15081508
drv->states[drv->state_count].flags |= CPUIDLE_FLAG_OFF;
15091509

1510+
if (intel_idle_state_needs_timer_stop(&drv->states[drv->state_count]))
1511+
drv->states[drv->state_count].flags |= CPUIDLE_FLAG_TIMER_STOP;
1512+
15101513
drv->state_count++;
15111514
}
15121515

0 commit comments

Comments
 (0)