mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
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:
1 parent
de4de79100
commit
73cb1383bf
3 files changed
+15
-7
No files matched your search
+12
-5
@@ -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)
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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);
|
||||
|
||||