Skip to content
Snippets Groups Projects
Commit f0b5d517 authored by Jacob Lorentzon's avatar Jacob Lorentzon :speech_balloon:
Browse files

Use the I/O APIC when applicable.

parent da6de394
No related branches found
No related tags found
1 merge request!117Support the I/O APIC alongside the 8259 PIC
...@@ -15,13 +15,16 @@ use crate::interrupt; ...@@ -15,13 +15,16 @@ use crate::interrupt;
use crate::start::{kstart_ap, CPU_COUNT, AP_READY}; use crate::start::{kstart_ap, CPU_COUNT, AP_READY};
/// The Multiple APIC Descriptor Table /// The Multiple APIC Descriptor Table
#[derive(Debug)] #[derive(Clone, Copy, Debug)]
pub struct Madt { pub struct Madt {
sdt: &'static Sdt, sdt: &'static Sdt,
pub local_address: u32, pub local_address: u32,
pub flags: u32 pub flags: u32
} }
pub static mut MADT: Option<Madt> = None;
pub const FLAG_PCAT: u32 = 1;
impl Madt { impl Madt {
pub fn init(active_table: &mut ActivePageTable) { pub fn init(active_table: &mut ActivePageTable) {
let madt_sdt = find_sdt("APIC"); let madt_sdt = find_sdt("APIC");
...@@ -34,6 +37,9 @@ impl Madt { ...@@ -34,6 +37,9 @@ impl Madt {
}; };
if let Some(madt) = madt { 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); println!(" APIC: {:>08X}: {}", madt.local_address, madt.flags);
let local_apic = unsafe { &mut LOCAL_APIC }; let local_apic = unsafe { &mut LOCAL_APIC };
......
...@@ -31,7 +31,7 @@ use self::aml::{parse_aml_table, AmlError, AmlValue}; ...@@ -31,7 +31,7 @@ use self::aml::{parse_aml_table, AmlError, AmlValue};
pub mod hpet; pub mod hpet;
mod dmar; mod dmar;
mod fadt; mod fadt;
mod madt; pub mod madt;
mod rsdt; mod rsdt;
mod sdt; mod sdt;
mod xsdt; mod xsdt;
......
use core::convert::TryFrom; use core::convert::TryFrom;
use core::mem;
use crate::memory::Frame; use crate::memory::Frame;
use crate::paging::{ActivePageTable, Page, PhysicalAddress, VirtualAddress}; use crate::paging::{ActivePageTable, Page, PhysicalAddress, VirtualAddress};
...@@ -36,10 +37,17 @@ impl RSDP { ...@@ -36,10 +37,17 @@ impl RSDP {
type Item = &'a [u8]; type Item = &'a [u8];
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
let length = <[u8; 4]>::try_from(&self.buf[..4]).ok()?; if self.buf.len() < 4 { return None }
let length_bytes = <[u8; 4]>::try_from(&self.buf[..4]).ok()?;
let length = u32::from_ne_bytes(length_bytes) as usize;
if (4 + length as usize) > self.buf.len() { return None } if (4 + length as usize) > self.buf.len() { return None }
self.buf = self.buf[4 + length..];
Ok(length) let buf = &self.buf[4..4 + length];
self.buf = &self.buf[4 + length..];
Some(buf)
} }
} }
fn slice_to_rsdp(slice: &[u8]) -> Option<&RSDP> { fn slice_to_rsdp(slice: &[u8]) -> Option<&RSDP> {
...@@ -52,20 +60,22 @@ impl RSDP { ...@@ -52,20 +60,22 @@ impl RSDP {
} else { None } } else { None }
} }
// first, find an RDSP for ACPI 2.0 // first, find an RSDP for ACPI 2.0
if let Some(rdsp_2_0) = Iter { buf: area }.filter_map(slice_to_rsdp).filter(|rsdp| rsdp.is_acpi_2_0()) { if let Some(rsdp_2_0) = (Iter { buf: area }.filter_map(slice_to_rsdp).find(|rsdp| rsdp.is_acpi_2_0())) {
return Some(rsdp_2_0); return Some(*rsdp_2_0);
} }
// secondly, find an RDSP for ACPI 1.0 // secondly, find an RSDP for ACPI 1.0
if let Some(rdsp_1_0) = Iter { buf: area }.filter_map(slice_to_rsdp).filter(|rsdp| rsdp.is_acpi_1_0()) { if let Some(rsdp_1_0) = (Iter { buf: area }.filter_map(slice_to_rsdp).find(|rsdp| rsdp.is_acpi_1_0())) {
return Some(rsdp_1_0); return Some(*rsdp_1_0);
} }
None
} }
pub fn get_rsdp(active_table: &mut ActivePageTable, already_supplied_rsdps: Option<(u64, u64)>) -> Option<RSDP> { pub fn get_rsdp(active_table: &mut ActivePageTable, already_supplied_rsdps: Option<(u64, u64)>) -> Option<RSDP> {
if let Some((base, size)) = already_supplied_rsdps { if let Some((base, size)) = already_supplied_rsdps {
let area = core::slice::from_raw_parts(base as usize as *const u8, size as usize); let area = unsafe { core::slice::from_raw_parts(base as usize as *const u8, size as usize) };
Self::get_already_supplied_rsdps(area) Self::get_already_supplied_rsdps(area).or_else(|| Self::get_rsdp_by_searching(active_table))
} else { } else {
Self::get_rsdp_by_searching(active_table) Self::get_rsdp_by_searching(active_table)
} }
......
use core::{fmt, ptr};
use alloc::vec::Vec;
use spin::Mutex;
#[cfg(feature = "acpi")]
use crate::acpi::madt::{self, Madt, MadtEntry, MadtIoApic, MadtIntSrcOverride};
use crate::arch::interrupt::irq;
use crate::memory::Frame;
use crate::paging::{ActivePageTable, entry::EntryFlags, Page, PhysicalAddress, VirtualAddress};
use crate::syscall::io::Mmio;
use super::pic;
pub struct IoApicRegs {
pointer: *const u32,
}
impl IoApicRegs {
fn ioregsel(&self) -> *const u32 {
self.pointer
}
fn iowin(&self) -> *const u32 {
// offset 0x10
unsafe { self.pointer.offset(4) }
}
fn read_ioregsel(&self) -> u32 {
unsafe { ptr::read_volatile::<u32>(self.ioregsel()) }
}
fn write_ioregsel(&mut self, value: u32) {
unsafe { ptr::write_volatile::<u32>(self.ioregsel() as *mut u32, value) }
}
fn read_iowin(&self) -> u32 {
unsafe { ptr::read_volatile::<u32>(self.iowin()) }
}
fn write_iowin(&mut self, value: u32) {
unsafe { ptr::write_volatile::<u32>(self.iowin() as *mut u32, value) }
}
fn read_reg(&mut self, reg: u8) -> u32 {
self.write_ioregsel(reg.into());
self.read_iowin()
}
fn write_reg(&mut self, reg: u8, value: u32) {
self.write_ioregsel(reg.into());
self.write_iowin(value);
}
pub fn read_ioapicid(&mut self) -> u32 {
self.read_reg(0x00)
}
pub fn write_ioapicid(&mut self, value: u32) {
self.write_reg(0x00, value);
}
pub fn read_ioapicver(&mut self) -> u32 {
self.read_reg(0x01)
}
pub fn read_ioapicarb(&mut self) -> u32 {
self.read_reg(0x02)
}
pub fn read_ioredtbl(&mut self, idx: u8) -> u64 {
assert!(idx < 24);
let lo = self.read_reg(0x10 + idx * 2);
let hi = self.read_reg(0x10 + idx * 2 + 1);
u64::from(lo) | (u64::from(hi) << 32)
}
pub fn write_ioredtbl(&mut self, idx: u8, value: u64) {
assert!(idx < 24);
let lo = value as u32;
let hi = (value >> 32) as u32;
self.write_reg(0x10 + idx * 2, lo);
self.write_reg(0x10 + idx * 2 + 1, hi);
}
pub fn max_redirection_table_entries(&mut self) -> u8 {
let ver = self.read_ioapicver();
((ver & 0x00FF_0000) >> 16) as u8
}
pub fn id(&mut self) -> u8 {
let id_reg = self.read_ioapicid();
((id_reg & 0x0F00_0000) >> 24) as u8
}
}
pub struct IoApic {
regs: Mutex<IoApicRegs>,
gsi_start: u32,
count: u8,
}
impl IoApic {
pub fn new(regs_base: *const u32, gsi_start: u32) -> Self {
let mut regs = IoApicRegs { pointer: regs_base };
let count = regs.max_redirection_table_entries();
Self {
regs: Mutex::new(regs),
gsi_start,
count,
}
}
/// Map an interrupt vector to a physical local APIC ID of a processor (thus physical mode).
pub fn map(&self, idx: u8, info: MapInfo) {
self.regs.lock().write_ioredtbl(idx, info.as_raw())
}
pub fn set_mask(&self, gsi: u32, mask: bool) {
let idx = (gsi - self.gsi_start) as u8;
let mut guard = self.regs.lock();
let mut reg = guard.read_ioredtbl(idx);
reg &= !(1 << 16);
reg |= u64::from(mask) << 16;
guard.write_ioredtbl(idx, reg);
}
}
#[repr(u8)]
#[derive(Clone, Copy, Debug)]
pub enum ApicTriggerMode {
Edge = 0,
Level = 1,
}
#[repr(u8)]
#[derive(Clone, Copy, Debug)]
pub enum ApicPolarity {
ActiveHigh = 0,
ActiveLow = 1,
}
#[repr(u8)]
#[derive(Clone, Copy, Debug)]
pub enum DestinationMode {
Physical = 0,
Logical = 1,
}
#[repr(u8)]
#[derive(Clone, Copy, Debug)]
pub enum DeliveryMode {
Fixed = 0b000,
LowestPriority = 0b001,
Smi = 0b010,
Nmi = 0b100,
Init = 0b101,
ExtInt = 0b111,
}
#[derive(Clone, Copy, Debug)]
pub struct MapInfo {
pub dest: u8,
pub mask: bool,
pub trigger_mode: ApicTriggerMode,
pub polarity: ApicPolarity,
pub dest_mode: DestinationMode,
pub delivery_mode: DeliveryMode,
pub vector: u8,
}
impl MapInfo {
pub fn as_raw(&self) -> u64 {
assert!(self.vector >= 0x20);
assert!(self.vector <= 0xFE);
// TODO: Check for reserved fields.
(u64::from(self.dest) << 56)
| (u64::from(self.mask) << 16)
| ((self.trigger_mode as u64) << 15)
| ((self.polarity as u64) << 13)
| ((self.dest_mode as u64) << 11)
| ((self.delivery_mode as u64) << 8)
| u64::from(self.vector)
}
}
impl fmt::Debug for IoApic {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
struct RedirTable<'a>(&'a Mutex<IoApicRegs>);
impl<'a> fmt::Debug for RedirTable<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut guard = self.0.lock();
let count = guard.max_redirection_table_entries();
f.debug_list().entries((0..count).map(|i| guard.read_ioredtbl(i))).finish()
}
}
f.debug_struct("IoApic")
.field("redir_table", &RedirTable(&self.regs))
.field("gsi_start", &self.gsi_start)
.field("count", &self.count)
.finish()
}
}
#[derive(Clone, Copy, Debug)]
pub enum TriggerMode {
ConformsToSpecs,
Edge,
Level,
}
#[derive(Clone, Copy, Debug)]
pub enum Polarity {
ConformsToSpecs,
ActiveHigh,
ActiveLow,
}
#[derive(Clone, Copy, Debug)]
pub struct Override {
bus_irq: u8,
gsi: u32,
trigger_mode: TriggerMode,
polarity: Polarity,
}
// static mut because only the AP initializes the I/O Apic, and when that is done, it's solely
// accessed immutably.
static mut IOAPICS: Option<Vec<IoApic>> = None;
// static mut for the same reason as above
static mut SRC_OVERRIDES: Option<Vec<Override>> = None;
pub fn ioapics() -> &'static [IoApic] {
unsafe {
IOAPICS.as_ref().map_or(&[], |vector| &vector[..])
}
}
pub fn src_overrides() -> &'static [Override] {
unsafe {
SRC_OVERRIDES.as_ref().map_or(&[], |vector| &vector[..])
}
}
#[cfg(feature = "acpi")]
pub unsafe fn handle_ioapic(active_table: &mut ActivePageTable, madt_ioapic: &'static MadtIoApic) {
// map the I/O APIC registers
let frame = Frame::containing_address(PhysicalAddress::new(madt_ioapic.address as usize));
let page = Page::containing_address(VirtualAddress::new(madt_ioapic.address as usize + crate::KERNEL_OFFSET));
assert_eq!(active_table.translate_page(page), None);
let result = active_table.map_to(page, frame, EntryFlags::PRESENT | EntryFlags::GLOBAL | EntryFlags::WRITABLE | EntryFlags::NO_CACHE);
result.flush(active_table);
let ioapic_registers = page.start_address().get() as *const u32;
let mut ioapic = IoApic::new(ioapic_registers, madt_ioapic.gsi_base);
assert_eq!(ioapic.regs.lock().id(), madt_ioapic.id, "mismatched ACPI MADT I/O APIC ID, and the ID reported by the I/O APIC");
IOAPICS.get_or_insert_with(Vec::new).push(ioapic);
}
#[cfg(feature = "acpi")]
pub unsafe fn handle_src_override(src_override: &'static MadtIntSrcOverride) {
let flags = src_override.flags;
let polarity_raw = (flags & 0x0003) as u8;
let trigger_mode_raw = ((flags & 0x000C) >> 2) as u8;
let polarity = match polarity_raw {
0b00 => Polarity::ConformsToSpecs,
0b01 => Polarity::ActiveHigh,
0b10 => return, // reserved
0b11 => Polarity::ActiveLow,
_ => unreachable!(),
};
let trigger_mode = match trigger_mode_raw {
0b00 => TriggerMode::ConformsToSpecs,
0b01 => TriggerMode::Edge,
0b10 => return, // reserved
0b11 => TriggerMode::Level,
_ => unreachable!(),
};
let over = Override {
bus_irq: src_override.irq_source,
gsi: src_override.gsi_base,
polarity,
trigger_mode,
};
SRC_OVERRIDES.get_or_insert_with(Vec::new).push(over);
}
pub unsafe fn init(active_table: &mut ActivePageTable) {
let mut bsp_apic_id = x86::cpuid::CpuId::new().get_feature_info().unwrap().initial_local_apic_id(); // TODO
// search the madt for all IOAPICs.
#[cfg(feature = "acpi")]
{
let madt: &'static Madt = match madt::MADT.as_ref() {
Some(m) => m,
// TODO: Parse MP tables too.
None => return,
};
if madt.flags & madt::FLAG_PCAT != 0 {
pic::disable();
}
// find all I/O APICs (usually one).
for entry in madt.iter() {
match entry {
MadtEntry::IoApic(ioapic) => handle_ioapic(active_table, ioapic),
MadtEntry::IntSrcOverride(src_override) => handle_src_override(src_override),
_ => (),
}
}
}
println!("I/O APICs: {:?}, overrides: {:?}", ioapics(), src_overrides());
// map the legacy PC-compatible IRQs (0-15) to 32-47, just like we did with 8259 PIC (if it
// wouldn't have been disabled due to this I/O APIC)
for legacy_irq in 0..=15 {
let (gsi, trigger_mode, polarity) = match get_override(legacy_irq) {
Some(over) => (over.gsi, over.trigger_mode, over.polarity),
None => {
if src_overrides().iter().any(|over| over.gsi == u32::from(legacy_irq) && over.bus_irq != legacy_irq) && !src_overrides().iter().any(|over| over.bus_irq == legacy_irq) {
// there's an IRQ conflict, making this legacy IRQ inaccessible.
continue;
}
(legacy_irq.into(), TriggerMode::ConformsToSpecs, Polarity::ConformsToSpecs)
}
};
let apic = match find_ioapic(gsi) {
Some(ioapic) => ioapic,
None => {
println!("Unable to find a suitable APIC for legacy IRQ {} (GSI {}). It will not be mapped.", legacy_irq, gsi);
continue;
}
};
let redir_tbl_index = (gsi - apic.gsi_start) as u8;
let map_info = MapInfo {
// only send to the BSP
dest: bsp_apic_id,
dest_mode: DestinationMode::Physical,
delivery_mode: DeliveryMode::Fixed,
mask: false,
polarity: match polarity {
Polarity::ActiveHigh => ApicPolarity::ActiveHigh,
Polarity::ActiveLow => ApicPolarity::ActiveLow,
Polarity::ConformsToSpecs => ApicPolarity::ActiveHigh,
},
trigger_mode: match trigger_mode {
TriggerMode::Edge => ApicTriggerMode::Edge,
TriggerMode::Level => ApicTriggerMode::Level,
TriggerMode::ConformsToSpecs => ApicTriggerMode::Edge,
},
vector: 32 + legacy_irq,
};
apic.map(redir_tbl_index, map_info);
}
println!("I/O APICs: {:?}, overrides: {:?}", ioapics(), src_overrides());
irq::set_irq_method(irq::IrqMethod::Apic);
}
fn get_override(irq: u8) -> Option<&'static Override> {
src_overrides().iter().find(|over| over.bus_irq == irq)
}
fn resolve(irq: u8) -> u32 {
get_override(irq).map_or(u32::from(irq), |over| over.gsi)
}
fn find_ioapic(gsi: u32) -> Option<&'static IoApic> {
ioapics().iter().find(|apic| gsi >= apic.gsi_start && gsi < apic.gsi_start + u32::from(apic.count))
}
pub unsafe fn mask(irq: u8) {
let gsi = resolve(irq);
let apic = match find_ioapic(gsi) {
Some(a) => a,
None => return,
};
apic.set_mask(gsi, true);
}
pub unsafe fn unmask(irq: u8) {
let gsi = resolve(irq);
let apic = match find_ioapic(gsi) {
Some(a) => a,
None => return,
};
apic.set_mask(gsi, false);
}
use crate::paging::ActivePageTable; use crate::paging::ActivePageTable;
pub mod cpu; pub mod cpu;
pub mod ioapic;
pub mod local_apic; pub mod local_apic;
pub mod pic; pub mod pic;
pub mod pit; pub mod pit;
...@@ -9,10 +10,14 @@ pub mod serial; ...@@ -9,10 +10,14 @@ pub mod serial;
#[cfg(feature = "acpi")] #[cfg(feature = "acpi")]
pub mod hpet; pub mod hpet;
pub unsafe fn init(active_table: &mut ActivePageTable){ pub unsafe fn init(active_table: &mut ActivePageTable) {
pic::init(); pic::init();
local_apic::init(active_table); local_apic::init(active_table);
} }
pub unsafe fn init_after_acpi(active_table: &mut ActivePageTable) {
// this will disable the IOAPIC if needed.
ioapic::init(active_table);
}
#[cfg(feature = "acpi")] #[cfg(feature = "acpi")]
unsafe fn init_hpet() -> bool { unsafe fn init_hpet() -> bool {
......
use crate::syscall::io::{Io, Pio}; use crate::syscall::io::{Io, Pio};
use crate::arch::interrupt::irq;
pub static mut MASTER: Pic = Pic::new(0x20); pub static mut MASTER: Pic = Pic::new(0x20);
pub static mut SLAVE: Pic = Pic::new(0xA0); pub static mut SLAVE: Pic = Pic::new(0xA0);
...@@ -27,6 +28,14 @@ pub unsafe fn init() { ...@@ -27,6 +28,14 @@ pub unsafe fn init() {
// Ack remaining interrupts // Ack remaining interrupts
MASTER.ack(); MASTER.ack();
SLAVE.ack(); SLAVE.ack();
// probably already set to PIC, but double-check
irq::set_irq_method(irq::IrqMethod::Pic);
}
pub unsafe fn disable() {
MASTER.data.write(0xFF);
SLAVE.data.write(0xFF);
} }
pub struct Pic { pub struct Pic {
......
use core::sync::atomic::{AtomicUsize, Ordering}; use core::sync::atomic::{AtomicUsize, Ordering};
use crate::context::timeout; use crate::context::timeout;
use crate::device::{local_apic, pic}; use crate::device::{local_apic, ioapic, pic};
use crate::device::serial::{COM1, COM2}; use crate::device::serial::{COM1, COM2};
use crate::ipi::{ipi, IpiKind, IpiTarget}; use crate::ipi::{ipi, IpiKind, IpiTarget};
use crate::scheme::debug::debug_input; use crate::scheme::debug::debug_input;
...@@ -11,38 +11,99 @@ use crate::{context, ptrace, time}; ...@@ -11,38 +11,99 @@ use crate::{context, ptrace, time};
#[thread_local] #[thread_local]
pub static PIT_TICKS: AtomicUsize = AtomicUsize::new(0); pub static PIT_TICKS: AtomicUsize = AtomicUsize::new(0);
#[repr(u8)]
pub enum IrqMethod {
Pic = 0,
Apic = 1,
}
static IRQ_METHOD: AtomicUsize = AtomicUsize::new(IrqMethod::Pic as usize);
pub fn set_irq_method(method: IrqMethod) {
IRQ_METHOD.store(method as usize, core::sync::atomic::Ordering::Release);
}
fn irq_method() -> IrqMethod {
let raw = IRQ_METHOD.load(core::sync::atomic::Ordering::Acquire);
match raw {
0 => IrqMethod::Pic,
1 => IrqMethod::Apic,
_ => unreachable!(),
}
}
extern { extern {
// triggers irq scheme
fn irq_trigger(irq: u8); fn irq_trigger(irq: u8);
} }
/// Notify the IRQ scheme that an IRQ has been registered. This should mask the IRQ until the
/// scheme user unmasks it ("acknowledges" it).
unsafe fn trigger(irq: u8) { unsafe fn trigger(irq: u8) {
match irq_method() {
IrqMethod::Pic => if irq < 16 { pic_mask(irq) },
IrqMethod::Apic => ioapic_mask(irq),
}
irq_trigger(irq);
}
/// Unmask the IRQ. This is called from the IRQ scheme, which does this when a user process has
/// processed the IRQ.
pub unsafe fn acknowledge(irq: usize) {
match irq_method() {
IrqMethod::Pic => if irq < 16 { pic_unmask(irq) },
IrqMethod::Apic => ioapic_unmask(irq),
}
}
/// Sends an end-of-interrupt, so that the interrupt controller can go on to the next one.
pub unsafe fn eoi(irq: u8) {
match irq_method() {
IrqMethod::Pic => if irq < 16 { pic_eoi(irq) },
IrqMethod::Apic => lapic_eoi(),
}
}
if irq < 16 { unsafe fn pic_mask(irq: u8) {
if irq >= 8 { debug_assert!(irq < 16);
pic::SLAVE.mask_set(irq - 8);
pic::MASTER.ack(); if irq >= 8 {
pic::SLAVE.ack(); pic::SLAVE.mask_set(irq - 8);
} else { } else {
pic::MASTER.mask_set(irq); pic::MASTER.mask_set(irq);
pic::MASTER.ack();
}
} }
}
irq_trigger(irq); unsafe fn ioapic_mask(irq: u8) {
ioapic::mask(irq);
}
unsafe fn pic_eoi(irq: u8) {
debug_assert!(irq < 16);
if irq >= 8 {
pic::MASTER.ack();
pic::SLAVE.ack();
} else {
pic::MASTER.ack();
}
} }
unsafe fn lapic_eoi() { unsafe fn lapic_eoi() {
local_apic::LOCAL_APIC.eoi() local_apic::LOCAL_APIC.eoi()
} }
pub unsafe fn acknowledge(irq: usize) { unsafe fn pic_unmask(irq: usize) {
if irq < 16 { debug_assert!(irq < 16);
if irq >= 8 {
pic::SLAVE.mask_clear(irq as u8 - 8); if irq >= 8 {
} else { pic::SLAVE.mask_clear(irq as u8 - 8);
pic::MASTER.mask_clear(irq as u8); } else {
} pic::MASTER.mask_clear(irq as u8);
} }
} }
unsafe fn ioapic_unmask(irq: usize) {
ioapic::unmask(irq as u8);
}
interrupt_stack!(pit, stack, { interrupt_stack!(pit, stack, {
// Saves CPU time by not sending IRQ event irq_trigger(0); // Saves CPU time by not sending IRQ event irq_trigger(0);
...@@ -56,7 +117,7 @@ interrupt_stack!(pit, stack, { ...@@ -56,7 +117,7 @@ interrupt_stack!(pit, stack, {
offset.0 += sum / 1_000_000_000; offset.0 += sum / 1_000_000_000;
} }
pic::MASTER.ack(); eoi(0);
// Wake up other CPUs // Wake up other CPUs
ipi(IpiKind::Pit, IpiTarget::Other); ipi(IpiKind::Pit, IpiTarget::Other);
...@@ -72,68 +133,80 @@ interrupt_stack!(pit, stack, { ...@@ -72,68 +133,80 @@ interrupt_stack!(pit, stack, {
interrupt!(keyboard, { interrupt!(keyboard, {
trigger(1); trigger(1);
eoi(1);
}); });
interrupt!(cascade, { interrupt!(cascade, {
// No need to do any operations on cascade // No need to do any operations on cascade
pic::MASTER.ack(); eoi(2);
}); });
interrupt!(com2, { interrupt!(com2, {
while let Some(c) = COM2.lock().receive() { while let Some(c) = COM2.lock().receive() {
debug_input(c); debug_input(c);
} }
pic::MASTER.ack(); eoi(3);
}); });
interrupt!(com1, { interrupt!(com1, {
while let Some(c) = COM1.lock().receive() { while let Some(c) = COM1.lock().receive() {
debug_input(c); debug_input(c);
} }
pic::MASTER.ack(); eoi(4);
}); });
interrupt!(lpt2, { interrupt!(lpt2, {
eoi(5);
trigger(5); trigger(5);
}); });
interrupt!(floppy, { interrupt!(floppy, {
eoi(6);
trigger(6); trigger(6);
}); });
interrupt!(lpt1, { interrupt!(lpt1, {
eoi(7);
trigger(7); trigger(7);
}); });
interrupt!(rtc, { interrupt!(rtc, {
eoi(8);
trigger(8); trigger(8);
}); });
interrupt!(pci1, { interrupt!(pci1, {
eoi(9);
trigger(9); trigger(9);
}); });
interrupt!(pci2, { interrupt!(pci2, {
eoi(10);
trigger(10); trigger(10);
}); });
interrupt!(pci3, { interrupt!(pci3, {
eoi(11);
trigger(11); trigger(11);
}); });
interrupt!(mouse, { interrupt!(mouse, {
eoi(12);
trigger(12); trigger(12);
}); });
interrupt!(fpu, { interrupt!(fpu, {
eoi(13);
trigger(13); trigger(13);
}); });
interrupt!(ata1, { interrupt!(ata1, {
eoi(14);
trigger(14); trigger(14);
}); });
interrupt!(ata2, { interrupt!(ata2, {
eoi(15);
trigger(15); trigger(15);
}); });
interrupt!(lapic_timer, { interrupt!(lapic_timer, {
...@@ -154,7 +227,7 @@ interrupt!(calib_pit, { ...@@ -154,7 +227,7 @@ interrupt!(calib_pit, {
offset.0 += sum / 1_000_000_000; offset.0 += sum / 1_000_000_000;
} }
pic::MASTER.ack(); eoi(0);
}); });
// XXX: This would look way prettier using const generics. // XXX: This would look way prettier using const generics.
......
...@@ -176,7 +176,10 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! { ...@@ -176,7 +176,10 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
// Read ACPI tables, starts APs // Read ACPI tables, starts APs
#[cfg(feature = "acpi")] #[cfg(feature = "acpi")]
acpi::init(&mut active_table, extended_kargs.as_ref().map(|kargs| (kargs.acpi_rsdps_base, kargs.acpi_rsdps_size))); {
acpi::init(&mut active_table, extended_kargs.as_ref().map(|kargs| (kargs.acpi_rsdps_base, kargs.acpi_rsdps_size)));
device::init_after_acpi(&mut active_table);
}
// Initialize all of the non-core devices not otherwise needed to complete initialization // Initialize all of the non-core devices not otherwise needed to complete initialization
device::init_noncore(); device::init_noncore();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment