Skip to content

Commit

Permalink
Add vector table
Browse files Browse the repository at this point in the history
  • Loading branch information
romancardenas committed Jun 27, 2024
1 parent db6c2f9 commit fc4f314
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 77 deletions.
40 changes: 40 additions & 0 deletions riscv-pac/macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,42 @@ impl PacEnumItem {
vectors
}

fn vector_table(&self) -> TokenStream2 {
let mut asm = String::from(
r#"
core::arch::global_asm!("
.section .trap, \"ax\"
.global _vector_table
.type _vector_table, @function
.option push
.balign 0x4 // TODO check if this is the correct alignment
.option norelax
.option norvc
_vector_table:
j _start_trap // Interrupt 0 is used for exceptions
"#,
);

for i in 1..=self.max_number {
if let Some(ident) = self.numbers.get(&i) {
asm.push_str(&format!(" j _start_{ident}_trap\n"));
} else {
asm.push_str(&format!(
" j _start_DefaultHandler_trap // Interrupt {i} is reserved\n"
));
}
}

asm.push_str(
r#" .option pop"
);"#,
);

TokenStream2::from_str(&asm).unwrap()
}

/// Returns a vector of token streams representing the trait implementations for
/// the enum. If the trait is an interrupt trait, the implementation also includes
/// the interrupt handler functions and the interrupt array.
Expand Down Expand Up @@ -269,6 +305,10 @@ impl PacEnumItem {
}
}
});

if let InterruptType::Core = interrupt_type {
res.push(self.vector_table());
}
}

res
Expand Down
32 changes: 0 additions & 32 deletions riscv-rt/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,38 +287,6 @@ riscv_rt_macros::vectored_interrupt_trap_riscv32!();
#[cfg(all(riscv64, feature = "v-trap"))]
riscv_rt_macros::vectored_interrupt_trap_riscv64!();

#[cfg(feature = "v-trap")]
cfg_global_asm!(
// Set the vector mode to vectored.
r#".section .trap, "ax"
.weak _vector_table
.type _vector_table, @function
.option push
.balign 0x4 // TODO check if this is the correct alignment
.option norelax
.option norvc
_vector_table:
j _start_trap // Interrupt 0 is used for exceptions
j _start_SupervisorSoft_trap
j _start_DefaultHandler_trap // Interrupt 2 is reserved
j _start_MachineSoft_trap
j _start_DefaultHandler_trap // Interrupt 4 is reserved
j _start_SupervisorTimer_trap
j _start_DefaultHandler_trap // Interrupt 6 is reserved
j _start_MachineTimer_trap
j _start_DefaultHandler_trap // Interrupt 8 is reserved
j _start_SupervisorExternal_trap
j _start_DefaultHandler_trap // Interrupt 10 is reserved
j _start_MachineExternal_trap
// default table does not include the remaining interrupts.
// Targets with extra interrupts should override this table.
.option pop"#,
);

#[rustfmt::skip]
global_asm!(
".section .text.abort
Expand Down
68 changes: 68 additions & 0 deletions riscv-rt/src/interrupt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
extern "C" {
fn SupervisorSoft();
fn MachineSoft();
fn SupervisorTimer();
fn MachineTimer();
fn SupervisorExternal();
fn MachineExternal();
fn DefaultHandler();
}

#[doc(hidden)]
#[no_mangle]
pub static __CORE_INTERRUPTS: [Option<unsafe extern "C" fn()>; 12] = [
None,
Some(SupervisorSoft),
None,
Some(MachineSoft),
None,
Some(SupervisorTimer),
None,
Some(MachineTimer),
None,
Some(SupervisorExternal),
None,
Some(MachineExternal),
];

#[export_name = "_dispatch_core_interrupt"]
unsafe extern "C" fn dispatch_core_interrupt(code: usize) {
if code < __CORE_INTERRUPTS.len() {
let h = &__CORE_INTERRUPTS[code];
if let Some(handler) = h {
handler();
} else {
DefaultHandler();
}
} else {
DefaultHandler();
}
}

#[cfg(all(riscv, feature = "v-trap"))]
core::arch::global_asm!(
r#" .section .trap, "ax"
.weak _vector_table
.type _vector_table, @function
.option push
.balign 0x4 // TODO check if this is the correct alignment
.option norelax
.option norvc
_vector_table:
j _start_trap // Interrupt 0 is used for exceptions
j _start_SupervisorSoft_trap
j _start_DefaultHandler_trap // Interrupt 2 is reserved
j _start_MachineSoft_trap
j _start_DefaultHandler_trap // Interrupt 4 is reserved
j _start_SupervisorTimer_trap
j _start_DefaultHandler_trap // Interrupt 6 is reserved
j _start_MachineTimer_trap
j _start_DefaultHandler_trap // Interrupt 8 is reserved
j _start_SupervisorExternal_trap
j _start_DefaultHandler_trap // Interrupt 10 is reserved
j _start_MachineExternal_trap
.option pop"#
);
46 changes: 2 additions & 44 deletions riscv-rt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,8 @@
#[cfg(riscv)]
mod asm;

mod interrupt;

#[cfg(feature = "s-mode")]
use riscv::register::scause as xcause;

Expand Down Expand Up @@ -578,47 +580,3 @@ pub static __EXCEPTIONS: [Option<unsafe extern "C" fn(&TrapFrame)>; 16] = [
None,
Some(StorePageFault),
];

#[export_name = "_dispatch_core_interrupt"]
unsafe extern "C" fn dispatch_core_interrupt(code: usize) {
extern "C" {
fn DefaultHandler();
}

if code < __INTERRUPTS.len() {
let h = &__INTERRUPTS[code];
if let Some(handler) = h {
handler();
} else {
DefaultHandler();
}
} else {
DefaultHandler();
}
}

extern "C" {
fn SupervisorSoft();
fn MachineSoft();
fn SupervisorTimer();
fn MachineTimer();
fn SupervisorExternal();
fn MachineExternal();
}

#[doc(hidden)]
#[no_mangle]
pub static __INTERRUPTS: [Option<unsafe extern "C" fn()>; 12] = [
None,
Some(SupervisorSoft),
None,
Some(MachineSoft),
None,
Some(SupervisorTimer),
None,
Some(MachineTimer),
None,
Some(SupervisorExternal),
None,
Some(MachineExternal),
];
2 changes: 1 addition & 1 deletion riscv/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ This project is developed and maintained by the [RISC-V team][team].

## Minimum Supported Rust Version (MSRV)

This crate is guaranteed to compile on stable Rust 1.60 and up. It *might*
This crate is guaranteed to compile on stable Rust 1.61 and up. It *might*
compile with older versions but that may change in any new patch release.

## License
Expand Down

0 comments on commit fc4f314

Please sign in to comment.