From 5f1e124862071b62aeb0bc02587bea1844a04a30 Mon Sep 17 00:00:00 2001 From: Mohanson Date: Mon, 15 Nov 2021 15:25:03 +0800 Subject: [PATCH] Save all dirty memory pages (including executable pages) and it's flag to snapshot (#218) * Store and resume page flag in snapshot * cargo fmt * Save code in snapshot * Keep the dirty flag caused by load_elf --- Cargo.toml | 4 +-- definitions/Cargo.toml | 2 +- src/machine/mod.rs | 6 +---- src/snapshot.rs | 4 +++ tests/test_resume.rs | 60 +++++++++++++++--------------------------- tests/test_versions.rs | 6 ++--- 6 files changed, 32 insertions(+), 50 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 505d3f9f..a07f7bb0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "ckb-vm" description = "CKB's Virtual machine" -version = "0.20.0" +version = "0.20.1" license = "MIT" authors = ["Nervos Core Dev "] edition = "2018" @@ -25,7 +25,7 @@ goblin_v023 = { package = "goblin", version = "=0.2.3" } goblin_v040 = { package = "goblin", version = "=0.4.0" } scroll = "0.10" serde = { version = "1.0", features = ["derive"] } -ckb-vm-definitions = { path = "definitions", version = "0.20.0" } +ckb-vm-definitions = { path = "definitions", version = "0.20.1" } derive_more = "0.99.2" rand = "0.7.3" diff --git a/definitions/Cargo.toml b/definitions/Cargo.toml index 3af4540c..40645a3f 100644 --- a/definitions/Cargo.toml +++ b/definitions/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "ckb-vm-definitions" description = "Common definition files for CKB VM" -version = "0.20.0" +version = "0.20.1" license = "MIT" authors = ["Nervos Core Dev "] edition = "2018" diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 4d7b0b23..fb4ded00 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -13,12 +13,11 @@ use scroll::Pread; use super::debugger::Debugger; use super::decoder::{build_decoder, Decoder}; use super::instructions::{execute, Instruction, Register}; -use super::memory::{round_page_down, round_page_up, Memory, FLAG_DIRTY}; +use super::memory::{round_page_down, round_page_up, Memory}; use super::syscalls::Syscalls; use super::{ registers::{A0, A7, REGISTER_ABI_NAMES, SP}, Error, DEFAULT_STACK_SIZE, ISA_MOP, RISCV_GENERAL_REGISTER_NUMBER, RISCV_MAX_MEMORY, - RISCV_PAGES, }; // Version 0 is the initial launched CKB VM, it is used in CKB Lina mainnet @@ -180,9 +179,6 @@ pub trait SupportMachine: CoreMachine { self.update_pc(Self::REG::from_u64(e_entry)); self.commit_pc(); } - for i in 0..RISCV_PAGES { - self.memory_mut().clear_flag(i as u64, FLAG_DIRTY)?; - } Ok(bytes) } diff --git a/src/snapshot.rs b/src/snapshot.rs index 0dd1a8ea..4da19544 100644 --- a/src/snapshot.rs +++ b/src/snapshot.rs @@ -33,6 +33,7 @@ pub struct Snapshot { pub registers: [u64; RISCV_GENERAL_REGISTER_NUMBER], pub pc: u64, pub page_indices: Vec, + pub page_flags: Vec, pub pages: Vec>, } @@ -70,6 +71,7 @@ pub fn make_snapshot(machine: &mut T) -> Result } snap.page_indices.push(i as u64); + snap.page_flags.push(flag); snap.pages.push(page); } } @@ -87,9 +89,11 @@ pub fn resume(machine: &mut T, snapshot: &Snapshot) -> Result<() machine.commit_pc(); for i in 0..snapshot.page_indices.len() { let page_index = snapshot.page_indices[i]; + let page_flag = snapshot.page_flags[i]; let page = &snapshot.pages[i]; let addr_from = page_index << RISCV_PAGE_SHIFTS; machine.memory_mut().store_bytes(addr_from, &page[..])?; + machine.memory_mut().set_flag(page_index, page_flag)?; } Ok(()) diff --git a/tests/test_resume.rs b/tests/test_resume.rs index 1d407eb4..67f364de 100644 --- a/tests/test_resume.rs +++ b/tests/test_resume.rs @@ -8,7 +8,7 @@ use ckb_vm::{ trace::TraceMachine, DefaultCoreMachine, DefaultMachine, SupportMachine, VERSION0, VERSION1, }, - memory::sparse::SparseMemory, + memory::{sparse::SparseMemory, wxorx::WXorXMemory}, snapshot::{make_snapshot, resume, Snapshot}, DefaultMachineBuilder, Error, Instruction, ISA_IMC, }; @@ -76,9 +76,6 @@ pub fn resume_asm_2_asm(version: u32, except_cycles: u64) { let snapshot = machine1.snapshot().unwrap(); let mut machine2 = MachineTy::Asm.build(version, 40, None); - machine2 - .load_program(&buffer, &vec!["alloc_many".into()]) - .unwrap(); machine2.resume(&snapshot).unwrap(); let result2 = machine2.run(); let cycles2 = machine2.cycles(); @@ -101,9 +98,6 @@ pub fn resume_asm_2_asm_2_asm(version: u32, except_cycles: u64) { let snapshot1 = machine1.snapshot().unwrap(); let mut machine2 = MachineTy::Asm.build(version, 4000000, None); - machine2 - .load_program(&buffer, &vec!["alloc_many".into()]) - .unwrap(); machine2.resume(&snapshot1).unwrap(); let result2 = machine2.run(); let cycles2 = machine2.cycles(); @@ -112,9 +106,6 @@ pub fn resume_asm_2_asm_2_asm(version: u32, except_cycles: u64) { let snapshot2 = machine2.snapshot().unwrap(); let mut machine3 = MachineTy::Asm.build(version, 4000000, None); - machine3 - .load_program(&buffer, &vec!["alloc_many".into()]) - .unwrap(); machine3.resume(&snapshot2).unwrap(); let result3 = machine3.run(); let cycles3 = machine3.cycles(); @@ -137,9 +128,6 @@ pub fn resume_asm_2_interpreter(version: u32, except_cycles: u64) { let snapshot = machine1.snapshot().unwrap(); let mut machine2 = MachineTy::Interpreter.build(version, 40, None); - machine2 - .load_program(&buffer, &vec!["alloc_many".into()]) - .unwrap(); machine2.resume(&snapshot).unwrap(); let result2 = machine2.run(); @@ -163,9 +151,6 @@ pub fn resume_interpreter_2_interpreter(version: u32, except_cycles: u64) { let snapshot = machine1.snapshot().unwrap(); let mut machine2 = MachineTy::Interpreter.build(version, 30, None); - machine2 - .load_program(&buffer, &vec!["alloc_many".into()]) - .unwrap(); machine2.resume(&snapshot).unwrap(); let result2 = machine2.run(); let cycles2 = machine2.cycles(); @@ -188,9 +173,6 @@ pub fn resume_interpreter_2_asm(version: u32, except_cycles: u64) { let snapshot = machine1.snapshot().unwrap(); let mut machine2 = MachineTy::Asm.build(version, 30, None); - machine2 - .load_program(&buffer, &vec!["alloc_many".into()]) - .unwrap(); machine2.resume(&snapshot).unwrap(); let result2 = machine2.run(); let cycles2 = machine2.cycles(); @@ -217,9 +199,6 @@ pub fn resume_aot_2_asm(version: u32, except_cycles: u64) { let snapshot = machine1.snapshot().unwrap(); let mut machine2 = MachineTy::Asm.build(version, 40, None); - machine2 - .load_program(&buffer, &vec!["alloc_many".into()]) - .unwrap(); machine2.resume(&snapshot).unwrap(); let result2 = machine2.run(); let cycles2 = machine2.cycles(); @@ -242,9 +221,6 @@ pub fn resume_interpreter_with_trace_2_asm_inner(version: u32, except_cycles: u6 let snapshot = machine1.snapshot().unwrap(); let mut machine2 = MachineTy::Asm.build(version, 30, None); - machine2 - .load_program(&buffer, &vec!["alloc_many".into()]) - .unwrap(); machine2.resume(&snapshot).unwrap(); let result2 = machine2.run(); let cycles2 = machine2.cycles(); @@ -285,10 +261,11 @@ impl MachineTy { Machine::Aot(AsmMachine::new(core1, program)) } MachineTy::Interpreter => { - let core_machine1 = - DefaultCoreMachine::>::new(ISA_IMC, version, max_cycles); + let core_machine1 = DefaultCoreMachine::>>::new( + ISA_IMC, version, max_cycles, + ); Machine::Interpreter( - DefaultMachineBuilder::>>::new( + DefaultMachineBuilder::>>>::new( core_machine1, ) .instruction_cycle_func(Box::new(dummy_cycle_func)) @@ -296,15 +273,18 @@ impl MachineTy { ) } MachineTy::InterpreterWithTrace => { - let core_machine1 = - DefaultCoreMachine::>::new(ISA_IMC, version, max_cycles); - Machine::InterpreterWithTrace(TraceMachine::new( - DefaultMachineBuilder::>>::new( - core_machine1, - ) - .instruction_cycle_func(Box::new(dummy_cycle_func)) - .build(), - )) + let core_machine1 = DefaultCoreMachine::>>::new( + ISA_IMC, version, max_cycles, + ); + Machine::InterpreterWithTrace( + TraceMachine::new( + DefaultMachineBuilder::< + DefaultCoreMachine>>, + >::new(core_machine1) + .instruction_cycle_func(Box::new(dummy_cycle_func)) + .build(), + ), + ) } } } @@ -313,8 +293,10 @@ impl MachineTy { enum Machine<'a> { Asm(AsmMachine<'static>), Aot(AsmMachine<'a>), - Interpreter(DefaultMachine<'static, DefaultCoreMachine>>), - InterpreterWithTrace(TraceMachine<'static, DefaultCoreMachine>>), + Interpreter(DefaultMachine<'static, DefaultCoreMachine>>>), + InterpreterWithTrace( + TraceMachine<'static, DefaultCoreMachine>>>, + ), } impl<'a> Machine<'a> { diff --git a/tests/test_versions.rs b/tests/test_versions.rs index 3b533047..76b2082d 100644 --- a/tests/test_versions.rs +++ b/tests/test_versions.rs @@ -6,7 +6,7 @@ use ckb_vm::{ asm::{AsmCoreMachine, AsmMachine}, VERSION0, VERSION1, }, - memory::FLAG_FREEZED, + memory::{FLAG_DIRTY, FLAG_FREEZED}, CoreMachine, DefaultCoreMachine, DefaultMachine, DefaultMachineBuilder, Error, Memory, SparseMemory, WXorXMemory, ISA_IMC, RISCV_PAGESIZE, }; @@ -434,7 +434,7 @@ pub fn test_asm_version0_writable_page() { // 0x12000 is the address of the variable "buffer", which can be found from the dump file. let page_index = 0x12000 / RISCV_PAGESIZE as u64; let flag = machine.machine.memory_mut().fetch_flag(page_index).unwrap(); - assert_eq!(flag, FLAG_FREEZED); + assert_eq!(flag, FLAG_DIRTY | FLAG_FREEZED); let result = machine.run(); assert!(result.is_ok()); assert_eq!(result.unwrap(), 0); @@ -445,7 +445,7 @@ pub fn test_asm_version1_writable_page() { let mut machine = create_asm_machine("writable_page".to_string(), VERSION1); let page_index = 0x12000 / RISCV_PAGESIZE as u64; let flag = machine.machine.memory_mut().fetch_flag(page_index).unwrap(); - assert_eq!(flag, 0); + assert_eq!(flag, FLAG_DIRTY); let result = machine.run(); assert!(result.is_ok()); assert_eq!(result.unwrap(), 0);