Better user programs with a special std. Sleep and exit are calling scheduler instead of wfi.
This commit is contained in:
@@ -6,4 +6,7 @@ build-std = ["core", "compiler_builtins", "alloc"]
|
|||||||
build-std-features = ["compiler-builtins-mem"]
|
build-std-features = ["compiler-builtins-mem"]
|
||||||
|
|
||||||
[target.riscv64]
|
[target.riscv64]
|
||||||
|
rustflags = [
|
||||||
|
"-C", "link-arg=-Tilm.ld",
|
||||||
|
]
|
||||||
runner = "qemu-system-riscv64 -machine virt -device bochs-display -bios none -m 512M -device loader,file=/home/julien/ensimag/TPs/kernel/disk.img,addr=0x90000000 -kernel"
|
runner = "qemu-system-riscv64 -machine virt -device bochs-display -bios none -m 512M -device loader,file=/home/julien/ensimag/TPs/kernel/disk.img,addr=0x90000000 -kernel"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
resolver = "3"
|
resolver = "3"
|
||||||
members = ["user/*"]
|
members = ["crates/os-std", "crates/shared", "user/*"]
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "kernel-rust"
|
name = "kernel-rust"
|
||||||
@@ -13,3 +13,4 @@ kernel-macros = { path = "crates/kernel-macros" }
|
|||||||
log = "0.4"
|
log = "0.4"
|
||||||
critical-section = { version = "1", features = ["restore-state-bool"] }
|
critical-section = { version = "1", features = ["restore-state-bool"] }
|
||||||
bffs = { path = "../../../code/bffs", features = ["alloc"] }
|
bffs = { path = "../../../code/bffs", features = ["alloc"] }
|
||||||
|
shared = { path = "crates/shared" }
|
||||||
|
|||||||
12
crates/os-std-macros/Cargo.toml
Normal file
12
crates/os-std-macros/Cargo.toml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
[package]
|
||||||
|
name = "os-std-macros"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
proc-macro = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
proc-macro2 = "1"
|
||||||
|
quote = "1"
|
||||||
|
syn = { version = "2", features = ["full"] }
|
||||||
1
crates/os-std-macros/src/lib.rs
Normal file
1
crates/os-std-macros/src/lib.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
8
crates/os-std/Cargo.toml
Normal file
8
crates/os-std/Cargo.toml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[package]
|
||||||
|
name = "os-std"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
os-std-macros = { path = "../os-std-macros" }
|
||||||
|
shared = { path = "../shared" }
|
||||||
21
crates/os-std/src/lib.rs
Normal file
21
crates/os-std/src/lib.rs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#![no_std]
|
||||||
|
|
||||||
|
mod prelude;
|
||||||
|
|
||||||
|
pub use shared::syscall;
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! custom_std_setup {
|
||||||
|
() => {
|
||||||
|
#[panic_handler]
|
||||||
|
fn panic(_panic_info: &core::panic::PanicInfo) -> ! {
|
||||||
|
// TODO print
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub extern "C" fn _start() {
|
||||||
|
main()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
1
crates/os-std/src/prelude.rs
Normal file
1
crates/os-std/src/prelude.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
6
crates/shared/Cargo.toml
Normal file
6
crates/shared/Cargo.toml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[package]
|
||||||
|
name = "shared"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
3
crates/shared/src/lib.rs
Normal file
3
crates/shared/src/lib.rs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
#![no_std]
|
||||||
|
|
||||||
|
pub mod syscall;
|
||||||
@@ -2,6 +2,7 @@ use core::time::Duration;
|
|||||||
|
|
||||||
#[repr(u64)]
|
#[repr(u64)]
|
||||||
pub enum SysCall {
|
pub enum SysCall {
|
||||||
|
Exit = 60,
|
||||||
NanoSleep = 101,
|
NanoSleep = 101,
|
||||||
WriteIntTemp = 998,
|
WriteIntTemp = 998,
|
||||||
WriteTemp = 999,
|
WriteTemp = 999,
|
||||||
@@ -11,6 +12,7 @@ pub enum SysCall {
|
|||||||
impl From<u64> for SysCall {
|
impl From<u64> for SysCall {
|
||||||
fn from(value: u64) -> Self {
|
fn from(value: u64) -> Self {
|
||||||
match value {
|
match value {
|
||||||
|
60 => SysCall::Exit,
|
||||||
101 => SysCall::NanoSleep,
|
101 => SysCall::NanoSleep,
|
||||||
998 => SysCall::WriteIntTemp,
|
998 => SysCall::WriteIntTemp,
|
||||||
999 => SysCall::WriteTemp,
|
999 => SysCall::WriteTemp,
|
||||||
@@ -75,6 +77,12 @@ macro_rules! syscall {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn exit() {
|
||||||
|
unsafe {
|
||||||
|
syscall!(SysCall::Exit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn sleep(duration: Duration) {
|
pub fn sleep(duration: Duration) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let (duration_secs, duration_nanos) = (duration.as_secs(), duration.subsec_nanos() as u64);
|
let (duration_secs, duration_nanos) = (duration.as_secs(), duration.subsec_nanos() as u64);
|
||||||
5
ilm.ld
5
ilm.ld
@@ -2,17 +2,16 @@
|
|||||||
* ld directives the for barmetal RISCV
|
* ld directives the for barmetal RISCV
|
||||||
*/
|
*/
|
||||||
OUTPUT_ARCH(riscv)
|
OUTPUT_ARCH(riscv)
|
||||||
ENTRY(entry)
|
ENTRY(_start)
|
||||||
|
|
||||||
MEMORY {
|
MEMORY {
|
||||||
RAM (wxa) : ORIGIN = 0x80000000, LENGTH = 128M
|
RAM (wxa) : ORIGIN = 0x80000000, LENGTH = 128M
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTIONS {
|
SECTIONS {
|
||||||
/* The kernel starts at 0x80000000 */
|
|
||||||
. = 0x80000000;
|
. = 0x80000000;
|
||||||
.text : {
|
.text : {
|
||||||
KEEP(*(.text.entry))
|
KEEP(*(.text._start))
|
||||||
|
|
||||||
*(.text .text.*)
|
*(.text .text.*)
|
||||||
} > RAM
|
} > RAM
|
||||||
|
|||||||
19
justfile
19
justfile
@@ -3,16 +3,23 @@ cargo_flags := if release != "" { "--release" } else { "" }
|
|||||||
|
|
||||||
default: run
|
default: run
|
||||||
|
|
||||||
build_user_prog prog:
|
mount_filesystem:
|
||||||
cd {{ "user" / prog }} && \
|
# Add some permissions to be able to do next operations without sudo
|
||||||
RUSTFLAGS="-C relocation-model=pic" cargo b {{ cargo_flags }}
|
@mountpoint -q mnt || sudo mount -o umask=0022,gid=$(id -g $USER),uid=$(id -u $USER) disk.img mnt
|
||||||
riscv64-elf-objcopy -O binary {{ "target/riscv64/debug" / prog }} {{ "user" / prog / prog + ".mem" }}
|
|
||||||
|
|
||||||
build: (map_dir "user" "build_user_prog")
|
sync_filesystem:
|
||||||
|
sync
|
||||||
|
|
||||||
|
build_user_prog prog:
|
||||||
|
RUSTFLAGS="-C relocation-model=pic -C link-arg=-Tilm.ld" cargo b {{ cargo_flags }} --package {{ prog }}
|
||||||
|
riscv64-elf-objcopy -O binary {{ "target/riscv64/debug" / prog }} {{ "mnt/usr/bin" / prog }}
|
||||||
|
|
||||||
|
build: mount_filesystem (map_dir "user" "build_user_prog")
|
||||||
cargo b {{ cargo_flags }}
|
cargo b {{ cargo_flags }}
|
||||||
|
just sync_filesystem
|
||||||
|
|
||||||
run: build
|
run: build
|
||||||
cargo r {{ cargo_flags }} --bin kernel-rust
|
cargo r {{ cargo_flags }}
|
||||||
|
|
||||||
map_dir dir recipe:
|
map_dir dir recipe:
|
||||||
@for file in `ls {{ dir }}`; do \
|
@for file in `ls {{ dir }}`; do \
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ pub mod sbi;
|
|||||||
|
|
||||||
#[unsafe(naked)]
|
#[unsafe(naked)]
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
pub extern "C" fn entry() {
|
pub extern "C" fn _start() {
|
||||||
naked_asm!(
|
naked_asm!(
|
||||||
"
|
"
|
||||||
la sp, _heap_end
|
la sp, _heap_end
|
||||||
|
|||||||
28
src/fs.rs
28
src/fs.rs
@@ -1,7 +1,33 @@
|
|||||||
use bffs::io::{IoBase, Read, Seek};
|
use core::{cell::UnsafeCell, ops::Deref};
|
||||||
|
|
||||||
|
use bffs::{
|
||||||
|
io::{IoBase, Read, Seek},
|
||||||
|
Fat32FileSystem,
|
||||||
|
};
|
||||||
|
|
||||||
const DISK_ADDR: *const u8 = 0x9000_0000 as *const _;
|
const DISK_ADDR: *const u8 = 0x9000_0000 as *const _;
|
||||||
|
|
||||||
|
pub struct FSTemp(UnsafeCell<Option<Fat32FileSystem<Disk>>>);
|
||||||
|
unsafe impl Sync for FSTemp {}
|
||||||
|
|
||||||
|
impl FSTemp {
|
||||||
|
pub unsafe fn init(&self) {
|
||||||
|
unsafe {
|
||||||
|
*self.0.get() = Some(Fat32FileSystem::new(Disk::new(1024 * 1024 * 16)).unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for FSTemp {
|
||||||
|
type Target = Fat32FileSystem<Disk>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
unsafe { (&*self.0.get()).as_ref().unwrap_unchecked() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub static FILE_SYSTEM: FSTemp = FSTemp(UnsafeCell::new(None));
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Disk {
|
pub struct Disk {
|
||||||
pos: u64,
|
pos: u64,
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
use alloc::str;
|
use alloc::str;
|
||||||
use log::info;
|
use log::info;
|
||||||
|
use shared::syscall::SysCall;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
boot::sbi::{EextensionID, TimerFunctionID},
|
boot::sbi::{EextensionID, TimerFunctionID},
|
||||||
clear_csr, generate_trap_handler,
|
clear_csr,
|
||||||
process::{sleep, ExecutionContext},
|
process::{exit_process, sleep, ExecutionContext},
|
||||||
read_csr,
|
read_csr,
|
||||||
riscv::disable_interrupt,
|
riscv::disable_interrupt,
|
||||||
scheduler::scheduler,
|
scheduler::scheduler_without_ret,
|
||||||
set_csr,
|
set_csr,
|
||||||
syscall::SysCall,
|
|
||||||
time::{setup_next_timer_interrupt, IRQ_M_TIMER},
|
time::{setup_next_timer_interrupt, IRQ_M_TIMER},
|
||||||
write_csr,
|
write_csr,
|
||||||
};
|
};
|
||||||
@@ -87,7 +87,7 @@ unsafe extern "C" fn machine_trap_handler(
|
|||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
unsafe extern "C" fn supervisor_trap_handler(
|
unsafe extern "C" fn supervisor_trap_handler(
|
||||||
interrupt_state: *mut ExecutionContext,
|
mut interrupt_state: *mut ExecutionContext,
|
||||||
scause: u64,
|
scause: u64,
|
||||||
_sie: u64,
|
_sie: u64,
|
||||||
_sip: u64,
|
_sip: u64,
|
||||||
@@ -96,13 +96,19 @@ unsafe extern "C" fn supervisor_trap_handler(
|
|||||||
#[allow(clippy::single_match)]
|
#[allow(clippy::single_match)]
|
||||||
match scause & !(1 << 63) {
|
match scause & !(1 << 63) {
|
||||||
8 => {
|
8 => {
|
||||||
|
// Advance sepc to exit the ecall
|
||||||
|
unsafe {
|
||||||
|
(*interrupt_state).mepc = (*interrupt_state).mepc.byte_add(4);
|
||||||
|
}
|
||||||
|
|
||||||
// Environment call from S-mode
|
// Environment call from S-mode
|
||||||
let syscall_u64: u64 = unsafe { (*interrupt_state).a[0] };
|
let syscall_u64: u64 = unsafe { (*interrupt_state).a[0] };
|
||||||
let a1: u64 = unsafe { (*interrupt_state).a[1] };
|
let a1: u64 = unsafe { (*interrupt_state).a[1] };
|
||||||
let a2: u64 = unsafe { (*interrupt_state).a[2] };
|
let a2: u64 = unsafe { (*interrupt_state).a[2] };
|
||||||
let syscall: SysCall = syscall_u64.into();
|
let syscall: SysCall = syscall_u64.into();
|
||||||
match syscall {
|
match syscall {
|
||||||
SysCall::NanoSleep => sleep(Duration::new(a1, a2 as u32)),
|
SysCall::Exit => exit_process(&mut interrupt_state),
|
||||||
|
SysCall::NanoSleep => sleep(Duration::new(a1, a2 as u32), &mut interrupt_state),
|
||||||
SysCall::WriteTemp => {
|
SysCall::WriteTemp => {
|
||||||
info!("Print from user space : {}", unsafe {
|
info!("Print from user space : {}", unsafe {
|
||||||
str::from_raw_parts(a1 as *const u8, a2 as usize)
|
str::from_raw_parts(a1 as *const u8, a2 as usize)
|
||||||
@@ -115,11 +121,6 @@ unsafe extern "C" fn supervisor_trap_handler(
|
|||||||
unimplemented!("Syscall {syscall_u64} is not implemented")
|
unimplemented!("Syscall {syscall_u64} is not implemented")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Advance sepc to exit the ecall
|
|
||||||
unsafe {
|
|
||||||
(*interrupt_state).mepc = (*interrupt_state).mepc.byte_add(4);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@@ -137,7 +138,7 @@ unsafe extern "C" fn supervisor_trap_handler(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
timer_interrupt();
|
timer_interrupt();
|
||||||
return scheduler(unsafe { *interrupt_state });
|
scheduler_without_ret(&mut interrupt_state);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@@ -207,24 +208,18 @@ unsafe extern "C" fn _machine_mode_trap() {
|
|||||||
mret"
|
mret"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
generate_trap_handler! {
|
|
||||||
_supervisor_mode_trap, supervisor_trap_handler, s
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! generate_trap_handler {
|
|
||||||
($name:ident, $jump_to:ident, $mode:ident) => {
|
|
||||||
#[unsafe(naked)]
|
#[unsafe(naked)]
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
unsafe extern "C" fn $name() {
|
unsafe extern "C" fn _supervisor_mode_trap() {
|
||||||
naked_asm!(concat!(
|
naked_asm!(concat!(
|
||||||
"
|
"
|
||||||
mv t0, sp
|
// Store sp before it gets modified
|
||||||
|
sd sp, 8-264(sp)
|
||||||
addi sp, sp, -264
|
addi sp, sp, -264
|
||||||
|
|
||||||
# Store the current frame
|
# Store the current frame
|
||||||
sd ra, 0(sp)
|
sd ra, 0(sp)
|
||||||
sd t0, 8(sp) // sp
|
// sp
|
||||||
sd gp, 16(sp)
|
sd gp, 16(sp)
|
||||||
sd tp, 24(sp)
|
sd tp, 24(sp)
|
||||||
sd a0, 32(sp)
|
sd a0, 32(sp)
|
||||||
@@ -260,20 +255,21 @@ macro_rules! generate_trap_handler {
|
|||||||
sd t0, 256(sp)
|
sd t0, 256(sp)
|
||||||
|
|
||||||
mv a0, sp
|
mv a0, sp
|
||||||
csrr a1, ",
|
csrr a1, scause
|
||||||
stringify!($mode),
|
csrr a2, sie
|
||||||
"cause
|
csrr a3, sip
|
||||||
csrr a2, ",
|
jal supervisor_trap_handler
|
||||||
stringify!($mode),
|
|
||||||
"ie
|
|
||||||
csrr a3, ",
|
|
||||||
stringify!($mode),
|
|
||||||
"ip
|
|
||||||
jal ",
|
|
||||||
stringify!($jump_to),
|
|
||||||
"
|
|
||||||
|
|
||||||
# Restore registers
|
# Restore registers and sret
|
||||||
|
jal restore_context"
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(naked)]
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn restore_context(context: *const ExecutionContext) -> ! {
|
||||||
|
naked_asm!(concat!(
|
||||||
|
"
|
||||||
ld t0, 248(a0)
|
ld t0, 248(a0)
|
||||||
csrw sepc, t0
|
csrw sepc, t0
|
||||||
ld t0, 256(a0)
|
ld t0, 256(a0)
|
||||||
@@ -311,13 +307,9 @@ macro_rules! generate_trap_handler {
|
|||||||
|
|
||||||
ld a0, 32(a0)
|
ld a0, 32(a0)
|
||||||
|
|
||||||
",
|
sret"
|
||||||
stringify!($mode),
|
|
||||||
"ret"
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
struct MachineInterruptState {
|
struct MachineInterruptState {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use log::{LevelFilter, SetLoggerError};
|
|||||||
|
|
||||||
use crate::uart::write_uart;
|
use crate::uart::write_uart;
|
||||||
|
|
||||||
fn print(content: String) {
|
pub(crate) fn print(content: String) {
|
||||||
write_uart(content);
|
write_uart(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
23
src/main.rs
23
src/main.rs
@@ -10,18 +10,15 @@
|
|||||||
macro_metavar_expr_concat
|
macro_metavar_expr_concat
|
||||||
)]
|
)]
|
||||||
|
|
||||||
use alloc::{boxed::Box, vec::Vec};
|
|
||||||
use bffs::{io::Read, Fat32FileSystem};
|
|
||||||
use embedded_alloc::LlffHeap as Heap;
|
use embedded_alloc::LlffHeap as Heap;
|
||||||
use log::info;
|
use log::info;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
fs::Disk,
|
fs::FILE_SYSTEM,
|
||||||
io::init_log,
|
io::init_log,
|
||||||
process::create_process,
|
process::{create_process, create_process_from_file},
|
||||||
riscv::enable_supervisor_interrupt,
|
riscv::enable_supervisor_interrupt,
|
||||||
scheduler::{idle, scheduler_init},
|
scheduler::{idle, scheduler_init},
|
||||||
tests_fat::MemoryDisk,
|
|
||||||
user::{proc2, test},
|
user::{proc2, test},
|
||||||
vga::{Color, Vga},
|
vga::{Color, Vga},
|
||||||
};
|
};
|
||||||
@@ -36,14 +33,12 @@ mod panic_handler;
|
|||||||
mod process;
|
mod process;
|
||||||
mod riscv;
|
mod riscv;
|
||||||
mod scheduler;
|
mod scheduler;
|
||||||
mod syscall;
|
|
||||||
mod tests_fat;
|
|
||||||
mod time;
|
mod time;
|
||||||
mod uart;
|
mod uart;
|
||||||
mod user;
|
mod user;
|
||||||
mod vga;
|
mod vga;
|
||||||
|
|
||||||
pub const HEAP_SIZE: usize = 40960;
|
pub const HEAP_SIZE: usize = 1024 * 1024; // 1Mo RAM
|
||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
static HEAP: Heap = Heap::empty();
|
static HEAP: Heap = Heap::empty();
|
||||||
|
|
||||||
@@ -56,6 +51,7 @@ pub extern "C" fn supervisor_mode_entry() {
|
|||||||
embedded_alloc::init!(HEAP, HEAP_SIZE);
|
embedded_alloc::init!(HEAP, HEAP_SIZE);
|
||||||
init_log().unwrap();
|
init_log().unwrap();
|
||||||
Vga::init();
|
Vga::init();
|
||||||
|
FILE_SYSTEM.init();
|
||||||
scheduler_init();
|
scheduler_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,16 +61,7 @@ pub extern "C" fn supervisor_mode_entry() {
|
|||||||
create_process(&test, "proc1");
|
create_process(&test, "proc1");
|
||||||
create_process(&proc2, "proc2");
|
create_process(&proc2, "proc2");
|
||||||
|
|
||||||
let fs = Fat32FileSystem::new(Disk::new(1024 * 1024 * 16)).unwrap();
|
create_process_from_file("/usr/bin/test_pic");
|
||||||
let mut bin = fs.open_file("/usr/bin/test").unwrap();
|
|
||||||
let mut content: Vec<u8> = Vec::new();
|
|
||||||
bin.read_to_end(&mut content).unwrap();
|
|
||||||
let test = unsafe { core::mem::transmute::<*const u8, extern "C" fn()>(content.as_ptr()) };
|
|
||||||
|
|
||||||
let test = Box::leak(Box::new(move || {
|
|
||||||
test();
|
|
||||||
}));
|
|
||||||
create_process(test, "dyn_proc");
|
|
||||||
|
|
||||||
enable_supervisor_interrupt();
|
enable_supervisor_interrupt();
|
||||||
idle();
|
idle();
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
use core::{arch::riscv64::wfi, time::Duration};
|
use core::time::Duration;
|
||||||
|
|
||||||
use alloc::{format, string::String};
|
use alloc::{boxed::Box, format, string::String, vec::Vec};
|
||||||
|
use bffs::{io::Read, path::Path};
|
||||||
|
use shared::syscall::exit;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
scheduler::{ACTIVE_PID, PROCESS_COUNT, PROCESS_TABLE},
|
fs::FILE_SYSTEM,
|
||||||
|
scheduler::{scheduler_without_ret, ACTIVE_PID, PROCESS_COUNT, PROCESS_TABLE},
|
||||||
time::elapsed_time_since_startup,
|
time::elapsed_time_since_startup,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -54,6 +57,21 @@ impl core::fmt::Debug for Process {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_process_from_file<'a, T: Into<Path<'a>>>(path: T) -> i64 {
|
||||||
|
let path = path.into();
|
||||||
|
let name = path.as_str();
|
||||||
|
let mut bin = FILE_SYSTEM.open_file(path).unwrap();
|
||||||
|
let mut content: Vec<u8> = Vec::new();
|
||||||
|
bin.read_to_end(&mut content).unwrap();
|
||||||
|
let test =
|
||||||
|
unsafe { core::mem::transmute::<*const u8, extern "C" fn()>(Vec::leak(content).as_ptr()) };
|
||||||
|
|
||||||
|
let test = Box::leak(Box::new(move || {
|
||||||
|
test();
|
||||||
|
}));
|
||||||
|
create_process(test, name)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_process<T: Into<String>, F: Fn()>(code: &'static F, name: T) -> i64 {
|
pub fn create_process<T: Into<String>, F: Fn()>(code: &'static F, name: T) -> i64 {
|
||||||
let mut next_pid = 0;
|
let mut next_pid = 0;
|
||||||
while next_pid < PROCESS_COUNT && unsafe { PROCESS_TABLE[next_pid].state != ProcessState::Dead }
|
while next_pid < PROCESS_COUNT && unsafe { PROCESS_TABLE[next_pid].state != ProcessState::Dead }
|
||||||
@@ -82,27 +100,21 @@ pub fn create_process<T: Into<String>, F: Fn()>(code: &'static F, name: T) -> i6
|
|||||||
|
|
||||||
extern "C" fn process_launcher(code: *const &dyn Fn()) {
|
extern "C" fn process_launcher(code: *const &dyn Fn()) {
|
||||||
unsafe { (*code)() };
|
unsafe { (*code)() };
|
||||||
terminate_process();
|
// User code didn't exit before the end of its execution, so we call the exit syscall ourselves
|
||||||
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn terminate_process() {
|
pub fn exit_process(interrupt_context: &mut *mut ExecutionContext) {
|
||||||
unsafe {
|
unsafe {
|
||||||
PROCESS_TABLE[ACTIVE_PID].state = ProcessState::Dead;
|
PROCESS_TABLE[ACTIVE_PID].state = ProcessState::Dead;
|
||||||
}
|
}
|
||||||
loop {}
|
scheduler_without_ret(interrupt_context)
|
||||||
// unsafe {
|
|
||||||
// wfi();
|
|
||||||
// }
|
|
||||||
// scheduler();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sleep(duration: Duration) {
|
pub fn sleep(duration: Duration, interrupt_context: &mut *mut ExecutionContext) {
|
||||||
unsafe {
|
unsafe {
|
||||||
PROCESS_TABLE[ACTIVE_PID].wake_time = elapsed_time_since_startup() + duration;
|
PROCESS_TABLE[ACTIVE_PID].wake_time = elapsed_time_since_startup() + duration;
|
||||||
PROCESS_TABLE[ACTIVE_PID].state = ProcessState::Asleep;
|
PROCESS_TABLE[ACTIVE_PID].state = ProcessState::Asleep;
|
||||||
}
|
}
|
||||||
unsafe {
|
scheduler_without_ret(interrupt_context)
|
||||||
wfi();
|
|
||||||
}
|
|
||||||
// scheduler();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,11 +57,11 @@ pub fn scheduler_init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scheduler(interrupt_state: ExecutionContext) -> *const ExecutionContext {
|
pub fn scheduler_without_ret(interrupt_state: &mut *mut ExecutionContext) {
|
||||||
// info!("scheduler");
|
// info!("scheduler");
|
||||||
unsafe {
|
unsafe {
|
||||||
let prev_pid = ACTIVE_PID;
|
let prev_pid = ACTIVE_PID;
|
||||||
PROCESS_TABLE[prev_pid].ctx = interrupt_state;
|
PROCESS_TABLE[prev_pid].ctx = **interrupt_state;
|
||||||
|
|
||||||
if PROCESS_TABLE[prev_pid].state == ProcessState::Active {
|
if PROCESS_TABLE[prev_pid].state == ProcessState::Active {
|
||||||
PROCESS_TABLE[prev_pid].state = ProcessState::Activable;
|
PROCESS_TABLE[prev_pid].state = ProcessState::Activable;
|
||||||
@@ -80,6 +80,6 @@ pub fn scheduler(interrupt_state: ExecutionContext) -> *const ExecutionContext {
|
|||||||
}
|
}
|
||||||
PROCESS_TABLE[ACTIVE_PID].state = ProcessState::Active;
|
PROCESS_TABLE[ACTIVE_PID].state = ProcessState::Active;
|
||||||
|
|
||||||
&raw const PROCESS_TABLE[ACTIVE_PID].ctx
|
*interrupt_state = &raw mut PROCESS_TABLE[ACTIVE_PID].ctx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
use core::str;
|
|
||||||
use log::info;
|
|
||||||
|
|
||||||
const DISK_ADDR: usize = 0x9000_0000;
|
|
||||||
|
|
||||||
pub struct MemoryDisk {}
|
|
||||||
|
|
||||||
impl MemoryDisk {
|
|
||||||
pub fn test() {
|
|
||||||
let test = unsafe { str::from_raw_parts(DISK_ADDR as *const u8, 13) };
|
|
||||||
info!("{}", test);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
10
src/user.rs
10
src/user.rs
@@ -1,15 +1,9 @@
|
|||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
|
|
||||||
use alloc::vec::Vec;
|
use shared::syscall::{sleep, write_int_temp, write_string_temp};
|
||||||
use bffs::{io::Read, Fat32FileSystem};
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
fs::Disk,
|
|
||||||
syscall::{sleep, write_int_temp, write_string_temp},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[repr(align(32))]
|
#[repr(align(32))]
|
||||||
struct Alignement([u8; 157]);
|
struct Alignement([u8; include_bytes!("../user/test_pic/test_pic.mem").len()]);
|
||||||
|
|
||||||
static PROG: Alignement = Alignement(*include_bytes!("../user/test_pic/test_pic.mem"));
|
static PROG: Alignement = Alignement(*include_bytes!("../user/test_pic/test_pic.mem"));
|
||||||
|
|
||||||
|
|||||||
@@ -4,3 +4,4 @@ version = "0.1.0"
|
|||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
os-std = { path = "../../crates/os-std" }
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
fn main() {
|
|
||||||
println!("cargo::rustc-link-arg=-Tilm.ld");
|
|
||||||
}
|
|
||||||
@@ -1,21 +1,11 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
os_std::custom_std_setup! {}
|
||||||
|
|
||||||
#[panic_handler]
|
use os_std::syscall::write_string_temp;
|
||||||
fn panic(_panic_info: &core::panic::PanicInfo) -> ! {
|
|
||||||
loop {}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
fn main() {
|
||||||
pub extern "C" fn entry() {
|
write_string_temp(
|
||||||
let test = "Hello from PIC program loaded dynamically";
|
"Hello from PIC program loaded dynamically with custom std and a better justfile, and syscalls !",
|
||||||
unsafe {
|
|
||||||
core::arch::asm!(
|
|
||||||
"ecall",
|
|
||||||
in("a0") 999,
|
|
||||||
in("a1") test.as_ptr(),
|
|
||||||
in("a2") test.len(),
|
|
||||||
clobber_abi("system")
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user