This commit is contained in:
parent
a77f8f6294
commit
9dd71885d3
17 changed files with 88 additions and 33 deletions
|
@ -4,3 +4,6 @@ members = ["lib/acpica-rs", "lib/kernel-common", "loader", "kernel"]
|
|||
|
||||
[profile.release]
|
||||
lto = true
|
||||
|
||||
[profile.dev]
|
||||
panic = "abort"
|
||||
|
|
11
build.sh
11
build.sh
|
@ -1,15 +1,24 @@
|
|||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
target=${OS_TARGET:-release}
|
||||
rm -rf img
|
||||
mkdir -p img/boot/efi/boot
|
||||
cd lib/acpica-build
|
||||
make -j4
|
||||
cd ../../kernel
|
||||
if [ "$target" = "release" ]; then
|
||||
cargo build --release
|
||||
else
|
||||
cargo build
|
||||
fi
|
||||
cd ../loader
|
||||
if [ "$target" = "release" ]; then
|
||||
cargo build --release
|
||||
else
|
||||
cargo build
|
||||
fi
|
||||
cd ..
|
||||
cp target/x86_64-unknown-uefi/release/loader.efi img/boot/efi/boot/bootx64.efi
|
||||
cp target/x86_64-unknown-uefi/$target/loader.efi img/boot/efi/boot/bootx64.efi
|
||||
cd img
|
||||
dd if=/dev/zero of=boot.img bs=1M count=16 status=none
|
||||
mformat -i boot.img
|
||||
|
|
|
@ -15,3 +15,6 @@ hashbrown = "0.15.2"
|
|||
kernel-common = {path = "../lib/kernel-common"}
|
||||
log = "0.4.22"
|
||||
spin = "0.9.8"
|
||||
|
||||
[lints.clippy]
|
||||
missing_safety_doc = "allow"
|
||||
|
|
|
@ -9,7 +9,7 @@ use spin::Mutex;
|
|||
use crate::sys::{
|
||||
lapic::{get_current_lapic_id, send_eoi},
|
||||
scheduler::scheduler,
|
||||
sync::{IN_ISR_HANDLER, LOCKS_HELD},
|
||||
sync::{Spinlock, IN_ISR_HANDLER, LOCKS_HELD},
|
||||
};
|
||||
|
||||
global_asm!(include_str!("isr.s"), options(att_syntax));
|
||||
|
@ -79,6 +79,7 @@ const EXCEPTIONS: [&str; 32] = [
|
|||
pub const ISR_INVALIDATE_TLB: u64 = 252;
|
||||
pub const ISR_SCHEDULER: u64 = 254;
|
||||
pub static ISR_HANDLERS: Mutex<[Option<fn()>; 256]> = Mutex::new([None; 256]);
|
||||
pub static ISR_HANDLERS_LOCK: Spinlock = Spinlock::new();
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn isr_handler(state: &mut ISRState) {
|
||||
|
@ -105,19 +106,21 @@ extern "C" fn isr_handler(state: &mut ISRState) {
|
|||
IN_ISR_HANDLER[lapic_id].store(true, Ordering::SeqCst);
|
||||
if state.isr == ISR_SCHEDULER {
|
||||
scheduler(state);
|
||||
assert_eq!(LOCKS_HELD[lapic_id].load(Ordering::SeqCst), 0);
|
||||
debug_assert_eq!(LOCKS_HELD[lapic_id].load(Ordering::SeqCst), 0);
|
||||
IN_ISR_HANDLER[lapic_id].store(false, Ordering::SeqCst);
|
||||
return;
|
||||
}
|
||||
let handler;
|
||||
{
|
||||
ISR_HANDLERS_LOCK.lock();
|
||||
handler = ISR_HANDLERS.lock()[state.isr as usize];
|
||||
ISR_HANDLERS_LOCK.unlock();
|
||||
}
|
||||
if let Some(handler) = handler {
|
||||
handler();
|
||||
} else {
|
||||
warn!("Unhandled interrupt: {}", state.isr);
|
||||
}
|
||||
assert_eq!(LOCKS_HELD[lapic_id].load(Ordering::SeqCst), 0);
|
||||
debug_assert_eq!(LOCKS_HELD[lapic_id].load(Ordering::SeqCst), 0);
|
||||
IN_ISR_HANDLER[lapic_id].store(false, Ordering::SeqCst);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ use core::{
|
|||
};
|
||||
|
||||
use alloc::{boxed::Box, vec::Vec};
|
||||
use bitvec::{bitvec, order::Lsb0, vec::BitVec};
|
||||
use bitvec::{order::Lsb0, vec::BitVec};
|
||||
use kernel_common::{
|
||||
loader_struct::LoaderStruct,
|
||||
paging::{load_cr3, PageEntry, PageTable, KERNEL_HEAP_INITIAL_SIZE, KERNEL_HEAP_START, KERNEL_VIRT_START},
|
||||
|
@ -191,7 +191,7 @@ pub unsafe fn unmap_physical(address: u64, size: u64) {
|
|||
pub fn setup_paging(loader_struct: &LoaderStruct, phys_start: u64, heap_start: u64) {
|
||||
HEAP_PHYS_START.store(heap_start, Ordering::SeqCst);
|
||||
let mut memory_size = 0;
|
||||
for i in loader_struct.available_memory {
|
||||
for i in &loader_struct.available_memory {
|
||||
if i.initial_page + i.page_count > memory_size {
|
||||
memory_size = i.initial_page + i.page_count;
|
||||
}
|
||||
|
@ -199,9 +199,9 @@ pub fn setup_paging(loader_struct: &LoaderStruct, phys_start: u64, heap_start: u
|
|||
info!("Memory size: {} MB", memory_size * 0x1000 / 1024 / 1024);
|
||||
{
|
||||
let mut frames_vec = PHYSICAL_FRAMES.lock();
|
||||
*frames_vec = Some(bitvec![u64, Lsb0; 1; memory_size as usize]);
|
||||
*frames_vec = Some(BitVec::<u64, Lsb0>::repeat(true, memory_size as usize));
|
||||
let frames_vec = frames_vec.as_mut().unwrap();
|
||||
for i in loader_struct.available_memory {
|
||||
for i in &loader_struct.available_memory {
|
||||
for j in 0..i.page_count {
|
||||
let page = i.initial_page + j;
|
||||
frames_vec.set(page as usize, false);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
.code16
|
||||
.align 0x1000
|
||||
|
||||
.global ap_trampoline
|
||||
ap_trampoline:
|
||||
mov %cr4, %eax
|
||||
bts $5, %eax // Physical Address Extension
|
||||
|
@ -29,10 +30,12 @@ ap_trampoline_2:
|
|||
call *%rax
|
||||
|
||||
.align 4
|
||||
.global trampoline_pml4
|
||||
trampoline_pml4:
|
||||
.int 0
|
||||
|
||||
.align 8
|
||||
.global trampoline_stack
|
||||
trampoline_stack:
|
||||
.quad 0
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ use sys::{
|
|||
early_acpi::EarlyACPIHandler,
|
||||
hpet::setup_hpet,
|
||||
lapic::{get_current_lapic_id, setup_lapic_timer, smp_broadcast_panic, start_aps},
|
||||
madt::parse_madt,
|
||||
madt::{parse_madt, INTERRUPTS_SETUP},
|
||||
pic::disable_pic,
|
||||
sync::LOCKS_HELD,
|
||||
task::setup_multitasking,
|
||||
|
@ -108,8 +108,10 @@ fn main() {
|
|||
fn panic(info: &PanicInfo) -> ! {
|
||||
cli();
|
||||
if !BROADCASTED_PANIC.load(Ordering::SeqCst) {
|
||||
if INTERRUPTS_SETUP.load(Ordering::SeqCst) {
|
||||
smp_broadcast_panic();
|
||||
LOCKS_HELD[get_current_lapic_id()].fetch_add(1, Ordering::SeqCst);
|
||||
}
|
||||
error!("{}", info);
|
||||
let str = format!("{}", info);
|
||||
display_print(&str);
|
||||
|
|
|
@ -16,7 +16,7 @@ use spin::Mutex;
|
|||
use crate::{
|
||||
cpu::paging::map_physical,
|
||||
misc::draw_target::FramebufferTarget,
|
||||
sys::{sync::Spinlock, task::MULTITASKING_ENABLED},
|
||||
sys::{madt::INTERRUPTS_SETUP, sync::Spinlock},
|
||||
};
|
||||
|
||||
static FRAMEBUFFER: Mutex<Option<FramebufferTarget>> = Mutex::new(None);
|
||||
|
@ -57,7 +57,7 @@ pub fn display_print(str: &str) {
|
|||
if FRAMEBUFFER_ADDR.load(Ordering::SeqCst) == null_mut() {
|
||||
return;
|
||||
}
|
||||
if MULTITASKING_ENABLED.load(Ordering::SeqCst) {
|
||||
if INTERRUPTS_SETUP.load(Ordering::SeqCst) {
|
||||
FRAMEBUFFER_LOCK.lock();
|
||||
}
|
||||
let mut current_x = CURRENT_X.load(Ordering::SeqCst);
|
||||
|
@ -84,7 +84,7 @@ pub fn display_print(str: &str) {
|
|||
CURRENT_X.store(current_x, Ordering::SeqCst);
|
||||
CURRENT_Y.store(current_y, Ordering::SeqCst);
|
||||
copy_to_fb();
|
||||
if MULTITASKING_ENABLED.load(Ordering::SeqCst) {
|
||||
if INTERRUPTS_SETUP.load(Ordering::SeqCst) {
|
||||
FRAMEBUFFER_LOCK.unlock();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,10 @@ use core::{
|
|||
use bitfield::bitfield;
|
||||
|
||||
use crate::{
|
||||
cpu::{isr::ISR_HANDLERS, paging::map_physical},
|
||||
cpu::{
|
||||
isr::{ISR_HANDLERS, ISR_HANDLERS_LOCK},
|
||||
paging::map_physical,
|
||||
},
|
||||
sys::lapic::BSP_LAPIC_ID,
|
||||
};
|
||||
|
||||
|
@ -82,7 +85,11 @@ pub fn set_irq_override(gsi: usize, vector: usize, polarity: u8, trigger: u8) {
|
|||
}
|
||||
pub fn register_irq_handler(vector: usize, handler: fn()) {
|
||||
assert!(ISR_HANDLERS.lock()[vector].is_none());
|
||||
{
|
||||
ISR_HANDLERS_LOCK.lock();
|
||||
ISR_HANDLERS.lock()[vector] = Some(handler);
|
||||
ISR_HANDLERS_LOCK.unlock();
|
||||
}
|
||||
for i in 0..NEXT_IOAPIC_ID.load(Ordering::SeqCst) {
|
||||
let start = IOAPICS[i].start_gsi.load(Ordering::SeqCst);
|
||||
let end = IOAPICS[i].end_gsi.load(Ordering::SeqCst);
|
||||
|
|
|
@ -68,8 +68,7 @@ pub fn send_eoi() {
|
|||
pub fn get_current_lapic_id() -> usize {
|
||||
let address = ADDRESS.load(Ordering::SeqCst);
|
||||
let lapic_id = unsafe { address.add(REGISTER_ID).read_volatile() as usize >> 24 };
|
||||
let rflags = get_rflags();
|
||||
assert!(rflags & (1 << 9) == 0);
|
||||
debug_assert!(get_rflags() & (1 << 9) == 0);
|
||||
lapic_id
|
||||
}
|
||||
pub fn setup_lapic(phys: u64) {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use core::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
use acpi::{
|
||||
madt::{Madt, MadtEntry},
|
||||
AcpiTables,
|
||||
|
@ -10,6 +12,8 @@ use super::{
|
|||
lapic::{add_lapic, setup_lapic},
|
||||
};
|
||||
|
||||
pub static INTERRUPTS_SETUP: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
pub fn parse_madt(tables: &AcpiTables<EarlyACPIHandler>) {
|
||||
let madt = tables.find_table::<Madt>().unwrap();
|
||||
let mut lapic_address: u64 = madt.local_apic_address as u64;
|
||||
|
@ -42,4 +46,5 @@ pub fn parse_madt(tables: &AcpiTables<EarlyACPIHandler>) {
|
|||
unsafe {
|
||||
sti();
|
||||
}
|
||||
INTERRUPTS_SETUP.store(true, Ordering::SeqCst);
|
||||
}
|
||||
|
|
|
@ -1,17 +1,21 @@
|
|||
use core::{arch::asm, sync::atomic::Ordering};
|
||||
|
||||
use alloc::{collections::vec_deque::VecDeque, vec::Vec};
|
||||
use kernel_common::instructions::cli;
|
||||
use spin::Mutex;
|
||||
|
||||
use crate::cpu::isr::ISRState;
|
||||
|
||||
use super::{
|
||||
lapic::{get_current_lapic_id, schedule_timer_interrupt},
|
||||
sync::{Spinlock, IN_ISR_HANDLER, LOCKS_HELD},
|
||||
sync::Spinlock,
|
||||
task::{switch_task, Task, TaskState, CURRENT_TASKS, CURRENT_TASK_LOCK, MULTITASKING_ENABLED},
|
||||
};
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
use super::sync::{IN_ISR_HANDLER, LOCKS_HELD};
|
||||
#[cfg(debug_assertions)]
|
||||
use kernel_common::instructions::{cli, sti};
|
||||
|
||||
static SCHEDULER_LIST: Mutex<VecDeque<Task>> = Mutex::new(VecDeque::new());
|
||||
pub static IDLE_TASKS: Mutex<Vec<Task>> = Mutex::new(Vec::new());
|
||||
pub static SCHEDULER_LOCK: Spinlock = Spinlock::new();
|
||||
|
@ -56,7 +60,7 @@ pub fn scheduler(state: &mut ISRState) {
|
|||
CURRENT_TASK_LOCK.unlock();
|
||||
}
|
||||
pub fn schedule_task(task: Task) {
|
||||
assert!(SCHEDULER_LOCK.is_locked() || !MULTITASKING_ENABLED.load(Ordering::SeqCst));
|
||||
debug_assert!(SCHEDULER_LOCK.is_locked() || !MULTITASKING_ENABLED.load(Ordering::SeqCst));
|
||||
let mut scheduler_list = SCHEDULER_LIST.lock();
|
||||
if scheduler_list.is_empty() {
|
||||
schedule_timer_interrupt();
|
||||
|
@ -64,11 +68,17 @@ pub fn schedule_task(task: Task) {
|
|||
scheduler_list.push_back(task);
|
||||
}
|
||||
pub fn yield_task() {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
cli();
|
||||
let lapic_id = get_current_lapic_id();
|
||||
assert!(!IN_ISR_HANDLER[lapic_id].load(Ordering::SeqCst));
|
||||
assert_eq!(LOCKS_HELD[lapic_id].load(Ordering::SeqCst), 0);
|
||||
debug_assert!(!IN_ISR_HANDLER[lapic_id].load(Ordering::SeqCst));
|
||||
debug_assert_eq!(LOCKS_HELD[lapic_id].load(Ordering::SeqCst), 0);
|
||||
unsafe {
|
||||
asm!("sti; int $254");
|
||||
sti();
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
asm!("int $254");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use alloc::{collections::vec_deque::VecDeque, sync::Arc};
|
|||
use kernel_common::instructions::{cli, sti};
|
||||
use spin::Mutex;
|
||||
|
||||
use crate::sys::task::MULTITASKING_ENABLED;
|
||||
use crate::sys::madt::INTERRUPTS_SETUP;
|
||||
|
||||
use super::{
|
||||
lapic::get_current_lapic_id,
|
||||
|
@ -34,7 +34,7 @@ impl Spinlock {
|
|||
}
|
||||
}
|
||||
pub fn lock(&self) {
|
||||
assert!(MULTITASKING_ENABLED.load(Ordering::SeqCst));
|
||||
debug_assert!(INTERRUPTS_SETUP.load(Ordering::SeqCst));
|
||||
cli();
|
||||
while !self.locked.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst).is_ok() {}
|
||||
let lapic_id = get_current_lapic_id();
|
||||
|
@ -42,8 +42,9 @@ impl Spinlock {
|
|||
self.lapic_id.store(lapic_id, Ordering::SeqCst);
|
||||
}
|
||||
pub fn unlock(&self) {
|
||||
assert!(self.locked.load(Ordering::SeqCst));
|
||||
debug_assert!(self.locked.load(Ordering::SeqCst));
|
||||
let lapic_id = self.lapic_id.load(Ordering::SeqCst);
|
||||
debug_assert_eq!(lapic_id, get_current_lapic_id());
|
||||
self.locked.store(false, Ordering::SeqCst);
|
||||
LOCKS_HELD[lapic_id].fetch_sub(1, Ordering::SeqCst);
|
||||
if !IN_ISR_HANDLER[lapic_id].load(Ordering::SeqCst) && LOCKS_HELD[lapic_id].load(Ordering::SeqCst) == 0 {
|
||||
|
@ -109,7 +110,7 @@ pub fn unlock_semaphore(semaphore: Arc<Semaphore>, count: usize) {
|
|||
semaphore.spinlock.lock();
|
||||
{
|
||||
semaphore.current_count.fetch_add(count, Ordering::SeqCst);
|
||||
assert!(semaphore.current_count.load(Ordering::SeqCst) <= semaphore.max_count);
|
||||
debug_assert!(semaphore.current_count.load(Ordering::SeqCst) <= semaphore.max_count);
|
||||
while let Some(mut task) = semaphore.blocked_list.lock().pop_front() {
|
||||
task.block_on_semaphore = None;
|
||||
task.semaphore_requested_count = 0;
|
||||
|
|
|
@ -55,7 +55,7 @@ pub fn allocate_stack() -> u64 {
|
|||
stack.leak().as_mut_ptr() as u64 + STACK_SIZE as u64
|
||||
}
|
||||
pub fn switch_task(current_state: &mut ISRState, new_task: Task) {
|
||||
assert!(CURRENT_TASK_LOCK.is_locked());
|
||||
debug_assert!(CURRENT_TASK_LOCK.is_locked());
|
||||
let mut _current_task = CURRENT_TASKS.lock();
|
||||
if let Some(mut current_task) = _current_task.remove(&get_current_lapic_id()) {
|
||||
current_task.state = *current_state;
|
||||
|
|
|
@ -7,3 +7,6 @@ license = "Unlicense"
|
|||
[dependencies]
|
||||
bitfield = "0.17.0"
|
||||
log = "0.4.22"
|
||||
|
||||
[lints.clippy]
|
||||
missing_safety_doc = "allow"
|
||||
|
|
|
@ -11,3 +11,6 @@ log = "0.4.22"
|
|||
raw-cpuid = "11.2.0"
|
||||
static-alloc = "0.2.5"
|
||||
uefi = "0.33.0"
|
||||
|
||||
[lints.clippy]
|
||||
missing_safety_doc = "allow"
|
||||
|
|
|
@ -39,6 +39,10 @@ mod paging;
|
|||
static ALLOC: Bump<[u8; 8 * 1024 * 1024]> = Bump::uninit();
|
||||
static BOOT_SERVICES_ACTIVE: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
const KERNEL: &[u8] = include_bytes!("../../target/x86_64-unknown-none/debug/kernel");
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
const KERNEL: &[u8] = include_bytes!("../../target/x86_64-unknown-none/release/kernel");
|
||||
|
||||
#[entry]
|
||||
|
|
Loading…
Add table
Reference in a new issue