Skip to content

Commit c52e637

Browse files
committed
rustsbi-qemu: deref virtual address may fail
Handle possible failure of deref virtual address by machine trap detection Add `prv_mem` module for this purpose Signed-off-by: luojia65 <me@luojia.cc>
1 parent c04b443 commit c52e637

File tree

6 files changed

+319
-43
lines changed

6 files changed

+319
-43
lines changed

CHANGELOG.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres
6+
to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## Unreleased
9+
10+
### Added
11+
12+
- Handle possible failure of deref virtual address by machine trap detection
13+
14+
### Modified
15+
16+
## [0.1.0] - 2022-02-13
17+
18+
### Added
19+
20+
- Adapts to RustSBI version 0.2.0
21+
- Implement SBI non-retentive resume procedure
22+
- PMP updates, use stabilized core::arch::asm! macro, thanks to @wyfcyx
23+
- Fixes on usage of CLINT peripheral, thanks to @duskmoon314
24+
- Numerous fixes to HSM module implementation, more documents
25+
26+
[Unreleased]: https://github.com/rustsbi/rustsbi-qemu/compare/v0.1.0...HEAD
27+
28+
[0.1.0]: https://github.com/rustsbi/rustsbi-qemu/releases/tag/v0.1.0

Cargo.lock

Lines changed: 9 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rustsbi-qemu/src/execute.rs

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
use crate::feature;
2-
use crate::qemu_hsm::{pause, HsmCommand, QemuHsm};
3-
use crate::runtime::{MachineTrap, Runtime, SupervisorContext};
41
use core::{
52
ops::{Generator, GeneratorState},
63
pin::Pin,
74
};
8-
use riscv::register::{
9-
mie, mip,
10-
scause::{Exception, Trap},
11-
};
5+
6+
use riscv::register::{mcause, mie, mip, scause::{Exception, Trap}};
7+
8+
use crate::feature;
9+
use crate::prv_mem::{self, SupervisorPointer};
10+
use crate::qemu_hsm::{HsmCommand, pause, QemuHsm};
11+
use crate::runtime::{MachineTrap, Runtime, SupervisorContext};
1212

1313
pub fn execute_supervisor(supervisor_mepc: usize, hart_id: usize, a1: usize, hsm: QemuHsm) -> ! {
1414
let mut rt = Runtime::new_sbi_supervisor(supervisor_mepc, hart_id, a1);
@@ -40,8 +40,12 @@ pub fn execute_supervisor(supervisor_mepc: usize, hart_id: usize, a1: usize, hsm
4040
}
4141
GeneratorState::Yielded(MachineTrap::IllegalInstruction()) => {
4242
let ctx = rt.context_mut();
43-
// FIXME: get_vaddr_u32这个过程可能出错。
44-
let ins = unsafe { get_vaddr_u32(ctx.mepc) } as usize;
43+
let ptr: SupervisorPointer<usize> = SupervisorPointer::cast(ctx.mepc);
44+
let deref_ans = unsafe { prv_mem::try_read(ptr) };
45+
let ins = match deref_ans {
46+
Ok(ins) => ins,
47+
Err(e) => fail_cant_read_exception_address(ctx, e),
48+
};
4549
if !emulate_illegal_instruction(ctx, ins) {
4650
unsafe {
4751
if feature::should_transfer_trap(ctx) {
@@ -107,32 +111,24 @@ pub fn execute_supervisor(supervisor_mepc: usize, hart_id: usize, a1: usize, hsm
107111
}
108112

109113
#[inline]
110-
unsafe fn get_vaddr_u32(vaddr: usize) -> u32 {
111-
let mut ans: u32;
112-
core::arch::asm!("
113-
li {tmp}, (1 << 17)
114-
csrrs {tmp}, mstatus, {tmp}
115-
lwu {ans}, 0({vaddr})
116-
csrw mstatus, {tmp}
117-
",
118-
tmp = out(reg) _,
119-
vaddr = in(reg) vaddr,
120-
ans = lateout(reg) ans
121-
);
122-
ans
123-
}
124-
125114
fn emulate_illegal_instruction(ctx: &mut SupervisorContext, ins: usize) -> bool {
126115
if feature::emulate_rdtime(ctx, ins) {
127116
return true;
128117
}
129118
false
130119
}
131120

132-
// 真·非法指令异常,是M层出现的
121+
// Illegal instruction occurred in M level
133122
fn fail_illegal_instruction(ctx: &mut SupervisorContext, ins: usize) -> ! {
134123
#[cfg(target_pointer_width = "64")]
135124
panic!("invalid instruction from machine level, mepc: {:016x?}, instruction: {:016x?}, context: {:016x?}", ctx.mepc, ins, ctx);
136125
#[cfg(target_pointer_width = "32")]
137126
panic!("invalid instruction from machine level, mepc: {:08x?}, instruction: {:08x?}, context: {:08x?}", ctx.mepc, ins, ctx);
138127
}
128+
129+
fn fail_cant_read_exception_address(ctx: &mut SupervisorContext, cause: mcause::Exception) -> ! {
130+
#[cfg(target_pointer_width = "64")]
131+
panic!("can't read exception address, cause: {:?}, mepc: {:016x?}, context: {:016x?}", cause, ctx.mepc, ctx);
132+
#[cfg(target_pointer_width = "32")]
133+
panic!("can't read exception address, cause: {:?}, mepc: {:08x?}, context: {:08x?}", cause, ctx.mepc, ctx);
134+
}

rustsbi-qemu/src/feature/emulate_rdtime.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,16 @@ use crate::runtime::SupervisorContext;
33

44
#[inline]
55
pub fn emulate_rdtime(ctx: &mut SupervisorContext, ins: usize) -> bool {
6-
if ins & 0xFFFFF07F == 0xC0102073 {
6+
return if ins & 0xFFFFF07F == 0xC0102073 {
77
let rd = ((ins >> 7) & 0b1_1111) as u8;
88
let clint = clint::Clint::new(0x2000000 as *mut u8);
99
let time_usize = clint.get_mtime() as usize;
1010
set_register_xi(ctx, rd, time_usize);
1111
ctx.mepc = ctx.mepc.wrapping_add(4); // skip rdtime instruction
12-
return true;
12+
true
1313
} else {
14-
return false; // is not a rdtime instruction
15-
}
14+
false // is not a rdtime instruction
15+
};
1616
}
1717

1818
#[inline]

rustsbi-qemu/src/main.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,25 @@
66
#![feature(default_alloc_error_handler)]
77

88
extern crate alloc;
9-
109
#[macro_use]
1110
extern crate rustsbi;
1211

12+
use core::arch::asm;
13+
use core::panic::PanicInfo;
14+
15+
use buddy_system_allocator::LockedHeap;
16+
1317
mod clint;
1418
mod count_harts;
1519
mod execute;
1620
mod feature;
1721
mod hart_csr_utils;
1822
mod ns16550a;
23+
mod prv_mem;
1924
mod qemu_hsm;
2025
mod runtime;
2126
mod test_device;
2227

23-
use buddy_system_allocator::LockedHeap;
24-
use core::arch::asm;
25-
use core::panic::PanicInfo;
26-
2728
const PER_HART_STACK_SIZE: usize = 4 * 4096; // 16KiB
2829
const SBI_STACK_SIZE: usize = 8 * PER_HART_STACK_SIZE; // assume 8 cores in QEMU
2930
#[link_section = ".bss.uninit"]

0 commit comments

Comments
 (0)