|
| 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_excp15, _do_excp16, |
| 19 | + _do_excp17, _do_excp18, _do_excp19, _do_excp2, _do_excp20, _do_excp3, _do_excp30, _do_excp4, |
| 20 | + _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