Skip to content

Commit

Permalink
Remove memory size limit
Browse files Browse the repository at this point in the history
  • Loading branch information
mohanson committed Sep 27, 2023
1 parent a3ee396 commit 11679d8
Show file tree
Hide file tree
Showing 12 changed files with 81 additions and 72 deletions.
7 changes: 3 additions & 4 deletions definitions/src/asm.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
instructions::Instruction, MEMORY_FRAMESIZE, MEMORY_FRAME_SHIFTS,
RISCV_GENERAL_REGISTER_NUMBER, RISCV_MAX_MEMORY, RISCV_PAGESIZE,
instructions::Instruction, DEFAULT_MEMORY_SIZE, MEMORY_FRAMESIZE, MEMORY_FRAME_SHIFTS,
RISCV_GENERAL_REGISTER_NUMBER, RISCV_PAGESIZE,
};
use std::alloc::{alloc, Layout};

Expand Down Expand Up @@ -108,7 +108,7 @@ pub struct AsmCoreMachine {

impl AsmCoreMachine {
pub fn new(isa: u8, version: u32, max_cycles: u64) -> Box<AsmCoreMachine> {
Self::new_with_memory(isa, version, max_cycles, RISCV_MAX_MEMORY)
Self::new_with_memory(isa, version, max_cycles, DEFAULT_MEMORY_SIZE)
}

pub fn new_with_memory(
Expand All @@ -118,7 +118,6 @@ impl AsmCoreMachine {
memory_size: usize,
) -> Box<AsmCoreMachine> {
assert_ne!(memory_size, 0);
assert!(memory_size <= RISCV_MAX_MEMORY);
assert_eq!(memory_size % RISCV_PAGESIZE, 0);
assert_eq!(memory_size % (1 << MEMORY_FRAME_SHIFTS), 0);
let mut machine = unsafe {
Expand Down
7 changes: 2 additions & 5 deletions definitions/src/generate_asm_constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use ckb_vm_definitions::{
instructions::{instruction_opcode_name, MAXIMUM_OPCODE, MINIMAL_OPCODE},
memory::{FLAG_DIRTY, FLAG_EXECUTABLE, FLAG_FREEZED, FLAG_WRITABLE, FLAG_WXORX_BIT},
registers::{RA, SP},
MEMORY_FRAMES, MEMORY_FRAMESIZE, MEMORY_FRAME_PAGE_SHIFTS, MEMORY_FRAME_SHIFTS,
RISCV_MAX_MEMORY, RISCV_PAGES, RISCV_PAGESIZE, RISCV_PAGE_SHIFTS,
MEMORY_FRAMESIZE, MEMORY_FRAME_PAGE_SHIFTS, MEMORY_FRAME_SHIFTS, RISCV_PAGESIZE,
RISCV_PAGE_SHIFTS,
};
use std::mem::{size_of, zeroed};

Expand All @@ -30,17 +30,14 @@ macro_rules! print_inst_label {
// of this as a workaround to the problem that build.rs cannot depend on any
// of its crate contents.
fn main() {
println!("#define CKB_VM_ASM_RISCV_MAX_MEMORY {}", RISCV_MAX_MEMORY);
println!("#define CKB_VM_ASM_RISCV_PAGE_SHIFTS {}", RISCV_PAGE_SHIFTS);
println!("#define CKB_VM_ASM_RISCV_PAGE_SIZE {}", RISCV_PAGESIZE);
println!("#define CKB_VM_ASM_RISCV_PAGE_MASK {}", RISCV_PAGESIZE - 1);
println!("#define CKB_VM_ASM_RISCV_PAGES {}", RISCV_PAGES);
println!(
"#define CKB_VM_ASM_MEMORY_FRAME_SHIFTS {}",
MEMORY_FRAME_SHIFTS
);
println!("#define CKB_VM_ASM_MEMORY_FRAMESIZE {}", MEMORY_FRAMESIZE);
println!("#define CKB_VM_ASM_MEMORY_FRAMES {}", MEMORY_FRAMES);
println!(
"#define CKB_VM_ASM_MEMORY_FRAME_PAGE_SHIFTS {}",
MEMORY_FRAME_PAGE_SHIFTS
Expand Down
11 changes: 3 additions & 8 deletions definitions/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,12 @@ pub mod registers;
pub const RISCV_PAGE_SHIFTS: usize = 12;
pub const RISCV_PAGESIZE: usize = 1 << RISCV_PAGE_SHIFTS;
pub const RISCV_GENERAL_REGISTER_NUMBER: usize = 32;
// 4 MB
pub const RISCV_MAX_MEMORY: usize = 4 << 20;
// 1 MB
pub const DEFAULT_STACK_SIZE: usize = 1 << 20;
pub const RISCV_PAGES: usize = RISCV_MAX_MEMORY / RISCV_PAGESIZE;
// 256 KB
pub const MEMORY_FRAME_SHIFTS: usize = 18;
pub const MEMORY_FRAMESIZE: usize = 1 << MEMORY_FRAME_SHIFTS;
pub const MEMORY_FRAMES: usize = RISCV_MAX_MEMORY / MEMORY_FRAMESIZE;
pub const MEMORY_FRAMESIZE: usize = 1 << MEMORY_FRAME_SHIFTS; // 256 KB
pub const MEMORY_FRAME_PAGE_SHIFTS: usize = MEMORY_FRAME_SHIFTS - RISCV_PAGE_SHIFTS;

pub const DEFAULT_MEMORY_SIZE: usize = 4 << 20; // 4 MB

pub const ISA_IMC: u8 = 0b0000_0000;
pub const ISA_B: u8 = 0b0000_0001;
pub const ISA_MOP: u8 = 0b0000_0010;
Expand Down
7 changes: 3 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,8 @@ pub use crate::{
pub use bytes::Bytes;

pub use ckb_vm_definitions::{
registers, DEFAULT_STACK_SIZE, ISA_A, ISA_B, ISA_IMC, ISA_MOP, MEMORY_FRAMES, MEMORY_FRAMESIZE,
MEMORY_FRAME_SHIFTS, RISCV_GENERAL_REGISTER_NUMBER, RISCV_MAX_MEMORY, RISCV_PAGES,
RISCV_PAGESIZE, RISCV_PAGE_SHIFTS,
registers, DEFAULT_MEMORY_SIZE, ISA_A, ISA_B, ISA_IMC, ISA_MOP, MEMORY_FRAMESIZE,
MEMORY_FRAME_SHIFTS, RISCV_GENERAL_REGISTER_NUMBER, RISCV_PAGESIZE, RISCV_PAGE_SHIFTS,
};

pub use error::Error;
Expand Down Expand Up @@ -74,7 +73,7 @@ mod tests {

#[test]
fn test_max_memory_must_be_multiple_of_pages() {
assert_eq!(RISCV_MAX_MEMORY % RISCV_PAGESIZE, 0);
assert_eq!(DEFAULT_MEMORY_SIZE % RISCV_PAGESIZE, 0);
}

#[test]
Expand Down
16 changes: 10 additions & 6 deletions src/machine/asm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ use crate::{
VERSION0,
},
memory::{
fill_page_data, get_page_indices, memset, round_page_down, round_page_up, FLAG_DIRTY,
FLAG_EXECUTABLE, FLAG_FREEZED, FLAG_WRITABLE, FLAG_WXORX_BIT,
check_no_overflow, fill_page_data, get_page_indices, memset, round_page_down,
round_page_up, FLAG_DIRTY, FLAG_EXECUTABLE, FLAG_FREEZED, FLAG_WRITABLE, FLAG_WXORX_BIT,
},
CoreMachine, DefaultMachine, Error, Machine, Memory, SupportMachine, MEMORY_FRAME_SHIFTS,
RISCV_PAGESIZE,
Expand Down Expand Up @@ -204,6 +204,7 @@ struct FastMemory<'a>(&'a mut Box<AsmCoreMachine>);

impl<'a> FastMemory<'a> {
fn prepare_memory(&mut self, addr: u64, size: u64) -> Result<(), Error> {
check_no_overflow(addr, size, self.0.memory_size)?;
let frame_start = addr >> MEMORY_FRAME_SHIFTS << MEMORY_FRAME_SHIFTS;
// There is some memory space between the start of the first memory
// frame touched, and the starting address of memory to be written. We
Expand All @@ -220,7 +221,7 @@ impl<'a> FastMemory<'a> {
if (aligned_end + RISCV_PAGESIZE as u64) < frame_next_start {
check_memory(self.0, aligned_end >> RISCV_PAGE_SHIFTS);
}
let page_indices = get_page_indices(addr, size)?;
let page_indices = get_page_indices(addr, size);
for page in page_indices.0..=page_indices.1 {
let frame_index = page >> MEMORY_FRAME_PAGE_SHIFTS;
let slice = self
Expand Down Expand Up @@ -442,7 +443,8 @@ impl Memory for Box<AsmCoreMachine> {
if value.is_empty() {
return Ok(());
}
let page_indices = get_page_indices(addr, value.len() as u64)?;
check_no_overflow(addr, value.len() as u64, self.memory_size)?;
let page_indices = get_page_indices(addr, value.len() as u64);
for page in page_indices.0..=page_indices.1 {
check_permission(self, page, FLAG_WRITABLE)?;
check_memory(self, page);
Expand All @@ -457,7 +459,8 @@ impl Memory for Box<AsmCoreMachine> {
if size == 0 {
return Ok(());
}
let page_indices = get_page_indices(addr, size)?;
check_no_overflow(addr, size, self.memory_size)?;
let page_indices = get_page_indices(addr, size);
for page in page_indices.0..=page_indices.1 {
check_permission(self, page, FLAG_WRITABLE)?;
check_memory(self, page);
Expand All @@ -472,7 +475,8 @@ impl Memory for Box<AsmCoreMachine> {
if size == 0 {
return Ok(Bytes::new());
}
let page_indices = get_page_indices(addr, size)?;
check_no_overflow(addr, size, self.memory_size)?;
let page_indices = get_page_indices(addr, size);
for page in page_indices.0..=page_indices.1 {
check_memory(self, page);
}
Expand Down
25 changes: 15 additions & 10 deletions src/memory/flat.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::super::{Error, Register, RISCV_MAX_MEMORY, RISCV_PAGESIZE};
use super::{fill_page_data, get_page_indices, memset, set_dirty, Memory};
use super::super::{Error, Register, DEFAULT_MEMORY_SIZE, RISCV_PAGESIZE};
use super::{check_no_overflow, fill_page_data, get_page_indices, memset, set_dirty, Memory};

use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use bytes::Bytes;
Expand Down Expand Up @@ -32,7 +32,6 @@ impl<R> DerefMut for FlatMemory<R> {

impl<R: Register> FlatMemory<R> {
pub fn new_with_memory(memory_size: usize) -> Self {
assert!(memory_size <= RISCV_MAX_MEMORY);
assert!(memory_size % RISCV_PAGESIZE == 0);
Self {
data: vec![0; memory_size],
Expand All @@ -47,7 +46,7 @@ impl<R: Register> FlatMemory<R> {

impl<R: Register> Default for FlatMemory<R> {
fn default() -> Self {
Self::new_with_memory(RISCV_MAX_MEMORY)
Self::new_with_memory(DEFAULT_MEMORY_SIZE)
}
}

Expand Down Expand Up @@ -161,7 +160,8 @@ impl<R: Register> Memory for FlatMemory<R> {

fn store8(&mut self, addr: &Self::REG, value: &Self::REG) -> Result<(), Error> {
let addr = addr.to_u64();
let page_indices = get_page_indices(addr.to_u64(), 1)?;
check_no_overflow(addr, 1, self.memory_size as u64)?;
let page_indices = get_page_indices(addr, 1);
set_dirty(self, &page_indices)?;
let mut writer = Cursor::new(&mut self.data);
writer.seek(SeekFrom::Start(addr as u64))?;
Expand All @@ -171,7 +171,8 @@ impl<R: Register> Memory for FlatMemory<R> {

fn store16(&mut self, addr: &Self::REG, value: &Self::REG) -> Result<(), Error> {
let addr = addr.to_u64();
let page_indices = get_page_indices(addr.to_u64(), 2)?;
check_no_overflow(addr, 2, self.memory_size as u64)?;
let page_indices = get_page_indices(addr, 2);
set_dirty(self, &page_indices)?;
let mut writer = Cursor::new(&mut self.data);
writer.seek(SeekFrom::Start(addr as u64))?;
Expand All @@ -181,7 +182,8 @@ impl<R: Register> Memory for FlatMemory<R> {

fn store32(&mut self, addr: &Self::REG, value: &Self::REG) -> Result<(), Error> {
let addr = addr.to_u64();
let page_indices = get_page_indices(addr.to_u64(), 4)?;
check_no_overflow(addr, 4, self.memory_size as u64)?;
let page_indices = get_page_indices(addr, 4);
set_dirty(self, &page_indices)?;
let mut writer = Cursor::new(&mut self.data);
writer.seek(SeekFrom::Start(addr as u64))?;
Expand All @@ -191,7 +193,8 @@ impl<R: Register> Memory for FlatMemory<R> {

fn store64(&mut self, addr: &Self::REG, value: &Self::REG) -> Result<(), Error> {
let addr = addr.to_u64();
let page_indices = get_page_indices(addr.to_u64(), 8)?;
check_no_overflow(addr, 8, self.memory_size as u64)?;
let page_indices = get_page_indices(addr, 8);
set_dirty(self, &page_indices)?;
let mut writer = Cursor::new(&mut self.data);
writer.seek(SeekFrom::Start(addr as u64))?;
Expand All @@ -204,7 +207,8 @@ impl<R: Register> Memory for FlatMemory<R> {
if size == 0 {
return Ok(());
}
let page_indices = get_page_indices(addr.to_u64(), size)?;
check_no_overflow(addr, size, self.memory_size as u64)?;
let page_indices = get_page_indices(addr, size);
set_dirty(self, &page_indices)?;
let slice = &mut self[addr as usize..(addr + size) as usize];
slice.copy_from_slice(value);
Expand All @@ -215,7 +219,8 @@ impl<R: Register> Memory for FlatMemory<R> {
if size == 0 {
return Ok(());
}
let page_indices = get_page_indices(addr.to_u64(), size)?;
check_no_overflow(addr, size, self.memory_size as u64)?;
let page_indices = get_page_indices(addr, size);
set_dirty(self, &page_indices)?;
memset(&mut self[addr as usize..(addr + size) as usize], value);
Ok(())
Expand Down
21 changes: 12 additions & 9 deletions src/memory/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub mod wxorx;

pub use ckb_vm_definitions::{
memory::{FLAG_DIRTY, FLAG_EXECUTABLE, FLAG_FREEZED, FLAG_WRITABLE, FLAG_WXORX_BIT},
MEMORY_FRAME_PAGE_SHIFTS, RISCV_MAX_MEMORY, RISCV_PAGE_SHIFTS,
DEFAULT_MEMORY_SIZE, MEMORY_FRAME_PAGE_SHIFTS, RISCV_PAGE_SHIFTS,
};

#[inline(always)]
Expand Down Expand Up @@ -100,18 +100,21 @@ pub fn fill_page_data<M: Memory>(
Ok(())
}

// `size` should be none zero u64
pub fn get_page_indices(addr: u64, size: u64) -> Result<(u64, u64), Error> {
pub fn check_no_overflow(addr: u64, size: u64, memory_size: u64) -> Result<(), Error> {
let (addr_end, overflowed) = addr.overflowing_add(size);
if overflowed {
return Err(Error::MemOutOfBound);
}
if addr_end > RISCV_MAX_MEMORY as u64 {
return Err(Error::MemOutOfBound);
if overflowed || addr_end > memory_size {
Err(Error::MemOutOfBound)
} else {
Ok(())
}
}

// `size` should be none zero u64
pub fn get_page_indices(addr: u64, size: u64) -> (u64, u64) {
let addr_end = addr.wrapping_add(size);
let page = addr >> RISCV_PAGE_SHIFTS;
let page_end = (addr_end - 1) >> RISCV_PAGE_SHIFTS;
Ok((page, page_end))
(page, page_end)
}

pub fn check_permission<M: Memory>(
Expand Down
5 changes: 2 additions & 3 deletions src/memory/sparse.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::super::{Error, Register, RISCV_MAX_MEMORY, RISCV_PAGESIZE, RISCV_PAGE_SHIFTS};
use super::super::{Error, Register, DEFAULT_MEMORY_SIZE, RISCV_PAGESIZE, RISCV_PAGE_SHIFTS};
use super::{fill_page_data, memset, round_page_down, Memory, Page, FLAG_DIRTY};

use bytes::Bytes;
Expand Down Expand Up @@ -67,7 +67,6 @@ impl<R: Register> SparseMemory<R> {
}

pub fn new_with_memory(memory_size: usize) -> Self {
assert!(memory_size <= RISCV_MAX_MEMORY);
assert!(memory_size % RISCV_PAGESIZE == 0);
Self {
indices: vec![INVALID_PAGE_INDEX; memory_size / RISCV_PAGESIZE],
Expand All @@ -83,7 +82,7 @@ impl<R: Register> SparseMemory<R> {

impl<R: Register> Default for SparseMemory<R> {
fn default() -> Self {
Self::new_with_memory(RISCV_MAX_MEMORY)
Self::new_with_memory(DEFAULT_MEMORY_SIZE)
}
}

Expand Down
28 changes: 18 additions & 10 deletions src/memory/wxorx.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::super::{Error, Register, RISCV_PAGESIZE};
use super::{
check_permission, get_page_indices, round_page_down, round_page_up, Memory, FLAG_EXECUTABLE,
FLAG_FREEZED, FLAG_WRITABLE,
check_no_overflow, check_permission, get_page_indices, round_page_down, round_page_up, Memory,
FLAG_EXECUTABLE, FLAG_FREEZED, FLAG_WRITABLE,
};

use bytes::Bytes;
Expand Down Expand Up @@ -80,13 +80,15 @@ impl<M: Memory> Memory for WXorXMemory<M> {
}

fn execute_load16(&mut self, addr: u64) -> Result<u16, Error> {
let page_indices = get_page_indices(addr, 2)?;
check_no_overflow(addr, 2, self.memory_size() as u64)?;
let page_indices = get_page_indices(addr, 2);
check_permission(self, &page_indices, FLAG_EXECUTABLE)?;
self.inner.execute_load16(addr)
}

fn execute_load32(&mut self, addr: u64) -> Result<u32, Error> {
let page_indices = get_page_indices(addr, 4)?;
check_no_overflow(addr, 4, self.memory_size() as u64)?;
let page_indices = get_page_indices(addr, 4);
check_permission(self, &page_indices, FLAG_EXECUTABLE)?;
self.inner.execute_load32(addr)
}
Expand All @@ -108,25 +110,29 @@ impl<M: Memory> Memory for WXorXMemory<M> {
}

fn store8(&mut self, addr: &Self::REG, value: &Self::REG) -> Result<(), Error> {
let page_indices = get_page_indices(addr.to_u64(), 1)?;
check_no_overflow(addr.to_u64(), 1, self.memory_size() as u64)?;
let page_indices = get_page_indices(addr.to_u64(), 1);
check_permission(self, &page_indices, FLAG_WRITABLE)?;
self.inner.store8(addr, value)
}

fn store16(&mut self, addr: &Self::REG, value: &Self::REG) -> Result<(), Error> {
let page_indices = get_page_indices(addr.to_u64(), 2)?;
check_no_overflow(addr.to_u64(), 2, self.memory_size() as u64)?;
let page_indices = get_page_indices(addr.to_u64(), 2);
check_permission(self, &page_indices, FLAG_WRITABLE)?;
self.inner.store16(addr, value)
}

fn store32(&mut self, addr: &Self::REG, value: &Self::REG) -> Result<(), Error> {
let page_indices = get_page_indices(addr.to_u64(), 4)?;
check_no_overflow(addr.to_u64(), 4, self.memory_size() as u64)?;
let page_indices = get_page_indices(addr.to_u64(), 4);
check_permission(self, &page_indices, FLAG_WRITABLE)?;
self.inner.store32(addr, value)
}

fn store64(&mut self, addr: &Self::REG, value: &Self::REG) -> Result<(), Error> {
let page_indices = get_page_indices(addr.to_u64(), 8)?;
check_no_overflow(addr.to_u64(), 8, self.memory_size() as u64)?;
let page_indices = get_page_indices(addr.to_u64(), 8);
check_permission(self, &page_indices, FLAG_WRITABLE)?;
self.inner.store64(addr, value)
}
Expand All @@ -135,7 +141,8 @@ impl<M: Memory> Memory for WXorXMemory<M> {
if value.is_empty() {
return Ok(());
}
let page_indices = get_page_indices(addr, value.len() as u64)?;
check_no_overflow(addr.to_u64(), value.len() as u64, self.memory_size() as u64)?;
let page_indices = get_page_indices(addr, value.len() as u64);
check_permission(self, &page_indices, FLAG_WRITABLE)?;
self.inner.store_bytes(addr, value)
}
Expand All @@ -144,7 +151,8 @@ impl<M: Memory> Memory for WXorXMemory<M> {
if size == 0 {
return Ok(());
}
let page_indices = get_page_indices(addr, size)?;
check_no_overflow(addr.to_u64(), size, self.memory_size() as u64)?;
let page_indices = get_page_indices(addr, size);
check_permission(self, &page_indices, FLAG_WRITABLE)?;
self.inner.store_byte(addr, size, value)
}
Expand Down
Loading

0 comments on commit 11679d8

Please sign in to comment.