Skip to content

Commit

Permalink
Add process table and exit syscall (#268)
Browse files Browse the repository at this point in the history
* Add process table

* Add exit syscall

* Update binaries

* Make pid mutable

* Use RW lock for the process table

* Change pid atomic ordering

* Fix return code

* Fix lock issue

* Add debug print

* Add exit to sleep binary

* Enable asm_sym feature

* Use the end of code area for stack area

* Add debug macro

* Use array instead of vec for process

* Refactor process data clone

* Increase max file handles to 32

* Increase sleep to 5 seconds

* Fix MAX_PID calculation

* Revert max file handle value to fix crash

* Close file handle after dup syscall

* Remove init

* Run the test in release mode

* Refactor debug

* Refactor debug output of syscall

* Remove NULL syscall

* Save and restore stack frame

* Fix install

* Save only scratch registers to the stack

* Add write volatile to registers

* Overwrite rax register on exit

* Set pid back to 0 after exit

* Add alloc_page function

* Remove debug output

* Unmap pages after exit

* Allocate memory after kernel heap

* Hide unmap error
  • Loading branch information
vinc authored Nov 27, 2021
1 parent 35f03ee commit e75c287
Show file tree
Hide file tree
Showing 19 changed files with 272 additions and 153 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Changelog

## Unreleased
- Add process table and exit syscall (#268)
- Improve UTF-8 support (#267)
- Bump acpi from 4.0.0 to 4.1.0 (#265)
- Add shell redirections (#262)
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ qemu:
qemu-system-x86_64 $(opts)

test:
cargo test --lib --no-default-features --features serial,$(nic) -- \
cargo test --release --lib --no-default-features --features serial,$(nic) -- \
-m 32 -display none -serial stdio -device isa-debug-exit,iobase=0xf4,iosize=0x04

clean:
Expand Down
Binary file modified dsk/bin/hello
Binary file not shown.
Binary file modified dsk/bin/sleep
Binary file not shown.
4 changes: 3 additions & 1 deletion dsk/src/bin/hello.s
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ _start:
mov rsi, msg ; addr of string
mov rdx, 14 ; size of string
int 0x80
jmp _start
mov rax, 1 ; syscall number for EXIT
mov rdi, 0 ; no error
int 0x80
6 changes: 4 additions & 2 deletions dsk/src/bin/sleep.s
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
[bits 64]
_start:
mov rax, 9 ; syscall number for SLEEP
mov rdi, __float64__(1.0) ; time to sleep in seconds
mov rdi, __float64__(5.0) ; time to sleep in seconds
mov rsi, 0
mov rdx, 0
int 0x80
jmp _start
mov rax, 1 ; syscall number for EXIT
mov rdi, 0 ; no error
int 0x80
3 changes: 2 additions & 1 deletion src/api/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,8 @@ pub fn reopen(path: &str, handle: usize) -> Result<usize, ()> {
};
if let Some(old_handle) = res {
syscall::dup(old_handle, handle);
return Ok(old_handle);
syscall::close(old_handle);
return Ok(handle);
}
Err(())
}
Expand Down
17 changes: 0 additions & 17 deletions src/api/regex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,6 @@ use alloc::vec::Vec;
use core::convert::From;
use core::ops::RangeBounds;

// TODO: Remove this when tests are done
const DEBUG: bool = false;
macro_rules! debug {
($($arg:tt)*) => ({
if DEBUG {
println!("{}", format_args!($($arg)*));
}
});
}

// See "A Regular Expression Matcher" by Rob Pike and Brian Kernighan (2007)

#[derive(Debug)]
Expand Down Expand Up @@ -72,7 +62,6 @@ pub struct Regex(String);

impl Regex {
pub fn new(re: &str) -> Self {
debug!("debug: Regex::new({:?})", re);
Self(re.to_string())
}
pub fn is_match(&self, text: &str) -> bool {
Expand All @@ -92,7 +81,6 @@ impl Regex {
}

fn is_match(re: &[char], text: &[char], start: &mut usize, end: &mut usize) -> bool {
debug!("debug: is_match({:?}, {:?})", re, text);
if re.len() == 0 {
return true;
}
Expand All @@ -116,7 +104,6 @@ fn is_match(re: &[char], text: &[char], start: &mut usize, end: &mut usize) -> b
}

fn is_match_here(re: &[char], text: &[char], end: &mut usize) -> bool {
debug!("debug: is_match_here({:?}, {:?})", re, text);
if re.len() == 0 {
return true;
}
Expand Down Expand Up @@ -148,22 +135,18 @@ fn is_match_here(re: &[char], text: &[char], end: &mut usize) -> bool {
}

fn is_match_star(lazy: bool, mc: MetaChar, re: &[char], text: &[char], end: &mut usize) -> bool {
debug!("debug: is_match_star({:?}, {:?}, {:?}", mc, re, text);
is_match_char(lazy, mc, re, text, .., end)
}

fn is_match_plus(lazy: bool, mc: MetaChar, re: &[char], text: &[char], end: &mut usize) -> bool {
debug!("debug: is_match_plus({:?}, {:?}, {:?}", mc, re, text);
is_match_char(lazy, mc, re, text, 1.., end)
}

fn is_match_ques(lazy: bool, mc: MetaChar, re: &[char], text: &[char], end: &mut usize) -> bool {
debug!("debug: is_match_ques({:?}, {:?}, {:?}", mc, re, text);
is_match_char(lazy, mc, re, text, ..2, end)
}

fn is_match_char<T: RangeBounds<usize>>(lazy: bool, mc: MetaChar, re: &[char], text: &[char], range: T, end: &mut usize) -> bool {
debug!("debug: is_match_char({:?}, {:?}, {:?}", mc, re, text);
let mut i = 0;
let n = text.len();

Expand Down
4 changes: 4 additions & 0 deletions src/api/syscall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ use crate::syscall;
use crate::sys::syscall::number::*;
use crate::sys::fs::FileStat;

pub fn exit(code: usize) -> usize {
unsafe { syscall!(EXIT, code as u64) }
}

pub fn sleep(seconds: f64) {
unsafe { syscall!(SLEEP, seconds.to_bits()) };
}
Expand Down
6 changes: 3 additions & 3 deletions src/bin/hello.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fn panic(_info: &PanicInfo) -> ! {

#[no_mangle]
pub unsafe extern "sysv64" fn _start() -> ! {
loop {
syscall::write(1, b"Hello, World!\n");
}
syscall::write(1, b"Hello, World!\n");
syscall::exit(0);
loop {}
}
6 changes: 3 additions & 3 deletions src/bin/sleep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fn panic(_info: &PanicInfo) -> ! {

#[no_mangle]
pub unsafe extern "sysv64" fn _start() -> ! {
loop {
syscall::sleep(1.0);
}
syscall::sleep(5.0);
syscall::exit(0);
loop {}
}
40 changes: 40 additions & 0 deletions src/sys/allocator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,46 @@ pub fn init_heap(mapper: &mut impl Mapper<Size4KiB>, frame_allocator: &mut impl
Ok(())
}

pub fn alloc_pages(addr: u64, size: u64) {
let mut mapper = unsafe { sys::mem::mapper(VirtAddr::new(sys::mem::PHYS_MEM_OFFSET)) };
let mut frame_allocator = unsafe { sys::mem::BootInfoFrameAllocator::init(sys::mem::MEMORY_MAP.unwrap()) };
let flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE | PageTableFlags::USER_ACCESSIBLE;
let pages = {
let start_page = Page::containing_address(VirtAddr::new(addr));
let end_page = Page::containing_address(VirtAddr::new(addr + size));
Page::range_inclusive(start_page, end_page)
};
for page in pages {
let frame = frame_allocator.allocate_frame().unwrap();
unsafe {
if let Ok(mapping) = mapper.map_to(page, frame, flags, &mut frame_allocator) {
mapping.flush();
} else {
debug!("Could not map {:?}", page);
}
}
}
}

use x86_64::structures::paging::page::PageRangeInclusive;

// TODO: Replace `free` by `dealloc`
pub fn free_pages(addr: u64, size: u64) {
let mut mapper = unsafe { sys::mem::mapper(VirtAddr::new(sys::mem::PHYS_MEM_OFFSET)) };
let pages: PageRangeInclusive<Size4KiB> = {
let start_page = Page::containing_address(VirtAddr::new(addr));
let end_page = Page::containing_address(VirtAddr::new(addr + size));
Page::range_inclusive(start_page, end_page)
};
for page in pages {
if let Ok((_frame, mapping)) = mapper.unmap(page) {
mapping.flush();
} else {
//debug!("Could not unmap {:?}", page);
}
}
}

#[derive(Clone)]
pub struct PhysBuf {
buf: Arc<Mutex<Vec<u8>>>,
Expand Down
64 changes: 26 additions & 38 deletions src/sys/idt.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use crate::sys;
use crate::sys::process::Registers;

use lazy_static::lazy_static;
use spin::Mutex;
use x86_64::instructions::interrupts;
use x86_64::instructions::port::Port;
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode};
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame, InterruptStackFrameValue, PageFaultErrorCode};

const PIC1: u16 = 0x21;
const PIC2: u16 = 0xA1;
Expand Down Expand Up @@ -116,36 +118,14 @@ extern "x86-interrupt" fn segment_not_present_handler(stack_frame: InterruptStac
panic!("EXCEPTION: SEGMENT NOT PRESENT\n{:#?}", stack_frame);
}

// See: https://github.com/xfoxfu/rust-xos/blob/8a07a69ef/kernel/src/interrupts/handlers.rs#L92
#[repr(align(8), C)]
#[derive(Debug, Clone, Default)]
pub struct Registers {
r15: usize,
r14: usize,
r13: usize,
r12: usize,
r11: usize,
r10: usize,
r9: usize,
r8: usize,
rdi: usize,
rsi: usize,
rdx: usize,
rcx: usize,
rbx: usize,
rax: usize,
rbp: usize,
}

// See: https://github.com/xfoxfu/rust-xos/blob/8a07a69ef/kernel/src/interrupts/handlers.rs#L112
// Naked function wrapper saving all scratch registers to the stack
// See: https://os.phil-opp.com/returning-from-exceptions/#a-naked-wrapper-function
macro_rules! wrap {
($fn: ident => $w:ident) => {
#[naked]
pub unsafe extern "sysv64" fn $w() {
asm!(
"push rbp",
"push rax",
"push rbx",
"push rcx",
"push rdx",
"push rsi",
Expand All @@ -154,18 +134,10 @@ macro_rules! wrap {
"push r9",
"push r10",
"push r11",
"push r12",
"push r13",
"push r14",
"push r15",
"mov rsi, rsp", // Arg #2: register list
"mov rdi, rsp", // Arg #1: interupt frame
"add rdi, 15 * 8",
"add rdi, 9 * 8",
"call {}",
"pop r15",
"pop r14",
"pop r13",
"pop r12",
"pop r11",
"pop r10",
"pop r9",
Expand All @@ -174,9 +146,7 @@ macro_rules! wrap {
"pop rsi",
"pop rdx",
"pop rcx",
"pop rbx",
"pop rax",
"pop rbp",
"iretq",
sym $fn,
options(noreturn)
Expand All @@ -190,13 +160,31 @@ wrap!(syscall_handler => wrapped_syscall_handler);
// NOTE: We can't use "x86-interrupt" for syscall_handler because we need to
// return a result in the RAX register and it will be overwritten when the
// context of the caller is restored.
extern "sysv64" fn syscall_handler(_stack_frame: &mut InterruptStackFrame, regs: &mut Registers) {
extern "sysv64" fn syscall_handler(stack_frame: &mut InterruptStackFrame, regs: &mut Registers) {
// The registers order follow the System V ABI convention
let n = regs.rax;
let arg1 = regs.rdi;
let arg2 = regs.rsi;
let arg3 = regs.rdx;
regs.rax = sys::syscall::dispatcher(n, arg1, arg2, arg3);

if n == sys::syscall::number::SPAWN { // Backup CPU context
sys::process::set_stack_frame(stack_frame.clone());
sys::process::set_registers(regs.clone());
}

let res = sys::syscall::dispatcher(n, arg1, arg2, arg3);

if n == sys::syscall::number::EXIT { // Restore CPU context
let sf = sys::process::stack_frame();
unsafe {
//stack_frame.as_mut().write(sf);
core::ptr::write_volatile(stack_frame.as_mut().extract_inner() as *mut InterruptStackFrameValue, sf); // FIXME
core::ptr::write_volatile(regs, sys::process::registers());
}
}

regs.rax = res;

unsafe { sys::pic::PICS.lock().notify_end_of_interrupt(0x80) };
}

Expand Down
12 changes: 12 additions & 0 deletions src/sys/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,17 @@ macro_rules! printk {
});
}

#[macro_export]
macro_rules! debug {
($($arg:tt)*) => ({
let csi_color = $crate::api::console::Style::color("Yellow");
let csi_reset = $crate::api::console::Style::reset();
$crate::sys::console::print_fmt(format_args!("{}DEBUG: ", csi_color));
$crate::sys::console::print_fmt(format_args!($($arg)*));
$crate::sys::console::print_fmt(format_args!("{}\n", csi_reset));
});
}

#[macro_export]
macro_rules! log {
($($arg:tt)*) => ({
Expand All @@ -14,6 +25,7 @@ macro_rules! log {
let csi_reset = $crate::api::console::Style::reset();
$crate::sys::console::print_fmt(format_args!("{}[{:.6}]{} ", csi_color, uptime, csi_reset));
$crate::sys::console::print_fmt(format_args!($($arg)*));
// TODO: Add newline
}
});
}
Expand Down
Loading

0 comments on commit e75c287

Please sign in to comment.