summaryrefslogtreecommitdiff
path: root/sys/arch/amd64
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2025-08-22 22:14:40 -0400
committerIan Moffett <ian@osmora.org>2025-08-22 22:14:40 -0400
commit7981d8b03c48afd0ff7c80dab1b8bed27c55c3da (patch)
treef818e8099c8d6fe8f46f46df6e1173301654ede7 /sys/arch/amd64
parent84cd06f9a7439f2a35aaa11d4a926eaa88751921 (diff)
kernel/amd64: ipi: Make halt IPI more direct
This commit assigns the halt IPI its own vector so that it may be dispatched fast without needing to go through the IPI path as it is typically used only in very sensitive situations. Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'sys/arch/amd64')
-rw-r--r--sys/arch/amd64/amd64/ipi.c3
-rw-r--r--sys/arch/amd64/amd64/machdep.c70
-rw-r--r--sys/arch/amd64/amd64/vector.S6
3 files changed, 20 insertions, 59 deletions
diff --git a/sys/arch/amd64/amd64/ipi.c b/sys/arch/amd64/amd64/ipi.c
index e367552..bf263d3 100644
--- a/sys/arch/amd64/amd64/ipi.c
+++ b/sys/arch/amd64/amd64/ipi.c
@@ -41,6 +41,7 @@
#include <string.h>
void ipi_isr(void);
+void halt_isr(void);
void __ipi_handle_common(void);
@@ -48,7 +49,6 @@ void __ipi_handle_common(void);
#define pr_error(...) pr_trace(__VA_ARGS__)
#define COOKIE 0x7E0A
-#define IPI_VECTOR 0x21
#define MAX_IPI 32
/* For the global state of the subsystem */
@@ -186,5 +186,6 @@ md_ipi_init(void)
{
/* Initialize the IPI vectors */
idt_set_desc(IPI_VECTOR, IDT_INT_GATE, ISR(ipi_isr), 0);
+ idt_set_desc(HALT_VECTOR, IDT_INT_GATE, ISR(halt_isr), 0);
cookie = COOKIE;
}
diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c
index 2976a51..60c37bf 100644
--- a/sys/arch/amd64/amd64/machdep.c
+++ b/sys/arch/amd64/amd64/machdep.c
@@ -86,19 +86,11 @@ void syscall_isr(void);
void pin_isr_load(void);
struct cpu_info g_bsp_ci = {0};
-static struct cpu_ipi *halt_ipi;
static struct cpu_ipi *tlb_ipi;
static struct spinlock ipi_lock = {0};
static bool bsp_init = false;
static int
-cpu_halt_handler(struct cpu_ipi *ipi)
-{
- __ASMV("cli; hlt");
- __builtin_unreachable();
-}
-
-static int
tlb_shootdown_handler(struct cpu_ipi *ipi)
{
struct cpu_info *ci;
@@ -223,13 +215,6 @@ init_ipis(void)
}
spinlock_acquire(&ipi_lock);
- error = md_ipi_alloc(&halt_ipi);
- if (error < 0) {
- pr_error("md_ipi_alloc: returned %d\n", error);
- panic("failed to init halt IPI\n");
- }
-
- halt_ipi->handler = cpu_halt_handler;
error = md_ipi_alloc(&tlb_ipi);
if (error < 0) {
pr_error("md_ipi_alloc: returned %d\n", error);
@@ -243,8 +228,6 @@ init_ipis(void)
* so that they are standard and usable
* throughout the rest of the sytem.
*/
- if (halt_ipi->id != IPI_HALT)
- panic("expected IPI_HALT for halt IPI\n");
if (tlb_ipi->id != IPI_TLB)
panic("expected IPI_TLB for TLB IPI\n");
@@ -461,31 +444,14 @@ md_backtrace(void)
void
cpu_halt_all(void)
{
- struct cpu_info *ci, *curcpu;
- uint32_t ncpu = cpu_count();
-
- /*
- * If we have no current 'cpu_info' structure set,
- * we can't send IPIs, so just assume only the current
- * processor is the only one active, clear interrupts
- * then halt it.
- */
- __ASMV("cli");
- if ((curcpu = this_cpu()) == NULL) {
- __ASMV("hlt");
- }
+ lapic_send_ipi(
+ 0,
+ IPI_SHORTHAND_ALL,
+ HALT_VECTOR
+ );
- for (int i = 0; i < ncpu; ++i) {
- ci = cpu_get(i);
- if (ci->id == curcpu->id) {
- continue;
- }
-
- md_ipi_send(ci, IPI_HALT);
- }
-
- __ASMV("hlt");
- for (;;);
+ __ASMV("cli; hlt");
+ __builtin_unreachable();
}
/*
@@ -495,23 +461,11 @@ cpu_halt_all(void)
void
cpu_halt_others(void)
{
- struct cpu_info *curcpu, *ci;
- uint32_t ncpu = cpu_count();
-
- if (rdmsr(IA32_GS_BASE) == 0 || ncpu <= 1) {
- return;
- }
-
- curcpu = this_cpu();
-
- for (int i = 0; i < ncpu; ++i) {
- if ((ci = cpu_get(i)) == NULL)
- continue;
- if (ci->id == curcpu->id)
- continue;
-
- md_ipi_send(ci, IPI_HALT);
- }
+ lapic_send_ipi(
+ 0,
+ IPI_SHORTHAND_OTHERS,
+ HALT_VECTOR
+ );
}
void
diff --git a/sys/arch/amd64/amd64/vector.S b/sys/arch/amd64/amd64/vector.S
index 69173d7..62bed1b 100644
--- a/sys/arch/amd64/amd64/vector.S
+++ b/sys/arch/amd64/amd64/vector.S
@@ -144,6 +144,12 @@ INTRENTRY(ipi_isr, ipi_trampoline)
call ipi_trampoline
retq
+ .globl halt_isr
+INTRENTRY(halt_isr, halt_trampoline)
+halt_trampoline:
+ cli
+ hlt
+
ipi_trampoline:
call __ipi_handle_common
retq