Startup additional cores
All checks were successful
Build / build (push) Successful in 1m15s

This commit is contained in:
Mathieu Strypsteen 2024-12-10 20:38:36 +01:00
parent b9ab8da576
commit 392572ea80
10 changed files with 119 additions and 39 deletions

28
Cargo.lock generated
View file

@ -1,6 +1,6 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
version = 4
[[package]]
name = "acpi"
@ -49,9 +49,9 @@ checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973"
[[package]]
name = "bindgen"
version = "0.70.1"
version = "0.71.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f"
checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3"
dependencies = [
"bitflags",
"cexpr",
@ -64,7 +64,7 @@ dependencies = [
"regex",
"rustc-hash",
"shlex",
"syn 2.0.89",
"syn 2.0.90",
]
[[package]]
@ -228,15 +228,15 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.164"
version = "0.2.168"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f"
checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d"
[[package]]
name = "libloading"
version = "0.8.5"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
dependencies = [
"cfg-if",
"windows-targets",
@ -314,7 +314,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033"
dependencies = [
"proc-macro2",
"syn 2.0.89",
"syn 2.0.90",
]
[[package]]
@ -401,9 +401,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "rustc-hash"
version = "1.1.0"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497"
[[package]]
name = "scopeguard"
@ -448,9 +448,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.89"
version = "2.0.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e"
checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31"
dependencies = [
"proc-macro2",
"quote",
@ -496,7 +496,7 @@ checksum = "9b24e77d3fc1e617051e630f99da24bcae6328abab37b8f9216bb68d06804f9a"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.89",
"syn 2.0.90",
]
[[package]]

View file

@ -136,7 +136,7 @@ fn map(pml4: &mut PageTable, virt: u64, phys: u64, user: bool, write: bool, exec
table.entries_phys[table_i].set_cache_disable(cache_disable as u64);
table.entries_phys[table_i].set_present(1);
}
fn unmap(address: u64) {
pub unsafe fn unmap(address: u64) {
let mut current_pml4 = CURRENT_PML4.lock();
let page = get_page(current_pml4.as_mut().unwrap(), address);
assert!(page.is_some(), "Page isn't mapped");
@ -149,7 +149,7 @@ fn unmap(address: u64) {
None => {}
}
}
fn map_range(virt_start: u64, phys_start: u64, size: u64, user: bool, write: bool, exec: bool, cache_disable: bool) {
pub unsafe fn map_range(virt_start: u64, phys_start: u64, size: u64, user: bool, write: bool, exec: bool, cache_disable: bool) {
assert_eq!(virt_start % 0x1000, 0);
assert_eq!(phys_start % 0x1000, 0);
assert_eq!(size % 0x1000, 0);
@ -166,7 +166,9 @@ pub unsafe fn map_physical(phys: u64, mut size: u64, write_combining: bool) -> u
size = phys_end - phys_start;
let virt_start = find_free_virt_range(KERNEL_MAPPINGS_START, KERNEL_MAPPINGS_END, size);
let cache_disable = !write_combining;
unsafe {
map_range(virt_start, phys_start, size, false, true, false, cache_disable);
}
virt_start + phys_offset
}
pub unsafe fn unmap_physical(address: u64, size: u64) {
@ -174,9 +176,11 @@ pub unsafe fn unmap_physical(address: u64, size: u64) {
let start = address / 0x1000 * 0x1000;
let size = end - start;
for i in 0..size / 0x1000 {
unsafe {
unmap(start + i * 0x1000);
}
}
}
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;
@ -189,12 +193,15 @@ pub fn setup_paging(loader_struct: &LoaderStruct, phys_start: u64, heap_start: u
{
let mut frames_vec = PHYSICAL_FRAMES.lock();
*frames_vec = Some(bitvec![u64, Lsb0; 1; memory_size as usize]);
let frames_vec = frames_vec.as_mut().unwrap();
for i in loader_struct.available_memory {
for j in 0..i.page_count {
let page = i.initial_page + j;
frames_vec.as_mut().unwrap().set(page as usize, false);
frames_vec.set(page as usize, false);
}
}
assert!(!frames_vec.get(1).unwrap());
frames_vec.set(1, true);
}
let text_start;
let text_end;

View file

@ -0,0 +1,5 @@
.text
.global ap_trampoline
ap_trampoline:
hlt

View file

@ -25,7 +25,16 @@ use kernel_common::{
use log::{error, info};
use misc::display::{display_print, setup_display};
use spin::Mutex;
use sys::{acpica_osl::AE_OK, early_acpi::EarlyACPIHandler, hpet::setup_hpet, lapic::setup_lapic_timer, madt::parse_madt, pic::disable_pic, sync::LOCKS_HELD, task::setup_multitasking};
use sys::{
acpica_osl::AE_OK,
early_acpi::EarlyACPIHandler,
hpet::setup_hpet,
lapic::{setup_lapic_timer, start_aps},
madt::parse_madt,
pic::disable_pic,
sync::LOCKS_HELD,
task::setup_multitasking,
};
mod cpu;
mod misc;
@ -50,6 +59,7 @@ static LOADER_STRUCT: Mutex<LoaderStruct> = Mutex::new(LoaderStruct {
});
global_asm!(include_str!("cpu/boot.s"), options(att_syntax));
global_asm!(include_str!("cpu/trampoline.s"), options(att_syntax));
#[no_mangle]
extern "C" fn early_main(temp_loader_struct: *const LoaderStruct) -> ! {
@ -90,6 +100,7 @@ fn main() {
assert_eq!(status, AE_OK);
status = unsafe { AcpiInitializeObjects(ACPI_FULL_INITIALIZATION) };
assert_eq!(status, AE_OK);
start_aps();
}
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {

View file

@ -1,6 +1,6 @@
use core::{
ptr::null_mut,
sync::atomic::{AtomicPtr, AtomicU32, AtomicUsize, Ordering},
sync::atomic::{AtomicPtr, AtomicUsize, Ordering},
};
use bitfield::bitfield;
@ -12,8 +12,8 @@ use crate::{
struct IOAPIC {
address: AtomicPtr<u32>,
start_gsi: AtomicU32,
end_gsi: AtomicU32,
start_gsi: AtomicUsize,
end_gsi: AtomicUsize,
}
bitfield! {
struct RedirectionEntry(u64);
@ -29,8 +29,8 @@ bitfield! {
}
const EMPTY_IOAPIC: IOAPIC = IOAPIC {
address: AtomicPtr::new(null_mut()),
start_gsi: AtomicU32::new(0),
end_gsi: AtomicU32::new(0),
start_gsi: AtomicUsize::new(0),
end_gsi: AtomicUsize::new(0),
};
const REGISTER_VERSION: u8 = 1;
const REGISTER_REDIRECTION: u8 = 0x10;
@ -51,7 +51,7 @@ fn write_register(apic_i: usize, reg_i: u8, val: u32) {
}
}
fn get_apic_for_gsi(gsi: usize) -> usize {
for i in 0..32 {
for i in 0..NEXT_IOAPIC_ID.load(Ordering::SeqCst) {
if gsi >= IOAPICS[i].start_gsi.load(Ordering::SeqCst) as usize && gsi < IOAPICS[i].end_gsi.load(Ordering::SeqCst) as usize {
return i;
}
@ -81,7 +81,7 @@ 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()[vector] = Some(handler);
for i in 0..32 {
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);
for j in start..end {
@ -93,12 +93,12 @@ pub fn register_irq_handler(vector: usize, handler: fn()) {
}
}
}
pub fn setup_ioapic(phys: u64, gsi_base: u32) {
pub fn setup_ioapic(phys: u64, gsi_base: usize) {
let address = unsafe { map_physical(phys, 0x14, false) as *mut u32 };
let next_id = NEXT_IOAPIC_ID.fetch_add(1, Ordering::SeqCst);
IOAPICS[next_id].address.store(address, Ordering::SeqCst);
IOAPICS[next_id].start_gsi.store(gsi_base, Ordering::SeqCst);
let max_ints = (read_register(next_id, REGISTER_VERSION) >> 16) & 0xff;
let max_ints = (read_register(next_id, REGISTER_VERSION) >> 16) as usize & 0xff;
IOAPICS[next_id].end_gsi.store(gsi_base + max_ints, Ordering::SeqCst);
assert!(gsi_base + max_ints < 128);
for i in gsi_base..gsi_base + max_ints {

View file

@ -1,23 +1,43 @@
use core::{
ptr::null_mut,
sync::atomic::{AtomicPtr, AtomicU8, AtomicUsize, Ordering},
ptr::{copy, null_mut},
sync::atomic::{AtomicBool, AtomicPtr, AtomicUsize, Ordering},
};
use crate::cpu::paging::map_physical;
use crate::cpu::paging::{map_physical, map_range, unmap};
use super::hpet::sleep;
extern "C" {
fn ap_trampoline();
}
struct LAPIC {
lapic_id: AtomicUsize,
present: AtomicBool,
}
const REGISTER_ID: usize = 8;
const REGISTER_EOI: usize = 0x2c;
const REGISTER_SPURIOUS_INT: usize = 0x3c;
const REGISTER_ICR_1: usize = 0xc0;
const REGISTER_ICR_2: usize = 0xc4;
const REGISTER_TIMER_LVT: usize = 0xc8;
const REGISTER_TIMER_INITIAL_COUNT: usize = 0xe0;
const REGISTER_TIMER_CURRENT_COUNT: usize = 0xe4;
const REGISTER_TIMER_DIVIDE: usize = 0xf8;
const IPI_INIT: u32 = 0x500;
const IPI_STARTUP: u32 = 0x600;
const EMPTY_LAPIC: LAPIC = LAPIC {
lapic_id: AtomicUsize::new(0),
present: AtomicBool::new(false),
};
static ADDRESS: AtomicPtr<u32> = AtomicPtr::new(null_mut());
pub static BSP_LAPIC_ID: AtomicU8 = AtomicU8::new(0);
pub static BSP_LAPIC_ID: AtomicUsize = AtomicUsize::new(0);
static LAPICS: [LAPIC; 256] = [EMPTY_LAPIC; 256];
static TICKS_PER_MS: AtomicUsize = AtomicUsize::new(0);
static NEXT_LAPIC_ID: AtomicUsize = AtomicUsize::new(0);
pub fn send_eoi() {
let address = ADDRESS.load(Ordering::SeqCst);
@ -29,7 +49,7 @@ pub fn setup_lapic(phys: u64) {
let address = unsafe { map_physical(phys, 0x400, false) as *mut u32 };
ADDRESS.store(address, Ordering::SeqCst);
unsafe {
BSP_LAPIC_ID.store(address.add(REGISTER_ID).read_volatile() as u8, Ordering::SeqCst);
BSP_LAPIC_ID.store(address.add(REGISTER_ID).read_volatile() as usize, Ordering::SeqCst);
address.add(REGISTER_SPURIOUS_INT).write_volatile(0x1ff);
}
send_eoi();
@ -46,6 +66,13 @@ fn calibrate_timer() {
address.add(REGISTER_TIMER_INITIAL_COUNT).write_volatile(0);
}
}
fn send_ipi(lapic_id: usize, data: u32) {
let address = ADDRESS.load(Ordering::SeqCst);
unsafe {
address.add(REGISTER_ICR_2).write_volatile((lapic_id << 24) as u32);
address.add(REGISTER_ICR_1).write_volatile(data);
}
}
pub fn schedule_timer_interrupt() {
let address = ADDRESS.load(Ordering::SeqCst);
unsafe {
@ -62,3 +89,28 @@ pub fn setup_lapic_timer() {
address.add(REGISTER_TIMER_LVT).write_volatile(254);
}
}
pub fn add_lapic(lapic_id: usize) {
let next_id = NEXT_LAPIC_ID.fetch_add(1, Ordering::SeqCst);
LAPICS[next_id].lapic_id.store(lapic_id, Ordering::SeqCst);
LAPICS[next_id].present.store(true, Ordering::SeqCst);
}
pub fn start_aps() {
unsafe {
map_range(0x1000, 0x1000, 0x1000, false, true, false, false);
let dest_ptr = 0x1000 as *mut u8;
let src_ptr = ap_trampoline as *const u8;
copy(src_ptr, dest_ptr, 0x1000);
}
for i in 0..NEXT_LAPIC_ID.load(Ordering::SeqCst) {
let lapic_id = LAPICS[i].lapic_id.load(Ordering::SeqCst);
if lapic_id == BSP_LAPIC_ID.load(Ordering::SeqCst) {
continue;
}
send_ipi(lapic_id, IPI_INIT);
sleep(10000);
send_ipi(lapic_id, IPI_STARTUP | 1);
}
unsafe {
unmap(0x1000);
}
}

View file

@ -7,7 +7,7 @@ use kernel_common::instructions::sti;
use super::{
early_acpi::EarlyACPIHandler,
ioapic::{set_irq_override, setup_ioapic},
lapic::setup_lapic,
lapic::{add_lapic, setup_lapic},
};
pub fn parse_madt(tables: &AcpiTables<EarlyACPIHandler>) {
@ -17,11 +17,16 @@ pub fn parse_madt(tables: &AcpiTables<EarlyACPIHandler>) {
if let MadtEntry::LocalApicAddressOverride(lapic_override) = i {
lapic_address = lapic_override.local_apic_address;
}
if let MadtEntry::LocalApic(lapic) = i {
if lapic.flags & 1 == 1 || lapic.flags & 2 == 2 {
add_lapic(lapic.apic_id as usize);
}
}
}
setup_lapic(lapic_address);
for i in madt.entries() {
if let MadtEntry::IoApic(ioapic) = i {
setup_ioapic(ioapic.io_apic_address as u64, ioapic.global_system_interrupt_base);
setup_ioapic(ioapic.io_apic_address as u64, ioapic.global_system_interrupt_base as usize);
}
}
for i in madt.entries() {

@ -1 +1 @@
Subproject commit 993a25704ac18784b44c1af75cb54abec5141981
Subproject commit 437f7e1a0039d227d3952677c3f9f5ad9c814395

View file

@ -5,4 +5,4 @@ edition = "2021"
license = "BSD-3-Clause-acpica"
[build-dependencies]
bindgen = "0.70.1"
bindgen = "0.71.0"

View file

@ -2,4 +2,4 @@
# shellcheck disable=SC2068
set -euo pipefail
./build.sh
qemu-system-x86_64 -M q35 -accel kvm -cpu qemu64,rdrand,smap,smep -m 256M -L /usr/share/OVMF -bios OVMF_CODE.fd -drive file=img/os.img,format=raw $@
qemu-system-x86_64 -M q35 -accel kvm -cpu qemu64,rdrand,smap,smep -smp 4 -m 256M -L /usr/share/OVMF -bios OVMF_CODE.fd -drive file=img/os.img,format=raw $@