Better MSR/CR interface for x86_64

This commit is contained in:
Mark Poliakov 2022-01-12 16:48:48 +02:00
parent 9126f8ac68
commit a799b71326
10 changed files with 631 additions and 444 deletions

View File

@ -1,40 +1,32 @@
use crate::arch::x86_64::{self, intc, gdt, idt};
use crate::arch::x86_64::{
self, gdt, idt, intc,
reg::{CR0, CR4},
syscall,
};
use crate::config::{ConfigKey, CONFIG};
use crate::debug;
use crate::dev::{display::FramebufferInfo, pseudo, Device};
use crate::font;
use crate::fs::{devfs, sysfs};
use crate::mem::{
self, heap,
phys::{self, MemoryRegion, PageUsage, ReservedRegion},
virt,
};
use crate::debug;
use crate::fs::{devfs, sysfs};
use crate::config::{ConfigKey, CONFIG};
use crate::dev::{pseudo, Device, display::FramebufferInfo};
use core::mem::MaybeUninit;
use crate::font;
use multiboot2::{BootInformation, MemoryArea};
use core::arch::{global_asm, asm};
use crate::proc;
use core::arch::{asm, global_asm};
use core::mem::MaybeUninit;
use multiboot2::{BootInformation, MemoryArea};
use tock_registers::interfaces::ReadWriteable;
static mut RESERVED_REGION_MB2: MaybeUninit<ReservedRegion> = MaybeUninit::uninit();
#[no_mangle]
extern "C" fn __x86_64_bsp_main(mb_checksum: u32, mb_info_ptr: u32) -> ! {
CR4.modify(CR4::OSXMMEXCPT::SET + CR4::OSFXSR::SET);
CR0.modify(CR0::EM::CLEAR + CR0::MP::SET);
unsafe {
// Enable SSE support
asm!(
r#"
mov %cr4, %rax
or $(1 << 9), %rax // FXSAVE, FXRSTOR
or $(1 << 10), %rax // OSXMMEXCPT
mov %rax, %cr4
mov %cr0, %rax
and $~(1 << 2), %rax // Disable EM
or $(1 << 1), %rax // Enable MP
mov %rax, %cr0
"#,
options(att_syntax)
);
// Setup a proper GDT
gdt::init();
idt::init(intc::map_isr_entries);
@ -90,15 +82,20 @@ extern "C" fn __x86_64_bsp_main(mb_checksum: u32, mb_info_ptr: u32) -> ! {
let fb_info = mb_info.framebuffer_tag().unwrap();
let virt = mem::virtualize(fb_info.address as usize);
debugln!("Framebuffer base: phys={:#x}, virt={:#x}", fb_info.address, virt);
debugln!(
"Framebuffer base: phys={:#x}, virt={:#x}",
fb_info.address,
virt
);
x86_64::DISPLAY.set_framebuffer(FramebufferInfo {
width: fb_info.width as usize,
height: fb_info.height as usize,
phys_base: fb_info.address as usize,
virt_base: virt
virt_base: virt,
});
font::init();
debug::set_display(&x86_64::DISPLAY);
syscall::init();
devfs::init();
sysfs::init();

View File

@ -0,0 +1,16 @@
use core::arch::asm;
#[inline(always)]
pub unsafe fn rdmsr(a: u32) -> u64 {
let mut eax: u32;
let mut edx: u32;
asm!("rdmsr", in("ecx") a, out("eax") eax, out("edx") edx);
(eax as u64) | ((edx as u64) << 32)
}
#[inline(always)]
pub unsafe fn wrmsr(a: u32, b: u64) {
let eax = b as u32;
let edx = (b >> 32) as u32;
asm!("wrmsr", in("ecx") a, in("eax") eax, in("edx") edx);
}

View File

@ -12,6 +12,9 @@ pub(self) use io::PortIo;
pub mod boot;
pub mod table;
pub mod context;
pub mod intrin;
pub mod reg;
pub(self) mod syscall;
pub(self) mod gdt;
pub(self) mod idt;
pub(self) mod exception;

View File

@ -0,0 +1,135 @@
macro_rules! wrap_msr {
($struct_name:ident, $name:ident, $address:expr, $fields:tt) => {
register_bitfields! {
u64,
pub $name $fields
}
pub struct $struct_name;
impl Readable for $struct_name {
type T = u64;
type R = $name::Register;
#[inline(always)]
fn get(&self) -> Self::T {
unsafe {
rdmsr($address)
}
}
}
impl Writeable for $struct_name {
type T = u64;
type R = $name::Register;
#[inline(always)]
fn set(&self, value: Self::T) {
unsafe {
wrmsr($address, value);
}
}
}
pub const $name: $struct_name = $struct_name;
}
}
use tock_registers::{
interfaces::{Readable, Writeable},
register_bitfields,
};
use core::arch::asm;
use crate::arch::x86_64::intrin::{rdmsr, wrmsr};
// CRn registers
register_bitfields! {
u64,
pub CR4 [
OSFXSR OFFSET(9) NUMBITS(1) [],
OSXMMEXCPT OFFSET(10) NUMBITS(1) []
]
}
register_bitfields! {
u64,
pub CR0 [
EM OFFSET(2) NUMBITS(1) [],
MP OFFSET(1) NUMBITS(1) []
]
}
pub struct Cr4;
pub struct Cr0;
impl Readable for Cr4 {
type T = u64;
type R = CR4::Register;
#[inline(always)]
fn get(&self) -> Self::T {
let mut res: u64;
unsafe {
asm!("mov %cr4, {}", out(reg) res, options(att_syntax))
}
res
}
}
impl Writeable for Cr4 {
type T = u64;
type R = CR4::Register;
#[inline(always)]
fn set(&self, value: Self::T) {
unsafe {
asm!("mov {}, %cr4", in(reg) value, options(att_syntax));
}
}
}
impl Readable for Cr0 {
type T = u64;
type R = CR0::Register;
#[inline(always)]
fn get(&self) -> Self::T {
let mut res: u64;
unsafe {
asm!("mov %cr0, {}", out(reg) res, options(att_syntax))
}
res
}
}
impl Writeable for Cr0 {
type T = u64;
type R = CR0::Register;
#[inline(always)]
fn set(&self, value: Self::T) {
unsafe {
asm!("mov {}, %cr0", in(reg) value, options(att_syntax));
}
}
}
pub const CR4: Cr4 = Cr4;
pub const CR0: Cr0 = Cr0;
wrap_msr!(MsrIa32Efer, MSR_IA32_EFER, 0xC0000080, [
SCE OFFSET(0) NUMBITS(1) [],
LME OFFSET(8) NUMBITS(1) [],
LMA OFFSET(10) NUMBITS(1) [],
NXE OFFSET(11) NUMBITS(1) []
]);
wrap_msr!(MsrIa32Lstar, MSR_IA32_LSTAR, 0xC0000082, [
VALUE OFFSET(0) NUMBITS(64) []
]);
wrap_msr!(MsrIa32Star, MSR_IA32_STAR, 0xC0000081, [
SYSCALL_CS_SS OFFSET(32) NUMBITS(8) [],
SYSRET_CS_SS OFFSET(48) NUMBITS(8) []
]);
wrap_msr!(MsrIa32Sfmask, MSR_IA32_SFMASK, 0xC0000084, [
IF OFFSET(9) NUMBITS(1) []
]);

View File

@ -0,0 +1,13 @@
use tock_registers::{
interfaces::{Readable, Writeable},
register_bitfields,
};
use crate::arch::x86_64::intrin::{rdmsr, wrmsr};
register_bitfields! {
u64,
pub MSR_IA32_EFER [
]
}
wrap_msr!(MSR_IA32_EFER, 0xC0000080);

View File

@ -0,0 +1,4 @@
.section .text
.global __x86_64_syscall_entry
__x86_64_syscall_entry:
jmp .

View File

@ -0,0 +1,17 @@
use crate::arch::x86_64::reg::{MSR_IA32_EFER, MSR_IA32_LSTAR, MSR_IA32_SFMASK, MSR_IA32_STAR};
use core::arch::global_asm;
use tock_registers::interfaces::{ReadWriteable, Writeable};
pub(super) fn init() {
extern "C" {
fn __x86_64_syscall_entry();
}
MSR_IA32_SFMASK.write(MSR_IA32_SFMASK::IF::SET);
MSR_IA32_LSTAR.set(__x86_64_syscall_entry as u64);
MSR_IA32_STAR
.write(MSR_IA32_STAR::SYSRET_CS_SS.val(0x1B - 8) + MSR_IA32_STAR::SYSCALL_CS_SS.val(0x08));
MSR_IA32_EFER.modify(MSR_IA32_EFER::SCE::SET);
}
global_asm!(include_str!("syscall.S"), options(att_syntax));

View File

@ -40,7 +40,7 @@ pub mod init;
pub mod mem;
pub mod proc;
pub mod sync;
// pub mod syscall;
pub mod syscall;
pub mod util;
#[panic_handler]

View File

@ -1,14 +1,14 @@
//! System call implementation
use crate::arch::{machine, platform::exception::ExceptionFrame};
use crate::debug::Level;
use crate::dev::timer::TimestampSource;
use crate::fs::create_filesystem;
use crate::mem::{phys::PageUsage, virt::MapAttributes};
// use crate::arch::{machine, platform::exception::ExceptionFrame};
// use crate::debug::Level;
// use crate::dev::timer::TimestampSource;
// use crate::fs::create_filesystem;
// use crate::mem::{phys::PageUsage, virt::MapAttributes};
use crate::proc::{self, elf, wait, Process, ProcessIo, Thread};
use core::mem::size_of;
// use core::mem::size_of;
use core::ops::DerefMut;
use core::time::Duration;
// use core::time::Duration;
use libsys::{
abi::SystemCall,
debug::TraceLevel,
@ -24,18 +24,18 @@ use libsys::{
};
use vfs::VnodeRef;
pub mod arg;
// pub mod arg;
/// Creates a "fork" process from current one using its register frame.
/// See [Process::fork()].
///
/// # Safety
///
/// Unsafe: accepts and clones process states. Only legal to call
/// from exception handlers.
pub unsafe fn sys_fork(regs: &mut ExceptionFrame) -> Result<Pid, Errno> {
Process::current().fork(regs)
}
// /// Creates a "fork" process from current one using its register frame.
// /// See [Process::fork()].
// ///
// /// # Safety
// ///
// /// Unsafe: accepts and clones process states. Only legal to call
// /// from exception handlers.
// pub unsafe fn sys_fork(regs: &mut ExceptionFrame) -> Result<Pid, Errno> {
// Process::current().fork(regs)
// }
fn find_at_node<T: DerefMut<Target = ProcessIo>>(
io: &mut T,
@ -57,405 +57,407 @@ fn find_at_node<T: DerefMut<Target = ProcessIo>>(
}
fn _syscall(num: SystemCall, args: &[usize]) -> Result<usize, Errno> {
match num {
// I/O
SystemCall::Read => {
let proc = Process::current();
let fd = FileDescriptor::from(args[0] as u32);
let mut io = proc.io.lock();
let buf = arg::buf_mut(args[1], args[2])?;
io.file(fd)?.borrow_mut().read(buf)
}
SystemCall::Write => {
let proc = Process::current();
let fd = FileDescriptor::from(args[0] as u32);
let mut io = proc.io.lock();
let buf = arg::buf_ref(args[1], args[2])?;
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::MapMemory => {
let len = args[1];
if len == 0 || (len & 0xFFF) != 0 {
return Err(Errno::InvalidArgument);
}
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::NOT_GLOBAL | MapAttributes::SH_OUTER | MapAttributes::PXN;
if !acc.contains(MemoryAccess::READ) {
return Err(Errno::NotImplemented);
}
if acc.contains(MemoryAccess::WRITE) {
if acc.contains(MemoryAccess::EXEC) {
return Err(Errno::PermissionDenied);
}
attrs |= MapAttributes::AP_BOTH_READWRITE;
} else {
attrs |= MapAttributes::AP_BOTH_READONLY;
}
if !acc.contains(MemoryAccess::EXEC) {
attrs |= MapAttributes::UXN;
}
// TODO don't ignore flags
let usage = PageUsage::UserPrivate;
let proc = Process::current();
proc.manipulate_space(move |space| {
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];
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)
}
e => e.map(|e| i32::from(e) as usize),
}
}
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)
}
SystemCall::Mount => {
let target = arg::str_ref(args[0], args[1])?;
let options = arg::struct_ref::<MountOptions>(args[2])?;
let proc = Process::current();
let mut io = proc.io.lock();
debugln!("mount(target={:?}, options={:#x?})", target, options);
let target_node = io.ioctx().find(None, target, true)?;
let root = create_filesystem(options)?;
target_node.mount(root)?;
Ok(0)
}
// Debugging
SystemCall::DebugTrace => {
let level = TraceLevel::from_repr(args[0])
.map(Level::from)
.ok_or(Errno::InvalidArgument)?;
let buf = arg::str_ref(args[1], args[2])?;
let thread = Thread::current();
let proc = thread.owner().unwrap();
println!(level, "[trace {:?}:{:?}] {}", proc.id(), thread.id(), buf);
Ok(args[1])
}
// Handled elsewhere
SystemCall::Fork => unreachable!(),
}
loop {}
// match num {
// // I/O
// SystemCall::Read => {
// let proc = Process::current();
// let fd = FileDescriptor::from(args[0] as u32);
// let mut io = proc.io.lock();
// let buf = arg::buf_mut(args[1], args[2])?;
//
// io.file(fd)?.borrow_mut().read(buf)
// }
// SystemCall::Write => {
// let proc = Process::current();
// let fd = FileDescriptor::from(args[0] as u32);
// let mut io = proc.io.lock();
// let buf = arg::buf_ref(args[1], args[2])?;
//
// 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::MapMemory => {
// let len = args[1];
// if len == 0 || (len & 0xFFF) != 0 {
// return Err(Errno::InvalidArgument);
// }
// 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::NOT_GLOBAL | MapAttributes::SH_OUTER | MapAttributes::PXN;
// if !acc.contains(MemoryAccess::READ) {
// return Err(Errno::NotImplemented);
// }
// if acc.contains(MemoryAccess::WRITE) {
// if acc.contains(MemoryAccess::EXEC) {
// return Err(Errno::PermissionDenied);
// }
// attrs |= MapAttributes::AP_BOTH_READWRITE;
// } else {
// attrs |= MapAttributes::AP_BOTH_READONLY;
// }
// if !acc.contains(MemoryAccess::EXEC) {
// attrs |= MapAttributes::UXN;
// }
//
// // TODO don't ignore flags
// let usage = PageUsage::UserPrivate;
//
// let proc = Process::current();
//
// proc.manipulate_space(move |space| {
// 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];
//
// 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)
// }
// e => e.map(|e| i32::from(e) as usize),
// }
// }
// 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)
// }
// SystemCall::Mount => {
// let target = arg::str_ref(args[0], args[1])?;
// let options = arg::struct_ref::<MountOptions>(args[2])?;
//
// let proc = Process::current();
// let mut io = proc.io.lock();
//
// debugln!("mount(target={:?}, options={:#x?})", target, options);
//
// let target_node = io.ioctx().find(None, target, true)?;
// let root = create_filesystem(options)?;
//
// target_node.mount(root)?;
//
// Ok(0)
// }
//
// // Debugging
// SystemCall::DebugTrace => {
// let level = TraceLevel::from_repr(args[0])
// .map(Level::from)
// .ok_or(Errno::InvalidArgument)?;
// let buf = arg::str_ref(args[1], args[2])?;
// let thread = Thread::current();
// let proc = thread.owner().unwrap();
// println!(level, "[trace {:?}:{:?}] {}", proc.id(), thread.id(), buf);
// Ok(args[1])
// }
//
// // Handled elsewhere
// SystemCall::Fork => unreachable!(),
// }
}
/// Main system call dispatcher function
pub fn syscall(num: SystemCall, args: &[usize]) -> Result<usize, Errno> {
let thread = Thread::current();
let process = thread.owner().unwrap();
let result = _syscall(num, args);
if !thread.is_handling_signal() {
process.handle_pending_signals();
}
result
todo!()
// let thread = Thread::current();
// let process = thread.owner().unwrap();
// let result = _syscall(num, args);
// if !thread.is_handling_signal() {
// process.handle_pending_signals();
// }
// result
}

View File

@ -26,7 +26,7 @@ extern "C" fn _start(arg: &'static ProgramArgs) -> ! {
fn main() -> i32;
}
// trace!(TraceLevel::Debug, "Test!");
trace!(TraceLevel::Debug, "Test!");
loop {}
// unsafe {