Add debug target
All checks were successful
Build / build (push) Successful in 2m53s

This commit is contained in:
Mathieu Strypsteen 2024-12-13 13:00:55 +01:00
parent a77f8f6294
commit 9dd71885d3
17 changed files with 88 additions and 33 deletions

View file

@ -4,3 +4,6 @@ members = ["lib/acpica-rs", "lib/kernel-common", "loader", "kernel"]
[profile.release]
lto = true
[profile.dev]
panic = "abort"

View file

@ -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

View file

@ -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"

View file

@ -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);
}

View file

@ -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);

View file

@ -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

View file

@ -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);

View file

@ -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();
}
}

View file

@ -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);

View file

@ -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) {

View file

@ -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);
}

View file

@ -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");
}
}

View file

@ -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;

View file

@ -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;

View file

@ -7,3 +7,6 @@ license = "Unlicense"
[dependencies]
bitfield = "0.17.0"
log = "0.4.22"
[lints.clippy]
missing_safety_doc = "allow"

View file

@ -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"

View file

@ -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]