x86_64: physical memory init
This commit is contained in:
parent
47f920addf
commit
aec161bc47
@ -12,13 +12,14 @@ yggdrasil-abi = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-abi.git" }
|
||||
|
||||
# atomic_enum = "0.2.0"
|
||||
bitflags = "2.3.3"
|
||||
# linked_list_allocator = "0.10.5"
|
||||
# spinning_top = "0.2.5"
|
||||
linked_list_allocator = "0.10.5"
|
||||
spinning_top = "0.2.5"
|
||||
# static_assertions = "1.1.0"
|
||||
# tock-registers = "0.8.1"
|
||||
cfg-if = "1.0.0"
|
||||
bitmap-font = { version = "0.3.0" }
|
||||
embedded-graphics = "0.8.0"
|
||||
git-version = "0.3.5"
|
||||
|
||||
[dependencies.elf]
|
||||
version = "0.7.2"
|
||||
|
@ -9,7 +9,6 @@ use plat_qemu::PLATFORM;
|
||||
use tock_registers::interfaces::{ReadWriteable, Readable, Writeable};
|
||||
|
||||
use crate::{
|
||||
absolute_address,
|
||||
arch::{
|
||||
aarch64::{boot::CPU_INIT_FENCE, cpu::Cpu, devtree::FdtMemoryRegionIter, smp::CPU_COUNT},
|
||||
Architecture,
|
||||
|
@ -7,12 +7,14 @@ cfg_if! {
|
||||
if #[cfg(target_arch = "aarch64")] {
|
||||
pub mod aarch64;
|
||||
|
||||
pub use aarch64::intrinsics::absolute_address;
|
||||
pub use aarch64::plat_qemu::{QemuPlatform as PlatformImpl, PLATFORM};
|
||||
pub use aarch64::{AArch64 as ArchitectureImpl, ARCHITECTURE};
|
||||
use abi::error::Error;
|
||||
use cfg_if::cfg_if;
|
||||
|
||||
} else if #[cfg(target_arch = "x86_64")] {
|
||||
#[macro_use]
|
||||
pub mod x86_64;
|
||||
|
||||
pub use x86_64::{
|
||||
|
@ -1,14 +1,23 @@
|
||||
use core::arch::global_asm;
|
||||
|
||||
use git_version::git_version;
|
||||
use yboot_proto::{
|
||||
v1::FramebufferOption, LoadProtocolHeader, LoadProtocolV1, KERNEL_MAGIC, LOADER_MAGIC,
|
||||
PROTOCOL_VERSION_1,
|
||||
v1::{FramebufferOption, MemoryMap},
|
||||
LoadProtocolHeader, LoadProtocolV1, KERNEL_MAGIC, LOADER_MAGIC, PROTOCOL_VERSION_1,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
arch::{Architecture, ArchitectureImpl},
|
||||
arch::{
|
||||
x86_64::{exception, gdt},
|
||||
Architecture, ArchitectureImpl,
|
||||
},
|
||||
debug,
|
||||
device::platform::Platform,
|
||||
mem::{
|
||||
heap,
|
||||
phys::{self, PageUsage},
|
||||
ConvertAddress,
|
||||
},
|
||||
};
|
||||
|
||||
use super::ARCHITECTURE;
|
||||
@ -35,6 +44,8 @@ static mut YBOOT_DATA: LoadProtocolV1 = LoadProtocolV1 {
|
||||
},
|
||||
kernel_virt_offset: KERNEL_VIRT_OFFSET as _,
|
||||
|
||||
memory_map: MemoryMap { address: 0, len: 0 },
|
||||
|
||||
opt_framebuffer: FramebufferOption {
|
||||
req_width: 640,
|
||||
req_height: 480,
|
||||
@ -59,16 +70,29 @@ unsafe extern "C" fn __x86_64_upper_entry() -> ! {
|
||||
ARCHITECTURE.init_primary_debug_sink();
|
||||
|
||||
debug::init();
|
||||
infoln!("Yggdrasil kernel git {} starting", git_version!());
|
||||
|
||||
let mut i = 0;
|
||||
loop {
|
||||
debugln!("{} {}", env!("PROFILE"), i);
|
||||
i += 1;
|
||||
if YBOOT_DATA.memory_map.address > 0xFFFFFFFF {
|
||||
errorln!("Unhandled case: memory map is above 4GiB");
|
||||
loop {
|
||||
ArchitectureImpl::wait_for_interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
// loop {
|
||||
// ArchitectureImpl::wait_for_interrupt();
|
||||
// }
|
||||
gdt::init();
|
||||
exception::init_exceptions(0);
|
||||
|
||||
// Setup physical memory allocation
|
||||
ArchitectureImpl::init_physical_memory(&YBOOT_DATA.memory_map);
|
||||
|
||||
// Allocate memory for the kernel heap
|
||||
let heap_base = phys::alloc_pages_contiguous(16, PageUsage::Used)
|
||||
.expect("Could not allocate a block for heap");
|
||||
heap::init_heap(heap_base.virtualize(), 16 * 0x1000);
|
||||
|
||||
loop {
|
||||
ArchitectureImpl::wait_for_interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
global_asm!(
|
||||
|
102
src/arch/x86_64/exception.rs
Normal file
102
src/arch/x86_64/exception.rs
Normal file
@ -0,0 +1,102 @@
|
||||
use core::{arch::global_asm, mem::size_of_val};
|
||||
|
||||
use crate::arch::{Architecture, ArchitectureImpl};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub struct ExceptionFrame {
|
||||
rax: usize,
|
||||
rcx: usize,
|
||||
rdx: usize,
|
||||
rbx: usize,
|
||||
rsi: usize,
|
||||
rdi: usize,
|
||||
rbp: usize,
|
||||
r8: usize,
|
||||
r9: usize,
|
||||
r10: usize,
|
||||
r11: usize,
|
||||
r12: usize,
|
||||
r13: usize,
|
||||
r14: usize,
|
||||
r15: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(packed)]
|
||||
struct Entry {
|
||||
base_lo: u16,
|
||||
selector: u16,
|
||||
__res0: u8,
|
||||
flags: u8,
|
||||
base_hi: u16,
|
||||
base_ex: u32,
|
||||
__res1: u32,
|
||||
}
|
||||
|
||||
#[repr(packed)]
|
||||
struct Pointer {
|
||||
limit: u16,
|
||||
offset: usize,
|
||||
}
|
||||
|
||||
const SIZE: usize = 256;
|
||||
|
||||
impl Entry {
|
||||
const PRESENT: u8 = 1 << 7;
|
||||
const INT32: u8 = 0xE;
|
||||
|
||||
const NULL: Self = Self {
|
||||
base_lo: 0,
|
||||
base_hi: 0,
|
||||
base_ex: 0,
|
||||
selector: 0,
|
||||
flags: 0,
|
||||
__res0: 0,
|
||||
__res1: 0,
|
||||
};
|
||||
|
||||
const fn new(base: usize, selector: u16, flags: u8) -> Self {
|
||||
Self {
|
||||
base_lo: (base & 0xFFFF) as u16,
|
||||
base_hi: ((base >> 16) & 0xFFFF) as u16,
|
||||
base_ex: (base >> 32) as u32,
|
||||
selector,
|
||||
flags,
|
||||
__res0: 0,
|
||||
__res1: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static mut IDT: [Entry; SIZE] = [Entry::NULL; SIZE];
|
||||
|
||||
extern "C" fn __x86_64_exception_handler() {
|
||||
errorln!("An exception occurrred");
|
||||
loop {
|
||||
ArchitectureImpl::wait_for_interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn init_exceptions(_cpu_index: usize) {
|
||||
extern "C" {
|
||||
static __x86_64_exception_vectors: [usize; 32];
|
||||
}
|
||||
|
||||
for (i, &entry) in __x86_64_exception_vectors.iter().enumerate() {
|
||||
IDT[i] = Entry::new(entry, 0x08, Entry::PRESENT | Entry::INT32);
|
||||
}
|
||||
|
||||
let idtr = Pointer {
|
||||
limit: size_of_val(&IDT) as u16 - 1,
|
||||
offset: &IDT as *const _ as usize,
|
||||
};
|
||||
|
||||
core::arch::asm!("wbinvd; lidt ({0})", in(reg) &idtr, options(att_syntax));
|
||||
}
|
||||
|
||||
global_asm!(
|
||||
include_str!("vectors.S"),
|
||||
exception_handler = sym __x86_64_exception_handler,
|
||||
options(att_syntax)
|
||||
);
|
111
src/arch/x86_64/gdt.rs
Normal file
111
src/arch/x86_64/gdt.rs
Normal file
@ -0,0 +1,111 @@
|
||||
// TODO TSS
|
||||
|
||||
use core::mem::size_of_val;
|
||||
|
||||
#[repr(packed)]
|
||||
struct Entry {
|
||||
limit_lo: u16,
|
||||
base_lo: u16,
|
||||
base_mi: u8,
|
||||
access: u8,
|
||||
flags: u8,
|
||||
base_hi: u8,
|
||||
}
|
||||
|
||||
#[repr(packed)]
|
||||
struct Pointer {
|
||||
limit: u16,
|
||||
offset: usize,
|
||||
}
|
||||
|
||||
impl Entry {
|
||||
const FLAG_LONG: u8 = 1 << 5;
|
||||
const ACC_PRESENT: u8 = 1 << 7;
|
||||
const ACC_SYSTEM: u8 = 1 << 4;
|
||||
const ACC_EXECUTE: u8 = 1 << 3;
|
||||
const ACC_WRITE: u8 = 1 << 1;
|
||||
const ACC_RING3: u8 = 3 << 5;
|
||||
const ACC_ACCESS: u8 = 1 << 0;
|
||||
|
||||
const NULL: Self = Self {
|
||||
base_lo: 0,
|
||||
base_mi: 0,
|
||||
base_hi: 0,
|
||||
access: 0,
|
||||
flags: 0,
|
||||
limit_lo: 0,
|
||||
};
|
||||
|
||||
const fn new(base: u32, limit: u32, flags: u8, access: u8) -> Self {
|
||||
Self {
|
||||
base_lo: (base & 0xFFFF) as u16,
|
||||
base_mi: ((base >> 16) & 0xFF) as u8,
|
||||
base_hi: ((base >> 24) & 0xFF) as u8,
|
||||
access,
|
||||
flags: (flags & 0xF0) | (((limit >> 16) & 0xF) as u8),
|
||||
limit_lo: (limit & 0xFFFF) as u16,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const SIZE: usize = 3;
|
||||
|
||||
// TODO per-CPU
|
||||
static mut GDT: [Entry; SIZE] = [
|
||||
// 0x00, NULL
|
||||
Entry::NULL,
|
||||
// 0x08, Ring0 CS64
|
||||
Entry::new(
|
||||
0,
|
||||
0,
|
||||
Entry::FLAG_LONG,
|
||||
Entry::ACC_PRESENT | Entry::ACC_SYSTEM | Entry::ACC_EXECUTE,
|
||||
),
|
||||
// 0x10, Ring0 DS64
|
||||
Entry::new(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
Entry::ACC_PRESENT | Entry::ACC_SYSTEM | Entry::ACC_WRITE,
|
||||
),
|
||||
];
|
||||
|
||||
pub unsafe fn init() {
|
||||
let gdtr = Pointer {
|
||||
limit: size_of_val(&GDT) as u16 - 1,
|
||||
offset: &GDT as *const _ as usize,
|
||||
};
|
||||
|
||||
core::arch::asm!(
|
||||
r#"
|
||||
wbinvd
|
||||
lgdt ({0})
|
||||
|
||||
// Have to use iretq here
|
||||
mov %rsp, %rcx
|
||||
leaq 1f(%rip), %rax
|
||||
|
||||
// SS:RSP
|
||||
pushq $0x10
|
||||
pushq %rcx
|
||||
|
||||
// RFLAGS
|
||||
pushfq
|
||||
|
||||
// CS:RIP
|
||||
pushq $0x08
|
||||
pushq %rax
|
||||
iretq
|
||||
1:
|
||||
mov $0x10, %ax
|
||||
mov %ax, %ds
|
||||
mov %ax, %es
|
||||
mov %ax, %fs
|
||||
mov %ax, %gs
|
||||
mov %ax, %ss
|
||||
"#,
|
||||
in(reg) &gdtr,
|
||||
out("rax") _,
|
||||
options(att_syntax)
|
||||
);
|
||||
}
|
12
src/arch/x86_64/intrinsics.rs
Normal file
12
src/arch/x86_64/intrinsics.rs
Normal file
@ -0,0 +1,12 @@
|
||||
/// Returns an absolute address to the given symbol
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! absolute_address {
|
||||
($sym:expr) => {{
|
||||
let mut _x: usize;
|
||||
unsafe {
|
||||
core::arch::asm!("movabsq ${1}, {0}", out(reg) _x, sym $sym, options(att_syntax));
|
||||
}
|
||||
_x
|
||||
}};
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
use abi::error::Error;
|
||||
use yboot_proto::v1::FramebufferOption;
|
||||
use yboot_proto::{v1::FramebufferOption, AvailableRegion, IterableMemoryMap};
|
||||
|
||||
use crate::{
|
||||
arch::x86_64::table::{init_fixed_tables, KERNEL_TABLES},
|
||||
@ -8,14 +8,59 @@ use crate::{
|
||||
display::{fb_console::FramebufferConsole, linear_fb::LinearFramebuffer},
|
||||
platform::Platform,
|
||||
},
|
||||
mem::phys::{self, reserved::reserve_region, PhysicalMemoryRegion},
|
||||
util::OneTimeInit,
|
||||
};
|
||||
|
||||
use super::Architecture;
|
||||
|
||||
#[macro_use]
|
||||
pub mod intrinsics;
|
||||
|
||||
pub mod boot;
|
||||
pub mod exception;
|
||||
pub mod gdt;
|
||||
pub mod table;
|
||||
|
||||
pub trait AbstractAvailableRegion {
|
||||
fn start_address(&self) -> usize;
|
||||
fn page_count(&self) -> usize;
|
||||
}
|
||||
|
||||
pub trait AbstractMemoryMap<'a>: 'a {
|
||||
type AvailableRegion: AbstractAvailableRegion;
|
||||
type Iter: Iterator<Item = &'a Self::AvailableRegion> + Clone;
|
||||
|
||||
fn reserved_range(&self) -> PhysicalMemoryRegion;
|
||||
fn iter(&self) -> Self::Iter;
|
||||
}
|
||||
|
||||
impl<T: AvailableRegion> AbstractAvailableRegion for T {
|
||||
fn start_address(&self) -> usize {
|
||||
<T as AvailableRegion>::start_address(self)
|
||||
}
|
||||
|
||||
fn page_count(&self) -> usize {
|
||||
<T as AvailableRegion>::page_count(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: IterableMemoryMap<'a> + 'a> AbstractMemoryMap<'a> for T {
|
||||
type AvailableRegion = T::Entry;
|
||||
type Iter = T::Iter;
|
||||
|
||||
fn reserved_range(&self) -> PhysicalMemoryRegion {
|
||||
PhysicalMemoryRegion {
|
||||
base: self.data_physical_base(),
|
||||
size: (self.data_size() + 0xFFF) & !0xFFF,
|
||||
}
|
||||
}
|
||||
|
||||
fn iter(&self) -> Self::Iter {
|
||||
<T as IterableMemoryMap>::iter_with_offset(self, X86_64::KERNEL_VIRT_OFFSET)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct X86_64 {
|
||||
yboot_framebuffer: OneTimeInit<FramebufferOption>,
|
||||
}
|
||||
@ -61,6 +106,8 @@ impl Architecture for X86_64 {
|
||||
}
|
||||
|
||||
impl Platform for X86_64 {
|
||||
const KERNEL_PHYS_BASE: usize = 0x400000;
|
||||
|
||||
unsafe fn init(&'static self, _is_bsp: bool) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
@ -100,6 +147,27 @@ impl Platform for X86_64 {
|
||||
}
|
||||
}
|
||||
|
||||
impl X86_64 {
|
||||
unsafe fn init_physical_memory<'a, M: AbstractMemoryMap<'a>>(memory_map: &M) {
|
||||
// Reserve the lower 8MiB of memory
|
||||
reserve_region(
|
||||
"lower-memory",
|
||||
PhysicalMemoryRegion {
|
||||
base: 0,
|
||||
size: 8 << 21,
|
||||
},
|
||||
);
|
||||
// Reserve memory map
|
||||
reserve_region("memory-map", memory_map.reserved_range());
|
||||
|
||||
phys::init_from_iter(memory_map.iter().map(|r| PhysicalMemoryRegion {
|
||||
base: r.start_address(),
|
||||
size: r.page_count() * 0x1000,
|
||||
}))
|
||||
.expect("Failed to initialize the physical memory manager");
|
||||
}
|
||||
}
|
||||
|
||||
pub static ARCHITECTURE: X86_64 = X86_64 {
|
||||
yboot_framebuffer: OneTimeInit::new(),
|
||||
};
|
||||
|
@ -24,6 +24,7 @@ pub struct FixedTables {
|
||||
// 512 entries
|
||||
device_l3: PageTable<L3>,
|
||||
|
||||
device_l2i: usize,
|
||||
device_l3i: usize,
|
||||
}
|
||||
|
||||
@ -43,6 +44,7 @@ impl FixedTables {
|
||||
device_l2: PageTable::zeroed(),
|
||||
device_l3: PageTable::zeroed(),
|
||||
|
||||
device_l2i: 1,
|
||||
device_l3i: 0,
|
||||
}
|
||||
}
|
||||
@ -51,8 +53,20 @@ impl FixedTables {
|
||||
if count > 512 * 512 {
|
||||
panic!("Unsupported device memory mapping size");
|
||||
} else if count > 512 {
|
||||
let count = (count + 511) / 512;
|
||||
// 2MiB mappings
|
||||
todo!();
|
||||
if self.device_l2i + count > 512 {
|
||||
return Err(Error::OutOfMemory);
|
||||
}
|
||||
|
||||
let virt = DEVICE_VIRT_OFFSET + (self.device_l2i << 21);
|
||||
for i in 0..count {
|
||||
self.device_l2[self.device_l2i + i] =
|
||||
PageEntry::block(phys, PageAttributes::WRITABLE);
|
||||
}
|
||||
self.device_l2i += count;
|
||||
|
||||
Ok(virt)
|
||||
} else {
|
||||
// 4KiB mappings
|
||||
if self.device_l3i + count > 512 {
|
||||
|
139
src/arch/x86_64/vectors.S
Normal file
139
src/arch/x86_64/vectors.S
Normal file
@ -0,0 +1,139 @@
|
||||
.macro ISR_NERR, n
|
||||
__x86_64_exc_\n:
|
||||
cli
|
||||
pushq $0
|
||||
pushq $\n
|
||||
jmp __x86_64_exc_common
|
||||
.endm
|
||||
|
||||
.macro ISR_YERR, n
|
||||
__x86_64_exc_\n:
|
||||
cli
|
||||
pushq $\n
|
||||
jmp __x86_64_exc_common
|
||||
.endm
|
||||
|
||||
// 16 general-purpose registers
|
||||
.set PT_REGS_SIZE, 15 * 8
|
||||
|
||||
.macro EXC_SAVE_STATE
|
||||
sub $PT_REGS_SIZE, %rsp
|
||||
mov %rax, 0(%rsp)
|
||||
mov %rcx, 8(%rsp)
|
||||
mov %rdx, 16(%rsp)
|
||||
mov %rbx, 32(%rsp)
|
||||
mov %rsi, 36(%rsp)
|
||||
mov %rdi, 40(%rsp)
|
||||
mov %rbp, 48(%rsp)
|
||||
|
||||
mov %r8, 52(%rsp)
|
||||
mov %r9, 56(%rsp)
|
||||
mov %r10, 60(%rsp)
|
||||
mov %r11, 64(%rsp)
|
||||
mov %r12, 68(%rsp)
|
||||
mov %r13, 72(%rsp)
|
||||
mov %r14, 76(%rsp)
|
||||
mov %r15, 80(%rsp)
|
||||
.endm
|
||||
|
||||
.macro EXC_RESTORE_STATE
|
||||
mov 0(%rsp), %rax
|
||||
mov 8(%rsp), %rcx
|
||||
mov 16(%rsp), %rdx
|
||||
mov 32(%rsp), %rbx
|
||||
mov 36(%rsp), %rsi
|
||||
mov 40(%rsp), %rdi
|
||||
mov 48(%rsp), %rbp
|
||||
|
||||
mov 52(%rsp), %r8
|
||||
mov 56(%rsp), %r9
|
||||
mov 60(%rsp), %r10
|
||||
mov 64(%rsp), %r11
|
||||
mov 68(%rsp), %r12
|
||||
mov 72(%rsp), %r13
|
||||
mov 76(%rsp), %r14
|
||||
mov 80(%rsp), %r15
|
||||
.endm
|
||||
|
||||
.global __x86_64_exception_vectors
|
||||
.section .text
|
||||
__x86_64_exc_common:
|
||||
EXC_SAVE_STATE
|
||||
mov %rsp, %rdi
|
||||
call {exception_handler}
|
||||
|
||||
// TODO
|
||||
1:
|
||||
cli
|
||||
hlt
|
||||
jmp 1b
|
||||
|
||||
ISR_NERR 0
|
||||
ISR_NERR 1
|
||||
ISR_NERR 2
|
||||
ISR_NERR 3
|
||||
ISR_NERR 4
|
||||
ISR_NERR 5
|
||||
ISR_NERR 6
|
||||
ISR_NERR 7
|
||||
ISR_YERR 8
|
||||
ISR_NERR 9
|
||||
ISR_YERR 10
|
||||
ISR_YERR 11
|
||||
ISR_YERR 12
|
||||
ISR_YERR 13
|
||||
ISR_YERR 14
|
||||
ISR_NERR 15
|
||||
ISR_NERR 16
|
||||
ISR_YERR 17
|
||||
ISR_NERR 18
|
||||
ISR_NERR 19
|
||||
ISR_NERR 20
|
||||
ISR_NERR 21
|
||||
ISR_NERR 22
|
||||
ISR_NERR 23
|
||||
ISR_NERR 24
|
||||
ISR_NERR 25
|
||||
ISR_NERR 26
|
||||
ISR_NERR 27
|
||||
ISR_NERR 28
|
||||
ISR_NERR 29
|
||||
ISR_YERR 30
|
||||
ISR_NERR 31
|
||||
|
||||
.section .rodata
|
||||
.global __x86_64_exception_vectors
|
||||
.p2align 4
|
||||
__x86_64_exception_vectors:
|
||||
.quad __x86_64_exc_0
|
||||
.quad __x86_64_exc_1
|
||||
.quad __x86_64_exc_2
|
||||
.quad __x86_64_exc_3
|
||||
.quad __x86_64_exc_4
|
||||
.quad __x86_64_exc_5
|
||||
.quad __x86_64_exc_6
|
||||
.quad __x86_64_exc_7
|
||||
.quad __x86_64_exc_8
|
||||
.quad __x86_64_exc_9
|
||||
.quad __x86_64_exc_10
|
||||
.quad __x86_64_exc_11
|
||||
.quad __x86_64_exc_12
|
||||
.quad __x86_64_exc_13
|
||||
.quad __x86_64_exc_14
|
||||
.quad __x86_64_exc_15
|
||||
.quad __x86_64_exc_16
|
||||
.quad __x86_64_exc_17
|
||||
.quad __x86_64_exc_18
|
||||
.quad __x86_64_exc_19
|
||||
.quad __x86_64_exc_20
|
||||
.quad __x86_64_exc_21
|
||||
.quad __x86_64_exc_22
|
||||
.quad __x86_64_exc_23
|
||||
.quad __x86_64_exc_24
|
||||
.quad __x86_64_exc_25
|
||||
.quad __x86_64_exc_26
|
||||
.quad __x86_64_exc_27
|
||||
.quad __x86_64_exc_28
|
||||
.quad __x86_64_exc_29
|
||||
.quad __x86_64_exc_30
|
||||
.quad __x86_64_exc_31
|
@ -39,9 +39,14 @@ impl LinearFramebuffer {
|
||||
stride,
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
let res = Self {
|
||||
inner: IrqSafeSpinlock::new(inner),
|
||||
})
|
||||
};
|
||||
|
||||
// Clear the screen
|
||||
res.lock().fill_rows(0, height, 0);
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
// TODO doesn't actually lock
|
||||
|
@ -12,7 +12,7 @@ pub trait Platform {
|
||||
// type IrqNumber;
|
||||
|
||||
/// Address, to which the kernel is expected to be loaded for this platform
|
||||
// const KERNEL_PHYS_BASE: usize;
|
||||
const KERNEL_PHYS_BASE: usize;
|
||||
|
||||
/// Initializes the platform devices to their usable state.
|
||||
///
|
||||
@ -21,27 +21,24 @@ pub trait Platform {
|
||||
/// Unsafe to call if the platform has already been initialized.
|
||||
unsafe fn init(&'static self, is_bsp: bool) -> Result<(), Error>;
|
||||
|
||||
// TODO use init_debug instead and let the platform code handle it
|
||||
/// Initializes the primary output device to provide the debugging output as early as possible.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Unsafe to call if the device has already been initialized.
|
||||
unsafe fn init_primary_debug_sink(&self);
|
||||
|
||||
// /// Initializes the primary serial device to provide the debugging output as early as possible.
|
||||
// ///
|
||||
// /// # Safety
|
||||
// ///
|
||||
// /// Unsafe to call if the device has already been initialized.
|
||||
// unsafe fn init_primary_serial(&self);
|
||||
|
||||
/// Returns a display name for the platform
|
||||
fn name(&self) -> &'static str;
|
||||
|
||||
/// Returns a reference to the primary debug output device.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// May not be initialized at the moment of calling.
|
||||
fn primary_debug_sink(&self) -> Option<&dyn DebugSink>;
|
||||
|
||||
// /// Returns a reference to the primary serial device.
|
||||
// ///
|
||||
// /// # Note
|
||||
// ///
|
||||
// /// May not be initialized at the moment of calling.
|
||||
// fn primary_serial(&self) -> Option<&dyn SerialDevice>;
|
||||
|
||||
// /// Returns a reference to the platform's interrupt controller.
|
||||
// ///
|
||||
// /// # Note
|
||||
|
10
src/main.rs
10
src/main.rs
@ -27,7 +27,7 @@ extern crate yggdrasil_abi as abi;
|
||||
// use task::process::Process;
|
||||
// use vfs::{Filesystem, IoContext, VnodeRef};
|
||||
//
|
||||
// extern crate alloc;
|
||||
extern crate alloc;
|
||||
//
|
||||
#[macro_use]
|
||||
pub mod debug;
|
||||
@ -36,7 +36,13 @@ pub mod arch;
|
||||
|
||||
#[panic_handler]
|
||||
fn panic_handler(_pi: &core::panic::PanicInfo) -> ! {
|
||||
loop {}
|
||||
use arch::{Architecture, ArchitectureImpl};
|
||||
|
||||
fatalln!("KERNEL PANIC");
|
||||
|
||||
loop {
|
||||
ArchitectureImpl::wait_for_interrupt();
|
||||
}
|
||||
}
|
||||
//
|
||||
pub mod device;
|
||||
|
@ -1,27 +1,25 @@
|
||||
//! Memory management utilities and types
|
||||
use core::{alloc::Layout, mem::size_of};
|
||||
// use core::{alloc::Layout, mem::size_of};
|
||||
|
||||
// use abi::error::Error;
|
||||
//
|
||||
// use crate::{
|
||||
// arch::{Architecture, ArchitectureImpl, PlatformImpl},
|
||||
// device::platform::Platform,
|
||||
// };
|
||||
use crate::{
|
||||
arch::{Architecture, ArchitectureImpl, PlatformImpl},
|
||||
device::platform::Platform,
|
||||
};
|
||||
//
|
||||
// use self::table::AddressSpace;
|
||||
|
||||
pub mod device;
|
||||
// pub mod heap;
|
||||
// pub mod phys;
|
||||
pub mod heap;
|
||||
pub mod phys;
|
||||
pub mod table;
|
||||
|
||||
/// Kernel's physical load address
|
||||
// pub const KERNEL_PHYS_BASE: usize = PlatformImpl::KERNEL_PHYS_BASE;
|
||||
pub const KERNEL_PHYS_BASE: usize = PlatformImpl::KERNEL_PHYS_BASE;
|
||||
/// Kernel's virtual memory mapping offset (i.e. kernel's virtual address is [KERNEL_PHYS_BASE] +
|
||||
/// [KERNEL_VIRT_OFFSET])
|
||||
// pub const KERNEL_VIRT_OFFSET: usize = ArchitectureImpl::KERNEL_VIRT_OFFSET;
|
||||
// TODO fix this
|
||||
pub const KERNEL_VIRT_OFFSET: usize = 0xFFFFFF8000000000;
|
||||
pub const KERNEL_VIRT_OFFSET: usize = ArchitectureImpl::KERNEL_VIRT_OFFSET;
|
||||
|
||||
/// Interface for converting between address spaces.
|
||||
///
|
||||
|
@ -4,7 +4,6 @@ use core::{iter::StepBy, mem::size_of, ops::Range};
|
||||
use abi::error::Error;
|
||||
|
||||
use crate::{
|
||||
absolute_address,
|
||||
debug::LogLevel,
|
||||
mem::{
|
||||
phys::reserved::{is_reserved, reserve_region},
|
||||
@ -16,6 +15,10 @@ use crate::{
|
||||
|
||||
use self::manager::PhysicalMemoryManager;
|
||||
|
||||
// Enumerating lots of pages is slow and I'm too lazy right now to write a better algorithm, so
|
||||
// capping the page count helps
|
||||
const PHYS_MEMORY_PAGE_CAP: usize = 65536;
|
||||
|
||||
pub mod manager;
|
||||
pub mod reserved;
|
||||
|
||||
@ -229,6 +232,10 @@ pub unsafe fn init_from_iter<I: Iterator<Item = PhysicalMemoryRegion> + Clone>(
|
||||
let mut page_count = 0;
|
||||
|
||||
for region in it {
|
||||
if page_count >= PHYS_MEMORY_PAGE_CAP {
|
||||
break;
|
||||
}
|
||||
|
||||
for page in region.pages() {
|
||||
if is_reserved(page) {
|
||||
continue;
|
||||
@ -236,10 +243,14 @@ pub unsafe fn init_from_iter<I: Iterator<Item = PhysicalMemoryRegion> + Clone>(
|
||||
|
||||
manager.add_available_page(page);
|
||||
page_count += 1;
|
||||
|
||||
if page_count >= PHYS_MEMORY_PAGE_CAP {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
infoln!("{} available pages", page_count);
|
||||
infoln!("{} available pages ({}KiB)", page_count, page_count * 4);
|
||||
|
||||
PHYSICAL_MEMORY.init(IrqSafeSpinlock::new(manager));
|
||||
Ok(())
|
||||
|
Loading…
x
Reference in New Issue
Block a user