Move some conditionally compiled code from common files into arch-gated files

This commit is contained in:
Andrey Turkin
2024-10-19 12:47:30 +03:00
parent 55041e2eeb
commit db32f5f7a3
11 changed files with 329 additions and 272 deletions
+1 -1
View File
@@ -175,7 +175,7 @@ exception_stack!(synchronous_exception_at_el0, |stack| {
0b010101 => {
let scratch = &stack.scratch;
let ret = syscall::syscall(
scratch.x8, scratch.x0, scratch.x1, scratch.x2, scratch.x3, scratch.x4, stack,
scratch.x8, scratch.x0, scratch.x1, scratch.x2, scratch.x3, scratch.x4,
);
stack.scratch.x0 = ret;
}
-1
View File
@@ -34,7 +34,6 @@ interrupt_stack!(syscall, |stack| {
scratch.edx,
preserved.esi,
preserved.edi,
stack,
);
stack.scratch.eax = ret;
})
-1
View File
@@ -75,7 +75,6 @@ pub unsafe extern "C" fn __inner_syscall_instruction(stack: *mut InterruptStack)
scratch.rdx,
scratch.r10,
scratch.r8,
&mut *stack,
);
(*stack).scratch.rax = ret;
}
+78 -6
View File
@@ -1,7 +1,13 @@
use crate::{
arch::{device::cpu::registers::control_regs, interrupt::InterruptStack, paging::PageMapper},
context::{context::Kstack, memory::Table},
percpu::PercpuBlock,
syscall::FloatRegisters,
};
use core::{arch::asm, mem, mem::offset_of, ptr, sync::atomic::AtomicBool};
use rmm::TableKind;
use spin::Once;
use crate::{percpu::PercpuBlock, syscall::FloatRegisters};
use syscall::{EnvRegisters, Error, Result, ENOMEM};
/// This must be used by the kernel to ensure that context switches are done atomically
/// Compare and exchange this to true when beginning a context switch on any CPU
@@ -62,23 +68,49 @@ impl Context {
}
}
pub fn set_stack(&mut self, address: usize) {
fn set_stack(&mut self, address: usize) {
self.sp = address;
}
pub fn set_x28(&mut self, x28: usize) {
fn set_x28(&mut self, x28: usize) {
self.x28 = x28;
}
pub fn set_lr(&mut self, address: usize) {
fn set_lr(&mut self, address: usize) {
self.lr = address;
}
pub fn set_context_handle(&mut self) {
fn set_context_handle(&mut self) {
let address = self as *const _ as usize;
self.tpidrro_el0 = address;
}
pub(crate) fn setup_initial_call(
&mut self,
stack: &Kstack,
func: extern "C" fn(),
userspace_allowed: bool,
) {
let mut stack_top = stack.initial_top();
const INT_REGS_SIZE: usize = core::mem::size_of::<InterruptStack>();
if userspace_allowed {
unsafe {
// Zero-initialize InterruptStack registers.
stack_top = stack_top.sub(INT_REGS_SIZE);
stack_top.write_bytes(0_u8, INT_REGS_SIZE);
(&mut *stack_top.cast::<InterruptStack>()).init();
}
}
self.set_lr(crate::interrupt::syscall::enter_usermode as usize);
self.set_x28(func as usize);
self.set_context_handle();
self.set_stack(stack_top as usize);
}
#[allow(unused)]
pub fn dump(&self) {
println!("elr_el1: 0x{:016x}", self.elr_el1);
@@ -131,6 +163,36 @@ impl super::Context {
scratch.x8, scratch.x0, scratch.x1, scratch.x2, scratch.x3, scratch.x4,
])
}
pub(crate) fn write_current_env_regs(&self, regs: EnvRegisters) -> Result<()> {
unsafe {
control_regs::tpidr_el0_write(regs.tpidr_el0 as u64);
control_regs::tpidrro_el0_write(regs.tpidrro_el0 as u64);
}
Ok(())
}
pub(crate) fn write_env_regs(&mut self, regs: EnvRegisters) -> Result<()> {
self.arch.tpidr_el0 = regs.tpidr_el0;
self.arch.tpidrro_el0 = regs.tpidrro_el0;
Ok(())
}
pub(crate) fn read_current_env_regs(&self) -> Result<EnvRegisters> {
unsafe {
Ok(EnvRegisters {
tpidr_el0: control_regs::tpidr_el0() as usize,
tpidrro_el0: control_regs::tpidrro_el0() as usize,
})
}
}
pub(crate) fn read_env_regs(&self) -> Result<EnvRegisters> {
Ok(EnvRegisters {
tpidr_el0: self.arch.tpidr_el0,
tpidrro_el0: self.arch.tpidrro_el0,
})
}
}
pub static EMPTY_CR3: Once<rmm::PhysicalAddress> = Once::new();
@@ -324,3 +386,13 @@ unsafe extern "C" fn switch_to_inner(_prev: &mut Context, _next: &mut Context) {
options(noreturn),
);
}
/// Allocates a new empty utable
pub fn setup_new_utable() -> Result<Table> {
let utable = unsafe {
PageMapper::create(TableKind::User, crate::memory::TheFrameAllocator)
.ok_or(Error::new(ENOMEM))?
};
Ok(Table { utable })
}
+113 -1
View File
@@ -6,8 +6,15 @@ use crate::{
syscall::FloatRegisters,
};
use crate::{
arch::{interrupt::InterruptStack, paging::PageMapper},
context::{context::Kstack, memory::Table},
memory::RmmA,
};
use core::mem::offset_of;
use rmm::{Arch, TableKind, VirtualAddress};
use spin::Once;
use syscall::{error::*, EnvRegisters};
/// This must be used by the kernel to ensure that context switches are done atomically
/// Compare and exchange this to true when beginning a context switch on any CPU
@@ -62,10 +69,41 @@ impl Context {
}
}
pub fn set_stack(&mut self, address: usize) {
fn set_stack(&mut self, address: usize) {
self.esp = address;
}
pub(crate) fn setup_initial_call(
&mut self,
stack: &Kstack,
func: extern "C" fn(),
userspace_allowed: bool,
) {
let mut stack_top = stack.initial_top();
const INT_REGS_SIZE: usize = core::mem::size_of::<InterruptStack>();
unsafe {
if userspace_allowed {
// Zero-initialize InterruptStack registers.
stack_top = stack_top.sub(INT_REGS_SIZE);
stack_top.write_bytes(0_u8, INT_REGS_SIZE);
(&mut *stack_top.cast::<InterruptStack>()).init();
stack_top = stack_top.sub(core::mem::size_of::<usize>());
stack_top
.cast::<usize>()
.write(crate::interrupt::syscall::enter_usermode as usize);
}
stack_top = stack_top.sub(core::mem::size_of::<usize>());
stack_top.cast::<usize>().write(func as usize);
}
self.set_stack(stack_top as usize);
}
}
impl super::Context {
pub fn get_fx_regs(&self) -> FloatRegisters {
let mut regs = unsafe { self.kfx.as_ptr().cast::<FloatRegisters>().read() };
@@ -121,6 +159,50 @@ impl super::Context {
regs.preserved.edi,
])
}
pub(crate) fn write_current_env_regs(&mut self, regs: EnvRegisters) -> Result<()> {
if RmmA::virt_is_valid(VirtualAddress::new(regs.fsbase as usize))
&& RmmA::virt_is_valid(VirtualAddress::new(regs.gsbase as usize))
{
unsafe {
(&mut *pcr()).gdt[GDT_USER_FS].set_offset(regs.fsbase);
(&mut *pcr()).gdt[GDT_USER_GS].set_offset(regs.gsbase);
}
self.arch.fsbase = regs.fsbase as usize;
self.arch.gsbase = regs.gsbase as usize;
Ok(())
} else {
Err(Error::new(EINVAL))
}
}
pub(crate) fn write_env_regs(&mut self, regs: EnvRegisters) -> Result<()> {
if RmmA::virt_is_valid(VirtualAddress::new(regs.fsbase as usize))
&& RmmA::virt_is_valid(VirtualAddress::new(regs.gsbase as usize))
{
self.arch.fsbase = regs.fsbase as usize;
self.arch.gsbase = regs.gsbase as usize;
Ok(())
} else {
Err(Error::new(EINVAL))
}
}
pub(crate) fn read_current_env_regs(&self) -> Result<EnvRegisters> {
unsafe {
Ok(EnvRegisters {
fsbase: (&*pcr()).gdt[GDT_USER_FS].offset(),
gsbase: (&*pcr()).gdt[GDT_USER_GS].offset(),
})
}
}
pub(crate) fn read_env_regs(&self) -> Result<EnvRegisters> {
Ok(EnvRegisters {
fsbase: self.arch.fsbase as u32,
gsbase: self.arch.gsbase as u32,
})
}
}
pub static EMPTY_CR3: Once<rmm::PhysicalAddress> = Once::new();
@@ -227,3 +309,33 @@ unsafe extern "cdecl" fn switch_to_inner() {
options(noreturn),
);
}
/// Allocates a new identically mapped ktable and empty utable (same memory on x86)
pub fn setup_new_utable() -> Result<Table> {
use crate::memory::KernelMapper;
let utable = unsafe {
PageMapper::create(TableKind::User, crate::memory::TheFrameAllocator)
.ok_or(Error::new(ENOMEM))?
};
{
let active_ktable = KernelMapper::lock();
let copy_mapping = |p4_no| unsafe {
let entry = active_ktable
.table()
.entry(p4_no)
.unwrap_or_else(|| panic!("expected kernel PML {} to be mapped", p4_no));
utable.table().set_entry(p4_no, entry)
};
// Copy higher half (kernel) mappings
for i in 512..1024 {
copy_mapping(i);
}
}
Ok(Table { utable })
}
+123 -2
View File
@@ -5,8 +5,15 @@ use core::{
use crate::syscall::FloatRegisters;
use crate::{
arch::{interrupt::InterruptStack, paging::PageMapper},
context::{context::Kstack, memory::Table},
memory::RmmA,
};
use core::mem::offset_of;
use rmm::{Arch, TableKind, VirtualAddress};
use spin::Once;
use syscall::{error::*, EnvRegisters};
use x86::msr;
/// This must be used by the kernel to ensure that context switches are done atomically
@@ -74,9 +81,39 @@ impl Context {
}
}
pub fn set_stack(&mut self, address: usize) {
fn set_stack(&mut self, address: usize) {
self.rsp = address;
}
pub(crate) fn setup_initial_call(
&mut self,
stack: &Kstack,
func: extern "C" fn(),
userspace_allowed: bool,
) {
let mut stack_top = stack.initial_top();
const INT_REGS_SIZE: usize = core::mem::size_of::<InterruptStack>();
unsafe {
if userspace_allowed {
// Zero-initialize InterruptStack registers.
stack_top = stack_top.sub(INT_REGS_SIZE);
stack_top.write_bytes(0_u8, INT_REGS_SIZE);
(&mut *stack_top.cast::<InterruptStack>()).init();
stack_top = stack_top.sub(core::mem::size_of::<usize>());
stack_top
.cast::<usize>()
.write(crate::interrupt::syscall::enter_usermode as usize);
}
stack_top = stack_top.sub(core::mem::size_of::<usize>());
stack_top.cast::<usize>().write(func as usize);
}
self.set_stack(stack_top as usize);
}
}
impl super::Context {
pub fn get_fx_regs(&self) -> FloatRegisters {
@@ -121,7 +158,7 @@ impl super::Context {
}
}
pub fn current_syscall(&self) -> Option<[usize; 6]> {
pub(crate) fn current_syscall(&self) -> Option<[usize; 6]> {
if !self.inside_syscall {
return None;
}
@@ -136,6 +173,54 @@ impl super::Context {
scratch.r8,
])
}
pub(crate) fn read_current_env_regs(&self) -> Result<EnvRegisters> {
// TODO: Avoid rdmsr if fsgsbase is not enabled, if this is worth optimizing for.
unsafe {
Ok(EnvRegisters {
fsbase: msr::rdmsr(msr::IA32_FS_BASE),
gsbase: msr::rdmsr(msr::IA32_KERNEL_GSBASE),
})
}
}
pub(crate) fn read_env_regs(&self) -> Result<EnvRegisters> {
Ok(EnvRegisters {
fsbase: self.arch.fsbase as u64,
gsbase: self.arch.gsbase as u64,
})
}
pub(crate) fn write_current_env_regs(&mut self, regs: EnvRegisters) -> Result<()> {
if RmmA::virt_is_valid(VirtualAddress::new(regs.fsbase as usize))
&& RmmA::virt_is_valid(VirtualAddress::new(regs.gsbase as usize))
{
unsafe {
x86::msr::wrmsr(x86::msr::IA32_FS_BASE, regs.fsbase as u64);
// We have to write to KERNEL_GSBASE, because when the kernel returns to
// userspace, it will have executed SWAPGS first.
x86::msr::wrmsr(x86::msr::IA32_KERNEL_GSBASE, regs.gsbase as u64);
}
self.arch.fsbase = regs.fsbase as usize;
self.arch.gsbase = regs.gsbase as usize;
Ok(())
} else {
Err(Error::new(EINVAL))
}
}
pub(crate) fn write_env_regs(&mut self, regs: EnvRegisters) -> Result<()> {
if RmmA::virt_is_valid(VirtualAddress::new(regs.fsbase as usize))
&& RmmA::virt_is_valid(VirtualAddress::new(regs.gsbase as usize))
{
self.arch.fsbase = regs.fsbase as usize;
self.arch.gsbase = regs.gsbase as usize;
Ok(())
} else {
Err(Error::new(EINVAL))
}
}
}
pub static EMPTY_CR3: Once<rmm::PhysicalAddress> = Once::new();
@@ -302,3 +387,39 @@ unsafe extern "sysv64" fn switch_to_inner(_prev: &mut Context, _next: &mut Conte
options(noreturn),
);
}
/// Allocates a new identically mapped ktable and empty utable (same memory on x86_64).
pub fn setup_new_utable() -> Result<Table> {
use crate::memory::{KernelMapper, TheFrameAllocator};
let utable = unsafe {
PageMapper::create(TableKind::User, TheFrameAllocator).ok_or(Error::new(ENOMEM))?
};
{
let active_ktable = KernelMapper::lock();
let copy_mapping = |p4_no| unsafe {
let entry = active_ktable
.table()
.entry(p4_no)
.unwrap_or_else(|| panic!("expected kernel PML {} to be mapped", p4_no));
utable.table().set_entry(p4_no, entry)
};
// TODO: Just copy all 256 mappings? Or copy KERNEL_PML4+KERNEL_PERCPU_PML4 (needed for
// paranoid ISRs which can occur anywhere; we don't want interrupts to triple fault!) and
// map lazily via page faults in the kernel.
// Copy kernel image mapping
copy_mapping(crate::KERNEL_PML4);
// Copy kernel heap mapping
copy_mapping(crate::KERNEL_HEAP_PML4);
// Copy physmap mapping
copy_mapping(crate::PHYS_PML4);
}
Ok(Table { utable })
}
+1 -78
View File
@@ -12,6 +12,7 @@ use syscall::{error::*, flag::MapFlags, GrantFlags, MunmapFlags};
use crate::{
arch::paging::PAGE_SIZE,
context::arch::setup_new_utable,
cpu_set::LogicalCpuSet,
memory::{
deallocate_frame, deallocate_p2frame, get_page_info, init_frame, the_zeroed_frame,
@@ -2258,84 +2259,6 @@ impl Drop for Table {
}
}
/// Allocates a new empty utable
#[cfg(target_arch = "aarch64")]
pub fn setup_new_utable() -> Result<Table> {
let utable = unsafe {
PageMapper::create(TableKind::User, crate::memory::TheFrameAllocator)
.ok_or(Error::new(ENOMEM))?
};
Ok(Table { utable })
}
/// Allocates a new identically mapped ktable and empty utable (same memory on x86)
#[cfg(target_arch = "x86")]
pub fn setup_new_utable() -> Result<Table> {
use crate::memory::KernelMapper;
let utable = unsafe {
PageMapper::create(TableKind::User, crate::memory::TheFrameAllocator)
.ok_or(Error::new(ENOMEM))?
};
{
let active_ktable = KernelMapper::lock();
let copy_mapping = |p4_no| unsafe {
let entry = active_ktable
.table()
.entry(p4_no)
.unwrap_or_else(|| panic!("expected kernel PML {} to be mapped", p4_no));
utable.table().set_entry(p4_no, entry)
};
// Copy higher half (kernel) mappings
for i in 512..1024 {
copy_mapping(i);
}
}
Ok(Table { utable })
}
/// Allocates a new identically mapped ktable and empty utable (same memory on x86_64).
#[cfg(target_arch = "x86_64")]
pub fn setup_new_utable() -> Result<Table> {
use crate::memory::{KernelMapper, TheFrameAllocator};
let utable = unsafe {
PageMapper::create(TableKind::User, TheFrameAllocator).ok_or(Error::new(ENOMEM))?
};
{
let active_ktable = KernelMapper::lock();
let copy_mapping = |p4_no| unsafe {
let entry = active_ktable
.table()
.entry(p4_no)
.unwrap_or_else(|| panic!("expected kernel PML {} to be mapped", p4_no));
utable.table().set_entry(p4_no, entry)
};
// TODO: Just copy all 256 mappings? Or copy KERNEL_PML4+KERNEL_PERCPU_PML4 (needed for
// paranoid ISRs which can occur anywhere; we don't want interrupts to triple fault!) and
// map lazily via page faults in the kernel.
// Copy kernel image mapping
copy_mapping(crate::KERNEL_PML4);
// Copy kernel heap mapping
copy_mapping(crate::KERNEL_HEAP_PML4);
// Copy physmap mapping
copy_mapping(crate::PHYS_PML4);
}
Ok(Table { utable })
}
#[derive(Clone, Copy, PartialEq)]
pub enum AccessMode {
Read,
+3 -37
View File
@@ -11,7 +11,6 @@ use syscall::ENOMEM;
use crate::{
context::memory::AddrSpaceWrapper,
cpu_set::LogicalCpuSet,
interrupt::InterruptStack,
paging::{RmmA, RmmArch, TableKind},
percpu::PercpuBlock,
sync::WaitMap,
@@ -182,42 +181,9 @@ pub fn spawn(
{
let mut context = context_lock.write();
let _ = context.set_addr_space(Some(AddrSpaceWrapper::new()?));
let mut stack_top = stack.initial_top();
const INT_REGS_SIZE: usize = core::mem::size_of::<crate::interrupt::InterruptStack>();
if userspace_allowed {
unsafe {
// Zero-initialize InterruptStack registers.
stack_top = stack_top.sub(INT_REGS_SIZE);
stack_top.write_bytes(0_u8, INT_REGS_SIZE);
(&mut *stack_top.cast::<InterruptStack>()).init();
}
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
unsafe {
if userspace_allowed {
stack_top = stack_top.sub(core::mem::size_of::<usize>());
stack_top
.cast::<usize>()
.write(crate::interrupt::syscall::enter_usermode as usize);
}
stack_top = stack_top.sub(core::mem::size_of::<usize>());
stack_top.cast::<usize>().write(func as usize);
}
#[cfg(target_arch = "aarch64")]
{
context
.arch
.set_lr(crate::interrupt::syscall::enter_usermode as usize);
context.arch.set_x28(func as usize);
context.arch.set_context_handle();
}
context.arch.set_stack(stack_top as usize);
context
.arch
.setup_initial_call(&stack, func, userspace_allowed);
context.kstack = Some(stack);
context.userspace = userspace_allowed;
+1 -1
View File
@@ -356,7 +356,7 @@ impl SchemeList {
}
}
for name in remove {
assert!(names.remove(&name).is_some());
assert!(names.swap_remove(&name).is_some());
}
}
}
+6 -134
View File
@@ -1630,147 +1630,19 @@ impl ContextHandle {
}
}
}
#[cfg(target_arch = "aarch64")]
fn write_env_regs(context: Arc<RwSpinlock<Context>>, regs: EnvRegisters) -> Result<()> {
use crate::device::cpu::registers::control_regs;
if context::is_current(&context) {
unsafe {
control_regs::tpidr_el0_write(regs.tpidr_el0 as u64);
control_regs::tpidrro_el0_write(regs.tpidrro_el0 as u64);
}
context::current().write().write_current_env_regs(regs)
} else {
try_stop_context(context, |context| {
context.arch.tpidr_el0 = regs.tpidr_el0;
context.arch.tpidrro_el0 = regs.tpidrro_el0;
Ok(())
})?;
try_stop_context(context, |context| context.write_env_regs(regs))
}
Ok(())
}
#[cfg(target_arch = "x86")]
fn write_env_regs(context: Arc<RwSpinlock<Context>>, regs: EnvRegisters) -> Result<()> {
if !(RmmA::virt_is_valid(VirtualAddress::new(regs.fsbase as usize))
&& RmmA::virt_is_valid(VirtualAddress::new(regs.gsbase as usize)))
{
return Err(Error::new(EINVAL));
}
fn read_env_regs(context: Arc<RwSpinlock<Context>>) -> Result<EnvRegisters> {
if context::is_current(&context) {
unsafe {
(&mut *crate::gdt::pcr()).gdt[crate::gdt::GDT_USER_FS].set_offset(regs.fsbase);
(&mut *crate::gdt::pcr()).gdt[crate::gdt::GDT_USER_GS].set_offset(regs.gsbase);
match context.write().arch {
ref mut arch => {
arch.fsbase = regs.fsbase as usize;
arch.gsbase = regs.gsbase as usize;
}
}
}
context::current().read().read_current_env_regs()
} else {
try_stop_context(context, |context| {
context.arch.fsbase = regs.fsbase as usize;
context.arch.gsbase = regs.gsbase as usize;
Ok(())
})?;
try_stop_context(context, |context| context.read_env_regs())
}
Ok(())
}
#[cfg(target_arch = "x86_64")]
fn write_env_regs(context: Arc<RwSpinlock<Context>>, regs: EnvRegisters) -> Result<()> {
use crate::memory::RmmA;
use rmm::Arch;
if !(RmmA::virt_is_valid(VirtualAddress::new(regs.fsbase as usize))
&& RmmA::virt_is_valid(VirtualAddress::new(regs.gsbase as usize)))
{
return Err(Error::new(EINVAL));
}
if context::is_current(&context) {
unsafe {
x86::msr::wrmsr(x86::msr::IA32_FS_BASE, regs.fsbase as u64);
// We have to write to KERNEL_GSBASE, because when the kernel returns to
// userspace, it will have executed SWAPGS first.
x86::msr::wrmsr(x86::msr::IA32_KERNEL_GSBASE, regs.gsbase as u64);
match context::current().write().arch {
ref mut arch => {
arch.fsbase = regs.fsbase as usize;
arch.gsbase = regs.gsbase as usize;
}
}
}
} else {
try_stop_context(context, |context| {
context.arch.fsbase = regs.fsbase as usize;
context.arch.gsbase = regs.gsbase as usize;
Ok(())
})?;
}
Ok(())
}
#[cfg(target_arch = "aarch64")]
fn read_env_regs(context: Arc<RwSpinlock<Context>>) -> Result<EnvRegisters> {
use crate::device::cpu::registers::control_regs;
let (tpidr_el0, tpidrro_el0) = if context::is_current(&context) {
unsafe {
(
control_regs::tpidr_el0() as usize,
control_regs::tpidrro_el0() as usize,
)
}
} else {
try_stop_context(context, |context| {
Ok((context.arch.tpidr_el0, context.arch.tpidrro_el0))
})?
};
Ok(EnvRegisters {
tpidr_el0,
tpidrro_el0,
})
}
#[cfg(target_arch = "x86")]
fn read_env_regs(context: Arc<RwSpinlock<Context>>) -> Result<EnvRegisters> {
let (fsbase, gsbase) = if context::is_current(&context) {
unsafe {
(
(&*crate::gdt::pcr()).gdt[crate::gdt::GDT_USER_FS].offset() as u64,
(&*crate::gdt::pcr()).gdt[crate::gdt::GDT_USER_GS].offset() as u64,
)
}
} else {
try_stop_context(context, |context| {
Ok((context.arch.fsbase as u64, context.arch.gsbase as u64))
})?
};
Ok(EnvRegisters {
fsbase: fsbase as _,
gsbase: gsbase as _,
})
}
#[cfg(target_arch = "x86_64")]
fn read_env_regs(context: Arc<RwSpinlock<Context>>) -> Result<EnvRegisters> {
// TODO: Avoid rdmsr if fsgsbase is not enabled, if this is worth optimizing for.
let (fsbase, gsbase) = if context::is_current(&context) {
unsafe {
(
x86::msr::rdmsr(x86::msr::IA32_FS_BASE),
x86::msr::rdmsr(x86::msr::IA32_KERNEL_GSBASE),
)
}
} else {
try_stop_context(context, |context| {
Ok((context.arch.fsbase as u64, context.arch.gsbase as u64))
})?
};
Ok(EnvRegisters {
fsbase: fsbase as _,
gsbase: gsbase as _,
})
}
+3 -10
View File
@@ -24,7 +24,7 @@ use self::{
usercopy::UserSlice,
};
use crate::{interrupt::InterruptStack, percpu::PercpuBlock};
use crate::percpu::PercpuBlock;
use crate::{
context::{memory::AddrSpace, process::ProcessId},
@@ -60,15 +60,8 @@ pub mod usercopy;
/// This function is the syscall handler of the kernel, it is composed of an inner function that returns a `Result<usize>`. After the inner function runs, the syscall
/// function calls [`Error::mux`] on it.
pub fn syscall(
a: usize,
b: usize,
c: usize,
d: usize,
e: usize,
f: usize,
_stack: &mut InterruptStack,
) -> usize {
#[must_use]
pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -> usize {
#[inline(always)]
fn inner(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -> Result<usize> {
let fd = FileHandle::from(b);