| 
 | 1 | +/*  | 
 | 2 | +Copyright 2024 The Hyperlight Authors.  | 
 | 3 | +
  | 
 | 4 | +Licensed under the Apache License, Version 2.0 (the "License");  | 
 | 5 | +you may not use this file except in compliance with the License.  | 
 | 6 | +You may obtain a copy of the License at  | 
 | 7 | +
  | 
 | 8 | +    http://www.apache.org/licenses/LICENSE-2.0  | 
 | 9 | +
  | 
 | 10 | +Unless required by applicable law or agreed to in writing, software  | 
 | 11 | +distributed under the License is distributed on an "AS IS" BASIS,  | 
 | 12 | +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  | 
 | 13 | +See the License for the specific language governing permissions and  | 
 | 14 | +limitations under the License.  | 
 | 15 | +*/  | 
 | 16 | + | 
 | 17 | +use crate::interrupt_entry::{  | 
 | 18 | +    _do_excp0, _do_excp1, _do_excp10, _do_excp11, _do_excp12, _do_excp13, _do_excp14, _do_excp15,  | 
 | 19 | +    _do_excp16, _do_excp17, _do_excp18, _do_excp19, _do_excp2, _do_excp20, _do_excp3, _do_excp30,  | 
 | 20 | +    _do_excp4, _do_excp5, _do_excp6, _do_excp7, _do_excp8, _do_excp9,  | 
 | 21 | +};  | 
 | 22 | + | 
 | 23 | +// An entry in the Interrupt Descriptor Table (IDT)  | 
 | 24 | +// For reference, see page 7-20 Vol. 3A of Intel 64 and IA-32  | 
 | 25 | +// Architectures Software Developer's Manual, figure 7-8  | 
 | 26 | +// (i.e., https://i.imgur.com/N4rEjHj.png).  | 
 | 27 | +// From the bottom, we have:  | 
 | 28 | +// - offset 15..0 = offset_low  | 
 | 29 | +// - segment selector 31..16 = selector  | 
 | 30 | +// - 000 0 0 Interrupt Stack Table 7..0 = interrupt_stack_table_offset  | 
 | 31 | +// - p dpl 0 type 15..8 = type_attr  | 
 | 32 | +// - offset 31..16 = offset_mid  | 
 | 33 | +// - offset 63..32 = offset_high  | 
 | 34 | +// - reserved 31..0 = zero  | 
 | 35 | +#[repr(C, align(16))]  | 
 | 36 | +pub(crate) struct IdtEntry {  | 
 | 37 | +    offset_low: u16,                  // Lower 16 bits of handler address  | 
 | 38 | +    selector: u16,                    // code segment selector in GDT  | 
 | 39 | +    interrupt_stack_table_offset: u8, // Interrupt Stack Table offset  | 
 | 40 | +    type_attr: u8,                    // Gate type and flags  | 
 | 41 | +    offset_mid: u16,                  // Middle 16 bits of handler address  | 
 | 42 | +    offset_high: u32,                 // High 32 bits of handler address  | 
 | 43 | +    zero: u32,                        // Reserved (always 0)  | 
 | 44 | +}  | 
 | 45 | + | 
 | 46 | +impl IdtEntry {  | 
 | 47 | +    fn new(handler: u64) -> Self {  | 
 | 48 | +        Self {  | 
 | 49 | +            offset_low: (handler & 0xFFFF) as u16,  | 
 | 50 | +            selector: 0x08,                  // Kernel Code Segment  | 
 | 51 | +            interrupt_stack_table_offset: 0, // No interrupt stack table used  | 
 | 52 | +            type_attr: 0x8E,  | 
 | 53 | +            // 0x8E = 10001110b  | 
 | 54 | +            // 1 00 0 1110  | 
 | 55 | +            // 1 = Present  | 
 | 56 | +            // 00 = Descriptor Privilege Level (0)  | 
 | 57 | +            // 0 = Storage Segment (0)  | 
 | 58 | +            // 1110 = Gate Type (0b1110 = 14 = 0xE)  | 
 | 59 | +            // 0xE means it's an interrupt gate  | 
 | 60 | +            offset_mid: ((handler >> 16) & 0xFFFF) as u16,  | 
 | 61 | +            offset_high: ((handler >> 32) & 0xFFFFFFFF) as u32,  | 
 | 62 | +            zero: 0,  | 
 | 63 | +        }  | 
 | 64 | +    }  | 
 | 65 | +}  | 
 | 66 | + | 
 | 67 | +// The IDT is an array of 256 IDT entries  | 
 | 68 | +// (for reference, see page 7-9 Vol. 3A of Intel 64 and IA-32  | 
 | 69 | +// Architectures Software Developer's Manual).  | 
 | 70 | +pub(crate) static mut IDT: [IdtEntry; 256] = unsafe { core::mem::zeroed() };  | 
 | 71 | + | 
 | 72 | +pub(crate) fn init_idt() {  | 
 | 73 | +    set_idt_entry(0, _do_excp0); // Divide by zero  | 
 | 74 | +    set_idt_entry(1, _do_excp1); // Debug  | 
 | 75 | +    set_idt_entry(2, _do_excp2); // Non-maskable interrupt  | 
 | 76 | +    set_idt_entry(3, _do_excp3); // Breakpoint  | 
 | 77 | +    set_idt_entry(4, _do_excp4); // Overflow  | 
 | 78 | +    set_idt_entry(5, _do_excp5); // Bound Range Exceeded  | 
 | 79 | +    set_idt_entry(6, _do_excp6); // Invalid Opcode  | 
 | 80 | +    set_idt_entry(7, _do_excp7); // Device Not Available  | 
 | 81 | +    set_idt_entry(8, _do_excp8); // Double Fault  | 
 | 82 | +    set_idt_entry(9, _do_excp9); // Coprocessor Segment Overrun  | 
 | 83 | +    set_idt_entry(10, _do_excp10); // Invalid TSS  | 
 | 84 | +    set_idt_entry(11, _do_excp11); // Segment Not Present  | 
 | 85 | +    set_idt_entry(12, _do_excp12); // Stack-Segment Fault  | 
 | 86 | +    set_idt_entry(13, _do_excp13); // General Protection Fault  | 
 | 87 | +    set_idt_entry(14, _do_excp14); // Page Fault  | 
 | 88 | +    set_idt_entry(15, _do_excp15); // Reserved  | 
 | 89 | +    set_idt_entry(16, _do_excp16); // x87 Floating-Point Exception  | 
 | 90 | +    set_idt_entry(17, _do_excp17); // Alignment Check  | 
 | 91 | +    set_idt_entry(18, _do_excp18); // Machine Check  | 
 | 92 | +    set_idt_entry(19, _do_excp19); // SIMD Floating-Point Exception  | 
 | 93 | +    set_idt_entry(20, _do_excp20); // Virtualization Exception  | 
 | 94 | +    set_idt_entry(30, _do_excp30); // Security Exception  | 
 | 95 | +}  | 
 | 96 | + | 
 | 97 | +fn set_idt_entry(index: usize, handler: unsafe extern "sysv64" fn()) {  | 
 | 98 | +    let handler_addr = handler as *const () as u64;  | 
 | 99 | +    unsafe {  | 
 | 100 | +        IDT[index] = IdtEntry::new(handler_addr);  | 
 | 101 | +    }  | 
 | 102 | +}  | 
0 commit comments