Load app from sdcard on K210, but panicked on qemu.

This commit is contained in:
Yifan Wu 2020-12-20 00:52:14 +08:00
parent ea515323d3
commit ae9eecf97b
18 changed files with 177 additions and 142 deletions

View File

@ -8,6 +8,5 @@ edition = "2018"
[dependencies]
spin = "0.7.0"
#lazy_static = { version = "1.4.0", features = ["spin_no_std"] }
lazy_static = "1.4.0"
rand = "0.8.0"
lazy_static = { version = "1.4.0", features = ["spin_no_std"] }
#rand = "0.8.0"

View File

@ -79,6 +79,7 @@ fn easy_fs_pack() -> std::io::Result<()> {
Ok(())
}
/*
#[test]
fn efs_test() -> std::io::Result<()> {
let block_file = Arc::new(BlockFile(Mutex::new(
@ -146,3 +147,4 @@ fn efs_test() -> std::io::Result<()> {
Ok(())
}
*/

View File

@ -5,6 +5,8 @@ KERNEL_ELF := target/$(TARGET)/$(MODE)/os
KERNEL_BIN := $(KERNEL_ELF).bin
KERNEL_ENTRY_PA := 0x80020000
DISASM_TMP := target/$(TARGET)/$(MODE)/asm
FS_IMG := ../user/target/$(TARGET)/$(MODE)/fs.img
SDCARD := /dev/sdb
# BOARD
BOARD ?= qemu
@ -22,11 +24,19 @@ OBJCOPY := rust-objcopy --binary-architecture=riscv64
# Disassembly
DISASM ?= -x
build: $(KERNEL_BIN)
build: $(KERNEL_BIN) $(FS_IMG)
sdcard: $(FS_IMG)
@sudo dd if=/dev/zero of=$(SDCARD) bs=1M count=16
@sudo dd if=$(FS_IMG) of=$(SDCARD)
$(KERNEL_BIN): kernel
@$(OBJCOPY) $(KERNEL_ELF) --strip-all -O binary $@
$(FS_IMG):
@echo "hello, world!"
@cd ../easy-fs && cargo run --release
kernel:
@cd ../user && make build
@cargo build --release --features "board_$(BOARD)"
@ -51,8 +61,8 @@ ifeq ($(BOARD),qemu)
-nographic \
-bios $(BOOTLOADER) \
-device loader,file=$(KERNEL_BIN),addr=$(KERNEL_ENTRY_PA) \
-drive file=fs.img,if=none,format=raw,id=x0 \
-device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0
-drive file=$(FS_IMG),if=none,format=raw,id=x0 \
-device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0
else
@cp $(BOOTLOADER) $(BOOTLOADER).copy
@dd if=$(KERNEL_BIN) of=$(BOOTLOADER).copy bs=128K seek=1

View File

@ -1,56 +1,6 @@
use std::io::{Result, Write};
use std::fs::{File, read_dir};
static TARGET_PATH: &str = "../user/target/riscv64gc-unknown-none-elf/release/";
fn main() {
println!("cargo:rerun-if-changed=../user/src/");
println!("cargo:rerun-if-changed={}", TARGET_PATH);
insert_app_data().unwrap();
}
static TARGET_PATH: &str = "../user/target/riscv64gc-unknown-none-elf/release/";
fn insert_app_data() -> Result<()> {
let mut f = File::create("src/link_app.S").unwrap();
let mut apps: Vec<_> = read_dir("../user/src/bin")
.unwrap()
.into_iter()
.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
})
.collect();
apps.sort();
writeln!(f, r#"
.align 4
.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 "{}\n""#, 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 12
app_{0}_start:
.incbin "{2}{1}"
app_{0}_end:"#, idx, app, TARGET_PATH)?;
}
Ok(())
}

View File

@ -16,7 +16,7 @@ pub const CLOCK_FREQ: usize = 12500000;
#[cfg(feature = "board_qemu")]
pub const MMIO: &[(usize, usize)] = &[
(0x10001000, 0x10000),
(0x10000000, 0x10000),
];
#[cfg(feature = "board_k210")]

View File

@ -4,11 +4,7 @@ mod sdcard;
use lazy_static::*;
use alloc::sync::Arc;
use core::any::Any;
pub trait BlockDevice : Send + Sync + Any {
fn read_block(&self, block_id: usize, buf: &mut [u8]);
fn write_block(&self, block_id: usize, buf: &[u8]);
}
use easy_fs::BlockDevice;
#[cfg(feature = "board_qemu")]
type BlockDeviceImpl = virtio_blk::VirtIOBlock;

View File

