diff --git a/src/snapshot.rs b/src/snapshot.rs index 6172a28c..ec42379d 100644 --- a/src/snapshot.rs +++ b/src/snapshot.rs @@ -32,12 +32,14 @@ pub struct Snapshot { pub page_indices: Vec, pub page_flags: Vec, pub pages: Vec>, + pub load_reservation_address: u64, } pub fn make_snapshot(machine: &mut T) -> Result { let mut snap = Snapshot { version: machine.version(), pc: machine.pc().to_u64(), + load_reservation_address: machine.memory().lr().to_u64(), ..Default::default() }; for (i, v) in machine.registers().iter().enumerate() { @@ -92,6 +94,8 @@ pub fn resume(machine: &mut T, snapshot: &Snapshot) -> Result<() machine.memory_mut().store_bytes(addr_from, &page[..])?; machine.memory_mut().set_flag(page_index, page_flag)?; } - + machine + .memory_mut() + .set_lr(&T::REG::from_u64(snapshot.load_reservation_address)); Ok(()) } diff --git a/tests/programs/_build_all_native.sh b/tests/programs/_build_all_native.sh index d1f2a627..1987653a 100755 --- a/tests/programs/_build_all_native.sh +++ b/tests/programs/_build_all_native.sh @@ -52,6 +52,7 @@ riscv64-unknown-elf-as -o rorw_in_end_of_aot_block.o rorw_in_end_of_aot_block.S sh rvc_pageend.sh # TODO: sbinvi_aot_load_imm_bug riscv64-unknown-elf-as -o sc_after_sc.o sc_after_sc.S && riscv64-unknown-elf-ld -T sc_after_sc.lds -o sc_after_sc sc_after_sc.o && rm sc_after_sc.o +riscv64-unknown-elf-as -o sc_after_snapshot.o sc_after_snapshot.S && riscv64-unknown-elf-ld -T sc_after_snapshot.lds -o sc_after_snapshot sc_after_snapshot.o && rm sc_after_snapshot.o riscv64-unknown-elf-as -o sc_only.o sc_only.S && riscv64-unknown-elf-ld -T sc_only.lds -o sc_only sc_only.o && rm sc_only.o # SKIP: simple riscv64-unknown-elf-gcc -o simple64 simple.c diff --git a/tests/programs/sc_after_snapshot b/tests/programs/sc_after_snapshot new file mode 100755 index 00000000..82abe646 Binary files /dev/null and b/tests/programs/sc_after_snapshot differ diff --git a/tests/programs/sc_after_snapshot.S b/tests/programs/sc_after_snapshot.S new file mode 100644 index 00000000..204b2bc6 --- /dev/null +++ b/tests/programs/sc_after_snapshot.S @@ -0,0 +1,22 @@ +.global _start +_start: +_test_case_sc_after_snapshot: + la a0, n0 # a0 holds address of memory location n0 + lr.d a2, (a0) + nop + nop + nop + nop + sc.d a3, a2, (a0) + bnez a3, fail # sc.d must success +done: + li a0, 0 + li a7, 93 + ecall +fail: + li a0, 1 + li a7, 93 + ecall +.section .data +n0: + .dword 4 # Initialize to 4 diff --git a/tests/programs/sc_after_snapshot.lds b/tests/programs/sc_after_snapshot.lds new file mode 100644 index 00000000..fdfa58fb --- /dev/null +++ b/tests/programs/sc_after_snapshot.lds @@ -0,0 +1,7 @@ +SECTIONS +{ +. = 0x100b0; +.text : { *(.text) } +. = 0x11000; +.data : { *(.data) } +} diff --git a/tests/test_resume.rs b/tests/test_resume.rs index 64317df6..0d589abd 100644 --- a/tests/test_resume.rs +++ b/tests/test_resume.rs @@ -4,10 +4,12 @@ use bytes::Bytes; use ckb_vm::cost_model::constant_cycles; use ckb_vm::machine::asm::{AsmCoreMachine, AsmMachine}; use ckb_vm::machine::trace::TraceMachine; -use ckb_vm::machine::{DefaultCoreMachine, DefaultMachine, SupportMachine, VERSION0, VERSION1}; +use ckb_vm::machine::{ + DefaultCoreMachine, DefaultMachine, SupportMachine, VERSION0, VERSION1, VERSION2, +}; use ckb_vm::memory::{sparse::SparseMemory, wxorx::WXorXMemory}; use ckb_vm::snapshot::{make_snapshot, resume, Snapshot}; -use ckb_vm::{DefaultMachineBuilder, Error, ISA_IMC}; +use ckb_vm::{DefaultMachineBuilder, Error, ISA_A, ISA_IMC}; use std::fs::File; use std::io::Read; @@ -294,3 +296,30 @@ impl Machine { } } } + +#[test] +pub fn test_sc_after_snapshot() { + let mut machine = machine_build::int_v2_imacb("tests/programs/sc_after_snapshot"); + machine.machine.inner_mut().set_max_cycles(5); + let ret = machine.run(); + assert!(ret.is_err()); + assert_eq!(ret.unwrap_err(), Error::CyclesExceeded); + + let snap = make_snapshot(&mut machine).unwrap(); + let mut machine_new = TraceMachine::new( + DefaultMachineBuilder::new( + DefaultCoreMachine::>>::new( + ISA_IMC | ISA_A, + VERSION2, + u64::max_value(), + ), + ) + .instruction_cycle_func(Box::new(constant_cycles)) + .build(), + ); + resume(&mut machine_new, &snap).unwrap(); + machine_new.machine.inner_mut().set_max_cycles(20); + let ret = machine_new.run(); + assert!(ret.is_ok()); + assert_eq!(ret.unwrap(), 0); +}