Better MSR/CR interface for x86_64
This commit is contained in:
parent
9126f8ac68
commit
a799b71326
@ -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();
|
||||
|
16
kernel/src/arch/x86_64/intrin.rs
Normal file
16
kernel/src/arch/x86_64/intrin.rs
Normal 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);
|
||||
}
|
@ -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;
|
||||
|
135
kernel/src/arch/x86_64/reg/mod.rs
Normal file
135
kernel/src/arch/x86_64/reg/mod.rs
Normal 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) []
|
||||
]);
|
13
kernel/src/arch/x86_64/reg/msr_ia32_efer.rs
Normal file
13
kernel/src/arch/x86_64/reg/msr_ia32_efer.rs
Normal 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);
|
4
kernel/src/arch/x86_64/syscall.S
Normal file
4
kernel/src/arch/x86_64/syscall.S
Normal file
@ -0,0 +1,4 @@
|
||||
.section .text
|
||||
.global __x86_64_syscall_entry
|
||||
__x86_64_syscall_entry:
|
||||
jmp .
|
17
kernel/src/arch/x86_64/syscall.rs
Normal file
17
kernel/src/arch/x86_64/syscall.rs
Normal 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));
|
@ -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]
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ extern "C" fn _start(arg: &'static ProgramArgs) -> ! {
|
||||
fn main() -> i32;
|
||||
}
|
||||
|
||||
// trace!(TraceLevel::Debug, "Test!");
|
||||
trace!(TraceLevel::Debug, "Test!");
|
||||
loop {}
|
||||
|
||||
// unsafe {
|
||||
|
Loading…
x
Reference in New Issue
Block a user