1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
use super::{PhysicalMemoryManager, SlabAllocator, Stack};
use crate::Platform;
use core::marker::PhantomData;
use hal::memory::VAddr;
use spinning_top::Spinlock;

pub struct KernelStackAllocator<P>
where
    P: Platform,
{
    kernel_stack_slots: Spinlock<SlabAllocator>,
    slot_size: usize,
    _phantom: PhantomData<P>,
}

impl<P> KernelStackAllocator<P>
where
    P: Platform,
{
    pub fn new(stacks_bottom: VAddr, stacks_top: VAddr, slot_size: usize) -> KernelStackAllocator<P> {
        KernelStackAllocator {
            kernel_stack_slots: Spinlock::new(SlabAllocator::new(stacks_bottom, stacks_top, slot_size)),
            slot_size,
            _phantom: PhantomData,
        }
    }

    pub fn alloc_kernel_stack(
        &self,
        initial_size: usize,
        physical_memory_manager: &PhysicalMemoryManager,
        kernel_page_table: &mut P::PageTable,
    ) -> Option<Stack> {
        use hal::memory::{Flags, PageTable};

        let slot_bottom = self.kernel_stack_slots.lock().alloc()?;
        let top = slot_bottom + self.slot_size - 1;
        let stack_bottom = top - initial_size + 1;

        let physical_start = physical_memory_manager.alloc_bytes(initial_size);
        kernel_page_table
            .map_area(
                stack_bottom,
                physical_start,
                initial_size,
                Flags { writable: true, ..Default::default() },
                physical_memory_manager,
            )
            .unwrap();

        Some(Stack { top, slot_bottom, stack_bottom, physical_start })
    }
}