Skip to content

Commit

Permalink
Merge tag 'locking-urgent-2020-11-29' of git://git.kernel.org/pub/scm…
Browse files Browse the repository at this point in the history
…/linux/kernel/git/tip/tip

Pull locking fixes from Thomas Gleixner:
 "Two more places which invoke tracing from RCU disabled regions in the
  idle path.

  Similar to the entry path the low level idle functions have to be
  non-instrumentable"

* tag 'locking-urgent-2020-11-29' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  intel_idle: Fix intel_idle() vs tracing
  sched/idle: Fix arch_cpu_idle() vs tracing
  • Loading branch information
torvalds committed Nov 29, 2020
2 parents 8b7a51b + 6e1d2bc commit f91a3aa
Show file tree
Hide file tree
Showing 24 changed files with 84 additions and 55 deletions.
2 changes: 1 addition & 1 deletion arch/alpha/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ EXPORT_SYMBOL(pm_power_off);
void arch_cpu_idle(void)
{
wtint(0);
local_irq_enable();
raw_local_irq_enable();
}

void arch_cpu_idle_dead(void)
Expand Down
2 changes: 1 addition & 1 deletion arch/arm/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ void arch_cpu_idle(void)
arm_pm_idle();
else
cpu_do_idle();
local_irq_enable();
raw_local_irq_enable();
}

void arch_cpu_idle_prepare(void)
Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ void arch_cpu_idle(void)
* tricks
*/
cpu_do_idle();
local_irq_enable();
raw_local_irq_enable();
}

#ifdef CONFIG_HOTPLUG_CPU
Expand Down
2 changes: 1 addition & 1 deletion arch/csky/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,6 @@ void arch_cpu_idle(void)
#ifdef CONFIG_CPU_PM_STOP
asm volatile("stop\n");
#endif
local_irq_enable();
raw_local_irq_enable();
}
#endif
2 changes: 1 addition & 1 deletion arch/h8300/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ asmlinkage void ret_from_kernel_thread(void);
*/
void arch_cpu_idle(void)
{
local_irq_enable();
raw_local_irq_enable();
__asm__("sleep");
}

Expand Down
2 changes: 1 addition & 1 deletion arch/hexagon/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ void arch_cpu_idle(void)
{
__vmwait();
/* interrupts wake us up, but irqs are still disabled */
local_irq_enable();
raw_local_irq_enable();
}

/*
Expand Down
2 changes: 1 addition & 1 deletion arch/ia64/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ void arch_cpu_idle(void)
if (mark_idle)
(*mark_idle)(1);

safe_halt();
raw_safe_halt();

if (mark_idle)
(*mark_idle)(0);
Expand Down
2 changes: 1 addition & 1 deletion arch/microblaze/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,5 +149,5 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs)

void arch_cpu_idle(void)
{
local_irq_enable();
raw_local_irq_enable();
}
12 changes: 6 additions & 6 deletions arch/mips/kernel/idle.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,19 @@ static void __cpuidle r3081_wait(void)
{
unsigned long cfg = read_c0_conf();
write_c0_conf(cfg | R30XX_CONF_HALT);
local_irq_enable();
raw_local_irq_enable();
}

static void __cpuidle r39xx_wait(void)
{
if (!need_resched())
write_c0_conf(read_c0_conf() | TX39_CONF_HALT);
local_irq_enable();
raw_local_irq_enable();
}

void __cpuidle r4k_wait(void)
{
local_irq_enable();
raw_local_irq_enable();
__r4k_wait();
}

Expand All @@ -64,7 +64,7 @@ void __cpuidle r4k_wait_irqoff(void)
" .set arch=r4000 \n"
" wait \n"
" .set pop \n");
local_irq_enable();
raw_local_irq_enable();
}

/*
Expand All @@ -84,7 +84,7 @@ static void __cpuidle rm7k_wait_irqoff(void)
" wait \n"
" mtc0 $1, $12 # stalls until W stage \n"
" .set pop \n");
local_irq_enable();
raw_local_irq_enable();
}

/*
Expand Down Expand Up @@ -257,7 +257,7 @@ void arch_cpu_idle(void)
if (cpu_wait)
cpu_wait();
else
local_irq_enable();
raw_local_irq_enable();
}

#ifdef CONFIG_CPU_IDLE
Expand Down
2 changes: 1 addition & 1 deletion arch/nios2/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ EXPORT_SYMBOL(pm_power_off);

void arch_cpu_idle(void)
{
local_irq_enable();
raw_local_irq_enable();
}

/*
Expand Down
2 changes: 1 addition & 1 deletion arch/openrisc/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ void machine_power_off(void)
*/
void arch_cpu_idle(void)
{
local_irq_enable();
raw_local_irq_enable();
if (mfspr(SPR_UPR) & SPR_UPR_PMP)
mtspr(SPR_PMR, mfspr(SPR_PMR) | SPR_PMR_DME);
}
Expand Down
2 changes: 1 addition & 1 deletion arch/parisc/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ void __cpuidle arch_cpu_idle_dead(void)

