arch trap
This commit is contained in:
parent
cbea3a19f4
commit
8edb4c2427
@ -1,4 +0,0 @@
|
||||
//! Architecture-agnostic CPU functions.
|
||||
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
pub use super::riscv::cpu::cpu_id;
|
@ -1,13 +0,0 @@
|
||||
//! Architecture-agnostic interrupt handling.
|
||||
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
pub use super::riscv::{
|
||||
asm::{
|
||||
intr_get as interrupts_enabled, intr_off as disable_interrupts,
|
||||
intr_on as enable_interrupts,
|
||||
},
|
||||
plic::{
|
||||
plic_claim as handle_interrupt, plic_complete as complete_interrupt, plicinit as init,
|
||||
plicinithart as inithart,
|
||||
},
|
||||
};
|
@ -1,19 +0,0 @@
|
||||
//! Architecture-agnostic memory management.
|
||||
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
pub use super::riscv::{
|
||||
asm::sfence_vma as flush_cached_pages,
|
||||
mem::{
|
||||
Pagetable, PagetableEntry, KERNEL_BASE, PAGE_SIZE, PHYSICAL_END, TRAMPOLINE, TRAPFRAME,
|
||||
PTE_V, PTE_R, PTE_W, PTE_X, PTE_U,
|
||||
VIRTUAL_MAX,
|
||||
},
|
||||
};
|
||||
|
||||
pub fn round_up_page(size: usize) -> usize {
|
||||
(size + PAGE_SIZE - 1) & !(PAGE_SIZE - 1)
|
||||
}
|
||||
|
||||
pub fn round_down_page(addr: usize) -> usize {
|
||||
addr & !(PAGE_SIZE - 1)
|
||||
}
|
@ -3,7 +3,52 @@ pub mod riscv;
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
pub use riscv::hardware;
|
||||
|
||||
pub mod cpu;
|
||||
pub mod interrupt;
|
||||
pub mod mem;
|
||||
pub mod power;
|
||||
pub mod trap;
|
||||
|
||||
pub mod cpu {
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
pub use super::riscv::cpu::cpu_id;
|
||||
}
|
||||
|
||||
pub mod interrupt {
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
pub use super::riscv::{
|
||||
asm::{
|
||||
intr_get as interrupts_enabled, intr_off as disable_interrupts,
|
||||
intr_on as enable_interrupts,
|
||||
},
|
||||
plic::{
|
||||
plic_claim as handle_interrupt, plic_complete as complete_interrupt, plicinit as init,
|
||||
plicinithart as inithart,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub mod mem {
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
pub use super::riscv::{
|
||||
asm::sfence_vma as flush_cached_pages,
|
||||
mem::{
|
||||
Pagetable, PagetableEntry, KERNEL_BASE, PAGE_SIZE, PHYSICAL_END, PTE_R, PTE_U, PTE_V,
|
||||
PTE_W, PTE_X, TRAMPOLINE, TRAPFRAME, VIRTUAL_MAX,
|
||||
},
|
||||
};
|
||||
|
||||
pub fn round_up_page(size: usize) -> usize {
|
||||
(size + PAGE_SIZE - 1) & !(PAGE_SIZE - 1)
|
||||
}
|
||||
|
||||
pub fn round_down_page(addr: usize) -> usize {
|
||||
addr & !(PAGE_SIZE - 1)
|
||||
}
|
||||
}
|
||||
|
||||
pub mod power {
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
pub use super::riscv::power::shutdown;
|
||||
}
|
||||
|
||||
pub mod clock {
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
pub use super::riscv::trap::CLOCK_TICKS;
|
||||
}
|
||||
|
@ -1,4 +0,0 @@
|
||||
//! Architecture-agnostic power handling.
|
||||
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
pub use super::riscv::power::shutdown;
|
@ -1,11 +1,12 @@
|
||||
pub mod asm;
|
||||
pub mod clint;
|
||||
pub mod cpu;
|
||||
pub mod mem;
|
||||
pub mod hardware;
|
||||
pub mod mem;
|
||||
pub mod plic;
|
||||
pub mod power;
|
||||
pub mod start;
|
||||
pub mod trap;
|
||||
|
||||
pub use mem::make_satp;
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
use super::{asm, mem::make_satp, SSTATUS_SPIE, SSTATUS_SPP};
|
||||
use crate::{
|
||||
arch::{
|
||||
self,
|
||||
mem::{PAGE_SIZE, TRAMPOLINE},
|
||||
hardware::{UART0_IRQ, VIRTIO0_IRQ},
|
||||
riscv::{asm, SSTATUS_SPP, SSTATUS_SPIE, mem::make_satp},
|
||||
interrupt,
|
||||
mem::{PAGE_SIZE, TRAMPOLINE},
|
||||
},
|
||||
println,
|
||||
proc::{
|
||||
@ -54,7 +54,7 @@ pub unsafe fn devintr() -> i32 {
|
||||
// This is a supervisor external interrupt, via PLIC.
|
||||
|
||||
// IRQ indicates which device interrupted.
|
||||
let irq = arch::interrupt::handle_interrupt();
|
||||
let irq = interrupt::handle_interrupt();
|
||||
|
||||
if irq == UART0_IRQ {
|
||||
crate::console::uart::UART0.interrupt();
|
||||
@ -68,7 +68,7 @@ pub unsafe fn devintr() -> i32 {
|
||||
// interrupt at a time; tell the PLIC the device is
|
||||
// now allowed to interrupt again.
|
||||
if irq > 0 {
|
||||
arch::interrupt::complete_interrupt(irq);
|
||||
interrupt::complete_interrupt(irq);
|
||||
}
|
||||
|
||||
1
|
||||
@ -90,46 +90,6 @@ pub unsafe fn devintr() -> i32 {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct InterruptBlocker;
|
||||
impl InterruptBlocker {
|
||||
pub fn new() -> InterruptBlocker {
|
||||
unsafe {
|
||||
let interrupts_before = arch::interrupt::interrupts_enabled();
|
||||
let cpu = Cpu::current();
|
||||
|
||||
arch::interrupt::disable_interrupts();
|
||||
|
||||
if cpu.interrupt_disable_layers == 0 {
|
||||
cpu.previous_interrupts_enabled = interrupts_before;
|
||||
}
|
||||
cpu.interrupt_disable_layers += 1;
|
||||
// crate::sync::spinlock::push_off();
|
||||
}
|
||||
InterruptBlocker
|
||||
}
|
||||
}
|
||||
impl core::ops::Drop for InterruptBlocker {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
let cpu = Cpu::current();
|
||||
|
||||
if arch::interrupt::interrupts_enabled() == 1 || cpu.interrupt_disable_layers < 1 {
|
||||
// panic!("pop_off mismatched");
|
||||
return;
|
||||
}
|
||||
|
||||
cpu.interrupt_disable_layers -= 1;
|
||||
|
||||
if cpu.interrupt_disable_layers == 0 && cpu.previous_interrupts_enabled == 1 {
|
||||
arch::interrupt::enable_interrupts();
|
||||
}
|
||||
// crate::sync::spinlock::pop_off();
|
||||
}
|
||||
}
|
||||
}
|
||||
impl !Send for InterruptBlocker {}
|
||||
|
||||
/// Return to user space
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn usertrapret() {
|
||||
@ -138,7 +98,7 @@ pub unsafe extern "C" fn usertrapret() {
|
||||
// We're about to switch the destination of traps from
|
||||
// kerneltrap() to usertrap(), so turn off interrupts until
|
||||
// we're back in user space, where usertrap() is correct.
|
||||
arch::interrupt::disable_interrupts();
|
||||
interrupt::disable_interrupts();
|
||||
|
||||
// Send syscalls, interrupts, and exceptions to uservec in trampoline.S
|
||||
let trampoline_uservec =
|
||||
@ -193,13 +153,18 @@ pub unsafe extern "C" fn kerneltrap() {
|
||||
|
||||
if sstatus & SSTATUS_SPP == 0 {
|
||||
panic!("kerneltrap: not from supervisor mode");
|
||||
} else if arch::interrupt::interrupts_enabled() != 0 {
|
||||
} else if interrupt::interrupts_enabled() != 0 {
|
||||
panic!("kerneltrap: interrupts enabled");
|
||||
}
|
||||
|
||||
let which_dev = devintr();
|
||||
if which_dev == 0 {
|
||||
println!("scause {}\nsepc={} stval={}", scause, asm::r_sepc(), asm::r_stval());
|
||||
println!(
|
||||
"scause {}\nsepc={} stval={}",
|
||||
scause,
|
||||
asm::r_sepc(),
|
||||
asm::r_stval()
|
||||
);
|
||||
panic!("kerneltrap");
|
||||
} else if which_dev == 2
|
||||
&& Process::current().is_some()
|
||||
@ -246,7 +211,7 @@ pub unsafe extern "C" fn usertrap() {
|
||||
|
||||
// An interrupt will change sepc, scause, and sstatus,
|
||||
// so enable only now that we're done with those registers.
|
||||
arch::interrupt::enable_interrupts();
|
||||
interrupt::enable_interrupts();
|
||||
|
||||
syscall();
|
||||
}
|
||||
@ -274,35 +239,3 @@ pub unsafe extern "C" fn usertrap() {
|
||||
|
||||
usertrapret();
|
||||
}
|
||||
|
||||
// push_intr_off/pop_intr_off are like intr_off()/intr_on() except that they are matched:
|
||||
// it takes two pop_intr_off()s to undo two push_intr_off()s. Also, if interrupts
|
||||
// are initially off, then push_intr_off, pop_intr_off leaves them off.
|
||||
|
||||
pub unsafe fn push_intr_off() {
|
||||
let old = arch::interrupt::interrupts_enabled();
|
||||
let cpu = Cpu::current();
|
||||
|
||||
arch::interrupt::disable_interrupts();
|
||||
if cpu.interrupt_disable_layers == 0 {
|
||||
cpu.previous_interrupts_enabled = old;
|
||||
}
|
||||
cpu.interrupt_disable_layers += 1;
|
||||
}
|
||||
pub unsafe fn pop_intr_off() {
|
||||
let cpu = Cpu::current();
|
||||
|
||||
if arch::interrupt::interrupts_enabled() == 1 {
|
||||
// crate::panic_byte(b'0');
|
||||
panic!("pop_intr_off - interruptible");
|
||||
} else if cpu.interrupt_disable_layers < 1 {
|
||||
// crate::panic_byte(b'1');
|
||||
panic!("pop_intr_off");
|
||||
}
|
||||
|
||||
cpu.interrupt_disable_layers -= 1;
|
||||
|
||||
if cpu.interrupt_disable_layers == 0 && cpu.previous_interrupts_enabled == 1 {
|
||||
arch::interrupt::enable_interrupts();
|
||||
}
|
||||
}
|
75
kernel/rustkernel/src/arch/trap.rs
Normal file
75
kernel/rustkernel/src/arch/trap.rs
Normal file
@ -0,0 +1,75 @@
|
||||
//! Architecture-agnostic trap handling.
|
||||
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
pub use super::riscv::trap::trapinithart as inithart;
|
||||
|
||||
use super::interrupt;
|
||||
use crate::proc::cpu::Cpu;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct InterruptBlocker;
|
||||
impl InterruptBlocker {
|
||||
pub fn new() -> InterruptBlocker {
|
||||
unsafe {
|
||||
let interrupts_before = interrupt::interrupts_enabled();
|
||||
let cpu = Cpu::current();
|
||||
|
||||
interrupt::disable_interrupts();
|
||||
|
||||
if cpu.interrupt_disable_layers == 0 {
|
||||
cpu.previous_interrupts_enabled = interrupts_before;
|
||||
}
|
||||
cpu.interrupt_disable_layers += 1;
|
||||
// crate::sync::spinlock::push_off();
|
||||
}
|
||||
InterruptBlocker
|
||||
}
|
||||
}
|
||||
impl core::ops::Drop for InterruptBlocker {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
let cpu = Cpu::current();
|
||||
|
||||
if interrupt::interrupts_enabled() == 1 || cpu.interrupt_disable_layers < 1 {
|
||||
// panic!("pop_off mismatched");
|
||||
return;
|
||||
}
|
||||
|
||||
cpu.interrupt_disable_layers -= 1;
|
||||
|
||||
if cpu.interrupt_disable_layers == 0 && cpu.previous_interrupts_enabled == 1 {
|
||||
interrupt::enable_interrupts();
|
||||
}
|
||||
// crate::sync::spinlock::pop_off();
|
||||
}
|
||||
}
|
||||
}
|
||||
impl !Send for InterruptBlocker {}
|
||||
|
||||
pub unsafe fn push_intr_off() {
|
||||
let old = interrupt::interrupts_enabled();
|
||||
let cpu = Cpu::current();
|
||||
|
||||
interrupt::disable_interrupts();
|
||||
if cpu.interrupt_disable_layers == 0 {
|
||||
cpu.previous_interrupts_enabled = old;
|
||||
}
|
||||
cpu.interrupt_disable_layers += 1;
|
||||
}
|
||||
pub unsafe fn pop_intr_off() {
|
||||
let cpu = Cpu::current();
|
||||
|
||||
if interrupt::interrupts_enabled() == 1 {
|
||||
// crate::panic_byte(b'0');
|
||||
panic!("pop_intr_off - interruptible");
|
||||
} else if cpu.interrupt_disable_layers < 1 {
|
||||
// crate::panic_byte(b'1');
|
||||
panic!("pop_intr_off");
|
||||
}
|
||||
|
||||
cpu.interrupt_disable_layers -= 1;
|
||||
|
||||
if cpu.interrupt_disable_layers == 0 && cpu.previous_interrupts_enabled == 1 {
|
||||
interrupt::enable_interrupts();
|
||||
}
|
||||
}
|
@ -2,8 +2,8 @@
|
||||
#![allow(non_upper_case_globals)]
|
||||
|
||||
use crate::{
|
||||
console::consoleintr, proc::scheduler::wakeup, queue::Queue, sync::mutex::Mutex,
|
||||
trap::InterruptBlocker,
|
||||
arch::trap::InterruptBlocker, console::consoleintr, proc::scheduler::wakeup, queue::Queue,
|
||||
sync::mutex::Mutex,
|
||||
};
|
||||
use core::ptr::addr_of;
|
||||
|
||||
|
@ -18,7 +18,6 @@ mod queue;
|
||||
mod string;
|
||||
mod sync;
|
||||
mod syscall;
|
||||
mod trap;
|
||||
|
||||
use crate::{proc::cpu::Cpu, sync::mutex::Mutex};
|
||||
use core::ffi::{c_char, CStr};
|
||||
@ -63,7 +62,7 @@ pub unsafe fn main() -> ! {
|
||||
mem::virtual_memory::kvminit();
|
||||
mem::virtual_memory::kvminithart();
|
||||
proc::process::procinit();
|
||||
trap::trapinithart();
|
||||
arch::trap::inithart();
|
||||
arch::interrupt::init();
|
||||
arch::interrupt::inithart();
|
||||
io::bio::binit();
|
||||
@ -77,7 +76,7 @@ pub unsafe fn main() -> ! {
|
||||
core::hint::spin_loop();
|
||||
}
|
||||
mem::virtual_memory::kvminithart();
|
||||
trap::trapinithart();
|
||||
arch::trap::inithart();
|
||||
arch::interrupt::inithart();
|
||||
}
|
||||
|
||||
|
@ -4,14 +4,9 @@ use crate::{
|
||||
hardware::{UART0, VIRTIO0},
|
||||
mem::{
|
||||
round_down_page, round_up_page, Pagetable, PagetableEntry, KERNEL_BASE, PAGE_SIZE,
|
||||
PHYSICAL_END, TRAMPOLINE, VIRTUAL_MAX, PTE_R, PTE_U, PTE_V, PTE_W, PTE_X,
|
||||
},
|
||||
riscv::{
|
||||
asm, make_satp,
|
||||
plic::PLIC,
|
||||
power::QEMU_POWER,
|
||||
mem::pte2pa,
|
||||
PHYSICAL_END, PTE_R, PTE_U, PTE_V, PTE_W, PTE_X, TRAMPOLINE, VIRTUAL_MAX,
|
||||
},
|
||||
riscv::{asm, make_satp, mem::pte2pa, plic::PLIC, power::QEMU_POWER},
|
||||
},
|
||||
mem::{
|
||||
kalloc::{kalloc, kfree},
|
||||
|
@ -8,8 +8,8 @@ use super::{
|
||||
};
|
||||
use crate::{
|
||||
arch::{
|
||||
mem::{Pagetable, PAGE_SIZE, TRAMPOLINE, TRAPFRAME,
|
||||
PTE_R, PTE_W, PTE_X},
|
||||
mem::{Pagetable, PAGE_SIZE, PTE_R, PTE_W, PTE_X, TRAMPOLINE, TRAPFRAME},
|
||||
trap::InterruptBlocker,
|
||||
},
|
||||
fs::{
|
||||
file::{fileclose, filedup, File, Inode},
|
||||
@ -135,7 +135,7 @@ impl Process {
|
||||
}
|
||||
}
|
||||
pub fn current() -> Option<&'static mut Process> {
|
||||
let _ = crate::trap::InterruptBlocker::new();
|
||||
let _ = InterruptBlocker::new();
|
||||
let p = Cpu::current().proc;
|
||||
if p.is_null() {
|
||||
None
|
||||
|
@ -30,7 +30,7 @@ impl Lock {
|
||||
|
||||
match lock_strategy {
|
||||
LockStrategy::Spin => {
|
||||
crate::trap::push_intr_off();
|
||||
crate::arch::trap::push_intr_off();
|
||||
|
||||
while self.locked.swap(true, Ordering::Acquire) {
|
||||
core::hint::spin_loop();
|
||||
@ -64,7 +64,7 @@ impl Lock {
|
||||
|
||||
match lock_strategy {
|
||||
LockStrategy::Spin => {
|
||||
crate::trap::pop_intr_off();
|
||||
crate::arch::trap::pop_intr_off();
|
||||
}
|
||||
LockStrategy::Sleep => {
|
||||
wakeup(addr_of!(*self).cast_mut().cast());
|
||||
|
@ -1,9 +1,9 @@
|
||||
use crate::{
|
||||
arch::trap::{pop_intr_off, push_intr_off},
|
||||
proc::{
|
||||
process::{Process, ProcessState},
|
||||
scheduler::sched,
|
||||
},
|
||||
trap::{pop_intr_off, push_intr_off},
|
||||
};
|
||||
use core::{
|
||||
ffi::c_char,
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
arch::power::shutdown,
|
||||
arch::{clock::CLOCK_TICKS, power::shutdown},
|
||||
fs::{
|
||||
self,
|
||||
file::{self, File},
|
||||
@ -10,7 +10,6 @@ use crate::{
|
||||
println,
|
||||
proc::process::Process,
|
||||
string::strlen,
|
||||
trap::CLOCK_TICKS,
|
||||
NOFILE,
|
||||
};
|
||||
use core::{
|
||||
|
Loading…
x
Reference in New Issue
Block a user