Sitelet https://github.com/r55-eth/rvemu/commit/6512fb09a674a3bef1d2d163d615683ffa9e07fc
Skip to content

Commit 6512fb0

Browse files
committed
Store a correct trap value for page fault exceptions.
1 parent 4a1c6b8 commit 6512fb0

2 files changed

Lines changed: 52 additions & 33 deletions

File tree

‎src/cpu.rs‎

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -406,9 +406,9 @@ impl Cpu {
406406
let x = (pte >> 3) & 1;
407407
if v == 0 || (r == 0 && w == 1) {
408408
match access_type {
409-
AccessType::Instruction => return Err(Exception::InstructionPageFault),
410-
AccessType::Load => return Err(Exception::LoadPageFault),
411-
AccessType::Store => return Err(Exception::StoreAMOPageFault),
409+
AccessType::Instruction => return Err(Exception::InstructionPageFault(addr)),
410+
AccessType::Load => return Err(Exception::LoadPageFault(addr)),
411+
AccessType::Store => return Err(Exception::StoreAMOPageFault(addr)),
412412
}
413413
}
414414

@@ -425,9 +425,9 @@ impl Cpu {
425425
a = ppn * PAGE_SIZE;
426426
if i < 0 {
427427
match access_type {
428-
AccessType::Instruction => return Err(Exception::InstructionPageFault),
429-
AccessType::Load => return Err(Exception::LoadPageFault),
430-
AccessType::Store => return Err(Exception::StoreAMOPageFault),
428+
AccessType::Instruction => return Err(Exception::InstructionPageFault(addr)),
429+
AccessType::Load => return Err(Exception::LoadPageFault(addr)),
430+
AccessType::Store => return Err(Exception::StoreAMOPageFault(addr)),
431431
}
432432
}
433433
}
@@ -464,9 +464,11 @@ impl Cpu {
464464
if ppn[j as usize] != 0 {
465465
// A misaligned superpage.
466466
match access_type {
467-
AccessType::Instruction => return Err(Exception::InstructionPageFault),
468-
AccessType::Load => return Err(Exception::LoadPageFault),
469-
AccessType::Store => return Err(Exception::StoreAMOPageFault),
467+
AccessType::Instruction => {
468+
return Err(Exception::InstructionPageFault(addr))
469+
}
470+
AccessType::Load => return Err(Exception::LoadPageFault(addr)),
471+
AccessType::Store => return Err(Exception::StoreAMOPageFault(addr)),
470472
}
471473
}
472474
}
@@ -522,9 +524,9 @@ impl Cpu {
522524
Ok((ppn[2] << 30) | (vpn[1] << 21) | (vpn[0] << 12) | offset)
523525
}
524526
_ => match access_type {
525-
AccessType::Instruction => return Err(Exception::InstructionPageFault),
526-
AccessType::Load => return Err(Exception::LoadPageFault),
527-
AccessType::Store => return Err(Exception::StoreAMOPageFault),
527+
AccessType::Instruction => return Err(Exception::InstructionPageFault(addr)),
528+
AccessType::Load => return Err(Exception::LoadPageFault(addr)),
529+
AccessType::Store => return Err(Exception::StoreAMOPageFault(addr)),
528530
},
529531
}
530532
}

‎src/exception.rs‎

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@ pub enum Exception {
2121
EnvironmentCallFromUMode,
2222
EnvironmentCallFromSMode,
2323
EnvironmentCallFromMMode,
24-
InstructionPageFault,
25-
LoadPageFault,
26-
StoreAMOPageFault,
24+
// Stores a trap value (the faulting address) for page fault exceptions.
25+
InstructionPageFault(u64),
26+
LoadPageFault(u64),
27+
StoreAMOPageFault(u64),
2728
}
2829

2930
/// All the trap kinds.
@@ -57,9 +58,9 @@ impl Exception {
5758
Exception::EnvironmentCallFromUMode => 8,
5859
Exception::EnvironmentCallFromSMode => 9,
5960
Exception::EnvironmentCallFromMMode => 11,
60-
Exception::InstructionPageFault => 12,
61-
Exception::LoadPageFault => 13,
62-
Exception::StoreAMOPageFault => 15,
61+
Exception::InstructionPageFault(_) => 12,
62+
Exception::LoadPageFault(_) => 13,
63+
Exception::StoreAMOPageFault(_) => 15,
6364
}
6465
}
6566

