Skip to content

Commit 124f64b

Browse files
Merge branch 'master' into add-fpu-support
2 parents 49b5588 + 5c447b8 commit 124f64b

File tree

4 files changed

+132
-62
lines changed

4 files changed

+132
-62
lines changed

.github/workflows/riscv-rt.yaml

+3-3
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ jobs:
3535
targets: ${{ matrix.target }}
3636
- name: Build (no features)
3737
run: RUSTFLAGS="-C link-arg=-Triscv-rt/examples/device.x" cargo build --package riscv-rt --target ${{ matrix.target }} --example ${{ matrix.example }}
38-
- name : Build example (s-mode)
38+
- name : Build (s-mode)
3939
run: RUSTFLAGS="-C link-arg=-Triscv-rt/examples/device.x" cargo build --package riscv-rt --target ${{ matrix.target }} --example ${{ matrix.example }} --features=s-mode
40-
- name : Build example (single-hart)
40+
- name : Build (single-hart)
4141
run: RUSTFLAGS="-C link-arg=-Triscv-rt/examples/device.x" cargo build --package riscv-rt --target ${{ matrix.target }} --example ${{ matrix.example }} --features=single-hart
42-
- name: Build example (all features)
42+
- name: Build (all features)
4343
run: RUSTFLAGS="-C link-arg=-Triscv-rt/examples/device.x" cargo build --package riscv-rt --target ${{ matrix.target }} --example ${{ matrix.example }} --all-features
4444

4545
# Job to check that all the builds succeeded

riscv-rt/CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1010
### Added
1111

1212
- Add FPU initialization
13+
- Static array for vectored-like handling of exceptions
1314
- New GitHub workflow for checking invalid labels in PRs
1415
- New GitHub workflow for checking modifications on CHANGELOG.md
1516
- New GitHub workflow for checking clippy lints in PRs
1617
- Optional cargo feature `single-hart` for single CPU targets
1718

1819
### Changed
1920

21+
- Removed U-mode interrupts to align with latest RISC-V specification
22+
- Changed `Vector` union. Now, it uses `Option<fn>`, which is more idiomatic in Rust
2023
- Removed riscv-target dependency for build
2124
- Upgrade rust-version to 1.60
2225
- Cargo workspace for riscv and riscv-rt

riscv-rt/link.x.in

+15
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,21 @@ PROVIDE(_max_hart_id = 0);
2828
PROVIDE(_hart_stack_size = 2K);
2929
PROVIDE(_heap_size = 0);
3030

31+
PROVIDE(InstructionMisaligned = ExceptionHandler);
32+
PROVIDE(InstructionFault = ExceptionHandler);
33+
PROVIDE(IllegalInstruction = ExceptionHandler);
34+
PROVIDE(Breakpoint = ExceptionHandler);
35+
PROVIDE(LoadMisaligned = ExceptionHandler);
36+
PROVIDE(LoadFault = ExceptionHandler);
37+
PROVIDE(StoreMisaligned = ExceptionHandler);
38+
PROVIDE(StoreFault = ExceptionHandler);;
39+
PROVIDE(UserEnvCall = ExceptionHandler);
40+
PROVIDE(SupervisorEnvCall = ExceptionHandler);
41+
PROVIDE(MachineEnvCall = ExceptionHandler);
42+
PROVIDE(InstructionPageFault = ExceptionHandler);
43+
PROVIDE(LoadPageFault = ExceptionHandler);
44+
PROVIDE(StorePageFault = ExceptionHandler);
45+
3146
PROVIDE(UserSoft = DefaultHandler);
3247
PROVIDE(SupervisorSoft = DefaultHandler);
3348
PROVIDE(MachineSoft = DefaultHandler);

riscv-rt/src/lib.rs

