Allocate kernel stacks using the frame allocator.
This commit is contained in:
@@ -148,7 +148,7 @@ pub unsafe fn switch_to(prev: &mut super::Context, next: &mut super::Context) {
|
||||
let pcr = crate::gdt::pcr();
|
||||
|
||||
if let Some(ref stack) = next.kstack {
|
||||
crate::gdt::set_tss_stack(pcr, stack.as_ptr() as usize + stack.len());
|
||||
crate::gdt::set_tss_stack(pcr, stack.initial_top() as usize);
|
||||
}
|
||||
crate::gdt::set_userspace_io_allowed(pcr, next.arch.userspace_io_allowed);
|
||||
|
||||
|
||||
+47
-7
@@ -1,10 +1,10 @@
|
||||
use alloc::{borrow::Cow, sync::Arc, vec::Vec};
|
||||
use syscall::{SIGKILL, SIGSTOP};
|
||||
use core::{cmp::Ordering, mem, num::NonZeroUsize};
|
||||
use core::{cmp::Ordering, mem::{self, size_of}, num::NonZeroUsize};
|
||||
use spin::RwLock;
|
||||
|
||||
use crate::{
|
||||
arch::{interrupt::InterruptStack, paging::PAGE_SIZE}, common::aligned_box::AlignedBox, context::{self, arch, file::FileDescriptor, memory::AddrSpace}, cpu_set::{LogicalCpuId, LogicalCpuSet}, ipi::{ipi, IpiKind, IpiTarget}, memory::{Frame, RaiiFrame}, paging::{RmmA, RmmArch}, percpu::PercpuBlock, scheme::{CallerCtx, FileHandle, SchemeNamespace}, sync::WaitMap,
|
||||
arch::{interrupt::InterruptStack, paging::PAGE_SIZE}, common::aligned_box::AlignedBox, context::{self, arch, file::FileDescriptor, memory::AddrSpace}, cpu_set::{LogicalCpuId, LogicalCpuSet}, ipi::{ipi, IpiKind, IpiTarget}, memory::{allocate_p2frame, deallocate_p2frame, Enomem, Frame, RaiiFrame}, paging::{RmmA, RmmArch}, percpu::PercpuBlock, scheme::{CallerCtx, FileHandle, SchemeNamespace}, sync::WaitMap,
|
||||
};
|
||||
|
||||
use crate::syscall::{
|
||||
@@ -180,7 +180,7 @@ pub struct Context {
|
||||
/// Kernel FX - used to store SIMD and FPU registers on context switch
|
||||
pub kfx: AlignedBox<[u8], { arch::KFX_ALIGN }>,
|
||||
/// Kernel stack, if located on the heap.
|
||||
pub kstack: Option<AlignedBox<[u8; arch::KSTACK_SIZE], { arch::KSTACK_ALIGN }>>,
|
||||
pub kstack: Option<Kstack>,
|
||||
/// Address space containing a page table lock, and grants. Normally this will have a value,
|
||||
/// but can be None while the context is being reaped or when a new context is created but has
|
||||
/// not yet had its address space changed. Note that these are only for user mappings; kernel
|
||||
@@ -460,8 +460,7 @@ impl Context {
|
||||
let Some(ref kstack) = self.kstack else {
|
||||
return None;
|
||||
};
|
||||
let range = kstack.len().checked_sub(mem::size_of::<InterruptStack>())?..;
|
||||
Some(unsafe { &*kstack.get(range)?.as_ptr().cast() })
|
||||
Some(unsafe { &*kstack.initial_top().sub(size_of::<InterruptStack>()).cast() })
|
||||
}
|
||||
pub fn regs_mut(&mut self) -> Option<&mut InterruptStack> {
|
||||
if !self.can_access_regs() {
|
||||
@@ -470,8 +469,7 @@ impl Context {
|
||||
let Some(ref mut kstack) = self.kstack else {
|
||||
return None;
|
||||
};
|
||||
let range = kstack.len().checked_sub(mem::size_of::<InterruptStack>())?..;
|
||||
Some(unsafe { &mut *kstack.get_mut(range)?.as_mut_ptr().cast() })
|
||||
Some(unsafe { &mut *kstack.initial_top().sub(size_of::<InterruptStack>()).cast() })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -581,3 +579,45 @@ impl Drop for BorrowedHtBuf {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Kstack {
|
||||
/// naturally aligned, order 4
|
||||
base: Frame,
|
||||
}
|
||||
impl Kstack {
|
||||
pub fn new() -> Result<Self, Enomem> {
|
||||
Ok(Self {
|
||||
base: allocate_p2frame(4).ok_or(Enomem)?,
|
||||
})
|
||||
}
|
||||
pub fn initial_top(&self) -> *mut u8 {
|
||||
unsafe {
|
||||
(RmmA::phys_to_virt(self.base.start_address()).data() as *mut u8).add(PAGE_SIZE << 4)
|
||||
}
|
||||
}
|
||||
pub fn len(&self) -> usize {
|
||||
PAGE_SIZE << 4
|
||||
}
|
||||
}
|
||||
|
||||
const _: () = {
|
||||
if PAGE_SIZE << 4 != arch::KSTACK_SIZE {
|
||||
panic!();
|
||||
}
|
||||
if arch::KSTACK_ALIGN > (PAGE_SIZE << 4) {
|
||||
panic!();
|
||||
}
|
||||
};
|
||||
|
||||
impl Drop for Kstack {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
deallocate_p2frame(self.base, 4)
|
||||
}
|
||||
}
|
||||
}
|
||||
impl core::fmt::Debug for Kstack {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "[kstack at {:?}]", self.base)
|
||||
}
|
||||
}
|
||||
|
||||
+3
-5
@@ -3,10 +3,8 @@ use core::iter;
|
||||
|
||||
use spinning_top::RwSpinlock;
|
||||
|
||||
use super::arch::KSTACK_SIZE;
|
||||
use super::context::{Context, ContextId};
|
||||
use super::context::{Context, ContextId, Kstack};
|
||||
use super::memory::AddrSpaceWrapper;
|
||||
use crate::common::aligned_box::AlignedBox;
|
||||
use crate::interrupt::InterruptStack;
|
||||
use crate::syscall::error::{Error, Result, EAGAIN};
|
||||
|
||||
@@ -108,14 +106,14 @@ impl ContextList {
|
||||
|
||||
/// Spawn a context from a function.
|
||||
pub fn spawn(&mut self, userspace_allowed: bool, func: extern "C" fn()) -> Result<&Arc<RwSpinlock<Context>>> {
|
||||
let mut stack = AlignedBox::<[u8; crate::context::arch::KSTACK_SIZE], {crate::context::arch::KSTACK_ALIGN}>::try_zeroed()?;
|
||||
let mut stack = Kstack::new()?;
|
||||
|
||||
let context_lock = self.new_context()?;
|
||||
{
|
||||
let mut context = context_lock.write();
|
||||
let _ = context.set_addr_space(Some(AddrSpaceWrapper::new()?));
|
||||
|
||||
let mut stack_top = unsafe { stack.as_mut_ptr().add(KSTACK_SIZE) };
|
||||
let mut stack_top = stack.initial_top();
|
||||
|
||||
const INT_REGS_SIZE: usize = core::mem::size_of::<crate::interrupt::InterruptStack>();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user