void __cpuidle arch_cpu_idle(void)
{
local_irq_enable();
raw_local_irq_enable();

/* nop on real hardware, qemu will idle sleep. */
asm volatile("or %%r10,%%r10,%%r10\n":::);
Expand Down
4 changes: 2 additions & 2 deletions arch/powerpc/kernel/idle.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ void arch_cpu_idle(void)
* interrupts enabled, some don't.
*/
if (irqs_disabled())
local_irq_enable();
raw_local_irq_enable();
} else {
local_irq_enable();
raw_local_irq_enable();
/*
* Go into low thread priority and possibly
* low power mode.
Expand Down
2 changes: 1 addition & 1 deletion arch/riscv/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ extern asmlinkage void ret_from_kernel_thread(void);
void arch_cpu_idle(void)
{
wait_for_interrupt();
local_irq_enable();
raw_local_irq_enable();
}

void show_regs(struct pt_regs *regs)
Expand Down
6 changes: 3 additions & 3 deletions arch/s390/kernel/idle.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ void enabled_wait(void)
PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
clear_cpu_flag(CIF_NOHZ_DELAY);

local_irq_save(flags);
raw_local_irq_save(flags);
/* Call the assembler magic in entry.S */
psw_idle(idle, psw_mask);
local_irq_restore(flags);
raw_local_irq_restore(flags);

/* Account time spent with enabled wait psw loaded as idle time. */
raw_write_seqcount_begin(&idle->seqcount);
Expand Down Expand Up @@ -123,7 +123,7 @@ void arch_cpu_idle_enter(void)
void arch_cpu_idle(void)
{
enabled_wait();
local_irq_enable();
raw_local_irq_enable();
}

void arch_cpu_idle_exit(void)
Expand Down
2 changes: 1 addition & 1 deletion arch/sh/kernel/idle.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ static void (*sh_idle)(void);
void default_idle(void)
{
set_bl_bit();
local_irq_enable();
raw_local_irq_enable();
/* Isn't this racy ? */
cpu_sleep();
clear_bl_bit();
Expand Down
4 changes: 2 additions & 2 deletions arch/sparc/kernel/leon_pmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ static void pmc_leon_idle_fixup(void)
register unsigned int address = (unsigned int)leon3_irqctrl_regs;

/* Interrupts need to be enabled to not hang the CPU */
local_irq_enable();
raw_local_irq_enable();

__asm__ __volatile__ (
"wr %%g0, %%asr19\n"
Expand All @@ -66,7 +66,7 @@ static void pmc_leon_idle_fixup(void)
static void pmc_leon_idle(void)
{
/* Interrupts need to be enabled to not hang the CPU */
local_irq_enable();
raw_local_irq_enable();

/* For systems without power-down, this will be no-op */
__asm__ __volatile__ ("wr %g0, %asr19\n\t");
Expand Down
2 changes: 1 addition & 1 deletion arch/sparc/kernel/process_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ void arch_cpu_idle(void)
{
if (sparc_idle)
(*sparc_idle)();
local_irq_enable();
raw_local_irq_enable();
}

/* XXX cli/sti -> local_irq_xxx here, check this works once SMP is fixed. */
Expand Down
4 changes: 2 additions & 2 deletions arch/sparc/kernel/process_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ void arch_cpu_idle(void)
{
if (tlb_type != hypervisor) {
touch_nmi_watchdog();
local_irq_enable();
raw_local_irq_enable();
} else {
unsigned long pstate;

local_irq_enable();
raw_local_irq_enable();

/* The sun4v sleeping code requires that we have PSTATE.IE cleared over
* the cpu sleep hypervisor call.
Expand Down
2 changes: 1 addition & 1 deletion arch/um/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ void arch_cpu_idle(void)
{
cpu_tasks[current_thread_info()->cpu].pid = os_getpid();
um_idle_sleep();
local_irq_enable();
raw_local_irq_enable();
}

int __cant_sleep(void) {
Expand Down
2 changes: 0 additions & 2 deletions arch/x86/include/asm/mwait.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,6 @@ static inline void __mwaitx(unsigned long eax, unsigned long ebx,

static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
{
trace_hardirqs_on();

mds_idle_clear_cpu_buffers();
/* "mwait %eax, %ecx;" */
asm volatile("sti; .byte 0x0f, 0x01, 0xc9;"
Expand Down
12 changes: 7 additions & 5 deletions arch/x86/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -685,7 +685,7 @@ void arch_cpu_idle(void)
*/
void __cpuidle default_idle(void)
{
safe_halt();
raw_safe_halt();
}
#if defined(CONFIG_APM_MODULE) || defined(CONFIG_HALTPOLL_CPUIDLE_MODULE)
EXPORT_SYMBOL(default_idle);
Expand Down Expand Up @@ -736,6 +736,8 @@ void stop_this_cpu(void *dummy)
/*
* AMD Erratum 400 aware idle routine. We handle it the same way as C3 power
* states (local apic timer and TSC stop).
*
* XXX this function is completely buggered vs RCU and tracing.
*/
static void amd_e400_idle(void)
{
Expand All @@ -757,9 +759,9 @@ static void amd_e400_idle(void)
* The switch back from broadcast mode needs to be called with
* interrupts disabled.
*/
local_irq_disable();
raw_local_irq_disable();
tick_broadcast_exit();
local_irq_enable();
raw_local_irq_enable();
}

/*
Expand Down Expand Up @@ -801,9 +803,9 @@ static __cpuidle void mwait_idle(void)
if (!need_resched())
__sti_mwait(0, 0);
else
local_irq_enable();
raw_local_irq_enable();
} else {
local_irq_enable();
raw_local_irq_enable();
}
__current_clr_polling();
}
Expand Down
37 changes: 20 additions & 17 deletions drivers/idle/intel_idle.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,26 +126,9 @@ static __cpuidle int intel_idle(struct cpuidle_device *dev,
struct cpuidle_state *state = &drv->states[index];
unsigned long eax = flg2MWAIT(state->flags);
unsigned long ecx = 1; /* break on interrupt flag */
bool tick;

if (!static_cpu_has(X86_FEATURE_ARAT)) {
/*
* 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;
}

Expand Down Expand Up @@ -1227,6 +1210,20 @@ static bool __init intel_idle_acpi_cst_extract(void)
return false;
}

static bool __init intel_idle_state_needs_timer_stop(struct cpuidle_state *state)
{
unsigned long eax = flg2MWAIT(state->flags);

if (boot_cpu_has(X86_FEATURE_ARAT))
return false;

/*
* Switch over to one-shot tick broadcast if the target C-state
* is deeper than C1.
*/
return !!((eax >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK);
}

static void __init intel_idle_init_cstates_acpi(struct cpuidle_driver *drv)
{
int cstate, limit = min_t(int, CPUIDLE_STATE_MAX, acpi_state_table.count);
Expand Down Expand Up @@ -1269,6 +1266,9 @@ static void __init intel_idle_init_cstates_acpi(struct cpuidle_driver *drv)
if (disabled_states_mask & BIT(cstate))
state->flags |= CPUIDLE_FLAG_OFF;

if (intel_idle_state_needs_timer_stop(state))
state->flags |= CPUIDLE_FLAG_TIMER_STOP;

state->enter = intel_idle;
state->enter_s2idle = intel_idle_s2idle;
}
Expand Down Expand Up @@ -1507,6 +1507,9 @@ static void __init intel_idle_init_cstates_icpu(struct cpuidle_driver *drv)
!(cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_ALWAYS_ENABLE)))
drv->states[drv->state_count].flags |= CPUIDLE_FLAG_OFF;

if (intel_idle_state_needs_timer_stop(&drv->states[drv->state_count]))
drv->states[drv->state_count].flags |= CPUIDLE_FLAG_TIMER_STOP;

drv->state_count++;
}

Expand Down
Loading

0 comments on commit f91a3aa

Please sign in to comment.