arch/aarch64: fix aarch64 build
This commit is contained in:
parent
b760a5bad9
commit
0e8860c719
@ -19,9 +19,6 @@ vmalloc = { path = "lib/vmalloc" }
|
||||
device-api-macros = { path = "lib/device-api/macros" }
|
||||
|
||||
# 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" }
|
||||
kernel-fs = { path = "driver/fs/kernel-fs" }
|
||||
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" }
|
||||
# TODO currently only supported here
|
||||
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]
|
||||
default = ["fb_console"]
|
||||
|
@ -5,6 +5,14 @@ use aarch64_cpu::{
|
||||
asm::barrier,
|
||||
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 super::{
|
||||
@ -13,10 +21,8 @@ use super::{
|
||||
};
|
||||
use crate::{
|
||||
arch::{aarch64::mem::table::L3, Architecture},
|
||||
fs::devfs,
|
||||
kernel_main, kernel_secondary_main,
|
||||
mem::{address::IntoRaw, phys, table::EntryLevel, PhysicalAddress, KERNEL_VIRT_OFFSET},
|
||||
task::runtime,
|
||||
mem::{phys, KERNEL_VIRT_OFFSET},
|
||||
};
|
||||
|
||||
unsafe fn pre_init_mmu() {
|
||||
|
@ -1,12 +1,22 @@
|
||||
//! 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 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 crate::{arch::CpuMessage, panic, task::sched::CpuQueue};
|
||||
use crate::{
|
||||
arch::{CpuAccess, CpuMessage, LocalCpuAccess},
|
||||
panic,
|
||||
task::{sched::CpuQueue, thread::ThreadId},
|
||||
};
|
||||
|
||||
use super::smp::CPU_COUNT;
|
||||
|
||||
@ -18,8 +28,17 @@ pub struct Cpu {
|
||||
id: u32,
|
||||
|
||||
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 {
|
||||
data: IrqSafeSpinlock<Option<CpuMessage>>,
|
||||
}
|
||||
@ -47,17 +66,11 @@ impl IpiQueue {
|
||||
}
|
||||
|
||||
impl Cpu {
|
||||
/// Returns a safe reference to the local CPU's private data structure
|
||||
#[inline(always)]
|
||||
pub fn local<'a>() -> &'a Self {
|
||||
Self::get_local().unwrap()
|
||||
}
|
||||
|
||||
/// 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 global list of interprocessor message queues
|
||||
pub fn init_ipi_queues() {
|
||||
IPI_QUEUES.init(Vec::from_iter(
|
||||
(0..CPU_COUNT.load(Ordering::Acquire)).map(|_| IpiQueue::new()),
|
||||
));
|
||||
}
|
||||
|
||||
/// Sets up the local CPU's private data structure.
|
||||
@ -69,60 +82,81 @@ impl Cpu {
|
||||
let this = Box::new(Cpu {
|
||||
id: Self::local_id(),
|
||||
queue: OneTimeInit::new(),
|
||||
thread_id: None,
|
||||
});
|
||||
TPIDR_EL1.set(Box::into_raw(this) as _);
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets up the local CPU's execution queue.
|
||||
pub fn init_queue(&self, queue: &'static CpuQueue) {
|
||||
self.queue.init(queue);
|
||||
impl CpuAccess for Cpu {
|
||||
type Local = LocalCpu;
|
||||
|
||||
fn id(&self) -> u32 {
|
||||
self.id
|
||||
}
|
||||
|
||||
/// Returns the local CPU's execution queue.
|
||||
pub fn queue(&self) -> &'static CpuQueue {
|
||||
self.queue.get()
|
||||
}
|
||||
|
||||
/// Returns the index of the local CPU
|
||||
#[inline(always)]
|
||||
pub fn local_id() -> u32 {
|
||||
fn local_id() -> u32 {
|
||||
(MPIDR_EL1.get() & 0xFF) as _
|
||||
}
|
||||
|
||||
/// Inserts an IPI message to the back of the target CPU's message queue
|
||||
pub fn push_ipi_queue(cpu_id: u32, msg: CpuMessage) {
|
||||
let ipi_queue = &IPI_QUEUES.get()[cpu_id as usize];
|
||||
ipi_queue.push(msg);
|
||||
fn try_local() -> Option<Self::Local> {
|
||||
let guard = IrqGuard::acquire();
|
||||
let tpidr = TPIDR_EL1.get() as *mut Cpu;
|
||||
unsafe { tpidr.as_mut() }.map(|cpu| LocalCpu(cpu, guard))
|
||||
}
|
||||
|
||||
/// Pops the first IPI message received for this CPU.
|
||||
///
|
||||
/// # 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()
|
||||
fn get_queue(&self) -> Option<&'static CpuQueue> {
|
||||
self.queue.try_get().copied()
|
||||
}
|
||||
|
||||
/// Sets up global list of interprocessor message queues
|
||||
pub fn init_ipi_queues() {
|
||||
IPI_QUEUES.init(Vec::from_iter(
|
||||
(0..CPU_COUNT.load(Ordering::Acquire)).map(|_| IpiQueue::new()),
|
||||
));
|
||||
fn init_queue(&mut self, queue: &'static CpuQueue) {
|
||||
self.queue.init(queue);
|
||||
}
|
||||
|
||||
/// Gets an IPI message from the processor's queue and takes corresponding actions. If there is
|
||||
/// none, this is treated as a spurious IPI and ignored. See [CpuMessage].
|
||||
pub fn handle_ipi(&self) {
|
||||
let Some(msg) = self.get_ipi() else {
|
||||
warnln!("Spurious IPI in cpu{}", self.id);
|
||||
return;
|
||||
};
|
||||
unsafe fn set_current_thread_id(&mut self, id: Option<ThreadId>) {
|
||||
self.thread_id = id;
|
||||
}
|
||||
|
||||
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::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
|
||||
}
|
||||
}
|
||||
|
@ -323,11 +323,7 @@ fn el0_sync_inner(frame: &mut ExceptionFrame) {
|
||||
// BRK in AArch64
|
||||
0b111100 => {
|
||||
let thread = Thread::current();
|
||||
warnln!(
|
||||
"Thread {} {:?} hit a breakpoint",
|
||||
thread.id(),
|
||||
thread.name()
|
||||
);
|
||||
warnln!("Thread {} {:?} hit a breakpoint", thread.id, thread.name);
|
||||
thread.raise_signal(Signal::Aborted);
|
||||
}
|
||||
_ => {
|
||||
@ -337,8 +333,8 @@ fn el0_sync_inner(frame: &mut ExceptionFrame) {
|
||||
let thread = Thread::current();
|
||||
warnln!(
|
||||
"Data abort in {} {:?} at {:#x} with address {:#x}",
|
||||
thread.id(),
|
||||
thread.name(),
|
||||
thread.id,
|
||||
thread.name,
|
||||
ELR_EL1.get(),
|
||||
FAR_EL1.get()
|
||||
);
|
||||
|
@ -1,12 +1,11 @@
|
||||
//! ARM GICv2 CPU registers
|
||||
use kernel_util::mem::device::DeviceMemoryIo;
|
||||
use tock_registers::{
|
||||
interfaces::{Readable, Writeable},
|
||||
register_bitfields, register_structs,
|
||||
registers::ReadWrite,
|
||||
};
|
||||
|
||||
use crate::mem::device::DeviceMemoryIo;
|
||||
|
||||
register_bitfields! {
|
||||
u32,
|
||||
CTLR [
|
||||
|
@ -1,5 +1,6 @@
|
||||
//! ARM GICv2 Distributor registers
|
||||
use device_api::interrupt::IpiDeliveryTarget;
|
||||
use kernel_util::mem::device::DeviceMemoryIo;
|
||||
use spinning_top::Spinlock;
|
||||
use tock_registers::{
|
||||
interfaces::{ReadWriteable, Readable, Writeable},
|
||||
@ -7,8 +8,6 @@ use tock_registers::{
|
||||
registers::{ReadOnly, ReadWrite, WriteOnly},
|
||||
};
|
||||
|
||||
use crate::mem::device::DeviceMemoryIo;
|
||||
|
||||
register_bitfields! {
|
||||
u32,
|
||||
CTLR [
|
||||
|
@ -12,17 +12,19 @@ use device_api::{
|
||||
},
|
||||
Device,
|
||||
};
|
||||
use kernel_util::{sync::IrqSafeSpinlock, util::OneTimeInit};
|
||||
use kernel_util::{
|
||||
mem::{
|
||||
address::{FromRaw, PhysicalAddress},
|
||||
device::{DeviceMemoryIo, RawDeviceMemoryMapping},
|
||||
},
|
||||
sync::IrqSafeSpinlock,
|
||||
util::OneTimeInit,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
arch::{aarch64::IrqNumber, Architecture, CpuMessage},
|
||||
arch::{aarch64::IrqNumber, Architecture, CpuAccess, CpuMessage},
|
||||
device::devtree::{self, DevTreeIndexPropExt},
|
||||
device_tree_driver,
|
||||
mem::{
|
||||
address::FromRaw,
|
||||
device::{DeviceMemoryIo, RawDeviceMemoryMapping},
|
||||
PhysicalAddress,
|
||||
},
|
||||
};
|
||||
|
||||
use self::{gicc::Gicc, gicd::Gicd};
|
||||
@ -141,7 +143,7 @@ impl LocalInterruptController for Gic {
|
||||
let local = Cpu::local_id();
|
||||
for i in 0..CPU_COUNT.load(Ordering::Acquire) {
|
||||
if i != local as usize {
|
||||
Cpu::push_ipi_queue(i as u32, msg);
|
||||
Cpu::push_ipi(i as u32, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,19 +6,21 @@ use core::{
|
||||
|
||||
use abi::error::Error;
|
||||
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 aarch64_cpu::registers::{TTBR0_EL1, TTBR1_EL1};
|
||||
use static_assertions::const_assert_eq;
|
||||
use tock_registers::interfaces::Writeable;
|
||||
|
||||
use crate::mem::{
|
||||
address::{FromRaw, IntoRaw, KernelImageObject},
|
||||
device::RawDeviceMemoryMapping,
|
||||
table::EntryLevel,
|
||||
PhysicalAddress, KERNEL_VIRT_OFFSET,
|
||||
};
|
||||
use crate::mem::{address::KernelImageObject, KERNEL_VIRT_OFFSET};
|
||||
|
||||
use self::table::{PageAttributes, PageEntry, PageTable, L1, L2, L3};
|
||||
|
||||
@ -36,8 +38,8 @@ cfg_if! {
|
||||
}
|
||||
|
||||
// Precomputed mappings
|
||||
const KERNEL_L1_INDEX: usize = L1::index(KERNEL_VIRT_OFFSET + KERNEL_PHYS_BASE);
|
||||
const KERNEL_START_L2_INDEX: usize = L2::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 = (KERNEL_VIRT_OFFSET + KERNEL_PHYS_BASE).page_index::<L2>();
|
||||
const KERNEL_END_L2_INDEX: usize = KERNEL_START_L2_INDEX + KERNEL_L3_COUNT;
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
let l3i = L3::index(address - EARLY_MAPPING_OFFSET);
|
||||
let l3i = (address - EARLY_MAPPING_OFFSET).page_index::<L3>();
|
||||
|
||||
assert!(EARLY_MAPPING_L3[l3i].is_present());
|
||||
EARLY_MAPPING_L3[l3i] = PageEntry::INVALID;
|
||||
@ -262,14 +264,14 @@ pub(super) unsafe fn map_device_memory(
|
||||
) -> Result<RawDeviceMemoryMapping, Error> {
|
||||
// debugln!("Map {}B @ {:#x}", size, base);
|
||||
let l3_aligned = base.page_align_down::<L3>();
|
||||
let l3_offset = L3::page_offset(base.into_raw());
|
||||
let page_count = (l3_offset + size + L3::SIZE - 1) / L3::SIZE;
|
||||
let l3_offset = base.page_offset::<L3>();
|
||||
let page_count = (l3_offset + size).page_count::<L3>();
|
||||
|
||||
if page_count > 256 {
|
||||
// Large mapping, use L2 mapping instead
|
||||
let l2_aligned = base.page_align_down::<L2>();
|
||||
let l2_offset = L2::page_offset(base.into_raw());
|
||||
let page_count = (l2_offset + size + L2::SIZE - 1) / L2::SIZE;
|
||||
let l2_offset = base.page_offset::<L2>();
|
||||
let page_count = (l2_offset + size).page_count::<L2>();
|
||||
|
||||
let base_address = map_device_memory_l2(l2_aligned, page_count)?;
|
||||
let address = base_address + l2_offset;
|
||||
@ -304,8 +306,8 @@ pub(super) unsafe fn unmap_device_memory(map: &RawDeviceMemoryMapping) {
|
||||
L3::SIZE => {
|
||||
for i in 0..map.page_count {
|
||||
let page = map.base_address + i * L3::SIZE;
|
||||
let l2i = L2::index(page);
|
||||
let l3i = L3::index(page);
|
||||
let l2i = page.page_index::<L2>();
|
||||
let l3i = page.page_index::<L3>();
|
||||
assert!(DEVICE_MAPPING_L3S[l2i][l3i].is_present());
|
||||
DEVICE_MAPPING_L3S[l2i][l3i] = PageEntry::INVALID;
|
||||
|
||||
|
@ -2,14 +2,16 @@
|
||||
use core::sync::atomic::{AtomicU8, Ordering};
|
||||
|
||||
use abi::error::Error;
|
||||
use kernel_util::mem::{
|
||||
address::{AsPhysicalAddress, PhysicalAddress},
|
||||
pointer::PhysicalRefMut,
|
||||
table::{EntryLevel, EntryLevelExt},
|
||||
};
|
||||
|
||||
use crate::mem::{
|
||||
address::AsPhysicalAddress,
|
||||
phys,
|
||||
pointer::PhysicalRefMut,
|
||||
process::ProcessAddressSpaceManager,
|
||||
table::{EntryLevel, MapAttributes, NextPageTable},
|
||||
PhysicalAddress,
|
||||
table::{MapAttributes, NextPageTable},
|
||||
};
|
||||
|
||||
use super::table::{PageEntry, PageTable, L1, L2, L3};
|
||||
@ -75,9 +77,9 @@ impl ProcessAddressSpaceImpl {
|
||||
entry: PageEntry<L3>,
|
||||
overwrite: bool,
|
||||
) -> Result<(), Error> {
|
||||
let l1i = L1::index(virt);
|
||||
let l2i = L2::index(virt);
|
||||
let l3i = L3::index(virt);
|
||||
let l1i = virt.page_index::<L1>();
|
||||
let l2i = virt.page_index::<L2>();
|
||||
let l3i = virt.page_index::<L3>();
|
||||
|
||||
let mut l2 = self.l1.get_mut_or_alloc(l1i)?;
|
||||
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> {
|
||||
let l1i = L1::index(virt);
|
||||
let l2i = L2::index(virt);
|
||||
let l3i = L3::index(virt);
|
||||
let l1i = virt.page_index::<L1>();
|
||||
let l2i = virt.page_index::<L2>();
|
||||
let l3i = virt.page_index::<L3>();
|
||||
|
||||
// TODO somehow drop tables if they're known to be empty?
|
||||
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)> {
|
||||
let l1i = L1::index(virt);
|
||||
let l2i = L2::index(virt);
|
||||
let l3i = L3::index(virt);
|
||||
let l1i = virt.page_index::<L1>();
|
||||
let l2i = virt.page_index::<L2>();
|
||||
let l3i = virt.page_index::<L3>();
|
||||
|
||||
let l2 = self.l1.get(l1i)?;
|
||||
let l3 = l2.get(l2i)?;
|
||||
|
@ -5,13 +5,15 @@ use core::{
|
||||
|
||||
use abi::error::Error;
|
||||
use bitflags::bitflags;
|
||||
use kernel_util::mem::{
|
||||
address::{AsPhysicalAddress, FromRaw, IntoRaw, PhysicalAddress},
|
||||
pointer::{PhysicalRef, PhysicalRefMut},
|
||||
table::EntryLevel,
|
||||
};
|
||||
|
||||
use crate::mem::{
|
||||
address::{AsPhysicalAddress, FromRaw, IntoRaw},
|
||||
phys,
|
||||
pointer::{PhysicalRef, PhysicalRefMut},
|
||||
table::{EntryLevel, MapAttributes, NextPageTable, NonTerminalEntryLevel},
|
||||
PhysicalAddress,
|
||||
table::{MapAttributes, NextPageTable, NonTerminalEntryLevel},
|
||||
};
|
||||
|
||||
bitflags! {
|
||||
@ -60,23 +62,23 @@ pub struct L2;
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct L3;
|
||||
|
||||
impl const EntryLevel for L1 {
|
||||
const SHIFT: usize = 30;
|
||||
}
|
||||
|
||||
impl NonTerminalEntryLevel for L1 {
|
||||
type NextLevel = L2;
|
||||
}
|
||||
|
||||
impl const EntryLevel for L2 {
|
||||
const SHIFT: usize = 21;
|
||||
}
|
||||
|
||||
impl NonTerminalEntryLevel for L2 {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,15 @@ use device_api::{
|
||||
};
|
||||
use fdt_rs::base::DevTree;
|
||||
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 crate::{
|
||||
@ -29,13 +37,8 @@ use crate::{
|
||||
},
|
||||
fs::{Initrd, INITRD_DATA},
|
||||
mem::{
|
||||
address::{FromRaw, IntoRaw},
|
||||
device::RawDeviceMemoryMapping,
|
||||
heap,
|
||||
phys::{self, reserved::reserve_region, PhysicalMemoryRegion},
|
||||
pointer::PhysicalRef,
|
||||
table::EntryLevel,
|
||||
PhysicalAddress,
|
||||
},
|
||||
};
|
||||
|
||||
@ -80,6 +83,8 @@ impl Architecture for AArch64 {
|
||||
|
||||
type IrqNumber = IrqNumber;
|
||||
|
||||
type L3 = L3;
|
||||
|
||||
unsafe fn start_application_processors(&self) {
|
||||
let dt = self.dt.get();
|
||||
if let Err(error) = smp::start_ap_cores(dt) {
|
||||
@ -125,7 +130,7 @@ impl Architecture for AArch64 {
|
||||
_memory_start: PhysicalAddress,
|
||||
memory_end: PhysicalAddress,
|
||||
) -> 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 {
|
||||
todo!()
|
||||
}
|
||||
@ -142,25 +147,23 @@ impl Architecture for AArch64 {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn virtualize(address: PhysicalAddress) -> Result<usize, Error> {
|
||||
let raw: usize = address.into_raw();
|
||||
if raw < *mem::MEMORY_LIMIT.get() {
|
||||
Ok(raw + mem::RAM_MAPPING_OFFSET)
|
||||
fn virtualize(address: u64) -> usize {
|
||||
let address = address as usize;
|
||||
if address < *mem::MEMORY_LIMIT.get() {
|
||||
address + mem::RAM_MAPPING_OFFSET
|
||||
} else {
|
||||
errorln!("Invalid physical address: {:#x}", address);
|
||||
Err(Error::InvalidMemoryOperation)
|
||||
panic!("Invalid physical address: {:#x}", address);
|
||||
}
|
||||
}
|
||||
|
||||
fn physicalize(address: usize) -> Result<PhysicalAddress, Error> {
|
||||
fn physicalize(address: usize) -> u64 {
|
||||
if address < mem::RAM_MAPPING_OFFSET
|
||||
|| address - mem::RAM_MAPPING_OFFSET >= *mem::MEMORY_LIMIT.get()
|
||||
{
|
||||
errorln!("Not a virtualized physical address: {:#x}", address);
|
||||
return Err(Error::InvalidMemoryOperation);
|
||||
panic!("Not a virtualized physical address: {:#x}", address);
|
||||
}
|
||||
|
||||
Ok(PhysicalAddress::from_raw(address - mem::RAM_MAPPING_OFFSET))
|
||||
(address - mem::RAM_MAPPING_OFFSET) as _
|
||||
}
|
||||
|
||||
fn local_interrupt_controller(
|
||||
@ -362,13 +365,12 @@ impl AArch64 {
|
||||
infoln!("Initializing aarch64 platform");
|
||||
|
||||
let nodes = dt.root().children();
|
||||
if let Err(error) = devtree::enumerate_dt(
|
||||
address_cells,
|
||||
size_cells,
|
||||
nodes,
|
||||
|_, probe| {
|
||||
if let Err(error) =
|
||||
devtree::enumerate_dt(address_cells, size_cells, nodes, |_, probe| {
|
||||
// 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(());
|
||||
}
|
||||
|
||||
@ -377,8 +379,8 @@ impl AArch64 {
|
||||
}
|
||||
|
||||
Ok(())
|
||||
},
|
||||
) {
|
||||
})
|
||||
{
|
||||
warnln!(
|
||||
"{} errors encountered when initializing platform devices",
|
||||
error
|
||||
|
@ -6,12 +6,12 @@ use aarch64_cpu::registers::{CNTFRQ_EL0, CNTPCT_EL0, CNTP_CTL_EL0, CNTP_TVAL_EL0
|
||||
use abi::error::Error;
|
||||
use alloc::boxed::Box;
|
||||
use device_api::{interrupt::InterruptHandler, timer::MonotonicTimestampProviderDevice, Device};
|
||||
use kernel_util::runtime;
|
||||
use tock_registers::interfaces::{ReadWriteable, Readable, Writeable};
|
||||
|
||||
use crate::{
|
||||
arch::{aarch64::IrqNumber, Architecture, ARCHITECTURE},
|
||||
arch::{aarch64::IrqNumber, Architecture, CpuAccess, ARCHITECTURE},
|
||||
device_tree_driver,
|
||||
task::runtime,
|
||||
};
|
||||
|
||||
use super::cpu::Cpu;
|
||||
|
@ -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
|
||||
fn local_id() -> u32;
|
||||
fn local_id() -> u32 {
|
||||
Self::try_local().map(|cpu| cpu.id()).unwrap_or(0)
|
||||
}
|
||||
|
||||
/// Initializes the CPU's scheduling queue.
|
||||
///
|
||||
@ -281,6 +283,18 @@ pub trait CpuAccess: Sized {
|
||||
///
|
||||
/// Only meant to be called from within the scheduler.
|
||||
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
|
||||
|
@ -9,11 +9,9 @@ use fdt_rs::{
|
||||
index::{iters::DevTreeIndexNodeSiblingIter, DevTreeIndex, DevTreeIndexNode, DevTreeIndexProp},
|
||||
prelude::PropReader,
|
||||
};
|
||||
use kernel_util::mem::address::{FromRaw, PhysicalAddress};
|
||||
|
||||
use crate::{
|
||||
debug::LogLevel,
|
||||
mem::{address::FromRaw, phys::PhysicalMemoryRegion, PhysicalAddress},
|
||||
};
|
||||
use crate::{debug::LogLevel, mem::phys::PhysicalMemoryRegion};
|
||||
|
||||
use super::register_device;
|
||||
|
||||
|
@ -2,25 +2,32 @@
|
||||
use abi::{error::Error, io::DeviceRequest};
|
||||
use alloc::boxed::Box;
|
||||
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::{
|
||||
interfaces::{ReadWriteable, Readable, Writeable},
|
||||
register_bitfields, register_structs,
|
||||
registers::{ReadOnly, ReadWrite, WriteOnly},
|
||||
};
|
||||
use vfs::CharDevice;
|
||||
use vfs::{CharDevice, FileReadiness};
|
||||
|
||||
use crate::{
|
||||
arch::{aarch64::IrqNumber, Architecture, ARCHITECTURE},
|
||||
block,
|
||||
debug::{self, DebugSink, LogLevel},
|
||||
device::{
|
||||
devtree::{self, DevTreeIndexPropExt},
|
||||
tty::{TtyContext, TtyDevice},
|
||||
},
|
||||
device_tree_driver,
|
||||
fs::devfs::{self, CharDeviceType},
|
||||
mem::{address::FromRaw, device::DeviceMemoryIo, PhysicalAddress},
|
||||
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 {
|
||||
// fn write(&self, blocking: bool, data: &[u8]) -> Result<usize, Error> {
|
||||
// assert!(blocking);
|
||||
|
@ -214,5 +214,6 @@ static QUEUES: OneTimeInit<Vec<CpuQueue>> = OneTimeInit::new();
|
||||
|
||||
/// Initializes the global queue list
|
||||
pub fn init_queues(queues: Vec<CpuQueue>) {
|
||||
debugln!("init_queues!!!");
|
||||
QUEUES.init(queues);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user