143 lines
3.1 KiB
Rust

#![feature(never_type, naked_functions, trace_macros)]
#![no_std]
extern crate alloc;
use core::ptr::null_mut;
use alloc::vec::Vec;
use device_api::interrupt::{LocalInterruptController, MessageInterruptController};
use kernel_arch_interface::{
cpu::{CpuData, CpuImpl, IpiQueue},
task::Scheduler,
Architecture,
};
pub mod context;
pub mod gdt;
pub mod mem;
pub use context::TaskContextImpl;
use kernel_arch_x86::cpuid::CpuFeatures;
pub use mem::{KernelTableManagerImpl, ProcessAddressSpaceImpl};
pub struct ArchitectureImpl;
#[repr(C)]
pub struct PerCpuData {
pub available_features: CpuFeatures,
pub enabled_features: CpuFeatures,
}
impl CpuData for PerCpuData {}
static mut CPU: *mut () = null_mut();
#[naked]
extern "C" fn idle_task(_: usize) -> ! {
unsafe {
core::arch::naked_asm!(
r#"
1:
nop
jmp 1b
"#,
options(att_syntax)
);
}
}
impl Architecture for ArchitectureImpl {
type PerCpuData = PerCpuData;
type CpuFeatures = CpuFeatures;
type BreakpointType = u8;
const BREAKPOINT_VALUE: Self::BreakpointType = 0xCC;
unsafe fn init_local_cpu<S: Scheduler + 'static>(id: Option<u32>, data: Self::PerCpuData) {
use alloc::boxed::Box;
let cpu = Box::leak(Box::new(CpuImpl::<Self, S>::new(
id.expect("x86_64 required manual CPU ID set"),
data,
)));
cpu.set_local();
}
unsafe fn set_interrupt_mask(mask: bool) -> bool {
let old = Self::interrupt_mask();
if mask {
core::arch::asm!("cli");
} else {
core::arch::asm!("sti");
}
old
}
fn interrupt_mask() -> bool {
let mut flags: u32;
unsafe {
core::arch::asm!("pushfl; pop {0:e}", out(reg) flags, options(att_syntax));
}
// If IF is zero, interrupts are disabled (masked)
flags & (1 << 9) == 0
}
fn wait_for_interrupt() {
unsafe {
core::arch::asm!("hlt");
}
}
unsafe fn init_ipi_queues(_queues: Vec<IpiQueue<Self>>) {}
fn local_cpu() -> *mut () {
unsafe { CPU }
}
fn cpu_index<S: Scheduler + 'static>() -> u32 {
0
}
unsafe fn set_local_cpu(cpu: *mut ()) {
CPU = cpu;
}
fn cpu_count() -> usize {
1
}
fn local_interrupt_controller() -> Option<&'static dyn LocalInterruptController> {
None
}
fn message_interrupt_controller() -> Option<&'static dyn MessageInterruptController> {
None
}
fn ipi_queue(_cpu_id: u32) -> Option<&'static IpiQueue<Self>> {
None
}
fn idle_task() -> extern "C" fn(usize) -> ! {
idle_task
}
fn halt() -> ! {
loop {
unsafe {
core::arch::asm!("cli; hlt");
}
}
}
fn cpu_available_features<S: Scheduler>(cpu: &CpuImpl<Self, S>) -> Option<&Self::CpuFeatures> {
Some(&cpu.available_features)
}
fn cpu_enabled_features<S: Scheduler>(cpu: &CpuImpl<Self, S>) -> Option<&Self::CpuFeatures> {
Some(&cpu.enabled_features)
}
}