diff --git a/.gitignore b/.gitignore index 2b0422cc..464b343a 100644 --- a/.gitignore +++ b/.gitignore @@ -32,4 +32,4 @@ oscomp-debian tools/siglibc tools/testsuits-for-oskernel tools/bash-5.1.16 -alien* \ No newline at end of file +alien-* \ No newline at end of file diff --git a/Makefile b/Makefile index f77a06c9..d006aaac 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,13 @@ FEATURES := QEMU_ARGS := MEMORY_SIZE := 128M img ?=fat32 +SLAB ?=n +TALLOC ?=y +BUDDY ?=n +comma:= , +empty:= +space:= $(empty) $(empty) ifeq ($(GUI),y) QEMU_ARGS += -device virtio-gpu-device \ @@ -40,7 +46,16 @@ else FEATURES += qemu endif +ifeq ($(SLAB),y) +FEATURES += slab +else ifeq ($(TALLOC),y) +FEATURES += talloc +else ifeq ($(BUDDY),y) +FEATURES += buddy +endif + +FEATURES := $(subst $(space),$(comma),$(FEATURES)) define boot_qemu qemu-system-riscv64 \ @@ -64,11 +79,11 @@ build:compile compile: - @cargo build --release -p boot --target riscv64gc-unknown-none-elf --features $(FEATURES) + cargo build --release -p boot --target riscv64gc-unknown-none-elf --features $(FEATURES) @(nm -n ${KERNEL_FILE} | $(TRACE_EXE) > kernel/src/trace/kernel_symbol.S) @#call trace_info - @cargo build --release -p boot --target riscv64gc-unknown-none-elf --features $(FEATURES) - @$(OBJCOPY) $(KERNEL_FILE) --strip-all -O binary $(KERNEL_BIN) + cargo build --release -p boot --target riscv64gc-unknown-none-elf --features $(FEATURES) + @#$(OBJCOPY) $(KERNEL_FILE) --strip-all -O binary $(KERNEL_BIN) @cp $(KERNEL_FILE) ./kernel-qemu trace_info: @@ -97,13 +112,13 @@ board:install compile vf2:board @mkimage -f ./tools/vf2.its ./alien-vf2.itb - @rm ./alien.bin + @#rm ./alien.bin @cp ./alien-vf2.itb /home/godones/projects/tftpboot/ cv1811h:board @mkimage -f ./tools/cv1811h.its ./alien-cv1811h.itb - @rm ./alien.bin + @#rm ./alien.bin @cp ./alien-cv1811h.itb /home/godones/projects/tftpboot/ diff --git a/alien.bin b/alien.bin new file mode 100755 index 00000000..f920bba1 Binary files /dev/null and b/alien.bin differ diff --git a/boot/Cargo.toml b/boot/Cargo.toml index e80c1188..a9c1a01a 100644 --- a/boot/Cargo.toml +++ b/boot/Cargo.toml @@ -6,18 +6,22 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -kernel = { path = "../kernel" } cfg-if = "1.0.0" riscv = "0.10.0" preprint = "0.1.0" basemachine = { path = "../modules/basemachine" } +kernel = { version = "0.1.0", path = "../kernel" } [features] -default = ["qemu"] -vf2 = [] -cv1811h = [] -qemu = [] +default = [] +vf2 = ["kernel/vf2"] +cv1811h = ["kernel/cv1811h"] +qemu = ["kernel/qemu"] +sivife = ["kernel/sifive"] +slab = ["kernel/slab"] +talloc = ["kernel/talloc"] +buddy = ["kernel/buddy"] -[build-dependencies] \ No newline at end of file +[build-dependencies] diff --git a/boot/build.rs b/boot/build.rs index 065c75fa..314f7d29 100644 --- a/boot/build.rs +++ b/boot/build.rs @@ -1,7 +1,7 @@ +use std::{env, fs}; use std::fs::File; use std::io::Write; use std::path::Path; -use std::{env, fs}; fn main() { // 指定target @@ -13,9 +13,9 @@ fn main() { let ld = fs::read_to_string(ld_path).unwrap(); #[cfg(not(feature = "vf2"))] - let base_addr = 0x80200000usize; + let base_addr = 0x80200000usize; #[cfg(feature = "vf2")] - let base_addr = 0x40200000; + let base_addr: usize = 0x80200000; let base_addr = format!("BASE_ADDRESS = {};", base_addr); let mut new_config = String::new(); for line in ld.lines() { diff --git a/boot/src/main.rs b/boot/src/main.rs index f05c6b53..3e9a2d4c 100644 --- a/boot/src/main.rs +++ b/boot/src/main.rs @@ -2,27 +2,31 @@ #![no_main] #![feature(naked_functions)] #![feature(asm_const)] +#![feature(stmt_expr_attributes)] use core::arch::asm; use core::hint::spin_loop; use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; +use cfg_if::cfg_if; + use basemachine::machine_info_from_dtb; +use kernel::{config, init_machine_info, println, syscall, task, thread_local_init, timer, trap}; +use kernel::arch::hart_id; +#[cfg(not(feature = "qemu"))] +use kernel::board; use kernel::config::{CPU_NUM, STACK_SIZE}; use kernel::fs::vfs::init_vfs; use kernel::memory::{init_memory_system, kernel_info}; use kernel::print::init_print; use kernel::sbi::hart_start; use kernel::task::init_per_cpu; -use kernel::trap::set_kernel_trap_entry; -use kernel::{ - config, driver, init_machine_info, println, syscall, task, thread_local_init, timer, trap, -}; // 多核启动标志 static STARTED: AtomicBool = AtomicBool::new(false); static CPUS: AtomicUsize = AtomicUsize::new(0); +#[inline] fn clear_bss() { extern "C" { fn sbss(); @@ -44,6 +48,9 @@ extern "C" fn _start() { unsafe { asm!("\ mv tp, a0 + csrw sscratch, a1 + csrci sstatus, 0x02 + csrw sie, zero add t0, a0, 1 slli t0, t0, 13 la sp, {boot_stack} @@ -56,41 +63,68 @@ extern "C" fn _start() { } } +#[inline] +fn device_tree_addr() -> usize { + let mut res: usize; + unsafe { + asm!( + " csrr {}, sscratch", + out(reg) res, + ) + } + res +} + /// rust_main is the entry of the kernel #[no_mangle] -fn main(hart_id: usize, device_tree_addr: usize) -> ! { - set_kernel_trap_entry(); +extern "C" fn main(_: usize, _: usize) -> ! { if !STARTED.load(Ordering::Relaxed) { + // this will clear the kernel stack, so if we want get hartid or device_tree_addr, + // clear_bss will cause error using vf2 clear_bss(); println!("{}", config::FLAG); + let mut device_tree_addr = device_tree_addr(); + #[cfg(feature = "vf2")] + device_tree_addr = board::FDT.as_ptr() as usize; + init_print(); + println!("boot hart id: {}, device tree addr: {:#x}", hart_id(), device_tree_addr); let machine_info = machine_info_from_dtb(device_tree_addr); println!("{:#x?}", machine_info); init_machine_info(machine_info.clone()); kernel_info(machine_info.memory.end); - init_print(); init_memory_system(machine_info.memory.end, true); thread_local_init(); + #[cfg(feature = "qemu")] driver::init_dt(device_tree_addr); trap::init_trap_subsystem(); init_per_cpu(); + cfg_if! { + if #[cfg(not(feature = "qemu"))]{ + board::checkout_fs_img(); + use kernel::driver::init_fake_disk; + init_fake_disk(); + } + } init_vfs(); syscall::register_all_syscall(); + println!("register syscall success"); task::init_process(); CPUS.fetch_add(1, Ordering::Release); STARTED.store(true, Ordering::Relaxed); - init_other_hart(hart_id); + init_other_hart(hart_id()); } else { while !STARTED.load(Ordering::Relaxed) { spin_loop(); } thread_local_init(); - println!("hart {:#x} start", kernel::arch::hart_id()); + println!("hart {:#x} start", hart_id()); init_memory_system(0, false); thread_local_init(); trap::init_trap_subsystem(); CPUS.fetch_add(1, Ordering::Release); } timer::set_next_trigger(); + println!("begin run task..."); task::schedule::first_into_user(); } diff --git a/kernel-qemu b/kernel-qemu index 0d31950e..dc904177 100755 Binary files a/kernel-qemu and b/kernel-qemu differ diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index c0af4721..124f2bb5 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -46,10 +46,12 @@ talc = { version = "1.0", optional = true } buddy_system_allocator = { version = "0.9.0", optional = true } [features] -default = ["talloc"] +default = [] vf2 = [] cv1811h = [] sifive = [] +qemu = [] + slab = [] talloc = ["talc"] buddy = ["buddy_system_allocator"] \ No newline at end of file diff --git a/kernel/src/arch/mod.rs b/kernel/src/arch/mod.rs index 3f295c5a..6e308dc5 100644 --- a/kernel/src/arch/mod.rs +++ b/kernel/src/arch/mod.rs @@ -6,12 +6,14 @@ use self::riscv::sstatus; pub mod riscv; pub fn hart_id() -> usize { - let id: usize; + let mut id: usize; unsafe { asm!( "mv {},tp", out(reg)id, ); } + #[cfg(any(feature = "vf2", feature = "sifive"))] + id -= 1; id } diff --git a/kernel/src/arch/riscv.rs b/kernel/src/arch/riscv.rs index a0c7abf3..b8d39679 100644 --- a/kernel/src/arch/riscv.rs +++ b/kernel/src/arch/riscv.rs @@ -24,6 +24,9 @@ pub mod sstatus { SPP::User } } + pub fn set_spie(&mut self) { + self.0.set_bit(5, true); + } pub fn sie(&self) -> bool { self.0.get_bit(1) } diff --git a/kernel/src/board/mod.rs b/kernel/src/board/mod.rs index 8724d75c..0351a72e 100644 --- a/kernel/src/board/mod.rs +++ b/kernel/src/board/mod.rs @@ -1,2 +1,37 @@ +use core::arch::global_asm; + +#[cfg(feature = "cv1811")] +pub use cv1811::*; +#[cfg(feature = "vf2")] +pub use vf2::*; + mod cv1811; mod vf2; + + +// pub static FAT32_IMG: &[u8] = include_bytes!("../../../tools/sdcard.img"); +#[cfg(any(feature = "vf2", feature = "cv1811h"))] +global_asm!( + r#" + .section .data + .global img_start + .global img_end + .align 12 + img_start: + .incbin "./tools/sdcard.img" + img_end: + "# +); + +#[cfg(any(feature = "vf2", feature = "cv1811h"))] +extern "C" { + pub fn img_start(); + pub fn img_end(); +} + +pub fn checkout_fs_img() { + let img_start = img_start as usize; + let img_end = img_end as usize; + let img_size = img_end - img_start; + println!("img_start: {:#x}, img_end: {:#x}, img_size: {:#x}", img_start, img_end, img_size); +} \ No newline at end of file diff --git a/kernel/src/board/vf2.rs b/kernel/src/board/vf2.rs index 8b137891..5836cb0b 100644 --- a/kernel/src/board/vf2.rs +++ b/kernel/src/board/vf2.rs @@ -1 +1,5 @@ +#[repr(align(4))] +struct _Wrapper(T); + +pub const FDT: &[u8] = &_Wrapper(*include_bytes!("../../../tools/jh7110-visionfive-v2.dtb")).0; diff --git a/kernel/src/config.rs b/kernel/src/config.rs index 1cc6d66a..464146e7 100644 --- a/kernel/src/config.rs +++ b/kernel/src/config.rs @@ -5,10 +5,10 @@ pub const FLAG: &str = r" / ___ \ | | | | | __/ | | | | /_/ \_\ |_| |_| \___| |_| |_| "; -#[cfg(not(feature = "vf2"))] +#[cfg(feature = "qemu")] pub const CLOCK_FREQ: usize = 12500000; #[cfg(feature = "vf2")] -pub const CLOCK_FREQ: usize = 4000000; +pub const CLOCK_FREQ: usize = 400_0000; #[cfg(feature = "sifive")] pub const CLOCK_FREQ: usize = 100_0000; @@ -22,8 +22,9 @@ pub const STACK_SIZE: usize = 1024 * 8; pub const STACK_SIZE_BITS: usize = 16; pub const TIMER_FREQ: usize = CLOCK_FREQ; -pub const CPU_NUM: usize = 4; +pub const CPU_NUM: usize = 1; +#[cfg(feature = "qemu")] pub const MMIO: &[(usize, usize)] = &[ (0x0010_0000, 0x00_2000), // VIRT_TEST/RTC in virt machine (0x2000000, 0x10000), @@ -32,6 +33,14 @@ pub const MMIO: &[(usize, usize)] = &[ (0x3000_0000, 0x1000_0000), ]; + +#[cfg(feature = "vf2")] +pub const MMIO: &[(usize, usize)] = &[ + (0x17040000, 0x10000), // RTC + (0xc000000, 0x4000000), //PLIC + (0x00_1000_0000, 0x10000) // UART +]; + pub const FRAME_MAX_ORDER: usize = 16; // todo!(if the app linker script changed, this should be changed too) diff --git a/kernel/src/driver/block_device.rs b/kernel/src/driver/block_device.rs index 4d312064..25e377ee 100644 --- a/kernel/src/driver/block_device.rs +++ b/kernel/src/driver/block_device.rs @@ -1,3 +1,5 @@ +use alloc::boxed::Box; +use alloc::string::ToString; use alloc::sync::Arc; use alloc::vec::Vec; use core::cmp::min; @@ -19,14 +21,14 @@ use crate::memory::{frame_alloc, FrameTracker}; const PAGE_CACHE_SIZE: usize = FRAME_SIZE; -pub struct QemuBlockDevice { - pub device: Mutex>, +pub struct GenericBlockDevice { + pub device: Mutex>, cache: Mutex>, dirty: Mutex>, } -impl QemuBlockDevice { - pub fn new(device: VirtIOBlk) -> Self { +impl GenericBlockDevice { + pub fn new(device: Box) -> Self { Self { device: Mutex::new(device), cache: Mutex::new(LruCache::new(NonZeroUsize::new(512).unwrap())), // 4MB cache @@ -35,21 +37,21 @@ impl QemuBlockDevice { } } -unsafe impl Send for QemuBlockDevice {} +unsafe impl Send for GenericBlockDevice {} -unsafe impl Sync for QemuBlockDevice {} +unsafe impl Sync for GenericBlockDevice {} lazy_static! { - pub static ref QEMU_BLOCK_DEVICE: Mutex>> = Mutex::new(Vec::new()); + pub static ref QEMU_BLOCK_DEVICE: Mutex>> = Mutex::new(Vec::new()); } -impl Debug for QemuBlockDevice { +impl Debug for GenericBlockDevice { fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { f.debug_struct("QemuBlockDevice").finish() } } -impl Device for QemuBlockDevice { +impl Device for GenericBlockDevice { fn read(&self, buf: &mut [u8], offset: usize) -> Result { let mut page_id = offset / PAGE_CACHE_SIZE; let mut offset = offset % PAGE_CACHE_SIZE; @@ -152,3 +154,63 @@ impl Device for QemuBlockDevice { // self.dirty.lock().clear(); } } + +pub trait LowBlockDriver { + fn read_block(&mut self, block_id: usize, buf: &mut [u8]) -> Result<(), VfsError>; + fn write_block(&mut self, block_id: usize, buf: &[u8]) -> Result<(), VfsError>; + fn capacity(&self) -> usize; + fn flush(&mut self) {} +} + +impl LowBlockDriver for VirtIOBlk { + fn read_block(&mut self, block_id: usize, buf: &mut [u8]) -> Result<(), VfsError> { + self.read_block(block_id, buf).map_err(|_| VfsError::DiskFsError("read block error".to_string())) + } + fn write_block(&mut self, block_id: usize, buf: &[u8]) -> Result<(), VfsError> { + self.write_block(block_id, buf).map_err(|_| VfsError::DiskFsError("write block error".to_string())) + } + + fn capacity(&self) -> usize { + self.capacity() as usize + } +} + +struct MemoryFat32Img { + data: &'static mut [u8], +} + +impl LowBlockDriver for MemoryFat32Img { + fn read_block(&mut self, block_id: usize, buf: &mut [u8]) -> Result<(), VfsError> { + let start = block_id * 512; + let end = start + 512; + buf.copy_from_slice(&self.data[start..end]); + Ok(()) + } + fn write_block(&mut self, block_id: usize, buf: &[u8]) -> Result<(), VfsError> { + let start = block_id * 512; + let end = start + 512; + self.data[start..end].copy_from_slice(buf); + Ok(()) + } + + fn capacity(&self) -> usize { + self.data.len() / 512 + } +} + +impl MemoryFat32Img { + pub fn new(data: &'static mut [u8]) -> Self { + Self { + data, + } + } +} + +#[cfg(any(feature = "vf2", feature = "cv1811h"))] +pub fn init_fake_disk() { + use crate::board::{img_end, img_start}; + let data = unsafe { core::slice::from_raw_parts_mut(img_start as *mut u8, img_end as usize - img_start as usize) }; + let device = GenericBlockDevice::new(Box::new(MemoryFat32Img::new(data))); + QEMU_BLOCK_DEVICE.lock().push(Arc::new(device)); + println!("init fake disk success"); +} \ No newline at end of file diff --git a/kernel/src/driver/dtb.rs b/kernel/src/driver/dtb.rs index a8ec6647..e566179f 100644 --- a/kernel/src/driver/dtb.rs +++ b/kernel/src/driver/dtb.rs @@ -1,32 +1,33 @@ +use alloc::boxed::Box; use alloc::collections::BTreeMap; use alloc::sync::Arc; use alloc::vec::Vec; use core::ptr::NonNull; +use fdt::Fdt; use fdt::node::FdtNode; use fdt::standard_nodes::Compatible; -use fdt::Fdt; use hashbrown::HashMap; use lazy_static::lazy_static; use spin::Once; use virtio_drivers::device::blk::VirtIOBlk; use virtio_drivers::device::gpu::VirtIOGpu; use virtio_drivers::device::input::VirtIOInput; -use virtio_drivers::transport::mmio::{MmioTransport, VirtIOHeader}; use virtio_drivers::transport::{DeviceType, Transport}; +use virtio_drivers::transport::mmio::{MmioTransport, VirtIOHeader}; use kernel_sync::Mutex; use plic::{Mode, PLIC}; use crate::arch::hart_id; use crate::config::{CPU_NUM, MAX_INPUT_EVENT_NUM}; -use crate::driver::gpu::{VirtIOGpuWrapper, GPU_DEVICE}; +use crate::driver::{GenericBlockDevice, pci_probe, QEMU_BLOCK_DEVICE}; +use crate::driver::DeviceBase; +use crate::driver::gpu::{GPU_DEVICE, VirtIOGpuWrapper}; use crate::driver::hal::HalImpl; -use crate::driver::input::{InputDriver, INPUT_DEVICE}; +use crate::driver::input::{INPUT_DEVICE, InputDriver}; use crate::driver::rtc::init_rtc; use crate::driver::uart::init_uart; -use crate::driver::DeviceBase; -use crate::driver::{pci_probe, QemuBlockDevice, QEMU_BLOCK_DEVICE}; pub static PLIC: Once = Once::new(); @@ -36,7 +37,7 @@ lazy_static! { } pub fn init_dt(dtb: usize) { - println!("device tree @ {:#x}", dtb); + println!("device tree @{:#x}", dtb); // Safe because the pointer is a valid pointer to unaliased memory. let fdt = unsafe { Fdt::from_ptr(dtb as *const u8).unwrap() }; init_plic(&fdt); @@ -67,13 +68,13 @@ fn walk_dt(fdt: &Fdt) { rtc_probe(node); } - #[cfg(not(any(feature = "Vf2", feature = "cv1811h")))] + #[cfg(not(any(feature = "vf2", feature = "cv1811h")))] if node.name.starts_with("uart") { println!("probe uart device"); uart_probe(node) } - #[cfg(feature = "Vf2")] + #[cfg(feature = "vf2")] if node.name.starts_with("uart") { // println!("probe uart device"); // uart_probe(node) @@ -175,7 +176,7 @@ fn virtio_blk(transport: MmioTransport) { VirtIOBlk::::new(transport).expect("failed to create blk driver"); let size = blk.capacity(); println!("blk device size is {}MB", size * 512 / 1024 / 1024); - let qemu_block_device = QemuBlockDevice::new(blk); + let qemu_block_device = GenericBlockDevice::new(Box::new(blk)); QEMU_BLOCK_DEVICE.lock().push(Arc::new(qemu_block_device)); println!("virtio-blk init finished"); } diff --git a/kernel/src/driver/mod.rs b/kernel/src/driver/mod.rs index aaee52f8..16429aa6 100644 --- a/kernel/src/driver/mod.rs +++ b/kernel/src/driver/mod.rs @@ -1,5 +1,5 @@ -pub use block_device::{QemuBlockDevice, QEMU_BLOCK_DEVICE}; -pub use dtb::{init_dt, DEVICE_TABLE, PLIC}; +pub use block_device::*; +pub use dtb::{DEVICE_TABLE, init_dt, PLIC}; pub use input::sys_event_get; pub use mpci::pci_probe; diff --git a/kernel/src/fs/vfs.rs b/kernel/src/fs/vfs.rs index 384bc0ea..40310727 100644 --- a/kernel/src/fs/vfs.rs +++ b/kernel/src/fs/vfs.rs @@ -9,20 +9,20 @@ use lazy_static::lazy_static; use rvfs::dentry::DirEntry; use rvfs::devfs::DEVFS_TYPE; use rvfs::file::{ - vfs_mkdir, vfs_mknod, vfs_open_file, vfs_read_file, vfs_write_file, FileMode, OpenFlags, + FileMode, OpenFlags, vfs_mkdir, vfs_mknod, vfs_open_file, vfs_read_file, vfs_write_file, }; use rvfs::info::{ProcessFs, ProcessFsInfo, VfsTime}; use rvfs::inode::{InodeMode, SpecialData}; use rvfs::mount::{do_mount, MountFlags, VfsMount}; use rvfs::mount_rootfs; use rvfs::ramfs::tmpfs::TMP_FS_TYPE; -use rvfs::superblock::{register_filesystem, DataOps, Device}; +use rvfs::superblock::{DataOps, Device, register_filesystem}; use kernel_sync::Mutex; use crate::config::{MEMINFO, PASSWORD, RTC_TIME, UTC}; -use crate::driver::rtc::get_rtc_time; use crate::driver::QEMU_BLOCK_DEVICE; +use crate::driver::rtc::get_rtc_time; use crate::task::current_task; // only call once before the first process is created @@ -55,14 +55,15 @@ pub fn init_vfs() { register_filesystem(DEVFS_TYPE).unwrap(); do_mount::("none", "/dev", "devfs", MountFlags::MNT_NO_DEV, None).unwrap(); - // do_mount::("root", "/tmp", "rootfs", MountFlags::MNT_NO_DEV, None).unwrap(); + #[cfg(any(feature = "vf2", feature = "sifive"))] + do_mount::("root", "/tmp", "rootfs", MountFlags::MNT_NO_DEV, None).unwrap(); vfs_mknod::( "/dev/null", InodeMode::S_CHARDEV, FileMode::FMODE_RDWR, u32::MAX, ) - .unwrap(); + .unwrap(); vfs_mknod::("/dev/zero", InodeMode::S_CHARDEV, FileMode::FMODE_RDWR, 0).unwrap(); register_filesystem(TMP_FS_TYPE).unwrap(); @@ -79,14 +80,15 @@ pub fn init_vfs() { // let fake_sort_src = vfs_open_file::("/sort.src", OpenFlags::O_CREAT | OpenFlags::O_RDWR, FileMode::FMODE_RDWR).unwrap(); // vfs_write_file::(fake_sort_src.clone(), SORT_SRC, 0).unwrap(); // vfs_close_file::(fake_sort_src).unwrap(); - println!("vfs init done"); + println!("vfs init success"); } fn prepare_var() { vfs_mkdir::("/var", FileMode::FMODE_RDWR).unwrap(); - // do_mount::("none", "/var", "tmpfs", MountFlags::MNT_NO_DEV, None).unwrap(); vfs_mkdir::("/var/log", FileMode::FMODE_RDWR).unwrap(); vfs_mkdir::("/var/tmp", FileMode::FMODE_RDWR).unwrap(); + #[cfg(any(feature = "vf2", feature = "sifive"))] + do_mount::("none", "/var/tmp", "tmpfs", MountFlags::MNT_NO_DEV, None).unwrap(); } fn prepare_root() { @@ -96,7 +98,7 @@ fn prepare_root() { OpenFlags::O_RDWR | OpenFlags::O_CREAT, FileMode::FMODE_RDWR, ) - .unwrap(); + .unwrap(); } fn prepare_dev() { @@ -107,7 +109,7 @@ fn prepare_dev() { OpenFlags::O_RDWR | OpenFlags::O_CREAT, FileMode::FMODE_RDWR, ) - .unwrap(); + .unwrap(); rtc_file .f_dentry @@ -126,7 +128,7 @@ fn prepare_test_need() { OpenFlags::O_RDWR | OpenFlags::O_CREAT, FileMode::FMODE_RDWR, ) - .unwrap(); + .unwrap(); } fn prepare_proc() { @@ -137,14 +139,14 @@ fn prepare_proc() { OpenFlags::O_RDWR | OpenFlags::O_CREAT, FileMode::FMODE_RDWR, ) - .unwrap(); + .unwrap(); vfs_write_file::(file, MOUNT_INFO.as_bytes(), 0).unwrap(); let mem_info = vfs_open_file::( "/proc/meminfo", OpenFlags::O_RDWR | OpenFlags::O_CREAT, FileMode::FMODE_RDWR, ) - .unwrap(); + .unwrap(); vfs_write_file::(mem_info, MEMINFO.as_bytes(), 0).unwrap(); } @@ -156,14 +158,14 @@ fn prepare_etc() { OpenFlags::O_RDWR | OpenFlags::O_CREAT, FileMode::FMODE_RDWR, ) - .unwrap(); + .unwrap(); vfs_write_file::(file, UTC, 0).unwrap(); let adjtime_file = vfs_open_file::( "/etc/adjtime", OpenFlags::O_RDWR | OpenFlags::O_CREAT, FileMode::FMODE_RDWR, ) - .unwrap(); + .unwrap(); vfs_write_file::(adjtime_file, RTC_TIME.as_bytes(), 0).unwrap(); let password = vfs_open_file::( @@ -171,7 +173,7 @@ fn prepare_etc() { OpenFlags::O_RDWR | OpenFlags::O_CREAT, FileMode::FMODE_RDWR, ) - .unwrap(); + .unwrap(); vfs_write_file::(password, PASSWORD.as_bytes(), 0).unwrap(); } diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index b8ea07a5..83691c3b 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -4,6 +4,7 @@ #![feature(panic_info_message)] #![feature(atomic_from_mut)] #![feature(ip_in_core)] +#![feature(stmt_expr_attributes)] extern crate alloc; #[macro_use] extern crate log; diff --git a/kernel/src/memory/frame.rs b/kernel/src/memory/frame.rs index 13a4bd68..2d432c01 100644 --- a/kernel/src/memory/frame.rs +++ b/kernel/src/memory/frame.rs @@ -11,8 +11,13 @@ use crate::config::{FRAME_BITS, FRAME_SIZE}; use super::manager::FrameRefManager; +#[cfg(feature = "vf2")] +const FRAME_NUM: usize = 2096300 / 8; +#[cfg(feature = "qemu")] +const FRAME_NUM: usize = 8192; + lazy_static! { - pub static ref FRAME_ALLOCATOR: Mutex> = Mutex::new(Bitmap::new()); + pub static ref FRAME_ALLOCATOR: Mutex> = Mutex::new(Bitmap::new()); } lazy_static! { @@ -34,6 +39,7 @@ pub fn init_frame_allocator(memory_end: usize) { "page start:{:#x},end:{:#x},count:{:#x}", page_start, page_end, page_count ); + println!("set frame allocator manage {} frames", FRAME_NUM); FRAME_ALLOCATOR.lock().init(start..end).unwrap(); } diff --git a/kernel/src/memory/vmm.rs b/kernel/src/memory/vmm.rs index d2ce2cd7..271d3c37 100644 --- a/kernel/src/memory/vmm.rs +++ b/kernel/src/memory/vmm.rs @@ -20,9 +20,9 @@ use crate::config::{ }; use crate::fs::vfs; use crate::ipc::ShmInfo; +use crate::memory::{frame_alloc_contiguous, FRAME_REF_MANAGER}; use crate::memory::elf::{ELFError, ELFInfo, ELFReader}; use crate::memory::frame::{addr_to_frame, frame_alloc}; -use crate::memory::{frame_alloc_contiguous, FRAME_REF_MANAGER}; use crate::trap::TrapFrame; lazy_static! { @@ -276,7 +276,7 @@ pub fn build_cow_address_space( if flag.contains(MappingFlags::W) { flags -= MappingFlags::W; flags |= MappingFlags::RSD; // we use the RSD flag to indicate that this page is a cow page - // update parent's flag and clear dirty + // update parent's flag and clear dirty p_table.modify_pte_flags(v_addr, flags, false).unwrap(); } address_space.map(v_addr, phy, page_size, flags).unwrap(); @@ -474,7 +474,7 @@ pub fn build_elf_address_space( warn!("elf: no phdr found, tls might not work"); Err(ELFError::NoEntrySegment) } - .unwrap_or(0); + .unwrap_or(0); warn!( "entry: {:#x}, phdr:{:#x}", elf.header.pt2.entry_point() + bias as u64, diff --git a/kernel/src/print/console.rs b/kernel/src/print/console.rs index 84e5605c..701f3a4e 100644 --- a/kernel/src/print/console.rs +++ b/kernel/src/print/console.rs @@ -103,8 +103,14 @@ struct UStdout; impl Write for UStdout { fn write_str(&mut self, out: &str) -> Result { - let uart = USER_UART.get().unwrap(); - uart.put_bytes(out.as_bytes()); + if UART_FLAG.load(Ordering::Relaxed) { + let uart = USER_UART.get().unwrap(); + uart.put_bytes(out.as_bytes()); + } else { + out.as_bytes().iter().for_each(|x| { + console_putchar(*x); + }); + } Ok(()) } } diff --git a/kernel/src/sys.rs b/kernel/src/sys.rs index 87740e62..f002975d 100644 --- a/kernel/src/sys.rs +++ b/kernel/src/sys.rs @@ -1,12 +1,12 @@ use core::cmp::min; -use syscall_define::sys::{Rusage, Sysinfo, SyslogAction, TimeVal}; use syscall_define::LinuxErrno; +use syscall_define::sys::{Rusage, Sysinfo, SyslogAction, TimeVal}; use syscall_table::syscall_func; +use crate::MACHINE_INFO; use crate::task::{current_task, TASK_MANAGER}; use crate::timer::{get_time_ms, TimeFromFreq}; -use crate::MACHINE_INFO; const LOG_BUF_LEN: usize = 4096; const LOG: &str = r" @@ -51,7 +51,7 @@ pub fn sys_info(dst_info: usize) -> isize { // calculate the task number // TASKMANAGER let task_number = TASK_MANAGER.lock().len(); - let memory_info = MACHINE_INFO.get().unwrap().memory.clone(); + let memory_info = MACHINE_INFO.get().as_ref().unwrap().memory.clone(); let info = Sysinfo { uptime: (get_time_ms() / 1000) as usize, loads: [ diff --git a/kernel/src/task/mod.rs b/kernel/src/task/mod.rs index 43f535c3..b2e17739 100644 --- a/kernel/src/task/mod.rs +++ b/kernel/src/task/mod.rs @@ -1,6 +1,6 @@ use alloc::sync::Arc; -use lazy_static::lazy_static; +use spin::Lazy; pub use cpu::*; pub use task::{StatisticalData, Task, TaskState}; @@ -15,20 +15,28 @@ pub mod schedule; mod stack; mod task; -lazy_static! { - pub static ref INIT_PROCESS: Arc = { - // let mut data = Vec::new(); - // vfs::read_all("/bin/init", &mut data); - let data = INIT; - let task = Task::from_elf("/bin/init", data).unwrap(); - Arc::new(task) - }; -} +// lazy_static! { +// pub static ref INIT_PROCESS: Arc = { +// // let mut data = Vec::new(); +// // vfs::read_all("/bin/init", &mut data); +// let data = INIT; +// let task = Task::from_elf("/bin/init", data).unwrap(); +// Arc::new(task) +// }; +// } + +static INIT_PROCESS: Lazy> = Lazy::new(|| { + let data = INIT; + let task = Task::from_elf("/bin/init", data).unwrap(); + println!("init process: {:#x?}", task); + Arc::new(task) +}); /// put init process into process pool pub fn init_process() { let mut task_pool = TASK_MANAGER.lock(); let task = INIT_PROCESS.clone(); + println!("clone init process success"); let dir = TMP_DIR.lock().clone(); let mnt = TMP_MNT.lock().clone(); task.access_inner().fs_info = diff --git a/kernel/src/task/task.rs b/kernel/src/task/task.rs index 6caacee0..58b019f6 100644 --- a/kernel/src/task/task.rs +++ b/kernel/src/task/task.rs @@ -1,8 +1,8 @@ +use alloc::{format, vec}; use alloc::collections::BTreeMap; use alloc::string::{String, ToString}; use alloc::sync::{Arc, Weak}; use alloc::vec::Vec; -use alloc::{format, vec}; use core::fmt::Debug; use core::ops::Range; @@ -12,13 +12,14 @@ use page_table::addr::{align_down_4k, align_up_4k, VirtAddr}; use page_table::pte::MappingFlags; use page_table::table::Sv39PageTable; use rvfs::dentry::DirEntry; -use rvfs::file::{vfs_close_file, File}; +use rvfs::file::{File, vfs_close_file}; use rvfs::info::ProcessFsInfo; use rvfs::link::vfs_unlink; use rvfs::mount::VfsMount; use gmanager::MinimalManager; use kernel_sync::{Mutex, MutexGuard}; +use syscall_define::{LinuxErrno, PrLimit, PrLimitRes}; use syscall_define::aux::{ AT_BASE, AT_EGID, AT_ENTRY, AT_EUID, AT_EXECFN, AT_GID, AT_PAGESZ, AT_PHDR, AT_PHENT, AT_PHNUM, AT_PLATFORM, AT_RANDOM, AT_SECURE, AT_UID, @@ -29,24 +30,23 @@ use syscall_define::signal::{SignalHandlers, SignalNumber, SignalReceivers, Sign use syscall_define::sys::TimeVal; use syscall_define::task::CloneFlags; use syscall_define::time::TimerType; -use syscall_define::{LinuxErrno, PrLimit, PrLimitRes}; use crate::config::{CPU_NUM, FRAME_BITS, MAX_FD_NUM, TRAP_CONTEXT_BASE, USER_STACK_SIZE}; use crate::config::{FRAME_SIZE, MAX_THREAD_NUM, USER_KERNEL_STACK_SIZE}; use crate::error::{AlienError, AlienResult}; +use crate::fs::{STDIN, STDOUT}; use crate::fs::file::KFile; use crate::fs::vfs::VfsProvider; -use crate::fs::{STDIN, STDOUT}; use crate::ipc::{global_register_signals, ShmInfo}; use crate::memory::{ - build_cow_address_space, build_elf_address_space, build_thread_address_space, kernel_satp, - MMapInfo, MMapRegion, PageAllocator, ProtFlags, UserStack, FRAME_REF_MANAGER, + build_cow_address_space, build_elf_address_space, build_thread_address_space, FRAME_REF_MANAGER, + kernel_satp, MMapInfo, MMapRegion, PageAllocator, ProtFlags, UserStack, }; use crate::task::context::Context; use crate::task::heap::HeapInfo; use crate::task::stack::Stack; -use crate::timer::{read_timer, ITimerVal, TimeNow, ToClock}; -use crate::trap::{trap_common_read_file, trap_return, user_trap_vector, TrapFrame}; +use crate::timer::{ITimerVal, read_timer, TimeNow, ToClock}; +use crate::trap::{trap_common_read_file, trap_return, TrapFrame, user_trap_vector}; type FdManager = MinimalManager>; @@ -618,7 +618,7 @@ impl TaskInner { .query(VirtAddr::from(ptr)) .unwrap(); if !flag.contains(MappingFlags::V) { - error!("invalid page {:?}", flag); + error!("[transfer_raw] invalid page {:?}, ptr:{:#x}", flag,ptr); self.invalid_page_solver(ptr).unwrap(); let (phy, flag, _) = self .address_space @@ -1225,7 +1225,7 @@ impl TaskInner { let read_offset = region.offset + (addr - region.start); return Ok(Some((file.clone(), buf, read_offset as u64))); } else { - error!("invalid page fault in stack"); + error!("invalid page fault in stack, addr: {:#x}",addr); let map_flags = "RWUVAD".into(); self.address_space .lock() @@ -1421,8 +1421,8 @@ impl Task { }), send_sigchld_when_exit: false, }; - let phy_button = process.transfer_raw(elf_info.stack_top - USER_STACK_SIZE); - let mut user_stack = UserStack::new(phy_button + USER_STACK_SIZE, elf_info.stack_top); + let phy_button = process.transfer_raw(elf_info.stack_top - FRAME_SIZE); + let mut user_stack = UserStack::new(phy_button + FRAME_SIZE, elf_info.stack_top); user_stack.push(0).unwrap(); let argc_ptr = user_stack.push(0).unwrap(); @@ -1435,7 +1435,9 @@ impl Task { user_trap_vector as usize, ); trap_frame.regs()[4] = elf_info.tls; // tp --> tls - Some(process) + let res = Some(process); + println!("build process success"); + res } /// fork a child pub fn t_clone( @@ -1659,9 +1661,9 @@ impl Task { "PATH=/bin:/usr/bin", "UB_BINDIR=./", ] - .iter() - .map(|x| x.to_string()) - .collect::>(); + .iter() + .map(|x| x.to_string()) + .collect::>(); envp } else { env diff --git a/kernel/src/trap/context.rs b/kernel/src/trap/context.rs index 0f2c2cb3..f3068206 100644 --- a/kernel/src/trap/context.rs +++ b/kernel/src/trap/context.rs @@ -1,6 +1,6 @@ use bit_field::BitField; -use crate::arch::riscv::sstatus::{self, Sstatus, SPP}; +use crate::arch::riscv::sstatus::{self, SPP, Sstatus}; #[repr(C)] #[derive(Debug, Copy, Clone)] @@ -64,7 +64,8 @@ impl TrapFrame { trap_handler: usize, ) -> Self { let mut sstatus = sstatus::read(); - assert!(sstatus.0.get_bit(5)); //spie ==1 + sstatus.set_spie(); + assert!(sstatus.0.get_bit(5)); //spie == 1 sstatus.set_spp(SPP::User); let mut res = Self { x: [0; 32], diff --git a/kernel/src/trap/mod.rs b/kernel/src/trap/mod.rs index f85b8396..36f31772 100644 --- a/kernel/src/trap/mod.rs +++ b/kernel/src/trap/mod.rs @@ -2,23 +2,23 @@ use core::arch::{asm, global_asm}; use bit_field::BitField; use page_table::addr::VirtAddr; -use riscv::register::sstatus::SPP; use riscv::register::{sepc, sscratch, stval}; +use riscv::register::sstatus::SPP; pub use context::TrapFrame; pub use exception::trap_common_read_file; -use syscall_define::signal::SignalNumber; use syscall_define::signal::SIGNAL_RETURN_TRAP; +use syscall_define::signal::SignalNumber; use syscall_define::time::TimerType; -use crate::arch::riscv::register::scause::{Exception, Interrupt, Trap}; -use crate::arch::riscv::register::stvec; -use crate::arch::riscv::register::stvec::TrapMode; -use crate::arch::riscv::sstatus; use crate::arch::{ external_interrupt_enable, hart_id, interrupt_disable, interrupt_enable, is_interrupt_enable, timer_interrupt_enable, }; +use crate::arch::riscv::register::scause::{Exception, Interrupt, Trap}; +use crate::arch::riscv::register::stvec; +use crate::arch::riscv::register::stvec::TrapMode; +use crate::arch::riscv::sstatus; use crate::config::TRAMPOLINE; use crate::error::AlienError; use crate::ipc::{send_signal, signal_handler, signal_return, solve_futex_wait}; @@ -88,6 +88,8 @@ pub fn set_kernel_trap_entry() { /// 开启中断/异常 pub fn init_trap_subsystem() { println!("++++ setup interrupt ++++"); + // todo!("why set_kernel_trap_entry can't work on vf2?") + // #[cfg(not(feature = "vf2"))] set_kernel_trap_entry(); external_interrupt_enable(); timer_interrupt_enable(); diff --git a/modules/Makefile b/modules/Makefile deleted file mode 100644 index 49bf9dfb..00000000 --- a/modules/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -APPS := $(shell ls -d */) -fmt: - @echo "Formatting code" - @$(foreach dir, $(APPS), (cd $(dir) && cargo fmt && cd ..);) - -clean: - @echo "Cleaning apps" - @$(foreach dir, $(APPS), (cd $(dir) && cargo clean && cd ..);) - @$(foreach dir, $(APPS), (cd $(dir) && rm -rf target && cd ..);) - - - -clock: - @$(foreach dir, $(APPS), (cd $(dir) && rm -rf Cargo.lock && cd ..);) \ No newline at end of file diff --git a/modules/basemachine/src/lib.rs b/modules/basemachine/src/lib.rs index 5c0cb801..d46f744f 100644 --- a/modules/basemachine/src/lib.rs +++ b/modules/basemachine/src/lib.rs @@ -91,12 +91,13 @@ fn walk_dt(fdt: Fdt) -> MachineInfo { if reg.is_none() { continue; } + let irq = node.property("interrupts").unwrap().value; + let irq = u32::from_be_bytes(irq.try_into().unwrap()); + let reg = reg.unwrap(); - let val = node.interrupts().unwrap().next().unwrap(); - // let irq = node.property("interrupts").unwrap().value; - // let irq = u32::from_be_bytes(irq.try_into().unwrap()); + // let val = node.interrupts().unwrap().next().unwrap(); let mut base = 0; - let irq = val as u32; + // let irq = val as u32; reg.for_each(|x| { base = x.starting_address as usize; }); diff --git a/modules/pager/src/bitmap.rs b/modules/pager/src/bitmap.rs index 12ed4fe8..1bb0b819 100644 --- a/modules/pager/src/bitmap.rs +++ b/modules/pager/src/bitmap.rs @@ -1,8 +1,8 @@ use core::fmt::{Debug, Formatter}; use core::ops::Range; -use crate::error::{check, BuddyError}; use crate::{BuddyResult, PageAllocator, PageAllocatorExt}; +use crate::error::{BuddyError, check}; pub struct Bitmap { /// Current number of allocated pages @@ -68,7 +68,7 @@ impl Bitmap { loop { let end = self.current + pages; if end > self.max && flag { - return Err(BuddyError::OutOfMemory); + return Err(BuddyError::OutOfMemory(self.max)); } if end > self.max { self.current = 0; @@ -116,7 +116,7 @@ impl PageAllocator for Bitmap { let end_page = memory.end >> 12; self.max = end_page - start_page; if self.max > N * 8 { - return Err(BuddyError::OutOfMemory); + return Err(BuddyError::OutOfMemory(self.max)); } self.start = start_page; Ok(()) diff --git a/modules/pager/src/buddy.rs b/modules/pager/src/buddy.rs index 48ddf796..2e58673d 100644 --- a/modules/pager/src/buddy.rs +++ b/modules/pager/src/buddy.rs @@ -5,8 +5,8 @@ use core::ops::Range; use doubly_linked_list::*; use log::trace; -use crate::error::{check, BuddyError}; use crate::{BuddyResult, PageAllocator, PageAllocatorExt}; +use crate::error::{BuddyError, check}; pub struct Zone { /// The pages in this zone @@ -49,7 +49,7 @@ impl Debug for Zone { " Order: {}, FreePages: {}\n", order, free_area.free_pages )) - .unwrap(); + .unwrap(); list_head.iter().for_each(|l| { f.write_fmt(format_args!(" {l:#x?}\n")).unwrap(); }) @@ -97,7 +97,7 @@ impl Zone { fn alloc_inner(&mut self, order: usize) -> BuddyResult<()> { let order = order + 1; if order >= MAX_ORDER { - return Err(BuddyError::OutOfMemory); + return Err(BuddyError::OutOfMemory(1 << MAX_ORDER)); } trace!( "alloc_inner:{}, free_pages:{}", diff --git a/modules/pager/src/error.rs b/modules/pager/src/error.rs index b6c7517c..304c99c5 100644 --- a/modules/pager/src/error.rs +++ b/modules/pager/src/error.rs @@ -5,7 +5,7 @@ use crate::BuddyResult; #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum BuddyError { - OutOfMemory, + OutOfMemory(usize), OrderTooLarge, PageOutOfRange, MemoryStartNotAligned, @@ -17,7 +17,7 @@ pub enum BuddyError { impl Display for BuddyError { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { - BuddyError::OutOfMemory => write!(f, "Out of memory"), + BuddyError::OutOfMemory(x) => write!(f, "{} Out of memory", x), BuddyError::OrderTooLarge => write!(f, "Order too large"), BuddyError::PageOutOfRange => write!(f, "Page out of range"), BuddyError::MemoryStartNotAligned => write!(f, "Memory start not aligned"), diff --git a/tools/link.ld b/tools/link.ld index e05df874..61199da8 100644 --- a/tools/link.ld +++ b/tools/link.ld @@ -37,7 +37,9 @@ SECTIONS . = ALIGN(4K); edata = .; .bss : { + . = ALIGN(4K); *(.bss.stack) + . = ALIGN(4K); sbss = .; *(.bss .bss.*) *(.sbss .sbss.*)