diff --git a/Kernel/Arch/x86/DescriptorTable.h b/Kernel/Arch/x86/DescriptorTable.h index b54da8070e..51585279a3 100644 --- a/Kernel/Arch/x86/DescriptorTable.h +++ b/Kernel/Arch/x86/DescriptorTable.h @@ -116,9 +116,15 @@ struct [[gnu::packed]] IDTEntry u16 offset_1; // offset bits 0..15 u16 selector; // a code segment selector in GDT or LDT - u8 zero; // unused, set to 0 (maybe used on amd64) +#if ARCH(I386) + u8 zero; // unused, set to 0 +#else + struct { + u8 interrupt_stack_table : 3; + u8 zero : 5; // unused, set to 0 + }; +#endif struct { - // FIXME: Is the order correct? u8 gate_type : 4; u8 storage_segment : 1; u8 descriptor_privilege_level : 2; @@ -126,7 +132,6 @@ struct [[gnu::packed]] IDTEntry } type_attr; // type and attributes u16 offset_2; // offset bits 16..31 #if !ARCH(I386) -// we may need to switch those around? u32 offset_3; u32 zeros; #endif @@ -135,6 +140,9 @@ struct [[gnu::packed]] IDTEntry IDTEntry(FlatPtr callback, u16 selector_, IDTEntryType type, u8 storage_segment, u8 privilege_level) : offset_1 { (u16)((FlatPtr)callback & 0xFFFF) } , selector { selector_ } +#if !ARCH(I386) + , interrupt_stack_table { 0 } +#endif , zero { 0 } , type_attr { .gate_type = (u8)type, @@ -150,7 +158,7 @@ struct [[gnu::packed]] IDTEntry { } - u32 off() + FlatPtr off() { #if ARCH(I386) return (u32)offset_2 << 16 & (u32)offset_1; @@ -165,4 +173,6 @@ struct [[gnu::packed]] IDTEntry }; // clang-format on +static_assert(sizeof(IDTEntry) == 2 * sizeof(void*)); + } diff --git a/Kernel/Arch/x86/TrapFrame.h b/Kernel/Arch/x86/TrapFrame.h index bf46e58f8c..48c7815e15 100644 --- a/Kernel/Arch/x86/TrapFrame.h +++ b/Kernel/Arch/x86/TrapFrame.h @@ -15,7 +15,7 @@ namespace Kernel { struct TrapFrame { - u32 prev_irq_level; + FlatPtr prev_irq_level; TrapFrame* next_trap; RegisterState* regs; // must be last diff --git a/Kernel/Arch/x86/common/Interrupts.cpp b/Kernel/Arch/x86/common/Interrupts.cpp index b205b9ad63..fe6db5c2ec 100644 --- a/Kernel/Arch/x86/common/Interrupts.cpp +++ b/Kernel/Arch/x86/common/Interrupts.cpp @@ -100,8 +100,32 @@ static EntropySource s_entropy_source_interrupts { EntropySource::Static::Interr asm( \ ".globl " #title "_asm_entry\n" \ "" #title "_asm_entry: \n" \ - " cli;hlt;\n" \ -); + " pushq %r15\n" \ + " pushq %r14\n" \ + " pushq %r13\n" \ + " pushq %r12\n" \ + " pushq %r11\n" \ + " pushq %r10\n" \ + " pushq %r9\n" \ + " pushq %r8\n" \ + " pushq %rax\n" \ + " pushq %rcx\n" \ + " pushq %rdx\n" \ + " pushq %rbx\n" \ + " pushq %rsp\n" \ + " pushq %rbp\n" \ + " pushq %rsi\n" \ + " pushq %rdi\n" \ + " pushq %rsp \n" /* set TrapFrame::regs */ \ + " subq $" __STRINGIFY(TRAP_FRAME_SIZE - 8) ", %rsp \n" \ + " subq $0x8, %rsp\n" /* align stack */ \ + " lea 0x8(%rsp), %rdi \n" \ + " cld\n" \ + " call enter_trap_no_irq \n" \ + " lea 0x8(%rsp), %rdi \n" \ + " call " #title "_handler\n" \ + " addq $0x8, %rsp\n" /* undo alignment */\ + " jmp common_trap_exit \n"); #define EH_ENTRY_NO_CODE(ec, title) \ extern "C" void title##_handler(TrapFrame*); \ @@ -109,8 +133,33 @@ static EntropySource s_entropy_source_interrupts { EntropySource::Static::Interr asm( \ ".globl " #title "_asm_entry\n" \ "" #title "_asm_entry: \n" \ - " cli;hlt;\n" \ -); + " pushq $0x0\n" \ + " pushq %r15\n" \ + " pushq %r14\n" \ + " pushq %r13\n" \ + " pushq %r12\n" \ + " pushq %r11\n" \ + " pushq %r10\n" \ + " pushq %r9\n" \ + " pushq %r8\n" \ + " pushq %rax\n" \ + " pushq %rcx\n" \ + " pushq %rdx\n" \ + " pushq %rbx\n" \ + " pushq %rsp\n" \ + " pushq %rbp\n" \ + " pushq %rsi\n" \ + " pushq %rdi\n" \ + " pushq %rsp \n" /* set TrapFrame::regs */ \ + " subq $" __STRINGIFY(TRAP_FRAME_SIZE - 8) ", %rsp \n" \ + " subq $0x8, %rsp\n" /* align stack */ \ + " lea 0x8(%rsp), %rdi \n" \ + " cld\n" \ + " call enter_trap_no_irq \n" \ + " lea 0x8(%rsp), %rdi \n" \ + " call " #title "_handler\n" \ + " addq $0x8, %rsp\n" /* undo alignment */\ + " jmp common_trap_exit \n"); #endif // clang-format on diff --git a/Kernel/Arch/x86/x86_64/InterruptEntry.cpp b/Kernel/Arch/x86/x86_64/InterruptEntry.cpp index 991583929f..58d2f2150b 100644 --- a/Kernel/Arch/x86/x86_64/InterruptEntry.cpp +++ b/Kernel/Arch/x86/x86_64/InterruptEntry.cpp @@ -10,15 +10,35 @@ // clang-format off asm( -".globl interrupt_common_asm_entry\n" -"interrupt_common_asm_entry: \n" -" int3 \n" // FIXME -".globl common_trap_exit \n" -"common_trap_exit: \n" -// another thread may have handled this trap at this point, so don't -// make assumptions about the stack other than there's a TrapFrame -// and a pointer to it. -" call exit_trap \n" -" int3 \n" // FIXME + ".globl interrupt_common_asm_entry\n" + "interrupt_common_asm_entry: \n" + " hlt \n" // FIXME + ".globl common_trap_exit \n" + "common_trap_exit: \n" + // another thread may have handled this trap at this point, so don't + // make assumptions about the stack other than there's a TrapFrame. + " movq %rsp, %rdi \n" + " call exit_trap \n" + " addq $" __STRINGIFY(TRAP_FRAME_SIZE) ", %rsp\n" // pop TrapFrame + ".globl interrupt_common_asm_exit \n" + "interrupt_common_asm_exit: \n" + " popq %rdi\n" + " popq %rsi\n" + " popq %rbp\n" + " addq $8, %rsp\n" // skip restoring rsp + " popq %rbx\n" + " popq %rdx\n" + " popq %rcx\n" + " popq %rax\n" + " popq %r8\n" + " popq %r9\n" + " popq %r10\n" + " popq %r11\n" + " popq %r12\n" + " popq %r13\n" + " popq %r14\n" + " popq %r15\n" + " addq $0x8, %rsp\n" // skip exception_code, isr_number + " iretq\n" ); // clang-format on