#![no_std] #![no_main] #![feature(abi_x86_interrupt)]
#![feature(inline_const)]
#![feature(int_roundings)]
#![feature(lazy_cell)]
#![feature(let_chains)]
#![feature(pointer_is_aligned)]
#![feature(const_mut_refs)]
#![allow(clippy::assertions_on_constants)]
#![allow(clippy::redundant_pattern_matching)]
use core::arch::global_asm;
use core::panic::PanicInfo;
use core::ptr::addr_of;
#[macro_use]
mod device;
#[macro_use]
mod arch;
mod gdt;
mod interrupts;
mod threading;
mod user;
mod util;
use device::cga::Window;
use device::{KEYBOARD, SERIAL};
#[cfg(feature = "smp")]
use crate::arch::smp;
use crate::arch::{acpi::Acpi, cpu, int};
use crate::device::{DBG, KOUT};
use crate::interrupts::guard::GUARD;
use crate::threading::Thread;
#[cfg(feature = "smp")]
const MAX_CPUS: usize = 4;
#[cfg(not(feature = "smp"))]
const MAX_CPUS: usize = 1;
global_asm!(include_str!("arch/i686/start.s"), options(raw));
#[allow(unused)]
extern "C" {
static MBOOT_SIG: u32;
static MBOOT_PTR: *mut ();
static KERNEL_BEGIN: u8;
static KERNEL_END: u8;
static start_high: u8;
}
const STACK_SIZE: usize = 16 * 1024;
#[no_mangle]
pub static mut INIT_STACKS: [[u32; STACK_SIZE / 4]; MAX_CPUS] = [[0; STACK_SIZE / 4]; MAX_CPUS];
#[no_mangle]
pub fn kmain() -> ! {
if cpu::online() == 0 {
SERIAL.lock().init();
}
serial!("core id: {} ({:08b})", cpu::id(), cpu::online());
if cpu::online() == 0 {
serial!("code: {:x?}", unsafe {
addr_of!(KERNEL_BEGIN)..addr_of!(KERNEL_END)
});
Window::whole().clear();
DBG.lock().clear();
KOUT.lock().clear();
println!("Hello World!");
let acpi = Acpi::load().unwrap();
serial!("global int");
#[allow(unused_variables)]
let cpus = interrupts::setup_global(acpi);
let _old_cid = cpu::id() as u8;
interrupts::setup_local();
unsafe { KEYBOARD.init() };
serial!("Start loading apps");
GUARD.run(|g| {
let sched = &mut g.scheduler;
sched.add(Thread::new(user::app_action));
sched.add(Thread::new(user::app_action));
sched.add(Thread::new(user::app_action));
sched.add(Thread::new(user::app_action));
sched.add(Thread::new(user::app_action));
sched.add(Thread::new(user::app_action));
sched.add(Thread::new(user::app_action));
sched.add(Thread::new(user::app_action));
sched.add(Thread::new(user::keyboard_action));
sched.add(Thread::new(user::init_action));
});
serial!("Finish loading apps");
#[cfg(feature = "smp")]
if cpus > 1 {
serial!("boot cores");
smp::boot(&int::lapic::LAPIC, _old_cid);
assert_eq!(cpus as u32, cpu::online().count_ones(), "we lost cores!");
}
} else {
interrupts::setup_local();
}
let mut guarded = GUARD.enter();
println!(dbg: "{}: int starting", cpu::id());
int::enable(true);
serial!("Scheduler starting...");
guarded.scheduler.schedule();
}
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
serial!(force: "{info}");
println!(dbg: "{info}");
loop {
int::enable(false);
cpu::halt();
}
}
pub mod assignments {
pub mod a1_syscalls {
#![doc = include_str!("../assignments/1-Syscalls.md")]
}
pub mod a2_paging {
#![doc = include_str!("../assignments/2-Paging.md")]
}
pub mod a3_ipc_cow {
#![doc = include_str!("../assignments/3-IPC-COW.md")]
}
}