Skip to content

Commit 11a59cf

Browse files
authored
Refactored flexible memory implementation (#378)
* Refactor dymnaic memory * Refactor memory flags * Refactor frames flags * Small optimization * Use less instructions for _CHECK_READ_FRAMES on aarch64 * Small optimization * Small optimization * Use alloc instead of vec * Add cast_ptr_to_slice and cast_ptr_to_slice_mut methods * Fix clippy * Remove memory size limit * Let AsmCoreMachine be responsible for memory allocation and release
1 parent acb7767 commit 11a59cf

19 files changed

+454
-415
lines changed

Makefile

+2-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ clippy_rule = -D warnings \
2828
-A clippy::inconsistent_digit_grouping \
2929
-A clippy::large_digit_groups \
3030
-A clippy::suspicious_operation_groupings \
31-
-A clippy::unnecessary_cast
31+
-A clippy::unnecessary_cast \
32+
-A clippy::mut_from_ref
3233
clippy:
3334
cargo clippy --all --features=asm -- $(clippy_rule)
3435
cd definitions && cargo clippy --all -- $(clippy_rule)

definitions/src/asm.rs

+43-15
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use crate::{
2-
instructions::Instruction, MEMORY_FRAMES, MEMORY_FRAMESIZE, MEMORY_FRAME_SHIFTS,
3-
RISCV_GENERAL_REGISTER_NUMBER, RISCV_MAX_MEMORY, RISCV_PAGES, RISCV_PAGESIZE,
2+
instructions::Instruction, DEFAULT_MEMORY_SIZE, MEMORY_FRAMESIZE, MEMORY_FRAME_SHIFTS,
3+
RISCV_GENERAL_REGISTER_NUMBER, RISCV_PAGESIZE,
44
};
5-
use std::alloc::{alloc, Layout};
5+
use std::alloc::{alloc, alloc_zeroed, dealloc, Layout};
66

77
// The number of trace items to keep
88
pub const TRACE_SIZE: usize = 8192;
@@ -101,15 +101,25 @@ pub struct AsmCoreMachine {
101101
pub last_read_frame: u64,
102102
pub last_write_page: u64,
103103

104-
pub flags: [u8; RISCV_PAGES],
105-
pub frames: [u8; MEMORY_FRAMES],
104+
pub memory_ptr: u64,
105+
pub flags_ptr: u64,
106+
pub frames_ptr: u64,
107+
}
106108

107-
pub memory: [u8; RISCV_MAX_MEMORY],
109+
impl Drop for AsmCoreMachine {
110+
fn drop(&mut self) {
111+
let memory_layout = Layout::array::<u8>(self.memory_size as usize).unwrap();
112+
unsafe { dealloc(self.memory_ptr as *mut u8, memory_layout) };
113+
let flags_layout = Layout::array::<u8>(self.flags_size as usize).unwrap();
114+
unsafe { dealloc(self.flags_ptr as *mut u8, flags_layout) };
115+
let frames_layout = Layout::array::<u8>(self.frames_size as usize).unwrap();
116+
unsafe { dealloc(self.frames_ptr as *mut u8, frames_layout) };
117+
}
108118
}
109119

110120
impl AsmCoreMachine {
111121
pub fn new(isa: u8, version: u32, max_cycles: u64) -> Box<AsmCoreMachine> {
112-
Self::new_with_memory(isa, version, max_cycles, RISCV_MAX_MEMORY)
122+
Self::new_with_memory(isa, version, max_cycles, DEFAULT_MEMORY_SIZE)
113123
}
114124

115125
pub fn new_with_memory(
@@ -119,15 +129,10 @@ impl AsmCoreMachine {
119129
memory_size: usize,
120130
) -> Box<AsmCoreMachine> {
121131
assert_ne!(memory_size, 0);
122-
assert!(memory_size <= RISCV_MAX_MEMORY);
123132
assert_eq!(memory_size % RISCV_PAGESIZE, 0);
124133
assert_eq!(memory_size % (1 << MEMORY_FRAME_SHIFTS), 0);
125-
126134
let mut machine = unsafe {
127-
let machine_size =
128-
std::mem::size_of::<AsmCoreMachine>() - RISCV_MAX_MEMORY + memory_size;
129-
130-
let layout = Layout::array::<u8>(machine_size).unwrap();
135+
let layout = Layout::new::<AsmCoreMachine>();
131136
let raw_allocation = alloc(layout) as *mut AsmCoreMachine;
132137
Box::from_raw(raw_allocation)
133138
};
@@ -146,8 +151,6 @@ impl AsmCoreMachine {
146151
machine.reset_signal = 0;
147152
machine.version = version;
148153
machine.isa = isa;
149-
machine.flags = [0; RISCV_PAGES];
150-
machine.frames = [0; MEMORY_FRAMES];
151154

152155
machine.memory_size = memory_size as u64;
153156
machine.frames_size = (memory_size / MEMORY_FRAMESIZE) as u64;
@@ -156,10 +159,35 @@ impl AsmCoreMachine {
156159
machine.last_read_frame = u64::max_value();
157160
machine.last_write_page = u64::max_value();
158161

162+
let memory_layout = Layout::array::<u8>(machine.memory_size as usize).unwrap();
163+
machine.memory_ptr = unsafe { alloc(memory_layout) } as u64;
164+
let flags_layout = Layout::array::<u8>(machine.flags_size as usize).unwrap();
165+
machine.flags_ptr = unsafe { alloc_zeroed(flags_layout) } as u64;
166+
let frames_layout = Layout::array::<u8>(machine.frames_size as usize).unwrap();
167+
machine.frames_ptr = unsafe { alloc_zeroed(frames_layout) } as u64;
168+
159169
machine
160170
}
161171

162172
pub fn set_max_cycles(&mut self, cycles: u64) {
163173
self.max_cycles = cycles;
164174
}
165175
}
176+
177+
impl AsmCoreMachine {
178+
pub fn cast_ptr_to_slice(&self, ptr: u64, offset: usize, size: usize) -> &[u8] {
179+
unsafe {
180+
let ptr = ptr as *mut u8;
181+
let ptr = ptr.add(offset);
182+
std::slice::from_raw_parts(ptr, size)
183+
}
184+
}
185+
186+
pub fn cast_ptr_to_slice_mut(&self, ptr: u64, offset: usize, size: usize) -> &mut [u8] {
187+
unsafe {
188+
let ptr = ptr as *mut u8;
189+
let ptr = ptr.add(offset);
190+
std::slice::from_raw_parts_mut(ptr, size)
191+
}
192+
}
193+
}

definitions/src/generate_asm_constants.rs

+8-24
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ use ckb_vm_definitions::{
88
instructions::{instruction_opcode_name, MAXIMUM_OPCODE, MINIMAL_OPCODE},
99
memory::{FLAG_DIRTY, FLAG_EXECUTABLE, FLAG_FREEZED, FLAG_WRITABLE, FLAG_WXORX_BIT},
1010
registers::{RA, SP},
11-
MEMORY_FRAMES, MEMORY_FRAMESIZE, MEMORY_FRAME_PAGE_SHIFTS, MEMORY_FRAME_SHIFTS,
12-
RISCV_MAX_MEMORY, RISCV_PAGES, RISCV_PAGESIZE, RISCV_PAGE_SHIFTS,
11+
MEMORY_FRAMESIZE, MEMORY_FRAME_PAGE_SHIFTS, MEMORY_FRAME_SHIFTS, RISCV_PAGESIZE,
12+
RISCV_PAGE_SHIFTS,
1313
};
1414
use std::mem::{size_of, zeroed};
1515

@@ -30,17 +30,14 @@ macro_rules! print_inst_label {
3030
// of this as a workaround to the problem that build.rs cannot depend on any
3131
// of its crate contents.
3232
fn main() {
33-
println!("#define CKB_VM_ASM_RISCV_MAX_MEMORY {}", RISCV_MAX_MEMORY);
3433
println!("#define CKB_VM_ASM_RISCV_PAGE_SHIFTS {}", RISCV_PAGE_SHIFTS);
3534
println!("#define CKB_VM_ASM_RISCV_PAGE_SIZE {}", RISCV_PAGESIZE);
3635
println!("#define CKB_VM_ASM_RISCV_PAGE_MASK {}", RISCV_PAGESIZE - 1);
37-
println!("#define CKB_VM_ASM_RISCV_PAGES {}", RISCV_PAGES);
3836
println!(
3937
"#define CKB_VM_ASM_MEMORY_FRAME_SHIFTS {}",
4038
MEMORY_FRAME_SHIFTS
4139
);
4240
println!("#define CKB_VM_ASM_MEMORY_FRAMESIZE {}", MEMORY_FRAMESIZE);
43-
println!("#define CKB_VM_ASM_MEMORY_FRAMES {}", MEMORY_FRAMES);
4441
println!(
4542
"#define CKB_VM_ASM_MEMORY_FRAME_PAGE_SHIFTS {}",
4643
MEMORY_FRAME_PAGE_SHIFTS
@@ -183,31 +180,18 @@ fn main() {
183180
"#define CKB_VM_ASM_ASM_CORE_MACHINE_OFFSET_LAST_WRITE_PAGE {}",
184181
(&m.last_write_page as *const u64 as usize) - m_address
185182
);
186-
187-
println!(
188-
"#define CKB_VM_ASM_ASM_CORE_MACHINE_OFFSET_FLAGS {}",
189-
(&m.flags as *const u8 as usize) - m_address
190-
);
191-
let memory_offset_address = (&m.memory as *const u8 as usize) - m_address;
192-
println!(
193-
"#define CKB_VM_ASM_ASM_CORE_MACHINE_OFFSET_MEMORY {}",
194-
memory_offset_address
195-
);
196183
println!(
197-
"#define CKB_VM_ASM_ASM_CORE_MACHINE_OFFSET_FRAMES {}",
198-
(&m.frames as *const u8 as usize) - m_address
184+
"#define CKB_VM_ASM_ASM_CORE_MACHINE_OFFSET_MEMORY_PTR {}",
185+
(&m.memory_ptr as *const u64 as usize) - m_address
199186
);
200-
println!();
201-
202187
println!(
203-
"#define CKB_VM_ASM_ASM_CORE_MACHINE_OFFSET_MEMORY_H {}",
204-
memory_offset_address.wrapping_shr(12).wrapping_shl(12)
188+
"#define CKB_VM_ASM_ASM_CORE_MACHINE_OFFSET_FLAGS_PTR {}",
189+
(&m.flags_ptr as *const u64 as usize) - m_address
205190
);
206191
println!(
207-
"#define CKB_VM_ASM_ASM_CORE_MACHINE_OFFSET_MEMORY_L {}",
208-
memory_offset_address & 0xFFF
192+
"#define CKB_VM_ASM_ASM_CORE_MACHINE_OFFSET_FRAMES_PTR {}",
193+
(&m.frames_ptr as *const u64 as usize) - m_address
209194
);
210-
211195
println!();
212196

213197
for op in MINIMAL_OPCODE..MAXIMUM_OPCODE {

definitions/src/lib.rs

+3-8
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,12 @@ pub mod registers;
66
pub const RISCV_PAGE_SHIFTS: usize = 12;
77
pub const RISCV_PAGESIZE: usize = 1 << RISCV_PAGE_SHIFTS;
88
pub const RISCV_GENERAL_REGISTER_NUMBER: usize = 32;
9-
// 4 MB
10-
pub const RISCV_MAX_MEMORY: usize = 4 << 20;
11-
// 1 MB
12-
pub const DEFAULT_STACK_SIZE: usize = 1 << 20;
13-
pub const RISCV_PAGES: usize = RISCV_MAX_MEMORY / RISCV_PAGESIZE;
14-
// 256 KB
159
pub const MEMORY_FRAME_SHIFTS: usize = 18;
16-
pub const MEMORY_FRAMESIZE: usize = 1 << MEMORY_FRAME_SHIFTS;
17-
pub const MEMORY_FRAMES: usize = RISCV_MAX_MEMORY / MEMORY_FRAMESIZE;
10+
pub const MEMORY_FRAMESIZE: usize = 1 << MEMORY_FRAME_SHIFTS; // 256 KB
1811
pub const MEMORY_FRAME_PAGE_SHIFTS: usize = MEMORY_FRAME_SHIFTS - RISCV_PAGE_SHIFTS;
1912

13+
pub const DEFAULT_MEMORY_SIZE: usize = 4 << 20; // 4 MB
14+
2015
pub const ISA_IMC: u8 = 0b0000_0000;
2116
pub const ISA_B: u8 = 0b0000_0001;
2217
pub const ISA_MOP: u8 = 0b0000_0010;

fuzz/fuzz_targets/isa_a.rs

-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ fuzz_target!(|data: [u8; 512]| {
4343
ckb_vm::machine::asm::AsmCoreMachine::new(ckb_vm_isa, ckb_vm_version, u64::MAX),
4444
)
4545
.build();
46-
4746
let insts: [u32; 18] = [
4847
0b00001_00_00000_00000_010_00000_0101111, // AMOSWAP.W
4948
0b00000_00_00000_00000_010_00000_0101111, // AMOADD.W

src/lib.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,8 @@ pub use crate::{
3030
pub use bytes::Bytes;
3131

3232
pub use ckb_vm_definitions::{
33-
registers, DEFAULT_STACK_SIZE, ISA_A, ISA_B, ISA_IMC, ISA_MOP, MEMORY_FRAMES, MEMORY_FRAMESIZE,
34-
MEMORY_FRAME_SHIFTS, RISCV_GENERAL_REGISTER_NUMBER, RISCV_MAX_MEMORY, RISCV_PAGES,
35-
RISCV_PAGESIZE, RISCV_PAGE_SHIFTS,
33+
registers, DEFAULT_MEMORY_SIZE, ISA_A, ISA_B, ISA_IMC, ISA_MOP, MEMORY_FRAMESIZE,
34+
MEMORY_FRAME_SHIFTS, RISCV_GENERAL_REGISTER_NUMBER, RISCV_PAGESIZE, RISCV_PAGE_SHIFTS,
3635
};
3736

3837
pub use error::Error;
@@ -74,7 +73,7 @@ mod tests {
7473

7574
#[test]
7675
fn test_max_memory_must_be_multiple_of_pages() {
77-
assert_eq!(RISCV_MAX_MEMORY % RISCV_PAGESIZE, 0);
76+
assert_eq!(DEFAULT_MEMORY_SIZE % RISCV_PAGESIZE, 0);
7877
}
7978

8079
#[test]

src/machine/asm/cdefinitions_generated.h

+3-9
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
1-
#define CKB_VM_ASM_RISCV_MAX_MEMORY 4194304
21
#define CKB_VM_ASM_RISCV_PAGE_SHIFTS 12
32
#define CKB_VM_ASM_RISCV_PAGE_SIZE 4096
43
#define CKB_VM_ASM_RISCV_PAGE_MASK 4095
5-
#define CKB_VM_ASM_RISCV_PAGES 1024
64
#define CKB_VM_ASM_MEMORY_FRAME_SHIFTS 18
75
#define CKB_VM_ASM_MEMORY_FRAMESIZE 262144
8-
#define CKB_VM_ASM_MEMORY_FRAMES 16
96
#define CKB_VM_ASM_MEMORY_FRAME_PAGE_SHIFTS 6
107

118
#define CKB_VM_ASM_MAXIMUM_TRACE_ADDRESS_LENGTH 64
@@ -52,12 +49,9 @@
5249
#define CKB_VM_ASM_ASM_CORE_MACHINE_OFFSET_FLAGS_SIZE 336
5350
#define CKB_VM_ASM_ASM_CORE_MACHINE_OFFSET_LAST_READ_FRAME 344
5451
#define CKB_VM_ASM_ASM_CORE_MACHINE_OFFSET_LAST_WRITE_PAGE 352
55-
#define CKB_VM_ASM_ASM_CORE_MACHINE_OFFSET_FLAGS 360
56-
#define CKB_VM_ASM_ASM_CORE_MACHINE_OFFSET_MEMORY 1400
57-
#define CKB_VM_ASM_ASM_CORE_MACHINE_OFFSET_FRAMES 1384
58-
59-
#define CKB_VM_ASM_ASM_CORE_MACHINE_OFFSET_MEMORY_H 0
60-
#define CKB_VM_ASM_ASM_CORE_MACHINE_OFFSET_MEMORY_L 1400
52+
#define CKB_VM_ASM_ASM_CORE_MACHINE_OFFSET_MEMORY_PTR 360
53+
#define CKB_VM_ASM_ASM_CORE_MACHINE_OFFSET_FLAGS_PTR 368
54+
#define CKB_VM_ASM_ASM_CORE_MACHINE_OFFSET_FRAMES_PTR 376
6155

6256
#define CKB_VM_ASM_OP_UNLOADED 16
6357
#define CKB_VM_ASM_OP_ADD 17

0 commit comments

Comments
 (0)