interrupt: nmi work

This commit is contained in:
Matheus
2025-12-05 18:09:36 -03:00
parent 47f5a2fcfb
commit d10295dcdf
4 changed files with 115 additions and 4 deletions
+31
View File
@@ -9,6 +9,7 @@
#include <arch/gdt.h>
#include <kernel/dpc.h>
#include <arch/context.h>
#include <arch/prof.h>
#define EFER_SYSCALLENABLE 1
@@ -45,6 +46,27 @@ static void x87isr(isr_t *self, context_t *ctx) {
}
}
void arch_nmi_isr(context_t *ctx) {
// we are in an NMI context, running on IST0
// first load the proper gsbase to get access to cpu-local variables.
// the pointer to cpu's data is at the beggining of the stack so after the context struct.
uint64_t old_gsbase = rdmsr(MSR_GSBASE);
wrmsr(MSR_GSBASE, *(uint64_t *)(ctx + 1));
bool handled = false;
#ifdef ENABLE_PROFILING
if (arch_profiling_irq(ctx))
handled = true;
#endif
if (!handled)
_panic("Unhandled NMI", ctx);
// restore the old gsbase
wrmsr(MSR_GSBASE, old_gsbase);
}
#define TOPOLOGY_TYPE_THREAD 1
#define TOPOLOGY_TYPE_CORE 2
#define TOPOLOGY_TYPE_PACKAGE 0xffffffff
@@ -237,6 +259,15 @@ void arch_cpu_init() {
}
current_cpu()->topology_node = topology_nodes[topology_depth - 1];
// allocate ists
uint64_t *ist1 = vmm_map(NULL, PAGE_SIZE * 4, VMM_FLAGS_ALLOCATE, ARCH_MMU_FLAGS_READ | ARCH_MMU_FLAGS_WRITE | ARCH_MMU_FLAGS_NOEXEC, NULL);
__assert(ist1);
// the cpu automatically aligns to 16 bytes when pushing the interrupt frame, so save ourselves the trouble:
ist1 += PAGE_SIZE * 4 / sizeof(uint64_t) - 2;
*ist1 = (uint64_t)current_cpu();
current_cpu()->ist.ist1 = (uint64_t)ist1;
}
INIT_ROUTINE_DEFINE(cpu, INIT_ROUTINE_FLAGS_NONE, arch_cpu_init, acpi_early);
+6 -4
View File
@@ -29,16 +29,18 @@ static idtr_t idtr = {
.offset = (uint64_t)idt
};
void asm_nmi_handler();
extern const uint64_t isr_table[256];
void arch_idt_setup() {
for (int i = 0; i < 256; ++i) {
idt[i].offset = isr_table[i] & 0xffff;
uint64_t addr = i == 2 ? (uint64_t)asm_nmi_handler : isr_table[i];
idt[i].offset = addr & 0xffff;
idt[i].segment = 0x8;
idt[i].ist = 0;
idt[i].ist = i == 2 ? 1 : 0;
idt[i].flags = 0x8e;
idt[i].offset2 = (isr_table[i] >> 16) & 0xffff;
idt[i].offset3 = (isr_table[i] >> 32) & 0xffffffff;
idt[i].offset2 = (addr >> 16) & 0xffff;
idt[i].offset3 = (addr >> 32) & 0xffffffff;
}
}
+75
View File
@@ -57,6 +57,9 @@ isr_common:
mov rdi, rbp ; vec
mov rsi, rsp ; ctx
; set this as the end of the stack frame
xor rbp, rbp
cld
extern interrupt_isr
call interrupt_isr
@@ -93,6 +96,78 @@ isr_common:
.notneeded2:
o64 iret
global asm_nmi_handler
asm_nmi_handler:
sub rsp, 8 ; error code, unused for nmi
push rbp
sub rsp, 8 ; vec number, unused for nmi
push rsi
push rdi
push r15
push r14
push r13
push r12
push r11
push r10
push r9
push r8
push rdx
push rcx
push rbx
push rax
mov rax, ds
push rax
mov rax, es
push rax
mov rax, fs
push rax
mov rax, gs
push rax
mov rdi,cr2
push rdi
; set up kernel segments
mov rdi, 0x10
mov ds, rdi
mov es, rdi
; save ctx pointer
mov rdi, rsp
; set this as the end of the stack frame
xor rbp, rbp
cld
extern arch_nmi_isr
call arch_nmi_isr
cli
; pop context
add rsp, 24 ; cr2 gs and fs are not popped.
pop rax
mov es,rax
pop rax
mov ds,rax
pop rax
pop rbx
pop rcx
pop rdx
pop r8
pop r9
pop r10
pop r11
pop r12
pop r13
pop r14
pop r15
pop rdi
pop rsi
add rsp, 8 ; vector num, unused for nmi
pop rbp
add rsp, 8 ; error code, unused for nmi
o64 iret
section .rodata
global isr_table
isr_table:
+3
View File
@@ -273,6 +273,9 @@ arch_syscall_entry:
mov rdx, rsi
mov rsi, rdi
; set this as the end of the stack frame
xor rbp, rbp
; call logging function
sti