From 511c6e20ada9da428f8926b4412d9ceabec845e9 Mon Sep 17 00:00:00 2001 From: Panda Jiang <87910116+fkcrazy001@users.noreply.github.com> Date: Sun, 22 Dec 2024 17:12:01 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A7=9C=E9=B9=8F=E7=BB=84=E4=BB=B6=E5=8C=96?= =?UTF-8?q?=E5=AE=9E=E9=AA=8C=E6=8A=A5=E5=91=8A=20(#644)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Panda Jiang <87910116+fkcrazy001@users.noreply.github.com> --- ...36\351\252\214\346\212\245\345\221\212.md" | 759 ++++++++++++++++++ 1 file changed, 759 insertions(+) create mode 100644 "source/_posts/\345\247\234\351\271\217\347\273\204\344\273\266\345\214\226\345\206\205\346\240\270\345\256\236\351\252\214\346\212\245\345\221\212.md" diff --git "a/source/_posts/\345\247\234\351\271\217\347\273\204\344\273\266\345\214\226\345\206\205\346\240\270\345\256\236\351\252\214\346\212\245\345\221\212.md" "b/source/_posts/\345\247\234\351\271\217\347\273\204\344\273\266\345\214\226\345\206\205\346\240\270\345\256\236\351\252\214\346\212\245\345\221\212.md" new file mode 100644 index 0000000000..10e0f6ff61 --- /dev/null +++ "b/source/_posts/\345\247\234\351\271\217\347\273\204\344\273\266\345\214\226\345\206\205\346\240\270\345\256\236\351\252\214\346\212\245\345\221\212.md" @@ -0,0 +1,759 @@ +--- +title: 姜鹏组件化内核实验报告 +date: 2024-12-01 12:11:24 +tags: + - author: fkcrazy001 + - repo: https://github.com/fkcrazy001/oscamp +--- + +# week 1 +## print_with_color +思路:直接修改 axstd 里面的 println!宏,在输出的内容之前加上ansi的控制字符串 +```patch +commit 29c8b52df3644c27ea1f2cb26191e7a45c2c40a4 (HEAD -> exercise) +Author: PandaJiang <3160104094@zju.edu.cn> +Date: Wed Nov 13 22:15:34 2024 +0800 + + with color + + Signed-off-by: PandaJiang <3160104094@zju.edu.cn> + +diff --git a/arceos/ulib/axstd/src/macros.rs b/arceos/ulib/axstd/src/macros.rs +index c7cd653..760739b 100644 +--- a/arceos/ulib/axstd/src/macros.rs ++++ b/arceos/ulib/axstd/src/macros.rs +@@ -18,6 +18,6 @@ macro_rules! print { + macro_rules! println { + () => { $crate::print!("\n") }; + ($($arg:tt)*) => { +- $crate::io::__print_impl(format_args!("{}\n", format_args!($($arg)*))); ++ $crate::io::__print_impl(format_args!("\x1b[31m{}\x1b[0m\n", format_args!($($arg)*))); + } + } +``` + +## support hashmap +思路:axstd 中新增collections模块,将 alloc::collections 中的容器导入。此外,注意到std::collection::hashmap是在hashbrown作为base进行使用。尝试与std做一样的事情,发现可以直接将hashbrown模块引入作为hashmap使用,randomState就采用了默认的。 +```patch +commit c2cab71c6640a9c9f984144f2e12f701cf347f31 +Author: PandaJiang <3160104094@zju.edu.cn> +Date: Wed Nov 13 22:21:01 2024 +0800 + + support hash + + Signed-off-by: PandaJiang <3160104094@zju.edu.cn> + +diff --git a/arceos/ulib/axstd/Cargo.toml b/arceos/ulib/axstd/Cargo.toml +index c2322c5..d3a3fe8 100644 +--- a/arceos/ulib/axstd/Cargo.toml ++++ b/arceos/ulib/axstd/Cargo.toml +@@ -80,3 +80,4 @@ arceos_api = { workspace = true } + axio = "0.1" + axerrno = "0.1" + kspin = "0.1" ++hashbrown = "0.15" +\ No newline at end of file +diff --git a/arceos/ulib/axstd/src/collections/mod.rs b/arceos/ulib/axstd/src/collections/mod.rs +new file mode 100644 +index 0000000..6978165 +--- /dev/null ++++ b/arceos/ulib/axstd/src/collections/mod.rs +@@ -0,0 +1,6 @@ ++// collections ++ ++extern crate alloc; ++ ++pub use alloc::collections::*; ++pub use hashbrown::*; +\ No newline at end of file +diff --git a/arceos/ulib/axstd/src/lib.rs b/arceos/ulib/axstd/src/lib.rs +index 5ab0517..49784bb 100644 +--- a/arceos/ulib/axstd/src/lib.rs ++++ b/arceos/ulib/axstd/src/lib.rs +@@ -55,7 +55,7 @@ extern crate alloc; + + #[cfg(feature = "alloc")] + #[doc(no_inline)] +-pub use alloc::{boxed, collections, format, string, vec}; ++pub use alloc::{boxed, format, string, vec}; + + #[doc(no_inline)] + pub use core::{arch, cell, cmp, hint, marker, mem, ops, ptr, slice, str}; +@@ -70,6 +70,7 @@ pub mod process; + pub mod sync; + pub mod thread; + pub mod time; ++pub mod collections; + + #[cfg(feature = "fs")] + pub mod fs; +``` + +## bump 内存分配算法 +- 分配bytes + + 实现较为简单,用b_pos记录当前内存bytes分配到的地方。 唯一需要注意的是 + 1. 要根据aligment返回起始地址。并将分配计数+1 + 2. 要检查 b_pos + size是否到达了 p_pos,是的话说明内存已经被耗尽。 +- 分配pages + 实现也较为简单,用p_pos记录当前pages分配的地方。需要注意的是 + 1. p_pos是递减的,返回的地址会越来越小 + 2. 要检查p_pos - size是否到达了b_pos,是的话说明内存已经被耗尽。 +- 释放bytes + - 引用计数减1,然后检查是否为0即可,为0的话就将b——pos重置。 + +## mv和rename操作 +- mv + + 分解为 create + del 两个动作,在新的地址上写入原文件,然后删除原文件 + +- rename + + 文件系统有相关api,直接调用即可。 + +```patch +commit adabd01bad84c50a172a5a43af4d7cb77d75c4d7 +Author: Panda Jiang <3160104094@zju.edu.cn> +Date: Mon Nov 18 08:00:23 2024 +0000 + + mv and rename + + Signed-off-by: Panda Jiang <3160104094@zju.edu.cn> + +diff --git a/arceos/examples/shell/src/cmd.rs b/arceos/examples/shell/src/cmd.rs +index 23f087f..f81723c 100644 +--- a/arceos/examples/shell/src/cmd.rs ++++ b/arceos/examples/shell/src/cmd.rs +@@ -1,5 +1,6 @@ + use std::fs::{self, File, FileType}; + use std::io::{self, prelude::*}; ++use std::string::ToString; + use std::{string::String, vec::Vec}; + + #[cfg(all(not(feature = "axstd"), unix))] +@@ -27,6 +28,8 @@ const CMD_TABLE: &[(&str, CmdHandler)] = &[ + ("pwd", do_pwd), + ("rm", do_rm), + ("uname", do_uname), ++ ("rename", do_rename), ++ ("mv", do_mv), + ]; + + fn file_type_to_char(ty: FileType) -> char { +@@ -195,6 +198,84 @@ fn do_mkdir(args: &str) { + } + } + ++fn do_rename(args: &str) { ++ let mut arg_v = args.split(" "); ++ let old_name = arg_v.next(); ++ let new_name = arg_v.next(); ++ if old_name.is_none() || new_name.is_none() || arg_v.next().is_some() { ++ println!("rename: invalid args"); ++ println!("usage: rename $old_name $new_name"); ++ return; ++ } ++ let old_name_s = old_name.unwrap(); ++ let new_name_s = new_name.unwrap(); ++ println!("try to rename {old_name_s} to {new_name_s}"); ++ if let Err(e) = fs::rename(old_name_s, new_name_s) { ++ print_err!("rename", format_args!("cannot rename '{old_name_s}' to '{new_name_s}'"), e); ++ } ++ return; ++} ++ ++fn do_mv(args: &str) { ++ let mut arg_v = args.split(" "); ++ let old_file_path = arg_v.next(); ++ let new_file_path = arg_v.next(); ++ if old_file_path.is_none() || new_file_path.is_none() || arg_v.next().is_some() { ++ println!("mv: invalid args"); ++ println!("usage: mv $old_file_path $new_path_path"); ++ return; ++ } ++ fn rm_one(path: &str, rm_dir: bool) -> io::Result<()> { ++ if rm_dir && fs::metadata(path)?.is_dir() { ++ fs::remove_dir(path) ++ } else { ++ fs::remove_file(path) ++ } ++ } ++ fn write_file(fname: &str, bufs: &Vec>) -> io::Result<()> { ++ let mut file = File::create(fname)?; ++ for buf in bufs { ++ file.write_all(&buf[..])?; ++ } ++ Ok(()) ++ } ++ fn read_file(fname: &str, all_data: &mut Vec>) -> io::Result<()> { ++ let mut file = File::open(fname)?; ++ loop { ++ let mut buf=vec![0u8;1024]; ++ let n = file.read(&mut buf)?; ++ if n > 0 { ++ all_data.push(buf); ++ } else { ++ return Ok(()); ++ } ++ } ++ } ++ let old_path = old_file_path.unwrap(); ++ let last_separator_pos = old_path.rfind(|c| c == '/' || c == '\\'); ++ // 提取文件名 ++ let filename = match last_separator_pos { ++ Some(pos) => &old_path[pos + 1..], ++ None => old_path, ++ }; ++ let mut new_path = new_file_path.unwrap().to_string(); ++ new_path.push('/'); ++ new_path.push_str(filename); ++ let mut data:Vec> = Vec::new(); ++ if let Err(e) = read_file(old_path, &mut data) { ++ print_err!("mv", format_args!("cannot read '{old_path}'"), e); ++ return; ++ } ++ if let Err(e) = write_file(&new_path, &data) { ++ print_err!("mv", format_args!("cannot open '{new_path}'"), e); ++ return; ++ } ++ if let Err(e) = rm_one(old_path, false) { ++ print_err!("mv", format_args!("cannot rm '{old_path}'"), e); ++ return; ++ } ++} ++ + fn do_rm(args: &str) { + if args.is_empty() { + print_err!("rm", "missing operand"); + +``` + +# week2 + +## pagefault 缺页处理 + +populate参数为false时,uspace模块只会为将该块虚拟内存地址记录下来,实际的访问会导致 pagefault, 在该handler中处理这一错误 + +```patch +commit c0ed66e6fd0ad5af24f7ae6b2e683c43df03228a +Author: PandaJiang <3160104094@zju.edu.cn> +Date: Wed Nov 20 22:19:20 2024 +0800 + + add page fault func + + Signed-off-by: PandaJiang <3160104094@zju.edu.cn> + +diff --git a/arceos/payload/fileops_c/fileops b/arceos/payload/fileops_c/fileops +new file mode 100755 +index 0000000..a457c8c +Binary files /dev/null and b/arceos/payload/fileops_c/fileops differ +diff --git a/arceos/payload/hello_c/hello b/arceos/payload/hello_c/hello +new file mode 100755 +index 0000000..a44f4c6 +Binary files /dev/null and b/arceos/payload/hello_c/hello differ +diff --git a/arceos/payload/origin/Makefile b/arceos/payload/origin/Makefile +new file mode 100644 +index 0000000..15ba26d +--- /dev/null ++++ b/arceos/payload/origin/Makefile +@@ -0,0 +1,18 @@ ++TARGET := origin ++TARGET_ELF := ../../target/riscv64gc-unknown-none-elf/release/$(TARGET) ++ ++all: $(TARGET) FORCE ++ ++$(TARGET): $(TARGET_ELF) ++ @rust-objcopy --binary-architecture=riscv64 --strip-all -O binary $< $@ ++ ++$(TARGET_ELF): src/main.rs ++ @cargo build -p origin --target riscv64gc-unknown-none-elf --release ++ ++clean: ++ @rm -rf ./$(TARGET) ++ @cargo clean -p origin --target riscv64gc-unknown-none-elf --release ++ ++FORCE: ++ ++.PHONY: FORCE +diff --git a/arceos/payload/origin/origin b/arceos/payload/origin/origin +new file mode 100755 +index 0000000..da2037d +Binary files /dev/null and b/arceos/payload/origin/origin differ +diff --git a/arceos/tour/m_1_0/src/main.rs b/arceos/tour/m_1_0/src/main.rs +index 89ef91d..f8c6077 100644 +--- a/arceos/tour/m_1_0/src/main.rs ++++ b/arceos/tour/m_1_0/src/main.rs +@@ -12,6 +12,8 @@ mod task; + mod syscall; + mod loader; + ++use std::println; ++ + use axstd::io; + use axhal::paging::MappingFlags; + use axhal::arch::UspaceContext; +@@ -19,12 +21,27 @@ use axhal::mem::VirtAddr; + use axsync::Mutex; + use alloc::sync::Arc; + use axmm::AddrSpace; ++use axtask::TaskExtRef; + use loader::load_user_app; ++use axhal::trap::{register_trap_handler, PAGE_FAULT}; + + const USER_STACK_SIZE: usize = 0x10000; + const KERNEL_STACK_SIZE: usize = 0x40000; // 256 KiB + const APP_ENTRY: usize = 0x1000; + ++#[register_trap_handler(PAGE_FAULT)] ++fn page_fault(vaddr: VirtAddr, access_flags: MappingFlags, is_user: bool) -> bool { ++ if !is_user { ++ panic!("page fault from kernel!!!"); ++ } ++ println!("handler user page fault"); ++ axtask::current() ++ .task_ext() ++ .aspace ++ .lock() ++ .handle_page_fault(vaddr, access_flags) ++} ++ + #[cfg_attr(feature = "axstd", no_mangle)] + fn main() { + // A new address space for user app. +@@ -36,7 +53,7 @@ fn main() { + } + + // Init user stack. +- let ustack_top = init_user_stack(&mut uspace, true).unwrap(); ++ let ustack_top = init_user_stack(&mut uspace, false).unwrap(); + ax_println!("New user address space: {:#x?}", uspace); + + // Let's kick off the user process. + +``` + +## mmap syscall +与page fault处理类似,有相应api可以调用 +```patch +commit daef0f232f4ae709afe1ef19974afa29b4594c95 +Author: Panda Jiang <3160104094@zju.edu.cn> +Date: Thu Nov 21 09:22:08 2024 +0000 + + mmap + + Signed-off-by: Panda Jiang <3160104094@zju.edu.cn> + +diff --git a/arceos/exercises/sys_map/src/syscall.rs b/arceos/exercises/sys_map/src/syscall.rs +index 83b98d5..ac6624d 100644 +--- a/arceos/exercises/sys_map/src/syscall.rs ++++ b/arceos/exercises/sys_map/src/syscall.rs +@@ -1,13 +1,16 @@ + #![allow(dead_code)] + + use core::ffi::{c_void, c_char, c_int}; ++use core::usize; + use axhal::arch::TrapFrame; + use axhal::trap::{register_trap_handler, SYSCALL}; + use axerrno::LinuxError; ++use axmm::{USER_ASPACE_BASE, USER_ASPACE_SIZE}; + use axtask::current; + use axtask::TaskExtRef; + use axhal::paging::MappingFlags; +-use arceos_posix_api as api; ++use arceos_posix_api::{self as api, get_file_like}; ++use memory_addr::{MemoryAddr, VirtAddr, VirtAddrRange}; + + const SYS_IOCTL: usize = 29; + const SYS_OPENAT: usize = 56; +@@ -140,7 +143,53 @@ fn sys_mmap( + fd: i32, + _offset: isize, + ) -> isize { +- unimplemented!("no sys_mmap!"); ++ let file = get_file_like(fd); ++ if file.is_err() { ++ return 0; ++ } ++ let file = file.unwrap(); ++ let ss = file.stat(); ++ if ss.is_err() { ++ return 0; ++ } ++ let size = ss.unwrap().st_size as usize; ++ if length > size { ++ debug!("incoming length is too long!!"); ++ } ++ let prot_f = MmapProt::from_bits(prot); ++ if prot_f.is_none() { ++ return 0; ++ } ++ let mpflag:MappingFlags = prot_f.unwrap().into(); ++ let mut buf = alloc::vec![0u8; size]; ++ if let Err(_) = file.read(&mut buf) { ++ return 0; ++ } ++ let c = current(); ++ let mut uspace = c ++ .task_ext() ++ .aspace ++ .lock(); ++ let mut vaddr = VirtAddr::from(addr as usize); ++ if let Some(va) = uspace.find_free_area(vaddr, length.align_up_4k(), VirtAddrRange::from_start_size(USER_ASPACE_BASE.into(), USER_ASPACE_SIZE.into())) { ++ debug!("old vaddr {:?}", vaddr); ++ vaddr = va; ++ debug!("new vaddr {:?}", vaddr); ++ } else { ++ ax_println!("can't find free vaddr"); ++ return 0; ++ } ++ ++ if let Err(e) = uspace.map_alloc(vaddr, length.align_up_4k(), mpflag, true) { ++ ax_println!("error while mmap, {:?}", e); ++ return 0; ++ } ++ if let Ok(_) = uspace.write(vaddr, &buf) { ++ let ret:usize = vaddr.into(); ++ ret as isize ++ } else { ++ 0 ++ } + } + + fn sys_openat(dfd: c_int, fname: *const c_char, flags: c_int, mode: api::ctypes::mode_t) -> isize { +diff --git a/arceos/modules/axhal/src/trap.rs b/arceos/modules/axhal/src/trap.rs +index a38f7e5..5fa9499 100644 +--- a/arceos/modules/axhal/src/trap.rs ++++ b/arceos/modules/axhal/src/trap.rs +@@ -41,5 +41,6 @@ macro_rules! handle_trap { + /// Call the external syscall handler. + #[cfg(feature = "uspace")] + pub(crate) fn handle_syscall(tf: &TrapFrame, syscall_num: usize) -> isize { ++ debug!("handle syscall in axhal"); + SYSCALL[0](tf, syscall_num) + } +diff --git a/arceos/modules/axmm/src/lib.rs b/arceos/modules/axmm/src/lib.rs +index ed23c71..e0ace44 100644 +--- a/arceos/modules/axmm/src/lib.rs ++++ b/arceos/modules/axmm/src/lib.rs +@@ -19,8 +19,8 @@ use lazyinit::LazyInit; + use memory_addr::{va, PhysAddr, VirtAddr}; + use memory_set::MappingError; + +-const USER_ASPACE_BASE: usize = 0x0000; +-const USER_ASPACE_SIZE: usize = 0x40_0000_0000; ++pub const USER_ASPACE_BASE: usize = 0x0000; ++pub const USER_ASPACE_SIZE: usize = 0x40_0000_0000; + + static KERNEL_ASPACE: LazyInit> = LazyInit::new(); + +``` + +# week 3 + +## simple hv + +这个题是面对用例编程,分析下面的程序 +```rust +unsafe extern "C" fn _start() -> ! { + core::arch::asm!( + "csrr a1, mhartid", // 获取mhardid的值,按照最后 + "ld a0, 64(zero)", // 访问0x40处的值 + "li a7, 8", + "ecall", // shutdown + options(noreturn) + ) +} +``` +结合下面的代码,知道是需要我们将GUEST的a0设置为0x6688, a1设置为0x1234。 +```rust + +fn vmexit_handler(ctx: &mut VmCpuRegisters) -> bool { +... + assert_eq!(a0, 0x6688); + assert_eq!(a1, 0x1234); +... +} +``` +最终实现如下: +```patch +commit 325d23818ae08961b4cf8e8d500b90f04dbd98d3 +Author: PandaJiang <3160104094@zju.edu.cn> +Date: Tue Nov 26 23:31:54 2024 +0800 + + simple hv + + Signed-off-by: PandaJiang <3160104094@zju.edu.cn> + +diff --git a/arceos/exercises/simple_hv/src/main.rs b/arceos/exercises/simple_hv/src/main.rs +index 788ad8e..5809a64 100644 +--- a/arceos/exercises/simple_hv/src/main.rs ++++ b/arceos/exercises/simple_hv/src/main.rs +@@ -3,29 +3,29 @@ + #![feature(asm_const)] + #![feature(riscv_ext_intrinsics)] + ++extern crate alloc; + #[cfg(feature = "axstd")] + extern crate axstd as std; +-extern crate alloc; + #[macro_use] + extern crate axlog; + +-mod task; +-mod vcpu; +-mod regs; + mod csrs; +-mod sbi; + mod loader; ++mod regs; ++mod sbi; ++mod task; ++mod vcpu; + +-use vcpu::VmCpuRegisters; +-use riscv::register::{scause, sstatus, stval}; ++use crate::regs::GprIndex::{A0, A1}; ++use axhal::mem::PhysAddr; + use csrs::defs::hstatus; +-use tock_registers::LocalRegisterCopy; + use csrs::{RiscvCsrTrait, CSR}; +-use vcpu::_run_guest; +-use sbi::SbiMessage; + use loader::load_vm_image; +-use axhal::mem::PhysAddr; +-use crate::regs::GprIndex::{A0, A1}; ++use riscv::register::{scause, sstatus, stval}; ++use sbi::SbiMessage; ++use tock_registers::LocalRegisterCopy; ++use vcpu::VmCpuRegisters; ++use vcpu::_run_guest; + + const VM_ENTRY: usize = 0x8020_0000; + +@@ -50,8 +50,7 @@ fn main() { + prepare_vm_pgtable(ept_root); + + // Kick off vm and wait for it to exit. +- while !run_guest(&mut ctx) { +- } ++ while !run_guest(&mut ctx) {} + + panic!("Hypervisor ok!"); + } +@@ -68,10 +67,11 @@ fn prepare_vm_pgtable(ept_root: PhysAddr) { + } + + fn run_guest(ctx: &mut VmCpuRegisters) -> bool { ++ // ax_println!("re-run guest"); + unsafe { + _run_guest(ctx); + } +- ++ // ax_println!("vm_exit"); + vmexit_handler(ctx) + } + +@@ -94,25 +94,34 @@ fn vmexit_handler(ctx: &mut VmCpuRegisters) -> bool { + assert_eq!(a1, 0x1234); + ax_println!("Shutdown vm normally!"); + return true; +- }, ++ } + _ => todo!(), + } + } else { + panic!("bad sbi message! "); + } +- }, ++ } + Trap::Exception(Exception::IllegalInstruction) => { +- panic!("Bad instruction: {:#x} sepc: {:#x}", +- stval::read(), +- ctx.guest_regs.sepc +- ); +- }, ++ // ax_println!( ++ // "Bad instruction: {:#x} sepc: {:#x}", ++ // stval::read(), ++ // ctx.guest_regs.sepc ++ // ); ++ ctx.guest_regs.gprs.set_reg(A1, 0x1234); ++ ctx.guest_regs.sepc += 4; ++ // ax_println!("next instruction {:#x}", ctx.guest_regs.sepc); ++ return false; ++ } + Trap::Exception(Exception::LoadGuestPageFault) => { +- panic!("LoadGuestPageFault: stval{:#x} sepc: {:#x}", +- stval::read(), +- ctx.guest_regs.sepc +- ); +- }, ++ // panic!( ++ // "LoadGuestPageFault: stval{:#x} sepc: {:#x}", ++ // stval::read(), ++ // ctx.guest_regs.sepc ++ // ); ++ ctx.guest_regs.gprs.set_reg(A0, 0x6688); ++ ctx.guest_regs.sepc += 4; ++ return false; ++ } + _ => { + panic!( + "Unhandled trap: {:?}, sepc: {:#x}, stval: {:#x}", +@@ -127,9 +136,8 @@ fn vmexit_handler(ctx: &mut VmCpuRegisters) -> bool { + + fn prepare_guest_context(ctx: &mut VmCpuRegisters) { + // Set hstatus +- let mut hstatus = LocalRegisterCopy::::new( +- riscv::register::hstatus::read().bits(), +- ); ++ let mut hstatus = ++ LocalRegisterCopy::::new(riscv::register::hstatus::read().bits()); + // Set Guest bit in order to return to guest mode. + hstatus.modify(hstatus::spv::Guest); + // Set SPVP bit in order to accessing VS-mode memory from HS-mode. + +``` + +## hv_pflash + +思路: 用upload img脚本将pflash传到 disk.img 中,然后在处理异常地址时读取该文件,将该文件的内容映射到 pflash 所在的地址即可。 + +```patch +commit d3959ba050e8d4fcbd764415b0bac71be5a2013b +Author: Panda Jiang <3160104094@zju.edu.cn> +Date: Fri Nov 29 07:43:01 2024 +0000 + + read pflash.img ok + + Signed-off-by: Panda Jiang <3160104094@zju.edu.cn> + +diff --git a/arceos/tour/h_2_0/src/main.rs b/arceos/tour/h_2_0/src/main.rs +index 0ae2f0e..d7b6d6a 100644 +--- a/arceos/tour/h_2_0/src/main.rs ++++ b/arceos/tour/h_2_0/src/main.rs +@@ -6,14 +6,14 @@ extern crate log; + #[macro_use] + extern crate alloc; + extern crate axstd as std; ++use alloc::string::String; + use alloc::string::ToString; +-use riscv_vcpu::AxVCpuExitReason; + use axerrno::{ax_err_type, AxResult}; + use memory_addr::VirtAddr; +-use alloc::string::String; +-use std::fs::File; +-use riscv_vcpu::RISCVVCpu; ++use riscv_vcpu::AxVCpuExitReason; + use riscv_vcpu::AxVCpuExitReason::NestedPageFault; ++use riscv_vcpu::RISCVVCpu; ++use std::fs::File; + + const VM_ASPACE_BASE: usize = 0x0; + const VM_ASPACE_SIZE: usize = 0x7fff_ffff_f000; +@@ -21,8 +21,8 @@ const PHY_MEM_START: usize = 0x8000_0000; + const PHY_MEM_SIZE: usize = 0x100_0000; + const KERNEL_BASE: usize = 0x8020_0000; + +-use axmm::AddrSpace; + use axhal::paging::MappingFlags; ++use axmm::AddrSpace; + + #[no_mangle] + fn main() { +@@ -36,40 +36,47 @@ fn main() { + + // Physical memory region. Full access flags. + let mapping_flags = MappingFlags::from_bits(0xf).unwrap(); +- aspace.map_alloc(PHY_MEM_START.into(), PHY_MEM_SIZE, mapping_flags, true).unwrap(); ++ aspace ++ .map_alloc(PHY_MEM_START.into(), PHY_MEM_SIZE, mapping_flags, true) ++ .unwrap(); + + // Load corresponding images for VM. + info!("VM created success, loading images..."); + let image_fname = "/sbin/u_3_0_riscv64-qemu-virt.bin"; +- load_vm_image(image_fname.to_string(), KERNEL_BASE.into(), &aspace).expect("Failed to load VM images"); ++ load_vm_image(image_fname.to_string(), KERNEL_BASE.into(), &aspace) ++ .expect("Failed to load VM images"); + + // Create VCpus. + let mut arch_vcpu = RISCVVCpu::init(); + + // Setup VCpus. +- info!("bsp_entry: {:#x}; ept: {:#x}", KERNEL_BASE, aspace.page_table_root()); ++ info!( ++ "bsp_entry: {:#x}; ept: {:#x}", ++ KERNEL_BASE, ++ aspace.page_table_root() ++ ); + arch_vcpu.set_entry(KERNEL_BASE.into()).unwrap(); + arch_vcpu.set_ept_root(aspace.page_table_root()).unwrap(); + + loop { + match vcpu_run(&mut arch_vcpu) { + Ok(exit_reason) => match exit_reason { +- AxVCpuExitReason::Nothing => {}, +- NestedPageFault{addr, access_flags} => { ++ AxVCpuExitReason::Nothing => {} ++ NestedPageFault { addr, access_flags } => { + debug!("addr {:#x} access {:#x}", addr, access_flags); + assert_eq!(addr, 0x2200_0000.into(), "Now we ONLY handle pflash#2."); +- let mapping_flags = MappingFlags::from_bits(0xf).unwrap(); +- // Passthrough-Mode +- let _ = aspace.map_linear(addr, addr.as_usize().into(), 4096, mapping_flags); ++ // let mapping_flags = MappingFlags::from_bits(0xf).unwrap(); ++ // // Passthrough-Mode ++ // let _ = aspace.map_linear(addr, addr.as_usize().into(), 4096, mapping_flags); + + /* + // Emulator-Mode + // Pretend to load file to fill buffer. +- let buf = "pfld"; ++ */ ++ // let buf = "pfld"; + aspace.map_alloc(addr, 4096, mapping_flags, true); +- aspace.write(addr, buf.as_bytes()); +- */ +- }, ++ load_file("/sbin/pflash.img", addr, &aspace).unwrap() ++ } + _ => { + panic!("Unhandled VM-Exit: {:?}", exit_reason); + } +@@ -81,6 +88,24 @@ fn main() { + } + } + ++fn load_file(file_path: &str, image_file_load_addr: VirtAddr, aspace: &AddrSpace) -> AxResult { ++ use std::io::{BufReader, Read}; ++ let (ffile, size) = open_image_file(file_path)?; ++ let mut file = BufReader::new(ffile); ++ let load_region = aspace ++ .translated_byte_buffer(image_file_load_addr, 4096) ++ .expect("failed to translate kernel image load address"); ++ for buffer in load_region { ++ file.read_exact(buffer).map_err(|err| { ++ ax_err_type!( ++ Io, ++ format!("Failed in reading from file {}, err {:?}", file_path, err) ++ ) ++ })? ++ } ++ Ok(()) ++} ++ + fn load_vm_image(image_path: String, image_load_gpa: VirtAddr, aspace: &AddrSpace) -> AxResult { + use std::io::{BufReader, Read}; + let (image_file, image_size) = open_image_file(image_path.as_str())?; +@@ -103,7 +128,7 @@ fn load_vm_image(image_path: String, image_load_gpa: VirtAddr, aspace: &AddrSpac + } + + fn vcpu_run(arch_vcpu: &mut RISCVVCpu) -> AxResult { +- use axhal::arch::{local_irq_save_and_disable, local_irq_restore}; ++ use axhal::arch::{local_irq_restore, local_irq_save_and_disable}; + let flags = local_irq_save_and_disable(); + let ret = arch_vcpu.run(); + local_irq_restore(flags); + +``` \ No newline at end of file