@@ -73,6 +74,32 @@ impl Exception {
7374
}
7475
}
7576

77+
fn trap_value(&self, pc: u64) -> u64 {
78+
// 3.1.17 Machine Trap Value Register (mtval)
79+
// 4.1.9 Supervisor Trap Value Register (stval)
80+
// "When a hardware breakpoint is triggered, or an address-misaligned, access-fault, or
81+
// page-fault exception occurs on an instruction fetch, load, or store, mtval (stval) is
82+
// written with the faulting virtual address. On an illegal instruction trap, mtval (stval)
83+
// may be written with the first XLEN or ILEN bits of the faulting instruction as described
84+
// below. For other traps, mtval (stval) is set to zero, but a future standard may redefine
85+
// mtval's (stval's) setting for other traps."
86+
//
87+
// TODO: support illegal instruction trap.
88+
match self {
89+
Exception::InstructionAddressMisaligned
90+
| Exception::InstructionAccessFault
91+
| Exception::Breakpoint
92+
| Exception::LoadAddressMisaligned
93+
| Exception::LoadAccessFault
94+
| Exception::StoreAMOAddressMisaligned
95+
| Exception::StoreAMOAccessFault => pc,
96+
Exception::InstructionPageFault(val)
97+
| Exception::LoadPageFault(val)
98+
| Exception::StoreAMOPageFault(val) => *val,
99+
_ => 0,
100+
}
101+
}
102+
76103
/// Update CSRs and the program counter depending on an exception.
77104
pub fn take_trap(&self, cpu: &mut Cpu) -> Trap {
78105
// 1.2 Privilege Levels
@@ -126,12 +153,7 @@ impl Exception {
126153
// "When a trap is taken into S-mode, stval is written with exception-specific
127154
// information to assist software in handling the trap. Otherwise, stval is never
128155
// written by the implementation, though it may be explicitly written by software."
129-
// "When a hardware breakpoint is triggered, or an instruction-fetch, load, or
130-
// store address-misaligned, access, or page-fault exception occurs, stval is
131-
// written with the faulting virtual address. On an illegal instruction trap,
132-
// stval may be written with the first XLEN or ILEN bits of the faulting
133-
// instruction as described below. For other exceptions, stval is set to zero."
134-
cpu.state.write(STVAL, 0);
156+
cpu.state.write(STVAL, self.trap_value(exception_pc));
135157

136158
// Set a previous interrupt-enable bit for supervisor mode (SPIE, 5) to the value
137159
// of a global interrupt-enable bit for supervisor mode (SIE, 1).
@@ -172,12 +194,7 @@ impl Exception {
172194
// exception-specific information to assist software in handling the trap.
173195
// Otherwise, mtval is never written by the implementation, though it may be
174196
// explicitly written by software."
175-
// "When a hardware breakpoint is triggered, or an instruction-fetch, load, or
176-
// store address-misaligned, access, or page-fault exception occurs, mtval is
177-
// written with the faulting virtual address. On an illegal instruction trap,
178-
// mtval may be written with the first XLEN or ILEN bits of the faulting
179-
// instruction as described below. For other traps, mtval is set to zero."
180-
cpu.state.write(MTVAL, 0);
197+
cpu.state.write(MTVAL, self.trap_value(exception_pc));
181198

182199
// Set a previous interrupt-enable bit for supervisor mode (MPIE, 7) to the value
183200
// of a global interrupt-enable bit for supervisor mode (MIE, 3).
@@ -208,9 +225,9 @@ impl Exception {
208225
Exception::EnvironmentCallFromUMode
209226
| Exception::EnvironmentCallFromSMode
210227
| Exception::EnvironmentCallFromMMode => Trap::Requested,
211-
Exception::InstructionPageFault
212-
| Exception::LoadPageFault
213-
| Exception::StoreAMOPageFault => Trap::Invisible,
228+
Exception::InstructionPageFault(_)
229+
| Exception::LoadPageFault(_)
230+
| Exception::StoreAMOPageFault(_) => Trap::Invisible,
214231
}
215232
}
216233
}

0 commit comments

Comments
 (0)