diff options
author | Ian Moffett <ian@osmora.org> | 2025-06-01 19:58:28 -0400 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2025-06-01 19:58:28 -0400 |
commit | c3091854eef84ba4655ada317c215c426a08045c (patch) | |
tree | 9346c4099fe4d5f1d5c7d68b6347ae3c9b227fe4 | |
parent | 7fb5702f6625b181dd61cd4bd59c45b16bb3983a (diff) |
kernel/amd64: Add support for TLB shootdowns
Signed-off-by: Ian Moffett <ian@osmora.org>
-rw-r--r-- | sys/arch/amd64/amd64/machdep.c | 48 | ||||
-rw-r--r-- | sys/include/arch/amd64/cpu.h | 5 |
2 files changed, 53 insertions, 0 deletions
diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c index 19918b7..c6fb6c4 100644 --- a/sys/arch/amd64/amd64/machdep.c +++ b/sys/arch/amd64/amd64/machdep.c @@ -42,9 +42,11 @@ #include <machine/uart.h> #include <machine/sync.h> #include <machine/intr.h> +#include <machine/cdefs.h> #include <machine/isa/i8042var.h> #define HALT_VECTOR 0x21 +#define TLB_VECTOR 0x22 #if defined(__SPECTRE_IBRS) #define SPECTRE_IBRS __SPECTRE_IBRS @@ -66,6 +68,31 @@ cpu_halt_isr(void *p) __builtin_unreachable(); } +__attribute__((__interrupt__)) +static void +tlb_shootdown_isr(void *p) +{ + struct cpu_info *ci; + int ipl; + + /* + * Get the current CPU and check if we even + * need a shootdown. If `tlb_shootdown' is + * unset, this is not for us. + */ + ci = this_cpu(); + if (!ci->tlb_shootdown) { + return; + } + + ipl = splraise(IPL_HIGH); + __invlpg(ci->shootdown_va); + + ci->shootdown_va = 0; + ci->tlb_shootdown = 0; + splx(ipl); +} + static void setup_vectors(void) { @@ -83,6 +110,7 @@ setup_vectors(void) 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); + idt_set_desc(TLB_VECTOR, IDT_INT_GATE, ISR(tlb_shootdown_isr), 0); pin_isr_load(); } @@ -128,6 +156,26 @@ backtrace_addr_to_name(uintptr_t addr, off_t *off) } void +cpu_shootdown_tlb(vaddr_t va) +{ + uint32_t ncpu = cpu_count(); + struct cpu_info *cip; + + for (uint32_t i = 0; i < ncpu; ++i) { + cip = cpu_get(i); + if (cip == NULL) { + break; + } + + spinlock_acquire(&cip->lock); + cip->shootdown_va = va; + cip->tlb_shootdown = 1; + lapic_send_ipi(cip->apicid, IPI_SHORTHAND_NONE, TLB_VECTOR); + spinlock_release(&cip->lock); + } +} + +void md_backtrace(void) { uintptr_t *rbp; diff --git a/sys/include/arch/amd64/cpu.h b/sys/include/arch/amd64/cpu.h index 89bc5e9..2d08d6e 100644 --- a/sys/include/arch/amd64/cpu.h +++ b/sys/include/arch/amd64/cpu.h @@ -33,6 +33,7 @@ #include <sys/types.h> #include <sys/cdefs.h> #include <sys/proc.h> +#include <sys/spinlock.h> #include <machine/tss.h> #define CPU_IRQ(IRQ_N) (BIT((IRQ_N)) & 0xFF) @@ -40,11 +41,14 @@ struct cpu_info { uint32_t apicid; uint8_t has_x2apic : 1; + uint8_t tlb_shootdown : 1; uint8_t ipl; size_t lapic_tmr_freq; uint8_t irq_mask; + vaddr_t shootdown_va; struct tss_entry *tss; struct proc *curtd; + struct spinlock lock; struct cpu_info *self; }; @@ -54,6 +58,7 @@ void cpu_startup(struct cpu_info *ci); struct cpu_info *cpu_get(uint32_t index); uint32_t cpu_count(void); +void cpu_shootdown_tlb(vaddr_t va); struct cpu_info *this_cpu(void); void mp_bootstrap_aps(struct cpu_info *ci); |