feature: x86_64 serial console
This commit is contained in:
@@ -5,7 +5,7 @@ use crate::arch::x86_64::{
|
||||
};
|
||||
use crate::config::{ConfigKey, CONFIG};
|
||||
use crate::debug;
|
||||
use crate::dev::{display::FramebufferInfo, pseudo, Device};
|
||||
use crate::dev::{display::FramebufferInfo, irq::IntSource, pseudo, Device};
|
||||
use crate::font;
|
||||
use crate::fs::{devfs::{self, CharDeviceType}, sysfs};
|
||||
use crate::mem::{
|
||||
@@ -93,6 +93,9 @@ extern "C" fn __x86_64_bsp_main(mb_checksum: u32, mb_info_ptr: u32) -> ! {
|
||||
phys_base: fb_info.address as usize,
|
||||
virt_base: virt,
|
||||
});
|
||||
unsafe {
|
||||
x86_64::COM1.init_irqs();
|
||||
}
|
||||
font::init();
|
||||
debug::set_display(&x86_64::DISPLAY);
|
||||
syscall::init();
|
||||
|
||||
@@ -100,6 +100,7 @@ impl IntController for I8259 {
|
||||
let irq_number = ic.token();
|
||||
assert!(irq_number > 0);
|
||||
|
||||
// Clear irq
|
||||
if irq_number > 8 {
|
||||
self.cmd_b.write(0x20);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,25 @@ __x86_64_irq_\no:
|
||||
mov %rsp, %rdi
|
||||
call __x86_64_irq_handler
|
||||
|
||||
jmp .
|
||||
pop %r15
|
||||
pop %r14
|
||||
pop %r13
|
||||
pop %r12
|
||||
pop %r11
|
||||
pop %r10
|
||||
pop %r9
|
||||
pop %r8
|
||||
|
||||
pop %rdi
|
||||
pop %rsi
|
||||
pop %rbp
|
||||
pop %rbx
|
||||
pop %rdx
|
||||
pop %rcx
|
||||
pop %rax
|
||||
|
||||
add $16, %rsp
|
||||
iretq
|
||||
.endm
|
||||
|
||||
.section .text
|
||||
@@ -49,10 +67,6 @@ __x86_64_irq_0:
|
||||
push %r14
|
||||
push %r15
|
||||
|
||||
mov $0x3F8, %dx
|
||||
mov $'T', %al
|
||||
outb %al, %dx
|
||||
|
||||
mov $0x20, %al
|
||||
mov $0x20, %dx
|
||||
outb %al, %dx
|
||||
|
||||
@@ -5,6 +5,7 @@ mod uart;
|
||||
use uart::Uart;
|
||||
mod intc;
|
||||
use intc::I8259;
|
||||
pub use intc::IrqNumber;
|
||||
|
||||
mod io;
|
||||
pub(self) use io::PortIo;
|
||||
@@ -54,6 +55,6 @@ pub fn console() -> &'static impl SerialDevice {
|
||||
&COM1
|
||||
}
|
||||
|
||||
static COM1: Uart = unsafe { Uart::new(0x3F8) };
|
||||
static INTC: I8259 = I8259::new();
|
||||
static COM1: Uart = unsafe { Uart::new(0x3F8, IrqNumber::new(4)) };
|
||||
pub(self) static INTC: I8259 = I8259::new();
|
||||
pub(self) static DISPLAY: StaticFramebuffer = StaticFramebuffer::uninit();
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
use crate::arch::x86_64::PortIo;
|
||||
use libsys::error::Errno;
|
||||
use crate::arch::x86_64::{self, IrqNumber, PortIo};
|
||||
use crate::dev::{
|
||||
tty::{CharRing, TtyDevice},
|
||||
irq::{IntController, IntSource},
|
||||
serial::SerialDevice,
|
||||
tty::{CharRing, TtyDevice},
|
||||
Device,
|
||||
};
|
||||
use libsys::error::Errno;
|
||||
|
||||
#[derive(TtyCharDevice)]
|
||||
pub(super) struct Uart {
|
||||
dr: PortIo<u8>,
|
||||
ring: CharRing<16>
|
||||
ier: PortIo<u8>,
|
||||
isr: PortIo<u8>,
|
||||
ring: CharRing<16>,
|
||||
irq: IrqNumber,
|
||||
}
|
||||
|
||||
impl Device for Uart {
|
||||
@@ -29,6 +32,24 @@ impl TtyDevice<16> for Uart {
|
||||
}
|
||||
}
|
||||
|
||||
impl IntSource for Uart {
|
||||
fn handle_irq(&self) -> Result<(), Errno> {
|
||||
if self.isr.read() != 0 {
|
||||
self.recv_byte(self.dr.read());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn init_irqs(&'static self) -> Result<(), Errno> {
|
||||
// TODO shared IRQs between COM# ports
|
||||
x86_64::INTC.register_handler(self.irq, self)?;
|
||||
self.ier.write((1 << 0));
|
||||
x86_64::INTC.enable_irq(self.irq)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl SerialDevice for Uart {
|
||||
fn send(&self, byte: u8) -> Result<(), Errno> {
|
||||
self.dr.write(byte);
|
||||
@@ -41,10 +62,13 @@ impl SerialDevice for Uart {
|
||||
}
|
||||
|
||||
impl Uart {
|
||||
pub const unsafe fn new(base: u16) -> Self {
|
||||
pub const unsafe fn new(base: u16, irq: IrqNumber) -> Self {
|
||||
Self {
|
||||
dr: PortIo::new(base),
|
||||
ring: CharRing::new()
|
||||
ier: PortIo::new(base + 1),
|
||||
isr: PortIo::new(base + 2),
|
||||
ring: CharRing::new(),
|
||||
irq,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,7 +229,6 @@ impl Space for SpaceImpl {
|
||||
);
|
||||
Err(Errno::AlreadyExists)
|
||||
} else {
|
||||
debugln!("write_last_level {:#x}, {:#x?}", virt, entry);
|
||||
l2_table[l3i] = entry;
|
||||
unsafe {
|
||||
core::arch::asm!("invlpg ({})", in(reg) virt, options(att_syntax));
|
||||
|
||||
@@ -137,6 +137,7 @@ pub trait Space {
|
||||
/// Creates a new virtual -> physical memory mapping. Will fail if one is
|
||||
/// already associated with given virtual address.
|
||||
fn map(&mut self, virt: usize, phys: usize, attrs: MapAttributes) -> Result<(), Errno> {
|
||||
#[cfg(feature = "verbose")]
|
||||
debugln!("Map {:#x} -> {:#x}, {:?}", virt, phys, attrs);
|
||||
unsafe {
|
||||
self.write_last_level(
|
||||
|
||||
+26
-1
@@ -69,7 +69,32 @@ impl Wait {
|
||||
|
||||
/// Interrupt wait pending on the channel
|
||||
pub fn abort(&self, tid: Tid, enqueue: bool) {
|
||||
todo!();
|
||||
let mut queue = self.queue.lock();
|
||||
let mut tick_lock = TICK_LIST.lock();
|
||||
let mut cursor = tick_lock.cursor_front_mut();
|
||||
while let Some(item) = cursor.current() {
|
||||
if tid == item.tid {
|
||||
cursor.remove_current();
|
||||
break;
|
||||
} else {
|
||||
cursor.move_next();
|
||||
}
|
||||
}
|
||||
|
||||
let mut cursor = queue.cursor_front_mut();
|
||||
while let Some(item) = cursor.current() {
|
||||
if tid == *item {
|
||||
cursor.remove_current();
|
||||
let thread = Thread::get(tid).unwrap();
|
||||
thread.set_wait_status(WaitStatus::Interrupted);
|
||||
if enqueue {
|
||||
SCHED.enqueue(tid);
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
cursor.move_next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn wakeup_some(&self, mut limit: usize) -> usize {
|
||||
|
||||
+306
-307
@@ -1,16 +1,17 @@
|
||||
//! System call implementation
|
||||
|
||||
// use crate::arch::{machine, platform::exception::ExceptionFrame};
|
||||
use crate::arch::platform::ForkFrame;
|
||||
use crate::arch::{machine, platform::ForkFrame};
|
||||
use crate::debug::Level;
|
||||
// use crate::dev::timer::TimestampSource;
|
||||
use crate::fs::create_filesystem;
|
||||
use crate::mem::{
|
||||
phys::PageUsage,
|
||||
virt::table::{Space, MapAttributes},
|
||||
virt::table::{MapAttributes, Space},
|
||||
};
|
||||
use crate::proc::{self, elf, wait, Process, ProcessIo, Thread};
|
||||
use core::mem::size_of;
|
||||
use core::ops::DerefMut;
|
||||
use core::time::Duration;
|
||||
use libsys::{
|
||||
abi::SystemCall,
|
||||
debug::TraceLevel,
|
||||
@@ -77,132 +78,132 @@ fn _syscall(num: SystemCall, args: &[usize]) -> Result<usize, Errno> {
|
||||
|
||||
io.file(fd)?.borrow_mut().write(buf)
|
||||
}
|
||||
// SystemCall::Open => {
|
||||
// let at_fd = FileDescriptor::from_i32(args[0] as i32)?;
|
||||
// let path = arg::str_ref(args[1], args[2])?;
|
||||
// let mode = FileMode::from_bits(args[3] as u32).ok_or(Errno::InvalidArgument)?;
|
||||
// let opts = OpenFlags::from_bits(args[4] as u32).ok_or(Errno::InvalidArgument)?;
|
||||
//
|
||||
// let proc = Process::current();
|
||||
// let mut io = proc.io.lock();
|
||||
//
|
||||
// let at = if let Some(fd) = at_fd {
|
||||
// io.file(fd)?.borrow().node()
|
||||
// } else {
|
||||
// None
|
||||
// };
|
||||
//
|
||||
// let file = io.ioctx().open(at, path, mode, opts)?;
|
||||
// Ok(u32::from(io.place_file(file)?) as usize)
|
||||
// }
|
||||
// SystemCall::Close => {
|
||||
// let proc = Process::current();
|
||||
// let mut io = proc.io.lock();
|
||||
// let fd = FileDescriptor::from(args[0] as u32);
|
||||
//
|
||||
// io.close_file(fd)?;
|
||||
// Ok(0)
|
||||
// }
|
||||
// SystemCall::FileStatus => {
|
||||
// let at_fd = FileDescriptor::from_i32(args[0] as i32)?;
|
||||
// let filename = arg::str_ref(args[1], args[2])?;
|
||||
// let buf = arg::struct_mut::<Stat>(args[3])?;
|
||||
// let flags = args[4] as u32;
|
||||
//
|
||||
// let proc = Process::current();
|
||||
// let mut io = proc.io.lock();
|
||||
// let stat =
|
||||
// find_at_node(&mut io, at_fd, filename, flags & AT_EMPTY_PATH != 0)?.stat()?;
|
||||
// *buf = stat;
|
||||
// Ok(0)
|
||||
// }
|
||||
// SystemCall::Ioctl => {
|
||||
// let fd = FileDescriptor::from(args[0] as u32);
|
||||
// let cmd = IoctlCmd::try_from(args[1] as u32)?;
|
||||
//
|
||||
// let proc = Process::current();
|
||||
// let mut io = proc.io.lock();
|
||||
//
|
||||
// let node = io.file(fd)?.borrow().node().ok_or(Errno::InvalidFile)?;
|
||||
// node.ioctl(cmd, args[2], args[3])
|
||||
// }
|
||||
// SystemCall::Select => {
|
||||
// let rfds = arg::option_struct_mut::<FdSet>(args[0])?;
|
||||
// let wfds = arg::option_struct_mut::<FdSet>(args[1])?;
|
||||
// let timeout = if args[2] == 0 {
|
||||
// None
|
||||
// } else {
|
||||
// Some(Duration::from_nanos(args[2] as u64))
|
||||
// };
|
||||
//
|
||||
// wait::select(Thread::current(), rfds, wfds, timeout)
|
||||
// }
|
||||
// SystemCall::Access => {
|
||||
// let at_fd = FileDescriptor::from_i32(args[0] as i32)?;
|
||||
// let path = arg::str_ref(args[1], args[2])?;
|
||||
// let mode = AccessMode::from_bits(args[3] as u32).ok_or(Errno::InvalidArgument)?;
|
||||
// let flags = args[4] as u32;
|
||||
//
|
||||
// let proc = Process::current();
|
||||
// let mut io = proc.io.lock();
|
||||
//
|
||||
// find_at_node(&mut io, at_fd, path, flags & AT_EMPTY_PATH != 0)?
|
||||
// .check_access(io.ioctx(), mode)?;
|
||||
// Ok(0)
|
||||
// }
|
||||
// SystemCall::ReadDirectory => {
|
||||
// let proc = Process::current();
|
||||
// let fd = FileDescriptor::from(args[0] as u32);
|
||||
// let mut io = proc.io.lock();
|
||||
// let buf = arg::struct_buf_mut::<DirectoryEntry>(args[1], args[2])?;
|
||||
//
|
||||
// io.file(fd)?.borrow_mut().readdir(buf)
|
||||
// }
|
||||
// SystemCall::GetUserId => {
|
||||
// let proc = Process::current();
|
||||
// let uid = proc.io.lock().uid();
|
||||
// Ok(u32::from(uid) as usize)
|
||||
// }
|
||||
// SystemCall::GetGroupId => {
|
||||
// let proc = Process::current();
|
||||
// let gid = proc.io.lock().gid();
|
||||
// Ok(u32::from(gid) as usize)
|
||||
// }
|
||||
// SystemCall::DuplicateFd => {
|
||||
// let src = FileDescriptor::from(args[0] as u32);
|
||||
// let dst = FileDescriptor::from_i32(args[1] as i32)?;
|
||||
//
|
||||
// let proc = Process::current();
|
||||
// let mut io = proc.io.lock();
|
||||
//
|
||||
// let res = io.duplicate_file(src, dst)?;
|
||||
//
|
||||
// Ok(u32::from(res) as usize)
|
||||
// }
|
||||
// SystemCall::SetUserId => {
|
||||
// let uid = UserId::from(args[0] as u32);
|
||||
// let proc = Process::current();
|
||||
// proc.io.lock().set_uid(uid)?;
|
||||
// Ok(0)
|
||||
// }
|
||||
// SystemCall::SetGroupId => {
|
||||
// let gid = GroupId::from(args[0] as u32);
|
||||
// let proc = Process::current();
|
||||
// proc.io.lock().set_gid(gid)?;
|
||||
// Ok(0)
|
||||
// }
|
||||
// SystemCall::SetCurrentDirectory => {
|
||||
// let path = arg::str_ref(args[0], args[1])?;
|
||||
// let proc = Process::current();
|
||||
// proc.io.lock().ioctx().chdir(path)?;
|
||||
// Ok(0)
|
||||
// }
|
||||
// SystemCall::GetCurrentDirectory => {
|
||||
// todo!()
|
||||
// }
|
||||
// SystemCall::Seek => {
|
||||
// todo!()
|
||||
// }
|
||||
SystemCall::Open => {
|
||||
let at_fd = FileDescriptor::from_i32(args[0] as i32)?;
|
||||
let path = arg::str_ref(args[1], args[2])?;
|
||||
let mode = FileMode::from_bits(args[3] as u32).ok_or(Errno::InvalidArgument)?;
|
||||
let opts = OpenFlags::from_bits(args[4] as u32).ok_or(Errno::InvalidArgument)?;
|
||||
|
||||
let proc = Process::current();
|
||||
let mut io = proc.io.lock();
|
||||
|
||||
let at = if let Some(fd) = at_fd {
|
||||
io.file(fd)?.borrow().node()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let file = io.ioctx().open(at, path, mode, opts)?;
|
||||
Ok(u32::from(io.place_file(file)?) as usize)
|
||||
}
|
||||
SystemCall::Close => {
|
||||
let proc = Process::current();
|
||||
let mut io = proc.io.lock();
|
||||
let fd = FileDescriptor::from(args[0] as u32);
|
||||
|
||||
io.close_file(fd)?;
|
||||
Ok(0)
|
||||
}
|
||||
SystemCall::FileStatus => {
|
||||
let at_fd = FileDescriptor::from_i32(args[0] as i32)?;
|
||||
let filename = arg::str_ref(args[1], args[2])?;
|
||||
let buf = arg::struct_mut::<Stat>(args[3])?;
|
||||
let flags = args[4] as u32;
|
||||
|
||||
let proc = Process::current();
|
||||
let mut io = proc.io.lock();
|
||||
let stat =
|
||||
find_at_node(&mut io, at_fd, filename, flags & AT_EMPTY_PATH != 0)?.stat()?;
|
||||
*buf = stat;
|
||||
Ok(0)
|
||||
}
|
||||
SystemCall::Ioctl => {
|
||||
let fd = FileDescriptor::from(args[0] as u32);
|
||||
let cmd = IoctlCmd::try_from(args[1] as u32)?;
|
||||
|
||||
let proc = Process::current();
|
||||
let mut io = proc.io.lock();
|
||||
|
||||
let node = io.file(fd)?.borrow().node().ok_or(Errno::InvalidFile)?;
|
||||
node.ioctl(cmd, args[2], args[3])
|
||||
}
|
||||
SystemCall::Select => {
|
||||
let rfds = arg::option_struct_mut::<FdSet>(args[0])?;
|
||||
let wfds = arg::option_struct_mut::<FdSet>(args[1])?;
|
||||
let timeout = if args[2] == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(Duration::from_nanos(args[2] as u64))
|
||||
};
|
||||
|
||||
wait::select(Thread::current(), rfds, wfds, timeout)
|
||||
}
|
||||
SystemCall::Access => {
|
||||
let at_fd = FileDescriptor::from_i32(args[0] as i32)?;
|
||||
let path = arg::str_ref(args[1], args[2])?;
|
||||
let mode = AccessMode::from_bits(args[3] as u32).ok_or(Errno::InvalidArgument)?;
|
||||
let flags = args[4] as u32;
|
||||
|
||||
let proc = Process::current();
|
||||
let mut io = proc.io.lock();
|
||||
|
||||
find_at_node(&mut io, at_fd, path, flags & AT_EMPTY_PATH != 0)?
|
||||
.check_access(io.ioctx(), mode)?;
|
||||
Ok(0)
|
||||
}
|
||||
SystemCall::ReadDirectory => {
|
||||
let proc = Process::current();
|
||||
let fd = FileDescriptor::from(args[0] as u32);
|
||||
let mut io = proc.io.lock();
|
||||
let buf = arg::struct_buf_mut::<DirectoryEntry>(args[1], args[2])?;
|
||||
|
||||
io.file(fd)?.borrow_mut().readdir(buf)
|
||||
}
|
||||
SystemCall::GetUserId => {
|
||||
let proc = Process::current();
|
||||
let uid = proc.io.lock().uid();
|
||||
Ok(u32::from(uid) as usize)
|
||||
}
|
||||
SystemCall::GetGroupId => {
|
||||
let proc = Process::current();
|
||||
let gid = proc.io.lock().gid();
|
||||
Ok(u32::from(gid) as usize)
|
||||
}
|
||||
SystemCall::DuplicateFd => {
|
||||
let src = FileDescriptor::from(args[0] as u32);
|
||||
let dst = FileDescriptor::from_i32(args[1] as i32)?;
|
||||
|
||||
let proc = Process::current();
|
||||
let mut io = proc.io.lock();
|
||||
|
||||
let res = io.duplicate_file(src, dst)?;
|
||||
|
||||
Ok(u32::from(res) as usize)
|
||||
}
|
||||
SystemCall::SetUserId => {
|
||||
let uid = UserId::from(args[0] as u32);
|
||||
let proc = Process::current();
|
||||
proc.io.lock().set_uid(uid)?;
|
||||
Ok(0)
|
||||
}
|
||||
SystemCall::SetGroupId => {
|
||||
let gid = GroupId::from(args[0] as u32);
|
||||
let proc = Process::current();
|
||||
proc.io.lock().set_gid(gid)?;
|
||||
Ok(0)
|
||||
}
|
||||
SystemCall::SetCurrentDirectory => {
|
||||
let path = arg::str_ref(args[0], args[1])?;
|
||||
let proc = Process::current();
|
||||
proc.io.lock().ioctx().chdir(path)?;
|
||||
Ok(0)
|
||||
}
|
||||
SystemCall::GetCurrentDirectory => {
|
||||
todo!()
|
||||
}
|
||||
SystemCall::Seek => {
|
||||
todo!()
|
||||
}
|
||||
SystemCall::MapMemory => {
|
||||
let len = args[1];
|
||||
if len == 0 || (len & 0xFFF) != 0 {
|
||||
@@ -211,8 +212,7 @@ fn _syscall(num: SystemCall, args: &[usize]) -> Result<usize, Errno> {
|
||||
let acc = MemoryAccess::from_bits(args[2] as u32).ok_or(Errno::InvalidArgument)?;
|
||||
let _flags = MemoryAccess::from_bits(args[3] as u32).ok_or(Errno::InvalidArgument)?;
|
||||
|
||||
let mut attrs =
|
||||
MapAttributes::SHARE_OUTER | MapAttributes::USER_READ;
|
||||
let mut attrs = MapAttributes::SHARE_OUTER | MapAttributes::USER_READ;
|
||||
if !acc.contains(MemoryAccess::READ) {
|
||||
return Err(Errno::NotImplemented);
|
||||
}
|
||||
@@ -237,186 +237,185 @@ fn _syscall(num: SystemCall, args: &[usize]) -> Result<usize, Errno> {
|
||||
space.allocate(0x100000000, 0xF00000000, len / 4096, attrs, usage)
|
||||
})
|
||||
}
|
||||
// SystemCall::UnmapMemory => {
|
||||
// let addr = args[0];
|
||||
// let len = args[1];
|
||||
//
|
||||
// if addr == 0 || len == 0 || addr & 0xFFF != 0 || len & 0xFFF != 0 {
|
||||
// return Err(Errno::InvalidArgument);
|
||||
// }
|
||||
//
|
||||
// let proc = Process::current();
|
||||
// proc.manipulate_space(move |space| space.free(addr, len / 4096))?;
|
||||
// Ok(0)
|
||||
// }
|
||||
//
|
||||
// // Process
|
||||
// SystemCall::Clone => {
|
||||
// let entry = args[0];
|
||||
// let stack = args[1];
|
||||
// let arg = args[2];
|
||||
//
|
||||
// Process::current()
|
||||
// .new_user_thread(entry, stack, arg)
|
||||
// .map(|e| u32::from(e) as usize)
|
||||
// }
|
||||
// SystemCall::Exec => {
|
||||
// let filename = arg::str_ref(args[0], args[1])?;
|
||||
// let argv = arg::struct_buf_ref::<&str>(args[2], args[3])?;
|
||||
// // Validate each argument as well
|
||||
// for item in argv.iter() {
|
||||
// arg::validate_ptr(item.as_ptr() as usize, item.len(), false)?;
|
||||
// }
|
||||
// let node = {
|
||||
// let proc = Process::current();
|
||||
// let mut io = proc.io.lock();
|
||||
// // TODO argv, envp array passing ABI?
|
||||
// let node = io.ioctx().find(None, filename, true)?;
|
||||
// drop(io);
|
||||
// node
|
||||
// };
|
||||
// let file = node.open(OpenFlags::O_RDONLY)?;
|
||||
// Process::execve(move |space| elf::load_elf(space, file), argv).unwrap();
|
||||
// panic!();
|
||||
// }
|
||||
SystemCall::Exit => {
|
||||
let status = ExitCode::from(args[0] as i32);
|
||||
let flags = args[1];
|
||||
SystemCall::UnmapMemory => {
|
||||
let addr = args[0];
|
||||
let len = args[1];
|
||||
|
||||
if flags & (1 << 0) != 0 {
|
||||
Process::exit_thread(Thread::current(), status);
|
||||
} else {
|
||||
Process::current().exit(status);
|
||||
}
|
||||
if addr == 0 || len == 0 || addr & 0xFFF != 0 || len & 0xFFF != 0 {
|
||||
return Err(Errno::InvalidArgument);
|
||||
}
|
||||
|
||||
unreachable!();
|
||||
let proc = Process::current();
|
||||
proc.manipulate_space(move |space| space.free(addr, len / 4096))?;
|
||||
Ok(0)
|
||||
}
|
||||
// // Process
|
||||
// SystemCall::Clone => {
|
||||
// let entry = args[0];
|
||||
// let stack = args[1];
|
||||
// let arg = args[2];
|
||||
|
||||
// Process::current()
|
||||
// .new_user_thread(entry, stack, arg)
|
||||
// .map(|e| u32::from(e) as usize)
|
||||
// }
|
||||
SystemCall::Exec => {
|
||||
let filename = arg::str_ref(args[0], args[1])?;
|
||||
let argv = arg::struct_buf_ref::<&str>(args[2], args[3])?;
|
||||
// Validate each argument as well
|
||||
for item in argv.iter() {
|
||||
arg::validate_ptr(item.as_ptr() as usize, item.len(), false)?;
|
||||
}
|
||||
let node = {
|
||||
let proc = Process::current();
|
||||
let mut io = proc.io.lock();
|
||||
// TODO argv, envp array passing ABI?
|
||||
let node = io.ioctx().find(None, filename, true)?;
|
||||
drop(io);
|
||||
node
|
||||
};
|
||||
let file = node.open(OpenFlags::O_RDONLY)?;
|
||||
Process::execve(move |space| elf::load_elf(space, file), argv).unwrap();
|
||||
panic!();
|
||||
}
|
||||
SystemCall::Exit => {
|
||||
let status = ExitCode::from(args[0] as i32);
|
||||
let flags = args[1];
|
||||
|
||||
if flags & (1 << 0) != 0 {
|
||||
Process::exit_thread(Thread::current(), status);
|
||||
} else {
|
||||
Process::current().exit(status);
|
||||
}
|
||||
|
||||
unreachable!();
|
||||
}
|
||||
SystemCall::WaitPid => {
|
||||
// TODO special "pid" values
|
||||
let pid = Pid::try_from(args[0] as u32)?;
|
||||
let status = arg::struct_mut::<i32>(args[1])?;
|
||||
|
||||
match Process::waitpid(pid) {
|
||||
Ok(exit) => {
|
||||
*status = i32::from(exit);
|
||||
Ok(0)
|
||||
}
|
||||
SystemCall::WaitPid => {
|
||||
// TODO special "pid" values
|
||||
let pid = Pid::try_from(args[0] as u32)?;
|
||||
let status = arg::struct_mut::<i32>(args[1])?;
|
||||
e => e.map(|e| i32::from(e) as usize),
|
||||
}
|
||||
}
|
||||
SystemCall::WaitTid => {
|
||||
let tid = Tid::from(args[0] as u32);
|
||||
|
||||
match Process::waitpid(pid) {
|
||||
Ok(exit) => {
|
||||
*status = i32::from(exit);
|
||||
Ok(0)
|
||||
}
|
||||
e => e.map(|e| i32::from(e) as usize),
|
||||
}
|
||||
match Thread::waittid(tid) {
|
||||
Ok(_) => Ok(0),
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
SystemCall::GetPid => Ok(u32::from(Process::current().id()) as usize),
|
||||
SystemCall::GetTid => Ok(u32::from(Thread::current().id()) as usize),
|
||||
SystemCall::Sleep => {
|
||||
let rem_buf = arg::option_buf_ref(args[1], size_of::<u64>() * 2)?;
|
||||
let mut rem = Duration::new(0, 0);
|
||||
let res = wait::sleep(Duration::from_nanos(args[0] as u64), &mut rem);
|
||||
if res == Err(Errno::Interrupt) {
|
||||
warnln!("Sleep interrupted, {:?} remaining", rem);
|
||||
if rem_buf.is_some() {
|
||||
todo!()
|
||||
}
|
||||
// SystemCall::WaitTid => {
|
||||
// let tid = Tid::from(args[0] as u32);
|
||||
//
|
||||
// match Thread::waittid(tid) {
|
||||
// Ok(_) => Ok(0),
|
||||
// _ => todo!(),
|
||||
// }
|
||||
// }
|
||||
// SystemCall::GetPid => Ok(u32::from(Process::current().id()) as usize),
|
||||
// SystemCall::GetTid => Ok(u32::from(Thread::current().id()) as usize),
|
||||
// SystemCall::Sleep => {
|
||||
// let rem_buf = arg::option_buf_ref(args[1], size_of::<u64>() * 2)?;
|
||||
// let mut rem = Duration::new(0, 0);
|
||||
// let res = wait::sleep(Duration::from_nanos(args[0] as u64), &mut rem);
|
||||
// if res == Err(Errno::Interrupt) {
|
||||
// warnln!("Sleep interrupted, {:?} remaining", rem);
|
||||
// if rem_buf.is_some() {
|
||||
// todo!()
|
||||
// }
|
||||
// }
|
||||
// res.map(|_| 0)
|
||||
// }
|
||||
// SystemCall::SetSignalEntry => {
|
||||
// Thread::current().set_signal_entry(args[0], args[1]);
|
||||
// Ok(0)
|
||||
// }
|
||||
// SystemCall::SignalReturn => {
|
||||
// Thread::current().return_from_signal();
|
||||
// unreachable!();
|
||||
// }
|
||||
// SystemCall::SendSignal => {
|
||||
// let target = SignalDestination::from(args[0] as isize);
|
||||
// let signal = Signal::try_from(args[1] as u32)?;
|
||||
//
|
||||
// match target {
|
||||
// SignalDestination::This => Process::current().set_signal(signal),
|
||||
// SignalDestination::Process(pid) => Process::get(pid)
|
||||
// .ok_or(Errno::DoesNotExist)?
|
||||
// .set_signal(signal),
|
||||
// _ => todo!(),
|
||||
// };
|
||||
// Ok(0)
|
||||
// }
|
||||
// SystemCall::Yield => {
|
||||
// proc::switch();
|
||||
// Ok(0)
|
||||
// }
|
||||
// SystemCall::GetSid => {
|
||||
// // TODO handle kernel processes here?
|
||||
// let pid = Pid::to_option(args[0] as u32);
|
||||
// let current = Process::current();
|
||||
// let proc = if let Some(pid) = pid {
|
||||
// let proc = Process::get(pid).ok_or(Errno::DoesNotExist)?;
|
||||
// if proc.sid() != current.sid() {
|
||||
// return Err(Errno::PermissionDenied);
|
||||
// }
|
||||
// proc
|
||||
// } else {
|
||||
// current
|
||||
// };
|
||||
//
|
||||
// Ok(u32::from(proc.sid()) as usize)
|
||||
// }
|
||||
// SystemCall::GetPgid => {
|
||||
// // TODO handle kernel processes here?
|
||||
// let pid = Pid::to_option(args[0] as u32);
|
||||
// let current = Process::current();
|
||||
// let proc = if let Some(pid) = pid {
|
||||
// Process::get(pid).ok_or(Errno::DoesNotExist)?
|
||||
// } else {
|
||||
// current
|
||||
// };
|
||||
//
|
||||
// Ok(u32::from(proc.pgid()) as usize)
|
||||
// }
|
||||
// SystemCall::GetPpid => Ok(u32::from(Process::current().ppid().unwrap()) as usize),
|
||||
// SystemCall::SetSid => {
|
||||
// let proc = Process::current();
|
||||
// let mut io = proc.io.lock();
|
||||
//
|
||||
// if let Some(_ctty) = io.ctty() {
|
||||
// todo!();
|
||||
// }
|
||||
//
|
||||
// let id = proc.id();
|
||||
// proc.set_sid(id);
|
||||
// Ok(u32::from(id) as usize)
|
||||
// }
|
||||
// SystemCall::SetPgid => {
|
||||
// let pid = Pid::to_option(args[0] as u32);
|
||||
// let pgid = Pid::to_option(args[1] as u32);
|
||||
//
|
||||
// let current = Process::current();
|
||||
// let proc = if let Some(_pid) = pid {
|
||||
// todo!()
|
||||
// } else {
|
||||
// current
|
||||
// };
|
||||
//
|
||||
// if let Some(_pgid) = pgid {
|
||||
// todo!();
|
||||
// } else {
|
||||
// proc.set_pgid(proc.id());
|
||||
// }
|
||||
//
|
||||
// Ok(u32::from(proc.pgid()) as usize)
|
||||
// }
|
||||
//
|
||||
// // System
|
||||
// SystemCall::GetCpuTime => {
|
||||
// let time = machine::local_timer().timestamp()?;
|
||||
// Ok(time.as_nanos() as usize)
|
||||
// }
|
||||
}
|
||||
res.map(|_| 0)
|
||||
}
|
||||
// SystemCall::SetSignalEntry => {
|
||||
// Thread::current().set_signal_entry(args[0], args[1]);
|
||||
// Ok(0)
|
||||
// }
|
||||
// SystemCall::SignalReturn => {
|
||||
// Thread::current().return_from_signal();
|
||||
// unreachable!();
|
||||
// }
|
||||
// SystemCall::SendSignal => {
|
||||
// let target = SignalDestination::from(args[0] as isize);
|
||||
// let signal = Signal::try_from(args[1] as u32)?;
|
||||
|
||||
// match target {
|
||||
// SignalDestination::This => Process::current().set_signal(signal),
|
||||
// SignalDestination::Process(pid) => Process::get(pid)
|
||||
// .ok_or(Errno::DoesNotExist)?
|
||||
// .set_signal(signal),
|
||||
// _ => todo!(),
|
||||
// };
|
||||
// Ok(0)
|
||||
// }
|
||||
SystemCall::Yield => {
|
||||
proc::switch();
|
||||
Ok(0)
|
||||
}
|
||||
SystemCall::GetSid => {
|
||||
// TODO handle kernel processes here?
|
||||
let pid = Pid::to_option(args[0] as u32);
|
||||
let current = Process::current();
|
||||
let proc = if let Some(pid) = pid {
|
||||
let proc = Process::get(pid).ok_or(Errno::DoesNotExist)?;
|
||||
if proc.sid() != current.sid() {
|
||||
return Err(Errno::PermissionDenied);
|
||||
}
|
||||
proc
|
||||
} else {
|
||||
current
|
||||
};
|
||||
|
||||
Ok(u32::from(proc.sid()) as usize)
|
||||
}
|
||||
SystemCall::GetPgid => {
|
||||
// TODO handle kernel processes here?
|
||||
let pid = Pid::to_option(args[0] as u32);
|
||||
let current = Process::current();
|
||||
let proc = if let Some(pid) = pid {
|
||||
Process::get(pid).ok_or(Errno::DoesNotExist)?
|
||||
} else {
|
||||
current
|
||||
};
|
||||
|
||||
Ok(u32::from(proc.pgid()) as usize)
|
||||
}
|
||||
SystemCall::GetPpid => Ok(u32::from(Process::current().ppid().unwrap()) as usize),
|
||||
SystemCall::SetSid => {
|
||||
let proc = Process::current();
|
||||
let mut io = proc.io.lock();
|
||||
|
||||
if let Some(_ctty) = io.ctty() {
|
||||
todo!();
|
||||
}
|
||||
|
||||
let id = proc.id();
|
||||
proc.set_sid(id);
|
||||
Ok(u32::from(id) as usize)
|
||||
}
|
||||
SystemCall::SetPgid => {
|
||||
let pid = Pid::to_option(args[0] as u32);
|
||||
let pgid = Pid::to_option(args[1] as u32);
|
||||
|
||||
let current = Process::current();
|
||||
let proc = if let Some(_pid) = pid {
|
||||
todo!()
|
||||
} else {
|
||||
current
|
||||
};
|
||||
|
||||
if let Some(_pgid) = pgid {
|
||||
todo!();
|
||||
} else {
|
||||
proc.set_pgid(proc.id());
|
||||
}
|
||||
|
||||
Ok(u32::from(proc.pgid()) as usize)
|
||||
}
|
||||
|
||||
// // System
|
||||
// SystemCall::GetCpuTime => {
|
||||
// let time = machine::local_timer().timestamp()?;
|
||||
// Ok(time.as_nanos() as usize)
|
||||
// }
|
||||
SystemCall::Mount => {
|
||||
let target = arg::str_ref(args[0], args[1])?;
|
||||
let options = arg::struct_ref::<MountOptions>(args[2])?;
|
||||
@@ -432,7 +431,7 @@ fn _syscall(num: SystemCall, args: &[usize]) -> Result<usize, Errno> {
|
||||
target_node.mount(root)?;
|
||||
|
||||
Ok(0)
|
||||
},
|
||||
}
|
||||
|
||||
// Debugging
|
||||
SystemCall::DebugTrace => {
|
||||
|
||||
Reference in New Issue
Block a user