174 lines
4.0 KiB
Rust
174 lines
4.0 KiB
Rust
//! x86-64 boot and entry functions
|
|
use core::{arch::global_asm, sync::atomic::Ordering};
|
|
|
|
use kernel_fs::devfs;
|
|
use kernel_util::runtime;
|
|
use tock_registers::interfaces::Writeable;
|
|
use yboot_proto::{
|
|
v1::{FramebufferOption, MemoryMap},
|
|
LoadProtocolHeader, LoadProtocolV1, KERNEL_MAGIC, LOADER_MAGIC, PROTOCOL_VERSION_1,
|
|
};
|
|
|
|
use crate::{
|
|
arch::x86_64::{registers::MSR_IA32_KERNEL_GS_BASE, smp::CPU_COUNT},
|
|
kernel_main, kernel_secondary_main,
|
|
mem::KERNEL_VIRT_OFFSET,
|
|
};
|
|
|
|
use super::{cpuid::init_cpuid, exception, ARCHITECTURE};
|
|
|
|
pub enum BootData {
|
|
YBoot(&'static LoadProtocolV1),
|
|
}
|
|
|
|
const BOOT_STACK_SIZE: usize = 1024 * 1024;
|
|
|
|
#[repr(C, align(0x20))]
|
|
struct BootStack {
|
|
data: [u8; BOOT_STACK_SIZE],
|
|
}
|
|
|
|
#[link_section = ".bss"]
|
|
static mut BSP_STACK: BootStack = BootStack {
|
|
data: [0; BOOT_STACK_SIZE],
|
|
};
|
|
|
|
#[used]
|
|
#[link_section = ".data.yboot"]
|
|
static YBOOT_DATA: LoadProtocolV1 = LoadProtocolV1 {
|
|
header: LoadProtocolHeader {
|
|
kernel_magic: KERNEL_MAGIC,
|
|
version: PROTOCOL_VERSION_1,
|
|
},
|
|
kernel_virt_offset: KERNEL_VIRT_OFFSET as _,
|
|
|
|
memory_map: MemoryMap { address: 0, len: 0 },
|
|
|
|
rsdp_address: 0,
|
|
initrd_address: 0,
|
|
initrd_size: 0,
|
|
|
|
opt_framebuffer: FramebufferOption {
|
|
req_width: 640,
|
|
req_height: 480,
|
|
|
|
res_width: 0,
|
|
res_height: 0,
|
|
res_stride: 0,
|
|
res_address: 0,
|
|
res_size: 0,
|
|
},
|
|
};
|
|
|
|
unsafe fn init_dummy_cpu() {
|
|
// TODO this is incorrect
|
|
static UNINIT_CPU_INNER: usize = 0;
|
|
static UNINIT_CPU_PTR: &usize = &UNINIT_CPU_INNER;
|
|
|
|
// Point %gs to a dummy structure so that Cpu::get_local() works properly even before the CPU
|
|
// data structure is initialized
|
|
MSR_IA32_KERNEL_GS_BASE.set(&UNINIT_CPU_PTR as *const _ as u64);
|
|
core::arch::asm!("swapgs");
|
|
MSR_IA32_KERNEL_GS_BASE.set(&UNINIT_CPU_PTR as *const _ as u64);
|
|
core::arch::asm!("swapgs");
|
|
}
|
|
|
|
extern "C" fn __x86_64_upper_entry() -> ! {
|
|
// Safety: ok, CPU hasn't been initialized yet and it's the early kernel entry
|
|
unsafe {
|
|
init_dummy_cpu();
|
|
}
|
|
|
|
ARCHITECTURE.set_boot_data(BootData::YBoot(&YBOOT_DATA));
|
|
|
|
// Gather available CPU features
|
|
init_cpuid();
|
|
|
|
// Setup memory management: kernel virtual memory tables, physical page manager and heap
|
|
unsafe {
|
|
ARCHITECTURE
|
|
.init_memory_management()
|
|
.expect("Could not initialize memory management");
|
|
}
|
|
|
|
unsafe {
|
|
exception::init_exceptions(0);
|
|
}
|
|
|
|
// Initialize async executor queue
|
|
runtime::init_task_queue();
|
|
|
|
devfs::init();
|
|
|
|
// Initializes: local CPU, platform devices (timers/serials/etc), debug output
|
|
unsafe {
|
|
ARCHITECTURE
|
|
.init_platform(0)
|
|
.expect("Could not initialize the platform");
|
|
}
|
|
|
|
kernel_main()
|
|
}
|
|
|
|
/// Application processor entry point
|
|
pub extern "C" fn __x86_64_ap_entry() -> ! {
|
|
let cpu_id = CPU_COUNT.load(Ordering::Acquire);
|
|
|
|
unsafe {
|
|
init_dummy_cpu();
|
|
}
|
|
|
|
// Still not initialized: GDT, IDT, CPU features, syscall, kernel_gs_base
|
|
|
|
infoln!("cpu{} initializing", cpu_id);
|
|
|
|
unsafe {
|
|
// Cpu::init_local(LocalApic::new(), cpu_id as u32);
|
|
// syscall::init_syscall();
|
|
exception::init_exceptions(cpu_id);
|
|
|
|
ARCHITECTURE
|
|
.init_platform(cpu_id)
|
|
.expect("Could not initialize the platform (AP)");
|
|
}
|
|
|
|
CPU_COUNT.fetch_add(1, Ordering::Release);
|
|
|
|
kernel_secondary_main()
|
|
}
|
|
|
|
global_asm!(
|
|
r#"
|
|
// {boot_data}
|
|
.global __x86_64_entry
|
|
|
|
.section .text.entry
|
|
__x86_64_entry:
|
|
cli
|
|
mov ${yboot_loader_magic}, %edi
|
|
cmp %edi, %eax
|
|
je 2f
|
|
|
|
// (Currently) unsupported bootloader
|
|
1:
|
|
cli
|
|
hlt
|
|
jmp 1b
|
|
|
|
2:
|
|
// yboot entry method
|
|
movabsq ${stack_bottom} + {stack_size}, %rax
|
|
movabsq ${entry}, %rcx
|
|
mov %rax, %rsp
|
|
callq *%rcx
|
|
|
|
.section .text
|
|
"#,
|
|
yboot_loader_magic = const LOADER_MAGIC,
|
|
stack_size = const BOOT_STACK_SIZE,
|
|
stack_bottom = sym BSP_STACK,
|
|
boot_data = sym YBOOT_DATA,
|
|
entry = sym __x86_64_upper_entry,
|
|
options(att_syntax)
|
|
);
|