diff --git a/Cargo.lock b/Cargo.lock index 2369d79..f3f7faa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -130,16 +130,6 @@ dependencies = [ [[package]] name = "gglib" version = "0.1.0" -dependencies = [ - "ggos_kernel", -] - -[[package]] -name = "ggos_app_sh" -version = "0.1.0" -dependencies = [ - "gglib", -] [[package]] name = "ggos_boot" @@ -174,6 +164,7 @@ dependencies = [ "embedded-graphics", "ggfs", "ggos_boot", + "ggos_elf", "lazy_static", "libm", "linked_list_allocator", @@ -185,6 +176,14 @@ dependencies = [ "volatile", "x86", "x86_64", + "xmas-elf", +] + +[[package]] +name = "ggos_sh" +version = "0.1.0" +dependencies = [ + "gglib", ] [[package]] diff --git a/Makefile b/Makefile index 3071092..8ceec9e 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,11 @@ BUILD_ARGS := QEMU_ARGS := -serial stdio MODE ?= release RUN_MODE ?= +CUR_PATH := $(shell pwd) +APP_PATH := $(CUR_PATH)/pkg/app +APPS := $(shell find $(APP_PATH) -maxdepth 1 -type d) +APPS := $(filter-out $(APP_PATH),$(patsubst $(APP_PATH)/%, %, $(APPS))) +APPS := $(filter-out config,$(APPS)) ifeq (${MODE}, release) BUILD_ARGS += --release @@ -15,7 +20,8 @@ endif .PHONY: build run debug clean launch \ target/x86_64-unknown-uefi/$(MODE)/ggos_boot.efi \ - target/x86_64-unknown-none/$(MODE)/ggos_kernel + target/x86_64-unknown-none/$(MODE)/ggos_kernel \ + target/x86_64-unknown-ggos/$(MODE) run: build launch @@ -37,9 +43,12 @@ debug: build clean: @cargo clean +list: + @for dir in $(APPS); do echo $$dir || exit; done + build: $(ESP) -$(ESP): $(ESP)/EFI/BOOT/BOOTX64.EFI $(ESP)/KERNEL.ELF $(ESP)/EFI/BOOT/boot.conf +$(ESP): $(ESP)/EFI/BOOT/BOOTX64.EFI $(ESP)/KERNEL.ELF $(ESP)/EFI/BOOT/boot.conf $(ESP)/APP $(ESP)/EFI/BOOT/BOOTX64.EFI: target/x86_64-unknown-uefi/$(MODE)/ggos_boot.efi @mkdir -p $(@D) @@ -50,8 +59,18 @@ $(ESP)/EFI/BOOT/boot.conf: pkg/kernel/config/boot.conf $(ESP)/KERNEL.ELF: target/x86_64-unknown-none/$(MODE)/ggos_kernel @mkdir -p $(@D) cp $< $@ +$(ESP)/APP: target/x86_64-unknown-ggos/$(MODE) + @for app in $(APPS); do \ + mkdir -p $(@D)/APP; \ + cp $"] diff --git a/pkg/app/sh/src/main.rs b/pkg/app/sh/src/main.rs index b024c72..d3e044a 100644 --- a/pkg/app/sh/src/main.rs +++ b/pkg/app/sh/src/main.rs @@ -1,5 +1,12 @@ -use lib; +#![no_std] +#![no_main] + +#[macro_use] +extern crate lib; fn main() { println!("Hello, world!"); + lib::sys_exit(0); } + +entry!(main); diff --git a/pkg/elf/Cargo.toml b/pkg/elf/Cargo.toml index b99da15..256db3a 100644 --- a/pkg/elf/Cargo.toml +++ b/pkg/elf/Cargo.toml @@ -8,4 +8,4 @@ authors = ["GZTime "] [dependencies] log = "0.4.16" x86_64 = "0.14.9" -xmas-elf = "0.8" +xmas-elf = "0.8" diff --git a/pkg/elf/src/lib.rs b/pkg/elf/src/lib.rs index f4647ee..7e6a22d 100644 --- a/pkg/elf/src/lib.rs +++ b/pkg/elf/src/lib.rs @@ -40,10 +40,10 @@ pub fn map_elf( page_table: &mut impl Mapper, frame_allocator: &mut impl FrameAllocator, ) -> Result<(), MapToError> { - debug!("Mapping ELF file..."); - let kernel_start = PhysAddr::new(elf.input.as_ptr() as u64); + debug!("Mapping ELF file...{:?}", elf.input.as_ptr()); + let start = PhysAddr::new(elf.input.as_ptr() as u64); for segment in elf.program_iter() { - map_segment(&segment, kernel_start, page_table, frame_allocator)?; + map_segment(&segment, start, page_table, frame_allocator)?; } Ok(()) } @@ -88,7 +88,7 @@ pub fn map_stack( fn map_segment( segment: &program::ProgramHeader, - kernel_start: PhysAddr, + start: PhysAddr, page_table: &mut impl Mapper, frame_allocator: &mut impl FrameAllocator, ) -> Result<(), MapToError> { @@ -100,7 +100,7 @@ fn map_segment( let mem_size = segment.mem_size(); let file_size = segment.file_size(); let file_offset = segment.offset() & !0xfff; - let phys_start_addr = kernel_start + file_offset; + let phys_start_addr = start + file_offset; let virt_start_addr = VirtAddr::new(segment.virtual_addr()); let start_page: Page = Page::containing_address(virt_start_addr); diff --git a/pkg/fs/src/device/disk.rs b/pkg/fs/src/device/disk.rs index 86e468e..a9fa95a 100644 --- a/pkg/fs/src/device/disk.rs +++ b/pkg/fs/src/device/disk.rs @@ -76,7 +76,7 @@ where } fn read_block(&self, offset: usize) -> Result { - debug!( + trace!( "read_block offset: {}, volume lba start: {}", offset, self.meta.begin_lba() diff --git a/pkg/kernel/Cargo.toml b/pkg/kernel/Cargo.toml index 1e99bd2..94dea67 100644 --- a/pkg/kernel/Cargo.toml +++ b/pkg/kernel/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ggos_kernel" -version = "0.6.4" +version = "0.7.0" edition = "2021" authors = ["GZTime "] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -8,6 +8,7 @@ authors = ["GZTime "] [dependencies] boot = { path = "../boot", package = "ggos_boot", default-features = false } fs = { path = "../fs", package = "ggfs" } +elf = { package = "ggos_elf", path = "../elf" } embedded-graphics = { version = "0.7.1", features = ['fixed_point'] } lazy_static = { version = "1.4.0", features = ["spin_no_std"] } paste = "1.0.7" @@ -24,3 +25,4 @@ linked_list_allocator = "0.9.1" pc-keyboard = "0.5.1" crossbeam-queue = { version = "0.3.5", default-features = false, features = ["alloc"] } volatile = "0.4.4" +xmas-elf = "0.8" diff --git a/pkg/kernel/config/boot.conf b/pkg/kernel/config/boot.conf index 36e5232..dbfadfa 100644 --- a/pkg/kernel/config/boot.conf +++ b/pkg/kernel/config/boot.conf @@ -12,12 +12,3 @@ physical_memory_offset=0xFFFF800000000000 # The path of kernel ELF kernel_path=\KERNEL.ELF - -# The resolution of graphic output -resolution=800x600 - -# Kernel Command Line -# cmdline= - -# The path of initramfs -# initramfs=\EFI\rCore\initramfs.img diff --git a/pkg/kernel/src/drivers/ata.rs b/pkg/kernel/src/drivers/ata.rs index 6bd12f9..e35f148 100644 --- a/pkg/kernel/src/drivers/ata.rs +++ b/pkg/kernel/src/drivers/ata.rs @@ -146,7 +146,7 @@ impl Bus { fn write_command(&mut self, cmd: ATACommand) -> Result<(), ()> { unsafe { self.command.write(cmd as u8) } - debug!("Wrote command {:?}", cmd); + trace!("Wrote command {:?}", cmd); self.status(); // Ignore results of first read self.clear_interrupt(); if self.status() == 0 { diff --git a/pkg/kernel/src/drivers/filesystem.rs b/pkg/kernel/src/drivers/filesystem.rs index 711e5f2..074d8d3 100644 --- a/pkg/kernel/src/drivers/filesystem.rs +++ b/pkg/kernel/src/drivers/filesystem.rs @@ -12,12 +12,10 @@ pub fn get_volume() -> &'static Volume { } #[derive(Debug, Clone)] -pub struct StdIO; - -impl StdIO { - pub fn new() -> Self { - Self {} - } +pub enum StdIO { + Stdin, + Stdout, + Stderr, } pub fn init() { @@ -29,7 +27,7 @@ pub fn init() { info!("Initialized Filesystem."); } -fn resolve_path(root_path: &str) -> Option { +pub fn resolve_path(root_path: &str) -> Option { let mut path = root_path.to_owned(); let mut root = fs::root_dir(); @@ -48,6 +46,7 @@ fn resolve_path(root_path: &str) -> Option { root = tmp.unwrap(); path = path[pos + 1..].to_string(); + trace!("Resolving path: {}", path); if path.len() == 0 { break; @@ -57,6 +56,28 @@ fn resolve_path(root_path: &str) -> Option { Some(root) } +pub fn try_get_file(path: &str) -> Result { + let path = path.to_owned(); + let pos = path.rfind('/'); + + if pos.is_none() { + return Err(VolumeError::FileNotFound); + } + let pos = pos.unwrap(); + + trace!("root: {}, filename: {}", &path[..pos + 1], &path[pos + 1..]); + + let root = resolve_path(&path[..pos + 1]); + let filename = &path[pos + 1..]; + + if root.is_none() { + return Err(VolumeError::FileNotFound); + } + let root = root.unwrap(); + + fs::open_file(get_volume(), &root, filename, file::Mode::ReadOnly) +} + pub fn ls(root_path: &str) { let root = match resolve_path(root_path) { diff --git a/pkg/kernel/src/interrupt/handlers.rs b/pkg/kernel/src/interrupt/handlers.rs index e932855..5c66eea 100644 --- a/pkg/kernel/src/interrupt/handlers.rs +++ b/pkg/kernel/src/interrupt/handlers.rs @@ -25,6 +25,9 @@ pub unsafe fn reg_idt(idt: &mut InterruptDescriptorTable) { idt.general_protection_fault .set_handler_fn(general_protection_fault_handler); idt.page_fault.set_handler_fn(page_fault_handler); + idt.alignment_check.set_handler_fn(alignment_check_handler); + idt.machine_check.set_handler_fn(machine_check_handler); + idt.simd_floating_point.set_handler_fn(simd_floating_point_handler); idt[(consts::Interrupts::IRQ0 as u8 + consts::IRQ::Timer as u8) as usize] .set_handler_fn(clock_handler) @@ -73,7 +76,7 @@ pub extern "x86-interrupt" fn double_fault_handler( error_code: u64, ) -> ! { panic!( - "EXCEPTION: DOUBLE FAULT, ERROR_CODE: 0x{:16x}\n\n{:#?}", + "EXCEPTION: DOUBLE FAULT, ERROR_CODE: 0x{:016x}\n\n{:#?}", error_code, stack_frame ); } @@ -83,7 +86,7 @@ pub extern "x86-interrupt" fn invalid_tss_handler( error_code: u64, ) { panic!( - "EXCEPTION: INVALID TSS, ERROR_CODE: 0x{:16x}\n\n{:#?}", + "EXCEPTION: INVALID TSS, ERROR_CODE: 0x{:016x}\n\n{:#?}", error_code, stack_frame ); } @@ -128,6 +131,24 @@ pub extern "x86-interrupt" fn page_fault_handler( ); } +pub extern "x86-interrupt" fn alignment_check_handler( + stack_frame: InterruptStackFrame, + error_code: u64, +) { + panic!( + "EXCEPTION: ALIGNMENT CHECK, ERROR_CODE: 0x{:016x}\n\n{:#?}", + error_code, stack_frame + ); +} + +pub extern "x86-interrupt" fn machine_check_handler(stack_frame: InterruptStackFrame) -> ! { + panic!("EXCEPTION: MACHINE CHECK\n\n{:#?}", stack_frame); +} + +pub extern "x86-interrupt" fn simd_floating_point_handler(stack_frame: InterruptStackFrame) { + panic!("EXCEPTION: SIMD FLOATING POINT\n\n{:#?}", stack_frame); +} + pub extern "C" fn clock(mut regs: Registers, mut sf: InterruptStackFrame) { super::ack(consts::Interrupts::IRQ0 as u8); crate::process::switch(&mut regs, &mut sf); @@ -137,7 +158,8 @@ as_handler!(clock); pub extern "C" fn syscall(mut regs: Registers, mut sf: InterruptStackFrame) { let args = - super::syscall::SyscallArgs::new(Syscall::from(regs.rax), regs.rbx, regs.rcx, regs.rdx); + super::syscall::SyscallArgs::new(Syscall::from(regs.rax), regs.rdi, regs.rsi, regs.rdx); + trace!("{}", args); unsafe { x86_64::instructions::interrupts::without_interrupts(|| { super::syscall::dispatcher(args, &mut regs, &mut sf); diff --git a/pkg/kernel/src/interrupt/syscall/mod.rs b/pkg/kernel/src/interrupt/syscall/mod.rs index d40bc40..7fbcab1 100644 --- a/pkg/kernel/src/interrupt/syscall/mod.rs +++ b/pkg/kernel/src/interrupt/syscall/mod.rs @@ -1,4 +1,5 @@ use crate::utils::*; +use core::alloc::Layout; use x86_64::structures::idt::InterruptStackFrame; mod service; @@ -13,10 +14,11 @@ pub enum Syscall { Open = 5, Close = 6, Stat = 7, - // rax = 8, ret: *rbx, u64 timestamp Clock = 8, Draw = 9, - None = 0xdeadbeef + Allocate = 10, + Deallocate = 11, + None = 0xdeadbeef, } #[derive(Clone, Debug)] @@ -28,22 +30,19 @@ pub struct SyscallArgs { } #[allow(unused_variables)] -pub unsafe fn dispatcher(args: SyscallArgs, regs: &mut Registers, st: &mut InterruptStackFrame) { +pub unsafe fn dispatcher(args: SyscallArgs, regs: &mut Registers, sf: &mut InterruptStackFrame) { match args.syscall { Syscall::SpwanProcess => {} - Syscall::ExitProcess => {} - Syscall::Read => { - match args.arg0 { - 0 => { - - } - fd => warn!("SYSCALL: cannot read from fd: {}", fd), - } - } + Syscall::ExitProcess => exit_process(regs, sf), // todo: handle exit code + Syscall::Read => match args.arg0 { + 0 => {} + fd => warn!("SYSCALL: cannot read from fd: {}", fd), + }, Syscall::Write => { - let s = core::str::from_utf8_unchecked( - core::slice::from_raw_parts(args.arg1 as *const u8, args.arg2) - ); + let s = core::str::from_utf8_unchecked(core::slice::from_raw_parts( + args.arg1 as *const u8, + args.arg2, + )); match args.arg0 { 1 => print!("{}", s), fd => warn!("SYSCALL: cannot write to fd: {}", fd), @@ -52,8 +51,15 @@ pub unsafe fn dispatcher(args: SyscallArgs, regs: &mut Registers, st: &mut Inter Syscall::Open => {} Syscall::Close => {} Syscall::Stat => {} - Syscall::Clock => *(args.arg0 as *mut i64) = sys_clock(), + Syscall::Clock => regs.set_rax(sys_clock() as usize), Syscall::Draw => sys_draw(args.arg0, args.arg1, args.arg2), + Syscall::Allocate => { + regs.set_rax(sys_allocate((args.arg0 as *const Layout).as_ref().unwrap()) as usize) + } + Syscall::Deallocate => sys_deallocate( + args.arg0 as *mut u8, + (args.arg1 as *const Layout).as_ref().unwrap(), + ), Syscall::None => {} } } @@ -69,10 +75,13 @@ impl From for Syscall { 6 => Self::Close, 7 => Self::Stat, 8 => Self::Clock, + 9 => Self::Draw, + 10 => Self::Allocate, + 11 => Self::Deallocate, _ => { warn!("Unknown SYSCALL: {}", num); Self::None - }, + } } } } @@ -92,7 +101,7 @@ impl core::fmt::Display for SyscallArgs { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { write!( f, - "SYSCALL: {:?} ({:016x}, {:016x}, {:016x})", + "SYSCALL: {:?} (0x{:016x}, 0x{:016x}, 0x{:016x})", self.syscall, self.arg0, self.arg1, self.arg2 ) } diff --git a/pkg/kernel/src/interrupt/syscall/service.rs b/pkg/kernel/src/interrupt/syscall/service.rs index c0d63f8..ab8f50d 100644 --- a/pkg/kernel/src/interrupt/syscall/service.rs +++ b/pkg/kernel/src/interrupt/syscall/service.rs @@ -1,5 +1,7 @@ use crate::{utils::*, display::get_display_for_sure}; use embedded_graphics::prelude::*; +use x86_64::structures::idt::InterruptStackFrame; +use crate::utils::Registers; pub fn sys_clock() -> i64 { clock::now().timestamp_nanos() @@ -11,3 +13,27 @@ pub fn sys_draw(x: usize, y: usize, color: usize) { color as u32 ); } + +pub fn sys_allocate(layout: &core::alloc::Layout) -> *mut u8 { + debug!("sys_allocate: \n{:#?}", layout); + let ptr = crate::allocator::ALLOCATOR + .lock() + .allocate_first_fit(layout.clone()) + .unwrap() + .as_ptr(); + debug!("allocated {:x}", ptr as u64); + ptr +} + +pub fn sys_deallocate(ptr: *mut u8, layout: &core::alloc::Layout) { + unsafe { + crate::allocator::ALLOCATOR + .lock() + .deallocate(core::ptr::NonNull::new_unchecked(ptr), layout.clone()); + } + debug!("deallocated {:x}", ptr as u64); +} + +pub fn exit_process(regs: &mut Registers, sf: &mut InterruptStackFrame) { + crate::process::process_exit(regs, sf); +} diff --git a/pkg/kernel/src/lib.rs b/pkg/kernel/src/lib.rs index 45be5c0..81c8d6c 100644 --- a/pkg/kernel/src/lib.rs +++ b/pkg/kernel/src/lib.rs @@ -55,15 +55,8 @@ pub fn init(boot_info: &'static BootInfo) { x86_64::instructions::interrupts::enable(); info!("Interrupts Enabled."); - // process::spawn_kernel_thread( - // utils::func::clock, - // alloc::string::String::from("clock"), - // None - // ); - info!("GGOS initialized."); - // Enable cursor...? print_serial!("\x1b[?25h"); } diff --git a/pkg/kernel/src/main.rs b/pkg/kernel/src/main.rs index 48e94ea..53226e2 100644 --- a/pkg/kernel/src/main.rs +++ b/pkg/kernel/src/main.rs @@ -13,6 +13,12 @@ boot::entry_point!(kernal_main); pub fn kernal_main(boot_info: &'static boot::BootInfo) -> ! { ggos::init(boot_info); + let sh_file = ggos::filesystem::try_get_file("/APP/SH").unwrap(); + + x86_64::instructions::interrupts::without_interrupts(|| { + ggos::process::spawn(&sh_file).unwrap(); + }); + let mut test_num = 0; let mut root_dir = String::from("/"); diff --git a/pkg/kernel/src/process/manager.rs b/pkg/kernel/src/process/manager.rs index 7bc444f..a99781e 100644 --- a/pkg/kernel/src/process/manager.rs +++ b/pkg/kernel/src/process/manager.rs @@ -4,6 +4,7 @@ use alloc::format; use alloc::vec::Vec; use x86_64::structures::idt::InterruptStackFrame; use x86_64::VirtAddr; +use xmas_elf::ElfFile; once_mutex!(pub PROCESS_MANAGER: ProcessManager); guard_access_fn! { @@ -57,7 +58,7 @@ impl ProcessManager { .processes .iter() .position(|x| x.pid() == self.cur_pid) - .unwrap() + .unwrap_or(0) + 1; if next_pos >= self.processes.len() { 0 @@ -82,19 +83,47 @@ impl ProcessManager { } pub fn spawn( + &mut self, + elf: &ElfFile, + name: String, + parent: u16, + proc_data: Option, + ) -> u16 { + let mut p = Process::new( + &mut *crate::memory::get_frame_alloc_for_sure(), + self.next_pid, + name, + parent, + proc_data, + ); + p.pause(); + p.init_stack_frame( + VirtAddr::new_truncate(elf.header.pt2.entry_point()), + VirtAddr::new_truncate(STACK_TOP), + ); + p.init_elf(elf); + info!("Spawn process: {}#{}", p.name(), p.pid()); + // info!("Spawn process:\n\n{:?}\n", p); + let pid = p.pid(); + self.processes.push(p); + self.next_pid += 1; // TODO: recycle PID + pid + } + + pub fn spawn_kernel_thread( &mut self, entry: VirtAddr, stack_top: VirtAddr, name: String, parent: u16, - proc_data: Option + proc_data: Option, ) -> u16 { let mut p = Process::new( &mut *crate::memory::get_frame_alloc_for_sure(), self.next_pid, name, parent, - proc_data + proc_data, ); p.pause(); p.init_stack_frame(entry, stack_top); diff --git a/pkg/kernel/src/process/mod.rs b/pkg/kernel/src/process/mod.rs index 6208b4e..46891b7 100644 --- a/pkg/kernel/src/process/mod.rs +++ b/pkg/kernel/src/process/mod.rs @@ -1,30 +1,38 @@ -mod process; mod manager; +mod process; mod scheduler; -use process::*; +use fs::File; use manager::*; +use process::*; -pub use scheduler::*; pub use process::ProcessData; +pub use scheduler::*; +use crate::{filesystem::get_volume, Registers}; use alloc::string::String; +use x86_64::structures::{idt::InterruptStackFrame, paging::FrameAllocator}; + use self::manager::init_PROCESS_MANAGER; +const STACK_BOT: u64 = 0x0000_2000_0000_0000; +const STACK_PAGES: u64 = 512; +const STACK_TOP: u64 = STACK_BOT + STACK_PAGES * 0x1000; + #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum ProgramStatus { Created, Running, Ready, Blocked, - Dead + Dead, } /// init process manager pub fn init() { let mut alloc = crate::memory::get_frame_alloc_for_sure(); // kernel process - let mut kproc = Process::new( &mut *alloc, 0, String::from("kernel"), 0, None); + let mut kproc = Process::new(&mut *alloc, 0, String::from("kernel"), 0, None); kproc.resume(); kproc.set_page_table_with_cr3(); init_PROCESS_MANAGER(ProcessManager::new(kproc)); @@ -43,3 +51,53 @@ pub fn env(key: &str) -> Option { get_process_manager_for_sure().current().env(key) }) } + +pub fn process_exit(regs: &mut Registers, sf: &mut InterruptStackFrame) { + x86_64::instructions::interrupts::without_interrupts(|| { + let mut manager = get_process_manager_for_sure(); + manager.kill(); + manager.switch_next(regs, sf); + }) +} + +pub fn spawn(file: &File) -> Result { + let size = file.length(); + let data = { + let pages = (size as usize + 0x1000 - 1) / 0x1000; + let allocator = &mut *crate::memory::get_frame_alloc_for_sure(); + + let mem_start = allocator.allocate_frame().unwrap() + .start_address().as_u64(); + + trace!("alloc = 0x{:016x}", mem_start); + + for _ in 1..pages { + let addr = allocator.allocate_frame().unwrap() + .start_address().as_u64(); + trace!("alloc = 0x{:016x}", addr); + } + + let mut buf = + unsafe { core::slice::from_raw_parts_mut(mem_start as *mut u8, pages * 0x1000) }; + + fs::read_to_buf(get_volume(), file, &mut buf).expect("Failed to read file"); + &mut buf[..pages * 0x1000] + }; + + let elf = xmas_elf::ElfFile::new(&data).expect("Failed to parse ELF file"); + + const STACK_BOT: u64 = 0x0000_2000_0000_0000; + const STACK_PAGES: u64 = 512; + const STACK_TOP: u64 = STACK_BOT + STACK_PAGES * 0x1000; + + let mut manager = get_process_manager_for_sure(); + + let parent = manager.current().pid(); + let pid = manager.spawn( + &elf, + file.entry.filename(), + parent, + Some(ProcessData::new()), + ); + Ok(pid) +} diff --git a/pkg/kernel/src/process/process.rs b/pkg/kernel/src/process/process.rs index dc4d4fb..2ee94ad 100644 --- a/pkg/kernel/src/process/process.rs +++ b/pkg/kernel/src/process/process.rs @@ -1,18 +1,19 @@ -use super::ProgramStatus; +use super::*; use crate::filesystem::StdIO; +use crate::memory::physical_to_virtual; use crate::memory::BootInfoFrameAllocator; use crate::utils::{Registers, RegistersValue, Resource}; -use crate::memory::physical_to_virtual; +use alloc::collections::btree_map::BTreeMap; +use alloc::string::String; +use alloc::vec::Vec; use core::intrinsics::copy_nonoverlapping; -use x86_64::structures::paging::{OffsetPageTable, PhysFrame, PageTable}; -use x86_64::structures::idt::{InterruptStackFrameValue, InterruptStackFrame}; -use x86_64::structures::paging::FrameAllocator; use x86_64::registers::control::{Cr3, Cr3Flags}; use x86_64::registers::rflags::RFlags; -use alloc::string::String; -use alloc::vec::Vec; +use x86_64::structures::idt::{InterruptStackFrame, InterruptStackFrameValue}; +use x86_64::structures::paging::FrameAllocator; +use x86_64::structures::paging::{OffsetPageTable, PageTable, PhysFrame}; use x86_64::VirtAddr; -use alloc::collections::btree_map::BTreeMap; +use xmas_elf::ElfFile; pub struct Process { pid: u16, @@ -21,17 +22,17 @@ pub struct Process { parent: u16, status: ProgramStatus, ticks_passed: usize, - children: Vec::, + children: Vec, stack_frame: InterruptStackFrameValue, page_table_addr: (PhysFrame, Cr3Flags), page_table: Option>, - proc_data: ProcessData + proc_data: ProcessData, } #[derive(Clone, Debug, Default)] pub struct ProcessData { env: BTreeMap, - file_handles: BTreeMap + file_handles: BTreeMap, } impl ProcessData { @@ -39,9 +40,9 @@ impl ProcessData { let env = BTreeMap::new(); let mut file_handles = BTreeMap::new(); // stdin, stdout, stderr - file_handles.insert(0, Resource::Console(StdIO::new())); - file_handles.insert(1, Resource::Console(StdIO::new())); - file_handles.insert(2, Resource::Console(StdIO::new())); + file_handles.insert(0, Resource::Console(StdIO::Stdin)); + file_handles.insert(1, Resource::Console(StdIO::Stdout)); + file_handles.insert(2, Resource::Console(StdIO::Stderr)); Self { env, file_handles } } @@ -89,8 +90,8 @@ impl Process { } pub fn save(&mut self, regs: &mut Registers, sf: &mut InterruptStackFrame) { - self.regs = unsafe{ regs.as_mut().read().clone() }; - self.stack_frame = unsafe{ sf.as_mut().read().clone() }; + self.regs = unsafe { regs.as_mut().read().clone() }; + self.stack_frame = unsafe { sf.as_mut().read().clone() }; self.status = ProgramStatus::Ready; } @@ -106,16 +107,20 @@ impl Process { pub fn init_stack_frame(&mut self, entry: VirtAddr, stack_top: VirtAddr) { self.stack_frame.stack_pointer = stack_top; self.stack_frame.instruction_pointer = entry; - self.stack_frame.cpu_flags = (RFlags::IOPL_HIGH | RFlags::IOPL_LOW | RFlags::INTERRUPT_FLAG).bits(); + self.stack_frame.cpu_flags = + (RFlags::IOPL_HIGH | RFlags::IOPL_LOW | RFlags::INTERRUPT_FLAG).bits(); } pub fn new( frame_alloc: &mut BootInfoFrameAllocator, - pid: u16, name: String, parent: u16, - proc_data: Option + pid: u16, + name: String, + parent: u16, + proc_data: Option, ) -> Self { // 1. alloc a page table for process - let page_table_addr = frame_alloc.allocate_frame() + let page_table_addr = frame_alloc + .allocate_frame() .expect("Cannot alloc page table for new process."); trace!("Alloc page table for {}: {:?}", name, page_table_addr); @@ -124,16 +129,16 @@ impl Process { copy_nonoverlapping::( Cr3::read().0.start_address().as_u64() as *mut PageTable, page_table_addr.start_address().as_u64() as *mut PageTable, - 1 + 1, ); } // 3. create page table object let page_table_raw = unsafe { - (physical_to_virtual(page_table_addr.start_address().as_u64()) - as *mut PageTable) - .as_mut() - }.unwrap(); + (physical_to_virtual(page_table_addr.start_address().as_u64()) as *mut PageTable) + .as_mut() + } + .unwrap(); let page_table = unsafe { OffsetPageTable::new( @@ -168,9 +173,20 @@ impl Process { page_table_addr: (page_table_addr, Cr3::read().1), page_table: Some(page_table), children: Vec::new(), - proc_data: proc_data.unwrap_or_default() + proc_data: proc_data.unwrap_or_default(), } } + + pub fn init_elf(&mut self, elf: &ElfFile) { + let alloc = &mut *crate::memory::get_frame_alloc_for_sure(); + + let mut page_table = self.page_table.take().unwrap(); + + elf::map_elf(elf, &mut page_table, alloc).unwrap(); + elf::map_stack(STACK_BOT, STACK_PAGES, &mut page_table, alloc).unwrap(); + + self.page_table = Some(page_table); + } } impl Drop for Process { @@ -189,9 +205,17 @@ impl core::fmt::Debug for Process { write!(f, " ticks_passed: {},\n", self.ticks_passed)?; write!(f, " children: {:?}\n", self.children)?; write!(f, " page_table_addr: {:?},\n", self.page_table_addr)?; - write!(f, " stack_top: 0x{:016x},\n", self.stack_frame.stack_pointer.as_u64())?; + write!( + f, + " stack_top: 0x{:016x},\n", + self.stack_frame.stack_pointer.as_u64() + )?; write!(f, " cpu_flags: 0x{:04x},\n", self.stack_frame.cpu_flags)?; - write!(f, " instruction_pointer: 0x{:016x}\n", self.stack_frame.instruction_pointer.as_u64())?; + write!( + f, + " instruction_pointer: 0x{:016x}\n", + self.stack_frame.instruction_pointer.as_u64() + )?; write!(f, "}}")?; Ok(()) } @@ -199,7 +223,11 @@ impl core::fmt::Debug for Process { impl core::fmt::Display for Process { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - write!(f, "#{:3} | {:10} | {}", self.pid, self.name, self.ticks_passed)?; + write!( + f, + "#{:3} | {:10} | {}", + self.pid, self.name, self.ticks_passed + )?; Ok(()) } } diff --git a/pkg/kernel/src/process/scheduler.rs b/pkg/kernel/src/process/scheduler.rs index 61b96c7..fd23d3d 100644 --- a/pkg/kernel/src/process/scheduler.rs +++ b/pkg/kernel/src/process/scheduler.rs @@ -27,6 +27,6 @@ pub fn spawn_kernel_thread(entry: fn() -> !, name: String, data: Option ! { let mut count = 0; @@ -21,84 +21,84 @@ pub fn test() -> ! { } } -#[no_mangle] -pub extern "C" fn syscall(syscall: usize, arg0: usize, arg1: usize, arg2: usize) { - unsafe { - core::arch::asm!( - "mov rbx, {} - int 0x80", - in(reg) arg0, - in("rax") syscall, - in("rcx") arg1, - in("rdx") arg2 - ); - } -} +// #[no_mangle] +// pub extern "C" fn syscall(syscall: usize, arg0: usize, arg1: usize, arg2: usize) { +// unsafe { +// core::arch::asm!( +// "mov rbx, {} +// int 0x80", +// in(reg) arg0, +// in("rax") syscall, +// in("rcx") arg1, +// in("rdx") arg2 +// ); +// } +// } -pub fn clock() -> ! { - let mut angle: f32 = 90.0; - const ANGLE_INCR: f32 = 15.0; - const D_OFFSET: i32 = 4; - let cx = x86_64::instructions::interrupts::without_interrupts(|| { - get_display_for_sure().resolution().0 - }); +// pub fn clock() -> ! { +// let mut angle: f32 = 90.0; +// const ANGLE_INCR: f32 = 15.0; +// const D_OFFSET: i32 = 4; +// let cx = x86_64::instructions::interrupts::without_interrupts(|| { +// get_display_for_sure().resolution().0 +// }); - use crate::utils::colors; - use embedded_graphics::prelude::*; - use embedded_graphics::primitives::*; - #[allow(unused_imports)] - use micromath::F32Ext; +// use crate::utils::colors; +// use embedded_graphics::prelude::*; +// use embedded_graphics::primitives::*; +// #[allow(unused_imports)] +// use micromath::F32Ext; - loop { - let mut start: i64 = 0; +// loop { +// let mut start: i64 = 0; - syscall( - Syscall::Clock as usize, - (&mut start as *mut i64) as usize, - 0, - 0, - ); +// syscall( +// Syscall::Clock as usize, +// (&mut start as *mut i64) as usize, +// 0, +// 0, +// ); - let mut current = start; +// let mut current = start; - while current - start < 1000_0000 { - syscall( - Syscall::Clock as usize, - (&mut current as *mut i64) as usize, - 0, - 0, - ); - } +// while current - start < 1000_0000 { +// syscall( +// Syscall::Clock as usize, +// (&mut current as *mut i64) as usize, +// 0, +// 0, +// ); +// } - angle += ANGLE_INCR; - if angle >= 360.0 { - angle = 0.0; - } - let value = angle / 180f32 * core::f32::consts::PI; +// angle += ANGLE_INCR; +// if angle >= 360.0 { +// angle = 0.0; +// } +// let value = angle / 180f32 * core::f32::consts::PI; - let len = 24i32; - let (cx, cy) = (cx as i32 - len - 10, len + 8); +// let len = 24i32; +// let (cx, cy) = (cx as i32 - len - 10, len + 8); - let (dx, dy) = ( - (len as f32 * value.cos()) as i32, - (len as f32 * value.sin()) as i32, - ); +// let (dx, dy) = ( +// (len as f32 * value.cos()) as i32, +// (len as f32 * value.sin()) as i32, +// ); - x86_64::instructions::interrupts::without_interrupts(|| { - if let Some(mut display) = crate::drivers::display::get_display() { - Circle::new( - Point::new(cx - len - D_OFFSET, cy - len - D_OFFSET), - (2 * len + D_OFFSET * 2) as u32, - ) - .into_styled(PrimitiveStyle::with_fill(colors::FRONTGROUND)) - .draw(&mut *display) - .unwrap(); +// x86_64::instructions::interrupts::without_interrupts(|| { +// if let Some(mut display) = crate::drivers::display::get_display() { +// Circle::new( +// Point::new(cx - len - D_OFFSET, cy - len - D_OFFSET), +// (2 * len + D_OFFSET * 2) as u32, +// ) +// .into_styled(PrimitiveStyle::with_fill(colors::FRONTGROUND)) +// .draw(&mut *display) +// .unwrap(); - Line::new(Point::new(cx, cy), Point::new(cx + dx, cy + dy)) - .into_styled(PrimitiveStyle::with_stroke(colors::GREEN, 5)) - .draw(&mut *display) - .unwrap(); - } - }); - } -} +// Line::new(Point::new(cx, cy), Point::new(cx + dx, cy + dy)) +// .into_styled(PrimitiveStyle::with_stroke(colors::GREEN, 5)) +// .draw(&mut *display) +// .unwrap(); +// } +// }); +// } +// } diff --git a/pkg/kernel/src/utils/regs.rs b/pkg/kernel/src/utils/regs.rs index 65b5efd..35fc15b 100644 --- a/pkg/kernel/src/utils/regs.rs +++ b/pkg/kernel/src/utils/regs.rs @@ -23,7 +23,7 @@ pub struct RegistersValue { } #[repr(C)] -pub struct Registers { +pub struct Registers { value: RegistersValue } @@ -32,6 +32,11 @@ impl Registers { pub unsafe fn as_mut(&mut self) -> Volatile<&mut RegistersValue> { Volatile::new(&mut self.value) } + + #[inline] + pub unsafe fn set_rax(&mut self, value: usize) { + self.value.rax = value; + } } impl Deref for Registers { diff --git a/pkg/kernel/src/utils/resource.rs b/pkg/kernel/src/utils/resource.rs index 1a9e354..4f34fe6 100644 --- a/pkg/kernel/src/utils/resource.rs +++ b/pkg/kernel/src/utils/resource.rs @@ -1,9 +1,9 @@ +use crate::input; use alloc::string::{String, ToString}; -use fs::{Random, File, Device}; +use fs::{Device, File, Random}; use pc_keyboard::DecodedKey; -use crate::input; -use crate::filesystem::{StdIO, get_volume}; +use crate::filesystem::{get_volume, StdIO}; #[derive(Debug, Clone)] pub enum Resource { @@ -16,32 +16,30 @@ pub enum Resource { impl Resource { pub fn read(&self, buf: &mut [u8]) -> Result { match self { - Resource::File(file) => { - fs::read_to_buf(get_volume(), file, buf) - .map_err(|_| ()) - }, - Resource::Console(_) => { - if buf.len() < 4 { - return Ok(0); - } - let mut s = if buf.len() == 4 { - if let DecodedKey::Unicode(c) = input::get_key() { - c.to_string() - } else { + Resource::File(file) => fs::read_to_buf(get_volume(), file, buf).map_err(|_| ()), + Resource::Console(stdio) => match stdio { + &StdIO::Stdin => { + if buf.len() < 4 { return Ok(0); } - } else { - input::get_line() - }; + let mut s = if buf.len() == 4 { + if let DecodedKey::Unicode(c) = input::get_key() { + c.to_string() + } else { + return Ok(0); + } + } else { + input::get_line() + }; - s.truncate(buf.len()); - let n = s.len(); - buf[..n].copy_from_slice(s.as_bytes()); - Ok(n) - }, - Resource::Random(random) => { - Ok(random.read(buf, 0, buf.len()).unwrap_or(0)) + s.truncate(buf.len()); + let n = s.len(); + buf[..n].copy_from_slice(s.as_bytes()); + Ok(n) + } + _ => Err(()), }, + Resource::Random(random) => Ok(random.read(buf, 0, buf.len()).unwrap_or(0)), Resource::Null => Ok(0), } } @@ -49,9 +47,16 @@ impl Resource { pub fn write(&self, buf: &[u8]) -> Result { match self { Resource::File(_) => unimplemented!(), - Resource::Console(_) => { - print!("{}", String::from_utf8_lossy(buf)); - Ok(buf.len()) + Resource::Console(stdio) => match stdio { + &StdIO::Stdin => Err(()), + &StdIO::Stdout => { + print!("{}", String::from_utf8_lossy(buf)); + Ok(buf.len()) + } + &StdIO::Stderr => { + warn!("{}", String::from_utf8_lossy(buf)); + Ok(buf.len()) + } }, Resource::Random(_) => Ok(0), Resource::Null => Ok(0), diff --git a/pkg/lib/Cargo.toml b/pkg/lib/Cargo.toml index 76f97ca..478886b 100644 --- a/pkg/lib/Cargo.toml +++ b/pkg/lib/Cargo.toml @@ -7,4 +7,3 @@ authors = ["GZTime "] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -kernel = { path = "../kernel", package = "ggos_kernel" } diff --git a/pkg/lib/src/allocator.rs b/pkg/lib/src/allocator.rs new file mode 100644 index 0000000..a89781a --- /dev/null +++ b/pkg/lib/src/allocator.rs @@ -0,0 +1,19 @@ +pub struct SystemAllocator; + +unsafe impl alloc::alloc::GlobalAlloc for SystemAllocator { + unsafe fn alloc(&self, layout: core::alloc::Layout) -> *mut u8 { + crate::sys_allocate(&layout) + } + unsafe fn dealloc(&self, ptr: *mut u8, layout: core::alloc::Layout) { + crate::sys_deallocate(ptr, &layout); + } +} + +#[global_allocator] +static ALLOCATOR: SystemAllocator = SystemAllocator; + +#[cfg(not(test))] +#[alloc_error_handler] +fn alloc_error_handler(layout: alloc::alloc::Layout) -> ! { + panic!("allocation error: {:?}", layout) +} diff --git a/pkg/lib/src/console.rs b/pkg/lib/src/console.rs deleted file mode 100644 index 4009f1d..0000000 --- a/pkg/lib/src/console.rs +++ /dev/null @@ -1,26 +0,0 @@ -use core::fmt::*; - -pub struct Console; - -impl Write for Console { - fn write_str(&mut self, s: &str) -> core::fmt::Result { - crate::sys_write(s, 1); - Ok(()) - } -} - -#[macro_export] -macro_rules! print { - ($($arg:tt)*) => ($crate::_print(format_args!($($arg)*))); -} - -#[macro_export] -macro_rules! println { - () => ($crate::print!("\n")); - ($($arg:tt)*) => ($crate::print!("{}\n", format_args!($($arg)*))); -} - -#[doc(hidden)] -pub fn _print(args: Arguments) { - Console.write_fmt(args).unwrap(); -} diff --git a/pkg/lib/src/io.rs b/pkg/lib/src/io.rs new file mode 100644 index 0000000..86d50be --- /dev/null +++ b/pkg/lib/src/io.rs @@ -0,0 +1,66 @@ +use crate::*; +use alloc::vec; +use alloc::string::{String, ToString}; + +pub struct Stdin; +pub struct Stdout; +pub struct Stderr; + +impl Stdin { + fn new() -> Self { + Self {} + } + + pub fn read_char(&self) -> Option { + let mut buf = vec![0; 4]; + if let Some(bytes) = sys_read(0, &mut buf) { + if bytes > 0 { + buf.resize(bytes, 0); + return Some(String::from_utf8_lossy(&buf).to_string().remove(0)); + } + } + None + } + + pub fn read_line(&self) -> String { + let mut buf = vec![0; 256]; + if let Some(bytes) = sys_read(0, &mut buf) { + buf.resize(bytes, 0); + String::from_utf8_lossy(&buf).to_string() + } else { + String::new() + } + } +} + +impl Stdout { + fn new() -> Self { + Self {} + } + + pub fn write(&self, s: &str) { + sys_write(1, s.as_bytes()); + } +} + +impl Stderr { + fn new() -> Self { + Self {} + } + + pub fn write(&self, s: &str) { + sys_write(2, s.as_bytes()); + } +} + +pub fn stdin() -> Stdin { + Stdin::new() +} + +pub fn stdout() -> Stdout { + Stdout::new() +} + +pub fn stderr() -> Stderr { + Stderr::new() +} diff --git a/pkg/lib/src/lib.rs b/pkg/lib/src/lib.rs index 397bd8f..f61f369 100644 --- a/pkg/lib/src/lib.rs +++ b/pkg/lib/src/lib.rs @@ -1,4 +1,66 @@ +#![no_std] +#![allow(dead_code)] +#![feature(panic_info_message)] +#![feature(alloc_error_handler)] + +extern crate alloc; + +#[macro_use] +pub mod macros; + +#[macro_use] +pub mod io; mod syscall; -mod console; +pub mod allocator; + +use io::{stdout, stderr}; +pub use syscall::*; +use core::fmt::*; +use alloc::format; + +#[derive(Clone, Debug)] +pub enum Syscall { + SpwanProcess = 1, + ExitProcess = 2, + Read = 3, + Write = 4, + Open = 5, + Close = 6, + Stat = 7, + Clock = 8, + Draw = 9, + Allocate = 10, + Deallocate = 11, +} + +#[macro_export] +macro_rules! print { + ($($arg:tt)*) => ($crate::_print(format_args!($($arg)*))); +} + +#[macro_export] +macro_rules! println { + () => ($crate::print!("\n")); + ($($arg:tt)*) => ($crate::print!("{}\n", format_args!($($arg)*))); +} + +#[macro_export] +macro_rules! err { + ($($arg:tt)*) => ($crate::_err(format_args!($($arg)*))); +} + +#[macro_export] +macro_rules! errln { + () => ($crate::err!("\n")); + ($($arg:tt)*) => ($crate::err!("{}\n", format_args!($($arg)*))); +} + +#[doc(hidden)] +pub fn _print(args: Arguments) { + stdout().write(format!("{}", args).as_str()); +} -use syscall::*; +#[doc(hidden)] +pub fn _err(args: Arguments) { + stderr().write(format!("{}", args).as_str()); +} diff --git a/pkg/lib/src/macros.rs b/pkg/lib/src/macros.rs new file mode 100644 index 0000000..13fedc0 --- /dev/null +++ b/pkg/lib/src/macros.rs @@ -0,0 +1,96 @@ +use crate::{Syscall, errln}; +use crate::alloc::string::ToString; +use core::arch::asm; + +#[doc(hidden)] +pub fn syscall0(n: Syscall) -> isize { + let ret: isize; + unsafe { + asm!( + "int 0x80", in("rax") n as usize, + lateout("rax") ret + ); + } + ret +} + +#[doc(hidden)] +pub fn syscall1(n: Syscall, arg0: usize) -> isize { + let ret: isize; + unsafe { + asm!( + "int 0x80", in("rax") n as usize, + in("rdi") arg0, + lateout("rax") ret + ); + } + ret +} + +#[doc(hidden)] +pub fn syscall2(n: Syscall, arg0: usize, arg1: usize) -> isize { + let ret: isize; + unsafe { + asm!( + "int 0x80", in("rax") n as usize, + in("rdi") arg0, in("rsi") arg1, + lateout("rax") ret + ); + } + ret +} + +#[doc(hidden)] +pub fn syscall3(n: Syscall, arg0: usize, arg1: usize, arg2: usize) -> isize { + let ret: isize; + unsafe { + asm!( + "int 0x80", in("rax") n as usize, + in("rdi") arg0, in("rsi") arg1, in("rdx") arg2, + lateout("rax") ret + ); + } + ret +} + +#[macro_export] +macro_rules! syscall { + ($n:expr) => { + $crate::macros::syscall0($n) + }; + ($n:expr, $a1:expr) => { + $crate::macros::syscall1($n, $a1 as usize) + }; + ($n:expr, $a1:expr, $a2:expr) => { + $crate::macros::syscall2($n, $a1 as usize, $a2 as usize) + }; + ($n:expr, $a1:expr, $a2:expr, $a3:expr) => { + $crate::macros::syscall3($n, $a1 as usize, $a2 as usize, $a3 as usize) + }; +} + +#[macro_export] +macro_rules! entry { + ($fn:ident) => { + #[export_name = "_start"] + pub extern "C" fn __impl_start() { + $fn(); + } + }; +} + +#[panic_handler] +fn panic(info: &core::panic::PanicInfo) -> ! { + let location = if let Some(location) = info.location() { + alloc::format!("{}@{}:{}", location.file(), location.line(), location.column()) + } else { + "Unknown location".to_string() + }; + let msg = if let Some(msg) = info.message() { + alloc::format!("{:#?}", msg) + } else { + "No more message...".to_string() + }; + errln!("\n\n\rERROR: panicked at {}\n\n\r{}", location, msg); + loop {} +} diff --git a/pkg/lib/src/syscall.rs b/pkg/lib/src/syscall.rs index d808909..99d9425 100644 --- a/pkg/lib/src/syscall.rs +++ b/pkg/lib/src/syscall.rs @@ -1,19 +1,42 @@ -use kernel::Syscall; +use crate::Syscall; -fn syscall(id: Syscall, arg0: u64, arg1: u64, arg2: u64) { - unsafe { - core::arch::asm!("int 0x80", in("rax") id as u64, in("rbx") arg0, in("rcx") arg1, in("rdx") arg2); +pub fn sys_draw(x: i32, y: i32, color: u32) -> isize { + syscall!(Syscall::Draw, x as usize, y as usize, color as usize) +} + +pub fn sys_write(fd: u64, buf: &[u8]) -> Option { + let ret = syscall!(Syscall::Write, fd, buf.as_ptr() as u64, buf.len() as u64); + if ret.is_negative() { + None + } else { + Some(ret as usize) + } +} + +pub fn sys_read(fd: u64, buf: &mut [u8]) -> Option { + let ret = syscall!(Syscall::Read, fd, buf.as_ptr() as u64, buf.len() as u64); + if ret.is_negative() { + None + } else { + Some(ret as usize) } } -pub fn sys_draw(x: i32, y: i32, color: u32) { - syscall(Syscall::Draw, x as u64, y as u64, color as u64); +pub fn sys_allocate(layout: &core::alloc::Layout) -> *mut u8 { + syscall!( + Syscall::Allocate, + layout as *const _ + ) as *mut u8 } -pub fn sys_write(s: &str, fd: usize) { - syscall(Syscall::Write, s.as_ptr() as u64, s.len() as u64, fd) +pub fn sys_deallocate(ptr: *mut u8, layout: &core::alloc::Layout) -> isize { + syscall!( + Syscall::Deallocate, + ptr, + layout as *const _ + ) } -pub fn sys_read(buf: &mut [u8], count: usize, fd: usize) -> usize { - syscall(Syscall::Read, buf.as_ptr() as u64, count as u64, fd) +pub fn sys_exit(code: usize) { + syscall!(Syscall::ExitProcess, code); }