Make it possible to compile acpi system on any arch
This commit is contained in:
@@ -1,329 +0,0 @@
|
||||
use core::mem;
|
||||
|
||||
use crate::{
|
||||
memory::{allocate_p2frame, Frame},
|
||||
paging::{Page, PageFlags, PhysicalAddress, RmmA, RmmArch, VirtualAddress, PAGE_SIZE},
|
||||
};
|
||||
|
||||
use super::{find_sdt, sdt::Sdt};
|
||||
|
||||
use core::sync::atomic::{AtomicU8, Ordering};
|
||||
|
||||
use crate::{
|
||||
device::local_apic::the_local_apic,
|
||||
interrupt,
|
||||
memory::KernelMapper,
|
||||
start::{kstart_ap, AP_READY, CPU_COUNT},
|
||||
};
|
||||
|
||||
/// The Multiple APIC Descriptor Table
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Madt {
|
||||
sdt: &'static Sdt,
|
||||
pub local_address: u32,
|
||||
pub flags: u32,
|
||||
}
|
||||
|
||||
const TRAMPOLINE: usize = 0x8000;
|
||||
static TRAMPOLINE_DATA: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/trampoline"));
|
||||
|
||||
pub static mut MADT: Option<Madt> = None;
|
||||
pub const FLAG_PCAT: u32 = 1;
|
||||
|
||||
impl Madt {
|
||||
pub fn init() {
|
||||
let madt_sdt = find_sdt("APIC");
|
||||
let madt = if madt_sdt.len() == 1 {
|
||||
Madt::new(madt_sdt[0])
|
||||
} else {
|
||||
println!("Unable to find MADT");
|
||||
return;
|
||||
};
|
||||
|
||||
if let Some(madt) = madt {
|
||||
// safe because no APs have been started yet.
|
||||
unsafe { MADT = Some(madt) };
|
||||
|
||||
println!(" APIC: {:>08X}: {}", madt.local_address, madt.flags);
|
||||
|
||||
let local_apic = unsafe { the_local_apic() };
|
||||
let me = local_apic.id() as u8;
|
||||
|
||||
if local_apic.x2 {
|
||||
println!(" X2APIC {}", me);
|
||||
} else {
|
||||
println!(" XAPIC {}: {:>08X}", me, local_apic.address);
|
||||
}
|
||||
|
||||
if cfg!(feature = "multi_core") {
|
||||
// Map trampoline
|
||||
let trampoline_frame = Frame::containing(PhysicalAddress::new(TRAMPOLINE));
|
||||
let trampoline_page = Page::containing_address(VirtualAddress::new(TRAMPOLINE));
|
||||
let (result, page_table_physaddr) = unsafe {
|
||||
//TODO: do not have writable and executable!
|
||||
let mut mapper = KernelMapper::lock();
|
||||
|
||||
let result = mapper
|
||||
.get_mut()
|
||||
.expect("expected kernel page table not to be recursively locked while initializing MADT")
|
||||
.map_phys(trampoline_page.start_address(), trampoline_frame.base(), PageFlags::new().execute(true).write(true))
|
||||
.expect("failed to map trampoline");
|
||||
|
||||
(result, mapper.table().phys().data())
|
||||
};
|
||||
result.flush();
|
||||
|
||||
// Write trampoline, make sure TRAMPOLINE page is free for use
|
||||
for i in 0..TRAMPOLINE_DATA.len() {
|
||||
unsafe {
|
||||
(*((TRAMPOLINE as *mut u8).add(i) as *const AtomicU8))
|
||||
.store(TRAMPOLINE_DATA[i], Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
|
||||
for madt_entry in madt.iter() {
|
||||
println!(" {:?}", madt_entry);
|
||||
match madt_entry {
|
||||
MadtEntry::LocalApic(ap_local_apic) => {
|
||||
if ap_local_apic.id == me {
|
||||
println!(" This is my local APIC");
|
||||
} else {
|
||||
if ap_local_apic.flags & 1 == 1 {
|
||||
// Increase CPU ID
|
||||
CPU_COUNT.fetch_add(1, Ordering::SeqCst);
|
||||
|
||||
// Allocate a stack
|
||||
let stack_start = allocate_p2frame(4)
|
||||
.expect("no more frames in acpi stack_start")
|
||||
.base()
|
||||
.data()
|
||||
+ crate::PHYS_OFFSET;
|
||||
let stack_end = stack_start + (PAGE_SIZE << 4);
|
||||
|
||||
let ap_ready = (TRAMPOLINE + 8) as *mut u64;
|
||||
let ap_cpu_id = unsafe { ap_ready.add(1) };
|
||||
let ap_page_table = unsafe { ap_ready.add(2) };
|
||||
let ap_stack_start = unsafe { ap_ready.add(3) };
|
||||
let ap_stack_end = unsafe { ap_ready.add(4) };
|
||||
let ap_code = unsafe { ap_ready.add(5) };
|
||||
|
||||
// Set the ap_ready to 0, volatile
|
||||
unsafe {
|
||||
ap_ready.write(0);
|
||||
ap_cpu_id.write(ap_local_apic.id.into());
|
||||
ap_page_table.write(page_table_physaddr as u64);
|
||||
ap_stack_start.write(stack_start as u64);
|
||||
ap_stack_end.write(stack_end as u64);
|
||||
ap_code.write(kstart_ap as u64);
|
||||
|
||||
// TODO: Is this necessary (this fence)?
|
||||
core::arch::asm!("");
|
||||
};
|
||||
AP_READY.store(false, Ordering::SeqCst);
|
||||
|
||||
print!(" AP {}:", ap_local_apic.id);
|
||||
|
||||
// Send INIT IPI
|
||||
{
|
||||
let mut icr = 0x4500;
|
||||
if local_apic.x2 {
|
||||
icr |= (ap_local_apic.id as u64) << 32;
|
||||
} else {
|
||||
icr |= (ap_local_apic.id as u64) << 56;
|
||||
}
|
||||
print!(" IPI...");
|
||||
local_apic.set_icr(icr);
|
||||
}
|
||||
|
||||
// Send START IPI
|
||||
{
|
||||
//Start at 0x0800:0000 => 0x8000. Hopefully the bootloader code is still there
|
||||
let ap_segment = (TRAMPOLINE >> 12) & 0xFF;
|
||||
let mut icr = 0x4600 | ap_segment as u64;
|
||||
|
||||
if local_apic.x2 {
|
||||
icr |= (ap_local_apic.id as u64) << 32;
|
||||
} else {
|
||||
icr |= (ap_local_apic.id as u64) << 56;
|
||||
}
|
||||
|
||||
print!(" SIPI...");
|
||||
local_apic.set_icr(icr);
|
||||
}
|
||||
|
||||
// Wait for trampoline ready
|
||||
print!(" Wait...");
|
||||
while unsafe {
|
||||
(*ap_ready.cast::<AtomicU8>()).load(Ordering::SeqCst)
|
||||
} == 0
|
||||
{
|
||||
interrupt::pause();
|
||||
}
|
||||
print!(" Trampoline...");
|
||||
while !AP_READY.load(Ordering::SeqCst) {
|
||||
interrupt::pause();
|
||||
}
|
||||
println!(" Ready");
|
||||
|
||||
unsafe {
|
||||
RmmA::invalidate_all();
|
||||
}
|
||||
} else {
|
||||
println!(" CPU Disabled");
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
// Unmap trampoline
|
||||
let (_frame, _, flush) = unsafe {
|
||||
KernelMapper::lock()
|
||||
.get_mut()
|
||||
.expect("expected kernel page table not to be recursively locked while initializing MADT")
|
||||
.unmap_phys(trampoline_page.start_address(), true)
|
||||
.expect("failed to unmap trampoline page")
|
||||
};
|
||||
flush.flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(sdt: &'static Sdt) -> Option<Madt> {
|
||||
if &sdt.signature == b"APIC" && sdt.data_len() >= 8 {
|
||||
//Not valid if no local address and flags
|
||||
let local_address = unsafe { (sdt.data_address() as *const u32).read_unaligned() };
|
||||
let flags = unsafe {
|
||||
(sdt.data_address() as *const u32)
|
||||
.offset(1)
|
||||
.read_unaligned()
|
||||
};
|
||||
|
||||
Some(Madt {
|
||||
sdt,
|
||||
local_address,
|
||||
flags,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> MadtIter {
|
||||
MadtIter {
|
||||
sdt: self.sdt,
|
||||
i: 8, // Skip local controller address and flags
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// MADT Local APIC
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[repr(C, packed)]
|
||||
pub struct MadtLocalApic {
|
||||
/// Processor ID
|
||||
pub processor: u8,
|
||||
/// Local APIC ID
|
||||
pub id: u8,
|
||||
/// Flags. 1 means that the processor is enabled
|
||||
pub flags: u32,
|
||||
}
|
||||
|
||||
/// MADT I/O APIC
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[repr(C, packed)]
|
||||
pub struct MadtIoApic {
|
||||
/// I/O APIC ID
|
||||
pub id: u8,
|
||||
/// reserved
|
||||
_reserved: u8,
|
||||
/// I/O APIC address
|
||||
pub address: u32,
|
||||
/// Global system interrupt base
|
||||
pub gsi_base: u32,
|
||||
}
|
||||
|
||||
/// MADT Interrupt Source Override
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[repr(C, packed)]
|
||||
pub struct MadtIntSrcOverride {
|
||||
/// Bus Source
|
||||
pub bus_source: u8,
|
||||
/// IRQ Source
|
||||
pub irq_source: u8,
|
||||
/// Global system interrupt base
|
||||
pub gsi_base: u32,
|
||||
/// Flags
|
||||
pub flags: u16,
|
||||
}
|
||||
|
||||
/// MADT Entries
|
||||
#[derive(Debug)]
|
||||
pub enum MadtEntry {
|
||||
LocalApic(&'static MadtLocalApic),
|
||||
InvalidLocalApic(usize),
|
||||
IoApic(&'static MadtIoApic),
|
||||
InvalidIoApic(usize),
|
||||
IntSrcOverride(&'static MadtIntSrcOverride),
|
||||
InvalidIntSrcOverride(usize),
|
||||
Unknown(u8),
|
||||
}
|
||||
|
||||
pub struct MadtIter {
|
||||
sdt: &'static Sdt,
|
||||
i: usize,
|
||||
}
|
||||
|
||||
impl Iterator for MadtIter {
|
||||
type Item = MadtEntry;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.i + 1 < self.sdt.data_len() {
|
||||
let entry_type = unsafe { *(self.sdt.data_address() as *const u8).add(self.i) };
|
||||
let entry_len =
|
||||
unsafe { *(self.sdt.data_address() as *const u8).add(self.i + 1) } as usize;
|
||||
|
||||
if self.i + entry_len <= self.sdt.data_len() {
|
||||
let item = match entry_type {
|
||||
0 => {
|
||||
if entry_len == mem::size_of::<MadtLocalApic>() + 2 {
|
||||
MadtEntry::LocalApic(unsafe {
|
||||
&*((self.sdt.data_address() + self.i + 2) as *const MadtLocalApic)
|
||||
})
|
||||
} else {
|
||||
MadtEntry::InvalidLocalApic(entry_len)
|
||||
}
|
||||
}
|
||||
1 => {
|
||||
if entry_len == mem::size_of::<MadtIoApic>() + 2 {
|
||||
MadtEntry::IoApic(unsafe {
|
||||
&*((self.sdt.data_address() + self.i + 2) as *const MadtIoApic)
|
||||
})
|
||||
} else {
|
||||
MadtEntry::InvalidIoApic(entry_len)
|
||||
}
|
||||
}
|
||||
2 => {
|
||||
if entry_len == mem::size_of::<MadtIntSrcOverride>() + 2 {
|
||||
MadtEntry::IntSrcOverride(unsafe {
|
||||
&*((self.sdt.data_address() + self.i + 2)
|
||||
as *const MadtIntSrcOverride)
|
||||
})
|
||||
} else {
|
||||
MadtEntry::InvalidIntSrcOverride(entry_len)
|
||||
}
|
||||
}
|
||||
_ => MadtEntry::Unknown(entry_type),
|
||||
};
|
||||
|
||||
self.i += entry_len;
|
||||
|
||||
Some(item)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
use super::Madt;
|
||||
|
||||
pub(super) fn init(_madt: Madt) {
|
||||
log::warn!("MADT not yet handled on this platform");
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
use core::sync::atomic::{AtomicU8, Ordering};
|
||||
|
||||
use crate::{
|
||||
device::local_apic::the_local_apic,
|
||||
interrupt,
|
||||
memory::{allocate_p2frame, Frame, KernelMapper},
|
||||
paging::{Page, PageFlags, PhysicalAddress, RmmA, RmmArch, VirtualAddress, PAGE_SIZE},
|
||||
start::{kstart_ap, AP_READY, CPU_COUNT},
|
||||
};
|
||||
|
||||
use super::{Madt, MadtEntry};
|
||||
|
||||
const TRAMPOLINE: usize = 0x8000;
|
||||
static TRAMPOLINE_DATA: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/trampoline"));
|
||||
|
||||
pub(super) fn init(madt: Madt) {
|
||||
let local_apic = unsafe { the_local_apic() };
|
||||
let me = local_apic.id() as u8;
|
||||
|
||||
if local_apic.x2 {
|
||||
println!(" X2APIC {}", me);
|
||||
} else {
|
||||
println!(" XAPIC {}: {:>08X}", me, local_apic.address);
|
||||
}
|
||||
|
||||
if cfg!(feature = "multi_core") {
|
||||
// Map trampoline
|
||||
let trampoline_frame = Frame::containing(PhysicalAddress::new(TRAMPOLINE));
|
||||
let trampoline_page = Page::containing_address(VirtualAddress::new(TRAMPOLINE));
|
||||
let (result, page_table_physaddr) = unsafe {
|
||||
//TODO: do not have writable and executable!
|
||||
let mut mapper = KernelMapper::lock();
|
||||
|
||||
let result = mapper
|
||||
.get_mut()
|
||||
.expect("expected kernel page table not to be recursively locked while initializing MADT")
|
||||
.map_phys(trampoline_page.start_address(), trampoline_frame.base(), PageFlags::new().execute(true).write(true))
|
||||
.expect("failed to map trampoline");
|
||||
|
||||
(result, mapper.table().phys().data())
|
||||
};
|
||||
result.flush();
|
||||
|
||||
// Write trampoline, make sure TRAMPOLINE page is free for use
|
||||
for i in 0..TRAMPOLINE_DATA.len() {
|
||||
unsafe {
|
||||
(*((TRAMPOLINE as *mut u8).add(i) as *const AtomicU8))
|
||||
.store(TRAMPOLINE_DATA[i], Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
|
||||
for madt_entry in madt.iter() {
|
||||
println!(" {:?}", madt_entry);
|
||||
match madt_entry {
|
||||
MadtEntry::LocalApic(ap_local_apic) => {
|
||||
if ap_local_apic.id == me {
|
||||
println!(" This is my local APIC");
|
||||
} else {
|
||||
if ap_local_apic.flags & 1 == 1 {
|
||||
// Increase CPU ID
|
||||
CPU_COUNT.fetch_add(1, Ordering::SeqCst);
|
||||
|
||||
// Allocate a stack
|
||||
let stack_start = allocate_p2frame(4)
|
||||
.expect("no more frames in acpi stack_start")
|
||||
.base()
|
||||
.data()
|
||||
+ crate::PHYS_OFFSET;
|
||||
let stack_end = stack_start + (PAGE_SIZE << 4);
|
||||
|
||||
let ap_ready = (TRAMPOLINE + 8) as *mut u64;
|
||||
let ap_cpu_id = unsafe { ap_ready.add(1) };
|
||||
let ap_page_table = unsafe { ap_ready.add(2) };
|
||||
let ap_stack_start = unsafe { ap_ready.add(3) };
|
||||
let ap_stack_end = unsafe { ap_ready.add(4) };
|
||||
let ap_code = unsafe { ap_ready.add(5) };
|
||||
|
||||
// Set the ap_ready to 0, volatile
|
||||
unsafe {
|
||||
ap_ready.write(0);
|
||||
ap_cpu_id.write(ap_local_apic.id.into());
|
||||
ap_page_table.write(page_table_physaddr as u64);
|
||||
ap_stack_start.write(stack_start as u64);
|
||||
ap_stack_end.write(stack_end as u64);
|
||||
ap_code.write(kstart_ap as u64);
|
||||
|
||||
// TODO: Is this necessary (this fence)?
|
||||
core::arch::asm!("");
|
||||
};
|
||||
AP_READY.store(false, Ordering::SeqCst);
|
||||
|
||||
print!(" AP {}:", ap_local_apic.id);
|
||||
|
||||
// Send INIT IPI
|
||||
{
|
||||
let mut icr = 0x4500;
|
||||
if local_apic.x2 {
|
||||
icr |= (ap_local_apic.id as u64) << 32;
|
||||
} else {
|
||||
icr |= (ap_local_apic.id as u64) << 56;
|
||||
}
|
||||
print!(" IPI...");
|
||||
local_apic.set_icr(icr);
|
||||
}
|
||||
|
||||
// Send START IPI
|
||||
{
|
||||
//Start at 0x0800:0000 => 0x8000. Hopefully the bootloader code is still there
|
||||
let ap_segment = (TRAMPOLINE >> 12) & 0xFF;
|
||||
let mut icr = 0x4600 | ap_segment as u64;
|
||||
|
||||
if local_apic.x2 {
|
||||
icr |= (ap_local_apic.id as u64) << 32;
|
||||
} else {
|
||||
icr |= (ap_local_apic.id as u64) << 56;
|
||||
}
|
||||
|
||||
print!(" SIPI...");
|
||||
local_apic.set_icr(icr);
|
||||
}
|
||||
|
||||
// Wait for trampoline ready
|
||||
print!(" Wait...");
|
||||
while unsafe { (*ap_ready.cast::<AtomicU8>()).load(Ordering::SeqCst) }
|
||||
== 0
|
||||
{
|
||||
interrupt::pause();
|
||||
}
|
||||
print!(" Trampoline...");
|
||||
while !AP_READY.load(Ordering::SeqCst) {
|
||||
interrupt::pause();
|
||||
}
|
||||
println!(" Ready");
|
||||
|
||||
unsafe {
|
||||
RmmA::invalidate_all();
|
||||
}
|
||||
} else {
|
||||
println!(" CPU Disabled");
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
// Unmap trampoline
|
||||
let (_frame, _, flush) = unsafe {
|
||||
KernelMapper::lock()
|
||||
.get_mut()
|
||||
.expect("expected kernel page table not to be recursively locked while initializing MADT")
|
||||
.unmap_phys(trampoline_page.start_address(), true)
|
||||
.expect("failed to unmap trampoline page")
|
||||
};
|
||||
flush.flush();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
use core::mem;
|
||||
|
||||
use super::{find_sdt, sdt::Sdt};
|
||||
|
||||
/// The Multiple APIC Descriptor Table
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Madt {
|
||||
sdt: &'static Sdt,
|
||||
pub local_address: u32,
|
||||
pub flags: u32,
|
||||
}
|
||||
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
#[path = "arch/x86.rs"]
|
||||
mod arch;
|
||||
|
||||
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
|
||||
#[path = "arch/other.rs"]
|
||||
mod arch;
|
||||
|
||||
pub static mut MADT: Option<Madt> = None;
|
||||
pub const FLAG_PCAT: u32 = 1;
|
||||
|
||||
impl Madt {
|
||||
pub fn init() {
|
||||
let madt_sdt = find_sdt("APIC");
|
||||
let madt = if madt_sdt.len() == 1 {
|
||||
Madt::new(madt_sdt[0])
|
||||
} else {
|
||||
println!("Unable to find MADT");
|
||||
return;
|
||||
};
|
||||
|
||||
if let Some(madt) = madt {
|
||||
// safe because no APs have been started yet.
|
||||
unsafe { MADT = Some(madt) };
|
||||
|
||||
println!(" APIC: {:>08X}: {}", madt.local_address, madt.flags);
|
||||
|
||||
arch::init(madt);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(sdt: &'static Sdt) -> Option<Madt> {
|
||||
if &sdt.signature == b"APIC" && sdt.data_len() >= 8 {
|
||||
//Not valid if no local address and flags
|
||||
let local_address = unsafe { (sdt.data_address() as *const u32).read_unaligned() };
|
||||
let flags = unsafe {
|
||||
(sdt.data_address() as *const u32)
|
||||
.offset(1)
|
||||
.read_unaligned()
|
||||
};
|
||||
|
||||
Some(Madt {
|
||||
sdt,
|
||||
local_address,
|
||||
flags,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> MadtIter {
|
||||
MadtIter {
|
||||
sdt: self.sdt,
|
||||
i: 8, // Skip local controller address and flags
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// MADT Local APIC
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[repr(C, packed)]
|
||||
pub struct MadtLocalApic {
|
||||
/// Processor ID
|
||||
pub processor: u8,
|
||||
/// Local APIC ID
|
||||
pub id: u8,
|
||||
/// Flags. 1 means that the processor is enabled
|
||||
pub flags: u32,
|
||||
}
|
||||
|
||||
/// MADT I/O APIC
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[repr(C, packed)]
|
||||
pub struct MadtIoApic {
|
||||
/// I/O APIC ID
|
||||
pub id: u8,
|
||||
/// reserved
|
||||
_reserved: u8,
|
||||
/// I/O APIC address
|
||||
pub address: u32,
|
||||
/// Global system interrupt base
|
||||
pub gsi_base: u32,
|
||||
}
|
||||
|
||||
/// MADT Interrupt Source Override
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[repr(C, packed)]
|
||||
pub struct MadtIntSrcOverride {
|
||||
/// Bus Source
|
||||
pub bus_source: u8,
|
||||
/// IRQ Source
|
||||
pub irq_source: u8,
|
||||
/// Global system interrupt base
|
||||
pub gsi_base: u32,
|
||||
/// Flags
|
||||
pub flags: u16,
|
||||
}
|
||||
|
||||
/// MADT Entries
|
||||
#[derive(Debug)]
|
||||
pub enum MadtEntry {
|
||||
LocalApic(&'static MadtLocalApic),
|
||||
InvalidLocalApic(usize),
|
||||
IoApic(&'static MadtIoApic),
|
||||
InvalidIoApic(usize),
|
||||
IntSrcOverride(&'static MadtIntSrcOverride),
|
||||
InvalidIntSrcOverride(usize),
|
||||
Unknown(u8),
|
||||
}
|
||||
|
||||
pub struct MadtIter {
|
||||
sdt: &'static Sdt,
|
||||
i: usize,
|
||||
}
|
||||
|
||||
impl Iterator for MadtIter {
|
||||
type Item = MadtEntry;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.i + 1 < self.sdt.data_len() {
|
||||
let entry_type = unsafe { *(self.sdt.data_address() as *const u8).add(self.i) };
|
||||
let entry_len =
|
||||
unsafe { *(self.sdt.data_address() as *const u8).add(self.i + 1) } as usize;
|
||||
|
||||
if self.i + entry_len <= self.sdt.data_len() {
|
||||
let item = match entry_type {
|
||||
0 => {
|
||||
if entry_len == mem::size_of::<MadtLocalApic>() + 2 {
|
||||
MadtEntry::LocalApic(unsafe {
|
||||
&*((self.sdt.data_address() + self.i + 2) as *const MadtLocalApic)
|
||||
})
|
||||
} else {
|
||||
MadtEntry::InvalidLocalApic(entry_len)
|
||||
}
|
||||
}
|
||||
1 => {
|
||||
if entry_len == mem::size_of::<MadtIoApic>() + 2 {
|
||||
MadtEntry::IoApic(unsafe {
|
||||
&*((self.sdt.data_address() + self.i + 2) as *const MadtIoApic)
|
||||
})
|
||||
} else {
|
||||
MadtEntry::InvalidIoApic(entry_len)
|
||||
}
|
||||
}
|
||||
2 => {
|
||||
if entry_len == mem::size_of::<MadtIntSrcOverride>() + 2 {
|
||||
MadtEntry::IntSrcOverride(unsafe {
|
||||
&*((self.sdt.data_address() + self.i + 2)
|
||||
as *const MadtIntSrcOverride)
|
||||
})
|
||||
} else {
|
||||
MadtEntry::InvalidIntSrcOverride(entry_len)
|
||||
}
|
||||
}
|
||||
_ => MadtEntry::Unknown(entry_type),
|
||||
};
|
||||
|
||||
self.i += entry_len;
|
||||
|
||||
Some(item)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ use spin::MutexGuard;
|
||||
use crate::log::{Log, LOG};
|
||||
|
||||
#[cfg(feature = "serial_debug")]
|
||||
use super::device::serial::{COM1, SerialKind};
|
||||
use super::device::serial::{SerialKind, COM1};
|
||||
#[cfg(feature = "graphical_debug")]
|
||||
use crate::devices::graphical_debug::{DebugDisplay, DEBUG_DISPLAY};
|
||||
|
||||
|
||||
@@ -43,10 +43,7 @@ impl GenericInterruptController {
|
||||
}
|
||||
}
|
||||
pub fn parse(fdt: &Fdt) -> Result<(usize, usize, usize, usize)> {
|
||||
if let Some(node) = fdt.find_compatible(&[
|
||||
"arm,cortex-a15-gic",
|
||||
"arm,gic-400",
|
||||
]) {
|
||||
if let Some(node) = fdt.find_compatible(&["arm,cortex-a15-gic", "arm,gic-400"]) {
|
||||
return GenericInterruptController::parse_inner(&node);
|
||||
} else {
|
||||
return Err(Error::new(EINVAL));
|
||||
|
||||
@@ -16,26 +16,23 @@ impl InterruptHandler for Null {
|
||||
impl InterruptController for Null {
|
||||
fn irq_init(
|
||||
&mut self,
|
||||
fdt: &Fdt,
|
||||
irq_desc: &mut [IrqDesc; 1024],
|
||||
ic_idx: usize,
|
||||
irq_idx: &mut usize,
|
||||
_fdt: &Fdt,
|
||||
_irq_desc: &mut [IrqDesc; 1024],
|
||||
_ic_idx: usize,
|
||||
_irq_idx: &mut usize,
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn irq_ack(&mut self) -> u32 {
|
||||
unimplemented!()
|
||||
}
|
||||
fn irq_eoi(&mut self, irq_num: u32) {
|
||||
}
|
||||
fn irq_enable(&mut self, irq_num: u32) {
|
||||
}
|
||||
fn irq_disable(&mut self, irq_num: u32) {
|
||||
}
|
||||
fn irq_xlate(&self, irq_data: &[u32; 3]) -> Result<usize> {
|
||||
fn irq_eoi(&mut self, _irq_num: u32) {}
|
||||
fn irq_enable(&mut self, _irq_num: u32) {}
|
||||
fn irq_disable(&mut self, _irq_num: u32) {}
|
||||
fn irq_xlate(&self, _irq_data: &[u32; 3]) -> Result<usize> {
|
||||
Err(Error::new(EINVAL))
|
||||
}
|
||||
fn irq_to_virq(&self, hwirq: u32) -> Option<usize> {
|
||||
fn irq_to_virq(&self, _hwirq: u32) -> Option<usize> {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use alloc::boxed::Box;
|
||||
use spin::Mutex;
|
||||
|
||||
|
||||
use crate::{
|
||||
arch::device::irqchip::ic_for_chip,
|
||||
device::uart_pl011,
|
||||
@@ -28,8 +27,8 @@ impl SerialKind {
|
||||
pub fn enable_irq(&mut self) {
|
||||
//TODO: implement for NS16550
|
||||
match self {
|
||||
Self::Ns16550u8(_) => {},
|
||||
Self::Ns16550u32(_) => {},
|
||||
Self::Ns16550u8(_) => {}
|
||||
Self::Ns16550u32(_) => {}
|
||||
Self::Pl011(inner) => inner.enable_irq(),
|
||||
}
|
||||
}
|
||||
@@ -42,13 +41,13 @@ impl SerialKind {
|
||||
debug_input(c);
|
||||
}
|
||||
debug_notify();
|
||||
},
|
||||
}
|
||||
Self::Ns16550u32(inner) => {
|
||||
while let Some(c) = inner.receive() {
|
||||
debug_input(c);
|
||||
}
|
||||
debug_notify();
|
||||
},
|
||||
}
|
||||
Self::Pl011(inner) => inner.receive(),
|
||||
}
|
||||
}
|
||||
@@ -105,9 +104,14 @@ pub unsafe fn init_early(dtb: &Fdt) {
|
||||
Some(serial) => {
|
||||
info!("UART {:?} at {:#X} size {:#X}", compatible, virt, size);
|
||||
*COM1.lock() = Some(serial);
|
||||
},
|
||||
}
|
||||
None => {
|
||||
log::warn!("UART {:?} at {:#X} size {:#X}: no driver found", compatible, virt, size);
|
||||
log::warn!(
|
||||
"UART {:?} at {:#X} size {:#X}: no driver found",
|
||||
compatible,
|
||||
virt,
|
||||
size
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,3 +78,12 @@ impl Iterator for PageIter {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Round down to the nearest multiple of page size
|
||||
pub fn round_down_pages(number: usize) -> usize {
|
||||
number - number % PAGE_SIZE
|
||||
}
|
||||
/// Round up to the nearest multiple of page size
|
||||
pub fn round_up_pages(number: usize) -> usize {
|
||||
round_down_pages(number + PAGE_SIZE - 1)
|
||||
}
|
||||
|
||||
+1
-1
@@ -90,7 +90,7 @@ use crate::arch::*;
|
||||
mod allocator;
|
||||
|
||||
/// ACPI table parsing
|
||||
#[cfg(all(feature = "acpi", any(target_arch = "x86", target_arch = "x86_64")))]
|
||||
#[cfg(feature = "acpi")]
|
||||
#[allow(dead_code)] // TODO
|
||||
mod acpi;
|
||||
|
||||
|
||||
+1
-2
@@ -8,7 +8,6 @@ use core::{
|
||||
};
|
||||
|
||||
use alloc::{collections::BTreeMap, string::String, vec::Vec};
|
||||
use log::{debug, info};
|
||||
|
||||
use spin::{Mutex, Once, RwLock};
|
||||
use syscall::dirent::{DirEntry, DirentBuf, DirentKind};
|
||||
@@ -187,7 +186,7 @@ impl IrqScheme {
|
||||
let irq_number = IRQ_CHIP
|
||||
.irq_xlate(ic_idx, &addr)
|
||||
.or(Err(Error::new(ENOENT)))?;
|
||||
debug!("open_phandle_irq virq={}", irq_number);
|
||||
log::debug!("open_phandle_irq virq={}", irq_number);
|
||||
if flags & O_STAT == 0 {
|
||||
if is_reserved(LogicalCpuId::new(0), irq_number as u8) {
|
||||
return Err(Error::new(EEXIST));
|
||||
|
||||
Reference in New Issue
Block a user