From 8d42b8085556abe25faa3cd35b1937707d814280 Mon Sep 17 00:00:00 2001 From: Matheus Date: Sun, 26 May 2024 20:51:54 -0300 Subject: [PATCH] smp: nmi ipi support --- kernel-src/arch/x86-64/apic.c | 2 +- kernel-src/arch/x86-64/mmu.c | 2 +- kernel-src/arch/x86-64/smp.c | 19 ++++++++++++++----- kernel-src/include/x86-64/arch/apic.h | 2 ++ kernel-src/include/x86-64/arch/smp.h | 3 ++- 5 files changed, 20 insertions(+), 8 deletions(-) diff --git a/kernel-src/arch/x86-64/apic.c b/kernel-src/arch/x86-64/apic.c index ad981aee..ddffa77f 100644 --- a/kernel-src/arch/x86-64/apic.c +++ b/kernel-src/arch/x86-64/apic.c @@ -284,7 +284,7 @@ void arch_apic_sendipi(uint8_t cpu, uint8_t vec, uint8_t dest, uint8_t mode, uin while (readlapic(APIC_REG_ICR_LO) & APIC_REG_ICR_LO_STATUS) CPU_PAUSE(); writelapic(APIC_REG_ICR_HI, (uint32_t)cpu << 24); - writelapic(APIC_REG_ICR_LO, vec | (level << 14) | (mode << 15) | (dest << 18)); + writelapic(APIC_REG_ICR_LO, vec | (level << 8) | (mode << 11) | (dest << 18) | (1 << 14)); } void arch_apic_init() { diff --git a/kernel-src/arch/x86-64/mmu.c b/kernel-src/arch/x86-64/mmu.c index 949a41d8..6c0f6418 100644 --- a/kernel-src/arch/x86-64/mmu.c +++ b/kernel-src/arch/x86-64/mmu.c @@ -220,7 +220,7 @@ void arch_mmu_tlbshootdown(void *page) { mmupage = page; remaining = arch_smp_cpusawake - 1; - arch_smp_sendipi(NULL, &_cpu()->isr[0xfe], ARCH_SMP_IPI_OTHERCPUS); + arch_smp_sendipi(NULL, &_cpu()->isr[0xfe], ARCH_SMP_IPI_OTHERCPUS, true); while (__atomic_load_n(&remaining, __ATOMIC_SEQ_CST)) CPU_PAUSE(); diff --git a/kernel-src/arch/x86-64/smp.c b/kernel-src/arch/x86-64/smp.c index 6e1acdad..ca080977 100644 --- a/kernel-src/arch/x86-64/smp.c +++ b/kernel-src/arch/x86-64/smp.c @@ -5,6 +5,7 @@ #include #include #include +#include static volatile struct limine_smp_request smprequest = { .id = LIMINE_SMP_REQUEST @@ -13,11 +14,19 @@ static volatile struct limine_smp_request smprequest = { // set to 1 because of the bsp size_t arch_smp_cpusawake = 1; +// for panic. if the nosmp argument is given to the kernel, this is what the APs will jump to +static void cpuwakeuphalt(struct limine_smp_info *info) { + asm("cli"); + for (;;) CPU_HALT(); +} + + static void cpuwakeup(struct limine_smp_info *info) { cpu_set((cpu_t *)info->extra_argument); arch_gdt_reload(); arch_idt_reload(); + interrupt_register(0xfd, (void *)cpuwakeuphalt, NULL, IPL_IGNORE); dpc_init(); arch_mmu_apswitch(); vmm_apinit(); @@ -30,16 +39,16 @@ static void cpuwakeup(struct limine_smp_info *info) { sched_apentry(); } -// if the nosmp argument is given to the kernel, this is what the APs will jump to -static void cpuwakeuphalt(struct limine_smp_info *info) { - for (;;) CPU_HALT(); +void arch_smp_sendipi(cpu_t *targcpu, isr_t *isr, int target, bool nmi) { + arch_apic_sendipi(targcpu ? targcpu->id : 0, INTERRUPT_IDTOVECTOR(isr->id), target, nmi ? APIC_MODE_NMI : 0, 0); } -void arch_smp_sendipi(cpu_t *targcpu, isr_t *isr, int target) { - arch_apic_sendipi(targcpu ? targcpu->id : 0, INTERRUPT_IDTOVECTOR(isr->id), target, 0, 1); +void arch_smp_haltallothers() { + arch_smp_sendipi(NULL, &_cpu()->isr[0xfd], ARCH_SMP_IPI_OTHERCPUS, true); } void arch_smp_wakeup() { + interrupt_register(0xfd, (void *)cpuwakeuphalt, NULL, IPL_IGNORE); struct limine_smp_response *response = smprequest.response; if (response == NULL) { // TODO try to detect the other processors manually diff --git a/kernel-src/include/x86-64/arch/apic.h b/kernel-src/include/x86-64/arch/apic.h index f1318b09..331042d3 100644 --- a/kernel-src/include/x86-64/arch/apic.h +++ b/kernel-src/include/x86-64/arch/apic.h @@ -1,6 +1,8 @@ #ifndef _APIC_H #define _APIC_H +#define APIC_MODE_NMI 4 + void arch_apic_timerinit(); void arch_apic_init(); void arch_apic_initap(); diff --git a/kernel-src/include/x86-64/arch/smp.h b/kernel-src/include/x86-64/arch/smp.h index 904ba9cd..43367192 100644 --- a/kernel-src/include/x86-64/arch/smp.h +++ b/kernel-src/include/x86-64/arch/smp.h @@ -9,6 +9,7 @@ extern size_t arch_smp_cpusawake; void arch_smp_wakeup(); -void arch_smp_sendipi(cpu_t *targcpu, isr_t *isr, int target); +void arch_smp_sendipi(cpu_t *targcpu, isr_t *isr, int target, bool nmi); +void arch_smp_haltallothers(); #endif