mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-09 05:16:47 +00:00
Rewrite trap/idt.rs
This commit is contained in:
parent
8c30b4b942
commit
c9a7d501b2
@ -1,47 +1,66 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0 OR MIT
|
|
||||||
//
|
|
||||||
// The original source code is from [trapframe-rs](https://github.com/rcore-os/trapframe-rs),
|
|
||||||
// which is released under the following license:
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
//
|
|
||||||
// Copyright (c) 2020 - 2024 Runji Wang
|
|
||||||
//
|
|
||||||
// We make the following new changes:
|
|
||||||
// * Include `trap.S` in this file and remove unused function `sidt`.
|
|
||||||
// * Link `VECTORS` to `trap_handler_table` defined in `trap.S`.
|
|
||||||
//
|
|
||||||
// These changes are released under the following license:
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
//! Configure Interrupt Descriptor Table (GDT).
|
//! Configure the Interrupt Descriptor Table (IDT).
|
||||||
|
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use core::arch::global_asm;
|
use core::arch::global_asm;
|
||||||
|
|
||||||
|
use spin::Once;
|
||||||
use x86_64::{
|
use x86_64::{
|
||||||
structures::idt::{Entry, HandlerFunc, InterruptDescriptorTable},
|
instructions::tables::lidt,
|
||||||
PrivilegeLevel,
|
structures::{idt::Entry, DescriptorTablePointer},
|
||||||
|
PrivilegeLevel, VirtAddr,
|
||||||
};
|
};
|
||||||
|
|
||||||
global_asm!(include_str!("trap.S"));
|
global_asm!(include_str!("trap.S"));
|
||||||
|
|
||||||
pub fn init() {
|
const NUM_INTERRUPTS: usize = 256;
|
||||||
extern "C" {
|
|
||||||
#[link_name = "trap_handler_table"]
|
|
||||||
static VECTORS: [HandlerFunc; 256];
|
|
||||||
}
|
|
||||||
|
|
||||||
let idt = Box::leak(Box::new(InterruptDescriptorTable::new()));
|
extern "C" {
|
||||||
let entries: &'static mut [Entry<HandlerFunc>; 256] =
|
#[link_name = "trap_handler_table"]
|
||||||
unsafe { core::mem::transmute_copy(&idt) };
|
static VECTORS: [usize; NUM_INTERRUPTS];
|
||||||
for i in 0..256 {
|
}
|
||||||
let opt = unsafe { entries[i].set_handler_fn(VECTORS[i]) };
|
|
||||||
// Enable user space `int3` and `into`.
|
static GLOBAL_IDT: Once<&'static [Entry<()>]> = Once::new();
|
||||||
if i == 3 || i == 4 {
|
|
||||||
|
/// Initializes and loads the IDT.
|
||||||
|
///
|
||||||
|
/// The caller should only call this method once in the boot context for each available processor.
|
||||||
|
/// This is not a safety requirement, however, because calling this method again will do nothing
|
||||||
|
/// more than load the same IDT.
|
||||||
|
pub(super) fn init() {
|
||||||
|
let idt = *GLOBAL_IDT.call_once(|| {
|
||||||
|
let idt = Box::leak(Box::new([const { Entry::missing() }; NUM_INTERRUPTS]));
|
||||||
|
|
||||||
|
// SAFETY: The vector array is properly initialized, lives for `'static`, and will never be
|
||||||
|
// mutated. So it's always fine to create an immutable borrow to it.
|
||||||
|
let vectors = unsafe { &VECTORS };
|
||||||
|
|
||||||
|
// Initialize the IDT entries.
|
||||||
|
for (intr_no, &handler) in vectors.iter().enumerate() {
|
||||||
|
let handler = VirtAddr::new(handler as u64);
|
||||||
|
|
||||||
|
let entry = &mut idt[intr_no];
|
||||||
|
// SAFETY: The handler defined in `trap.S` has a correct signature to handle the
|
||||||
|
// corresponding exception or interrupt.
|
||||||
|
let opt = unsafe { entry.set_handler_addr(handler) };
|
||||||
|
|
||||||
|
// Enable `int3` and `into` in the userspace.
|
||||||
|
if intr_no == 3 || intr_no == 4 {
|
||||||
opt.set_privilege_level(PrivilegeLevel::Ring3);
|
opt.set_privilege_level(PrivilegeLevel::Ring3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
idt.load();
|
|
||||||
|
idt
|
||||||
|
});
|
||||||
|
|
||||||
|
let idtr = DescriptorTablePointer {
|
||||||
|
limit: (core::mem::size_of_val(idt) - 1) as u16,
|
||||||
|
base: VirtAddr::new(idt.as_ptr().addr() as u64),
|
||||||
|
};
|
||||||
|
// SAFETY: The IDT is valid to load because:
|
||||||
|
// - It lives for `'static`.
|
||||||
|
// - It contains correct entries at correct indexes: all handlers are defined in `trap.S` with
|
||||||
|
// correct handler signatures.
|
||||||
|
unsafe { lidt(&idtr) };
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@ pub struct TrapFrame {
|
|||||||
/// This function will:
|
/// This function will:
|
||||||
/// - Switch to a new, CPU-local [GDT].
|
/// - Switch to a new, CPU-local [GDT].
|
||||||
/// - Switch to a new, CPU-local [TSS].
|
/// - Switch to a new, CPU-local [TSS].
|
||||||
/// - Switch to a new, CPU-local [IDT].
|
/// - Switch to a new, global [IDT].
|
||||||
/// - Enable the [`syscall`] instruction.
|
/// - Enable the [`syscall`] instruction.
|
||||||
///
|
///
|
||||||
/// [GDT]: https://wiki.osdev.org/GDT
|
/// [GDT]: https://wiki.osdev.org/GDT
|
||||||
|
Loading…
x
Reference in New Issue
Block a user