From 67f9d3c5e58f1a958a2b1b7a102a71e3ce252fc4 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Wed, 10 Jul 2024 20:59:37 -0400 Subject: kernel/amd64: reboot: Halt all with REBOOT_HALT This commit changes how reboot() handles REBOOT_HALT. Now instead of one core being halted, all cores will be halted through an IPI to a halt vector. Signed-off-by: Ian Moffett --- sys/arch/amd64/amd64/machdep.c | 24 ++++++++++++++++++++++++ sys/arch/amd64/amd64/reboot.c | 9 ++------- sys/include/arch/amd64/cpu.h | 2 ++ 3 files changed, 28 insertions(+), 7 deletions(-) (limited to 'sys') diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c index 03b10f0..2185028 100644 --- a/sys/arch/amd64/amd64/machdep.c +++ b/sys/arch/amd64/amd64/machdep.c @@ -38,6 +38,7 @@ #include #include #include +#include #if defined(__SPECTRE_IBRS) #define SPECTRE_IBRS __SPECTRE_IBRS @@ -45,6 +46,8 @@ #define SPECTRE_IBRS 0 #endif +static uint8_t halt_vector = 0; + int ibrs_enable(void); void syscall_isr(void); @@ -54,9 +57,21 @@ static struct gdtr bsp_gdtr = { .offset = (uintptr_t)&g_gdt_data[0] }; +__attribute__((__interrupt__)) +static void +cpu_halt_isr(void *p) +{ + __ASMV("cli; hlt"); + __builtin_unreachable(); +} + static void setup_vectors(void) { + if (halt_vector == 0) { + halt_vector = intr_alloc_vector("cpu-halt", IPL_HIGH); + } + idt_set_desc(0x0, IDT_TRAP_GATE, ISR(arith_err), 0); idt_set_desc(0x2, IDT_TRAP_GATE, ISR(nmi), 0); idt_set_desc(0x3, IDT_TRAP_GATE, ISR(breakpoint_handler), 0); @@ -70,6 +85,7 @@ setup_vectors(void) idt_set_desc(0xD, IDT_TRAP_GATE, ISR(general_prot), 0); idt_set_desc(0xE, IDT_TRAP_GATE, ISR(page_fault), 0); idt_set_desc(0x80, IDT_USER_INT_GATE, ISR(syscall_isr), 0); + idt_set_desc(halt_vector, IDT_INT_GATE, ISR(cpu_halt_isr), 0); } static inline void @@ -92,6 +108,14 @@ try_mitigate_spectre(void) ibrs_enable(); } +void +cpu_halt_all(void) +{ + /* Send IPI to all cores */ + lapic_send_ipi(0, IPI_SHORTHAND_ALL, halt_vector); + for (;;); +} + void serial_init(void) { diff --git a/sys/arch/amd64/amd64/reboot.c b/sys/arch/amd64/amd64/reboot.c index da1b46a..02126d3 100644 --- a/sys/arch/amd64/amd64/reboot.c +++ b/sys/arch/amd64/amd64/reboot.c @@ -31,18 +31,13 @@ #include #include #include - -__always_inline static inline void -cpu_halt(void) -{ - __ASMV("cli; hlt"); -} +#include void cpu_reboot(int method) { if (ISSET(method, REBOOT_HALT)) { - cpu_halt(); + cpu_halt_all(); } /* Pulse the reset line until the machine goes down */ diff --git a/sys/include/arch/amd64/cpu.h b/sys/include/arch/amd64/cpu.h index 2ce363c..37f28cb 100644 --- a/sys/include/arch/amd64/cpu.h +++ b/sys/include/arch/amd64/cpu.h @@ -45,7 +45,9 @@ struct cpu_info { struct cpu_info *self; }; +__dead void cpu_halt_all(void); void cpu_startup(struct cpu_info *ci); + struct cpu_info *this_cpu(void); void mp_bootstrap_aps(struct cpu_info *ci); -- cgit v1.2.3