174 lines
4.0 KiB
Rust
Raw Normal View History

//! x86-64 boot and entry functions
2023-09-15 00:02:14 +03:00
use core::{arch::global_asm, sync::atomic::Ordering};
2023-07-29 19:31:56 +03:00
use kernel_fs::devfs;
use kernel_util::runtime;
use tock_registers::interfaces::Writeable;
2023-07-29 19:31:56 +03:00
use yboot_proto::{
2023-07-30 16:40:30 +03:00
v1::{FramebufferOption, MemoryMap},
LoadProtocolHeader, LoadProtocolV1, KERNEL_MAGIC, LOADER_MAGIC, PROTOCOL_VERSION_1,
2023-07-29 19:31:56 +03:00
};
use crate::{
arch::x86_64::{registers::MSR_IA32_KERNEL_GS_BASE, smp::CPU_COUNT},
2023-09-15 00:02:14 +03:00
kernel_main, kernel_secondary_main,
mem::KERNEL_VIRT_OFFSET,
2023-07-29 19:31:56 +03:00
};
use super::{cpuid::init_cpuid, exception, ARCHITECTURE};
pub enum BootData {
YBoot(&'static LoadProtocolV1),
}
2023-07-29 19:31:56 +03:00
const BOOT_STACK_SIZE: usize = 1024 * 1024;
2023-07-29 19:31:56 +03:00
#[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 {
2023-07-29 19:31:56 +03:00
header: LoadProtocolHeader {
kernel_magic: KERNEL_MAGIC,
version: PROTOCOL_VERSION_1,
},
kernel_virt_offset: KERNEL_VIRT_OFFSET as _,
2023-07-30 16:40:30 +03:00
memory_map: MemoryMap { address: 0, len: 0 },
rsdp_address: 0,
initrd_address: 0,
initrd_size: 0,
2023-07-29 19:31:56 +03:00
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;
2023-12-07 10:16:44 +02:00
static UNINIT_CPU_PTR: &usize = &UNINIT_CPU_INNER;
2023-07-29 19:31:56 +03:00
2023-08-06 20:16:23 +03:00
// 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);
2023-08-06 20:16:23 +03:00
core::arch::asm!("swapgs");
MSR_IA32_KERNEL_GS_BASE.set(&UNINIT_CPU_PTR as *const _ as u64);
2023-08-06 20:16:23 +03:00
core::arch::asm!("swapgs");
}
2023-08-06 20:16:23 +03:00
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();
}
2023-07-29 19:31:56 +03:00
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 {
2023-09-15 23:23:20 +03:00
ARCHITECTURE
.init_memory_management()
.expect("Could not initialize memory management");
}
unsafe {
exception::init_exceptions(0);
}
2023-09-06 10:57:02 +03:00
// Initialize async executor queue
runtime::init_task_queue();
devfs::init();
// Initializes: local CPU, platform devices (timers/serials/etc), debug output
unsafe {
2023-09-15 23:23:20 +03:00
ARCHITECTURE
.init_platform(0)
.expect("Could not initialize the platform");
}
2023-07-30 16:40:30 +03:00
kernel_main()
2023-07-29 19:31:56 +03:00
}
2023-09-15 00:02:14 +03:00
/// 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);
2023-09-15 23:23:20 +03:00
ARCHITECTURE
.init_platform(cpu_id)
.expect("Could not initialize the platform (AP)");
2023-09-15 00:02:14 +03:00
}
CPU_COUNT.fetch_add(1, Ordering::Release);
kernel_secondary_main()
}
2023-07-29 19:31:56 +03:00
global_asm!(
r#"
// {boot_data}
2023-07-29 19:31:56 +03:00
.global __x86_64_entry
.section .text.entry
__x86_64_entry:
cli
2023-07-29 19:31:56 +03:00
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
2023-07-29 21:11:15 +03:00
callq *%rcx
2023-07-29 19:31:56 +03:00
.section .text
"#,
yboot_loader_magic = const LOADER_MAGIC,
stack_size = const BOOT_STACK_SIZE,
stack_bottom = sym BSP_STACK,
boot_data = sym YBOOT_DATA,
2023-07-29 19:31:56 +03:00
entry = sym __x86_64_upper_entry,
options(att_syntax)
);