Skip to content

Commit 4ae0ff4

Browse files
authored
report execution failed when vm trapped (#1208)
`let _ = vm.iter_until_halt().take(max_steps).count();` will keep calling `next()` even emulator halt. This PR add termination mechanism
1 parent fe4b65d commit 4ae0ff4

File tree

3 files changed

+20
-8
lines changed

3 files changed

+20
-8
lines changed

ceno_emul/src/tracer.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ pub trait Tracer {
9090

9191
fn advance(&mut self) -> Self::Record;
9292

93-
fn is_busy_loop(record: &Self::Record) -> bool;
93+
fn is_busy_loop(&self, record: &Self::Record) -> bool;
9494

9595
fn store_pc(&mut self, pc: ByteAddr);
9696

@@ -654,6 +654,7 @@ impl FullTracer {
654654
if self.record.memory_op.is_some() {
655655
unimplemented!("Only one memory access is supported");
656656
}
657+
657658
// update min/max mmio access
658659
if let Some((start_addr, (_, end_addr, min_addr, max_addr))) = self
659660
.mmio_min_max_access
@@ -767,6 +768,7 @@ impl FullTracer {
767768
#[derive(Debug)]
768769
pub struct PreflightTracer {
769770
cycle: Cycle,
771+
pc: Change<ByteAddr>,
770772
mmio_min_max_access: Option<BTreeMap<WordAddr, (WordAddr, WordAddr, WordAddr, WordAddr)>>,
771773
latest_accesses: LatestAccesses,
772774
next_accesses: NextCycleAccess,
@@ -783,6 +785,7 @@ impl PreflightTracer {
783785
pub fn new(platform: &Platform) -> Self {
784786
let mut tracer = PreflightTracer {
785787
cycle: <Self as Tracer>::SUBCYCLES_PER_INSN,
788+
pc: Default::default(),
786789
mmio_min_max_access: Some(init_mmio_min_max_access(platform)),
787790
latest_accesses: LatestAccesses::new(platform),
788791
next_accesses: NextCycleAccess::new(ACCESSED_CHUNK_SIZE),
@@ -800,6 +803,8 @@ impl PreflightTracer {
800803
.and_then(|mmio_max_access| mmio_max_access.range_mut(..=addr).next_back())
801804
&& addr < *end_addr
802805
{
806+
// skip if the target address is not within the range tracked by this MMIO region
807+
// this condition ensures the address is within the MMIO region's end address
803808
if addr >= *max_addr {
804809
*max_addr = addr + WordAddr::from(WORD_SIZE as u32);
805810
}
@@ -828,15 +833,19 @@ impl Tracer for PreflightTracer {
828833
self.reset_register_tracking();
829834
}
830835

831-
fn is_busy_loop(_: &Self::Record) -> bool {
832-
false
836+
fn is_busy_loop(&self, _: &Self::Record) -> bool {
837+
self.pc.before == self.pc.after
833838
}
834839

835840
#[inline(always)]
836-
fn store_pc(&mut self, _pc: ByteAddr) {}
841+
fn store_pc(&mut self, pc: ByteAddr) {
842+
self.pc.after = pc;
843+
}
837844

838845
#[inline(always)]
839-
fn fetch(&mut self, _pc: WordAddr, _value: Instruction) {}
846+
fn fetch(&mut self, pc: WordAddr, _value: Instruction) {
847+
self.pc.before = pc.baddr();
848+
}
840849

841850
#[inline(always)]
842851
fn track_mmu_maxtouch_before(&mut self) {}
@@ -944,7 +953,7 @@ impl Tracer for FullTracer {
944953
}
945954

946955
#[inline(always)]
947-
fn is_busy_loop(record: &Self::Record) -> bool {
956+
fn is_busy_loop(&self, record: &Self::Record) -> bool {
948957
record.is_busy_loop()
949958
}
950959

ceno_emul/src/vm_state.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ impl<T: Tracer> VMState<T> {
129129
fn step(&mut self) -> Result<T::Record> {
130130
crate::rv32im::step(self)?;
131131
let step = self.tracer.advance();
132-
if T::is_busy_loop(&step) && !self.halted() {
132+
if self.tracer.is_busy_loop(&step) && !self.halted() {
133133
Err(anyhow!("Stuck in loop {}", "{}"))
134134
} else {
135135
Ok(step)

ceno_zkvm/src/e2e.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -823,7 +823,10 @@ pub fn emulate_program<'a>(
823823
}
824824

825825
let exit_code = info_span!("[ceno] emulator.preflight-execute").in_scope(|| {
826-
let _ = vm.iter_until_halt().take(max_steps).count();
826+
vm.iter_until_halt()
827+
.take(max_steps)
828+
.try_for_each(|step| step.map(|_| ()))
829+
.unwrap_or_else(|err| panic!("emulator trapped before halt: {err}"));
827830
vm.halted_state().map(|halt_state| halt_state.exit_code)
828831
});
829832

0 commit comments

Comments
 (0)