From 4c6f6c94b239c5bdee464456486d60d25a90235a Mon Sep 17 00:00:00 2001 From: ChenRuiwei <1982833213@qq.com> Date: Thu, 18 Jul 2024 11:41:34 +0800 Subject: [PATCH 01/10] refactor: a little --- Cargo.lock | 13 +++++++++++-- config/src/mm.rs | 2 +- driver/src/qemu/virtio_blk.rs | 5 ++--- driver/src/serial/uart8250.rs | 20 ++++++++++---------- kernel/src/syscall/fs.rs | 4 ++++ kernel/src/syscall/mod.rs | 3 ++- modules/memory/src/heap.rs | 7 ++++++- modules/vfs-core/src/file.rs | 1 - modules/vfs/src/fd_table.rs | 1 - user/src/bin/runtestcase.rs | 25 ++++++++++++------------- 10 files changed, 48 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8484b885..860bdeae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -226,7 +226,7 @@ dependencies = [ "spin", "sync", "systype", - "virtio-drivers", + "virtio-drivers 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -403,7 +403,7 @@ dependencies = [ "timer", "vfs", "vfs-core", - "virtio-drivers", + "virtio-drivers 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "xmas-elf", ] @@ -874,6 +874,15 @@ dependencies = [ "time", ] +[[package]] +name = "virtio-drivers" +version = "0.7.3" +dependencies = [ + "bitflags 2.6.0", + "log", + "zerocopy", +] + [[package]] name = "virtio-drivers" version = "0.7.3" diff --git a/config/src/mm.rs b/config/src/mm.rs index 24a3da34..ceb858d4 100644 --- a/config/src/mm.rs +++ b/config/src/mm.rs @@ -39,7 +39,7 @@ pub const PAGE_TABLE_LEVEL_NUM: usize = 3; /// Dynamic linked interpreter address range in user space pub const DL_INTERP_OFFSET: usize = 0x20_0000_0000; -pub const MAX_BUFFER_CACHE: usize = 0x100; +pub const MAX_BUFFER_CACHE: usize = 0x1000; pub const MAX_BUFFER_PAGES: usize = MAX_BUFFER_CACHE / MAX_BUFFERS_PER_PAGE; pub const MAX_BUFFERS_PER_PAGE: usize = PAGE_SIZE / BLOCK_SIZE; pub const BUFFER_NEED_CACHE_CNT: usize = 8; diff --git a/driver/src/qemu/virtio_blk.rs b/driver/src/qemu/virtio_blk.rs index a1010d09..2a14ddd9 100644 --- a/driver/src/qemu/virtio_blk.rs +++ b/driver/src/qemu/virtio_blk.rs @@ -65,7 +65,6 @@ impl VirtIOBlkDev { irq_no: usize, transport: MmioTransport, ) -> Option> { - // const VIRTIO0: usize = 0x10001000 + VIRT_RAM_OFFSET; match VirtIOBlk::::new(transport) { Ok(virtio_blk) => { let device = SpinNoIrqLock::new(virtio_blk); @@ -77,7 +76,7 @@ impl VirtIOBlkDev { name: "virtio-blk".to_string(), mmio_base, mmio_size, - irq_no: Some(irq_no), + irq_no: None, // TODO: Do not accept interrupt now. dtype: DeviceType::Block, }; let blk_dev = Arc::new(Self { @@ -111,6 +110,6 @@ impl BaseDeviceOps for VirtIOBlkDev { } fn handle_irq(&self) { - // todo!() + // TODO: } } diff --git a/driver/src/serial/uart8250.rs b/driver/src/serial/uart8250.rs index 525a29e9..f6e21137 100644 --- a/driver/src/serial/uart8250.rs +++ b/driver/src/serial/uart8250.rs @@ -56,7 +56,7 @@ bitflags! { #[derive(Debug)] pub struct Uart { /// UART MMIO base address - mmio_base: usize, + mmio_base_vaddr: usize, clock_frequency: u32, baud_rate: u32, reg_io_width: usize, @@ -71,7 +71,7 @@ impl Uart { /// base address really points to a serial port device. #[rustversion::attr(since(1.61), const)] pub unsafe fn new( - mmio_base: usize, + mmio_base_vaddr: usize, clock_frequency: usize, baud_rate: usize, reg_io_width: usize, @@ -79,7 +79,7 @@ impl Uart { is_snps: bool, ) -> Self { Self { - mmio_base, + mmio_base_vaddr, clock_frequency: clock_frequency as u32, baud_rate: baud_rate as u32, reg_io_width, @@ -111,7 +111,7 @@ impl Uart { } fn init_u8(&mut self) { - let reg = self.mmio_base as *mut u8; + let reg = self.mmio_base_vaddr as *mut u8; unsafe { // Disable Interrupt @@ -144,7 +144,7 @@ impl Uart { } fn init_u32(&mut self) { - let reg = self.mmio_base as *mut u32; + let reg = self.mmio_base_vaddr as *mut u32; unsafe { // Disable Interrupt @@ -180,14 +180,14 @@ impl Uart { } fn line_sts_u8(&self) -> LineStsFlags { - let ptr = self.mmio_base as *mut u8; + let ptr = self.mmio_base_vaddr as *mut u8; unsafe { LineStsFlags::from_bits_truncate(ptr.byte_add(LSR << self.reg_shift).read_volatile()) } } fn line_sts_u32(&self) -> LineStsFlags { - let ptr = self.mmio_base as *mut u32; + let ptr = self.mmio_base_vaddr as *mut u32; unsafe { LineStsFlags::from_bits_truncate( ptr.byte_add(LSR << self.reg_shift).read_volatile() as u8 @@ -197,7 +197,7 @@ impl Uart { /// Sends a byte on the serial port. pub fn send_u8(&mut self, c: u8) { - let ptr = self.mmio_base as *mut u8; + let ptr = self.mmio_base_vaddr as *mut u8; unsafe { match c { 8 | 0x7F => { @@ -220,7 +220,7 @@ impl Uart { } pub fn send_u32(&mut self, c: u8) { - let ptr = self.mmio_base as *mut u32; + let ptr = self.mmio_base_vaddr as *mut u32; unsafe { match c { 8 | 0x7F => { @@ -244,7 +244,7 @@ impl Uart { /// Receives a byte on the serial port. pub fn receive(&mut self) -> u8 { - let ptr = self.mmio_base as *mut u32; + let ptr = self.mmio_base_vaddr as *mut u32; unsafe { wait_for!(self.line_sts_u8().contains(LineStsFlags::INPUT_FULL)); if self.is_snps { diff --git a/kernel/src/syscall/fs.rs b/kernel/src/syscall/fs.rs index cb13d1e5..8b0cfa34 100644 --- a/kernel/src/syscall/fs.rs +++ b/kernel/src/syscall/fs.rs @@ -934,6 +934,10 @@ impl Syscall<'_> { pub async fn sys_ftruncate(&self, fd: usize, length: u64) -> SyscallResult { let task = self.task; let file = task.with_fd_table(|table| table.get_file(fd))?; + log::error!( + "[sys_ftruncate] file path {}, length:{length}", + file.dentry().path() + ); file.inode().truncate(length as usize) } } diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 2db7cab5..70feeceb 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -23,7 +23,7 @@ use systype::SyscallResult; use crate::{syscall::sched::*, task::Task}; #[cfg(feature = "strace")] -pub const STRACE_COLOR_CODE: ColorCode = ColorCode::BrightMagenta; +pub const STRACE_COLOR_CODE: logging::ColorCode = logging::ColorCode::BrightMagenta; /// Syscall trace. // TODO: syscall trace with exact args and return value @@ -190,6 +190,7 @@ impl<'a> Syscall<'a> { } SYNC => self.sys_do_nothing("sync"), FSYNC => self.sys_do_nothing("fsync"), + FTRUNCATE => self.sys_ftruncate(args[0], args[1] as _).await, // IO PPOLL => { self.sys_ppoll(args[0].into(), args[1], args[2].into(), args[3]) diff --git a/modules/memory/src/heap.rs b/modules/memory/src/heap.rs index 7ccdaaff..56899fb8 100644 --- a/modules/memory/src/heap.rs +++ b/modules/memory/src/heap.rs @@ -20,12 +20,17 @@ type GlobalHeap = LockedLinkedHeap; static HEAP_ALLOCATOR: GlobalHeap = GlobalHeap::empty(); /// heap space +#[link_section = ".bss.heap"] static mut HEAP_SPACE: [u8; KERNEL_HEAP_SIZE] = [0; KERNEL_HEAP_SIZE]; /// Panic when heap allocation error occurs. #[alloc_error_handler] pub fn handle_alloc_error(layout: core::alloc::Layout) -> ! { - panic!("Heap allocation error, layout = {:?}", layout); + let inner = HEAP_ALLOCATOR.0.lock(); + let alloc_user = inner.stats_alloc_user(); + let alloc_actual = inner.stats_alloc_actual(); + let total_bytes = inner.stats_total_bytes(); + panic!("Heap allocation error, layout = {layout:?}, alloc_user: {alloc_user}, alloc_actual: {alloc_actual}, total_bytes: {total_bytes}"); } struct LockedBuddyHeap(SpinNoIrqLock>); diff --git a/modules/vfs-core/src/file.rs b/modules/vfs-core/src/file.rs index 9621017a..f2a8a760 100644 --- a/modules/vfs-core/src/file.rs +++ b/modules/vfs-core/src/file.rs @@ -301,7 +301,6 @@ impl dyn File { offset_it += len; buf_it = &buf_it[len..]; } - if offset_it > self.size() { log::warn!( "[File::write_at] write beyond file, offset_it:{offset_it}, size:{}", diff --git a/modules/vfs/src/fd_table.rs b/modules/vfs/src/fd_table.rs index d5a33258..ef83bb44 100644 --- a/modules/vfs/src/fd_table.rs +++ b/modules/vfs/src/fd_table.rs @@ -30,7 +30,6 @@ impl From for FdFlags { if value.contains(OpenFlags::O_CLOEXEC) { FdFlags::CLOEXEC } else { - log::warn!("[FdFlags::from] unsupported flag"); FdFlags::empty() } } diff --git a/user/src/bin/runtestcase.rs b/user/src/bin/runtestcase.rs index 364c965c..c5d43404 100644 --- a/user/src/bin/runtestcase.rs +++ b/user/src/bin/runtestcase.rs @@ -12,24 +12,18 @@ extern crate user_lib; // const TESTCASES: [&str; 0] = []; -const TESTCASES: [&str; 17] = [ - "cyclictest_testcode.sh", +const TESTCASES: [&str; 8] = [ + // "cyclictest_testcode.sh", "busybox_testcode.sh", + "lua_testcode.sh", "time-test", + "libc-bench", "libctest_testcode.sh", "lmbench_testcode.sh", - "lua_testcode.sh", "iozone_testcode.sh", - "libc-bench", "unixbench_testcode.sh", - "netperf_testcode.sh", - "iperf_testcode.sh", - "interrupts-test-1", - "interrupts-test-2", - "copy-file-range-test-1", - "copy-file-range-test-2", - "copy-file-range-test-3", - "copy-file-range-test-4", + // "netperf_testcode.sh", + // "iperf_testcode.sh", ]; #[no_mangle] @@ -42,7 +36,12 @@ fn main() -> i32 { if execve( &testname, &[testname.as_ptr(), core::ptr::null::()], - &[core::ptr::null::()], + &[ + "PATH=/:/bin:/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin:\0".as_ptr(), + "LD_LIBRARY_PATH=/:/lib:/lib64/lp64d:/usr/lib:/usr/local/lib:\0".as_ptr(), + "TERM=screen\0".as_ptr(), + core::ptr::null::(), + ], ) != 0 { println!("Error when executing!"); From df5bd0efc8f0d2e7c6420d183f16ff5dde50dec8 Mon Sep 17 00:00:00 2001 From: ChenRuiwei <1982833213@qq.com> Date: Thu, 18 Jul 2024 17:35:03 +0800 Subject: [PATCH 02/10] fix(shm): fix shared memory nattch attribute --- kernel/src/ipc/shm.rs | 8 +++++++ kernel/src/mm/memory_space/mod.rs | 27 ++++++++++++----------- kernel/src/mm/memory_space/vm_area.rs | 31 +++++++++++---------------- kernel/src/syscall/fs.rs | 2 +- kernel/src/syscall/mm.rs | 11 +++++----- kernel/src/task/task.rs | 8 ++++++- modules/vfs-core/src/file.rs | 15 ++++++++++++- user/src/bin/runtestcase.rs | 2 +- user/src/lib.rs | 2 +- 9 files changed, 66 insertions(+), 40 deletions(-) diff --git a/kernel/src/ipc/shm.rs b/kernel/src/ipc/shm.rs index 43140a8b..a4416e12 100644 --- a/kernel/src/ipc/shm.rs +++ b/kernel/src/ipc/shm.rs @@ -91,10 +91,18 @@ impl SharedMemory { } pub struct SharedMemoryManager(pub SpinNoIrqLock>); + impl SharedMemoryManager { pub fn init() -> Self { Self(SpinNoIrqLock::new(HashMap::new())) } + + pub fn attach(&self, shm_id: usize, lpid: usize) { + let mut shm_manager = self.0.lock(); + let shm = shm_manager.get_mut(&shm_id).unwrap(); + shm.shmid_ds.attach(lpid); + } + pub fn detach(&self, shm_id: usize, lpid: usize) { let mut shm_manager = self.0.lock(); let shm = shm_manager.get_mut(&shm_id).unwrap(); diff --git a/kernel/src/mm/memory_space/mod.rs b/kernel/src/mm/memory_space/mod.rs index 95c268a7..0c682bb5 100644 --- a/kernel/src/mm/memory_space/mod.rs +++ b/kernel/src/mm/memory_space/mod.rs @@ -347,7 +347,7 @@ impl MemorySpace { vm_area.pages.insert(vpn, page.clone()); } } - self.push_vma(vm_area); + self.push_vma_lazily(vm_area); return ret_addr; } @@ -576,7 +576,7 @@ impl MemorySpace { Ok(start) } - // NOTE: can not alloc all pages from `AddressSpace`, otherwise lmbench + // NOTE: can not alloc all pages from `PageCache`, otherwise lmbench // lat_pagefault will test page fault time as zero. pub fn alloc_mmap_area_lazily( &mut self, @@ -611,18 +611,21 @@ impl MemorySpace { let mut range_vpn = vma.range_vpn(); let length = cmp::min(length, MMAP_PRE_ALLOC_PAGES * PAGE_SIZE); for offset_aligned in (offset..offset + length).step_by(PAGE_SIZE) { - let page = if let Some(page) = page_cache.get_page(offset_aligned) { - page - } else if let Some(page) = block_on(async { file.read_page_at(offset_aligned).await })? - { - page + if let Some(page) = block_on(async { file.get_page_at(offset_aligned).await })? { + let vpn = range_vpn.next().unwrap(); + // TODO: support copy on write for private mapping + if flags.contains(MmapFlags::MAP_PRIVATE) { + let new_page = Page::new(); + new_page.copy_from_slice(page.bytes_array()); + page_table.map(vpn, new_page.ppn(), perm.into()); + vma.pages.insert(vpn, new_page); + } else { + page_table.map(vpn, page.ppn(), perm.into()); + vma.pages.insert(vpn, page); + } } else { - // no page means EOF break; - }; - let vpn = range_vpn.next().unwrap(); - page_table.map(vpn, page.ppn(), perm.into()); - vma.pages.insert(vpn, page); + } } self.push_vma_lazily(vma); Ok(start) diff --git a/kernel/src/mm/memory_space/vm_area.rs b/kernel/src/mm/memory_space/vm_area.rs index c3ec50db..5f5c643d 100644 --- a/kernel/src/mm/memory_space/vm_area.rs +++ b/kernel/src/mm/memory_space/vm_area.rs @@ -464,22 +464,13 @@ impl VmArea { } VmAreaType::Mmap => { if !self.mmap_flags.contains(MmapFlags::MAP_ANONYMOUS) { + // file mapping let file = self.backed_file.as_ref().unwrap(); let offset = self.offset + (vpn - self.start_vpn()) * PAGE_SIZE; let offset_aligned = round_down_to_page(offset); if self.mmap_flags.contains(MmapFlags::MAP_SHARED) { - let page = if let Some(page) = - file.inode().page_cache().unwrap().get_page(offset_aligned) - { - page - } else if let Some(page) = - block_on(async { file.read_page_at(offset_aligned).await })? - { - page - } else { - // no page means EOF - unreachable!() - }; + let page = block_on(async { file.get_page_at(offset_aligned).await })? + .unwrap(); page_table.map(vpn, page.ppn(), self.map_perm.into()); self.pages.insert(vpn, page); unsafe { sfence_vma_vaddr(vpn.to_va().into()) }; @@ -487,12 +478,16 @@ impl VmArea { todo!() } } else if self.mmap_flags.contains(MmapFlags::MAP_PRIVATE) { - // private anonymous area - page = Page::new(); - page.fill_zero(); - page_table.map(vpn, page.ppn(), self.map_perm.into()); - self.pages.insert(vpn, page); - unsafe { sfence_vma_vaddr(vpn.to_va().into()) }; + if self.mmap_flags.contains(MmapFlags::MAP_SHARED) { + todo!() + } else { + // private anonymous area + page = Page::new(); + page.fill_zero(); + page_table.map(vpn, page.ppn(), self.map_perm.into()); + self.pages.insert(vpn, page); + unsafe { sfence_vma_vaddr(vpn.to_va().into()) }; + } } } _ => {} diff --git a/kernel/src/syscall/fs.rs b/kernel/src/syscall/fs.rs index 8b0cfa34..de6b8ecc 100644 --- a/kernel/src/syscall/fs.rs +++ b/kernel/src/syscall/fs.rs @@ -934,7 +934,7 @@ impl Syscall<'_> { pub async fn sys_ftruncate(&self, fd: usize, length: u64) -> SyscallResult { let task = self.task; let file = task.with_fd_table(|table| table.get_file(fd))?; - log::error!( + log::warn!( "[sys_ftruncate] file path {}, length:{length}", file.dentry().path() ); diff --git a/kernel/src/syscall/mm.rs b/kernel/src/syscall/mm.rs index 55520a96..6d12dec9 100644 --- a/kernel/src/syscall/mm.rs +++ b/kernel/src/syscall/mm.rs @@ -153,7 +153,6 @@ impl Syscall<'_> { .with_mut_memory_space(|m| m.alloc_mmap_anonymous(perm, flags, length))?; Ok(start_va.bits()) } else { - log::warn!("private copy on write mmap is not implemented yet"); let file = task.with_fd_table(|table| table.get_file(fd))?; if offset + length > file.size() { log::warn!("offset plus length is bigger than file size"); @@ -301,8 +300,8 @@ impl Syscall<'_> { if shmflg.contains(ShmAtFlags::SHM_RDONLY) { map_perm.remove(MapPerm::W); } - let mut shm_manager = SHARED_MEMORY_MANAGER.0.lock(); - if let Some(shm) = shm_manager.get_mut(&shmid) { + let mut ret = 0; + if let Some(shm) = SHARED_MEMORY_MANAGER.0.lock().get_mut(&shmid) { let task = self.task; let ret_addr = task.with_mut_memory_space(|m| { m.attach_shm(shm.size(), shmaddr_aligned, map_perm, &mut shm.pages) @@ -310,11 +309,13 @@ impl Syscall<'_> { task.with_mut_shm_ids(|ids| { ids.insert(ret_addr, shmid); }); - Ok(ret_addr.into()) + ret = ret_addr.into(); } else { // Invalid shmid value - Err(SysError::EINVAL) + return Err(SysError::EINVAL); } + SHARED_MEMORY_MANAGER.attach(shmid, self.task.pid()); + return Ok(ret); } /// When a process no longer uses a shared memory block, it should detach diff --git a/kernel/src/task/task.rs b/kernel/src/task/task.rs index 6d314568..74bb3b4b 100644 --- a/kernel/src/task/task.rs +++ b/kernel/src/task/task.rs @@ -314,6 +314,7 @@ impl Task { let cwd; let itimers; let robust; + let shm_ids; let sig_handlers = if flags.contains(CloneFlags::SIGHAND) { self.sig_handlers.clone() } else { @@ -328,6 +329,7 @@ impl Task { itimers = self.itimers.clone(); cwd = self.cwd.clone(); robust = self.robust.clone(); + shm_ids = self.shm_ids.clone(); } else { is_leader = true; leader = None; @@ -341,6 +343,10 @@ impl Task { ]); cwd = new_shared(self.cwd()); robust = new_shared(RobustListHead::default()); + shm_ids = new_shared(BTreeMap::clone(&self.shm_ids.lock())); + for (_, shm_id) in shm_ids.lock().iter() { + SHARED_MEMORY_MANAGER.attach(*shm_id, tid.0); + } } let memory_space; @@ -385,7 +391,7 @@ impl Task { tid_address: SyncUnsafeCell::new(TidAddress::new()), cpus_allowed: SyncUnsafeCell::new(CpuMask::CPU_ALL), // After a fork(2), the child inherits the attached shared memory segments. - shm_ids: self.shm_ids.clone(), + shm_ids, }); if !flags.contains(CloneFlags::THREAD) { diff --git a/modules/vfs-core/src/file.rs b/modules/vfs-core/src/file.rs index a9e0ce79..12627047 100644 --- a/modules/vfs-core/src/file.rs +++ b/modules/vfs-core/src/file.rs @@ -72,7 +72,7 @@ pub trait File: Send + Sync + DowncastSync { todo!() } - /// Read a page at `offset_aligned` without address space. + /// Read a page at `offset_aligned` without page cache. async fn read_page_at(&self, offset_aligned: usize) -> SysResult>> { log::trace!("[File::read_page] read offset {offset_aligned}"); @@ -251,6 +251,19 @@ impl dyn File { Ok(offset_it - offset) } + pub async fn get_page_at(&self, offset_aligned: usize) -> SysResult>> { + let inode = self.inode(); + let page_cache = inode.page_cache().unwrap(); + if let Some(page) = page_cache.get_page(offset_aligned) { + Ok(Some(page)) + } else if let Some(page) = self.read_page_at(offset_aligned).await? { + Ok(Some(page)) + } else { + // no page means EOF + Ok(None) + } + } + /// Called by write(2) and related system calls. /// /// On success, the number of bytes written is returned, and the file offset diff --git a/user/src/bin/runtestcase.rs b/user/src/bin/runtestcase.rs index c5d43404..0ca1a10b 100644 --- a/user/src/bin/runtestcase.rs +++ b/user/src/bin/runtestcase.rs @@ -19,8 +19,8 @@ const TESTCASES: [&str; 8] = [ "time-test", "libc-bench", "libctest_testcode.sh", - "lmbench_testcode.sh", "iozone_testcode.sh", + "lmbench_testcode.sh", "unixbench_testcode.sh", // "netperf_testcode.sh", // "iperf_testcode.sh", diff --git a/user/src/lib.rs b/user/src/lib.rs index ed1e9c1c..f4d92e6d 100644 --- a/user/src/lib.rs +++ b/user/src/lib.rs @@ -179,7 +179,7 @@ pub fn waitpid(pid: usize, exit_code: &mut i32) -> isize { } pub fn pipe(pipe_fd: &mut [i32]) -> isize { - sys_pipe(pipe_fd.()) + sys_pipe(pipe_fd[0] as *mut _) } pub fn close(fd: usize) -> isize { From 3ad74c2cb60297153222df788ad2ab3c98333872 Mon Sep 17 00:00:00 2001 From: ChenRuiwei <1982833213@qq.com> Date: Thu, 18 Jul 2024 20:39:05 +0800 Subject: [PATCH 03/10] feat(early-print): add early-print crate to enable sbi print feature to prevent panic loop caused by print --- Cargo.lock | 9 +++++++++ crates/early-print/Cargo.toml | 9 +++++++++ crates/early-print/src/lib.rs | 32 ++++++++++++++++++++++++++++++++ kernel/Cargo.toml | 1 + kernel/src/panic.rs | 12 +++++++----- modules/memory/Cargo.toml | 1 + modules/memory/src/heap.rs | 15 ++++++++++++++- 7 files changed, 73 insertions(+), 6 deletions(-) create mode 100644 crates/early-print/Cargo.toml create mode 100644 crates/early-print/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 203dd2d8..ba3d2eaa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -240,6 +240,13 @@ dependencies = [ "virtio-drivers 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "early-print" +version = "0.1.0" +dependencies = [ + "sbi-rt", +] + [[package]] name = "either" version = "1.13.0" @@ -567,6 +574,7 @@ dependencies = [ "crate_interface", "downcast-rs", "driver", + "early-print", "executor", "hashbrown", "log", @@ -678,6 +686,7 @@ dependencies = [ "bitmap-allocator", "buddy_system_allocator", "config", + "early-print", "linked_list_allocator", "log", "riscv", diff --git a/crates/early-print/Cargo.toml b/crates/early-print/Cargo.toml new file mode 100644 index 00000000..8c105643 --- /dev/null +++ b/crates/early-print/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "early-print" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +sbi-rt = { version = "0.0.3", features = ["legacy"] } diff --git a/crates/early-print/src/lib.rs b/crates/early-print/src/lib.rs new file mode 100644 index 00000000..2fbf3329 --- /dev/null +++ b/crates/early-print/src/lib.rs @@ -0,0 +1,32 @@ +#![no_std] +#![no_main] + +use core::{fmt, fmt::Write}; + +struct EarlyStdout; + +impl fmt::Write for EarlyStdout { + fn write_str(&mut self, s: &str) -> fmt::Result { + for s in s.as_bytes() { + sbi_rt::legacy::console_putchar(*s as usize); + } + Ok(()) + } +} + +pub fn early_print(args: fmt::Arguments<'_>) { + EarlyStdout.write_fmt(args).unwrap(); +} + +#[macro_export] +macro_rules! early_print { + ($($arg:tt)*) => {{ + $crate::early_print(format_args!($($arg)*)); + }}; +} + +#[macro_export] +macro_rules! early_println { + () => ($crate::early_print!("\n")); + ($($arg:tt)*) => ($crate::early_print!("{}\n", format_args!($($arg)*))); +} diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index a3c77a5a..89b7ed05 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -22,6 +22,7 @@ time = { path = "../modules/time/" } timer = { path = "../modules/timer/" } page = { path = "../modules/page/" } net = { path = "../modules/net/" } +early-print = { path = "../crates/early-print/" } cfg-if = "1.0" crate_interface = "0.1" diff --git a/kernel/src/panic.rs b/kernel/src/panic.rs index ad721d16..c23be1f7 100644 --- a/kernel/src/panic.rs +++ b/kernel/src/panic.rs @@ -7,6 +7,7 @@ use core::{ use arch::interrupts::disable_interrupt; use driver::shutdown; +use early_print::early_println; use logging::LOG_INITIALIZED; use crate::processor::hart::local_hart; @@ -17,11 +18,11 @@ static PANIC_CNT: AtomicUsize = AtomicUsize::new(0); fn panic(info: &PanicInfo) -> ! { unsafe { disable_interrupt() }; - println!("panic now!!!"); + early_println!("early panic now!!!"); if PANIC_CNT.fetch_add(1, Ordering::Relaxed) > 0 { unsafe { LOG_INITIALIZED.store(false, Ordering::Relaxed) } if let Some(location) = info.location() { - println!( + early_println!( "Hart {} panic at {}:{}, msg: {}", local_hart().hart_id(), location.file(), @@ -29,13 +30,14 @@ fn panic(info: &PanicInfo) -> ! { info.message().unwrap() ); } else if let Some(msg) = info.message() { - println!("Panicked: {}", msg); + early_println!("Panicked: {}", msg); } else { - println!("Unknown panic: {:?}", info); + early_println!("Unknown panic: {:?}", info); } backtrace(); shutdown() } + println!("panic now!!!"); // NOTE: message below is mostly printed in log, if these messages can not be @@ -89,7 +91,7 @@ pub fn backtrace() { let mut current_fp = arch::register::fp(); while current_pc >= _stext as usize && current_pc <= _etext as usize && current_fp != 0 { - println!("{:#018x}", current_pc - size_of::()); + early_println!("{:#018x}", current_pc - size_of::()); current_fp = *(current_fp as *const usize).offset(-2); current_pc = *(current_fp as *const usize).offset(-1); } diff --git a/modules/memory/Cargo.toml b/modules/memory/Cargo.toml index 56f2352d..ec52f53c 100644 --- a/modules/memory/Cargo.toml +++ b/modules/memory/Cargo.toml @@ -9,6 +9,7 @@ edition = "2021" config = { path = "../../config/" } sync = { path = "../sync/" } arch = { path = "../../arch" } +early-print = { path = "../../crates/early-print/" } buddy_system_allocator = "0.9" linked_list_allocator = "0.10" diff --git a/modules/memory/src/heap.rs b/modules/memory/src/heap.rs index 56899fb8..3bb94239 100644 --- a/modules/memory/src/heap.rs +++ b/modules/memory/src/heap.rs @@ -1,11 +1,13 @@ //! The global allocator use core::{ + self, alloc::{GlobalAlloc, Layout}, ptr::NonNull, }; use buddy_system_allocator::Heap as BuddyHeap; use config::mm::KERNEL_HEAP_SIZE; +use early_print::early_println; #[cfg(all(feature = "linked", not(feature = "buddy")))] use linked_list_allocator::Heap as LinkedHeap; use sync::mutex::SpinNoIrqLock; @@ -26,11 +28,22 @@ static mut HEAP_SPACE: [u8; KERNEL_HEAP_SIZE] = [0; KERNEL_HEAP_SIZE]; /// Panic when heap allocation error occurs. #[alloc_error_handler] pub fn handle_alloc_error(layout: core::alloc::Layout) -> ! { + log::error!("heap alloc error"); + let inner = HEAP_ALLOCATOR.0.lock(); let alloc_user = inner.stats_alloc_user(); let alloc_actual = inner.stats_alloc_actual(); let total_bytes = inner.stats_total_bytes(); - panic!("Heap allocation error, layout = {layout:?}, alloc_user: {alloc_user}, alloc_actual: {alloc_actual}, total_bytes: {total_bytes}"); + + early_println!( + "Heap allocation error, layout = {:?}, alloc_user: {}, alloc_actual: {}, total_bytes: {}", + layout, + alloc_user, + alloc_actual, + total_bytes + ); + + panic!(); } struct LockedBuddyHeap(SpinNoIrqLock>); From 0e5de8cdd290190854a3f7753a9a480b889e9265 Mon Sep 17 00:00:00 2001 From: ChenRuiwei <1982833213@qq.com> Date: Thu, 18 Jul 2024 21:04:46 +0800 Subject: [PATCH 04/10] refactor(backtrace): add backtrace crate --- Cargo.lock | 9 +++++++++ crates/backtrace/Cargo.toml | 10 ++++++++++ crates/backtrace/src/lib.rs | 23 +++++++++++++++++++++++ kernel/Cargo.toml | 1 + kernel/src/panic.rs | 18 +----------------- kernel/src/trap/user_trap.rs | 4 +--- 6 files changed, 45 insertions(+), 20 deletions(-) create mode 100644 crates/backtrace/Cargo.toml create mode 100644 crates/backtrace/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index ba3d2eaa..1b07b552 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -81,6 +81,14 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +[[package]] +name = "backtrace" +version = "0.1.0" +dependencies = [ + "arch", + "early-print", +] + [[package]] name = "bit_field" version = "0.10.2" @@ -566,6 +574,7 @@ dependencies = [ "arch", "async-trait", "async_utils", + "backtrace", "bit_field", "bitflags 2.6.0", "buddy_system_allocator", diff --git a/crates/backtrace/Cargo.toml b/crates/backtrace/Cargo.toml new file mode 100644 index 00000000..38f42d10 --- /dev/null +++ b/crates/backtrace/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "backtrace" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +arch = { path = "../../arch/" } +early-print = { path = "../early-print/" } diff --git a/crates/backtrace/src/lib.rs b/crates/backtrace/src/lib.rs new file mode 100644 index 00000000..62b2fc00 --- /dev/null +++ b/crates/backtrace/src/lib.rs @@ -0,0 +1,23 @@ +#![no_std] +#![no_main] + +use core::mem::size_of; + +use early_print::early_println; + +pub fn backtrace() { + extern "C" { + fn _stext(); + fn _etext(); + } + unsafe { + let mut current_pc = arch::register::ra(); + let mut current_fp = arch::register::fp(); + + while current_pc >= _stext as usize && current_pc <= _etext as usize && current_fp != 0 { + early_println!("{:#018x}", current_pc - size_of::()); + current_fp = *(current_fp as *const usize).offset(-2); + current_pc = *(current_fp as *const usize).offset(-1); + } + } +} diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 89b7ed05..699cbfcc 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -23,6 +23,7 @@ timer = { path = "../modules/timer/" } page = { path = "../modules/page/" } net = { path = "../modules/net/" } early-print = { path = "../crates/early-print/" } +backtrace = { path = "../crates/backtrace/" } cfg-if = "1.0" crate_interface = "0.1" diff --git a/kernel/src/panic.rs b/kernel/src/panic.rs index c23be1f7..93cb7e8c 100644 --- a/kernel/src/panic.rs +++ b/kernel/src/panic.rs @@ -6,6 +6,7 @@ use core::{ }; use arch::interrupts::disable_interrupt; +use backtrace::backtrace; use driver::shutdown; use early_print::early_println; use logging::LOG_INITIALIZED; @@ -80,20 +81,3 @@ fn panic(info: &PanicInfo) -> ! { shutdown() } - -pub fn backtrace() { - extern "C" { - fn _stext(); - fn _etext(); - } - unsafe { - let mut current_pc = arch::register::ra(); - let mut current_fp = arch::register::fp(); - - while current_pc >= _stext as usize && current_pc <= _etext as usize && current_fp != 0 { - early_println!("{:#018x}", current_pc - size_of::()); - current_fp = *(current_fp as *const usize).offset(-2); - current_pc = *(current_fp as *const usize).offset(-1); - } - } -} diff --git a/kernel/src/trap/user_trap.rs b/kernel/src/trap/user_trap.rs index 11230715..dec9b830 100644 --- a/kernel/src/trap/user_trap.rs +++ b/kernel/src/trap/user_trap.rs @@ -20,9 +20,7 @@ use systype::SysError; use timer::TIMER_MANAGER; use super::{set_kernel_trap, TrapContext}; -use crate::{ - mm::PageFaultAccessType, panic::backtrace, syscall::Syscall, task::Task, trap::set_user_trap, -}; +use crate::{mm::PageFaultAccessType, syscall::Syscall, task::Task, trap::set_user_trap}; /// handle an interrupt, exception, or system call from user space /// return if it is syscall and has been interrupted From 2e10e8d8cd384cc08e9520baf98aee9e546e7eb4 Mon Sep 17 00:00:00 2001 From: ChenRuiwei <1982833213@qq.com> Date: Thu, 18 Jul 2024 21:54:01 +0800 Subject: [PATCH 05/10] refactor(init): refactor spawn_init_proc function --- kernel/src/main.rs | 2 +- kernel/src/mm/memory_space/mod.rs | 62 ++++++--------------------- kernel/src/mm/memory_space/vm_area.rs | 1 - kernel/src/syscall/process.rs | 2 +- kernel/src/task/mod.rs | 37 +++++++++++++--- kernel/src/task/task.rs | 27 +++++++----- modules/page/src/buffer_cache.rs | 1 + 7 files changed, 66 insertions(+), 66 deletions(-) diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 7fa3e452..5bc7ef79 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -73,7 +73,7 @@ fn rust_main(hart_id: usize, dtb_addr: usize) { loader::init(); vfs::init(); task::spawn_kernel_task(async move { - task::add_init_proc(); + task::spawn_init_proc(); }); #[cfg(feature = "smp")] diff --git a/kernel/src/mm/memory_space/mod.rs b/kernel/src/mm/memory_space/mod.rs index 0c682bb5..6571830e 100644 --- a/kernel/src/mm/memory_space/mod.rs +++ b/kernel/src/mm/memory_space/mod.rs @@ -120,7 +120,12 @@ impl MemorySpace { /// Map the sections in the elf. /// /// Return the max end vpn and the first section's va. - pub fn map_elf(&mut self, elf: &ElfFile, offset: VirtAddr) -> (VirtPageNum, VirtAddr) { + pub fn map_elf( + &mut self, + elf_file: Arc, + elf: &ElfFile, + offset: VirtAddr, + ) -> (VirtPageNum, VirtAddr) { let elf_header = elf.header; let ph_count = elf_header.pt2.ph_count(); @@ -178,51 +183,11 @@ impl MemorySpace { (max_end_vpn, header_va.into()) } - /// Include sections in elf and TrapContext and user stack, - /// also returns user_sp and entry point. - // PERF: resolve elf file lazily - // TODO: dynamic interpreter - pub fn from_elf(elf_data: &[u8]) -> (Self, usize, usize, Vec) { - const ELF_MAGIC: [u8; 4] = [0x7f, 0x45, 0x4c, 0x46]; - - let mut memory_space = Self::new_user(); - - // map program headers of elf, with U flag - let elf = xmas_elf::ElfFile::new(elf_data).unwrap(); - let elf_header = elf.header; - assert_eq!(elf_header.pt1.magic, ELF_MAGIC, "invalid elf!"); - let entry_point = elf_header.pt2.entry_point() as usize; - let ph_entry_size = elf_header.pt2.ph_entry_size() as usize; - let ph_count = elf_header.pt2.ph_count() as usize; - - let mut auxv = generate_early_auxv(ph_entry_size, ph_count, entry_point); - - auxv.push(AuxHeader::new(AT_BASE, 0)); - - let (max_end_vpn, header_va) = memory_space.map_elf(&elf, 0.into()); - - let ph_head_addr = header_va.0 + elf.header.pt2.ph_offset() as usize; - log::debug!("[from_elf] AT_PHDR ph_head_addr is {ph_head_addr:x} "); - auxv.push(AuxHeader::new(AT_PHDR, ph_head_addr)); - - // map user stack with U flags - let max_end_va: VirtAddr = max_end_vpn.into(); - let user_stack_bottom: usize = usize::from(max_end_va) + PAGE_SIZE; - let user_stack_top = user_stack_bottom + USER_STACK_SIZE; - let ustack_vma = VmArea::new( - user_stack_bottom.into()..user_stack_top.into(), - MapPerm::URW, - VmAreaType::Stack, - ); - memory_space.push_vma(ustack_vma); - log::info!("[from_elf] map ustack: {user_stack_bottom:#x}, {user_stack_top:#x}",); - - memory_space.alloc_heap_lazily(); - - (memory_space, user_stack_top, entry_point, auxv) - } - - pub fn parse_and_map_elf(&mut self, elf_data: &[u8]) -> (usize, Vec) { + pub fn parse_and_map_elf( + &mut self, + elf_file: Arc, + elf_data: &[u8], + ) -> (usize, Vec) { const ELF_MAGIC: [u8; 4] = [0x7f, 0x45, 0x4c, 0x46]; // map program headers of elf, with U flag @@ -237,7 +202,7 @@ impl MemorySpace { auxv.push(AuxHeader::new(AT_BASE, 0)); - let (_max_end_vpn, header_va) = self.map_elf(&elf, 0.into()); + let (_max_end_vpn, header_va) = self.map_elf(elf_file, &elf, 0.into()); let ph_head_addr = header_va.0 + elf.header.pt2.ph_offset() as usize; auxv.push(AuxHeader::new(AT_RANDOM, ph_head_addr)); @@ -294,7 +259,7 @@ impl MemorySpace { let interp_file = interp_dentry.open().ok().unwrap(); let interp_elf_data = block_on(async { interp_file.read_all().await }).ok()?; let interp_elf = xmas_elf::ElfFile::new(&interp_elf_data).unwrap(); - self.map_elf(&interp_elf, DL_INTERP_OFFSET.into()); + self.map_elf(interp_file, &interp_elf, DL_INTERP_OFFSET.into()); Some(interp_elf.header.pt2.entry_point() as usize + DL_INTERP_OFFSET) } else { @@ -508,6 +473,7 @@ impl MemorySpace { } _ => { // copy on write + // TODO: MmapFlags::MAP_SHARED let mut new_flags = pte.flags() | PTEFlags::COW; new_flags.remove(PTEFlags::W); pte.set_flags(new_flags); diff --git a/kernel/src/mm/memory_space/vm_area.rs b/kernel/src/mm/memory_space/vm_area.rs index 5f5c643d..48925599 100644 --- a/kernel/src/mm/memory_space/vm_area.rs +++ b/kernel/src/mm/memory_space/vm_area.rs @@ -419,7 +419,6 @@ impl VmArea { // PERF: copying data vs. lock the area vs. atomic ref cnt let old_page = self.get_page(vpn); - let mut _cnt: usize; let cnt = Arc::strong_count(old_page); if cnt > 1 { // shared now diff --git a/kernel/src/syscall/process.rs b/kernel/src/syscall/process.rs index 8bd31de1..d684635b 100644 --- a/kernel/src/syscall/process.rs +++ b/kernel/src/syscall/process.rs @@ -295,7 +295,7 @@ impl Syscall<'_> { let file = task.resolve_path(&path)?.open()?; let elf_data = file.read_all().await?; - task.do_execve(&elf_data, argv, envp); + task.do_execve(file, &elf_data, argv, envp); Ok(0) } diff --git a/kernel/src/task/mod.rs b/kernel/src/task/mod.rs index f4bf4c1d..6cd07460 100644 --- a/kernel/src/task/mod.rs +++ b/kernel/src/task/mod.rs @@ -6,17 +6,44 @@ pub mod signal; pub mod task; mod tid; +use alloc::{sync::Arc, vec::Vec}; + +use async_utils::block_on; +use config::mm::USER_STACK_SIZE; pub use manager::TASK_MANAGER; pub use schedule::{spawn_kernel_task, spawn_user_task}; pub use task::Task; pub use tid::{PGid, Pid, Tid}; +use vfs::sys_root_dentry; +use vfs_core::Path; + +use crate::{ + loader::get_app_data_by_name, + mm::memory_space::{self, init_stack, MemorySpace}, + processor::env::within_sum, + trap::TrapContext, +}; + +pub fn spawn_init_proc() { + let init_proc_path = "/init_proc"; + let argv = Vec::new(); + let envp = Vec::new(); + + let path = Path::new(sys_root_dentry(), sys_root_dentry(), init_proc_path); + let file = path.walk().unwrap().open().unwrap(); + let elf_data = block_on(async { file.read_all().await }).unwrap(); + + let mut memory_space = MemorySpace::new_user(); + unsafe { memory_space.switch_page_table() }; + let (entry, auxv) = memory_space.parse_and_map_elf(file, &elf_data); + let sp_init = memory_space.alloc_stack_lazily(USER_STACK_SIZE); + let (sp, argc, argv, envp) = within_sum(|| init_stack(sp_init, argv, envp, auxv)); + memory_space.alloc_heap_lazily(); -use crate::loader::get_app_data_by_name; + let trap_context = TrapContext::new(entry, sp); -pub fn add_init_proc() { - let elf_data = get_app_data_by_name("init_proc").unwrap(); - // let elf_data = get_app_data_by_name("futex_test").unwrap(); - Task::spawn_from_elf(elf_data); + let task = Task::new_init(memory_space, trap_context); + schedule::spawn_user_task(task); } #[macro_export] diff --git a/kernel/src/task/task.rs b/kernel/src/task/task.rs index 74bb3b4b..521835ba 100644 --- a/kernel/src/task/task.rs +++ b/kernel/src/task/task.rs @@ -26,7 +26,7 @@ use sync::mutex::SpinNoIrqLock; use systype::SysResult; use time::stat::TaskTimeStat; use vfs::{fd_table::FdTable, sys_root_dentry}; -use vfs_core::{is_absolute_path, AtFd, Dentry, InodeMode, Path}; +use vfs_core::{is_absolute_path, AtFd, Dentry, File, InodeMode, Path}; use super::{ resource::CpuMask, @@ -39,7 +39,10 @@ use crate::{ futex::{futex_manager, FutexHashKey, RobustListHead, FUTEX_MANAGER}, shm::SHARED_MEMORY_MANAGER, }, - mm::{memory_space::init_stack, MemorySpace, UserReadPtr, UserWritePtr}, + mm::{ + memory_space::{self, init_stack}, + MemorySpace, UserReadPtr, UserWritePtr, + }, processor::env::within_sum, syscall::{self, CloneFlags}, task::{ @@ -175,10 +178,7 @@ impl Task { shm_ids: BTreeMap ); - // TODO: this function is not clear, may be replaced with exec - pub fn spawn_from_elf(elf_data: &[u8]) { - let (memory_space, user_sp_top, entry_point, _auxv) = MemorySpace::from_elf(elf_data); - let trap_context = TrapContext::new(entry_point, user_sp_top); + pub fn new_init(memory_space: MemorySpace, trap_context: TrapContext) -> Arc { let task = Arc::new(Self { tid: alloc_tid(), leader: None, @@ -209,11 +209,12 @@ impl Task { cpus_allowed: SyncUnsafeCell::new(CpuMask::CPU_ALL), shm_ids: new_shared(BTreeMap::new()), }); + task.thread_group.lock().push(task.clone()); task.memory_space.lock().set_task(&task); TASK_MANAGER.add(&task); - log::debug!("create a new process, pid {}", task.tid()); - schedule::spawn_user_task(task); + + task } pub fn parent(&self) -> Option> { @@ -408,11 +409,17 @@ impl Task { } // TODO: figure out what should be reserved across this syscall - pub fn do_execve(self: &Arc, elf_data: &[u8], argv: Vec, envp: Vec) { + pub fn do_execve( + self: &Arc, + elf_file: Arc, + elf_data: &[u8], + argv: Vec, + envp: Vec, + ) { log::debug!("[Task::do_execve] parsing elf"); let mut memory_space = MemorySpace::new_user(); memory_space.set_task(&self.leader()); - let (mut entry, mut auxv) = memory_space.parse_and_map_elf(elf_data); + let (mut entry, mut auxv) = memory_space.parse_and_map_elf(elf_file, elf_data); let elf = xmas_elf::ElfFile::new(elf_data).unwrap(); if let Some(interp_entry_point) = memory_space.load_dl_interp_if_needed(&elf) { diff --git a/modules/page/src/buffer_cache.rs b/modules/page/src/buffer_cache.rs index 55644a31..b8e02f7d 100644 --- a/modules/page/src/buffer_cache.rs +++ b/modules/page/src/buffer_cache.rs @@ -31,6 +31,7 @@ pub struct BufferCache { // block data. pages: LruCache>, /// Block idx to `BufferHead`. + // TODO: add lru support, otherwise may occupy too much heap space // NOTE: Stores all accesses to block device. Some of them will be attached // to pages above, while others with file related will be attached to pages // stored in address space. From 2b8b5b50805e86321ccc354638cdc9c755cf0f2a Mon Sep 17 00:00:00 2001 From: ChenRuiwei <1982833213@qq.com> Date: Thu, 18 Jul 2024 21:57:18 +0800 Subject: [PATCH 06/10] refactor: remove loader module --- kernel/build.rs | 64 ------------------------------------------ kernel/src/loader.rs | 62 ---------------------------------------- kernel/src/main.rs | 3 -- kernel/src/task/mod.rs | 1 - 4 files changed, 130 deletions(-) delete mode 100644 kernel/src/loader.rs diff --git a/kernel/build.rs b/kernel/build.rs index 9cb0bb13..1a0dad5d 100644 --- a/kernel/build.rs +++ b/kernel/build.rs @@ -21,68 +21,4 @@ fn main() { let dest = PathBuf::from(out_dir).join("linker.ld"); fs::write(&dest, new).unwrap(); println!("cargo:rustc-link-arg=-T{}", dest.display()); - - insert_app_data().unwrap(); -} - -fn insert_app_data() -> Result<()> { - let mut target_path: String = String::from("./target/riscv64gc-unknown-none-elf/"); - let mode = option_env!("MODE").unwrap_or("debug"); - target_path.push_str(mode); - target_path.push('/'); - let mut f = File::create("src/link_app.asm").unwrap(); - let mut apps: Vec<_> = read_dir("../user/src/bin") - .unwrap() - .map(|dir_entry| { - let mut name_with_ext = dir_entry.unwrap().file_name().into_string().unwrap(); - name_with_ext.drain(name_with_ext.find('.').unwrap()..name_with_ext.len()); - name_with_ext - }) - .filter(|name| name == "init_proc") - .collect(); - - apps.sort(); - - writeln!( - f, - r#" - .align 3 - .section .data - .global _num_app -_num_app: - .quad {}"#, - apps.len() - )?; - - for i in 0..apps.len() { - writeln!(f, r#" .quad app_{}_start"#, i)?; - } - writeln!(f, r#" .quad app_{}_end"#, apps.len() - 1)?; - - writeln!( - f, - r#" - .global _app_names -_app_names:"# - )?; - for app in apps.iter() { - writeln!(f, r#" .string "{}""#, app)?; - } - - for (idx, app) in apps.iter().enumerate() { - println!("app_{}: {}", idx, app); - writeln!( - f, - r#" - .section .data - .global app_{0}_start - .global app_{0}_end - .align 3 -app_{0}_start: - .incbin "{2}{1}" -app_{0}_end:"#, - idx, app, target_path - )?; - } - Ok(()) } diff --git a/kernel/src/loader.rs b/kernel/src/loader.rs deleted file mode 100644 index 28e50b50..00000000 --- a/kernel/src/loader.rs +++ /dev/null @@ -1,62 +0,0 @@ -//! Loading user applications into memory - -/// Get the total number of applications. -use alloc::vec::Vec; -/// get app number -pub fn get_num_app() -> usize { - extern "C" { - fn _num_app(); - } - unsafe { (_num_app as usize as *const usize).read_volatile() } -} -/// get applications data -pub fn get_app_data(app_id: usize) -> &'static [u8] { - extern "C" { - fn _num_app(); - } - let num_app_ptr = _num_app as usize as *const usize; - let num_app = get_num_app(); - let app_start = unsafe { core::slice::from_raw_parts(num_app_ptr.add(1), num_app + 1) }; - assert!(app_id < num_app); - unsafe { - core::slice::from_raw_parts( - app_start[app_id] as *const u8, - app_start[app_id + 1] - app_start[app_id], - ) - } -} - -pub fn init() { - let num_app = get_num_app(); - extern "C" { - fn _app_names(); - } - let mut start = _app_names as usize as *const u8; - let mut v = Vec::with_capacity(num_app); - unsafe { - for _ in 0..num_app { - let mut end = start; - while end.read_volatile() != b'\0' { - end = end.add(1); - } - let slice = core::slice::from_raw_parts(start, end as usize - start as usize); - let str = core::str::from_utf8(slice).unwrap(); - v.push(str); - start = end.add(1); - } - APP_NAMES = Some(v); - } -} - -static mut APP_NAMES: Option> = None; - -#[allow(unused)] -/// get app data from name -pub fn get_app_data_by_name(name: &str) -> Option<&'static [u8]> { - // warn!("app name {}", name); - let app_names = unsafe { APP_NAMES.as_ref().unwrap() }; - let num_app = get_num_app(); - (0..num_app) - .find(|&i| app_names[i] == name) - .map(get_app_data) -} diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 5bc7ef79..e0e9d42c 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -18,7 +18,6 @@ mod boot; mod impls; mod ipc; -mod loader; mod mm; mod net; mod panic; @@ -48,7 +47,6 @@ extern crate driver; extern crate logging; global_asm!(include_str!("trampoline.asm")); -global_asm!(include_str!("link_app.asm")); static FIRST_HART: AtomicBool = AtomicBool::new(true); @@ -70,7 +68,6 @@ fn rust_main(hart_id: usize, dtb_addr: usize) { mm::init(); trap::init(); driver::init(); - loader::init(); vfs::init(); task::spawn_kernel_task(async move { task::spawn_init_proc(); diff --git a/kernel/src/task/mod.rs b/kernel/src/task/mod.rs index 6cd07460..a7d870f4 100644 --- a/kernel/src/task/mod.rs +++ b/kernel/src/task/mod.rs @@ -18,7 +18,6 @@ use vfs::sys_root_dentry; use vfs_core::Path; use crate::{ - loader::get_app_data_by_name, mm::memory_space::{self, init_stack, MemorySpace}, processor::env::within_sum, trap::TrapContext, From 99575458787c876bbe610811e3b990dad6eef6f8 Mon Sep 17 00:00:00 2001 From: ChenRuiwei <1982833213@qq.com> Date: Fri, 19 Jul 2024 14:26:58 +0800 Subject: [PATCH 07/10] refactor(print): refactor some print work --- Cargo.lock | 1 + crates/early-print/src/lib.rs | 2 +- driver/Cargo.toml | 1 + driver/src/lib.rs | 31 ++---- driver/src/virtio/virtio_blk.rs | 4 + kernel/src/impls.rs | 4 +- kernel/src/main.rs | 13 ++- kernel/src/mm/memory_space/mod.rs | 65 ++++++++++--- kernel/src/panic.rs | 2 +- modules/device-core/src/lib.rs | 2 + modules/page/src/buffer_cache.rs | 19 ++-- modules/timer/src/timelimited_task.rs | 4 + modules/vfs-core/src/file.rs | 8 +- modules/vfs/src/devfs/mod.rs | 1 - modules/vfs/src/devfs/stdio.rs | 130 -------------------------- modules/vfs/src/devfs/tty.rs | 9 +- modules/vfs/src/fd_table.rs | 2 +- 17 files changed, 108 insertions(+), 190 deletions(-) delete mode 100644 modules/vfs/src/devfs/stdio.rs diff --git a/Cargo.lock b/Cargo.lock index 1b07b552..86f2e4ff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -234,6 +234,7 @@ dependencies = [ "config", "crate_interface", "device-core", + "early-print", "fdt", "log", "memory", diff --git a/crates/early-print/src/lib.rs b/crates/early-print/src/lib.rs index 2fbf3329..58f87298 100644 --- a/crates/early-print/src/lib.rs +++ b/crates/early-print/src/lib.rs @@ -3,7 +3,7 @@ use core::{fmt, fmt::Write}; -struct EarlyStdout; +pub struct EarlyStdout; impl fmt::Write for EarlyStdout { fn write_str(&mut self, s: &str) -> fmt::Result { diff --git a/driver/Cargo.toml b/driver/Cargo.toml index 198ec6d3..969c73fb 100644 --- a/driver/Cargo.toml +++ b/driver/Cargo.toml @@ -14,6 +14,7 @@ memory = { path = "../modules/memory/" } systype = { path = "../modules/systype/" } page = { path = "../modules/page/" } device-core = { path = "../modules/device-core/" } +early-print = { path = "../crates/early-print/" } net = { path = "../modules/net/" } bitflags = "2.5" diff --git a/driver/src/lib.rs b/driver/src/lib.rs index d6085fd3..587d65d5 100644 --- a/driver/src/lib.rs +++ b/driver/src/lib.rs @@ -14,6 +14,7 @@ use core::fmt::{self, Write}; use async_utils::block_on; use crate_interface::call_interface; use device_core::{BlockDriverOps, CharDevice, DeviceMajor}; +use early_print::EarlyStdout; use manager::DeviceManager; use memory::PageTable; use spin::Once; @@ -94,42 +95,26 @@ impl Write for Stdout { fn write_str(&mut self, s: &str) -> fmt::Result { if let Some(serial) = unsafe { UART0.lock().as_mut() } { block_on(async { serial.write(s.as_bytes()).await }); - return Ok(()); + Ok(()) + } else { + EarlyStdout.write_str(s) } - for s in s.as_bytes() { - console_putchar(*s as usize); - } - Ok(()) } } -pub fn print(args: fmt::Arguments<'_>) { +pub fn _print(args: fmt::Arguments) { Stdout.write_fmt(args).unwrap(); } -/// print string macro #[macro_export] macro_rules! print { ($($arg:tt)*) => {{ - $crate::print(format_args!($($arg)*)); + $crate::_print(format_args!($($arg)*)); }}; } -/// println string macro #[macro_export] macro_rules! println { - () => { - $crate::print!("\n") - }; - ($($arg:tt)*) => {{ - $crate::print(format_args_nl!($($arg)*)); - }}; -} - -pub fn shutdown() -> ! { - sbi::shutdown() -} - -pub fn set_timer(timer: usize) { - sbi::set_timer(timer) + () => ($crate::print!("\n")); + ($($arg:tt)*) => ($crate::print!("{}\n", format_args!($($arg)*))); } diff --git a/driver/src/virtio/virtio_blk.rs b/driver/src/virtio/virtio_blk.rs index 3d4644ac..16bb2b88 100644 --- a/driver/src/virtio/virtio_blk.rs +++ b/driver/src/virtio/virtio_blk.rs @@ -55,6 +55,10 @@ impl BlockDriverOps for VirtIoBlkDev { fn write_block(&self, block_id: usize, buf: &[u8]) { self.cache.lock().write_block(block_id, buf) } + + fn buffer_head_cnts(&self) -> usize { + self.cache.lock().buffer_heads.len() + } } impl VirtIoBlkDev { diff --git a/kernel/src/impls.rs b/kernel/src/impls.rs index 372f1b70..4b48a674 100644 --- a/kernel/src/impls.rs +++ b/kernel/src/impls.rs @@ -14,7 +14,7 @@ use crate::{ /// Print msg with color pub fn print_in_color(args: fmt::Arguments, color_code: u8) { - driver::print(with_color!(color_code, "{}", args)); + driver::_print(with_color!(color_code, "{}", args)); } struct LogIfImpl; @@ -51,7 +51,7 @@ impl LogIf for LogIfImpl { } else { "-".to_string() }; - driver::print(with_color!( + driver::_print(with_color!( ColorCode::White, "{}{}{} {} \r\n", with_color!(level_color, "[{:>5}]", level), diff --git a/kernel/src/main.rs b/kernel/src/main.rs index e0e9d42c..ca422116 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -11,7 +11,6 @@ #![feature(stdsimd)] #![feature(riscv_ext_intrinsics)] #![feature(map_try_insert)] -#![feature(format_args_nl)] #![allow(clippy::mut_from_ref)] #![feature(new_uninit)] @@ -32,6 +31,8 @@ use core::{ }; use ::net::init_network; +use driver::BLOCK_DEVICE; +use timer::timelimited_task::ksleep_s; use crate::processor::hart; @@ -73,6 +74,16 @@ fn rust_main(hart_id: usize, dtb_addr: usize) { task::spawn_init_proc(); }); + task::spawn_kernel_task(async move { + loop { + log::error!( + "buffer head cnts {}", + BLOCK_DEVICE.get().unwrap().buffer_head_cnts() + ); + ksleep_s(3).await; + } + }); + #[cfg(feature = "smp")] boot::start_harts(hart_id); } else { diff --git a/kernel/src/mm/memory_space/mod.rs b/kernel/src/mm/memory_space/mod.rs index 6571830e..6b94d3c6 100644 --- a/kernel/src/mm/memory_space/mod.rs +++ b/kernel/src/mm/memory_space/mod.rs @@ -12,14 +12,15 @@ use core::{ ops::{self, Range}, }; +use arch::memory::{sfence_vma_all, sfence_vma_vaddr}; use async_utils::block_on; use config::{ board::MEMORY_END, mm::{ - align_offset_to_page, is_aligned_to_page, DL_INTERP_OFFSET, MMAP_PRE_ALLOC_PAGES, - PAGE_SIZE, USER_STACK_PRE_ALLOC_SIZE, USER_STACK_SIZE, U_SEG_FILE_BEG, U_SEG_FILE_END, - U_SEG_HEAP_BEG, U_SEG_HEAP_END, U_SEG_SHARE_BEG, U_SEG_SHARE_END, U_SEG_STACK_BEG, - U_SEG_STACK_END, VIRT_RAM_OFFSET, + align_offset_to_page, is_aligned_to_page, round_down_to_page, DL_INTERP_OFFSET, + MMAP_PRE_ALLOC_PAGES, PAGE_SIZE, USER_ELF_PRE_ALLOC_PAGE_CNT, USER_STACK_PRE_ALLOC_SIZE, + USER_STACK_SIZE, U_SEG_FILE_BEG, U_SEG_FILE_END, U_SEG_HEAP_BEG, U_SEG_HEAP_END, + U_SEG_SHARE_BEG, U_SEG_SHARE_END, U_SEG_STACK_BEG, U_SEG_STACK_END, VIRT_RAM_OFFSET, }, }; use log::info; @@ -156,7 +157,7 @@ impl MemorySpace { if ph_flags.is_execute() { map_perm |= MapPerm::X; } - let vm_area = VmArea::new(start_va..end_va, map_perm, VmAreaType::Elf); + let mut vm_area = VmArea::new(start_va..end_va, map_perm, VmAreaType::Elf); log::debug!("[map_elf] [{start_va:#x}, {end_va:#x}], map_perm: {map_perm:?} start...",); @@ -171,13 +172,53 @@ impl MemorySpace { ph.mem_size() ); - self.push_vma_with_data( - vm_area, - map_offset, - &elf.input[ph.offset() as usize..(ph.offset() + ph.file_size()) as usize], - ); - - log::info!("[map_elf] [{start_va:#x}, {end_va:#x}], map_perm: {map_perm:?}",); + if ph.file_size() == ph.mem_size() && is_aligned_to_page(ph.offset() as usize) { + assert!(!map_perm.contains(MapPerm::W)); + // NOTE: only add cow flag in elf page newly mapped. + // FIXME: mprotect is not checked yet + // WARN: the underlying elf file page cache may be edited, may cause unknown + // behavior + let mut pre_alloc_page_cnt = 0; + for vpn in vm_area.range_vpn() { + let start_offset = ph.offset() as usize; + let offset = start_offset + (vpn - vm_area.start_vpn()) * PAGE_SIZE; + let offset_aligned = round_down_to_page(offset); + if let Some(page) = + block_on(async { elf_file.get_page_at(offset_aligned).await }).unwrap() + { + if pre_alloc_page_cnt < USER_ELF_PRE_ALLOC_PAGE_CNT { + let new_page = Page::new(); + // WARN: area outer than region may should be set to zero + new_page.copy_from_slice(page.bytes_array()); + self.page_table_mut() + .map(vpn, new_page.ppn(), map_perm.into()); + vm_area.pages.insert(vpn, new_page); + unsafe { sfence_vma_vaddr(vpn.into()) }; + } else { + let (pte_flags, ppn) = { + let mut new_flags: PTEFlags = map_perm.into(); + new_flags |= PTEFlags::COW; + new_flags.remove(PTEFlags::W); + (new_flags, page.ppn()) + }; + self.page_table_mut().map(vpn, ppn, pte_flags); + vm_area.pages.insert(vpn, page); + unsafe { sfence_vma_vaddr(vpn.into()) }; + } + pre_alloc_page_cnt += 1; + } else { + break; + } + } + self.push_vma_lazily(vm_area); + log::info!("[map_elf] [{start_va:#x}, {end_va:#x}], map_perm: {map_perm:?}",); + } else { + self.push_vma_with_data( + vm_area, + map_offset, + &elf.input[ph.offset() as usize..(ph.offset() + ph.file_size()) as usize], + ); + } } (max_end_vpn, header_va.into()) diff --git a/kernel/src/panic.rs b/kernel/src/panic.rs index 93cb7e8c..f68f5d9c 100644 --- a/kernel/src/panic.rs +++ b/kernel/src/panic.rs @@ -7,7 +7,7 @@ use core::{ use arch::interrupts::disable_interrupt; use backtrace::backtrace; -use driver::shutdown; +use driver::sbi::shutdown; use early_print::early_println; use logging::LOG_INITIALIZED; diff --git a/modules/device-core/src/lib.rs b/modules/device-core/src/lib.rs index c1fa3a42..90a38d86 100644 --- a/modules/device-core/src/lib.rs +++ b/modules/device-core/src/lib.rs @@ -98,6 +98,8 @@ pub trait BlockDriverOps: BaseDriverOps { fn block_size(&self) -> usize; + fn buffer_head_cnts(&self) -> usize; + /// Read data form block to buffer fn base_read_block(&self, block_id: usize, buf: &mut [u8]); diff --git a/modules/page/src/buffer_cache.rs b/modules/page/src/buffer_cache.rs index b8e02f7d..2b94b0fa 100644 --- a/modules/page/src/buffer_cache.rs +++ b/modules/page/src/buffer_cache.rs @@ -13,7 +13,7 @@ use config::{ board::BLOCK_SIZE, mm::{ block_page_id, is_aligned_to_block, BUFFER_NEED_CACHE_CNT, MAX_BUFFERS_PER_PAGE, - MAX_BUFFER_PAGES, PAGE_SIZE, + MAX_BUFFER_HEADS, MAX_BUFFER_PAGES, PAGE_SIZE, }, }; use device_core::BlockDriverOps; @@ -35,7 +35,7 @@ pub struct BufferCache { // NOTE: Stores all accesses to block device. Some of them will be attached // to pages above, while others with file related will be attached to pages // stored in address space. - buffer_heads: BTreeMap>, + pub buffer_heads: LruCache>, } impl BufferCache { @@ -43,7 +43,7 @@ impl BufferCache { Self { device: None, pages: LruCache::new(NonZeroUsize::new(MAX_BUFFER_PAGES).unwrap()), - buffer_heads: BTreeMap::new(), + buffer_heads: LruCache::new(NonZeroUsize::new(MAX_BUFFER_HEADS).unwrap()), } } @@ -100,13 +100,20 @@ impl BufferCache { // {block_id}" ); let buffer_head = BufferHead::new_arc(block_id); buffer_head.inc_acc_cnt(); - self.buffer_heads.insert(block_id, buffer_head.clone()); + self.buffer_heads.push(block_id, buffer_head.clone()); buffer_head } } - pub fn get_buffer_head(&self, block_id: usize) -> Arc { - self.buffer_heads.get(&block_id).cloned().unwrap() + pub fn get_buffer_head_or_create(&mut self, block_id: usize) -> Arc { + // self.buffer_heads.get(&block_id).cloned().unwrap() + if let Some(buffer_head) = self.buffer_heads.get_mut(&block_id) { + buffer_head.clone() + } else { + let buffer_head = BufferHead::new_arc(block_id); + self.buffer_heads.push(block_id, buffer_head.clone()); + buffer_head + } } } diff --git a/modules/timer/src/timelimited_task.rs b/modules/timer/src/timelimited_task.rs index 0ad265ed..23e6fb2e 100644 --- a/modules/timer/src/timelimited_task.rs +++ b/modules/timer/src/timelimited_task.rs @@ -65,6 +65,10 @@ impl Future for IdleFuture { } } +pub async fn ksleep_s(sec: usize) { + TimeLimitedTaskFuture::new(Duration::from_secs(sec as u64), IdleFuture).await; +} + pub async fn ksleep_ms(msec: usize) { TimeLimitedTaskFuture::new(Duration::from_millis(msec as u64), IdleFuture).await; } diff --git a/modules/vfs-core/src/file.rs b/modules/vfs-core/src/file.rs index 12627047..979d4afd 100644 --- a/modules/vfs-core/src/file.rs +++ b/modules/vfs-core/src/file.rs @@ -94,10 +94,10 @@ pub trait File: Send + Sync + DowncastSync { let virtio_blk = device .downcast_arc::() .unwrap_or_else(|_| unreachable!()); - let buffer_caches = virtio_blk.cache.lock(); + let mut buffer_caches = virtio_blk.cache.lock(); for offset in (offset_aligned..offset_aligned + len).step_by(BLOCK_SIZE) { let block_id = inode.get_blk_idx(offset)?; - let buffer_head = buffer_caches.get_buffer_head(block_id as usize); + let buffer_head = buffer_caches.get_buffer_head_or_create(block_id as usize); page.insert_buffer_head(buffer_head); } @@ -326,14 +326,14 @@ impl dyn File { let virtio_blk = device .downcast_arc::() .unwrap_or_else(|_| unreachable!()); - let buffer_caches = virtio_blk.cache.lock(); + let mut buffer_caches = virtio_blk.cache.lock(); for offset_aligned_page in (round_down_to_page(old_size)..new_size).step_by(PAGE_SIZE) { let page = page_cache.get_page(offset_aligned_page).unwrap(); for i in page.buffer_head_cnts()..MAX_BUFFERS_PER_PAGE { let offset_aligned_block = offset_aligned_page + i * BLOCK_SIZE; if offset_aligned_block < new_size { let blk_idx = inode.get_blk_idx(offset_aligned_block)?; - let buffer_head = buffer_caches.get_buffer_head(blk_idx); + let buffer_head = buffer_caches.get_buffer_head_or_create(blk_idx); page.insert_buffer_head(buffer_head); } } diff --git a/modules/vfs/src/devfs/mod.rs b/modules/vfs/src/devfs/mod.rs index 8fe18cb0..6da6bd22 100644 --- a/modules/vfs/src/devfs/mod.rs +++ b/modules/vfs/src/devfs/mod.rs @@ -19,7 +19,6 @@ use crate::{ mod null; mod rtc; -pub mod stdio; pub mod tty; mod zero; diff --git a/modules/vfs/src/devfs/stdio.rs b/modules/vfs/src/devfs/stdio.rs deleted file mode 100644 index b33b4fe9..00000000 --- a/modules/vfs/src/devfs/stdio.rs +++ /dev/null @@ -1,130 +0,0 @@ -use alloc::{boxed::Box, sync::Arc}; - -use async_trait::async_trait; -use async_utils::yield_now; -use driver::{print, sbi::console_getchar}; -use systype::SyscallResult; -use vfs_core::{File, FileMeta, Inode, InodeMeta, InodeMode}; - -// TODO: This file has a lot to do - -pub struct StdOutInode { - meta: InodeMeta, -} - -pub struct StdOutFile { - meta: FileMeta, -} - -impl StdOutFile { - pub fn new() -> Arc { - let inode = Arc::new(StdOutInode { - meta: InodeMeta::new(InodeMode::CHAR, Arc::::new_zeroed(), 0), - }); - Arc::new(Self { - meta: FileMeta::new(Arc::::new_zeroed(), inode), - }) - } -} - -impl Inode for StdOutInode { - fn meta(&self) -> &vfs_core::InodeMeta { - &self.meta - } - - fn get_attr(&self) -> systype::SysResult { - todo!() - } -} - -#[async_trait] -impl File for StdOutFile { - fn meta(&self) -> &vfs_core::FileMeta { - &self.meta - } - - async fn base_read_at(&self, _offset: usize, _buf: &mut [u8]) -> SyscallResult { - todo!() - } - - async fn base_write_at(&self, _offset: usize, buf: &[u8]) -> SyscallResult { - if let Ok(data) = core::str::from_utf8(buf) { - print!("{}", data); - } else { - (0..buf.len()).for_each(|i| { - log::warn!("User stderr (non-utf8): {} ", buf[i]); - }); - } - Ok(buf.len()) - } - - fn base_read_dir(&self) -> systype::SysResult> { - todo!() - } - - fn flush(&self) -> systype::SysResult { - todo!() - } -} - -pub struct StdInInode { - meta: InodeMeta, -} - -pub struct StdInFile { - meta: FileMeta, -} - -impl StdInFile { - pub fn new() -> Arc { - let inode = Arc::new(StdInInode { - meta: InodeMeta::new(InodeMode::CHAR, Arc::::new_zeroed(), 0), - }); - Arc::new(Self { - meta: FileMeta::new(Arc::::new_zeroed(), inode.clone()), - }) - } -} - -impl Inode for StdInInode { - fn meta(&self) -> &InodeMeta { - &self.meta - } - - fn get_attr(&self) -> systype::SysResult { - todo!() - } -} - -#[async_trait] -impl File for StdInFile { - fn meta(&self) -> &FileMeta { - &self.meta - } - - async fn base_read_at(&self, _offset: usize, buf: &mut [u8]) -> systype::SysResult { - if buf.is_empty() { - return Ok(0); - } - let mut cnt = 0; - while cnt < buf.len() { - let c = console_getchar(); - buf[cnt] = c; - cnt += 1; - yield_now().await; - } - Ok(cnt) - } - - async fn base_write_at(&self, _offset: usize, _buf: &[u8]) -> systype::SysResult { - todo!() - } - - fn base_read_dir(&self) -> systype::SysResult> { - todo!() - } - - fn flush(&self) -> systype::SysResult { - todo!() - } -} diff --git a/modules/vfs/src/devfs/tty.rs b/modules/vfs/src/devfs/tty.rs index b89073b4..5ccc9984 100644 --- a/modules/vfs/src/devfs/tty.rs +++ b/modules/vfs/src/devfs/tty.rs @@ -4,7 +4,7 @@ use core::{cmp, ptr::drop_in_place}; use async_trait::async_trait; use async_utils::{block_on, get_waker, yield_now}; use device_core::{CharDevice, DeviceMajor}; -use driver::{get_device_manager, get_device_manager_mut, print, serial::Serial}; +use driver::{_print, get_device_manager, get_device_manager_mut, serial::Serial}; use ringbuffer::{AllocRingBuffer, RingBuffer}; use spin::Once; use strum::FromRepr; @@ -222,13 +222,6 @@ impl File for TtyFile { } async fn base_write_at(&self, _offset: usize, buf: &[u8]) -> SyscallResult { - let utf8_buf: Vec = buf.iter().filter(|c| c.is_ascii()).map(|c| *c).collect(); - // if PRINT_LOCKED { - // let _locked = PRINT_MUTEX.lock().await; - // print!("{}", unsafe { core::str::from_utf8_unchecked(&utf8_buf) }); - // } else { - // print!("{}", unsafe { core::str::from_utf8_unchecked(&utf8_buf) }); - // } let char_dev = &self .inode() .downcast_arc::() diff --git a/modules/vfs/src/fd_table.rs b/modules/vfs/src/fd_table.rs index ef83bb44..6bf156ac 100644 --- a/modules/vfs/src/fd_table.rs +++ b/modules/vfs/src/fd_table.rs @@ -7,7 +7,7 @@ use config::fs::MAX_FD_NUM; use systype::{RLimit, SysError, SysResult}; use vfs_core::{File, OpenFlags}; -use crate::devfs::{stdio, tty::TTY}; +use crate::devfs::tty::TTY; pub type Fd = usize; From abba55d47aa425d8ccc3f085746ebc8cb709ad47 Mon Sep 17 00:00:00 2001 From: ChenRuiwei <1982833213@qq.com> Date: Fri, 19 Jul 2024 22:15:49 +0800 Subject: [PATCH 08/10] fix(buffer_cache): increase buffer head count and heap size --- config/src/mm.rs | 9 ++++++--- kernel/src/ipc/shm.rs | 1 + kernel/src/main.rs | 27 +++++++++++++++++---------- kernel/src/task/manager.rs | 6 +++--- kernel/src/task/schedule.rs | 2 +- kernel/src/task/task.rs | 4 ++-- modules/device-core/src/lib.rs | 1 + modules/vfs-core/src/inode.rs | 1 - modules/vfs-core/src/super_block.rs | 4 ---- 9 files changed, 31 insertions(+), 24 deletions(-) diff --git a/config/src/mm.rs b/config/src/mm.rs index ceb858d4..a9b82998 100644 --- a/config/src/mm.rs +++ b/config/src/mm.rs @@ -13,17 +13,19 @@ pub const KERNEL_OFFSET: usize = 0x20_0000; pub const KERNEL_START_PHYS: usize = RAM_START + KERNEL_OFFSET; pub const KERNEL_START: usize = VIRT_START + KERNEL_OFFSET; -pub const KERNEL_STACK_SIZE: usize = 64 * 1024; // 64K -pub const KERNEL_HEAP_SIZE: usize = 32 * 1024 * 1024; // 32M +pub const KERNEL_STACK_SIZE: usize = 64 * 1024; +pub const KERNEL_HEAP_SIZE: usize = 48 * 1024 * 1024; register_mut_const!(pub DTB_ADDR, usize, 0); /// boot pub const HART_START_ADDR: usize = 0x80200000; -pub const USER_STACK_SIZE: usize = 8 * 1024 * 1024; // 8M +pub const USER_STACK_SIZE: usize = 8 * 1024 * 1024; pub const USER_STACK_PRE_ALLOC_SIZE: usize = 4 * PAGE_SIZE; +pub const USER_ELF_PRE_ALLOC_PAGE_CNT: usize = 0; + pub const PAGE_SIZE: usize = 1 << PAGE_SIZE_BITS; pub const PAGE_MASK: usize = PAGE_SIZE - 1; pub const PAGE_SIZE_BITS: usize = 12; @@ -39,6 +41,7 @@ pub const PAGE_TABLE_LEVEL_NUM: usize = 3; /// Dynamic linked interpreter address range in user space pub const DL_INTERP_OFFSET: usize = 0x20_0000_0000; +pub const MAX_BUFFER_HEADS: usize = 0x30000; pub const MAX_BUFFER_CACHE: usize = 0x1000; pub const MAX_BUFFER_PAGES: usize = MAX_BUFFER_CACHE / MAX_BUFFERS_PER_PAGE; pub const MAX_BUFFERS_PER_PAGE: usize = PAGE_SIZE / BLOCK_SIZE; diff --git a/kernel/src/ipc/shm.rs b/kernel/src/ipc/shm.rs index a4416e12..69690dbb 100644 --- a/kernel/src/ipc/shm.rs +++ b/kernel/src/ipc/shm.rs @@ -52,6 +52,7 @@ impl ShmIdDs { shm_nattch: 0, } } + pub fn attach(&mut self, lpid: usize) { // shm_atime is set to the current time. self.shm_atime = get_time_sec(); diff --git a/kernel/src/main.rs b/kernel/src/main.rs index ca422116..11c463e4 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -34,7 +34,7 @@ use ::net::init_network; use driver::BLOCK_DEVICE; use timer::timelimited_task::ksleep_s; -use crate::processor::hart; +use crate::{processor::hart, task::TASK_MANAGER}; extern crate alloc; @@ -74,15 +74,22 @@ fn rust_main(hart_id: usize, dtb_addr: usize) { task::spawn_init_proc(); }); - task::spawn_kernel_task(async move { - loop { - log::error!( - "buffer head cnts {}", - BLOCK_DEVICE.get().unwrap().buffer_head_cnts() - ); - ksleep_s(3).await; - } - }); + // task::spawn_kernel_task(async move { + // loop { + // log::error!( + // "buffer head cnts {}", + // BLOCK_DEVICE.get().unwrap().buffer_head_cnts() + // ); + // ksleep_s(3).await; + // } + // }); + // + // task::spawn_kernel_task(async move { + // loop { + // log::error!("task counts {}", TASK_MANAGER.len()); + // ksleep_s(3).await; + // } + // }); #[cfg(feature = "smp")] boot::start_harts(hart_id); diff --git a/kernel/src/task/manager.rs b/kernel/src/task/manager.rs index eef51298..e78e8b45 100644 --- a/kernel/src/task/manager.rs +++ b/kernel/src/task/manager.rs @@ -51,9 +51,9 @@ impl TaskManager { Ok(()) } - // pub fn total_num(&self) -> usize { - // self.0.lock().len() - // } + pub fn len(&self) -> usize { + self.0.lock().len() + } } /// PGid -> Process group diff --git a/kernel/src/task/schedule.rs b/kernel/src/task/schedule.rs index 9509aad1..cae1ea04 100644 --- a/kernel/src/task/schedule.rs +++ b/kernel/src/task/schedule.rs @@ -6,7 +6,7 @@ use core::{ time::Duration, }; -use arch::time::get_time_duration; +use arch::time::{get_time_duration, get_time_us}; use async_utils::{get_waker, suspend_now, yield_now}; use timer::{Timer, TIMER_MANAGER}; diff --git a/kernel/src/task/task.rs b/kernel/src/task/task.rs index 521835ba..bb4a56ab 100644 --- a/kernel/src/task/task.rs +++ b/kernel/src/task/task.rs @@ -10,7 +10,7 @@ use core::{ task::Waker, }; -use arch::memory::sfence_vma_all; +use arch::{memory::sfence_vma_all, time::get_time_us}; use config::{ mm::{DL_INTERP_OFFSET, USER_STACK_SIZE}, process::INIT_PROC_PID, @@ -408,7 +408,6 @@ impl Task { new } - // TODO: figure out what should be reserved across this syscall pub fn do_execve( self: &Arc, elf_file: Arc, @@ -428,6 +427,7 @@ impl Task { } else { auxv.push(AuxHeader::new(AT_BASE, 0)); } + // NOTE: should do termination before switching page table, so that other // threads will trap in by page fault and be handled by `do_exit` log::debug!("[Task::do_execve] terminating all threads except the leader"); diff --git a/modules/device-core/src/lib.rs b/modules/device-core/src/lib.rs index 90a38d86..53e212f7 100644 --- a/modules/device-core/src/lib.rs +++ b/modules/device-core/src/lib.rs @@ -11,6 +11,7 @@ use async_trait::async_trait; use downcast_rs::{impl_downcast, DowncastSync}; use error::DevResult; pub use smoltcp::phy::{Loopback, Medium}; + /// General Device Operations #[derive(Debug, Clone, Copy, Eq, PartialEq)] pub enum DeviceType { diff --git a/modules/vfs-core/src/inode.rs b/modules/vfs-core/src/inode.rs index fc1f4d97..ff0f4471 100644 --- a/modules/vfs-core/src/inode.rs +++ b/modules/vfs-core/src/inode.rs @@ -152,7 +152,6 @@ impl_downcast!(sync Inode); pub enum InodeState { /// Init state, indicates that this inode is not loaded from disk yet. UnInit, - /// already sync Sync, Dirty, Removed, diff --git a/modules/vfs-core/src/super_block.rs b/modules/vfs-core/src/super_block.rs index efe6c335..db41cf1e 100644 --- a/modules/vfs-core/src/super_block.rs +++ b/modules/vfs-core/src/super_block.rs @@ -18,10 +18,6 @@ pub struct SuperBlockMeta { pub fs_type: Weak, /// Root dentry points to the mount point. pub root_dentry: Once>, - // /// All inodes. - // pub inodes: Mutex>>, - // /// All dirty inodes. - // pub dirty: Mutex>>, } impl SuperBlockMeta { From 068f3ad6f5a9bba115d41be0d357615105c2b846 Mon Sep 17 00:00:00 2001 From: ChenRuiwei <1982833213@qq.com> Date: Sat, 20 Jul 2024 15:20:23 +0800 Subject: [PATCH 09/10] fix(buffer_cache): block cache is enabled to transfer to file cache now Some block caches are mis recognized, e.g. directory. When a directory is frequently accessed, it is likely to be recognized as a block cache. However, when the directory is removed, file may be created on the same block, and the block is now as a file cache block now. --- driver/src/virtio/virtio_blk.rs | 15 +++++++++------ kernel/src/task/mod.rs | 7 +++++-- modules/device-core/src/lib.rs | 2 ++ modules/ext4/src/dentry.rs | 2 +- modules/page/src/buffer_cache.rs | 25 ++++++++++++++++++++----- modules/page/src/page.rs | 16 +++++++++++++++- modules/vfs-core/src/file.rs | 3 +++ 7 files changed, 55 insertions(+), 15 deletions(-) diff --git a/driver/src/virtio/virtio_blk.rs b/driver/src/virtio/virtio_blk.rs index 16bb2b88..36d73c5e 100644 --- a/driver/src/virtio/virtio_blk.rs +++ b/driver/src/virtio/virtio_blk.rs @@ -30,8 +30,15 @@ impl BlockDriverOps for VirtIoBlkDev { BLOCK_SIZE } + fn buffer_head_cnts(&self) -> usize { + self.cache.lock().buffer_heads.len() + } + + fn remove_buffer_page(&self, block_id: usize) { + self.cache.lock().pages.pop(&block_id); + } + fn base_read_block(&self, block_id: usize, buf: &mut [u8]) { - // log::error!("read blk id {}", block_id); let res = self.device.lock().read_blocks(block_id, buf); if res.is_err() { panic!( @@ -55,10 +62,6 @@ impl BlockDriverOps for VirtIoBlkDev { fn write_block(&self, block_id: usize, buf: &[u8]) { self.cache.lock().write_block(block_id, buf) } - - fn buffer_head_cnts(&self) -> usize { - self.cache.lock().buffer_heads.len() - } } impl VirtIoBlkDev { @@ -80,7 +83,7 @@ impl VirtIoBlkDev { name: "virtio-blk".to_string(), mmio_base, mmio_size, - irq_no: None, // TODO: block device don't support interrupts in this system + irq_no: None, // TODO: support interrupt for block device dtype: DeviceType::Block, }; let blk_dev = Arc::new(Self { diff --git a/kernel/src/task/mod.rs b/kernel/src/task/mod.rs index a7d870f4..8165274a 100644 --- a/kernel/src/task/mod.rs +++ b/kernel/src/task/mod.rs @@ -28,8 +28,11 @@ pub fn spawn_init_proc() { let argv = Vec::new(); let envp = Vec::new(); - let path = Path::new(sys_root_dentry(), sys_root_dentry(), init_proc_path); - let file = path.walk().unwrap().open().unwrap(); + let file = Path::new(sys_root_dentry(), sys_root_dentry(), init_proc_path) + .walk() + .unwrap() + .open() + .unwrap(); let elf_data = block_on(async { file.read_all().await }).unwrap(); let mut memory_space = MemorySpace::new_user(); diff --git a/modules/device-core/src/lib.rs b/modules/device-core/src/lib.rs index 53e212f7..79bc9412 100644 --- a/modules/device-core/src/lib.rs +++ b/modules/device-core/src/lib.rs @@ -101,6 +101,8 @@ pub trait BlockDriverOps: BaseDriverOps { fn buffer_head_cnts(&self) -> usize; + fn remove_buffer_page(&self, block_id: usize); + /// Read data form block to buffer fn base_read_block(&self, block_id: usize, buf: &mut [u8]); diff --git a/modules/ext4/src/dentry.rs b/modules/ext4/src/dentry.rs index e61ee5c8..f831a40e 100644 --- a/modules/ext4/src/dentry.rs +++ b/modules/ext4/src/dentry.rs @@ -107,7 +107,7 @@ impl Dentry for Ext4Dentry { .unwrap_or_else(|_| unreachable!()); let sub_dentry = self.get_child(name).unwrap(); let fpath = sub_dentry.path(); - log::debug!("[Ext4Dentry::base_remove] path: {fpath}"); + log::info!("[Ext4Dentry::base_remove] path: {fpath}"); let mut file = inode.file.lock(); if file.check_inode_exist(&fpath, InodeTypes::EXT4_DE_DIR) { // Recursive directory remove diff --git a/modules/page/src/buffer_cache.rs b/modules/page/src/buffer_cache.rs index 2b94b0fa..4c843727 100644 --- a/modules/page/src/buffer_cache.rs +++ b/modules/page/src/buffer_cache.rs @@ -22,19 +22,20 @@ use lru::LruCache; use spin::Once; use sync::mutex::SpinNoIrqLock; -use crate::Page; +use crate::{Page, PageKind}; pub struct BufferCache { device: Option>, /// Block page id to `Page`. // NOTE: These `Page`s are pages without file, only exist for caching pure // block data. - pages: LruCache>, + pub pages: LruCache>, /// Block idx to `BufferHead`. // TODO: add lru support, otherwise may occupy too much heap space // NOTE: Stores all accesses to block device. Some of them will be attached // to pages above, while others with file related will be attached to pages // stored in address space. + // PERF: perf issue will happen when lru cache is full pub buffer_heads: LruCache>, } @@ -80,7 +81,7 @@ impl BufferCache { buffer_head.inc_acc_cnt(); // log::error!("acc cnt {}", buffer_head.acc_cnt()); if buffer_head.need_cache() && !buffer_head.has_cached() { - // log::error!("need cache"); + // log::error!("block id {block_id} need cache"); if let Some(page) = self.pages.get_mut(&block_page_id(block_id)) { // log::error!("has page"); device.base_read_block(block_id, page.block_bytes_array(block_id)); @@ -166,10 +167,24 @@ impl BufferHead { pub fn init(&self, page: &Arc, offset: usize) { if self.has_cached() { log::error!( - "block id {} already cached, with acc_cnt {}", + "block id {} already cached, with acc_cnt {}, page kind {:?}", self.block_id, - self.acc_cnt() + self.acc_cnt(), + self.page().kind() ); + // only block cache can be transfered to file cache, e.g. a directory is mis + // recognized as block cache + assert!(self.page().kind().is_block_cache()); + assert!(page.kind().is_file_cache()); + match &self.page().kind() { + PageKind::BlockCache(inner) => { + let mut inner = inner.lock(); + let device = inner.device.upgrade().unwrap(); + device.remove_buffer_page(self.block_id); + // block page should be dropped here + } + _ => panic!(), + } } debug_assert!(is_aligned_to_block(offset) && offset < PAGE_SIZE); let mut inner = self.inner.lock(); diff --git a/modules/page/src/page.rs b/modules/page/src/page.rs index f981e2fc..3d5a56c7 100644 --- a/modules/page/src/page.rs +++ b/modules/page/src/page.rs @@ -23,13 +23,27 @@ pub enum PageKind { BlockCache(SpinNoIrqLock), } +impl core::fmt::Debug for PageKind { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("PageKind") + .field("kind", &{ + match self { + PageKind::Normal => "normal", + PageKind::FileCache(_) => "file cache", + PageKind::BlockCache(_) => "block cache", + } + }) + .finish() + } +} + pub struct Page { frame: FrameTracker, kind: PageKind, } pub struct BufferInfo { - device: Weak, + pub device: Weak, buffer_heads: LinkedList, buffer_head_cnts: usize, } diff --git a/modules/vfs-core/src/file.rs b/modules/vfs-core/src/file.rs index 979d4afd..8bfccd4e 100644 --- a/modules/vfs-core/src/file.rs +++ b/modules/vfs-core/src/file.rs @@ -333,8 +333,11 @@ impl dyn File { let offset_aligned_block = offset_aligned_page + i * BLOCK_SIZE; if offset_aligned_block < new_size { let blk_idx = inode.get_blk_idx(offset_aligned_block)?; + log::debug!("offset {offset_aligned_block}, blk idx {blk_idx}"); let buffer_head = buffer_caches.get_buffer_head_or_create(blk_idx); page.insert_buffer_head(buffer_head); + } else { + break; } } } From 225f8afa04b66a89f20415fcf17fe71945f0a805 Mon Sep 17 00:00:00 2001 From: ChenRuiwei <1982833213@qq.com> Date: Sat, 20 Jul 2024 15:56:52 +0800 Subject: [PATCH 10/10] refactor(user): use final_tests to test all --- config/src/mm.rs | 2 +- user/src/bin/{runtestcase.rs => final_tests.rs} | 17 +++++------------ 2 files changed, 6 insertions(+), 13 deletions(-) rename user/src/bin/{runtestcase.rs => final_tests.rs} (79%) diff --git a/config/src/mm.rs b/config/src/mm.rs index a9b82998..a223b65b 100644 --- a/config/src/mm.rs +++ b/config/src/mm.rs @@ -14,7 +14,7 @@ pub const KERNEL_START_PHYS: usize = RAM_START + KERNEL_OFFSET; pub const KERNEL_START: usize = VIRT_START + KERNEL_OFFSET; pub const KERNEL_STACK_SIZE: usize = 64 * 1024; -pub const KERNEL_HEAP_SIZE: usize = 48 * 1024 * 1024; +pub const KERNEL_HEAP_SIZE: usize = 64 * 1024 * 1024; register_mut_const!(pub DTB_ADDR, usize, 0); diff --git a/user/src/bin/runtestcase.rs b/user/src/bin/final_tests.rs similarity index 79% rename from user/src/bin/runtestcase.rs rename to user/src/bin/final_tests.rs index 0ca1a10b..5bbb99be 100644 --- a/user/src/bin/runtestcase.rs +++ b/user/src/bin/final_tests.rs @@ -10,20 +10,15 @@ use user_lib::{execve, fork, wait, waitpid}; #[macro_use] extern crate user_lib; -// const TESTCASES: [&str; 0] = []; - const TESTCASES: [&str; 8] = [ - // "cyclictest_testcode.sh", "busybox_testcode.sh", "lua_testcode.sh", "time-test", "libc-bench", "libctest_testcode.sh", - "iozone_testcode.sh", "lmbench_testcode.sh", + "iozone_testcode.sh", "unixbench_testcode.sh", - // "netperf_testcode.sh", - // "iperf_testcode.sh", ]; #[no_mangle] @@ -52,15 +47,13 @@ fn main() -> i32 { waitpid(pid as usize, &mut exit_code); } } - println!(" !TEST FINISH! "); } else { loop { let mut exit_code: i32 = 0; - let _pid = wait(&mut exit_code); - // println!( - // "[initproc] Released a zombie process, pid={}, exit_code={}", - // pid, exit_code, - // ); + let pid = wait(&mut exit_code); + if pid < 0 { + break; + } } } 0