143 lines
3.1 KiB
Rust
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)
|
|
}
|
|
}
|