diff --git a/crates/riscv-cpu/src/cpu.rs b/crates/riscv-cpu/src/cpu.rs index b1556d6..3208f71 100644 --- a/crates/riscv-cpu/src/cpu.rs +++ b/crates/riscv-cpu/src/cpu.rs @@ -1,4 +1,4 @@ -use std::sync::{Arc, RwLock, mpsc::Receiver}; +use std::sync::{mpsc::Receiver, Arc, RwLock}; pub use super::mmu::Memory; use super::mmu::{AddressingMode, Mmu}; @@ -58,9 +58,9 @@ pub enum TickResult { Ok, ExitThread(u64), PauseEmulation(Receiver<([i64; 8], Option<(Vec, u64)>)>), + CpuTrap(Trap), } - /// Emulates a RISC-V CPU core pub struct Cpu { clock: u64, @@ -343,7 +343,6 @@ impl Cpu { /// Runs program one cycle. Fetch, decode, and execution are completed in a cycle so far. pub fn tick(&mut self) -> TickResult { - let instruction_address = self.pc; match self.tick_operate() { Ok(()) => {} Err(Trap { @@ -358,7 +357,7 @@ impl Cpu { }) => { return TickResult::ExitThread(self.read_register(10) as u64); } - Err(e) => self.handle_exception(e, instruction_address), + Err(e) => return TickResult::CpuTrap(e), } self.mmu.tick(&mut self.csr[CSR_MIP_ADDRESS as usize]); self.handle_interrupt(self.pc); @@ -781,7 +780,7 @@ impl Cpu { // println!("Fetching word from {:08x}...", self.pc); self.mmu.fetch_word(self.pc).map_err(|e| { self.pc = self.pc.wrapping_add(4); // @TODO: What if instruction is compressed? - // println!("Fetch error: {:x?}", e); + // println!("Fetch error: {:x?}", e); e }) } diff --git a/crates/riscv-cpu/src/memory.rs b/crates/riscv-cpu/src/memory.rs index 1ce7bce..f74ea31 100644 --- a/crates/riscv-cpu/src/memory.rs +++ b/crates/riscv-cpu/src/memory.rs @@ -1,171 +1,170 @@ /// Emulates main memory. pub struct Memory { - /// Memory content - data: Vec + /// Memory content + data: Vec, } impl Memory { - /// Creates a new `Memory` - pub fn new() -> Self { - Memory { - data: vec![] - } - } + /// Creates a new `Memory` + pub fn new() -> Self { + Memory { data: vec![] } + } - /// Initializes memory content. - /// This method is expected to be called only once. - /// - /// # Arguments - /// * `capacity` - pub fn init(&mut self, capacity: u64) { - for _i in 0..((capacity + 7) / 8) { - self.data.push(0); - } - } - - /// Reads a byte from memory. - /// - /// # Arguments - /// * `address` - pub fn read_byte(&self, address: u64) -> u8 { - let index = (address >> 3) as usize; - let pos = (address % 8) * 8; - (self.data[index] >> pos) as u8 - } + /// Initializes memory content. + /// This method is expected to be called only once. + /// + /// # Arguments + /// * `capacity` + pub fn init(&mut self, capacity: u64) { + for _i in 0..((capacity + 7) / 8) { + self.data.push(0); + } + } - /// Reads two bytes from memory. - /// - /// # Arguments - /// * `address` - pub fn read_halfword(&self, address: u64) -> u16 { - if (address % 2) == 0 { - let index = (address >> 3) as usize; - let pos = (address % 8) * 8; - (self.data[index] >> pos) as u16 - } else { - self.read_bytes(address, 2) as u16 - } - } + /// Reads a byte from memory. + /// + /// # Arguments + /// * `address` + pub fn read_byte(&self, address: u64) -> u8 { + let index = (address >> 3) as usize; + let pos = (address % 8) * 8; + (self.data[index] >> pos) as u8 + } - /// Reads four bytes from memory. - /// - /// # Arguments - /// * `address` - pub fn read_word(&self, address: u64) -> u32 { - if (address % 4) == 0 { - let index = (address >> 3) as usize; - let pos = (address % 8) * 8; - (self.data[index] >> pos) as u32 - } else { - self.read_bytes(address, 4) as u32 - } - } + /// Reads two bytes from memory. + /// + /// # Arguments + /// * `address` + pub fn read_halfword(&self, address: u64) -> u16 { + if (address % 2) == 0 { + let index = (address >> 3) as usize; + let pos = (address % 8) * 8; + (self.data[index] >> pos) as u16 + } else { + self.read_bytes(address, 2) as u16 + } + } - /// Reads eight bytes from memory. - /// - /// # Arguments - /// * `address` - pub fn read_doubleword(&self, address: u64) -> u64 { - if (address % 8) == 0 { - let index = (address >> 3) as usize; - self.data[index] - } else if (address % 4) == 0 { - (self.read_word(address) as u64) | ((self.read_word(address.wrapping_add(4)) as u64) << 4) - } else { - self.read_bytes(address, 8) - } - } + /// Reads four bytes from memory. + /// + /// # Arguments + /// * `address` + pub fn read_word(&self, address: u64) -> u32 { + if (address % 4) == 0 { + let index = (address >> 3) as usize; + let pos = (address % 8) * 8; + (self.data[index] >> pos) as u32 + } else { + self.read_bytes(address, 4) as u32 + } + } - /// Reads multiple bytes from memory. - /// - /// # Arguments - /// * `address` - /// * `width` up to eight - pub fn read_bytes(&self, address: u64, width: u64) -> u64 { - let mut data = 0; - for i in 0..width { - data |= (self.read_byte(address.wrapping_add(i)) as u64) << (i * 8); - } - data - } + /// Reads eight bytes from memory. + /// + /// # Arguments + /// * `address` + pub fn read_doubleword(&self, address: u64) -> u64 { + if (address % 8) == 0 { + let index = (address >> 3) as usize; + self.data[index] + } else if (address % 4) == 0 { + (self.read_word(address) as u64) + | ((self.read_word(address.wrapping_add(4)) as u64) << 4) + } else { + self.read_bytes(address, 8) + } + } - /// Writes a byte to memory. - /// - /// # Arguments - /// * `address` - /// * `value` - pub fn write_byte(&mut self, address: u64, value: u8) { - let index = (address >> 3) as usize; - let pos = (address % 8) * 8; - self.data[index] = (self.data[index] & !(0xff << pos)) | ((value as u64) << pos); - } + /// Reads multiple bytes from memory. + /// + /// # Arguments + /// * `address` + /// * `width` up to eight + pub fn read_bytes(&self, address: u64, width: u64) -> u64 { + let mut data = 0; + for i in 0..width { + data |= (self.read_byte(address.wrapping_add(i)) as u64) << (i * 8); + } + data + } - /// Writes two bytes to memory. - /// - /// # Arguments - /// * `address` - /// * `value` - pub fn write_halfword(&mut self, address: u64, value: u16) { - if (address % 2) == 0 { - let index = (address >> 3) as usize; - let pos = (address % 8) * 8; - self.data[index] = (self.data[index] & !(0xffff << pos)) | ((value as u64) << pos); - } else { - self.write_bytes(address, value as u64, 2); - } - } + /// Writes a byte to memory. + /// + /// # Arguments + /// * `address` + /// * `value` + pub fn write_byte(&mut self, address: u64, value: u8) { + let index = (address >> 3) as usize; + let pos = (address % 8) * 8; + self.data[index] = (self.data[index] & !(0xff << pos)) | ((value as u64) << pos); + } - /// Writes four bytes to memory. - /// - /// # Arguments - /// * `address` - /// * `value` - pub fn write_word(&mut self, address: u64, value: u32) { - if (address % 4) == 0 { - let index = (address >> 3) as usize; - let pos = (address % 8) * 8; - self.data[index] = (self.data[index] & !(0xffffffff << pos)) | ((value as u64) << pos); - } else { - self.write_bytes(address, value as u64, 4); - } - } + /// Writes two bytes to memory. + /// + /// # Arguments + /// * `address` + /// * `value` + pub fn write_halfword(&mut self, address: u64, value: u16) { + if (address % 2) == 0 { + let index = (address >> 3) as usize; + let pos = (address % 8) * 8; + self.data[index] = (self.data[index] & !(0xffff << pos)) | ((value as u64) << pos); + } else { + self.write_bytes(address, value as u64, 2); + } + } - /// Writes eight bytes to memory. - /// - /// # Arguments - /// * `address` - /// * `value` - pub fn write_doubleword(&mut self, address: u64, value: u64) { - if (address % 8) == 0 { - let index = (address >> 3) as usize; - self.data[index] = value; - } else if (address % 4) == 0 { - self.write_word(address, (value & 0xffffffff) as u32); - self.write_word(address.wrapping_add(4), (value >> 32) as u32); - } else { - self.write_bytes(address, value, 8); - } - } + /// Writes four bytes to memory. + /// + /// # Arguments + /// * `address` + /// * `value` + pub fn write_word(&mut self, address: u64, value: u32) { + if (address % 4) == 0 { + let index = (address >> 3) as usize; + let pos = (address % 8) * 8; + self.data[index] = (self.data[index] & !(0xffffffff << pos)) | ((value as u64) << pos); + } else { + self.write_bytes(address, value as u64, 4); + } + } - /// Write multiple bytes to memory. - /// - /// # Arguments - /// * `address` - /// * `value` - /// * `width` up to eight - pub fn write_bytes(&mut self, address: u64, value: u64, width: u64) { - for i in 0..width { - self.write_byte(address.wrapping_add(i), (value >> (i * 8)) as u8); - } - } + /// Writes eight bytes to memory. + /// + /// # Arguments + /// * `address` + /// * `value` + pub fn write_doubleword(&mut self, address: u64, value: u64) { + if (address % 8) == 0 { + let index = (address >> 3) as usize; + self.data[index] = value; + } else if (address % 4) == 0 { + self.write_word(address, (value & 0xffffffff) as u32); + self.write_word(address.wrapping_add(4), (value >> 32) as u32); + } else { + self.write_bytes(address, value, 8); + } + } - /// Check if the address is valid memory address - /// - /// # Arguments - /// * `address` - pub fn validate_address(&self, address: u64) -> bool { - (address as usize) < self.data.len() - } + /// Write multiple bytes to memory. + /// + /// # Arguments + /// * `address` + /// * `value` + /// * `width` up to eight + pub fn write_bytes(&mut self, address: u64, value: u64, width: u64) { + for i in 0..width { + self.write_byte(address.wrapping_add(i), (value >> (i * 8)) as u8); + } + } + + /// Check if the address is valid memory address + /// + /// # Arguments + /// * `address` + pub fn validate_address(&self, address: u64) -> bool { + (address as usize) < self.data.len() + } } impl Default for Memory { diff --git a/src/xous.rs b/src/xous.rs index 7897daf..540d03f 100644 --- a/src/xous.rs +++ b/src/xous.rs @@ -75,20 +75,33 @@ struct Memory { satp: u32, connections: HashMap>, memory_cmd: Sender, + turbo: bool, } struct Worker { cpu: riscv_cpu::Cpu, cmd: Sender, tid: i64, + memory: Arc>, } impl Worker { - fn new(cpu: riscv_cpu::Cpu, cmd: Sender, tid: i64) -> Self { - Self { cpu, cmd, tid } + fn new( + cpu: riscv_cpu::Cpu, + cmd: Sender, + tid: i64, + memory: Arc>, + ) -> Self { + Self { + cpu, + cmd, + tid, + memory, + } } fn run(&mut self) { use riscv_cpu::cpu::TickResult; + // println!("Running CPU thread {}", self.tid); loop { match self.cpu.tick() { TickResult::PauseEmulation(e) => { @@ -110,7 +123,21 @@ impl Worker { .send(MemoryCommand::ExitThread(self.tid as u32, val as u32)) .unwrap(); // println!("Thread {} exited", self.tid); - break; + return; + } + TickResult::CpuTrap(trap) => { + self.memory.read().unwrap().print_mmu(); + // called `Result::unwrap()` on an `Err` value: "Valid bit is 0, or read is 0 and write is 1 at 40002fec: 000802e6" + println!( + "CPU trap at PC {:08x}, exiting thread {}: {:x?}", + self.cpu.read_pc(), + self.tid, + trap + ); + self.cmd + .send(MemoryCommand::ExitThread(self.tid as u32, 1)) + .unwrap(); + return; } TickResult::Ok => {} } @@ -124,21 +151,21 @@ struct WorkerHandle { impl Memory { pub fn new(base: u32, size: usize) -> (Self, Receiver) { - let mut data = HashMap::new(); + let mut backing = HashMap::new(); let mut free_pages = BTreeSet::new(); let mut allocated_pages = BTreeSet::new(); - for page in (base..(base + size as u32)).step_by(4096) { - data.insert(page as usize, [0; 4096]); - free_pages.insert(page as usize); + for phys in (base..(base + size as u32)).step_by(4096) { + backing.insert(phys as usize, [0; 4096]); + free_pages.insert(phys as usize); } // Remove the l0 page table - free_pages.remove(&(MEMORY_BASE as usize + 4096)); - allocated_pages.insert(MEMORY_BASE as usize + 4096); + assert!(free_pages.remove(&(MEMORY_BASE as usize + 4096))); + assert!(allocated_pages.insert(MEMORY_BASE as usize + 4096)); let (memory_cmd, memory_cmd_rx) = std::sync::mpsc::channel(); ( Self { base, - data, + data: backing, allocated_pages, free_pages, l1_pt: MEMORY_BASE + 4096, @@ -148,26 +175,74 @@ impl Memory { allocation_previous: 0x4000_0000, connections: HashMap::new(), memory_cmd, + turbo: false, }, memory_cmd_rx, ) } - fn allocate_page(&mut self) -> u32 { - let page = self.free_pages.pop_first().expect("out of memory"); - self.allocated_pages.insert(page); - page as u32 + pub fn turbo(&mut self) { + self.turbo = true; } - fn free_page(&mut self, page: u32) -> Result<(), ()> { - let phys = self.virt_to_phys(page).ok_or(())?; - if !self.allocated_pages.remove(&(phys as usize)) { - panic!("Page wasn't allocated!"); - } - self.free_pages.insert(phys as usize); + pub fn normal(&mut self) { + self.turbo = false; + self.memory_ck(); + } - let vpn1 = ((page >> 22) & ((1 << 10) - 1)) as usize * 4; - let vpn0 = ((page >> 12) & ((1 << 10) - 1)) as usize * 4; + fn memory_ck(&self) { + // if self.turbo { + // return; + // } + // let mut seen_pages = HashMap::new(); + // seen_pages.insert(self.l1_pt, 0); + // for vpn1 in 0..1024 { + // let l1_entry = self.read_u32(self.l1_pt as u64 + vpn1 * 4); + // if l1_entry & MMUFLAG_VALID == 0 { + // continue; + // } + + // let superpage_addr = vpn1 as u32 * (1 << 22); + + // for vpn0 in 0..1024 { + // let l0_entry = self.read_u32((((l1_entry >> 10) << 12) as u64) + vpn0 as u64 * 4); + // if l0_entry & 0x1 == 0 { + // continue; + // } + // let phys = (l0_entry >> 10) << 12; + // let current = superpage_addr + vpn0 as u32 * (1 << 12); + // if let Some(existing) = seen_pages.get(&phys) { + // self.print_mmu(); + // panic!( + // "Error! Page {:08x} is mapped twice! Once at {:08x} and once at {:08x}", + // phys, existing, current, + // ); + // } + // seen_pages.insert(phys, current); + // } + // } + } + + fn allocate_page(&mut self) -> u32 { + self.memory_ck(); + let phys = self.free_pages.pop_first().expect("out of memory"); + assert!(self.allocated_pages.insert(phys)); + + // The root (l1) pagetable is defined to be mapped into our virtual + // address space at this address. + if phys == 0 { + panic!("Attempt to allocate zero page"); + } + self.memory_ck(); + phys as u32 + } + + fn free_page(&mut self, virt: u32) -> Result<(), ()> { + self.memory_ck(); + let phys = self.virt_to_phys(virt).ok_or(())?; + + let vpn1 = ((virt >> 22) & ((1 << 10) - 1)) as usize * 4; + let vpn0 = ((virt >> 12) & ((1 << 10) - 1)) as usize * 4; // The root (l1) pagetable is defined to be mapped into our virtual // address space at this address. @@ -178,13 +253,25 @@ impl Memory { return Ok(()); } + // println!("Deallocating page {:08x} @ {:08x}", virt, phys); + if !self.allocated_pages.remove(&(phys as usize)) { + // self.print_mmu(); + panic!( + "Page {:08x} @ {:08x} wasn't in the list of allocated pages!", + phys, virt + ); + } + assert!(self.free_pages.insert(phys as usize)); + let l0_pt_phys = ((l1_pt_entry >> 10) << 12) + vpn0 as u32; self.write_u32(l0_pt_phys as u64, 0); + self.memory_ck(); Ok(()) } fn allocate_virt_region(&mut self, size: usize) -> Option { + self.memory_ck(); let mut start = self.allocation_previous; // Find a free region that will fit this page. 'outer: loop { @@ -199,18 +286,22 @@ impl Memory { // Allocate the region for page in (start..(start + size as u32)).step_by(4096) { self.ensure_page(page); + // println!( + // "Allocated {:08x} @ {:08x}", + // page, + // self.virt_to_phys(page).unwrap() + // ); } self.allocation_previous = start + size as u32 + 4096; + self.memory_ck(); Some(start) } fn ensure_page(&mut self, address: u32) { + self.memory_ck(); let vpn1 = ((address >> 22) & ((1 << 10) - 1)) as usize * 4; let vpn0 = ((address >> 12) & ((1 << 10) - 1)) as usize * 4; - // The root (l1) pagetable is defined to be mapped into our virtual - // address space at this address. - // If the level 1 pagetable doesn't exist, then this address is invalid let mut l1_pt_entry = self.read_u32(self.l1_pt as u64 + vpn1 as u64); if l1_pt_entry & MMUFLAG_VALID == 0 { @@ -240,6 +331,52 @@ impl Memory { // Map the level 0 pagetable into the level 1 pagetable self.write_u32(l0_pt_phys as u64, l0_pt_entry); } + assert!(self + .allocated_pages + .contains(&(((l0_pt_entry >> 10) << 12) as usize))); + assert!(!self + .free_pages + .contains(&(((l0_pt_entry >> 10) << 12) as usize))); + self.memory_ck(); + } + + fn remove_memory_flags(&mut self, virt: u32, new_flags: u32) { + self.memory_ck(); + // Ensure they're only adjusting legal flags + assert!(new_flags & !(MMUFLAG_READABLE | MMUFLAG_WRITABLE | MMUFLAG_EXECUTABLE) == 0); + + let vpn1 = ((virt >> 22) & ((1 << 10) - 1)) as usize * 4; + let vpn0 = ((virt >> 12) & ((1 << 10) - 1)) as usize * 4; + + // The root (l1) pagetable is defined to be mapped into our virtual + // address space at this address. + let l1_pt_entry = self.read_u32(self.l1_pt as u64 + vpn1 as u64); + + // If the level 1 pagetable doesn't exist, then this address is invalid + if l1_pt_entry & MMUFLAG_VALID == 0 { + return; + } + + let l0_pt_entry = self.read_u32((((l1_pt_entry >> 10) << 12) + vpn0 as u32) as u64); + + // Ensure the entry hasn't already been mapped. + if l0_pt_entry & MMUFLAG_VALID == 0 { + return; + } + + let old_flags = l0_pt_entry & 0xff; + + // Ensure we're not adding flags + assert!(old_flags | new_flags == old_flags); + + let l0_pt_entry = + (l0_pt_entry & !(MMUFLAG_READABLE | MMUFLAG_WRITABLE | MMUFLAG_EXECUTABLE)) | new_flags; + + self.write_u32( + (((l1_pt_entry >> 10) << 12) + vpn0 as u32) as u64, + l0_pt_entry, + ); + self.memory_ck(); } fn write_bytes(&mut self, data: &[u8], start: u32) { @@ -254,35 +391,35 @@ impl Memory { #[allow(dead_code)] pub fn print_mmu(&self) { + use crate::xous::definitions::memoryflags::MemoryFlags; + println!(); println!("Memory Map:"); - for vpn1 in (0..4096).step_by(4) { - let l1_entry = self.read_u32(self.l1_pt as u64 + vpn1); + for vpn1 in 0..1024 { + let l1_entry = self.read_u32(self.l1_pt as u64 + vpn1 * 4); if l1_entry & MMUFLAG_VALID == 0 { continue; } let superpage_addr = vpn1 as u32 * (1 << 22); println!( - " {:4} Superpage for {:08x} @ {:08x} (flags: {:?})", + " {:4} Superpage for {:08x} @ {:08x} (flags: {})", vpn1, superpage_addr, (l1_entry >> 10) << 12, - // MMUFlags::from_bits(l1_entry & 0xff).unwrap() - l1_entry & 0xff, + MemoryFlags::from_bits(l1_entry as usize & 0xff).unwrap(), ); - for vpn0 in (0..4096).step_by(4) { - let l0_entry = self.read_u32((((l1_entry >> 10) << 12) as u64) + vpn0 as u64); - if l0_entry & 0x7 == 0 { + for vpn0 in 0..1024 { + let l0_entry = self.read_u32((((l1_entry >> 10) << 12) as u64) + vpn0 as u64 * 4); + if l0_entry & 0x1 == 0 { continue; } let page_addr = vpn0 as u32 * (1 << 12); println!( - " {:4} {:08x} -> {:08x} (flags: {:?})", + " {:4} {:08x} -> {:08x} (flags: {})", vpn0, superpage_addr + page_addr, (l0_entry >> 10) << 12, - // MMUFlags::from_bits(l0_entry & 0xff).unwrap() - l0_entry & 0xff, + MemoryFlags::from_bits(l0_entry as usize & 0xff).unwrap() ); } } @@ -424,7 +561,7 @@ impl riscv_cpu::cpu::Memory for Memory { fn syscall(&mut self, args: [i64; 8]) -> SyscallResult { let syscall: Syscall = args.into(); - // print!("Syscall: "); + // println!("Syscall {:?}", SyscallNumber::from(args[0])); match syscall { Syscall::IncreaseHeap(bytes, _flags) => { // println!("IncreaseHeap({} bytes, flags: {:02x})", bytes, _flags); @@ -458,7 +595,7 @@ impl riscv_cpu::cpu::Memory for Memory { } Syscall::MapMemory(phys, virt, size, _flags) => { - // println!( + // print!( // "MapMemory(phys: {:08x}, virt: {:08x}, bytes: {}, flags: {:02x})", // phys, virt, size, _flags // ); @@ -471,6 +608,7 @@ impl riscv_cpu::cpu::Memory for Memory { let region = self .allocate_virt_region(size as usize) .expect("out of memory"); + // println!(" -> {:08x}", region); [ SyscallResultNumber::MemoryRange as i64, region as i64, @@ -649,7 +787,10 @@ impl riscv_cpu::cpu::Memory for Memory { } } } - Syscall::UpdateMemoryFlags(_address, _range, _value) => { + Syscall::UpdateMemoryFlags(address, range, value) => { + for addr in address..(address + range) { + self.remove_memory_flags(addr as u32, value as u32); + } [SyscallResultNumber::Ok as i64, 0, 0, 0, 0, 0, 0, 0].into() } Syscall::Yield => [SyscallResultNumber::Ok as i64, 0, 0, 0, 0, 0, 0, 0].into(), @@ -722,7 +863,7 @@ pub struct Machine { satp: u64, memory_cmd_sender: Sender, memory_cmd: Receiver, - thread_id: AtomicI64, + thread_id_counter: AtomicI64, } impl Machine { @@ -737,7 +878,7 @@ impl Machine { satp: 0, memory_cmd, memory_cmd_sender, - thread_id: AtomicI64::new(1), + thread_id_counter: AtomicI64::new(1), }; machine.load_program(program)?; @@ -760,6 +901,7 @@ impl Machine { } let mut memory_writer = self.memory.write().unwrap(); + memory_writer.turbo(); for sh in elf.section_headers { if sh.sh_flags as u32 & goblin::elf::section_header::SHF_ALLOC == 0 { continue; @@ -776,7 +918,8 @@ impl Machine { } } - memory_writer.print_mmu(); + // memory_writer.print_mmu(); + memory_writer.normal(); // TODO: Get memory permissions correct @@ -802,10 +945,11 @@ impl Machine { cpu.execute_opcode(0x10200073).map_err(LoadError::CpuTrap)?; // Update the stack pointer - cpu.write_register(2, 0xc002_0000 - 4); + cpu.write_register(2, 0xc002_0000 - 16); let cmd = self.memory_cmd_sender.clone(); - let joiner = std::thread::spawn(move || Worker::new(cpu, cmd, 0).run()); + let memory = self.memory.clone(); + let joiner = std::thread::spawn(move || Worker::new(cpu, cmd, 0, memory).run()); self.workers.push(WorkerHandle { joiner }); self.satp = satp; @@ -868,7 +1012,7 @@ impl Machine { MemoryCommand::CreateThread( entry_point, stack_pointer, - _stack_length, + stack_length, argument_1, argument_2, argument_3, @@ -894,16 +1038,19 @@ impl Machine { cpu.execute_opcode(0x10200073).map_err(LoadError::CpuTrap)?; // Update the stack pointer - cpu.write_register(2, stack_pointer as i64 - 16); + cpu.write_register(2, (stack_pointer + stack_length) as i64 - 16); cpu.write_register(10, argument_1 as i64); cpu.write_register(11, argument_2 as i64); cpu.write_register(12, argument_3 as i64); cpu.write_register(13, argument_4 as i64); let cmd = self.memory_cmd_sender.clone(); - let tid = self.thread_id.fetch_add(1, Ordering::SeqCst); + let tid = self.thread_id_counter.fetch_add(1, Ordering::SeqCst); + let memory = self.memory.clone(); join_tx - .send(std::thread::spawn(move || Worker::new(cpu, cmd, tid).run())) + .send(std::thread::spawn(move || { + Worker::new(cpu, cmd, tid, memory).run() + })) .unwrap(); tx.send(tid).unwrap(); } diff --git a/src/xous/definitions.rs b/src/xous/definitions.rs index 1bae439..ae37d21 100644 --- a/src/xous/definitions.rs +++ b/src/xous/definitions.rs @@ -1,5 +1,7 @@ #![allow(dead_code)] +pub mod memoryflags; + #[derive(Debug, Copy, Clone)] pub enum Message { MutableBorrow = 0,