diff --git a/src/memory/memory_set.rs b/src/memory/memory_set.rs index e47b991..a6e510b 100644 --- a/src/memory/memory_set.rs +++ b/src/memory/memory_set.rs @@ -6,15 +6,48 @@ use core::fmt::{Debug, Formatter, Error}; /// 对应ucore中 `vma_struct` #[derive(Debug, Eq, PartialEq)] pub struct MemoryArea { - pub start_addr: VirtAddr, - pub end_addr: VirtAddr, - pub phys_start_addr: Option, - pub flags: u32, - pub name: &'static str, - pub mapped: bool, + start_addr: VirtAddr, + end_addr: VirtAddr, + phys_start_addr: Option, + flags: u64, + name: &'static str, + mapped: bool, } impl MemoryArea { + pub fn new(start_addr: VirtAddr, end_addr: VirtAddr, flags: EntryFlags, name: &'static str) -> Self { + assert!(start_addr <= end_addr, "invalid memory area"); + MemoryArea { + start_addr, + end_addr, + phys_start_addr: None, + flags: flags.bits(), + name, + mapped: false, + } + } + pub fn new_identity(start_addr: VirtAddr, end_addr: VirtAddr, flags: EntryFlags, name: &'static str) -> Self { + assert!(start_addr <= end_addr, "invalid memory area"); + MemoryArea { + start_addr, + end_addr, + phys_start_addr: Some(PhysAddr(start_addr as u64)), + flags: flags.bits(), + name, + mapped: false, + } + } + pub fn new_kernel(start_addr: VirtAddr, end_addr: VirtAddr, flags: EntryFlags, name: &'static str) -> Self { + assert!(start_addr <= end_addr, "invalid memory area"); + MemoryArea { + start_addr, + end_addr, + phys_start_addr: Some(PhysAddr::from_kernel_virtual(start_addr)), + flags: flags.bits(), + name, + mapped: false, + } + } pub fn contains(&self, addr: VirtAddr) -> bool { addr >= self.start_addr && addr < self.end_addr } @@ -54,11 +87,6 @@ impl MemorySet { self.areas.iter().find(|area| area.contains(addr)) } pub fn push(&mut self, area: MemoryArea) { - assert!(area.start_addr <= area.end_addr, "invalid memory area"); - if let Some(phys_addr) = area.phys_start_addr { - assert_eq!(area.start_addr % PAGE_SIZE, phys_addr.get() % PAGE_SIZE, - "virtual & physical start address must have same page offset"); - } assert!(self.areas.iter() .find(|other| area.is_overlap_with(other)) .is_none(), "memory area overlap"); diff --git a/src/memory/mod.rs b/src/memory/mod.rs index e80894b..3770e7d 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -71,30 +71,9 @@ pub fn remap_the_kernel(boot_info: BootInformation) -> (ActivePageTable, Stack) let mut memory_set = MemorySet::from(boot_info.elf_sections_tag().unwrap()); use consts::{KERNEL_HEAP_OFFSET, KERNEL_HEAP_SIZE}; - memory_set.push(MemoryArea { - start_addr: 0xb8000, - end_addr: 0xb9000, - phys_start_addr: Some(PhysAddr(0xb8000)), - flags: EntryFlags::WRITABLE.bits() as u32, - name: "VGA", - mapped: false, - }); - memory_set.push(MemoryArea { - start_addr: boot_info.start_address(), - end_addr: boot_info.end_address(), - phys_start_addr: Some(PhysAddr(boot_info.start_address() as u64)), - flags: EntryFlags::PRESENT.bits() as u32, - name: "multiboot", - mapped: false, - }); - memory_set.push(MemoryArea { - start_addr: KERNEL_HEAP_OFFSET, - end_addr: KERNEL_HEAP_OFFSET + KERNEL_HEAP_SIZE, - phys_start_addr: None, - flags: EntryFlags::WRITABLE.bits() as u32, - name: "kernel_heap", - mapped: false, - }); + memory_set.push(MemoryArea::new_identity(0xb8000, 0xb9000, EntryFlags::WRITABLE, "VGA")); + memory_set.push(MemoryArea::new_identity(boot_info.start_address(), boot_info.end_address(), EntryFlags::PRESENT, "multiboot")); + memory_set.push(MemoryArea::new(KERNEL_HEAP_OFFSET, KERNEL_HEAP_OFFSET + KERNEL_HEAP_SIZE, EntryFlags::WRITABLE, "kernel_heap")); let mut page_table = InactivePageTable::new(alloc_frame(), &mut active_table); active_table.with(&mut page_table, |pt| memory_set.map(pt)); @@ -136,29 +115,15 @@ impl From for MemorySet { impl From for MemoryArea { fn from(section: ElfSection) -> Self { use self::address::FromToVirtualAddress; - let start_addr = section.start_address() as usize; - let end_addr = section.end_address() as usize; + let mut start_addr = section.start_address() as usize; + let mut end_addr = section.end_address() as usize; assert_eq!(start_addr % PAGE_SIZE, 0, "sections need to be page aligned"); let name = unsafe { &*(section.name() as *const str) }; if start_addr < KERNEL_OFFSET { - MemoryArea { - start_addr: start_addr + KERNEL_OFFSET, - end_addr: end_addr + KERNEL_OFFSET, - phys_start_addr: Some(PhysAddr(section.start_address() as u64)), - flags: EntryFlags::from(section.flags()).bits() as u32, - name, - mapped: false, - } - } else { - MemoryArea { - start_addr, - end_addr, - phys_start_addr: Some(PhysAddr::from_kernel_virtual(start_addr)), - flags: EntryFlags::from(section.flags()).bits() as u32, - name, - mapped: false, - } + start_addr += KERNEL_OFFSET; + end_addr += KERNEL_OFFSET; } + MemoryArea::new_kernel(start_addr, end_addr, EntryFlags::from(section.flags()), name) } } diff --git a/src/process/process.rs b/src/process/process.rs index 6a86df5..23342c1 100644 --- a/src/process/process.rs +++ b/src/process/process.rs @@ -64,7 +64,10 @@ impl Process { let elf = ElfFile::new(slice).expect("failed to read elf"); // Make page table + use consts::{USER_STACK_OFFSET, USER_STACK_SIZE}; let mut memory_set = MemorySet::from(&elf); + memory_set.push(MemoryArea::new(USER_STACK_OFFSET, USER_STACK_OFFSET + USER_STACK_SIZE, + EntryFlags::WRITABLE | EntryFlags::NO_EXECUTE | EntryFlags::USER_ACCESSIBLE, "user_stack")); let page_table = mc.make_page_table(&mut memory_set); debug!("{:#x?}", memory_set); @@ -86,7 +89,7 @@ impl Process { // Allocate kernel stack and push trap frame let kstack = mc.alloc_stack(7).unwrap(); - let tf = TrapFrame::new_user_thread(entry_addr, kstack.top()); + let tf = TrapFrame::new_user_thread(entry_addr, USER_STACK_OFFSET + USER_STACK_SIZE); let rsp = kstack.push_at_top(tf); Process { @@ -112,14 +115,11 @@ impl<'a> From<&'a ElfFile<'a>> for MemorySet { ProgramHeader::Ph64(ph) => ph, _ => unimplemented!(), }; - set.push(MemoryArea { - start_addr: ph.virtual_addr as usize, - end_addr: (ph.virtual_addr + ph.mem_size) as usize, - phys_start_addr: None, - flags: EntryFlags::from(ph.flags).bits() as u32, - name: "", - mapped: false, - }); + set.push(MemoryArea::new( + ph.virtual_addr as usize, + (ph.virtual_addr + ph.mem_size) as usize, + EntryFlags::from(ph.flags), + "")); } set }