x86/idle: re-arrange dead-idle handling

In order to be able to wake parked CPUs from default_dead_idle() (for
them to then enter a different dead-idle routine), the function should
not itself loop. Move the loop into play_dead(), and use play_dead() as
well on the AP boot error path.

Furthermore, not the least considering the comment in play_dead(),
make sure NMI raised (for now this would be a bug elsewhere, but that's
about to change) against a parked or fully offline CPU won't invoke the
actual, full-blown NMI handler.

Note however that this doesn't make #MC any safer for fully offline
CPUs.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
This commit is contained in:
Jan Beulich committed 2019-05-21 08:30:23 +02:00
1 parent de4de79100
commit 73cb1383bf
3 files changed
+15 -7

No files matched your search

+12 -5
View File
@@ -100,14 +100,20 @@ void default_dead_idle(void)
*/
spec_ctrl_enter_idle(get_cpu_info());
wbinvd();
for ( ; ; )
halt();
halt();
spec_ctrl_exit_idle(get_cpu_info());
}
static void play_dead(void)
void play_dead(void)
{
unsigned int cpu = smp_processor_id();
local_irq_disable();
/* Change the NMI handler to a nop (see comment below). */
_set_gate_lower(&idt_tables[cpu][TRAP_nmi], SYS_DESC_irq_gate, 0,
&trap_nop);
/*
* NOTE: After cpu_exit_clear, per-cpu variables may no longer accessible,
* as they may be freed at any time if offline CPUs don't get parked. In
@@ -118,9 +124,10 @@ static void play_dead(void)
* Consider very carefully when adding code to *dead_idle. Most hypervisor
* subsystems are unsafe to call.
*/
cpu_exit_clear(smp_processor_id());
cpu_exit_clear(cpu);
(*dead_idle)();
for ( ; ; )
dead_idle();
}
static void idle_loop(void)
+2 -2
View File
@@ -33,6 +33,7 @@
#include <xen/serial.h>
#include <xen/numa.h>
#include <xen/cpu.h>
#include <asm/cpuidle.h>
#include <asm/current.h>
#include <asm/mc146818rtc.h>
#include <asm/desc.h>
@@ -209,8 +210,7 @@ static void smp_callin(void)
halt:
clear_local_APIC();
spin_debug_enable();
cpu_exit_clear(cpu);
(*dead_idle)();
play_dead();
}
/* Allow the master to continue. */
+1
View File
@@ -20,6 +20,7 @@ int mwait_idle_init(struct notifier_block *);
int cpuidle_init_cpu(unsigned int cpu);
void default_dead_idle(void);
void acpi_dead_idle(void);
void play_dead(void);
void trace_exit_reason(u32 *irq_traced);
void update_idle_stats(struct acpi_processor_power *,
struct acpi_processor_cx *, uint64_t, uint64_t);
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.