+111-59
Original file line numberDiff line numberDiff line change
@@ -245,9 +245,47 @@
245245
//!
246246
//! Default implementation of this function wakes hart 0 and busy-loops all the other harts.
247247
//!
248+
//!
249+
//! ### Core exception handlers
250+
//!
251+
//! This functions are called when corresponding exception occurs.
252+
//! You can define an exception handler with one of the following names:
253+
//! * `InstructionMisaligned`
254+
//! * `InstructionFault`
255+
//! * `IllegalInstruction`
256+
//! * `Breakpoint`
257+
//! * `LoadMisaligned`
258+
//! * `LoadFault`
259+
//! * `StoreMisaligned`
260+
//! * `StoreFault`
261+
//! * `UserEnvCall`
262+
//! * `SupervisorEnvCall`
263+
//! * `MachineEnvCall`
264+
//! * `InstructionPageFault`
265+
//! * `LoadPageFault`
266+
//! * `StorePageFault`
267+
//!
268+
//! For example:
269+
//! ``` no_run
270+
//! #[export_name = "MachineEnvCall"]
271+
//! fn custom_menv_call_handler(trap_frame: &riscv_rt::TrapFrame) {
272+
//! // ...
273+
//! }
274+
//! ```
275+
//! or
276+
//! ``` no_run
277+
//! #[no_mangle]
278+
//! fn MachineEnvCall(trap_frame: &riscv_rt::TrapFrame) -> ! {
279+
//! // ...
280+
//! }
281+
//! ```
282+
//!
283+
//! If exception handler is not explicitly defined, `ExceptionHandler` is called.
284+
//!
248285
//! ### `ExceptionHandler`
249286
//!
250-
//! This function is called when exception is occured. The exception reason can be decoded from the
287+
//! This function is called when exception without defined exception handler is occured.
288+
//! The exception reason can be decoded from the
251289
//! `mcause`/`scause` register.
252290
//!
253291
//! This function can be redefined in the following way:
@@ -581,15 +619,27 @@ pub unsafe extern "C" fn start_trap_rust(trap_frame: *const TrapFrame) {
581619
}
582620

583621
let cause = xcause::read();
622+
let code = cause.code();
584623

