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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#![no_std]
#![feature(
decl_macro,
allocator_api,
alloc_error_handler,
core_intrinsics,
trait_alias,
type_ascription,
naked_functions,
box_syntax,
const_btree_new,
get_mut_unchecked
)]
#[macro_use]
extern crate alloc;
mod heap_allocator;
pub mod memory;
pub mod object;
pub mod pci;
pub mod per_cpu;
pub mod scheduler;
pub mod syscall;
use crate::memory::Stack;
use alloc::{boxed::Box, sync::Arc};
use core::pin::Pin;
use hal::memory::{FrameSize, PageTable, VAddr};
use heap_allocator::LockedHoleAllocator;
use memory::{KernelStackAllocator, PhysicalMemoryManager};
use object::{address_space::AddressSpace, memory_object::MemoryObject, task::Task, KernelObject, KernelObjectId};
use pci::PciInfo;
use pci_types::ConfigRegionAccess as PciConfigRegionAccess;
use per_cpu::PerCpu;
use poplar_util::InitGuard;
use scheduler::Scheduler;
use seed::boot_info::LoadedImage;
use spin::{Mutex, RwLock};
#[cfg(not(test))]
#[global_allocator]
pub static ALLOCATOR: LockedHoleAllocator = LockedHoleAllocator::new_uninitialized();
pub static PHYSICAL_MEMORY_MANAGER: InitGuard<PhysicalMemoryManager> = InitGuard::uninit();
pub static FRAMEBUFFER: InitGuard<(poplar::syscall::FramebufferInfo, Arc<MemoryObject>)> = InitGuard::uninit();
pub static PCI_INFO: RwLock<Option<PciInfo>> = RwLock::new(None);
pub static PCI_ACCESS: InitGuard<Option<Mutex<Box<dyn PciConfigRegionAccess>>>> = InitGuard::uninit();
pub trait Platform: Sized + 'static {
type PageTableSize: FrameSize;
type PageTable: PageTable<Self::PageTableSize> + Send;
type PerCpu: PerCpu<Self>;
fn kernel_page_table(&mut self) -> &mut Self::PageTable;
fn per_cpu<'a>() -> Pin<&'a mut Self::PerCpu>;
unsafe fn initialize_task_stacks(
kernel_stack: &Stack,
user_stack: &Stack,
task_entry_point: VAddr,
) -> (VAddr, VAddr);
unsafe fn context_switch(current_kernel_stack: *mut VAddr, new_kernel_stack: VAddr);
unsafe fn drop_into_userspace() -> !;
}
pub fn load_task<P>(
scheduler: &mut Scheduler<P>,
image: &LoadedImage,
kernel_page_table: &mut P::PageTable,
allocator: &PhysicalMemoryManager,
kernel_stack_allocator: &mut KernelStackAllocator<P>,
) where
P: Platform,
{
use object::SENTINEL_KERNEL_ID;
let address_space = AddressSpace::new(SENTINEL_KERNEL_ID, kernel_page_table, allocator);
let task = Task::from_boot_info(
SENTINEL_KERNEL_ID,
address_space.clone(),
image,
allocator,
kernel_page_table,
kernel_stack_allocator,
)
.expect("Failed to load initial task");
for segment in &image.segments {
let memory_object = MemoryObject::from_boot_info(task.id(), segment);
address_space.map_memory_object(memory_object, None, allocator).unwrap();
}
scheduler.add_task(task);
}
pub fn create_framebuffer(video_info: &seed::boot_info::VideoModeInfo) {
use hal::memory::{Flags, Size4KiB};
use poplar::syscall::{FramebufferInfo, PixelFormat};
use seed::boot_info::PixelFormat as BootPixelFormat;
const BPP: usize = 4;
let size_in_bytes = video_info.stride * video_info.height * BPP;
let memory_object = MemoryObject::new(
object::SENTINEL_KERNEL_ID,
None,
video_info.framebuffer_address,
poplar_util::math::align_up(size_in_bytes, Size4KiB::SIZE),
Flags { writable: true, user_accessible: true, cached: false, ..Default::default() },
);
let info = FramebufferInfo {
width: video_info.width as u16,
height: video_info.height as u16,
stride: video_info.stride as u16,
pixel_format: match video_info.pixel_format {
BootPixelFormat::Rgb32 => PixelFormat::Rgb32,
BootPixelFormat::Bgr32 => PixelFormat::Bgr32,
},
};
FRAMEBUFFER.initialize((info, memory_object));
}