mirror of
https://github.com/sgmarz/osblog.git
synced 2024-11-23 18:06:20 +04:00
Added syscalls and information to support syscalls.
This commit is contained in:
parent
9a26a90962
commit
f6d842b02b
@ -208,6 +208,7 @@ impl File {
|
||||
}
|
||||
// println!("DEBUG: Map 0x{:08x} to 0x{:08x} {:02x}", vaddr, paddr, bits);
|
||||
}
|
||||
my_proc.brk += 0x1000;
|
||||
}
|
||||
// This will map all of the program pages. Notice that in linker.lds in
|
||||
// userspace we set the entry point address to 0x2000_0000. This is the
|
||||
|
@ -402,6 +402,11 @@ impl Drop for Process {
|
||||
}
|
||||
dealloc(self.mmu_table as *mut u8);
|
||||
dealloc(self.frame as *mut u8);
|
||||
for i in self.data.pages.drain(..) {
|
||||
dealloc(i as *mut u8);
|
||||
}
|
||||
// Kernel processes don't have a program, instead the program is linked
|
||||
// directly in the kernel.
|
||||
if !self.program.is_null() {
|
||||
dealloc(self.program);
|
||||
}
|
||||
@ -425,6 +430,7 @@ pub struct ProcessData {
|
||||
pub environ: BTreeMap<String, String>,
|
||||
pub fdesc: BTreeMap<u16, FileDescriptor>,
|
||||
pub cwd: String,
|
||||
pub pages: VecDeque<usize>,
|
||||
}
|
||||
|
||||
// This is private data that we can query with system calls.
|
||||
@ -436,6 +442,7 @@ impl ProcessData {
|
||||
environ: BTreeMap::new(),
|
||||
fdesc: BTreeMap::new(),
|
||||
cwd: String::new(),
|
||||
pages: VecDeque::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ use crate::{block::block_op,
|
||||
fs,
|
||||
gpu,
|
||||
input::{Event, ABS_EVENTS, KEY_EVENTS},
|
||||
page::{map, virt_to_phys, EntryBits, Table, PAGE_SIZE},
|
||||
page::{map, virt_to_phys, EntryBits, Table, PAGE_SIZE, zalloc},
|
||||
process::{add_kernel_process_args, delete_process, get_by_pid, set_sleeping, set_waiting, PROCESS_LIST, PROCESS_LIST_MUTEX}};
|
||||
use alloc::{boxed::Box, string::String};
|
||||
|
||||
@ -125,6 +125,10 @@ pub unsafe fn do_syscall(mepc: usize, frame: *mut TrapFrame) -> usize {
|
||||
(*frame).regs[gp(Registers::A0)] = -1isize as usize;
|
||||
0
|
||||
}
|
||||
57 => {
|
||||
// #define SYS_close 57
|
||||
0
|
||||
}
|
||||
63 => {
|
||||
// Read system call
|
||||
// This is an asynchronous call. This will get the
|
||||
@ -174,19 +178,20 @@ pub unsafe fn do_syscall(mepc: usize, frame: *mut TrapFrame) -> usize {
|
||||
let mut buf = (*frame).regs[gp(Registers::A1)] as *const u8;
|
||||
let size = (*frame).regs[gp(Registers::A2)];
|
||||
let process = get_by_pid((*frame).pid as u16);
|
||||
if (*frame).satp >> 60 != 0 {
|
||||
let table = ((*process).mmu_table).as_mut().unwrap();
|
||||
let paddr = virt_to_phys(table, buf as usize);
|
||||
if let Some(bufaddr) = paddr {
|
||||
buf = bufaddr as *const u8;
|
||||
}
|
||||
else {
|
||||
(*frame).regs[gp(Registers::A0)] = -1isize as usize;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// if (*frame).satp >> 60 != 0 {
|
||||
// let table = ((*process).mmu_table).as_mut().unwrap();
|
||||
// let paddr = virt_to_phys(table, buf as usize);
|
||||
// if let Some(bufaddr) = paddr {
|
||||
// buf = bufaddr as *const u8;
|
||||
// }
|
||||
// else {
|
||||
// (*frame).regs[gp(Registers::A0)] = -1isize as usize;
|
||||
// return 0;
|
||||
// }
|
||||
// }
|
||||
if fd == 1 || fd == 2 {
|
||||
// stdout / stderr
|
||||
// println!("WRITE {}, 0x{:08x}, {}", fd, bu/f as usize, size);
|
||||
let mut iter = 0;
|
||||
for _ in 0..size {
|
||||
iter += 1;
|
||||
@ -194,7 +199,8 @@ pub unsafe fn do_syscall(mepc: usize, frame: *mut TrapFrame) -> usize {
|
||||
let table = ((*process).mmu_table).as_mut().unwrap();
|
||||
let paddr = virt_to_phys(table, buf as usize);
|
||||
if let Some(bufaddr) = paddr {
|
||||
buf = bufaddr as *const u8;
|
||||
let output = *(bufaddr as *const u8) as char;
|
||||
print!("{}", output);
|
||||
}
|
||||
else {
|
||||
(*frame).regs[gp(Registers::A0)] = -1isize as usize;
|
||||
@ -215,6 +221,12 @@ pub unsafe fn do_syscall(mepc: usize, frame: *mut TrapFrame) -> usize {
|
||||
(*frame).regs[gp(Registers::A0)] = -1isize as usize;
|
||||
0
|
||||
}
|
||||
// #define SYS_fstat 80
|
||||
80 => {
|
||||
// int fstat(int filedes, struct stat *buf)
|
||||
(*frame).regs[gp(Registers::A0)] = 0;
|
||||
0
|
||||
}
|
||||
172 => {
|
||||
// A0 = pid
|
||||
(*frame).regs[Registers::A0 as usize] = (*frame).pid;
|
||||
@ -236,8 +248,21 @@ pub unsafe fn do_syscall(mepc: usize, frame: *mut TrapFrame) -> usize {
|
||||
// #define SYS_brk 214
|
||||
// int brk(void *addr);
|
||||
let addr = (*frame).regs[gp(Registers::A0)];
|
||||
println!("BRK Addr = 0x{:08x}", addr);
|
||||
(*frame).regs[gp(Registers::A0)] = -1isize as usize;
|
||||
let process = get_by_pid((*frame).pid as u16).as_mut().unwrap();
|
||||
// println!("Break move from 0x{:08x} to 0x{:08x}", process.brk, addr);
|
||||
if addr > process.brk {
|
||||
if (*frame).satp >> 60 != 0 {
|
||||
let table = ((*process).mmu_table).as_mut().unwrap();
|
||||
let diff = (addr + PAGE_SIZE - process.brk) / PAGE_SIZE;
|
||||
for i in 0..diff {
|
||||
let new_addr = zalloc(1) as usize;
|
||||
process.data.pages.push_back(new_addr);
|
||||
map(table, process.brk + (i << 12), new_addr, EntryBits::UserReadWrite.val(), 0);
|
||||
}
|
||||
}
|
||||
process.brk = addr;
|
||||
}
|
||||
(*frame).regs[gp(Registers::A0)] = process.brk;
|
||||
0
|
||||
}
|
||||
// System calls 1000 and above are "special" system calls for our OS. I'll
|
||||
@ -393,11 +418,12 @@ fn exec_func(args: usize) {
|
||||
println!("Failed to launch process.");
|
||||
}
|
||||
else {
|
||||
let process = proc.ok().unwrap();
|
||||
// If we hold this lock, we can still be preempted, but the scheduler will
|
||||
// return control to us. This required us to use try_lock in the scheduler.
|
||||
PROCESS_LIST_MUTEX.sleep_lock();
|
||||
if let Some(mut proc_list) = PROCESS_LIST.take() {
|
||||
proc_list.push_back(proc.ok().unwrap());
|
||||
proc_list.push_back(process);
|
||||
PROCESS_LIST.replace(proc_list);
|
||||
}
|
||||
PROCESS_LIST_MUTEX.unlock();
|
||||
@ -412,14 +438,13 @@ fn exec_func(args: usize) {
|
||||
// #define SYS_faccessat 48
|
||||
// #define SYS_chdir 49
|
||||
// #define SYS_openat 56
|
||||
// #define SYS_close 57
|
||||
// #define SYS_getdents 61
|
||||
// #define SYS_lseek 62
|
||||
// #define SYS_read 63
|
||||
// #define SYS_pread 67
|
||||
// #define SYS_pwrite 68
|
||||
// #define SYS_fstatat 79
|
||||
// #define SYS_fstat 80
|
||||
|
||||
// #define SYS_kill 129
|
||||
// #define SYS_rt_sigaction 134
|
||||
// #define SYS_times 153
|
||||
|
@ -45,7 +45,7 @@ extern "C" fn m_trap(epc: usize,
|
||||
// We will use this to awaken our other CPUs so they can process
|
||||
// processes.
|
||||
println!("Machine software interrupt CPU #{}", hart);
|
||||
},
|
||||
}
|
||||
7 => {
|
||||
// This is the context-switch timer.
|
||||
// We would typically invoke the scheduler here to pick another
|
||||
@ -56,7 +56,7 @@ extern "C" fn m_trap(epc: usize,
|
||||
if new_frame != 0 {
|
||||
rust_switch_to_user(new_frame);
|
||||
}
|
||||
},
|
||||
}
|
||||
11 => {
|
||||
// Machine external (interrupt from Platform Interrupt Controller (PLIC))
|
||||
// println!("Machine external interrupt CPU#{}", hart);
|
||||
@ -65,10 +65,10 @@ extern "C" fn m_trap(epc: usize,
|
||||
// get an interrupt from a non-PLIC source. This is the main reason that the PLIC
|
||||
// hardwires the id 0 to 0, so that we can use it as an error case.
|
||||
plic::handle_interrupt();
|
||||
},
|
||||
}
|
||||
_ => {
|
||||
panic!("Unhandled async trap CPU#{} -> {}\n", hart, cause_num);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -85,7 +85,7 @@ extern "C" fn m_trap(epc: usize,
|
||||
let frame = schedule();
|
||||
schedule_next_context_switch(1);
|
||||
rust_switch_to_user(frame);
|
||||
},
|
||||
}
|
||||
3 => {
|
||||
// breakpoint
|
||||
println!("BKPT\n\n");
|
||||
@ -97,7 +97,7 @@ extern "C" fn m_trap(epc: usize,
|
||||
let frame = schedule();
|
||||
schedule_next_context_switch(1);
|
||||
rust_switch_to_user(frame);
|
||||
},
|
||||
}
|
||||
8 | 9 | 11 => unsafe {
|
||||
// Environment (system) call from User, Supervisor, and Machine modes
|
||||
// println!("E-call from User mode! CPU#{} -> 0x{:08x}", hart, epc);
|
||||
@ -110,7 +110,7 @@ extern "C" fn m_trap(epc: usize,
|
||||
schedule_next_context_switch(1);
|
||||
rust_switch_to_user(frame);
|
||||
}
|
||||
},
|
||||
}
|
||||
// Page faults
|
||||
12 => unsafe {
|
||||
// Instruction page fault
|
||||
@ -119,7 +119,7 @@ extern "C" fn m_trap(epc: usize,
|
||||
let frame = schedule();
|
||||
schedule_next_context_switch(1);
|
||||
rust_switch_to_user(frame);
|
||||
},
|
||||
}
|
||||
13 => unsafe {
|
||||
// Load page fault
|
||||
println!("Load page fault CPU#{} -> 0x{:08x}: 0x{:08x}", hart, epc, tval);
|
||||
@ -127,7 +127,7 @@ extern "C" fn m_trap(epc: usize,
|
||||
let frame = schedule();
|
||||
schedule_next_context_switch(1);
|
||||
rust_switch_to_user(frame);
|
||||
},
|
||||
}
|
||||
15 => unsafe {
|
||||
// Store page fault
|
||||
println!("Store page fault CPU#{} -> 0x{:08x}: 0x{:08x}", hart, epc, tval);
|
||||
@ -135,13 +135,13 @@ extern "C" fn m_trap(epc: usize,
|
||||
let frame = schedule();
|
||||
schedule_next_context_switch(1);
|
||||
rust_switch_to_user(frame);
|
||||
},
|
||||
}
|
||||
_ => {
|
||||
panic!(
|
||||
"Unhandled sync trap {}. CPU#{} -> 0x{:08x}: 0x{:08x}\n",
|
||||
cause_num, hart, epc, tval
|
||||
);
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
// Finally, return the updated program counter
|
||||
|
Loading…
Reference in New Issue
Block a user