585624
if cause.is_exception() {
586-
ExceptionHandler(&*trap_frame)
587-
} else if cause.code() < __INTERRUPTS.len() {
588-
let h = &__INTERRUPTS[cause.code()];
589-
if h.reserved == 0 {
590-
DefaultHandler();
625+
let trap_frame = &*trap_frame;
626+
if code < __EXCEPTIONS.len() {
627+
let h = &__EXCEPTIONS[code];
628+
if let Some(handler) = h {
629+
handler(trap_frame);
630+
} else {
631+
ExceptionHandler(trap_frame);
632+
}
591633
} else {
592-
(h.handler)();
634+
ExceptionHandler(trap_frame);
635+
}
636+
ExceptionHandler(trap_frame)
637+
} else if code < __INTERRUPTS.len() {
638+
let h = &__INTERRUPTS[code];
639+
if let Some(handler) = h {
640+
handler();
641+
} else {
642+
DefaultHandler();
593643
}
594644
} else {
595645
DefaultHandler();
@@ -609,7 +659,7 @@ pub fn DefaultExceptionHandler(trap_frame: &TrapFrame) -> ! {
609659

610660
#[doc(hidden)]
611661
#[no_mangle]
612-
#[allow(unused_variables, non_snake_case)]
662+
#[allow(non_snake_case)]
613663
pub fn DefaultInterruptHandler() {
614664
loop {
615665
// Prevent this from turning into a UDF instruction
@@ -618,76 +668,78 @@ pub fn DefaultInterruptHandler() {
618668
}
619669
}
620670

621-
/* Interrupts */
622-
#[doc(hidden)]
623-
pub enum Interrupt {
624-
UserSoft,
625-
SupervisorSoft,
626-
MachineSoft,
627-
UserTimer,
628-
SupervisorTimer,
629-
MachineTimer,
630-
UserExternal,
631-
SupervisorExternal,
632-
MachineExternal,
671+
extern "C" {
672+
fn InstructionMisaligned(trap_frame: &TrapFrame);
673+
fn InstructionFault(trap_frame: &TrapFrame);
674+
fn IllegalInstruction(trap_frame: &TrapFrame);
675+
fn Breakpoint(trap_frame: &TrapFrame);
676+
fn LoadMisaligned(trap_frame: &TrapFrame);
677+
fn LoadFault(trap_frame: &TrapFrame);
678+
fn StoreMisaligned(trap_frame: &TrapFrame);
679+
fn StoreFault(trap_frame: &TrapFrame);
680+
fn UserEnvCall(trap_frame: &TrapFrame);
681+
fn SupervisorEnvCall(trap_frame: &TrapFrame);
682+
fn MachineEnvCall(trap_frame: &TrapFrame);
683+
fn InstructionPageFault(trap_frame: &TrapFrame);
684+
fn LoadPageFault(trap_frame: &TrapFrame);
685+
fn StorePageFault(trap_frame: &TrapFrame);
633686
}
634687

635-
pub use self::Interrupt as interrupt;
688+
#[doc(hidden)]
689+
#[no_mangle]
690+
pub static __EXCEPTIONS: [Option<unsafe extern "C" fn(&TrapFrame)>; 16] = [
691+
Some(InstructionMisaligned),
692+
Some(InstructionFault),
693+
Some(IllegalInstruction),
694+
Some(Breakpoint),
695+
Some(LoadMisaligned),
696+
Some(LoadFault),
697+
Some(StoreMisaligned),
698+
Some(StoreFault),
699+
Some(UserEnvCall),
700+
Some(SupervisorEnvCall),
701+
None,
702+
Some(MachineEnvCall),
703+
Some(InstructionPageFault),
704+
Some(LoadPageFault),
705+
None,
706+
Some(StorePageFault),
707+
];
636708

637709
extern "C" {
638-
fn UserSoft();
639710
fn SupervisorSoft();
640711
fn MachineSoft();
641-
fn UserTimer();
642712
fn SupervisorTimer();
643713
fn MachineTimer();
644-
fn UserExternal();
645714
fn SupervisorExternal();
646715
fn MachineExternal();
647716
}
648717

649-
#[doc(hidden)]
650-
pub union Vector {
651-
pub handler: unsafe extern "C" fn(),
652-
pub reserved: usize,
653-
}
654-
655718
#[doc(hidden)]
656719
#[no_mangle]
657-
pub static __INTERRUPTS: [Vector; 12] = [
658-
Vector { handler: UserSoft },
659-
Vector {
660-
handler: SupervisorSoft,
661-
},
662-
Vector { reserved: 0 },
663-
Vector {
664-
handler: MachineSoft,
665-
},
666-
Vector { handler: UserTimer },
667-
Vector {
668-
handler: SupervisorTimer,
669-
},
670-
Vector { reserved: 0 },
671-
Vector {
672-
handler: MachineTimer,
673-
},
674-
Vector {
675-
handler: UserExternal,
676-
},
677-
Vector {
678-
handler: SupervisorExternal,
679-
},
680-
Vector { reserved: 0 },
681-
Vector {
682-
handler: MachineExternal,
683-
},
720+
pub static __INTERRUPTS: [Option<unsafe extern "C" fn()>; 12] = [
721+
None,
722+
Some(SupervisorSoft),
723+
None,
724+
Some(MachineSoft),
725+
None,
726+
Some(SupervisorTimer),
727+
None,
728+
Some(MachineTimer),
729+
None,
730+
Some(SupervisorExternal),
731+
None,
732+
Some(MachineExternal),
684733
];
685734

735+
/// Default implementation of `_pre_init` does nothing.
736+
/// Users can override this function with the [`#[pre_init]`] macro.
686737
#[doc(hidden)]
687738
#[no_mangle]
688739
#[rustfmt::skip]
689-
pub unsafe extern "Rust" fn default_pre_init() {}
740+
pub extern "Rust" fn default_pre_init() {}
690741

742+
/// Default implementation of `_mp_hook` wakes hart 0 and busy-loops all the other harts.
691743
#[doc(hidden)]
692744
#[no_mangle]
693745
#[rustfmt::skip]
@@ -701,7 +753,7 @@ pub extern "Rust" fn default_mp_hook(hartid: usize) -> bool {
701753
}
702754
}
703755

704-
/// Default implementation of `_setup_interrupts` that sets `mtvec`/`stvec` to a trap handler address.
756+
/// Default implementation of `_setup_interrupts` sets `mtvec`/`stvec` to the address of `_start_trap`.
705757
#[doc(hidden)]
706758
#[no_mangle]
707759
#[rustfmt::skip]

0 commit comments

Comments
 (0)