@ -717,7 +717,7 @@ lazy_static! {
fn init_sdcard() -> SDCard<SPIImpl<SPI0>> {
// wait previous output
usleep(100000);
let peripherals = Peripherals::take().unwrap();
let peripherals = unsafe { Peripherals::steal() };
sysctl::pll_set_freq(sysctl::pll::PLL0, 800_000_000).unwrap();
sysctl::pll_set_freq(sysctl::pll::PLL1, 300_000_000).unwrap();
sysctl::pll_set_freq(sysctl::pll::PLL2, 45_158_400).unwrap();

View File

@ -23,9 +23,12 @@ lazy_static! {
impl BlockDevice for VirtIOBlock {
fn read_block(&self, block_id: usize, buf: &mut [u8]) {
//println!("read block {}", block_id);
self.0.lock().read_block(block_id, buf).expect("Error when reading VirtIOBlk");
//println!("read block OK!");
}
fn write_block(&self, block_id: usize, buf: &[u8]) {
//println!("write block {}", block_id);
self.0.lock().write_block(block_id, buf).expect("Error when writing VirtIOBlk");
}
}
@ -44,6 +47,7 @@ pub extern "C" fn virtio_dma_alloc(pages: usize) -> PhysAddr {
for i in 0..pages {
let frame = frame_alloc().unwrap();
if i == 0 { ppn_base = frame.ppn; }
println!("virtio_dma_alloc {:?}", frame.ppn);
assert_eq!(frame.ppn.0, ppn_base.0 + i);
QUEUE_FRAMES.lock().push(frame);
}

104
os/src/fs/inode.rs Normal file
View File

@ -0,0 +1,104 @@
use easy_fs::{
EasyFileSystem,
Inode,
};
use crate::drivers::BLOCK_DEVICE;
use alloc::sync::Arc;
use lazy_static::*;
use bitflags::*;
use alloc::vec::Vec;
use spin::Mutex;
pub struct OSInode {
readable: bool,
writable: bool,
inner: Mutex<OSInodeInner>,
}
pub struct OSInodeInner {
offset: usize,
inode: Arc<Inode>,
}
impl OSInode {
pub fn new(
readable: bool,
writable: bool,
inode: Arc<Inode>,
) -> Self {
Self {
readable,
writable,
inner: Mutex::new(OSInodeInner {
offset: 0,
inode,
}),
}
}
pub fn read_all(&self) -> Vec<u8> {
let mut inner = self.inner.lock();
let mut buffer = [0u8; 512];
let mut v: Vec<u8> = Vec::new();
loop {
let len = inner.inode.read_at(inner.offset, &mut buffer);
if len == 0 {
break;
}
inner.offset += len;
v.extend_from_slice(&buffer[..len]);
}
v
}
}
lazy_static! {
pub static ref ROOT_INODE: Arc<Inode> = {
let efs = EasyFileSystem::open(BLOCK_DEVICE.clone());
Arc::new(EasyFileSystem::root_inode(&efs))
};
}
pub fn list_apps() {
println!("/**** APPS ****");
for app in ROOT_INODE.ls() {
println!("{}", app);
}
println!("**************/")
}
bitflags! {
pub struct OpenFlags: u32 {
const RDONLY = 0;
const WRONLY = 1 << 0;
const RDWR = 1 << 1;
const CREATE = 1 << 9;
const TRUNC = 1 << 10;
}
}
impl OpenFlags {
/// Do not check validity for simplicity
/// Return (readable, writable)
pub fn read_write(&self) -> (bool, bool) {
if self.is_empty() {
(true, false)
} else if self.contains(Self::WRONLY) {
(false, true)
} else {
(true, true)
}
}
}
pub fn open_file(name: &str, flags: OpenFlags) -> Option<Arc<OSInode>> {
let (readable, writable) = flags.read_write();
// TODO: do not support CREATE or TRUNC flags now
ROOT_INODE.find(name)
.map(|inode| {
Arc::new(OSInode::new(
readable,
writable,
inode
))
})
}

View File

@ -1,10 +1,13 @@
mod pipe;
mod stdio;
mod inode;
use crate::mm::UserBuffer;
use core::any::Any;
pub trait File : Any + Send + Sync {
fn readable(&self) -> bool;
fn writable(&self) -> bool;
fn read(&self, buf: UserBuffer) -> usize;
fn write(&self, buf: UserBuffer) -> usize;
fn as_any_ref(&self) -> &dyn Any;
@ -19,3 +22,4 @@ impl dyn File {
pub use pipe::{Pipe, make_pipe};
pub use stdio::{Stdin, Stdout};
pub use inode::{OSInode, open_file, OpenFlags, list_apps};

View File

@ -114,8 +114,10 @@ pub fn make_pipe() -> (Arc<Pipe>, Arc<Pipe>) {
}
impl File for Pipe {
fn readable(&self) -> bool { self.readable }
fn writable(&self) -> bool { self.writable }
fn read(&self, buf: UserBuffer) -> usize {
assert_eq!(self.readable, true);
assert_eq!(self.readable(), true);
let mut buf_iter = buf.into_iter();
let mut read_size = 0usize;
loop {
@ -141,7 +143,7 @@ impl File for Pipe {
}
}
fn write(&self, buf: UserBuffer) -> usize {
assert_eq!(self.writable, true);
assert_eq!(self.writable(), true);
let mut buf_iter = buf.into_iter();
let mut write_size = 0usize;
loop {

View File

@ -9,6 +9,8 @@ pub struct Stdin;
pub struct Stdout;
impl File for Stdin {
fn readable(&self) -> bool { true }
fn writable(&self) -> bool { false }
fn read(&self, mut user_buf: UserBuffer) -> usize {
assert_eq!(user_buf.len(), 1);
// busy loop
@ -33,6 +35,8 @@ impl File for Stdin {
}
impl File for Stdout {
fn readable(&self) -> bool { false }
fn writable(&self) -> bool { true }
fn read(&self, _user_buf: UserBuffer) -> usize{
panic!("Cannot read from stdout!");
}

View File

@ -1,62 +0,0 @@
use alloc::vec::Vec;
pub fn get_num_app() -> usize {
extern "C" { fn _num_app(); }
unsafe { (_num_app as usize as *const usize).read_volatile() }
}
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]
)
}
}
#[allow(unused)]
pub fn get_app_data_by_name(name: &str) -> Option<&'static [u8]> {
let num_app = get_num_app();
let app_names = app_names();
(0..num_app)
.find(|&i| app_names[i] == name)
.map(|i| get_app_data(i))
}
#[allow(unused)]
fn app_names() -> Vec<&'static str> {
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::new();
unsafe {
for _ in 0..num_app {
let mut end = start;
while end.read_volatile() != '\n' as u8 {
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);
// Mention that there is a extra char between names
start = end.add(2);
}
}
v
}
pub fn list_apps() {
let apps = app_names();
println!("/**** APPS ****");
for app in apps {
println!("{}", app);
}
println!("**************/")
}

View File

@ -17,7 +17,6 @@ mod lang_items;
mod sbi;
mod syscall;
mod trap;
mod loader;
mod config;
mod task;
mod timer;
@ -26,7 +25,6 @@ mod fs;
mod drivers;
global_asm!(include_str!("entry.asm"));
global_asm!(include_str!("link_app.S"));
fn clear_bss() {
extern "C" {
@ -44,11 +42,21 @@ pub fn rust_main() -> ! {
println!("[kernel] Hello, world!");
mm::init();
mm::remap_test();
task::add_initproc();
trap::init();
trap::enable_timer_interrupt();
timer::set_next_trigger();
loader::list_apps();
fs::list_apps();
//println!("after listing apps");
task::add_initproc();
/*
println!("after adding initproc!");
println!("list apps again!");
fs::list_apps();
println!("test user_shell now!");
let user_shell = fs::open_file("user_shell", fs::OpenFlags::RDONLY).unwrap();
println!("user_shell size = {}", user_shell.read_all().len());
println!("before running tasks!");
*/
task::run_tasks();
panic!("Unreachable in rust_main!");
}

View File

@ -10,6 +10,9 @@ pub fn sys_write(fd: usize, buf: *const u8, len: usize) -> isize {
return -1;
}
if let Some(file) = &inner.fd_table[fd] {
if !file.writable() {
return -1;
}
let file = file.clone();
// release Task lock manually to avoid deadlock
drop(inner);
@ -30,6 +33,9 @@ pub fn sys_read(fd: usize, buf: *const u8, len: usize) -> isize {
}
if let Some(file) = &inner.fd_table[fd] {
let file = file.clone();
if !file.readable() {
return -1;
}
// release Task lock manually to avoid deadlock
drop(inner);
file.read(

View File

@ -10,7 +10,11 @@ use crate::mm::{
translated_str,
translated_refmut,
};
use crate::loader::get_app_data_by_name;
use crate::fs::{
OSInode,
open_file,
OpenFlags,
};
use alloc::sync::Arc;
pub fn sys_exit(exit_code: i32) -> ! {
@ -48,9 +52,10 @@ pub fn sys_fork() -> isize {
pub fn sys_exec(path: *const u8) -> isize {
let token = current_user_token();
let path = translated_str(token, path);
if let Some(data) = get_app_data_by_name(path.as_str()) {
if let Some(app_inode) = open_file(path.as_str(), OpenFlags::RDONLY) {
let all_data = app_inode.read_all();
let task = current_task().unwrap();
task.exec(data);
task.exec(all_data.as_slice());
0
} else {
-1

View File

@ -5,14 +5,14 @@ mod manager;
mod processor;
mod pid;
use crate::loader::{get_app_data_by_name};
use crate::fs::{open_file, OpenFlags};
use switch::__switch;
use task::{TaskControlBlock, TaskStatus};
use alloc::sync::Arc;
use manager::fetch_task;
use lazy_static::*;
pub use context::TaskContext;
pub use processor::{
run_tasks,
current_task,
@ -76,9 +76,11 @@ pub fn exit_current_and_run_next(exit_code: i32) {
}
lazy_static! {
pub static ref INITPROC: Arc<TaskControlBlock> = Arc::new(
TaskControlBlock::new(get_app_data_by_name("initproc").unwrap())
);
pub static ref INITPROC: Arc<TaskControlBlock> = Arc::new({
let inode = open_file("initproc", OpenFlags::RDONLY).unwrap();
let v = inode.read_all();
TaskControlBlock::new(v.as_slice())
});
}
pub fn add_initproc() {

View File

@ -61,6 +61,7 @@ lazy_static! {
}
pub fn run_tasks() {
println!("into Processor::run_tasks!");
PROCESSOR.run();
}