arch/aarch64: fix aarch64 build

This commit is contained in:
Mark Poliakov 2024-01-04 23:04:34 +02:00
parent b760a5bad9
commit 0e8860c719
16 changed files with 228 additions and 158 deletions

View File

@ -19,9 +19,6 @@ vmalloc = { path = "lib/vmalloc" }
device-api-macros = { path = "lib/device-api/macros" } device-api-macros = { path = "lib/device-api/macros" }
# Drivers # Drivers
ygg_driver_pci = { path = "driver/bus/pci" }
ygg_driver_nvme = { path = "driver/block/nvme" }
ygg_driver_ahci = { path = "driver/block/ahci" }
ygg_driver_block = { path = "driver/block/core" } ygg_driver_block = { path = "driver/block/core" }
kernel-fs = { path = "driver/fs/kernel-fs" } kernel-fs = { path = "driver/fs/kernel-fs" }
memfs = { path = "driver/fs/memfs" } memfs = { path = "driver/fs/memfs" }
@ -57,6 +54,9 @@ acpi_lib = { git = "https://github.com/alnyan/acpi.git", package = "acpi", branc
acpi-system = { git = "https://github.com/alnyan/acpi-system.git" } acpi-system = { git = "https://github.com/alnyan/acpi-system.git" }
# TODO currently only supported here # TODO currently only supported here
xhci_lib = { git = "https://github.com/rust-osdev/xhci.git", package = "xhci" } xhci_lib = { git = "https://github.com/rust-osdev/xhci.git", package = "xhci" }
ygg_driver_pci = { path = "driver/bus/pci" }
ygg_driver_nvme = { path = "driver/block/nvme" }
ygg_driver_ahci = { path = "driver/block/ahci" }
[features] [features]
default = ["fb_console"] default = ["fb_console"]

View File

@ -5,6 +5,14 @@ use aarch64_cpu::{
asm::barrier, asm::barrier,
registers::{CPACR_EL1, ID_AA64MMFR0_EL1, MAIR_EL1, SCTLR_EL1, TCR_EL1, TTBR0_EL1}, registers::{CPACR_EL1, ID_AA64MMFR0_EL1, MAIR_EL1, SCTLR_EL1, TCR_EL1, TTBR0_EL1},
}; };
use kernel_fs::devfs;
use kernel_util::{
mem::{
address::{IntoRaw, PhysicalAddress},
table::EntryLevel,
},
runtime,
};
use tock_registers::interfaces::{ReadWriteable, Readable, Writeable}; use tock_registers::interfaces::{ReadWriteable, Readable, Writeable};
use super::{ use super::{
@ -13,10 +21,8 @@ use super::{
}; };
use crate::{ use crate::{
arch::{aarch64::mem::table::L3, Architecture}, arch::{aarch64::mem::table::L3, Architecture},
fs::devfs,
kernel_main, kernel_secondary_main, kernel_main, kernel_secondary_main,
mem::{address::IntoRaw, phys, table::EntryLevel, PhysicalAddress, KERNEL_VIRT_OFFSET}, mem::{phys, KERNEL_VIRT_OFFSET},
task::runtime,
}; };
unsafe fn pre_init_mmu() { unsafe fn pre_init_mmu() {

View File

@ -1,12 +1,22 @@
//! Per-CPU data structures //! Per-CPU data structures
use core::sync::atomic::Ordering; use core::{
ops::{Deref, DerefMut},
sync::atomic::Ordering,
};
use aarch64_cpu::registers::{MPIDR_EL1, TPIDR_EL1}; use aarch64_cpu::registers::{MPIDR_EL1, TPIDR_EL1};
use alloc::{boxed::Box, vec::Vec}; use alloc::{boxed::Box, vec::Vec};
use kernel_util::{sync::IrqSafeSpinlock, util::OneTimeInit}; use kernel_util::{
sync::{IrqGuard, IrqSafeSpinlock},
util::OneTimeInit,
};
use tock_registers::interfaces::{Readable, Writeable}; use tock_registers::interfaces::{Readable, Writeable};
use crate::{arch::CpuMessage, panic, task::sched::CpuQueue}; use crate::{
arch::{CpuAccess, CpuMessage, LocalCpuAccess},
panic,
task::{sched::CpuQueue, thread::ThreadId},
};
use super::smp::CPU_COUNT; use super::smp::CPU_COUNT;
@ -18,8 +28,17 @@ pub struct Cpu {
id: u32, id: u32,
queue: OneTimeInit<&'static CpuQueue>, queue: OneTimeInit<&'static CpuQueue>,
thread_id: Option<ThreadId>,
} }
/// Handle allowing safe access to the local CPU.
///
/// # Note
///
/// Obtaining this handle prevents IRQs from being delivered to ensure the context having this
/// struct cannot be interrupted by another (which could obtain it as well).
pub struct LocalCpu(&'static mut Cpu, IrqGuard);
struct IpiQueue { struct IpiQueue {
data: IrqSafeSpinlock<Option<CpuMessage>>, data: IrqSafeSpinlock<Option<CpuMessage>>,
} }
@ -47,17 +66,11 @@ impl IpiQueue {
} }
impl Cpu { impl Cpu {
/// Returns a safe reference to the local CPU's private data structure /// Sets up global list of interprocessor message queues
#[inline(always)] pub fn init_ipi_queues() {
pub fn local<'a>() -> &'a Self { IPI_QUEUES.init(Vec::from_iter(
Self::get_local().unwrap() (0..CPU_COUNT.load(Ordering::Acquire)).map(|_| IpiQueue::new()),
} ));
/// Returns the local CPU data structure reference, if it was set up
#[inline(always)]
pub fn get_local<'a>() -> Option<&'a Self> {
let tpidr = TPIDR_EL1.get() as *mut Cpu;
unsafe { tpidr.as_ref() }
} }
/// Sets up the local CPU's private data structure. /// Sets up the local CPU's private data structure.
@ -69,60 +82,81 @@ impl Cpu {
let this = Box::new(Cpu { let this = Box::new(Cpu {
id: Self::local_id(), id: Self::local_id(),
queue: OneTimeInit::new(), queue: OneTimeInit::new(),
thread_id: None,
}); });
TPIDR_EL1.set(Box::into_raw(this) as _); TPIDR_EL1.set(Box::into_raw(this) as _);
} }
}
/// Sets up the local CPU's execution queue. impl CpuAccess for Cpu {
pub fn init_queue(&self, queue: &'static CpuQueue) { type Local = LocalCpu;
self.queue.init(queue);
fn id(&self) -> u32 {
self.id
} }
/// Returns the local CPU's execution queue. fn local_id() -> u32 {
pub fn queue(&self) -> &'static CpuQueue {
self.queue.get()
}
/// Returns the index of the local CPU
#[inline(always)]
pub fn local_id() -> u32 {
(MPIDR_EL1.get() & 0xFF) as _ (MPIDR_EL1.get() & 0xFF) as _
} }
/// Inserts an IPI message to the back of the target CPU's message queue fn try_local() -> Option<Self::Local> {
pub fn push_ipi_queue(cpu_id: u32, msg: CpuMessage) { let guard = IrqGuard::acquire();
let ipi_queue = &IPI_QUEUES.get()[cpu_id as usize]; let tpidr = TPIDR_EL1.get() as *mut Cpu;
ipi_queue.push(msg); unsafe { tpidr.as_mut() }.map(|cpu| LocalCpu(cpu, guard))
} }
/// Pops the first IPI message received for this CPU. fn get_queue(&self) -> Option<&'static CpuQueue> {
/// self.queue.try_get().copied()
/// # Note
///
/// Currently the queue consists of only one entry, so the CPU will only receive the last one.
pub fn get_ipi(&self) -> Option<CpuMessage> {
let ipi_queue = &IPI_QUEUES.get()[self.id as usize];
ipi_queue.pop()
} }
/// Sets up global list of interprocessor message queues fn init_queue(&mut self, queue: &'static CpuQueue) {
pub fn init_ipi_queues() { self.queue.init(queue);
IPI_QUEUES.init(Vec::from_iter(
(0..CPU_COUNT.load(Ordering::Acquire)).map(|_| IpiQueue::new()),
));
} }
/// Gets an IPI message from the processor's queue and takes corresponding actions. If there is unsafe fn set_current_thread_id(&mut self, id: Option<ThreadId>) {
/// none, this is treated as a spurious IPI and ignored. See [CpuMessage]. self.thread_id = id;
pub fn handle_ipi(&self) { }
let Some(msg) = self.get_ipi() else {
warnln!("Spurious IPI in cpu{}", self.id);
return;
};
match msg { fn current_thread_id(&self) -> Option<ThreadId> {
self.thread_id
}
fn push_ipi(id: u32, msg: CpuMessage) {
if let Some(q) = IPI_QUEUES.try_get().and_then(|q| q.get(id as usize)) {
q.push(msg);
}
}
fn handle_ipi(&mut self) {
if let Some(ipi) = IPI_QUEUES
.try_get()
.and_then(|q| q.get(self.id() as usize))
.and_then(|q| q.pop())
{
match ipi {
CpuMessage::Panic => panic::panic_secondary(), CpuMessage::Panic => panic::panic_secondary(),
CpuMessage::Shutdown => todo!(), CpuMessage::Shutdown => todo!(),
} }
} }
}
}
impl LocalCpuAccess<Cpu> for LocalCpu {
fn into_guard(self) -> IrqGuard {
self.1
}
}
impl Deref for LocalCpu {
type Target = Cpu;
fn deref(&self) -> &Self::Target {
self.0
}
}
impl DerefMut for LocalCpu {
fn deref_mut(&mut self) -> &mut Self::Target {
self.0
}
} }

