Compare commits
10 commits
eeb8ac2352
...
3a57c25f66
Author | SHA1 | Date | |
---|---|---|---|
3a57c25f66 | |||
b7612e38d7 | |||
![]() |
cec2f15896 | ||
![]() |
493e373bcd | ||
![]() |
1f2b9a2faf | ||
![]() |
f9fc2a538c | ||
![]() |
5b846fce6a | ||
![]() |
123595601d | ||
![]() |
6699e80a30 | ||
![]() |
fcf104f124 |
50 changed files with 337 additions and 123 deletions
7
.github/workflows/doc-and-test.yml
vendored
7
.github/workflows/doc-and-test.yml
vendored
|
@ -4,7 +4,7 @@ on: [push]
|
||||||
|
|
||||||
env:
|
env:
|
||||||
CARGO_TERM_COLOR: always
|
CARGO_TERM_COLOR: always
|
||||||
rust_toolchain: nightly-2024-01-18
|
rust_toolchain: nightly-2025-02-18
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-doc:
|
build-doc:
|
||||||
|
@ -49,7 +49,10 @@ jobs:
|
||||||
- name: Install QEMU
|
- name: Install QEMU
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install ninja-build -y
|
sudo apt-get install autoconf automake autotools-dev curl libmpc-dev libmpfr-dev libgmp-dev \
|
||||||
|
gawk build-essential bison flex texinfo gperf libtool patchutils bc \
|
||||||
|
zlib1g-dev libexpat-dev pkg-config libglib2.0-dev libpixman-1-dev libsdl2-dev libslirp-dev \
|
||||||
|
python3 python3-pip ninja-build -y
|
||||||
if [ ! -d qemu-7.0.0 ]; then
|
if [ ! -d qemu-7.0.0 ]; then
|
||||||
wget https://download.qemu.org/qemu-7.0.0.tar.xz
|
wget https://download.qemu.org/qemu-7.0.0.tar.xz
|
||||||
tar -xf qemu-7.0.0.tar.xz
|
tar -xf qemu-7.0.0.tar.xz
|
||||||
|
|
|
@ -149,3 +149,59 @@ fn efs_test() -> std::io::Result<()> {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn mac_test() -> std::io::Result<()> {
|
||||||
|
const BLOCK_SZ: usize = 512;
|
||||||
|
|
||||||
|
let block_file = Arc::new(BlockFile(Mutex::new({
|
||||||
|
let f = OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.write(true)
|
||||||
|
.create(true)
|
||||||
|
.open("target/fs_mac.img")?;
|
||||||
|
f.set_len(8192 * BLOCK_SZ).unwrap();
|
||||||
|
f
|
||||||
|
})));
|
||||||
|
|
||||||
|
EasyFileSystem::create(block_file.clone(), 4096, 1);
|
||||||
|
let efs = EasyFileSystem::open(block_file.clone());
|
||||||
|
let root_inode = EasyFileSystem::root_inode(&efs);
|
||||||
|
|
||||||
|
root_inode.create("root_file");
|
||||||
|
root_inode.create("public_file");
|
||||||
|
|
||||||
|
let secret_inode = root_inode.find("root_file").unwrap();
|
||||||
|
secret_inode.write_at(0, b"TOP SECRET: root only!");
|
||||||
|
let public_inode = root_inode.find("public_file").unwrap();
|
||||||
|
public_inode.write_at(0, b"This file is public.");
|
||||||
|
|
||||||
|
let check_permission = |user: &str, filename: &str| -> bool {
|
||||||
|
if filename == "root_file" && user != "root" {
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let users = ["root", "nonroot"];
|
||||||
|
for user in users.iter() {
|
||||||
|
println!("{} task:", user);
|
||||||
|
|
||||||
|
for filename in ["root_file", "public_file"].iter() {
|
||||||
|
if check_permission(user, filename) {
|
||||||
|
let inode = root_inode.find(filename).unwrap();
|
||||||
|
let mut buf = [0u8; 128];
|
||||||
|
let len = inode.read_at(0, &mut buf);
|
||||||
|
let content = core::str::from_utf8(&buf[..len]).unwrap();
|
||||||
|
println!("{}: Opened successfully");
|
||||||
|
} else {
|
||||||
|
println!("{}: Permission denied");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
|
@ -1,12 +1,56 @@
|
||||||
use super::{BlockDevice, BLOCK_SZ};
|
use super::{BlockDevice, BLOCK_SZ};
|
||||||
|
use alloc::boxed::Box;
|
||||||
use alloc::collections::VecDeque;
|
use alloc::collections::VecDeque;
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
|
use core::alloc::Layout;
|
||||||
|
use core::mem::ManuallyDrop;
|
||||||
|
use core::ptr::{addr_of, addr_of_mut};
|
||||||
|
use core::slice;
|
||||||
use lazy_static::*;
|
use lazy_static::*;
|
||||||
use spin::Mutex;
|
use spin::Mutex;
|
||||||
|
|
||||||
|
/// Use `ManuallyDrop` to ensure data is deallocated with an alignment of `BLOCK_SZ`
|
||||||
|
struct CacheData(ManuallyDrop<Box<[u8; BLOCK_SZ]>>);
|
||||||
|
|
||||||
|
impl CacheData {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let data = unsafe {
|
||||||
|
let raw = alloc::alloc::alloc(Self::layout());
|
||||||
|
Box::from_raw(raw as *mut [u8; BLOCK_SZ])
|
||||||
|
};
|
||||||
|
Self(ManuallyDrop::new(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn layout() -> Layout {
|
||||||
|
Layout::from_size_align(BLOCK_SZ, BLOCK_SZ).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for CacheData {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
let ptr = self.0.as_mut_ptr();
|
||||||
|
unsafe { alloc::alloc::dealloc(ptr, Self::layout()) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<[u8]> for CacheData {
|
||||||
|
fn as_ref(&self) -> &[u8] {
|
||||||
|
let ptr = self.0.as_ptr() as *const u8;
|
||||||
|
unsafe { slice::from_raw_parts(ptr, BLOCK_SZ) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsMut<[u8]> for CacheData {
|
||||||
|
fn as_mut(&mut self) -> &mut [u8] {
|
||||||
|
let ptr = self.0.as_mut_ptr() as *mut u8;
|
||||||
|
unsafe { slice::from_raw_parts_mut(ptr, BLOCK_SZ) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Cached block inside memory
|
/// Cached block inside memory
|
||||||
pub struct BlockCache {
|
pub struct BlockCache {
|
||||||
/// cached block data
|
/// cached block data
|
||||||
cache: [u8; BLOCK_SZ],
|
cache: CacheData,
|
||||||
/// underlying block id
|
/// underlying block id
|
||||||
block_id: usize,
|
block_id: usize,
|
||||||
/// underlying block device
|
/// underlying block device
|
||||||
|
@ -18,8 +62,9 @@ pub struct BlockCache {
|
||||||
impl BlockCache {
|
impl BlockCache {
|
||||||
/// Load a new BlockCache from disk.
|
/// Load a new BlockCache from disk.
|
||||||
pub fn new(block_id: usize, block_device: Arc<dyn BlockDevice>) -> Self {
|
pub fn new(block_id: usize, block_device: Arc<dyn BlockDevice>) -> Self {
|
||||||
let mut cache = [0u8; BLOCK_SZ];
|
// for alignment and move effciency
|
||||||
block_device.read_block(block_id, &mut cache);
|
let mut cache = CacheData::new();
|
||||||
|
block_device.read_block(block_id, cache.as_mut());
|
||||||
Self {
|
Self {
|
||||||
cache,
|
cache,
|
||||||
block_id,
|
block_id,
|
||||||
|
@ -28,8 +73,12 @@ impl BlockCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Get the address of an offset inside the cached block data
|
/// Get the address of an offset inside the cached block data
|
||||||
fn addr_of_offset(&self, offset: usize) -> usize {
|
fn addr_of_offset(&self, offset: usize) -> *const u8 {
|
||||||
&self.cache[offset] as *const _ as usize
|
addr_of!(self.cache.as_ref()[offset])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn addr_of_offset_mut(&mut self, offset: usize) -> *mut u8 {
|
||||||
|
addr_of_mut!(self.cache.as_mut()[offset])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_ref<T>(&self, offset: usize) -> &T
|
pub fn get_ref<T>(&self, offset: usize) -> &T
|
||||||
|
@ -38,8 +87,8 @@ impl BlockCache {
|
||||||
{
|
{
|
||||||
let type_size = core::mem::size_of::<T>();
|
let type_size = core::mem::size_of::<T>();
|
||||||
assert!(offset + type_size <= BLOCK_SZ);
|
assert!(offset + type_size <= BLOCK_SZ);
|
||||||
let addr = self.addr_of_offset(offset);
|
let addr = self.addr_of_offset(offset) as *const T;
|
||||||
unsafe { &*(addr as *const T) }
|
unsafe { &*addr }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_mut<T>(&mut self, offset: usize) -> &mut T
|
pub fn get_mut<T>(&mut self, offset: usize) -> &mut T
|
||||||
|
@ -49,8 +98,8 @@ impl BlockCache {
|
||||||
let type_size = core::mem::size_of::<T>();
|
let type_size = core::mem::size_of::<T>();
|
||||||
assert!(offset + type_size <= BLOCK_SZ);
|
assert!(offset + type_size <= BLOCK_SZ);
|
||||||
self.modified = true;
|
self.modified = true;
|
||||||
let addr = self.addr_of_offset(offset);
|
let addr = self.addr_of_offset_mut(offset) as *mut T;
|
||||||
unsafe { &mut *(addr as *mut T) }
|
unsafe { &mut *addr }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read<T, V>(&self, offset: usize, f: impl FnOnce(&T) -> V) -> V {
|
pub fn read<T, V>(&self, offset: usize, f: impl FnOnce(&T) -> V) -> V {
|
||||||
|
@ -64,7 +113,8 @@ impl BlockCache {
|
||||||
pub fn sync(&mut self) {
|
pub fn sync(&mut self) {
|
||||||
if self.modified {
|
if self.modified {
|
||||||
self.modified = false;
|
self.modified = false;
|
||||||
self.block_device.write_block(self.block_id, &self.cache);
|
self.block_device
|
||||||
|
.write_block(self.block_id, self.cache.as_ref());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ impl EasyFileSystem {
|
||||||
let data_bitmap_blocks = (data_total_blocks + 4096) / 4097;
|
let data_bitmap_blocks = (data_total_blocks + 4096) / 4097;
|
||||||
let data_area_blocks = data_total_blocks - data_bitmap_blocks;
|
let data_area_blocks = data_total_blocks - data_bitmap_blocks;
|
||||||
let data_bitmap = Bitmap::new(
|
let data_bitmap = Bitmap::new(
|
||||||
(1 + inode_bitmap_blocks + inode_area_blocks) as usize,
|
(1 + inode_total_blocks) as usize,
|
||||||
data_bitmap_blocks as usize,
|
data_bitmap_blocks as usize,
|
||||||
);
|
);
|
||||||
let mut efs = Self {
|
let mut efs = Self {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
name = "os"
|
name = "os"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Yifan Wu <shinbokuow@163.com>"]
|
authors = ["Yifan Wu <shinbokuow@163.com>"]
|
||||||
edition = "2021"
|
edition = "2024"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
|
13
os/Makefile
13
os/Makefile
|
@ -74,20 +74,23 @@ QEMU_ARGS := -machine virt \
|
||||||
-drive file=$(FS_IMG),if=none,format=raw,id=x0 \
|
-drive file=$(FS_IMG),if=none,format=raw,id=x0 \
|
||||||
-device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0
|
-device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0
|
||||||
|
|
||||||
run-inner: build
|
QEMU_NAME := qemu-system-riscv64
|
||||||
|
qemu-version-check:
|
||||||
|
@sh scripts/qemu-ver-check.sh $(QEMU_NAME)
|
||||||
|
|
||||||
|
run-inner: qemu-version-check build
|
||||||
@qemu-system-riscv64 $(QEMU_ARGS)
|
@qemu-system-riscv64 $(QEMU_ARGS)
|
||||||
|
|
||||||
debug: build
|
debug: qemu-version-check build
|
||||||
@tmux new-session -d \
|
@tmux new-session -d \
|
||||||
"qemu-system-riscv64 $(QEMU_ARGS) -s -S" && \
|
"qemu-system-riscv64 $(QEMU_ARGS) -s -S" && \
|
||||||
tmux split-window -h "riscv64-unknown-elf-gdb -ex 'file $(KERNEL_ELF)' -ex 'set arch riscv:rv64' -ex 'target remote localhost:1234'" && \
|
tmux split-window -h "riscv64-unknown-elf-gdb -ex 'file $(KERNEL_ELF)' -ex 'set arch riscv:rv64' -ex 'target remote localhost:1234'" && \
|
||||||
tmux -2 attach-session -d
|
tmux -2 attach-session -d
|
||||||
|
|
||||||
|
gdbserver: qemu-version-check build
|
||||||
gdbserver: build
|
|
||||||
@qemu-system-riscv64 $(QEMU_ARGS) -s -S
|
@qemu-system-riscv64 $(QEMU_ARGS) -s -S
|
||||||
|
|
||||||
gdbclient:
|
gdbclient:
|
||||||
@riscv64-unknown-elf-gdb -ex 'file $(KERNEL_ELF)' -ex 'set arch riscv:rv64' -ex 'target remote localhost:1234'
|
@riscv64-unknown-elf-gdb -ex 'file $(KERNEL_ELF)' -ex 'set arch riscv:rv64' -ex 'target remote localhost:1234'
|
||||||
|
|
||||||
.PHONY: build env kernel clean disasm disasm-vim run-inner fs-img gdbserver gdbclient
|
.PHONY: build env kernel clean disasm disasm-vim run-inner fs-img gdbserver gdbclient qemu-version-check
|
||||||
|
|
26
os/scripts/qemu-ver-check.sh
Executable file
26
os/scripts/qemu-ver-check.sh
Executable file
|
@ -0,0 +1,26 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Argument1: The filename of qemu executable, e.g. qemu-system-riscv64
|
||||||
|
QEMU_PATH=$(which $1)
|
||||||
|
RET=$?
|
||||||
|
MINIMUM_MAJOR_VERSION=7
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
NC='\033[0m'
|
||||||
|
if [ $RET != 0 ]
|
||||||
|
then
|
||||||
|
echo "$1 not found"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
QEMU_VERSION=$($1 --version|head -n 1|awk '{print $4}')
|
||||||
|
MAJOR_VERSION=$(echo $QEMU_VERSION | awk -F '.' '{print $1}')
|
||||||
|
if [ $MAJOR_VERSION -lt $MINIMUM_MAJOR_VERSION ]
|
||||||
|
then
|
||||||
|
echo "${RED}Error: Required major version of QEMU is ${MINIMUM_MAJOR_VERSION}, " \
|
||||||
|
"but current is ${QEMU_VERSION}.${NC}"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "${GREEN}QEMU version is ${QEMU_VERSION}(>=${MINIMUM_MAJOR_VERSION}), OK!${NC}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
|
@ -1,7 +1,7 @@
|
||||||
use super::BlockDevice;
|
use super::BlockDevice;
|
||||||
use crate::mm::{
|
use crate::mm::{
|
||||||
frame_alloc, frame_dealloc, kernel_token, FrameTracker, PageTable, PhysAddr, PhysPageNum,
|
FrameTracker, PageTable, PhysAddr, PhysPageNum, StepByOne, VirtAddr, frame_alloc,
|
||||||
StepByOne, VirtAddr,
|
frame_dealloc, kernel_token,
|
||||||
};
|
};
|
||||||
use crate::sync::UPSafeCell;
|
use crate::sync::UPSafeCell;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
|
|
@ -15,5 +15,5 @@ pub trait File: Send + Sync {
|
||||||
fn write(&self, buf: UserBuffer) -> usize;
|
fn write(&self, buf: UserBuffer) -> usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use inode::{list_apps, open_file, OSInode, OpenFlags};
|
pub use inode::{OSInode, OpenFlags, list_apps, open_file};
|
||||||
pub use stdio::{Stdin, Stdout};
|
pub use stdio::{Stdin, Stdout};
|
||||||
|
|
|
@ -10,10 +10,10 @@ fn panic(info: &PanicInfo) -> ! {
|
||||||
"[kernel] Panicked at {}:{} {}",
|
"[kernel] Panicked at {}:{} {}",
|
||||||
location.file(),
|
location.file(),
|
||||||
location.line(),
|
location.line(),
|
||||||
info.message().unwrap()
|
info.message()
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
error!("[kernel] Panicked: {}", info.message().unwrap());
|
error!("[kernel] Panicked: {}", info.message());
|
||||||
}
|
}
|
||||||
shutdown(true)
|
shutdown(true)
|
||||||
}
|
}
|
||||||
|
|
47
os/src/logging.rs
Normal file
47
os/src/logging.rs
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
/*!
|
||||||
|
|
||||||
|
本模块利用 log crate 为你提供了日志功能,使用方式见 main.rs.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
use log::{self, Level, LevelFilter, Log, Metadata, Record};
|
||||||
|
|
||||||
|
struct SimpleLogger;
|
||||||
|
|
||||||
|
impl Log for SimpleLogger {
|
||||||
|
fn enabled(&self, _metadata: &Metadata) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
fn log(&self, record: &Record) {
|
||||||
|
if !self.enabled(record.metadata()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let color = match record.level() {
|
||||||
|
Level::Error => 31, // Red
|
||||||
|
Level::Warn => 93, // BrightYellow
|
||||||
|
Level::Info => 34, // Blue
|
||||||
|
Level::Debug => 32, // Green
|
||||||
|
Level::Trace => 90, // BrightBlack
|
||||||
|
};
|
||||||
|
println!(
|
||||||
|
"\u{1B}[{}m[{:>5}] {}\u{1B}[0m",
|
||||||
|
color,
|
||||||
|
record.level(),
|
||||||
|
record.args(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
fn flush(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init() {
|
||||||
|
static LOGGER: SimpleLogger = SimpleLogger;
|
||||||
|
log::set_logger(&LOGGER).unwrap();
|
||||||
|
log::set_max_level(match option_env!("LOG") {
|
||||||
|
Some("ERROR") => LevelFilter::Error,
|
||||||
|
Some("WARN") => LevelFilter::Warn,
|
||||||
|
Some("INFO") => LevelFilter::Info,
|
||||||
|
Some("DEBUG") => LevelFilter::Debug,
|
||||||
|
Some("TRACE") => LevelFilter::Trace,
|
||||||
|
_ => LevelFilter::Info,
|
||||||
|
});
|
||||||
|
}
|
|
@ -23,7 +23,6 @@
|
||||||
#![allow(unused_imports)]
|
#![allow(unused_imports)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
#![feature(panic_info_message)]
|
|
||||||
#![feature(alloc_error_handler)]
|
#![feature(alloc_error_handler)]
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
@ -31,6 +30,8 @@ extern crate alloc;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate bitflags;
|
extern crate bitflags;
|
||||||
|
|
||||||
|
use log::*;
|
||||||
|
|
||||||
#[path = "boards/qemu.rs"]
|
#[path = "boards/qemu.rs"]
|
||||||
mod board;
|
mod board;
|
||||||
|
|
||||||
|
@ -40,6 +41,7 @@ mod config;
|
||||||
mod drivers;
|
mod drivers;
|
||||||
pub mod fs;
|
pub mod fs;
|
||||||
pub mod lang_items;
|
pub mod lang_items;
|
||||||
|
mod logging;
|
||||||
pub mod mm;
|
pub mod mm;
|
||||||
pub mod sbi;
|
pub mod sbi;
|
||||||
pub mod sync;
|
pub mod sync;
|
||||||
|
@ -53,9 +55,9 @@ use core::arch::global_asm;
|
||||||
global_asm!(include_str!("entry.asm"));
|
global_asm!(include_str!("entry.asm"));
|
||||||
/// clear BSS segment
|
/// clear BSS segment
|
||||||
fn clear_bss() {
|
fn clear_bss() {
|
||||||
extern "C" {
|
unsafe extern "C" {
|
||||||
fn sbss();
|
safe fn sbss();
|
||||||
fn ebss();
|
safe fn ebss();
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
core::slice::from_raw_parts_mut(sbss as usize as *mut u8, ebss as usize - sbss as usize)
|
core::slice::from_raw_parts_mut(sbss as usize as *mut u8, ebss as usize - sbss as usize)
|
||||||
|
@ -63,11 +65,12 @@ fn clear_bss() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
/// the rust entry-point of os
|
/// the rust entry-point of os
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
pub fn rust_main() -> ! {
|
pub fn rust_main() -> ! {
|
||||||
clear_bss();
|
clear_bss();
|
||||||
println!("[kernel] Hello, world!");
|
logging::init();
|
||||||
|
info!("[kernel] Hello, world!");
|
||||||
mm::init();
|
mm::init();
|
||||||
mm::remap_test();
|
mm::remap_test();
|
||||||
trap::init();
|
trap::init();
|
||||||
|
|
|
@ -94,8 +94,8 @@ lazy_static! {
|
||||||
}
|
}
|
||||||
/// initiate the frame allocator using `ekernel` and `MEMORY_END`
|
/// initiate the frame allocator using `ekernel` and `MEMORY_END`
|
||||||
pub fn init_frame_allocator() {
|
pub fn init_frame_allocator() {
|
||||||
extern "C" {
|
unsafe extern "C" {
|
||||||
fn ekernel();
|
safe fn ekernel();
|
||||||
}
|
}
|
||||||
FRAME_ALLOCATOR.exclusive_access().init(
|
FRAME_ALLOCATOR.exclusive_access().init(
|
||||||
PhysAddr::from(ekernel as usize).ceil(),
|
PhysAddr::from(ekernel as usize).ceil(),
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
//! The global allocator
|
//! The global allocator
|
||||||
use crate::config::KERNEL_HEAP_SIZE;
|
use crate::config::KERNEL_HEAP_SIZE;
|
||||||
use buddy_system_allocator::LockedHeap;
|
use buddy_system_allocator::LockedHeap;
|
||||||
|
use core::ptr::addr_of_mut;
|
||||||
|
|
||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
/// heap allocator instance
|
/// heap allocator instance
|
||||||
|
@ -18,7 +19,7 @@ pub fn init_heap() {
|
||||||
unsafe {
|
unsafe {
|
||||||
HEAP_ALLOCATOR
|
HEAP_ALLOCATOR
|
||||||
.lock()
|
.lock()
|
||||||
.init(HEAP_SPACE.as_ptr() as usize, KERNEL_HEAP_SIZE);
|
.init(addr_of_mut!(HEAP_SPACE) as usize, KERNEL_HEAP_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,9 +27,9 @@ pub fn init_heap() {
|
||||||
pub fn heap_test() {
|
pub fn heap_test() {
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
extern "C" {
|
unsafe extern "C" {
|
||||||
fn sbss();
|
safe fn sbss();
|
||||||
fn ebss();
|
safe fn ebss();
|
||||||
}
|
}
|
||||||
let bss_range = sbss as usize..ebss as usize;
|
let bss_range = sbss as usize..ebss as usize;
|
||||||
let a = Box::new(5);
|
let a = Box::new(5);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
//! Implementation of [`MapArea`] and [`MemorySet`].
|
//! Implementation of [`MapArea`] and [`MemorySet`].
|
||||||
use super::{frame_alloc, FrameTracker};
|
|
||||||
|
use super::{FrameTracker, frame_alloc};
|
||||||
use super::{PTEFlags, PageTable, PageTableEntry};
|
use super::{PTEFlags, PageTable, PageTableEntry};
|
||||||
use super::{PhysAddr, PhysPageNum, VirtAddr, VirtPageNum};
|
use super::{PhysAddr, PhysPageNum, VirtAddr, VirtPageNum};
|
||||||
use super::{StepByOne, VPNRange};
|
use super::{StepByOne, VPNRange};
|
||||||
|
@ -12,17 +13,17 @@ use core::arch::asm;
|
||||||
use lazy_static::*;
|
use lazy_static::*;
|
||||||
use riscv::register::satp;
|
use riscv::register::satp;
|
||||||
|
|
||||||
extern "C" {
|
unsafe extern "C" {
|
||||||
fn stext();
|
safe fn stext();
|
||||||
fn etext();
|
safe fn etext();
|
||||||
fn srodata();
|
safe fn srodata();
|
||||||
fn erodata();
|
safe fn erodata();
|
||||||
fn sdata();
|
safe fn sdata();
|
||||||
fn edata();
|
safe fn edata();
|
||||||
fn sbss_with_stack();
|
safe fn sbss_with_stack();
|
||||||
fn ebss();
|
safe fn ebss();
|
||||||
fn ekernel();
|
safe fn ekernel();
|
||||||
fn strampoline();
|
safe fn strampoline();
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
|
@ -389,20 +390,26 @@ pub fn remap_test() {
|
||||||
let mid_text: VirtAddr = ((stext as usize + etext as usize) / 2).into();
|
let mid_text: VirtAddr = ((stext as usize + etext as usize) / 2).into();
|
||||||
let mid_rodata: VirtAddr = ((srodata as usize + erodata as usize) / 2).into();
|
let mid_rodata: VirtAddr = ((srodata as usize + erodata as usize) / 2).into();
|
||||||
let mid_data: VirtAddr = ((sdata as usize + edata as usize) / 2).into();
|
let mid_data: VirtAddr = ((sdata as usize + edata as usize) / 2).into();
|
||||||
assert!(!kernel_space
|
assert!(
|
||||||
.page_table
|
!kernel_space
|
||||||
.translate(mid_text.floor())
|
.page_table
|
||||||
.unwrap()
|
.translate(mid_text.floor())
|
||||||
.writable(),);
|
.unwrap()
|
||||||
assert!(!kernel_space
|
.writable(),
|
||||||
.page_table
|
);
|
||||||
.translate(mid_rodata.floor())
|
assert!(
|
||||||
.unwrap()
|
!kernel_space
|
||||||
.writable(),);
|
.page_table
|
||||||
assert!(!kernel_space
|
.translate(mid_rodata.floor())
|
||||||
.page_table
|
.unwrap()
|
||||||
.translate(mid_data.floor())
|
.writable(),
|
||||||
.unwrap()
|
);
|
||||||
.executable(),);
|
assert!(
|
||||||
|
!kernel_space
|
||||||
|
.page_table
|
||||||
|
.translate(mid_data.floor())
|
||||||
|
.unwrap()
|
||||||
|
.executable(),
|
||||||
|
);
|
||||||
println!("remap_test passed!");
|
println!("remap_test passed!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,13 +13,13 @@ mod page_table;
|
||||||
|
|
||||||
use address::VPNRange;
|
use address::VPNRange;
|
||||||
pub use address::{PhysAddr, PhysPageNum, StepByOne, VirtAddr, VirtPageNum};
|
pub use address::{PhysAddr, PhysPageNum, StepByOne, VirtAddr, VirtPageNum};
|
||||||
pub use frame_allocator::{frame_alloc, frame_dealloc, FrameTracker};
|
pub use frame_allocator::{FrameTracker, frame_alloc, frame_dealloc};
|
||||||
pub use memory_set::remap_test;
|
pub use memory_set::remap_test;
|
||||||
pub use memory_set::{kernel_token, MapPermission, MemorySet, KERNEL_SPACE};
|
pub use memory_set::{KERNEL_SPACE, MapPermission, MemorySet, kernel_token};
|
||||||
use page_table::PTEFlags;
|
use page_table::PTEFlags;
|
||||||
pub use page_table::{
|
pub use page_table::{
|
||||||
translated_byte_buffer, translated_ref, translated_refmut, translated_str, PageTable,
|
PageTable, PageTableEntry, UserBuffer, UserBufferIterator, translated_byte_buffer,
|
||||||
PageTableEntry, UserBuffer, UserBufferIterator,
|
translated_ref, translated_refmut, translated_str,
|
||||||
};
|
};
|
||||||
/// initiate heap allocator, frame allocator and kernel space
|
/// initiate heap allocator, frame allocator and kernel space
|
||||||
pub fn init() {
|
pub fn init() {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
//! Implementation of [`PageTableEntry`] and [`PageTable`].
|
//! Implementation of [`PageTableEntry`] and [`PageTable`].
|
||||||
use super::{frame_alloc, FrameTracker, PhysAddr, PhysPageNum, StepByOne, VirtAddr, VirtPageNum};
|
|
||||||
|
use super::{FrameTracker, PhysAddr, PhysPageNum, StepByOne, VirtAddr, VirtPageNum, frame_alloc};
|
||||||
use alloc::string::String;
|
use alloc::string::String;
|
||||||
use alloc::vec;
|
use alloc::vec;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
|
|
@ -20,7 +20,7 @@ pub fn set_timer(timer: usize) {
|
||||||
|
|
||||||
/// use sbi call to shutdown the kernel
|
/// use sbi call to shutdown the kernel
|
||||||
pub fn shutdown(failure: bool) -> ! {
|
pub fn shutdown(failure: bool) -> ! {
|
||||||
use sbi_rt::{system_reset, NoReason, Shutdown, SystemFailure};
|
use sbi_rt::{NoReason, Shutdown, SystemFailure, system_reset};
|
||||||
if !failure {
|
if !failure {
|
||||||
system_reset(Shutdown, NoReason);
|
system_reset(Shutdown, NoReason);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! File and filesystem-related syscalls
|
//! File and filesystem-related syscalls
|
||||||
use crate::fs::{open_file, OpenFlags};
|
use crate::fs::{OpenFlags, open_file};
|
||||||
use crate::mm::{translated_byte_buffer, translated_str, UserBuffer};
|
use crate::mm::{UserBuffer, translated_byte_buffer, translated_str};
|
||||||
use crate::task::{current_task, current_user_token};
|
use crate::task::{current_task, current_user_token};
|
||||||
|
|
||||||
pub fn sys_write(fd: usize, buf: *const u8, len: usize) -> isize {
|
pub fn sys_write(fd: usize, buf: *const u8, len: usize) -> isize {
|
||||||
|
@ -47,6 +47,13 @@ pub fn sys_open(path: *const u8, flags: u32) -> isize {
|
||||||
let task = current_task().unwrap();
|
let task = current_task().unwrap();
|
||||||
let token = current_user_token();
|
let token = current_user_token();
|
||||||
let path = translated_str(token, path);
|
let path = translated_str(token, path);
|
||||||
|
|
||||||
|
// 简单用户检查示例:非 root 用户不能打开 /root 下文件
|
||||||
|
let username = task.inner_exclusive_access().user.clone();
|
||||||
|
if path.starts_with("/root") && username != "root" {
|
||||||
|
return -1; // Permission denied
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(inode) = open_file(path.as_str(), OpenFlags::from_bits(flags).unwrap()) {
|
if let Some(inode) = open_file(path.as_str(), OpenFlags::from_bits(flags).unwrap()) {
|
||||||
let mut inner = task.inner_exclusive_access();
|
let mut inner = task.inner_exclusive_access();
|
||||||
let fd = inner.alloc_fd();
|
let fd = inner.alloc_fd();
|
||||||
|
@ -57,6 +64,7 @@ pub fn sys_open(path: *const u8, flags: u32) -> isize {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn sys_close(fd: usize) -> isize {
|
pub fn sys_close(fd: usize) -> isize {
|
||||||
let task = current_task().unwrap();
|
let task = current_task().unwrap();
|
||||||
let mut inner = task.inner_exclusive_access();
|
let mut inner = task.inner_exclusive_access();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::fs::{open_file, OpenFlags};
|
use crate::fs::{OpenFlags, open_file};
|
||||||
use crate::mm::{translated_refmut, translated_str};
|
use crate::mm::{translated_refmut, translated_str};
|
||||||
use crate::task::{
|
use crate::task::{
|
||||||
add_task, current_task, current_user_token, exit_current_and_run_next,
|
add_task, current_task, current_user_token, exit_current_and_run_next,
|
||||||
|
|
|
@ -23,20 +23,20 @@ mod switch;
|
||||||
#[allow(rustdoc::private_intra_doc_links)]
|
#[allow(rustdoc::private_intra_doc_links)]
|
||||||
mod task;
|
mod task;
|
||||||
|
|
||||||
use crate::fs::{open_file, OpenFlags};
|
use crate::fs::{OpenFlags, open_file};
|
||||||
use crate::sbi::shutdown;
|
use crate::sbi::shutdown;
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
pub use context::TaskContext;
|
pub use context::TaskContext;
|
||||||
use lazy_static::*;
|
use lazy_static::*;
|
||||||
pub use manager::{fetch_task, TaskManager};
|
pub use manager::{TaskManager, fetch_task};
|
||||||
use switch::__switch;
|
use switch::__switch;
|
||||||
use task::{TaskControlBlock, TaskStatus};
|
use task::{TaskControlBlock, TaskStatus};
|
||||||
|
|
||||||
pub use manager::add_task;
|
pub use manager::add_task;
|
||||||
pub use pid::{pid_alloc, KernelStack, PidAllocator, PidHandle};
|
pub use pid::{KernelStack, PidAllocator, PidHandle, pid_alloc};
|
||||||
pub use processor::{
|
pub use processor::{
|
||||||
current_task, current_trap_cx, current_user_token, run_tasks, schedule, take_current_task,
|
Processor, current_task, current_trap_cx, current_user_token, run_tasks, schedule,
|
||||||
Processor,
|
take_current_task,
|
||||||
};
|
};
|
||||||
/// Suspend the current 'Running' task and run the next task in task list.
|
/// Suspend the current 'Running' task and run the next task in task list.
|
||||||
pub fn suspend_current_and_run_next() {
|
pub fn suspend_current_and_run_next() {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//!Implementation of [`PidAllocator`]
|
//!Implementation of [`PidAllocator`]
|
||||||
use crate::config::{KERNEL_STACK_SIZE, PAGE_SIZE, TRAMPOLINE};
|
use crate::config::{KERNEL_STACK_SIZE, PAGE_SIZE, TRAMPOLINE};
|
||||||
use crate::mm::{MapPermission, VirtAddr, KERNEL_SPACE};
|
use crate::mm::{KERNEL_SPACE, MapPermission, VirtAddr};
|
||||||
use crate::sync::UPSafeCell;
|
use crate::sync::UPSafeCell;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use lazy_static::*;
|
use lazy_static::*;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//!Implementation of [`Processor`] and Intersection of control flow
|
//!Implementation of [`Processor`] and Intersection of control flow
|
||||||
use super::__switch;
|
use super::__switch;
|
||||||
use super::{fetch_task, TaskStatus};
|
|
||||||
use super::{TaskContext, TaskControlBlock};
|
use super::{TaskContext, TaskControlBlock};
|
||||||
|
use super::{TaskStatus, fetch_task};
|
||||||
use crate::sync::UPSafeCell;
|
use crate::sync::UPSafeCell;
|
||||||
use crate::trap::TrapContext;
|
use crate::trap::TrapContext;
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
|
|
|
@ -4,6 +4,11 @@ use core::arch::global_asm;
|
||||||
|
|
||||||
global_asm!(include_str!("switch.S"));
|
global_asm!(include_str!("switch.S"));
|
||||||
|
|
||||||
extern "C" {
|
unsafe extern "C" {
|
||||||
pub fn __switch(current_task_cx_ptr: *mut TaskContext, next_task_cx_ptr: *const TaskContext);
|
/// Switch to the context of `next_task_cx_ptr`, saving the current context
|
||||||
|
/// in `current_task_cx_ptr`.
|
||||||
|
pub unsafe fn __switch(
|
||||||
|
current_task_cx_ptr: *mut TaskContext,
|
||||||
|
next_task_cx_ptr: *const TaskContext,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
//!Implementation of [`TaskControlBlock`]
|
//!Implementation of [`TaskControlBlock`]
|
||||||
use super::TaskContext;
|
use super::TaskContext;
|
||||||
use super::{pid_alloc, KernelStack, PidHandle};
|
use super::{KernelStack, PidHandle, pid_alloc};
|
||||||
use crate::config::TRAP_CONTEXT;
|
use crate::config::TRAP_CONTEXT;
|
||||||
use crate::fs::{File, Stdin, Stdout};
|
use crate::fs::{File, Stdin, Stdout};
|
||||||
use crate::mm::{MemorySet, PhysPageNum, VirtAddr, KERNEL_SPACE};
|
use crate::mm::{KERNEL_SPACE, MemorySet, PhysPageNum, VirtAddr};
|
||||||
use crate::sync::UPSafeCell;
|
use crate::sync::UPSafeCell;
|
||||||
use crate::trap::{trap_handler, TrapContext};
|
use crate::trap::{TrapContext, trap_handler};
|
||||||
use alloc::sync::{Arc, Weak};
|
use alloc::sync::{Arc, Weak};
|
||||||
use alloc::vec;
|
use alloc::vec;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
@ -30,6 +30,9 @@ pub struct TaskControlBlockInner {
|
||||||
pub children: Vec<Arc<TaskControlBlock>>,
|
pub children: Vec<Arc<TaskControlBlock>>,
|
||||||
pub exit_code: i32,
|
pub exit_code: i32,
|
||||||
pub fd_table: Vec<Option<Arc<dyn File + Send + Sync>>>,
|
pub fd_table: Vec<Option<Arc<dyn File + Send + Sync>>>,
|
||||||
|
|
||||||
|
// New: User
|
||||||
|
pub user: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TaskControlBlockInner {
|
impl TaskControlBlockInner {
|
||||||
|
@ -166,6 +169,7 @@ impl TaskControlBlock {
|
||||||
children: Vec::new(),
|
children: Vec::new(),
|
||||||
exit_code: 0,
|
exit_code: 0,
|
||||||
fd_table: new_fd_table,
|
fd_table: new_fd_table,
|
||||||
|
user: username.to_string(), // Init User name
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//! Implementation of [`TrapContext`]
|
//! Implementation of [`TrapContext`]
|
||||||
use riscv::register::sstatus::{self, Sstatus, SPP};
|
use riscv::register::sstatus::{self, SPP, Sstatus};
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
|
@ -50,7 +50,7 @@ pub fn enable_timer_interrupt() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[unsafe(no_mangle)]
|
||||||
/// handle an interrupt, exception, or system call from user space
|
/// handle an interrupt, exception, or system call from user space
|
||||||
pub fn trap_handler() -> ! {
|
pub fn trap_handler() -> ! {
|
||||||
set_kernel_trap_entry();
|
set_kernel_trap_entry();
|
||||||
|
@ -103,7 +103,7 @@ pub fn trap_handler() -> ! {
|
||||||
trap_return();
|
trap_return();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[unsafe(no_mangle)]
|
||||||
/// set the new addr of __restore asm function in TRAMPOLINE page,
|
/// set the new addr of __restore asm function in TRAMPOLINE page,
|
||||||
/// set the reg a0 = trap_cx_ptr, reg a1 = phy addr of usr page table,
|
/// set the reg a0 = trap_cx_ptr, reg a1 = phy addr of usr page table,
|
||||||
/// finally, jump to new addr of __restore asm function
|
/// finally, jump to new addr of __restore asm function
|
||||||
|
@ -111,9 +111,9 @@ pub fn trap_return() -> ! {
|
||||||
set_user_trap_entry();
|
set_user_trap_entry();
|
||||||
let trap_cx_ptr = TRAP_CONTEXT;
|
let trap_cx_ptr = TRAP_CONTEXT;
|
||||||
let user_satp = current_user_token();
|
let user_satp = current_user_token();
|
||||||
extern "C" {
|
unsafe extern "C" {
|
||||||
fn __alltraps();
|
unsafe fn __alltraps();
|
||||||
fn __restore();
|
unsafe fn __restore();
|
||||||
}
|
}
|
||||||
let restore_va = __restore as usize - __alltraps as usize + TRAMPOLINE;
|
let restore_va = __restore as usize - __alltraps as usize + TRAMPOLINE;
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -128,7 +128,7 @@ pub fn trap_return() -> ! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[unsafe(no_mangle)]
|
||||||
/// Unimplement: traps/interrupts/exceptions from kernel mode
|
/// Unimplement: traps/interrupts/exceptions from kernel mode
|
||||||
/// Todo: Chapter 9: I/O device
|
/// Todo: Chapter 9: I/O device
|
||||||
pub fn trap_from_kernel() -> ! {
|
pub fn trap_from_kernel() -> ! {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[toolchain]
|
[toolchain]
|
||||||
profile = "minimal"
|
profile = "minimal"
|
||||||
# use the nightly version of the last stable toolchain, see <https://forge.rust-lang.org/>
|
# use the nightly version of the last stable toolchain, see <https://forge.rust-lang.org/>
|
||||||
channel = "nightly-2024-05-01"
|
channel = "nightly-2025-02-18"
|
||||||
components = ["rust-src", "llvm-tools", "rustfmt", "clippy"]
|
components = ["rust-src", "llvm-tools", "rustfmt", "clippy"]
|
||||||
targets = ["riscv64gc-unknown-none-elf"]
|
targets = ["riscv64gc-unknown-none-elf"]
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
name = "user_lib"
|
name = "user_lib"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Yifan Wu <shinbokuow@163.com>"]
|
authors = ["Yifan Wu <shinbokuow@163.com>"]
|
||||||
edition = "2018"
|
edition = "2024"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,9 @@
|
||||||
extern crate user_lib;
|
extern crate user_lib;
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
use user_lib::{close, open, read, OpenFlags};
|
use user_lib::{OpenFlags, close, open, read};
|
||||||
|
|
||||||
#[no_mangle]
|
#[unsafe(no_mangle)]
|
||||||
pub fn main() -> i32 {
|
pub fn main() -> i32 {
|
||||||
let fd = open("filea\0", OpenFlags::RDONLY);
|
let fd = open("filea\0", OpenFlags::RDONLY);
|
||||||
if fd == -1 {
|
if fd == -1 {
|
||||||
|
|
|
@ -7,7 +7,7 @@ use user_lib::{exit, fork, wait, waitpid, yield_};
|
||||||
|
|
||||||
const MAGIC: i32 = -0x10384;
|
const MAGIC: i32 = -0x10384;
|
||||||
|
|
||||||
#[no_mangle]
|
#[unsafe(no_mangle)]
|
||||||
pub fn main() -> i32 {
|
pub fn main() -> i32 {
|
||||||
println!("I am the parent. Forking the child...");
|
println!("I am the parent. Forking the child...");
|
||||||
let pid = fork();
|
let pid = fork();
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
extern crate user_lib;
|
extern crate user_lib;
|
||||||
|
|
||||||
macro_rules! color_text {
|
macro_rules! color_text {
|
||||||
($text:expr, $color:expr) => {{
|
($text:expr, $color:expr) => {
|
||||||
format_args!("\x1b[{}m{}\x1b[0m", $color, $text)
|
format_args!("\x1b[{}m{}\x1b[0m", $color, $text)
|
||||||
}};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[unsafe(no_mangle)]
|
||||||
pub fn main() -> i32 {
|
pub fn main() -> i32 {
|
||||||
println!(
|
println!(
|
||||||
"{}{}{}{}{} {}{}{}{} {}{}{}{}{}{}",
|
"{}{}{}{}{} {}{}{}{} {}{}{}{}{}{}",
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate user_lib;
|
extern crate user_lib;
|
||||||
|
|
||||||
use user_lib::{close, open, read, write, OpenFlags};
|
use user_lib::{OpenFlags, close, open, read, write};
|
||||||
|
|
||||||
#[no_mangle]
|
#[unsafe(no_mangle)]
|
||||||
pub fn main() -> i32 {
|
pub fn main() -> i32 {
|
||||||
let test_str = "Hello, world!";
|
let test_str = "Hello, world!";
|
||||||
let filea = "filea\0";
|
let filea = "filea\0";
|
||||||
|
|
|
@ -8,7 +8,7 @@ use user_lib::{exit, fork, wait};
|
||||||
|
|
||||||
const MAX_CHILD: usize = 30;
|
const MAX_CHILD: usize = 30;
|
||||||
|
|
||||||
#[no_mangle]
|
#[unsafe(no_mangle)]
|
||||||
pub fn main() -> i32 {
|
pub fn main() -> i32 {
|
||||||
for i in 0..MAX_CHILD {
|
for i in 0..MAX_CHILD {
|
||||||
let pid = fork();
|
let pid = fork();
|
||||||
|
|
|
@ -8,7 +8,7 @@ use user_lib::{exit, fork, get_time, getpid, sleep, wait};
|
||||||
|
|
||||||
static NUM: usize = 30;
|
static NUM: usize = 30;
|
||||||
|
|
||||||
#[no_mangle]
|
#[unsafe(no_mangle)]
|
||||||
pub fn main() -> i32 {
|
pub fn main() -> i32 {
|
||||||
for _ in 0..NUM {
|
for _ in 0..NUM {
|
||||||
let pid = fork();
|
let pid = fork();
|
||||||
|
|
|
@ -6,7 +6,7 @@ extern crate user_lib;
|
||||||
|
|
||||||
use user_lib::{fork, getpid, wait};
|
use user_lib::{fork, getpid, wait};
|
||||||
|
|
||||||
#[no_mangle]
|
#[unsafe(no_mangle)]
|
||||||
pub fn main() -> i32 {
|
pub fn main() -> i32 {
|
||||||
assert_eq!(wait(&mut 0i32), -1);
|
assert_eq!(wait(&mut 0i32), -1);
|
||||||
println!("sys_wait without child process test passed!");
|
println!("sys_wait without child process test passed!");
|
||||||
|
|
|
@ -29,7 +29,7 @@ fn fork_tree(cur: &str) {
|
||||||
fork_child(cur, '1');
|
fork_child(cur, '1');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[unsafe(no_mangle)]
|
||||||
pub fn main() -> i32 {
|
pub fn main() -> i32 {
|
||||||
fork_tree("");
|
fork_tree("");
|
||||||
sleep(3000);
|
sleep(3000);
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate user_lib;
|
extern crate user_lib;
|
||||||
|
|
||||||
#[no_mangle]
|
#[unsafe(no_mangle)]
|
||||||
pub fn main() -> i32 {
|
pub fn main() -> i32 {
|
||||||
println!("Hello world from user mode program!");
|
println!("Hello world from user mode program!");
|
||||||
0
|
0
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate user_lib;
|
extern crate user_lib;
|
||||||
|
|
||||||
use user_lib::{close, get_time, open, write, OpenFlags};
|
use user_lib::{OpenFlags, close, get_time, open, write};
|
||||||
|
|
||||||
#[no_mangle]
|
#[unsafe(no_mangle)]
|
||||||
pub fn main() -> i32 {
|
pub fn main() -> i32 {
|
||||||
let mut buffer = [0u8; 1024]; // 1KiB
|
let mut buffer = [0u8; 1024]; // 1KiB
|
||||||
for (i, ch) in buffer.iter_mut().enumerate() {
|
for (i, ch) in buffer.iter_mut().enumerate() {
|
||||||
|
|
|
@ -6,7 +6,7 @@ extern crate user_lib;
|
||||||
|
|
||||||
use user_lib::{exec, fork, wait, yield_};
|
use user_lib::{exec, fork, wait, yield_};
|
||||||
|
|
||||||
#[no_mangle]
|
#[unsafe(no_mangle)]
|
||||||
fn main() -> i32 {
|
fn main() -> i32 {
|
||||||
if fork() == 0 {
|
if fork() == 0 {
|
||||||
exec("user_shell\0");
|
exec("user_shell\0");
|
||||||
|
|
|
@ -44,7 +44,7 @@ fn work(times: isize) {
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[unsafe(no_mangle)]
|
||||||
pub fn main() -> i32 {
|
pub fn main() -> i32 {
|
||||||
for _ in 0..NUM {
|
for _ in 0..NUM {
|
||||||
let pid = fork();
|
let pid = fork();
|
||||||
|
|
|
@ -15,7 +15,7 @@ fn sleepy() {
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[unsafe(no_mangle)]
|
||||||
pub fn main() -> i32 {
|
pub fn main() -> i32 {
|
||||||
let current_time = get_time();
|
let current_time = get_time();
|
||||||
let pid = fork();
|
let pid = fork();
|
||||||
|
|
|
@ -6,7 +6,7 @@ extern crate user_lib;
|
||||||
|
|
||||||
use user_lib::{get_time, sleep};
|
use user_lib::{get_time, sleep};
|
||||||
|
|
||||||
#[no_mangle]
|
#[unsafe(no_mangle)]
|
||||||
pub fn main() -> i32 {
|
pub fn main() -> i32 {
|
||||||
println!("into sleep test!");
|
println!("into sleep test!");
|
||||||
let start = get_time();
|
let start = get_time();
|
||||||
|
|
|
@ -12,7 +12,7 @@ fn f(depth: usize) {
|
||||||
f(depth + 1);
|
f(depth + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[unsafe(no_mangle)]
|
||||||
pub fn main() -> i32 {
|
pub fn main() -> i32 {
|
||||||
println!("It should trigger segmentation fault!");
|
println!("It should trigger segmentation fault!");
|
||||||
f(0);
|
f(0);
|
||||||
|
|
|
@ -16,7 +16,7 @@ use alloc::string::String;
|
||||||
use user_lib::console::getchar;
|
use user_lib::console::getchar;
|
||||||
use user_lib::{exec, fork, waitpid};
|
use user_lib::{exec, fork, waitpid};
|
||||||
|
|
||||||
#[no_mangle]
|
#[unsafe(no_mangle)]
|
||||||
pub fn main() -> i32 {
|
pub fn main() -> i32 {
|
||||||
println!("Rust user shell");
|
println!("Rust user shell");
|
||||||
let mut line: String = String::new();
|
let mut line: String = String::new();
|
||||||
|
|
|
@ -84,7 +84,7 @@ fn run_tests(tests: &[(&str, &str, &str, &str, i32)]) -> i32 {
|
||||||
pass_num
|
pass_num
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[unsafe(no_mangle)]
|
||||||
pub fn main() -> i32 {
|
pub fn main() -> i32 {
|
||||||
let succ_num = run_tests(SUCC_TESTS);
|
let succ_num = run_tests(SUCC_TESTS);
|
||||||
let err_num = run_tests(FAIL_TESTS);
|
let err_num = run_tests(FAIL_TESTS);
|
||||||
|
|
|
@ -20,7 +20,7 @@ static TESTS: &[&str] = &[
|
||||||
|
|
||||||
use user_lib::{exec, fork, waitpid};
|
use user_lib::{exec, fork, waitpid};
|
||||||
|
|
||||||
#[no_mangle]
|
#[unsafe(no_mangle)]
|
||||||
pub fn main() -> i32 {
|
pub fn main() -> i32 {
|
||||||
for test in TESTS {
|
for test in TESTS {
|
||||||
println!("Usertests: Running {}", test);
|
println!("Usertests: Running {}", test);
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
extern crate user_lib;
|
extern crate user_lib;
|
||||||
use user_lib::{getpid, yield_};
|
use user_lib::{getpid, yield_};
|
||||||
|
|
||||||
#[no_mangle]
|
#[unsafe(no_mangle)]
|
||||||
pub fn main() -> i32 {
|
pub fn main() -> i32 {
|
||||||
println!("Hello, I am process {}.", getpid());
|
println!("Hello, I am process {}.", getpid());
|
||||||
for i in 0..5 {
|
for i in 0..5 {
|
||||||
|
|
|
@ -2,7 +2,7 @@ use super::exit;
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic_handler(panic_info: &core::panic::PanicInfo) -> ! {
|
fn panic_handler(panic_info: &core::panic::PanicInfo) -> ! {
|
||||||
let err = panic_info.message().unwrap();
|
let err = panic_info.message();
|
||||||
if let Some(location) = panic_info.location() {
|
if let Some(location) = panic_info.location() {
|
||||||
println!(
|
println!(
|
||||||
"Panicked at {}:{}, {}",
|
"Panicked at {}:{}, {}",
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![feature(linkage)]
|
#![feature(linkage)]
|
||||||
#![feature(panic_info_message)]
|
|
||||||
#![feature(alloc_error_handler)]
|
#![feature(alloc_error_handler)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
@ -13,6 +12,7 @@ extern crate alloc;
|
||||||
extern crate bitflags;
|
extern crate bitflags;
|
||||||
|
|
||||||
use buddy_system_allocator::LockedHeap;
|
use buddy_system_allocator::LockedHeap;
|
||||||
|
use core::ptr::addr_of_mut;
|
||||||
use syscall::*;
|
use syscall::*;
|
||||||
|
|
||||||
const USER_HEAP_SIZE: usize = 32768;
|
const USER_HEAP_SIZE: usize = 32768;
|
||||||
|
@ -27,18 +27,18 @@ pub fn handle_alloc_error(layout: core::alloc::Layout) -> ! {
|
||||||
panic!("Heap allocation error, layout = {:?}", layout);
|
panic!("Heap allocation error, layout = {:?}", layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[unsafe(no_mangle)]
|
||||||
#[link_section = ".text.entry"]
|
#[unsafe(link_section = ".text.entry")]
|
||||||
pub extern "C" fn _start() -> ! {
|
pub extern "C" fn _start() -> ! {
|
||||||
unsafe {
|
unsafe {
|
||||||
HEAP.lock()
|
HEAP.lock()
|
||||||
.init(HEAP_SPACE.as_ptr() as usize, USER_HEAP_SIZE);
|
.init(addr_of_mut!(HEAP_SPACE) as usize, USER_HEAP_SIZE);
|
||||||
}
|
}
|
||||||
exit(main());
|
exit(main());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[linkage = "weak"]
|
#[linkage = "weak"]
|
||||||
#[no_mangle]
|
#[unsafe(no_mangle)]
|
||||||
fn main() -> i32 {
|
fn main() -> i32 {
|
||||||
panic!("Cannot find main!");
|
panic!("Cannot find main!");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue