feat: tasks
This commit is contained in:
+55
-7
@@ -3,10 +3,16 @@ use crate::memory::{
|
||||
VirtualAddr,
|
||||
};
|
||||
|
||||
const STACK_PAGES: usize = 16;
|
||||
const STACK_SIZE: usize = STACK_PAGES * FRAME_SIZE;
|
||||
const GUARD_PAGES: usize = 1; // 4KiB
|
||||
const KERNEL_STACK_PAGES: usize = 8; // 32KiB
|
||||
const USER_STACK_PAGES: usize = 16; // 64KiB
|
||||
const KERNEL_STACK_SIZE: usize = KERNEL_STACK_PAGES * FRAME_SIZE;
|
||||
const USER_STACK_SIZE: usize = USER_STACK_PAGES * FRAME_SIZE;
|
||||
|
||||
const KERNEL_SLOT_SIZE: usize = (KERNEL_STACK_PAGES + GUARD_PAGES) * FRAME_SIZE;
|
||||
const MAX_KERNEL_STACKS: usize = 64;
|
||||
const KERNEL_STACK_BASE: usize = 0xFFFF_FFFE_0000_0000;
|
||||
|
||||
const KERNEL_STACK_TOP: VirtualAddr = VirtualAddr::new(0xFFFF_FFFE_0000_0000);
|
||||
const USER_STACK_TOP: VirtualAddr = VirtualAddr::new(0x0000_7FFF_FFFF_F000);
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -14,13 +20,16 @@ pub enum StackCreateError {
|
||||
AddressOverflow,
|
||||
UnalignedStackTop,
|
||||
OutOfFrames,
|
||||
OutOfStacks,
|
||||
GuardPageMapped,
|
||||
Map(MapError),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct StackMapping {
|
||||
guard_page: VirtualAddr,
|
||||
mapped_start: VirtualAddr,
|
||||
stack_size: usize,
|
||||
top: VirtualAddr,
|
||||
}
|
||||
|
||||
@@ -28,6 +37,7 @@ impl StackMapping {
|
||||
fn allocate(
|
||||
address_space: &mut AddressSpace,
|
||||
allocator: &mut FrameAllocator,
|
||||
stack_size: usize,
|
||||
top: VirtualAddr,
|
||||
permissions: PagePermissions,
|
||||
) -> Result<Self, StackCreateError> {
|
||||
@@ -37,7 +47,7 @@ impl StackMapping {
|
||||
|
||||
let mapped_start = VirtualAddr::new(
|
||||
top.as_usize()
|
||||
.checked_sub(STACK_SIZE)
|
||||
.checked_sub(stack_size)
|
||||
.ok_or(StackCreateError::AddressOverflow)?,
|
||||
);
|
||||
let guard_page = VirtualAddr::new(
|
||||
@@ -53,7 +63,7 @@ impl StackMapping {
|
||||
|
||||
let mut mapped_pages = 0;
|
||||
|
||||
while mapped_pages < STACK_PAGES {
|
||||
while mapped_pages < stack_size / FRAME_SIZE {
|
||||
let virtual_address = VirtualAddr::new(
|
||||
mapped_start
|
||||
.as_usize()
|
||||
@@ -89,6 +99,7 @@ impl StackMapping {
|
||||
Ok(Self {
|
||||
guard_page,
|
||||
mapped_start,
|
||||
stack_size,
|
||||
top,
|
||||
})
|
||||
}
|
||||
@@ -115,7 +126,7 @@ impl StackMapping {
|
||||
/// The caller must ensure this stack is not active on any CPU and cannot be accessed by any
|
||||
/// kernel operation while it is being destroyed.
|
||||
unsafe fn destroy(self, address_space: &mut AddressSpace, allocator: &mut FrameAllocator) {
|
||||
for page in (0..STACK_PAGES).rev() {
|
||||
for page in (0..self.stack_size / FRAME_SIZE).rev() {
|
||||
let virtual_address =
|
||||
VirtualAddr::new(self.mapped_start.as_usize() + page * FRAME_SIZE);
|
||||
let frame = unsafe {
|
||||
@@ -130,6 +141,7 @@ impl StackMapping {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct KernelStack {
|
||||
mapping: StackMapping,
|
||||
}
|
||||
@@ -137,12 +149,14 @@ pub struct KernelStack {
|
||||
impl KernelStack {
|
||||
pub fn allocate(
|
||||
address_space: &mut AddressSpace,
|
||||
top: usize,
|
||||
allocator: &mut FrameAllocator,
|
||||
) -> Result<Self, StackCreateError> {
|
||||
let mapping = StackMapping::allocate(
|
||||
address_space,
|
||||
allocator,
|
||||
KERNEL_STACK_TOP,
|
||||
KERNEL_STACK_SIZE,
|
||||
VirtualAddr::new(top),
|
||||
PagePermissions::new(true, false, false),
|
||||
)?;
|
||||
|
||||
@@ -175,6 +189,7 @@ impl UserStack {
|
||||
let mapping = StackMapping::allocate(
|
||||
address_space,
|
||||
allocator,
|
||||
USER_STACK_SIZE,
|
||||
top,
|
||||
PagePermissions::new(true, false, true),
|
||||
)?;
|
||||
@@ -194,3 +209,36 @@ impl UserStack {
|
||||
unsafe { self.mapping.destroy(address_space, allocator) };
|
||||
}
|
||||
}
|
||||
|
||||
pub struct KernelStackPool {
|
||||
free_slots: u64, // bitmap
|
||||
}
|
||||
|
||||
impl KernelStackPool {
|
||||
pub fn new() -> Self {
|
||||
Self { free_slots: 0 }
|
||||
}
|
||||
|
||||
pub fn allocate(
|
||||
&mut self,
|
||||
address_space: &mut AddressSpace,
|
||||
allocator: &mut FrameAllocator,
|
||||
) -> Result<KernelStack, StackCreateError> {
|
||||
let mut slot = 0;
|
||||
while slot < MAX_KERNEL_STACKS {
|
||||
if self.free_slots & (1 << slot) == 0 {
|
||||
self.free_slots |= 1 << slot;
|
||||
let top = KERNEL_STACK_BASE + ((slot + 1) * KERNEL_SLOT_SIZE);
|
||||
return KernelStack::allocate(address_space, top, allocator);
|
||||
}
|
||||
slot += 1;
|
||||
}
|
||||
|
||||
Err(StackCreateError::OutOfStacks)
|
||||
}
|
||||
|
||||
pub fn free(&mut self, stack: &KernelStack) {
|
||||
let slot = (stack.top().as_usize() - KERNEL_STACK_BASE) / KERNEL_SLOT_SIZE - 1;
|
||||
self.free_slots &= !(1 << slot);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user