summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2024-07-10 20:59:37 -0400
committerIan Moffett <ian@osmora.org>2024-07-10 21:02:56 -0400
commit67f9d3c5e58f1a958a2b1b7a102a71e3ce252fc4 (patch)
tree108fbc812dd0acd00005e025faf2be9831f95100
parentd243e9b36fe2bf8e9551cc6677aaa2747604fcfa (diff)
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 <ian@osmora.org>
-rw-r--r--sys/arch/amd64/amd64/machdep.c24
-rw-r--r--sys/arch/amd64/amd64/reboot.c9
-rw-r--r--sys/include/arch/amd64/cpu.h2
3 files changed, 28 insertions, 7 deletions
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 <machine/cpuid.h>
#include <machine/lapic.h>
#include <machine/uart.h>
+#include <machine/intr.h>
#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
@@ -93,6 +109,14 @@ try_mitigate_spectre(void)
}
void
+cpu_halt_all(void)
+{
+ /* Send IPI to all cores */
+ lapic_send_ipi(0, IPI_SHORTHAND_ALL, halt_vector);
+ for (;;);
+}
+
+void
serial_init(void)
{
uart_init();
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 <sys/param.h>
#include <sys/cdefs.h>
#include <machine/pio.h>
-
-__always_inline static inline void
-cpu_halt(void)
-{
- __ASMV("cli; hlt");
-}
+#include <machine/cpu.h>
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);