This commit is contained in:
parent
b9ab8da576
commit
392572ea80
10 changed files with 119 additions and 39 deletions
28
Cargo.lock
generated
28
Cargo.lock
generated
|
@ -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]]
|
||||
|
|
|
@ -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,8 +176,10 @@ 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);
|
||||
|
@ -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;
|
||||
|
|
5
kernel/src/cpu/trampoline.s
Normal file
5
kernel/src/cpu/trampoline.s
Normal file
|
@ -0,0 +1,5 @@
|
|||
.text
|
||||
|
||||
.global ap_trampoline
|
||||
ap_trampoline:
|
||||
hlt
|
|
@ -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) -> ! {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -5,4 +5,4 @@ edition = "2021"
|
|||
license = "BSD-3-Clause-acpica"
|
||||
|
||||
[build-dependencies]
|
||||
bindgen = "0.70.1"
|
||||
bindgen = "0.71.0"
|
||||
|
|
2
qemu.sh
2
qemu.sh
|
@ -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 $@
|
||||
|
|
Loading…
Add table
Reference in a new issue