Compare commits
3 Commits
fadecc7c95
...
f966a1239e
| Author | SHA1 | Date | |
|---|---|---|---|
| f966a1239e | |||
| 15ecefb5fb | |||
| 897775f63a |
8
.gdbinit
8
.gdbinit
@@ -1,6 +1,6 @@
|
|||||||
file target/riscv64/debug/kernel-rust
|
# file target/riscv64/debug/kernel-rust
|
||||||
target remote localhost:1234
|
target remote localhost:1234
|
||||||
break machine_mode_entry
|
# break machine_mode_entry
|
||||||
# break *0x800bf000
|
break *0x800cfdd8
|
||||||
# add-symbol-file target/riscv64/debug/test_pic 0x800bf000
|
add-symbol-file target/riscv64/debug/test_pic 0x800cfdd8
|
||||||
c
|
c
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
resolver = "3"
|
resolver = "3"
|
||||||
members = ["user/*"]
|
members = ["user/*"]
|
||||||
exclude = ["library"]
|
exclude = ["library", "build-tools"]
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "kernel-rust"
|
name = "kernel-rust"
|
||||||
|
|||||||
2
build-tools/.cargo/config.toml
Normal file
2
build-tools/.cargo/config.toml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[build]
|
||||||
|
target = "x86_64-unknown-linux-gnu"
|
||||||
14
build-tools/Cargo.toml
Normal file
14
build-tools/Cargo.toml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
[package]
|
||||||
|
name = "build-tools"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "gen-symbols"
|
||||||
|
path = "src/gen_symbols.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
rayon = "1.11"
|
||||||
|
object = "0.32"
|
||||||
|
addr2line = "0.21"
|
||||||
|
rustc-demangle = "0.1"
|
||||||
128
build-tools/src/gen_symbols.rs
Normal file
128
build-tools/src/gen_symbols.rs
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
use addr2line::Context;
|
||||||
|
use object::{Object, ObjectSymbol, SymbolKind};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{BufWriter, Write};
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
#[repr(C, packed(4))]
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct RawSymbol {
|
||||||
|
addr: u64,
|
||||||
|
line: u32,
|
||||||
|
name_off: u32,
|
||||||
|
file_off: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let elf_path = "../target/riscv64/debug/kernel-rust";
|
||||||
|
let bin_data = std::fs::read(elf_path)?;
|
||||||
|
let obj_file = object::File::parse(&*bin_data)?;
|
||||||
|
|
||||||
|
let context = Context::new(&obj_file)?;
|
||||||
|
|
||||||
|
let mut symbols_list = Vec::new();
|
||||||
|
let mut string_table = Vec::new();
|
||||||
|
let mut str_cache = HashMap::new();
|
||||||
|
|
||||||
|
// Helper pour gérer la table des chaînes (String Table)
|
||||||
|
let mut add_string = |s: &str| -> u32 {
|
||||||
|
*str_cache.entry(s.to_string()).or_insert_with(|| {
|
||||||
|
let off = string_table.len() as u32;
|
||||||
|
string_table.extend_from_slice(s.as_bytes());
|
||||||
|
string_table.push(0); // Null terminator
|
||||||
|
off
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("Extraction des symboles depuis {}...", elf_path);
|
||||||
|
|
||||||
|
obj_file.symbols().enumerate().for_each(|(i, sym)| {
|
||||||
|
// On ne garde que les fonctions (Text)
|
||||||
|
if sym.kind() == SymbolKind::Text && sym.size() > 0 {
|
||||||
|
let addr = sym.address();
|
||||||
|
let raw_name = sym.name().unwrap_or("unknown");
|
||||||
|
let name = format!("{:#}", rustc_demangle::demangle(raw_name));
|
||||||
|
|
||||||
|
let mut frames = context.find_frames(addr).skip_all_loads().unwrap();
|
||||||
|
|
||||||
|
let (file, line) = if let Ok(Some(frame)) = frames.next() {
|
||||||
|
let f = frame
|
||||||
|
.location
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|l| {
|
||||||
|
l.file.and_then(|file| {
|
||||||
|
Path::new(file)
|
||||||
|
.strip_prefix(std::env::current_dir().unwrap().parent().unwrap())
|
||||||
|
.map_or(Some(file), |p| p.to_str())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.unwrap_or("unknown");
|
||||||
|
let l = frame.location.as_ref().and_then(|l| l.line).unwrap_or(0);
|
||||||
|
(f, l)
|
||||||
|
} else {
|
||||||
|
("unknown", 0)
|
||||||
|
};
|
||||||
|
|
||||||
|
symbols_list.push(RawSymbol {
|
||||||
|
addr,
|
||||||
|
line,
|
||||||
|
name_off: add_string(&name),
|
||||||
|
file_off: add_string(file),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Tri par adresse pour la recherche binaire au runtime
|
||||||
|
symbols_list.sort_by_key(|s| s.addr);
|
||||||
|
|
||||||
|
let idx = match symbols_list.binary_search_by_key(&(0x000000008004073c), |s| s.addr) {
|
||||||
|
Ok(i) => i,
|
||||||
|
Err(i) if i > 0 => i - 1,
|
||||||
|
_ => panic!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("{:?}", unsafe {
|
||||||
|
get_str(
|
||||||
|
string_table
|
||||||
|
.as_ptr()
|
||||||
|
.add(symbols_list[idx].name_off as usize),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
// Écriture du fichier symbols.bin
|
||||||
|
let mut f = BufWriter::new(File::create("../target/symbols.bin")?);
|
||||||
|
|
||||||
|
// Header : [u64: count] [u64: string_table_offset]
|
||||||
|
let header_size = 16;
|
||||||
|
let sym_table_size = symbols_list.len() * std::mem::size_of::<RawSymbol>();
|
||||||
|
f.write_all(&(symbols_list.len() as u64).to_le_bytes())?;
|
||||||
|
f.write_all(&((header_size + sym_table_size) as u64).to_le_bytes())?;
|
||||||
|
|
||||||
|
// Table des symboles
|
||||||
|
for sym in &symbols_list {
|
||||||
|
unsafe {
|
||||||
|
let bytes = std::slice::from_raw_parts(
|
||||||
|
(sym as *const RawSymbol) as *const u8,
|
||||||
|
std::mem::size_of::<RawSymbol>(),
|
||||||
|
);
|
||||||
|
f.write_all(bytes)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Table des noms
|
||||||
|
f.write_all(&string_table)?;
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"Terminé ! {} symboles écrits dans symbols.bin",
|
||||||
|
symbols_list.len()
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
unsafe fn get_str(ptr: *const u8) -> &'static str {
|
||||||
|
let mut len = 0;
|
||||||
|
while *ptr.add(len) != 0 {
|
||||||
|
len += 1;
|
||||||
|
}
|
||||||
|
core::str::from_utf8_unchecked(core::slice::from_raw_parts(ptr, len))
|
||||||
|
}
|
||||||
@@ -1,10 +1,5 @@
|
|||||||
use core::{alloc::Layout, time::Duration};
|
use core::{alloc::Layout, time::Duration};
|
||||||
|
|
||||||
use bffs::path::Path;
|
|
||||||
use io::SeekFrom;
|
|
||||||
|
|
||||||
use crate::fs::File;
|
|
||||||
|
|
||||||
#[repr(u64)]
|
#[repr(u64)]
|
||||||
pub enum SysCall {
|
pub enum SysCall {
|
||||||
Read = 0,
|
Read = 0,
|
||||||
@@ -100,10 +95,12 @@ macro_rules! syscall {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exit() {
|
pub fn exit() -> ! {
|
||||||
unsafe {
|
unsafe {
|
||||||
syscall!(SysCall::Exit);
|
syscall!(SysCall::Exit);
|
||||||
}
|
}
|
||||||
|
#[allow(clippy::empty_loop)]
|
||||||
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sleep(duration: Duration) {
|
pub fn sleep(duration: Duration) {
|
||||||
@@ -128,6 +125,8 @@ pub fn write_int_temp(content: u64) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unknown_lints)]
|
||||||
|
#[allow(fuzzy_provenance_casts)]
|
||||||
pub fn alloc(layout: Layout) -> *mut u8 {
|
pub fn alloc(layout: Layout) -> *mut u8 {
|
||||||
unsafe {
|
unsafe {
|
||||||
let size = layout.size();
|
let size = layout.size();
|
||||||
@@ -143,13 +142,12 @@ pub fn dealloc(ptr: *mut u8, layout: core::alloc::Layout) {
|
|||||||
syscall!(SysCall::Dealloc, ptr as u64, size as u64, align as u64);
|
syscall!(SysCall::Dealloc, ptr as u64, size as u64, align as u64);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn open<P: AsRef<Path>>(path: P) -> File {
|
pub fn open(path: &str) -> u64 {
|
||||||
unsafe {
|
unsafe {
|
||||||
let path_str = path.as_ref().as_str();
|
let ptr = path.as_ptr();
|
||||||
let ptr = path_str.as_ptr();
|
let size = path.len();
|
||||||
let size = path_str.len();
|
|
||||||
let (fd, ..) = syscall!(SysCall::Open, ptr as u64, size as u64);
|
let (fd, ..) = syscall!(SysCall::Open, ptr as u64, size as u64);
|
||||||
File::from_raw_fd(fd)
|
fd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn close(file_descriptor: u64) {
|
pub fn close(file_descriptor: u64) {
|
||||||
@@ -173,29 +171,23 @@ pub fn read(file_descriptor: u64, buf: &mut [u8]) -> u64 {
|
|||||||
len
|
len
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn seek(file_descriptor: u64, seek: SeekFrom) {
|
/// seek_type: 0 -> start, 1 -> end, 2 -> current
|
||||||
|
pub fn seek(file_descriptor: u64, seek_type: u8, seek: u64) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let (discriminant, value) = match seek {
|
syscall!(SysCall::Seek, file_descriptor, seek_type as u64, seek);
|
||||||
SeekFrom::Start(v) => (0, v),
|
|
||||||
SeekFrom::End(v) => (1, v as u64),
|
|
||||||
SeekFrom::Current(v) => (2, v as u64),
|
|
||||||
};
|
|
||||||
syscall!(SysCall::Seek, file_descriptor, discriminant, value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn spawn<P: AsRef<Path>>(path: P) {
|
pub fn spawn(path: &str) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let path_str = path.as_ref().as_str();
|
let ptr = path.as_ptr();
|
||||||
let ptr = path_str.as_ptr();
|
let size = path.len();
|
||||||
let size = path_str.len();
|
|
||||||
syscall!(SysCall::Spawn, ptr as u64, size as u64);
|
syscall!(SysCall::Spawn, ptr as u64, size as u64);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn execve<P: AsRef<Path>>(path: P) {
|
pub fn execve(path: &str) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let path_str = path.as_ref().as_str();
|
let ptr = path.as_ptr();
|
||||||
let ptr = path_str.as_ptr();
|
let size = path.len();
|
||||||
let size = path_str.len();
|
|
||||||
syscall!(SysCall::ExecVE, ptr as u64, size as u64);
|
syscall!(SysCall::ExecVE, ptr as u64, size as u64);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
4
ilm.ld
4
ilm.ld
@@ -16,11 +16,11 @@ SECTIONS {
|
|||||||
*(.text .text.*)
|
*(.text .text.*)
|
||||||
} > RAM
|
} > RAM
|
||||||
|
|
||||||
.rodata : {
|
.rodata : ALIGN(8) {
|
||||||
*(.rodata .rodata.*)
|
*(.rodata .rodata.*)
|
||||||
} > RAM
|
} > RAM
|
||||||
|
|
||||||
.data : {
|
.data : ALIGN(8) {
|
||||||
*(.data .data.*)
|
*(.data .data.*)
|
||||||
} > RAM
|
} > RAM
|
||||||
|
|
||||||
|
|||||||
61
justfile
61
justfile
@@ -2,62 +2,75 @@ release := ""
|
|||||||
qemu_flags := ""
|
qemu_flags := ""
|
||||||
cargo_flags := "" + if release != "" { "--release" } else { "" }
|
cargo_flags := "" + if release != "" { "--release" } else { "" }
|
||||||
bin_path := if release != "" { "target/riscv64/release" } else { "target/riscv64/debug" }
|
bin_path := if release != "" { "target/riscv64/release" } else { "target/riscv64/debug" }
|
||||||
|
GDB := "gf2"
|
||||||
|
|
||||||
default: run
|
default: run
|
||||||
|
|
||||||
mount_filesystem:
|
mount_filesystem:
|
||||||
@# Add some permissions to be able to do next operations without sudo
|
@# Add some permissions to be able to do next operations without sudo
|
||||||
mountpoint -q mnt || sudo mount -o umask=0022,gid=$(id -g $USER),uid=$(id -u $USER) disk.img mnt
|
mountpoint -q mnt || sudo mount -o umask=0022,gid=$(id -g),uid=$(id -u) disk.img mnt
|
||||||
|
|
||||||
sync_filesystem:
|
|
||||||
sync
|
|
||||||
|
|
||||||
update-std:
|
update-std:
|
||||||
@cd library/std && just update-std
|
@cd library/std && {{ just_executable() }} update-std
|
||||||
|
|
||||||
build-sysroot:
|
build-sysroot:
|
||||||
@cd library/std && just build-sysroot
|
@cd library/std && {{ just_executable() }} build-sysroot
|
||||||
|
|
||||||
build_user_prog prog:
|
build_user_prog prog:
|
||||||
RUSTFLAGS="-C relocation-model=pic -C link-arg=-pie --sysroot {{ justfile_directory() / "sysroot" }}" cargo b {{ cargo_flags }} --package {{ prog }}
|
RUSTFLAGS="-Clink-arg=-Tuser.ld -C relocation-model=pic -C link-arg=-pie --sysroot {{ justfile_directory() / "sysroot" }}" \
|
||||||
riscv64-elf-strip {{ bin_path / prog }}
|
cargo b {{ cargo_flags }} --package {{ prog }}
|
||||||
cp {{ bin_path / prog }} {{ "mnt/usr/bin" / prog }}
|
cp {{ bin_path / prog }} {{ bin_path / prog + "-stripped" }}
|
||||||
|
if command -v riscv64-elf-strip >/dev/null 2>&1; then \
|
||||||
|
riscv64-elf-strip {{ bin_path / prog + "-stripped" }}; \
|
||||||
|
fi
|
||||||
|
cp {{ bin_path / prog + "-stripped" }} {{ "mnt/usr/bin" / prog }}
|
||||||
|
|
||||||
build: mount_filesystem (map_dir "user" f"just release=\"{{release}}\" cargo_flags=\"{{cargo_flags}}\" build_user_prog")
|
make-symbols:
|
||||||
RUSTFLAGS="-Clink-arg=-Tilm.ld --sysroot {{ justfile_directory() / "sysroot" }}" cargo b {{ cargo_flags }}
|
cd build-tools && cargo r --bin gen-symbols --release
|
||||||
just sync_filesystem
|
|
||||||
|
build: mount_filesystem
|
||||||
|
@for file in `ls user`; do \
|
||||||
|
{{ just_executable() }} release="{{ release }}" cargo_flags="{{ cargo_flags }}" build_user_prog $file ; \
|
||||||
|
done
|
||||||
|
RUSTFLAGS="-Cforce-frame-pointers=yes -Clink-arg=-Tilm.ld --sysroot {{ justfile_directory() / "sysroot" }}" cargo b {{ cargo_flags }}
|
||||||
|
{{ just_executable() }} make-symbols
|
||||||
|
sync
|
||||||
|
|
||||||
run: build (runner f"{{bin_path / "kernel-rust"}}")
|
run: build (runner f"{{bin_path / "kernel-rust"}}")
|
||||||
|
|
||||||
map_dir dir recipe:
|
QEMU := f"qemu-system-riscv64 \
|
||||||
@for file in `ls {{ dir }}`; do \
|
|
||||||
{{ recipe }} $file ; \
|
|
||||||
done
|
|
||||||
|
|
||||||
qemu := f"qemu-system-riscv64 \
|
|
||||||
-machine virt \
|
-machine virt \
|
||||||
-serial mon:stdio \
|
-serial mon:stdio \
|
||||||
-device bochs-display \
|
-device bochs-display \
|
||||||
-device virtio-keyboard-pci \
|
-device virtio-keyboard-pci \
|
||||||
-device virtio-mouse-pci \
|
-device virtio-mouse-pci \
|
||||||
-device loader,file=disk.img,addr=0xA0000000 \
|
-device loader,file=disk.img,addr=0xA0000000 \
|
||||||
|
-device loader,file=target/symbols.bin,addr=0xB0000000 \
|
||||||
-bios none -m 1024M {{qemu_flags}}"
|
-bios none -m 1024M {{qemu_flags}}"
|
||||||
|
|
||||||
# -trace \"virtio*\"
|
# -trace \"virtio*\"
|
||||||
# -d guest_errors,unimp,int"
|
# -d guest_errors,unimp,int"
|
||||||
|
|
||||||
perf: build
|
perf: build
|
||||||
{{ qemu }} -perfmap -kernel {{ bin_path / "kernel-rust" }}&
|
{{ QEMU }} -perfmap -kernel {{ bin_path / "kernel-rust" }}&
|
||||||
perf record --output=/tmp/perf.data --call-graph=dwarf -F 999 -p $(pidof qemu-system-riscv64) -- sleep 20; exit 0
|
perf record --output=/tmp/perf.data --call-graph=dwarf -F 999 -p $(pidof qemu-system-riscv64) -- sleep 20; exit 0
|
||||||
cd /tmp && hotspot perf.data
|
cd /tmp && hotspot perf.data
|
||||||
|
|
||||||
gdb: build
|
dbg: build
|
||||||
{{ qemu }} -s -S -kernel {{ bin_path / "kernel-rust" }}&
|
{{ QEMU }} -s -S -kernel {{ bin_path / "kernel-rust" }}&
|
||||||
gf2
|
{{ GDB }}
|
||||||
|
|
||||||
|
dbg-user prog addr: build
|
||||||
|
{{ QEMU }} -s -S -kernel {{ bin_path / "kernel-rust" }}&
|
||||||
|
{{ GDB }} -nx \
|
||||||
|
-ex "target remote localhost:1234" \
|
||||||
|
-ex "break *{{ addr }}" \
|
||||||
|
-ex "add-symbol-file target/riscv64/debug/{{ prog }} {{ addr }}" \
|
||||||
|
-ex "c"
|
||||||
|
|
||||||
runner args:
|
runner args:
|
||||||
{{ qemu }} -kernel {{ args }}
|
{{ QEMU }} -kernel {{ args }}
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
cd library && just clean
|
cd library && {{ just_executable() }} clean
|
||||||
cargo clean
|
cargo clean
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ STD_FILES := "\
|
|||||||
sys/thread_local/no_threads.rs sys/thread_local/os.rs sys/time/mod.rs \
|
sys/thread_local/no_threads.rs sys/thread_local/os.rs sys/time/mod.rs \
|
||||||
sys/time/unsupported.rs sys/backtrace.rs sys/cmath.rs \
|
sys/time/unsupported.rs sys/backtrace.rs sys/cmath.rs \
|
||||||
sys/configure_builtins.rs sys/env_consts.rs sys/exit.rs sys/mod.rs thread"
|
sys/configure_builtins.rs sys/env_consts.rs sys/exit.rs sys/mod.rs thread"
|
||||||
KEEP_FILES := "sys sys/pal sys/pal/survos.rs sys/alloc sys/alloc/survos.rs"
|
KEEP_FILES := "survos.rs"
|
||||||
|
|
||||||
setup-std:
|
setup-std:
|
||||||
@echo "🔗 Linking root directories..."
|
@echo "🔗 Linking root directories..."
|
||||||
@@ -74,6 +74,7 @@ patch-std:
|
|||||||
done
|
done
|
||||||
|
|
||||||
build-sysroot:
|
build-sysroot:
|
||||||
|
cargo clean
|
||||||
RUSTFLAGS="-Zforce-unstable-if-unmarked -C relocation-model=pic -C link-arg=-pie" \
|
RUSTFLAGS="-Zforce-unstable-if-unmarked -C relocation-model=pic -C link-arg=-pie" \
|
||||||
cargo build --package std --target ../riscv64.json --features compiler-builtins-mem
|
cargo build --package std --target ../riscv64.json --features compiler-builtins-mem
|
||||||
mkdir -p ../sysroot/lib/rustlib/riscv64/lib
|
mkdir -p ../sysroot/lib/rustlib/riscv64/lib
|
||||||
@@ -83,11 +84,10 @@ build-sysroot:
|
|||||||
clean:
|
clean:
|
||||||
cargo clean
|
cargo clean
|
||||||
rm -rf ../sysroot/lib/rustlib/riscv64/lib/*
|
rm -rf ../sysroot/lib/rustlib/riscv64/lib/*
|
||||||
@for item in $(find library/std/src); do \
|
@for item in $(find std/src -type f); do \
|
||||||
basename_item=$(basename "$item"); \
|
basename_item=$(basename "$item"); \
|
||||||
keep=0; \
|
keep=0; \
|
||||||
for protected in {{ KEEP_FILES }}; do \
|
for protected in {{ KEEP_FILES }}; do \
|
||||||
echo $basename_item = $protected; \
|
|
||||||
if [ "$basename_item" = "$protected" ]; then keep=1; break; fi; \
|
if [ "$basename_item" = "$protected" ]; then keep=1; break; fi; \
|
||||||
done; \
|
done; \
|
||||||
if [ "$keep" -eq 0 ]; then \
|
if [ "$keep" -eq 0 ]; then \
|
||||||
|
|||||||
1
library/std/.gitignore
vendored
1
library/std/.gitignore
vendored
@@ -91,7 +91,6 @@ src/sys/mod.rs
|
|||||||
src/sys/time
|
src/sys/time
|
||||||
src/sys/time/mod.rs
|
src/sys/time/mod.rs
|
||||||
src/sys/time/unsupported.rs
|
src/sys/time/unsupported.rs
|
||||||
src/sys/stdio
|
|
||||||
src/sys/stdio/mod.rs
|
src/sys/stdio/mod.rs
|
||||||
src/sys/stdio/unsupported.rs
|
src/sys/stdio/unsupported.rs
|
||||||
src/sys/cmath.rs
|
src/sys/cmath.rs
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
62a \ target_os = "survos" => { \
|
62a \ target_os = "survos" => { \
|
||||||
mod unsupported; \
|
|
||||||
pub use self::unsupported::*; \
|
|
||||||
mod survos; \
|
mod survos; \
|
||||||
pub use self::survos::*; \
|
pub use self::survos::*; \
|
||||||
}
|
}
|
||||||
|
|||||||
4
library/std/patches/sys/stdio/mod.sed
Normal file
4
library/std/patches/sys/stdio/mod.sed
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
47a \ target_os = "survos" => { \
|
||||||
|
mod survos; \
|
||||||
|
pub use self::survos::*; \
|
||||||
|
}
|
||||||
@@ -1,3 +1,10 @@
|
|||||||
|
#[path = "unsupported/mod.rs"]
|
||||||
|
mod unsupported;
|
||||||
|
pub use self::unsupported::*;
|
||||||
|
|
||||||
|
#[path = "../../../../../crates/shared/src/syscall.rs"]
|
||||||
|
mod syscall;
|
||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
/// `argc` and `argv` are passed by the kernel
|
/// `argc` and `argv` are passed by the kernel
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
@@ -9,3 +16,8 @@ pub unsafe extern "C" fn _start(argc: isize, argv: *const *const u8) -> isize {
|
|||||||
|
|
||||||
unsafe { main(argc, argv) }
|
unsafe { main(argc, argv) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn abort_internal() -> ! {
|
||||||
|
// todo real abort
|
||||||
|
syscall::exit()
|
||||||
|
}
|
||||||
|
|||||||
152
library/std/src/sys/stdio/survos.rs
Normal file
152
library/std/src/sys/stdio/survos.rs
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
use crate::io;
|
||||||
|
|
||||||
|
#[path = "unsupported.rs"]
|
||||||
|
mod unsupported;
|
||||||
|
pub use self::unsupported::{STDIN_BUF_SIZE, Stderr, is_ebadf};
|
||||||
|
|
||||||
|
pub struct Stdout;
|
||||||
|
pub struct Stdin;
|
||||||
|
|
||||||
|
impl Stdout {
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
Self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Stdin {
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
Self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl io::Write for Stdout {
|
||||||
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
|
Ok(write(1, buf) as usize)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) -> io::Result<()> {
|
||||||
|
// todo!()
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl io::Read for Stdin {
|
||||||
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
|
Ok(read(0, buf) as usize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn panic_output() -> Option<impl io::Write> {
|
||||||
|
// Todo, use Stderr
|
||||||
|
Some(Stdout::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(u64)]
|
||||||
|
pub enum SysCall {
|
||||||
|
Read = 0,
|
||||||
|
Write = 1,
|
||||||
|
Open = 2,
|
||||||
|
Close = 3,
|
||||||
|
Seek = 8,
|
||||||
|
Alloc = 40,
|
||||||
|
Dealloc = 41,
|
||||||
|
Spawn = 58,
|
||||||
|
ExecVE = 59,
|
||||||
|
Exit = 60,
|
||||||
|
NanoSleep = 101,
|
||||||
|
WriteIntTemp = 998,
|
||||||
|
WriteTemp = 999,
|
||||||
|
Unimplemented = 1 << 31,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u64> for SysCall {
|
||||||
|
fn from(value: u64) -> Self {
|
||||||
|
match value {
|
||||||
|
0 => SysCall::Read,
|
||||||
|
1 => SysCall::Write,
|
||||||
|
2 => SysCall::Open,
|
||||||
|
3 => SysCall::Close,
|
||||||
|
8 => SysCall::Seek,
|
||||||
|
40 => SysCall::Alloc,
|
||||||
|
41 => SysCall::Dealloc,
|
||||||
|
58 => SysCall::Spawn,
|
||||||
|
59 => SysCall::ExecVE,
|
||||||
|
60 => SysCall::Exit,
|
||||||
|
101 => SysCall::NanoSleep,
|
||||||
|
998 => SysCall::WriteIntTemp,
|
||||||
|
999 => SysCall::WriteTemp,
|
||||||
|
_ => SysCall::Unimplemented,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
unsafe fn _syscall(
|
||||||
|
syscall: SysCall,
|
||||||
|
mut a1: u64,
|
||||||
|
mut a2: u64,
|
||||||
|
mut a3: u64,
|
||||||
|
mut a4: u64,
|
||||||
|
mut a5: u64,
|
||||||
|
mut a6: u64,
|
||||||
|
mut a7: u64,
|
||||||
|
) -> (u64, u64, u64, u64, u64, u64, u64, u64) {
|
||||||
|
let mut a0 = syscall as u64;
|
||||||
|
unsafe {
|
||||||
|
core::arch::asm!(
|
||||||
|
"ecall",
|
||||||
|
inlateout("a0") a0,
|
||||||
|
inlateout("a1") a1,
|
||||||
|
inlateout("a2") a2,
|
||||||
|
inlateout("a3") a3,
|
||||||
|
inlateout("a4") a4,
|
||||||
|
inlateout("a5") a5,
|
||||||
|
inlateout("a6") a6,
|
||||||
|
inlateout("a7") a7,
|
||||||
|
clobber_abi("system")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
(a0, a1, a2, a3, a4, a5, a6, a7)
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! syscall {
|
||||||
|
($syscall:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr, $a6:expr, $a7:expr) => {
|
||||||
|
_syscall($syscall, $a1, $a2, $a3, $a4, $a5, $a6, $a7)
|
||||||
|
};
|
||||||
|
($syscall:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr, $a6:expr) => {
|
||||||
|
syscall!($syscall, $a1, $a2, $a3, $a4, $a5, $a6, 0)
|
||||||
|
};
|
||||||
|
($syscall:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr) => {
|
||||||
|
syscall!($syscall, $a1, $a2, $a3, $a4, $a5, 0)
|
||||||
|
};
|
||||||
|
($syscall:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr) => {
|
||||||
|
syscall!($syscall, $a1, $a2, $a3, $a4, 0)
|
||||||
|
};
|
||||||
|
($syscall:expr, $a1:expr, $a2:expr, $a3:expr) => {
|
||||||
|
syscall!($syscall, $a1, $a2, $a3, 0)
|
||||||
|
};
|
||||||
|
($syscall:expr, $a1:expr, $a2:expr) => {
|
||||||
|
syscall!($syscall, $a1, $a2, 0)
|
||||||
|
};
|
||||||
|
($syscall:expr, $a1:expr) => {
|
||||||
|
syscall!($syscall, $a1, 0)
|
||||||
|
};
|
||||||
|
($syscall:expr) => {
|
||||||
|
syscall!($syscall, 0)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
pub fn write(file_descriptor: u64, buf: &[u8]) -> u64 {
|
||||||
|
unsafe {
|
||||||
|
let ptr = buf.as_ptr();
|
||||||
|
let size = buf.len();
|
||||||
|
let (len, ..) = syscall!(SysCall::Write, file_descriptor, ptr as u64, size as u64);
|
||||||
|
len
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn read(file_descriptor: u64, buf: &mut [u8]) -> u64 {
|
||||||
|
unsafe {
|
||||||
|
let ptr = buf.as_ptr();
|
||||||
|
let size = buf.len();
|
||||||
|
let (len, ..) = syscall!(SysCall::Read, file_descriptor, ptr as u64, size as u64);
|
||||||
|
len
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,6 +18,14 @@ pub extern "C" fn _start() {
|
|||||||
naked_asm!(
|
naked_asm!(
|
||||||
"
|
"
|
||||||
la sp, _heap_end
|
la sp, _heap_end
|
||||||
|
|
||||||
|
// Set BSS to zero
|
||||||
|
la t0, __bss_start
|
||||||
|
la t1, __bss_end
|
||||||
|
1: sd zero, 0(t0)
|
||||||
|
addi t0, t0, 8
|
||||||
|
bleu t0, t1, 1b
|
||||||
|
|
||||||
jal machine_mode_entry
|
jal machine_mode_entry
|
||||||
1:
|
1:
|
||||||
j 1b"
|
j 1b"
|
||||||
|
|||||||
@@ -9,18 +9,7 @@ use log::info;
|
|||||||
use shared::syscall::SysCall;
|
use shared::syscall::SysCall;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
boot::sbi::{ExtensionID, TimerFunctionID},
|
boot::sbi::{ExtensionID, TimerFunctionID}, clear_csr, drivers::{keyboard::KBD_DRIVER, mouse::MOUSE_DRIVER}, println, process::{ExecutionContext, exit_process, sleep}, read_csr, riscv::{disable_interrupt, dump_cpu}, scheduler::SCHEDULER, set_csr, syscall, time::{IRQ_M_EXTERNAL, IRQ_M_TIMER, setup_next_timer_interrupt}, virtio::input::HANDLING_INTERRUPT, virtual_fs::{FILE_SYSTEM, VirtualFileSystem}, write_csr
|
||||||
clear_csr,
|
|
||||||
drivers::{keyboard::KBD_DRIVER, mouse::MOUSE_DRIVER},
|
|
||||||
process::{ExecutionContext, exit_process, sleep},
|
|
||||||
read_csr,
|
|
||||||
riscv::{disable_interrupt, dump_cpu},
|
|
||||||
scheduler::SCHEDULER,
|
|
||||||
set_csr, syscall,
|
|
||||||
time::{IRQ_M_EXTERNAL, IRQ_M_TIMER, setup_next_timer_interrupt},
|
|
||||||
virtio::input::HANDLING_INTERRUPT,
|
|
||||||
virtual_fs::{FILE_SYSTEM, VirtualFileSystem},
|
|
||||||
write_csr,
|
|
||||||
};
|
};
|
||||||
use core::{alloc::Layout, arch::naked_asm, time::Duration};
|
use core::{alloc::Layout, arch::naked_asm, time::Duration};
|
||||||
|
|
||||||
@@ -185,6 +174,7 @@ unsafe extern "C" fn supervisor_trap_handler(
|
|||||||
let buf =
|
let buf =
|
||||||
unsafe { core::slice::from_raw_parts_mut(a2 as *mut u8, a3 as usize) };
|
unsafe { core::slice::from_raw_parts_mut(a2 as *mut u8, a3 as usize) };
|
||||||
|
|
||||||
|
|
||||||
let mut scheduler = SCHEDULER.lock();
|
let mut scheduler = SCHEDULER.lock();
|
||||||
let current_process = scheduler.get_current_process();
|
let current_process = scheduler.get_current_process();
|
||||||
let vnode = current_process.fd_table[fd as usize].as_mut().unwrap();
|
let vnode = current_process.fd_table[fd as usize].as_mut().unwrap();
|
||||||
|
|||||||
34
src/io.rs
34
src/io.rs
@@ -2,8 +2,12 @@
|
|||||||
//!
|
//!
|
||||||
//! Provides a lightweight logger implementation routing to UART and helper
|
//! Provides a lightweight logger implementation routing to UART and helper
|
||||||
//! macros for printing from kernel code.
|
//! macros for printing from kernel code.
|
||||||
use crate::println;
|
|
||||||
|
|
||||||
|
use crate::print;
|
||||||
|
use crate::tty::{TTY_INITIALIZED, TTY0};
|
||||||
|
|
||||||
|
use alloc::format;
|
||||||
|
use io::Write;
|
||||||
use log::{Level, Metadata, Record};
|
use log::{Level, Metadata, Record};
|
||||||
use log::{LevelFilter, SetLoggerError};
|
use log::{LevelFilter, SetLoggerError};
|
||||||
|
|
||||||
@@ -14,11 +18,15 @@ use crate::uart::write_uart;
|
|||||||
/// Accepts any type that implements `AsRef<str>` to avoid unnecessary
|
/// Accepts any type that implements `AsRef<str>` to avoid unnecessary
|
||||||
/// allocations at call sites.
|
/// allocations at call sites.
|
||||||
pub(crate) fn print<T: AsRef<str>>(content: T) {
|
pub(crate) fn print<T: AsRef<str>>(content: T) {
|
||||||
write_uart(content);
|
if TTY_INITIALIZED.load(core::sync::atomic::Ordering::Relaxed) {
|
||||||
|
unsafe { TTY0.new_node().write(content.as_ref().as_bytes()).unwrap() };
|
||||||
|
} else {
|
||||||
|
write_uart(&content);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Logger implementation that routes kernel log records to the UART-based console.
|
/// Logger implementation that routes kernel log records to the UART-based console.
|
||||||
struct Logger;
|
pub struct Logger;
|
||||||
|
|
||||||
impl log::Log for Logger {
|
impl log::Log for Logger {
|
||||||
fn enabled(&self, metadata: &Metadata) -> bool {
|
fn enabled(&self, metadata: &Metadata) -> bool {
|
||||||
@@ -27,24 +35,25 @@ impl log::Log for Logger {
|
|||||||
|
|
||||||
fn log(&self, record: &Record) {
|
fn log(&self, record: &Record) {
|
||||||
if self.enabled(record.metadata()) {
|
if self.enabled(record.metadata()) {
|
||||||
if let Some((file, line)) = record.file().zip(record.line()) {
|
let to_print = if let Some((file, line)) = record.file().zip(record.line()) {
|
||||||
println!(
|
format!(
|
||||||
"[{}] at {}:{} - {}",
|
"[{}] at {}:{} - {}\n",
|
||||||
record.level(),
|
record.level(),
|
||||||
file,
|
file,
|
||||||
line,
|
line,
|
||||||
record.args()
|
record.args()
|
||||||
);
|
)
|
||||||
} else {
|
} else {
|
||||||
println!("[{}] - {}", record.level(), record.args());
|
format!("[{}] - {}\n", record.level(), record.args())
|
||||||
}
|
};
|
||||||
|
print!("{to_print}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flush(&self) {}
|
fn flush(&self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
static LOGGER: Logger = Logger;
|
pub static LOGGER: Logger = Logger;
|
||||||
|
|
||||||
/// Initialize the kernel logger and set the default level.
|
/// Initialize the kernel logger and set the default level.
|
||||||
///
|
///
|
||||||
@@ -62,10 +71,9 @@ macro_rules! print {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! println {
|
macro_rules! println {
|
||||||
() => {
|
() => {
|
||||||
$crate::print!("\n\r")
|
$crate::print!("\n")
|
||||||
};
|
};
|
||||||
($($args:expr),*) => {{
|
($($args:expr),*) => {{
|
||||||
$crate::print!($($args),*);
|
$crate::print!("{}\n", alloc::format!($($args),*));
|
||||||
$crate::println!();
|
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,8 +104,8 @@ pub const fn map_keycode(code: u16, state: &KeyboardState) -> KeyType {
|
|||||||
// KEY_8 => KeyType::Ascii('−'),
|
// KEY_8 => KeyType::Ascii('−'),
|
||||||
KEY_9 => KeyType::Ascii('÷'),
|
KEY_9 => KeyType::Ascii('÷'),
|
||||||
KEY_0 => KeyType::Ascii('×'),
|
KEY_0 => KeyType::Ascii('×'),
|
||||||
// KEY_MINUS => KeyType::Ascii('≠'),
|
KEY_MINUS => KeyType::Ascii('≠'),
|
||||||
// KEY_EQUAL => KeyType::Ascii('‰'),
|
KEY_EQUAL => KeyType::Ascii('‰'),
|
||||||
KEY_Q => KeyType::Ascii('|'),
|
KEY_Q => KeyType::Ascii('|'),
|
||||||
// KEY_W => KeyType::Ascii(''),
|
// KEY_W => KeyType::Ascii(''),
|
||||||
KEY_E => KeyType::Ascii('&'),
|
KEY_E => KeyType::Ascii('&'),
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ mod virtio;
|
|||||||
mod virtual_console;
|
mod virtual_console;
|
||||||
mod virtual_fs;
|
mod virtual_fs;
|
||||||
|
|
||||||
pub const HEAP_SIZE: usize = 1024 * 1024 * 32; // 32Mo RAM
|
pub const HEAP_SIZE: usize = 1024 * 1024 * 128; // 128Mo RAM
|
||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
static HEAP: Heap = Heap::empty();
|
static HEAP: Heap = Heap::empty();
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,10 @@
|
|||||||
//! framebuffer before halting the CPU.
|
//! framebuffer before halting the CPU.
|
||||||
use core::arch::riscv64::wfi;
|
use core::arch::riscv64::wfi;
|
||||||
|
|
||||||
use alloc::{format, string::ToString};
|
use alloc::{
|
||||||
|
format,
|
||||||
|
string::{String, ToString},
|
||||||
|
};
|
||||||
use log::error;
|
use log::error;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -14,6 +17,27 @@ use crate::{
|
|||||||
vga::Vga,
|
vga::Vga,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fn print_stack_trace() {
|
||||||
|
let mut fp: usize;
|
||||||
|
unsafe {
|
||||||
|
core::arch::asm!("mv {}, s0", out(reg) fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
error!("STACK TRACE:");
|
||||||
|
for i in 0..10 {
|
||||||
|
if fp == 0 || !fp.is_multiple_of(8) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
// On RISC-V with FP :
|
||||||
|
// fp - 8 => Return Address (ra)
|
||||||
|
// fp - 16 => Previous Frame Pointer
|
||||||
|
let ra = *((fp - 8) as *const usize);
|
||||||
|
error!(" [{}] 0x{:016x} {}", i, ra, resolve_symbol(ra));
|
||||||
|
fp = *((fp - 16) as *const usize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
/// Kernel panic handler that displays the panic message on the framebuffer and halts.
|
/// Kernel panic handler that displays the panic message on the framebuffer and halts.
|
||||||
fn panic(panic_info: &core::panic::PanicInfo) -> ! {
|
fn panic(panic_info: &core::panic::PanicInfo) -> ! {
|
||||||
@@ -26,6 +50,7 @@ fn panic(panic_info: &core::panic::PanicInfo) -> ! {
|
|||||||
panic_message = format!("{panic_message} at {}:{}", location.file(), location.line());
|
panic_message = format!("{panic_message} at {}:{}", location.file(), location.line());
|
||||||
}
|
}
|
||||||
error!("{panic_message}");
|
error!("{panic_message}");
|
||||||
|
print_stack_trace();
|
||||||
|
|
||||||
Vga.clear_screen(Color::WHITE);
|
Vga.clear_screen(Color::WHITE);
|
||||||
unsafe { Vga.draw_string(0, 0, "PANIC !", Color::BLACK, Color::WHITE) };
|
unsafe { Vga.draw_string(0, 0, "PANIC !", Color::BLACK, Color::WHITE) };
|
||||||
@@ -44,3 +69,47 @@ fn panic(panic_info: &core::panic::PanicInfo) -> ! {
|
|||||||
unsafe { wfi() }
|
unsafe { wfi() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C, packed(4))]
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct RawSymbol {
|
||||||
|
addr: u64,
|
||||||
|
line: u32,
|
||||||
|
name_off: u32,
|
||||||
|
file_off: u32,
|
||||||
|
}
|
||||||
|
pub fn resolve_symbol(pc: usize) -> String {
|
||||||
|
let start = 0xB000_0000 as *const u8;
|
||||||
|
|
||||||
|
let count = unsafe { *(start as *const u64) };
|
||||||
|
let str_table_off = unsafe { *((start as *const u64).add(1)) };
|
||||||
|
let symbol_ptr = unsafe { start.add(16) as *const RawSymbol };
|
||||||
|
let str_table_ptr = unsafe { start.add(str_table_off as usize) };
|
||||||
|
|
||||||
|
let symbols = unsafe { core::slice::from_raw_parts(symbol_ptr, count as usize) };
|
||||||
|
|
||||||
|
let idx = match symbols.binary_search_by_key(&(pc as u64), |s| s.addr) {
|
||||||
|
Ok(i) => i,
|
||||||
|
Err(i) if i > 0 => i - 1,
|
||||||
|
_ => return Default::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let sym = &symbols[idx];
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let name = get_str(str_table_ptr.add(sym.name_off as usize));
|
||||||
|
let file = get_str(str_table_ptr.add(sym.file_off as usize));
|
||||||
|
|
||||||
|
format!("at {} ({}:{})", name, file, sym.line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn get_str(ptr: *const u8) -> &'static str {
|
||||||
|
unsafe {
|
||||||
|
let mut len = 0;
|
||||||
|
while *ptr.add(len) != 0 {
|
||||||
|
len += 1;
|
||||||
|
}
|
||||||
|
core::str::from_utf8_unchecked(core::slice::from_raw_parts(ptr, len))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Size of the stack allocated to each process (in 64-bit words).
|
/// Size of the stack allocated to each process (in 64-bit words).
|
||||||
const STACK_SIZE: usize = 4096;
|
const STACK_SIZE: usize = 1024 * 1024 * 2;
|
||||||
|
|
||||||
/// Represents the state of a process in the system.
|
/// Represents the state of a process in the system.
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
@@ -207,6 +207,12 @@ impl Scheduler {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for ph in gelf.program_headers.iter() {
|
||||||
|
if ph.p_type == goblin::elf::program_header::PT_LOAD {
|
||||||
|
let dst = unsafe { base.add((ph.p_vaddr - min_vaddr) as usize) };
|
||||||
|
let copy_len = ph.p_filesz as usize;
|
||||||
if ph.p_memsz as usize > copy_len {
|
if ph.p_memsz as usize > copy_len {
|
||||||
unsafe {
|
unsafe {
|
||||||
core::slice::from_raw_parts_mut(
|
core::slice::from_raw_parts_mut(
|
||||||
|
|||||||
21
src/tty.rs
21
src/tty.rs
@@ -1,4 +1,7 @@
|
|||||||
use core::cell::{LazyCell, RefCell};
|
use core::{
|
||||||
|
cell::{LazyCell, RefCell},
|
||||||
|
sync::atomic::AtomicBool,
|
||||||
|
};
|
||||||
|
|
||||||
use alloc::{boxed::Box, rc::Rc};
|
use alloc::{boxed::Box, rc::Rc};
|
||||||
use io::{IoBase, Read, Seek, Write};
|
use io::{IoBase, Read, Seek, Write};
|
||||||
@@ -10,7 +13,12 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub const TTY_BUFFER_SIZE: usize = 4096; // 4Ko
|
pub const TTY_BUFFER_SIZE: usize = 4096; // 4Ko
|
||||||
pub static mut TTY0: LazyCell<Tty> = LazyCell::new(Tty::new);
|
pub static mut TTY0: LazyCell<Tty> = LazyCell::new(|| {
|
||||||
|
let tty = Tty::new();
|
||||||
|
TTY_INITIALIZED.store(true, core::sync::atomic::Ordering::Relaxed);
|
||||||
|
tty
|
||||||
|
});
|
||||||
|
pub static TTY_INITIALIZED: AtomicBool = AtomicBool::new(false);
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Tty {
|
pub struct Tty {
|
||||||
@@ -25,10 +33,13 @@ impl Tty {
|
|||||||
console: RefCell::new(VirtualConsole::new()).into(),
|
console: RefCell::new(VirtualConsole::new()).into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn new_node(&'_ self) -> TtyNode<'_> {
|
||||||
|
TtyNode { tty: self }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct TtyNode<'a> {
|
pub struct TtyNode<'a> {
|
||||||
tty: &'a Tty,
|
tty: &'a Tty,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,7 +51,7 @@ impl VirtualFileSystem for Tty {
|
|||||||
if !path.is_empty() {
|
if !path.is_empty() {
|
||||||
Err(())
|
Err(())
|
||||||
} else {
|
} else {
|
||||||
Ok(Box::new(TtyNode { tty: self }))
|
Ok(Box::new(self.new_node()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -68,10 +79,12 @@ impl Seek for TtyNode<'_> {
|
|||||||
|
|
||||||
impl Write for TtyNode<'_> {
|
impl Write for TtyNode<'_> {
|
||||||
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
|
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
|
||||||
|
critical_section::with(|_| {
|
||||||
self.tty
|
self.tty
|
||||||
.console
|
.console
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.write_str(str::from_utf8(buf).unwrap());
|
.write_str(str::from_utf8(buf).unwrap());
|
||||||
|
});
|
||||||
Ok(buf.len())
|
Ok(buf.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
19
src/vga.rs
19
src/vga.rs
@@ -4,7 +4,7 @@
|
|||||||
//! draw text using an embedded font plate.
|
//! draw text using an embedded font plate.
|
||||||
use log::info;
|
use log::info;
|
||||||
|
|
||||||
use crate::draw::{Color, Draw};
|
use crate::draw::{Color, Draw, FONT_HEIGHT};
|
||||||
|
|
||||||
const PCI_ECAM_BASE_ADDRESS: *mut u32 = 0x30000000 as *mut _;
|
const PCI_ECAM_BASE_ADDRESS: *mut u32 = 0x30000000 as *mut _;
|
||||||
const BOCHS_DISPLAY_BASE_ADDRESS: *mut u32 = 0x50000000 as *mut _;
|
const BOCHS_DISPLAY_BASE_ADDRESS: *mut u32 = 0x50000000 as *mut _;
|
||||||
@@ -58,6 +58,23 @@ impl Vga {
|
|||||||
pub unsafe fn write_u8_unsafe(offset: usize, value: u8) {
|
pub unsafe fn write_u8_unsafe(offset: usize, value: u8) {
|
||||||
unsafe { *(VGA_ADDRESS.byte_add(offset) as *mut u8) = value }
|
unsafe { *(VGA_ADDRESS.byte_add(offset) as *mut u8) = value }
|
||||||
}
|
}
|
||||||
|
pub unsafe fn read_u8_unsafe(offset: usize) -> u8 {
|
||||||
|
unsafe { *(VGA_ADDRESS.byte_add(offset) as *mut u8) }
|
||||||
|
}
|
||||||
|
pub fn line_up(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
core::ptr::copy(
|
||||||
|
VGA_ADDRESS.add(self.get_width() * FONT_HEIGHT),
|
||||||
|
VGA_ADDRESS,
|
||||||
|
self.get_width() * (self.get_height() - FONT_HEIGHT),
|
||||||
|
);
|
||||||
|
for y in self.get_height() - FONT_HEIGHT..self.get_height() {
|
||||||
|
for x in 0..self.get_width() {
|
||||||
|
self.write_pixel_unsafe(x as u16, y as u16, Color::BLACK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Draw for Vga {
|
impl Draw for Vga {
|
||||||
|
|||||||
@@ -3,8 +3,9 @@ use io::SeekFrom;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
draw::{Color, Draw, FONT_HEIGHT, FONT_WIDTH},
|
draw::{Color, Draw, FONT_HEIGHT, FONT_WIDTH},
|
||||||
vga::{self, Vga},
|
uart::write_uart,
|
||||||
virtual_fs::{self, FILE_SYSTEM, VirtualFileSystem},
|
vga::Vga,
|
||||||
|
virtual_fs::{self, VGAFileSystem},
|
||||||
};
|
};
|
||||||
|
|
||||||
const TAB_SIZE: u64 = 4;
|
const TAB_SIZE: u64 = 4;
|
||||||
@@ -31,11 +32,12 @@ impl VirtualConsole {
|
|||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
VirtualConsole {
|
VirtualConsole {
|
||||||
cursor: Cursor::new(),
|
cursor: Cursor::new(),
|
||||||
framebuffer: unsafe { FILE_SYSTEM.open("/dev/fb0".as_ref()).unwrap() },
|
framebuffer: Box::new(VGAFileSystem.open_vga()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_str(&mut self, s: &str) {
|
pub fn write_str(&mut self, s: &str) {
|
||||||
|
write_uart(s);
|
||||||
s.chars().for_each(|c| self.write_char(c));
|
s.chars().for_each(|c| self.write_char(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,11 +83,11 @@ impl VirtualConsole {
|
|||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
if self.cursor.x as usize * FONT_WIDTH >= vga::WIDTH {
|
if self.cursor.x as usize * FONT_WIDTH >= self.get_width() {
|
||||||
self.cursor.x = 0;
|
self.cursor.x = 0;
|
||||||
self.cursor.y += 1;
|
self.cursor.y += 1;
|
||||||
}
|
}
|
||||||
if self.cursor.y as usize * FONT_HEIGHT >= vga::HEIGHT {
|
if (self.cursor.y + 1) as usize * FONT_HEIGHT >= self.get_height() {
|
||||||
self.line_up();
|
self.line_up();
|
||||||
if last_cursor.y > 0 {
|
if last_cursor.y > 0 {
|
||||||
last_cursor.y -= 1;
|
last_cursor.y -= 1;
|
||||||
@@ -96,7 +98,13 @@ impl VirtualConsole {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn line_up(&mut self) {}
|
fn line_up(&mut self) {
|
||||||
|
// TODO avoid calling Vga directly
|
||||||
|
Vga.line_up();
|
||||||
|
if self.cursor.y > 0 {
|
||||||
|
self.cursor.y -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
fn move_cursor_line(&mut self, _last: Cursor) {}
|
fn move_cursor_line(&mut self, _last: Cursor) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ impl VirtualFileSystem for MainFileSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub static mut FILE_SYSTEM: LazyCell<MainFileSystem> = LazyCell::new(|| MainFileSystem {
|
pub static mut FILE_SYSTEM: LazyCell<MainFileSystem> = LazyCell::new(|| MainFileSystem {
|
||||||
root: Box::new(Fat32FileSystem::new(Disk::new(1024 * 1024 * 16)).unwrap()),
|
root: Box::new(Fat32FileSystem::new(Disk::new(1024 * 1024 * 64)).unwrap()),
|
||||||
mounts: HashMap::new(),
|
mounts: HashMap::new(),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -75,10 +75,16 @@ pub unsafe fn init_file_system() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct VGAFileSystem;
|
pub struct VGAFileSystem;
|
||||||
|
|
||||||
|
impl VGAFileSystem {
|
||||||
|
pub fn open_vga(&self) -> VGAVirtualNode {
|
||||||
|
VGAVirtualNode { position: 0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct VGAVirtualNode {
|
pub struct VGAVirtualNode {
|
||||||
position: u64,
|
position: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,8 +109,11 @@ impl Seek for VGAVirtualNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Read for VGAVirtualNode {
|
impl Read for VGAVirtualNode {
|
||||||
fn read(&mut self, _buf: &mut [u8]) -> Result<usize, ()> {
|
fn read(&mut self, buf: &mut [u8]) -> Result<usize, ()> {
|
||||||
todo!()
|
buf.iter_mut().for_each(|val| {
|
||||||
|
*val = unsafe { Vga::read_u8_unsafe(self.position as usize) };
|
||||||
|
});
|
||||||
|
Ok(buf.len())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,7 +137,7 @@ impl VirtualFileSystem for VGAFileSystem {
|
|||||||
if !path.is_empty() {
|
if !path.is_empty() {
|
||||||
Err(())
|
Err(())
|
||||||
} else {
|
} else {
|
||||||
Ok(Box::new(VGAVirtualNode { position: 0 }))
|
Ok(Box::new(self.open_vga()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,12 +39,12 @@ impl Seek for NullNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Write for NullNode {
|
impl Write for NullNode {
|
||||||
fn write(&mut self, _buf: &[u8]) -> Result<usize, Self::Error> {
|
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
|
||||||
todo!()
|
Ok(buf.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flush(&mut self) -> Result<(), Self::Error> {
|
fn flush(&mut self) -> Result<(), Self::Error> {
|
||||||
todo!()
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
35
user.ld
Normal file
35
user.ld
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* ld directives the for barmetal RISCV
|
||||||
|
*/
|
||||||
|
OUTPUT_ARCH(riscv)
|
||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
MEMORY {
|
||||||
|
RAM (wxa) : ORIGIN = 0x0, LENGTH = 512M
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
. = 0x0;
|
||||||
|
.text : {
|
||||||
|
KEEP(*(.text._start))
|
||||||
|
|
||||||
|
*(.text .text.*)
|
||||||
|
} > RAM
|
||||||
|
|
||||||
|
.rodata : ALIGN(8) {
|
||||||
|
*(.rodata .rodata.*)
|
||||||
|
} > RAM
|
||||||
|
|
||||||
|
.data : ALIGN(8) {
|
||||||
|
*(.data .data.*)
|
||||||
|
} > RAM
|
||||||
|
|
||||||
|
.bss : ALIGN(8) {
|
||||||
|
__bss_start = .;
|
||||||
|
*(.bss .bss.*)
|
||||||
|
__bss_end = .;
|
||||||
|
} > RAM
|
||||||
|
|
||||||
|
_heap_start = ALIGN(8);
|
||||||
|
_heap_end = ORIGIN(RAM) + LENGTH(RAM);
|
||||||
|
}
|
||||||
@@ -4,6 +4,5 @@ version = "0.1.0"
|
|||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# std = { path = "../../crates/std" }
|
|
||||||
# shared = { path = "../../crates/shared", features = ["user"] }
|
# shared = { path = "../../crates/shared", features = ["user"] }
|
||||||
# core = { path = "../../crates/std/crates/core" }
|
# core = { path = "../../crates/std/crates/core" }
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
// use std::io::_print;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let a = std::env::args();
|
let a = std::env::args();
|
||||||
for a in a {
|
for a in a {
|
||||||
|
|||||||
@@ -1,24 +1,23 @@
|
|||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
|
|
||||||
use io::{Read, Write};
|
use core::sync::atomic::AtomicUsize;
|
||||||
use std::io::{Stdin, stdin};
|
use shared::{fs::File, syscall};
|
||||||
use shared::syscall;
|
use std::io::{Read, Stdin, Write, stdin, stdout};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut input = String::new();
|
|
||||||
input.push('a');
|
|
||||||
// let mut file = syscall::open("/dev/fb0");
|
|
||||||
// syscall::seek(&mut file, SeekFrom::End(-3));
|
|
||||||
// syscall::write(&mut file, &[255; 6400 * 50]);
|
|
||||||
// syscall::sleep(Duration::from_secs_f64(2.0));
|
|
||||||
syscall::close(0);
|
syscall::close(0);
|
||||||
let mut tty = syscall::open("/dev/tty0");
|
let mut tty = unsafe { File::from_raw_fd(syscall::open("/dev/tty0")) };
|
||||||
tty.write(input.as_bytes()).unwrap();
|
syscall::close(1);
|
||||||
|
let _ = syscall::open("/dev/tty0");
|
||||||
|
println!("test from test_pic");
|
||||||
syscall::spawn("/usr/bin/shell");
|
syscall::spawn("/usr/bin/shell");
|
||||||
|
// panic!("explicit panic");
|
||||||
|
// std::process::abort();
|
||||||
|
// unsafe {core::arch::asm!("unimp")};
|
||||||
loop {
|
loop {
|
||||||
let mut test = [0; 2];
|
let mut test = [0; 4];
|
||||||
let len = tty.read(&mut test).unwrap();
|
let len = stdin().read(&mut test).unwrap();
|
||||||
tty.write(str::from_utf8(&test[..len as usize]).unwrap().as_bytes())
|
print!("{}", str::from_utf8(&test[..len as usize]).unwrap());
|
||||||
.unwrap();
|
stdout().flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user