View File

@ -323,11 +323,7 @@ fn el0_sync_inner(frame: &mut ExceptionFrame) {
// BRK in AArch64 // BRK in AArch64
0b111100 => { 0b111100 => {
let thread = Thread::current(); let thread = Thread::current();
warnln!( warnln!("Thread {} {:?} hit a breakpoint", thread.id, thread.name);
"Thread {} {:?} hit a breakpoint",
thread.id(),
thread.name()
);
thread.raise_signal(Signal::Aborted); thread.raise_signal(Signal::Aborted);
} }
_ => { _ => {
@ -337,8 +333,8 @@ fn el0_sync_inner(frame: &mut ExceptionFrame) {
let thread = Thread::current(); let thread = Thread::current();
warnln!( warnln!(
"Data abort in {} {:?} at {:#x} with address {:#x}", "Data abort in {} {:?} at {:#x} with address {:#x}",
thread.id(), thread.id,
thread.name(), thread.name,
ELR_EL1.get(), ELR_EL1.get(),
FAR_EL1.get() FAR_EL1.get()
); );

View File

@ -1,12 +1,11 @@
//! ARM GICv2 CPU registers //! ARM GICv2 CPU registers
use kernel_util::mem::device::DeviceMemoryIo;
use tock_registers::{ use tock_registers::{
interfaces::{Readable, Writeable}, interfaces::{Readable, Writeable},
register_bitfields, register_structs, register_bitfields, register_structs,
registers::ReadWrite, registers::ReadWrite,
}; };
use crate::mem::device::DeviceMemoryIo;
register_bitfields! { register_bitfields! {
u32, u32,
CTLR [ CTLR [

View File

@ -1,5 +1,6 @@
//! ARM GICv2 Distributor registers //! ARM GICv2 Distributor registers
use device_api::interrupt::IpiDeliveryTarget; use device_api::interrupt::IpiDeliveryTarget;
use kernel_util::mem::device::DeviceMemoryIo;
use spinning_top::Spinlock; use spinning_top::Spinlock;
use tock_registers::{ use tock_registers::{
interfaces::{ReadWriteable, Readable, Writeable}, interfaces::{ReadWriteable, Readable, Writeable},
@ -7,8 +8,6 @@ use tock_registers::{
registers::{ReadOnly, ReadWrite, WriteOnly}, registers::{ReadOnly, ReadWrite, WriteOnly},
}; };
use crate::mem::device::DeviceMemoryIo;
register_bitfields! { register_bitfields! {
u32, u32,
CTLR [ CTLR [

View File

@ -12,17 +12,19 @@ use device_api::{
}, },
Device, Device,
}; };
use kernel_util::{sync::IrqSafeSpinlock, util::OneTimeInit}; use kernel_util::{
mem::{
address::{FromRaw, PhysicalAddress},
device::{DeviceMemoryIo, RawDeviceMemoryMapping},
},
sync::IrqSafeSpinlock,
util::OneTimeInit,
};
use crate::{ use crate::{
arch::{aarch64::IrqNumber, Architecture, CpuMessage}, arch::{aarch64::IrqNumber, Architecture, CpuAccess, CpuMessage},
device::devtree::{self, DevTreeIndexPropExt}, device::devtree::{self, DevTreeIndexPropExt},
device_tree_driver, device_tree_driver,
mem::{
address::FromRaw,
device::{DeviceMemoryIo, RawDeviceMemoryMapping},
PhysicalAddress,
},
}; };
use self::{gicc::Gicc, gicd::Gicd}; use self::{gicc::Gicc, gicd::Gicd};
@ -141,7 +143,7 @@ impl LocalInterruptController for Gic {
let local = Cpu::local_id(); let local = Cpu::local_id();
for i in 0..CPU_COUNT.load(Ordering::Acquire) { for i in 0..CPU_COUNT.load(Ordering::Acquire) {
if i != local as usize { if i != local as usize {
Cpu::push_ipi_queue(i as u32, msg); Cpu::push_ipi(i as u32, msg);
} }
} }
} }

View File

@ -6,19 +6,21 @@ use core::{
use abi::error::Error; use abi::error::Error;
use cfg_if::cfg_if; use cfg_if::cfg_if;
use kernel_util::util::OneTimeInit; use kernel_util::{
mem::{
address::{FromRaw, PhysicalAddress},
device::RawDeviceMemoryMapping,
table::{EntryLevel, EntryLevelExt},
},
util::OneTimeInit,
};
use memtables::aarch64::{FixedTables, KERNEL_L3_COUNT}; use memtables::aarch64::{FixedTables, KERNEL_L3_COUNT};
use aarch64_cpu::registers::{TTBR0_EL1, TTBR1_EL1}; use aarch64_cpu::registers::{TTBR0_EL1, TTBR1_EL1};
use static_assertions::const_assert_eq; use static_assertions::const_assert_eq;
use tock_registers::interfaces::Writeable; use tock_registers::interfaces::Writeable;
use crate::mem::{ use crate::mem::{address::KernelImageObject, KERNEL_VIRT_OFFSET};
address::{FromRaw, IntoRaw, KernelImageObject},
device::RawDeviceMemoryMapping,
table::EntryLevel,
PhysicalAddress, KERNEL_VIRT_OFFSET,
};
use self::table::{PageAttributes, PageEntry, PageTable, L1, L2, L3}; use self::table::{PageAttributes, PageEntry, PageTable, L1, L2, L3};
@ -36,8 +38,8 @@ cfg_if! {
} }
// Precomputed mappings // Precomputed mappings
const KERNEL_L1_INDEX: usize = L1::index(KERNEL_VIRT_OFFSET + KERNEL_PHYS_BASE); const KERNEL_L1_INDEX: usize = (KERNEL_VIRT_OFFSET + KERNEL_PHYS_BASE).page_index::<L1>();
const KERNEL_START_L2_INDEX: usize = L2::index(KERNEL_VIRT_OFFSET + KERNEL_PHYS_BASE); const KERNEL_START_L2_INDEX: usize = (KERNEL_VIRT_OFFSET + KERNEL_PHYS_BASE).page_index::<L2>();
const KERNEL_END_L2_INDEX: usize = KERNEL_START_L2_INDEX + KERNEL_L3_COUNT; const KERNEL_END_L2_INDEX: usize = KERNEL_START_L2_INDEX + KERNEL_L3_COUNT;
// Must not be zero, should be at 4MiB // Must not be zero, should be at 4MiB
@ -177,7 +179,7 @@ unsafe fn unmap_early_page(address: usize) {
panic!("Tried to unmap invalid early mapping: {:#x}", address); panic!("Tried to unmap invalid early mapping: {:#x}", address);
} }
let l3i = L3::index(address - EARLY_MAPPING_OFFSET); let l3i = (address - EARLY_MAPPING_OFFSET).page_index::<L3>();
assert!(EARLY_MAPPING_L3[l3i].is_present()); assert!(EARLY_MAPPING_L3[l3i].is_present());
EARLY_MAPPING_L3[l3i] = PageEntry::INVALID; EARLY_MAPPING_L3[l3i] = PageEntry::INVALID;
@ -262,14 +264,14 @@ pub(super) unsafe fn map_device_memory(
) -> Result<RawDeviceMemoryMapping, Error> { ) -> Result<RawDeviceMemoryMapping, Error> {
// debugln!("Map {}B @ {:#x}", size, base); // debugln!("Map {}B @ {:#x}", size, base);
let l3_aligned = base.page_align_down::<L3>(); let l3_aligned = base.page_align_down::<L3>();
let l3_offset = L3::page_offset(base.into_raw()); let l3_offset = base.page_offset::<L3>();
let page_count = (l3_offset + size + L3::SIZE - 1) / L3::SIZE; let page_count = (l3_offset + size).page_count::<L3>();
if page_count > 256 { if page_count > 256 {
// Large mapping, use L2 mapping instead // Large mapping, use L2 mapping instead
let l2_aligned = base.page_align_down::<L2>(); let l2_aligned = base.page_align_down::<L2>();
let l2_offset = L2::page_offset(base.into_raw()); let l2_offset = base.page_offset::<L2>();
let page_count = (l2_offset + size + L2::SIZE - 1) / L2::SIZE; let page_count = (l2_offset + size).page_count::<L2>();
let base_address = map_device_memory_l2(l2_aligned, page_count)?; let base_address = map_device_memory_l2(l2_aligned, page_count)?;
let address = base_address + l2_offset; let address = base_address + l2_offset;
@ -304,8 +306,8 @@ pub(super) unsafe fn unmap_device_memory(map: &RawDeviceMemoryMapping) {
L3::SIZE => { L3::SIZE => {
for i in 0..map.page_count { for i in 0..map.page_count {
let page = map.base_address + i * L3::SIZE; let page = map.base_address + i * L3::SIZE;
let l2i = L2::index(page); let l2i = page.page_index::<L2>();
let l3i = L3::index(page); let l3i = page.page_index::<L3>();
assert!(DEVICE_MAPPING_L3S[l2i][l3i].is_present()); assert!(DEVICE_MAPPING_L3S[l2i][l3i].is_present());
DEVICE_MAPPING_L3S[l2i][l3i] = PageEntry::INVALID; DEVICE_MAPPING_L3S[l2i][l3i] = PageEntry::INVALID;

View File

@ -2,14 +2,16 @@
use core::sync::atomic::{AtomicU8, Ordering}; use core::sync::atomic::{AtomicU8, Ordering};
use abi::error::Error; use abi::error::Error;
use kernel_util::mem::{
address::{AsPhysicalAddress, PhysicalAddress},
pointer::PhysicalRefMut,
table::{EntryLevel, EntryLevelExt},
};
use crate::mem::{ use crate::mem::{
address::AsPhysicalAddress,
phys, phys,
pointer::PhysicalRefMut,
process::ProcessAddressSpaceManager, process::ProcessAddressSpaceManager,
table::{EntryLevel, MapAttributes, NextPageTable}, table::{MapAttributes, NextPageTable},
PhysicalAddress,
}; };
use super::table::{PageEntry, PageTable, L1, L2, L3}; use super::table::{PageEntry, PageTable, L1, L2, L3};
@ -75,9 +77,9 @@ impl ProcessAddressSpaceImpl {
entry: PageEntry<L3>, entry: PageEntry<L3>,
overwrite: bool, overwrite: bool,
) -> Result<(), Error> { ) -> Result<(), Error> {
let l1i = L1::index(virt); let l1i = virt.page_index::<L1>();
let l2i = L2::index(virt); let l2i = virt.page_index::<L2>();
let l3i = L3::index(virt); let l3i = virt.page_index::<L3>();
let mut l2 = self.l1.get_mut_or_alloc(l1i)?; let mut l2 = self.l1.get_mut_or_alloc(l1i)?;
let mut l3 = l2.get_mut_or_alloc(l2i)?; let mut l3 = l2.get_mut_or_alloc(l2i)?;
@ -93,9 +95,9 @@ impl ProcessAddressSpaceImpl {
} }
fn pop_l3_entry(&mut self, virt: usize) -> Result<PhysicalAddress, Error> { fn pop_l3_entry(&mut self, virt: usize) -> Result<PhysicalAddress, Error> {
let l1i = L1::index(virt); let l1i = virt.page_index::<L1>();
let l2i = L2::index(virt); let l2i = virt.page_index::<L2>();
let l3i = L3::index(virt); let l3i = virt.page_index::<L3>();
// TODO somehow drop tables if they're known to be empty? // TODO somehow drop tables if they're known to be empty?
let mut l2 = self.l1.get_mut(l1i).ok_or(Error::DoesNotExist)?; let mut l2 = self.l1.get_mut(l1i).ok_or(Error::DoesNotExist)?;
@ -110,9 +112,9 @@ impl ProcessAddressSpaceImpl {
} }
fn read_l3_entry(&self, virt: usize) -> Option<(PhysicalAddress, MapAttributes)> { fn read_l3_entry(&self, virt: usize) -> Option<(PhysicalAddress, MapAttributes)> {
let l1i = L1::index(virt); let l1i = virt.page_index::<L1>();
let l2i = L2::index(virt); let l2i = virt.page_index::<L2>();
let l3i = L3::index(virt); let l3i = virt.page_index::<L3>();
let l2 = self.l1.get(l1i)?; let l2 = self.l1.get(l1i)?;
let l3 = l2.get(l2i)?; let l3 = l2.get(l2i)?;

View File

@ -5,13 +5,15 @@ use core::{
use abi::error::Error; use abi::error::Error;
use bitflags::bitflags; use bitflags::bitflags;
use kernel_util::mem::{
address::{AsPhysicalAddress, FromRaw, IntoRaw, PhysicalAddress},
pointer::{PhysicalRef, PhysicalRefMut},
table::EntryLevel,
};
use crate::mem::{ use crate::mem::{
address::{AsPhysicalAddress, FromRaw, IntoRaw},
phys, phys,
pointer::{PhysicalRef, PhysicalRefMut}, table::{MapAttributes, NextPageTable, NonTerminalEntryLevel},
table::{EntryLevel, MapAttributes, NextPageTable, NonTerminalEntryLevel},
PhysicalAddress,
}; };
bitflags! { bitflags! {
@ -60,23 +62,23 @@ pub struct L2;
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct L3; pub struct L3;
impl const EntryLevel for L1 {
const SHIFT: usize = 30;
}
impl NonTerminalEntryLevel for L1 { impl NonTerminalEntryLevel for L1 {
type NextLevel = L2; type NextLevel = L2;
} }
impl const EntryLevel for L2 {
const SHIFT: usize = 21;
}
impl NonTerminalEntryLevel for L2 { impl NonTerminalEntryLevel for L2 {
type NextLevel = L3; type NextLevel = L3;
} }
impl const EntryLevel for L3 { impl EntryLevel for L1 {
const SHIFT: usize = 30;
}
impl EntryLevel for L2 {
const SHIFT: usize = 21;
}
impl EntryLevel for L3 {
const SHIFT: usize = 12; const SHIFT: usize = 12;
} }

View File

@ -13,7 +13,15 @@ use device_api::{
}; };
use fdt_rs::base::DevTree; use fdt_rs::base::DevTree;
use git_version::git_version; use git_version::git_version;
use kernel_util::util::OneTimeInit; use kernel_util::{
mem::{
address::{FromRaw, IntoRaw, PhysicalAddress},
device::RawDeviceMemoryMapping,
pointer::PhysicalRef,
table::{EntryLevel, EntryLevelExt},
},
util::OneTimeInit,
};
use tock_registers::interfaces::{ReadWriteable, Readable, Writeable}; use tock_registers::interfaces::{ReadWriteable, Readable, Writeable};
use crate::{ use crate::{
@ -29,13 +37,8 @@ use crate::{
}, },
fs::{Initrd, INITRD_DATA}, fs::{Initrd, INITRD_DATA},
mem::{ mem::{
address::{FromRaw, IntoRaw},
device::RawDeviceMemoryMapping,
heap, heap,
phys::{self, reserved::reserve_region, PhysicalMemoryRegion}, phys::{self, reserved::reserve_region, PhysicalMemoryRegion},
pointer::PhysicalRef,
table::EntryLevel,
PhysicalAddress,
}, },
}; };
@ -80,6 +83,8 @@ impl Architecture for AArch64 {
type IrqNumber = IrqNumber; type IrqNumber = IrqNumber;
type L3 = L3;
unsafe fn start_application_processors(&self) { unsafe fn start_application_processors(&self) {
let dt = self.dt.get(); let dt = self.dt.get();
if let Err(error) = smp::start_ap_cores(dt) { if let Err(error) = smp::start_ap_cores(dt) {
@ -125,7 +130,7 @@ impl Architecture for AArch64 {
_memory_start: PhysicalAddress, _memory_start: PhysicalAddress,
memory_end: PhysicalAddress, memory_end: PhysicalAddress,
) -> Result<(), Error> { ) -> Result<(), Error> {
let end_l1i = L1::index(memory_end.page_align_up::<L1>().into_raw()); let end_l1i = memory_end.page_align_up::<L1>().page_index::<L1>();
if end_l1i > mem::RAM_MAPPING_L1_COUNT { if end_l1i > mem::RAM_MAPPING_L1_COUNT {
todo!() todo!()
} }
@ -142,25 +147,23 @@ impl Architecture for AArch64 {
Ok(()) Ok(())
} }
fn virtualize(address: PhysicalAddress) -> Result<usize, Error> { fn virtualize(address: u64) -> usize {
let raw: usize = address.into_raw(); let address = address as usize;
if raw < *mem::MEMORY_LIMIT.get() { if address < *mem::MEMORY_LIMIT.get() {
Ok(raw + mem::RAM_MAPPING_OFFSET) address + mem::RAM_MAPPING_OFFSET
} else { } else {
errorln!("Invalid physical address: {:#x}", address); panic!("Invalid physical address: {:#x}", address);
Err(Error::InvalidMemoryOperation)
} }
} }
fn physicalize(address: usize) -> Result<PhysicalAddress, Error> { fn physicalize(address: usize) -> u64 {
if address < mem::RAM_MAPPING_OFFSET if address < mem::RAM_MAPPING_OFFSET
|| address - mem::RAM_MAPPING_OFFSET >= *mem::MEMORY_LIMIT.get() || address - mem::RAM_MAPPING_OFFSET >= *mem::MEMORY_LIMIT.get()
{ {
errorln!("Not a virtualized physical address: {:#x}", address); panic!("Not a virtualized physical address: {:#x}", address);
return Err(Error::InvalidMemoryOperation);
} }
Ok(PhysicalAddress::from_raw(address - mem::RAM_MAPPING_OFFSET)) (address - mem::RAM_MAPPING_OFFSET) as _
} }
fn local_interrupt_controller( fn local_interrupt_controller(
@ -362,13 +365,12 @@ impl AArch64 {
infoln!("Initializing aarch64 platform"); infoln!("Initializing aarch64 platform");
let nodes = dt.root().children(); let nodes = dt.root().children();
if let Err(error) = devtree::enumerate_dt( if let Err(error) =
address_cells, devtree::enumerate_dt(address_cells, size_cells, nodes, |_, probe| {
size_cells,
nodes,
|_, probe| {
// Skip chosen-stdout, already initialized // Skip chosen-stdout, already initialized
if let Some(ref chosen_stdout) = chosen_stdout && chosen_stdout.name() == probe.node.name() { if let Some(ref chosen_stdout) = chosen_stdout
&& chosen_stdout.name() == probe.node.name()
{
return Ok(()); return Ok(());
} }
@ -377,8 +379,8 @@ impl AArch64 {
} }
Ok(()) Ok(())
}, })
) { {
warnln!( warnln!(
"{} errors encountered when initializing platform devices", "{} errors encountered when initializing platform devices",
error error

View File

@ -6,12 +6,12 @@ use aarch64_cpu::registers::{CNTFRQ_EL0, CNTPCT_EL0, CNTP_CTL_EL0, CNTP_TVAL_EL0
use abi::error::Error; use abi::error::Error;
use alloc::boxed::Box; use alloc::boxed::Box;
use device_api::{interrupt::InterruptHandler, timer::MonotonicTimestampProviderDevice, Device}; use device_api::{interrupt::InterruptHandler, timer::MonotonicTimestampProviderDevice, Device};
use kernel_util::runtime;
use tock_registers::interfaces::{ReadWriteable, Readable, Writeable}; use tock_registers::interfaces::{ReadWriteable, Readable, Writeable};
use crate::{ use crate::{
arch::{aarch64::IrqNumber, Architecture, ARCHITECTURE}, arch::{aarch64::IrqNumber, Architecture, CpuAccess, ARCHITECTURE},
device_tree_driver, device_tree_driver,
task::runtime,
}; };
use super::cpu::Cpu; use super::cpu::Cpu;

View File

@ -251,7 +251,9 @@ pub trait CpuAccess: Sized {
} }
/// Returns the ID of the local processor or 0 if the processor has not yet been initialized /// Returns the ID of the local processor or 0 if the processor has not yet been initialized
fn local_id() -> u32; fn local_id() -> u32 {
Self::try_local().map(|cpu| cpu.id()).unwrap_or(0)
}
/// Initializes the CPU's scheduling queue. /// Initializes the CPU's scheduling queue.
/// ///
@ -281,6 +283,18 @@ pub trait CpuAccess: Sized {
/// ///
/// Only meant to be called from within the scheduler. /// Only meant to be called from within the scheduler.
unsafe fn set_current_thread_id(&mut self, id: Option<ThreadId>); unsafe fn set_current_thread_id(&mut self, id: Option<ThreadId>);
/// Push an IPI message to the CPU's queue
fn push_ipi(id: u32, msg: CpuMessage) {
let _ = id;
let _ = msg;
// Not implemented by default
}
/// Pops an IPI message (if any is present) from the CPU's queue and handles it
fn handle_ipi(&mut self) {
// Not implemented by default
}
} }
// External API for architecture specifics // External API for architecture specifics

View File

@ -9,11 +9,9 @@ use fdt_rs::{
index::{iters::DevTreeIndexNodeSiblingIter, DevTreeIndex, DevTreeIndexNode, DevTreeIndexProp}, index::{iters::DevTreeIndexNodeSiblingIter, DevTreeIndex, DevTreeIndexNode, DevTreeIndexProp},
prelude::PropReader, prelude::PropReader,
}; };
use kernel_util::mem::address::{FromRaw, PhysicalAddress};
use crate::{ use crate::{debug::LogLevel, mem::phys::PhysicalMemoryRegion};
debug::LogLevel,
mem::{address::FromRaw, phys::PhysicalMemoryRegion, PhysicalAddress},
};
use super::register_device; use super::register_device;

View File

@ -2,25 +2,32 @@
use abi::{error::Error, io::DeviceRequest}; use abi::{error::Error, io::DeviceRequest};
use alloc::boxed::Box; use alloc::boxed::Box;
use device_api::{interrupt::InterruptHandler, serial::SerialDevice, Device}; use device_api::{interrupt::InterruptHandler, serial::SerialDevice, Device};
use kernel_util::{sync::IrqSafeSpinlock, util::OneTimeInit}; use futures_util::task::{Context, Poll};
use kernel_fs::devfs::{self, CharDeviceType};
use kernel_util::{
block,
mem::{
address::{FromRaw, PhysicalAddress},
device::DeviceMemoryIo,
},
sync::IrqSafeSpinlock,
util::OneTimeInit,
};
use tock_registers::{ use tock_registers::{
interfaces::{ReadWriteable, Readable, Writeable}, interfaces::{ReadWriteable, Readable, Writeable},
register_bitfields, register_structs, register_bitfields, register_structs,
registers::{ReadOnly, ReadWrite, WriteOnly}, registers::{ReadOnly, ReadWrite, WriteOnly},
}; };
use vfs::CharDevice; use vfs::{CharDevice, FileReadiness};
use crate::{ use crate::{
arch::{aarch64::IrqNumber, Architecture, ARCHITECTURE}, arch::{aarch64::IrqNumber, Architecture, ARCHITECTURE},
block,
debug::{self, DebugSink, LogLevel}, debug::{self, DebugSink, LogLevel},
device::{ device::{
devtree::{self, DevTreeIndexPropExt}, devtree::{self, DevTreeIndexPropExt},
tty::{TtyContext, TtyDevice}, tty::{TtyContext, TtyDevice},
}, },
device_tree_driver, device_tree_driver,
fs::devfs::{self, CharDeviceType},
mem::{address::FromRaw, device::DeviceMemoryIo, PhysicalAddress},
task::process::ProcessId, task::process::ProcessId,
}; };
@ -108,6 +115,12 @@ impl TtyDevice for Pl011 {
} }
} }
impl FileReadiness for Pl011 {
fn poll_read(&self, _cx: &mut Context<'_>) -> Poll<Result<(), Error>> {
todo!()
}
}
// impl CharDevice for Pl011 { // impl CharDevice for Pl011 {
// fn write(&self, blocking: bool, data: &[u8]) -> Result<usize, Error> { // fn write(&self, blocking: bool, data: &[u8]) -> Result<usize, Error> {
// assert!(blocking); // assert!(blocking);

View File

@ -214,5 +214,6 @@ static QUEUES: OneTimeInit<Vec<CpuQueue>> = OneTimeInit::new();
/// Initializes the global queue list /// Initializes the global queue list
pub fn init_queues(queues: Vec<CpuQueue>) { pub fn init_queues(queues: Vec<CpuQueue>) {
debugln!("init_queues!!!");
QUEUES.init(queues); QUEUES.init(queues);
} }