diff --git a/.gitignore b/.gitignore index eb5a316..485dee6 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -target +.idea diff --git a/src/arch/x86_64/interrupt/exception.rs b/src/arch/x86_64/interrupt/exception.rs index 142e2b5..cf35828 100644 --- a/src/arch/x86_64/interrupt/exception.rs +++ b/src/arch/x86_64/interrupt/exception.rs @@ -41,7 +41,7 @@ interrupt_stack!(debug, @paranoid, |stack| { } }); -interrupt_stack!(non_maskable, @paranoid, |stack| { +nmi_handler!(non_maskable, |stack| { println!("Non-maskable interrupt"); stack.dump(); }); diff --git a/src/arch/x86_64/interrupt/handler.rs b/src/arch/x86_64/interrupt/handler.rs index ddbef82..9604770 100644 --- a/src/arch/x86_64/interrupt/handler.rs +++ b/src/arch/x86_64/interrupt/handler.rs @@ -406,12 +406,21 @@ macro_rules! interrupt_stack { $code } } + fn function_name(){ + println!("hello"); + } + fn function_name2(){ + println!("hello 2"); + } core::arch::asm!(concat!( // Backup all userspace registers to stack $save1!(), "push rax\n", push_scratch!(), push_preserved!(), + " + //call {p} + ", $save2!(), @@ -434,9 +443,15 @@ macro_rules! interrupt_stack { pop_scratch!(), $rstor1!(), + " + // call {p2} + ", "iretq\n", ), + p = sym function_name, + p2 = sym function_name2, + inner = sym inner, IA32_GS_BASE = const(x86::msr::IA32_GS_BASE), KERNEL_PERCPU_SHIFT = const(crate::KERNEL_PERCPU_SHIFT), @@ -452,6 +467,138 @@ macro_rules! interrupt_stack { ($name:ident, |$stack:ident| $code:block) => { interrupt_stack!($name, swapgs_iff_ring3_fast!, nop!, nop!, swapgs_iff_ring3_fast!, is_paranoid: false, |$stack| $code); }; ($name:ident, @paranoid, |$stack:ident| $code:block) => { interrupt_stack!($name, nop!, save_and_set_gsbase_paranoid!, restore_gsbase_paranoid!, nop!, is_paranoid: true, |$stack| $code); } } +#[macro_export] +macro_rules! nmi_handler { + ($name:ident, |$stack:ident| $code:block) => { + + #[naked] + #[allow(named_asm_labels)] + pub unsafe extern "C" fn $ name() { + unsafe extern "C" fn inner( $ stack: &mut $ crate::arch::x86_64::interrupt::InterruptStack) { + # [allow(unused_unsafe)] + unsafe { + $ code + } + } + + core::arch::asm!(concat!( + " + push rdx + // replace test come from kernel + cmp QWORD PTR [rsp + 8*2], {GDT_KERNEL_CODE} + jne first_nmi + ", + // not from user space + " + cmp QWORD PTR [rsp -8], $1 + je nested_nmi + ", + // if nmi stack + " + lea rdx, [rsp + 6*8] + cmp 4*8[rsp], rdx + ja first_nmi + ", + // nested nmi + " + nested_nmi: + /// ! repalce with address of repeat nmi and end repeat nmi + mov rdx, 0x080a3352 + cmp rdx, 8[rsp] + ja 1f + mov rdx, 0x080a3377 + cmp rdx, 8[rsp] + ja nested_nmi_out + ", + // prepare + " + 1: + lea rdx, -1*8[rsp] + mov rsp, rdx + lea rdx, -10*8[rsp] + push {GDT_KERNEL_DATA} + push rdx + pushf + push {GDT_KERNEL_CODE} + //replace address repeat nmi + push 0x080a3352 + ", + // nested nmi out + " + nested_nmi_out: + pop rdx + iretq + ", + + + // first nmi + " + first_nmi: + mov rdx, [rsp] + push $1 + ", + // first copy + " + sub rsp, $(5*8) + + .rept 5 + push 11*8[rsp] + .endr + ", + //second copy + " + repeat_nmi: + mov QWORD PTR 10*8[rsp], $1 + + add rsp, $(10*8) + + .rept 5 + push -6*8[rsp] + .endr + sub rsp, $(5*8) + ", + //normal continuation + " + end_repeat_nmi: + ", + swapgs_iff_ring3_fast!(), + " + push rax + ", + push_scratch!(), + push_preserved!(), + // save_and_set_gsbase_paranoid!(), + " + mov rdi,rsp + call {inner} + ", + // restore_gbase_paranoid!(), + pop_preserved!(), + pop_scratch!(), + swapgs_iff_ring3_fast!(), + " + 7: + add rsp,$6*8 + + mov QWORD PTR 5*8[rsp], $0 + + iretq + ", + + ), + + inner = sym inner, + GDT_KERNEL_CODE = const(crate::gdt::GDT_KERNEL_CODE), + GDT_KERNEL_DATA = const(crate::gdt::GDT_KERNEL_DATA), + + options(noreturn), + + ); + + } + } +} + #[macro_export] macro_rules! interrupt { diff --git a/src/syscall/mod.rs b/src/syscall/mod.rs index 5f18288..3f4df68 100644 --- a/src/syscall/mod.rs +++ b/src/syscall/mod.rs @@ -33,7 +33,7 @@ use self::flag::{MapFlags, PhysmapFlags, WaitFlags}; use self::number::*; use crate::context::ContextId; -use crate::interrupt::exception::{divide_by_zero, non_maskable}; +use crate::interrupt::exception::divide_by_zero; use crate::interrupt::InterruptStack; use crate::scheme::{FileHandle, SchemeNamespace, memory::MemoryScheme}; @@ -63,9 +63,9 @@ pub mod validate; fn nmi_t() -> Result{ println!("Yo"); - unsafe { - //non_maskable(); - } + // unsafe { + // divide_by_zero(); + // } Ok(0) }