Changes to allow for detection and init of ASPs
This commit is contained in:
parent
7b2acdd79c
commit
08900d56c8
2
Makefile
2
Makefile
|
@ -10,7 +10,7 @@ bochs: build/harddrive.bin
|
||||||
bochs -f bochs.$(ARCH)
|
bochs -f bochs.$(ARCH)
|
||||||
|
|
||||||
qemu: build/harddrive.bin
|
qemu: build/harddrive.bin
|
||||||
qemu-system-$(ARCH) -enable-kvm -cpu host -machine q35 \
|
qemu-system-$(ARCH) -enable-kvm -cpu host -smp 4 -machine q35 \
|
||||||
-serial mon:stdio -drive file=$<,format=raw,index=0,media=disk \
|
-serial mon:stdio -drive file=$<,format=raw,index=0,media=disk \
|
||||||
-nographic -d guest_errors
|
-nographic -d guest_errors
|
||||||
#-device intel-iommu
|
#-device intel-iommu
|
||||||
|
|
51
arch/x86_64/src/acpi/local_apic.rs
Normal file
51
arch/x86_64/src/acpi/local_apic.rs
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
use x86::msr::*;
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
pub flags LocalApicIcr: u64 {
|
||||||
|
const ICR_VECTOR = 0xFF,
|
||||||
|
|
||||||
|
const ICR_FIXED = 0b000 << 8,
|
||||||
|
const ICR_SMI = 0b010 << 8,
|
||||||
|
const ICR_NMI = 0b100 << 8,
|
||||||
|
const ICR_INIT = 0b101 << 8,
|
||||||
|
const ICR_START = 0b110 << 8,
|
||||||
|
|
||||||
|
const ICR_PHYSICAL = 0 << 11,
|
||||||
|
const ICR_LOGICAL = 1 << 11,
|
||||||
|
|
||||||
|
const ICR_DEASSERT = 0 << 14,
|
||||||
|
const ICR_ASSERT = 1 << 14,
|
||||||
|
|
||||||
|
const ICR_EDGE = 0 << 15,
|
||||||
|
const ICR_LEVEL = 1 << 15,
|
||||||
|
|
||||||
|
const ICR_DESTINATION = 0b1111 << 56,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Local APIC
|
||||||
|
#[repr(packed)]
|
||||||
|
pub struct LocalApic;
|
||||||
|
|
||||||
|
impl LocalApic {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
unsafe { wrmsr(IA32_APIC_BASE, rdmsr(IA32_APIC_BASE) | 1 << 10) }
|
||||||
|
LocalApic
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn id(&self) -> u32 {
|
||||||
|
unsafe { rdmsr(IA32_X2APIC_APICID) as u32 }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn version(&self) -> u32 {
|
||||||
|
unsafe { rdmsr(IA32_X2APIC_VERSION) as u32 }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn icr(&self) -> u64 {
|
||||||
|
unsafe { rdmsr(IA32_X2APIC_ICR) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_icr(&mut self, value: u64) {
|
||||||
|
unsafe { wrmsr(IA32_X2APIC_ICR, value) }
|
||||||
|
}
|
||||||
|
}
|
133
arch/x86_64/src/acpi/madt.rs
Normal file
133
arch/x86_64/src/acpi/madt.rs
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
use core::mem;
|
||||||
|
|
||||||
|
use super::sdt::Sdt;
|
||||||
|
|
||||||
|
/// The Multiple APIC Descriptor Table
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Madt {
|
||||||
|
sdt: &'static Sdt,
|
||||||
|
pub local_address: u32,
|
||||||
|
pub flags: u32
|
||||||
|
}
|
||||||
|
|
||||||
|
impl 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) };
|
||||||
|
let flags = unsafe { *(sdt.data_address() as *const u32).offset(1) };
|
||||||
|
|
||||||
|
Some(Madt {
|
||||||
|
sdt: sdt,
|
||||||
|
local_address: local_address,
|
||||||
|
flags: flags
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter(&self) -> MadtIter {
|
||||||
|
MadtIter {
|
||||||
|
sdt: self.sdt,
|
||||||
|
i: 8 // Skip local controller address and flags
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
/// MADT Local APIC
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[repr(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(Debug)]
|
||||||
|
#[repr(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(Debug)]
|
||||||
|
#[repr(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
|
||||||
|
}
|
||||||
|
|
||||||
|
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).offset(self.i as isize) };
|
||||||
|
let entry_len = unsafe { *(self.sdt.data_address() as *const u8).offset(self.i as isize + 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
|
||||||
|
};
|
||||||
|
|
||||||
|
self.i += entry_len;
|
||||||
|
|
||||||
|
Some(item)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,18 +4,74 @@
|
||||||
use memory::{Frame, FrameAllocator};
|
use memory::{Frame, FrameAllocator};
|
||||||
use paging::{entry, ActivePageTable, Page, PhysicalAddress, VirtualAddress};
|
use paging::{entry, ActivePageTable, Page, PhysicalAddress, VirtualAddress};
|
||||||
|
|
||||||
use self::rsdt::RSDT;
|
use self::local_apic::{LocalApic, LocalApicIcr};
|
||||||
use self::sdt::SDT;
|
use self::madt::{Madt, MadtEntry};
|
||||||
use self::xsdt::XSDT;
|
use self::rsdt::Rsdt;
|
||||||
|
use self::sdt::Sdt;
|
||||||
|
use self::xsdt::Xsdt;
|
||||||
|
|
||||||
|
pub mod local_apic;
|
||||||
|
pub mod madt;
|
||||||
pub mod rsdt;
|
pub mod rsdt;
|
||||||
pub mod sdt;
|
pub mod sdt;
|
||||||
pub mod xsdt;
|
pub mod xsdt;
|
||||||
|
|
||||||
|
pub fn init_sdt(sdt: &'static Sdt) {
|
||||||
|
print!(" ");
|
||||||
|
for &c in sdt.signature.iter() {
|
||||||
|
print!("{}", c as char);
|
||||||
|
}
|
||||||
|
println!(":");
|
||||||
|
|
||||||
|
if let Some(madt) = Madt::new(sdt) {
|
||||||
|
println!(" {:>016X}: {}", madt.local_address, madt.flags);
|
||||||
|
|
||||||
|
let mut local_apic = LocalApic::new();
|
||||||
|
|
||||||
|
let me = local_apic.id() as u8;
|
||||||
|
|
||||||
|
for madt_entry in madt.iter() {
|
||||||
|
println!(" {:?}", madt_entry);
|
||||||
|
match madt_entry {
|
||||||
|
MadtEntry::LocalApic(asp_local_apic) => if asp_local_apic.id == me {
|
||||||
|
println!(" This is my local APIC");
|
||||||
|
} else {
|
||||||
|
if asp_local_apic.flags & 1 == 1 {
|
||||||
|
{
|
||||||
|
let icr = 0x00004500 | (asp_local_apic.id as u64) << 32;
|
||||||
|
println!(" Sending IPI to {}: {:>016X} {:?}", asp_local_apic.id, icr, LocalApicIcr::from_bits(icr));
|
||||||
|
local_apic.set_icr(icr);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let icr = 0x00004600 | (asp_local_apic.id as u64) << 32;
|
||||||
|
println!(" Sending SIPI to {}: {:>016X} {:?}", asp_local_apic.id, icr, LocalApicIcr::from_bits(icr));
|
||||||
|
local_apic.set_icr(icr);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println!(" CPU Disabled");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
println!(" {:?}", sdt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Parse the ACPI tables to gather CPU, interrupt, and timer information
|
/// Parse the ACPI tables to gather CPU, interrupt, and timer information
|
||||||
pub unsafe fn init<A>(allocator: &mut A, active_table: &mut ActivePageTable) -> Option<Acpi>
|
pub unsafe fn init<A>(allocator: &mut A, active_table: &mut ActivePageTable) -> Option<Acpi>
|
||||||
where A: FrameAllocator
|
where A: FrameAllocator
|
||||||
{
|
{
|
||||||
|
// Stupidity of enormous proportion. Write the halt opcode to the 0'th physical address
|
||||||
|
// so that START IPI's can halt the processor
|
||||||
|
{
|
||||||
|
if active_table.translate_page(Page::containing_address(VirtualAddress::new(0))).is_none() {
|
||||||
|
active_table.identity_map(Frame::containing_address(PhysicalAddress::new(0)), entry::PRESENT | entry::WRITABLE, allocator);
|
||||||
|
}
|
||||||
|
unsafe { *(0 as *mut u8) = 0xF4 };
|
||||||
|
}
|
||||||
|
|
||||||
let start_addr = 0xE0000;
|
let start_addr = 0xE0000;
|
||||||
let end_addr = 0xFFFFF;
|
let end_addr = 0xFFFFF;
|
||||||
|
|
||||||
|
@ -34,12 +90,12 @@ pub unsafe fn init<A>(allocator: &mut A, active_table: &mut ActivePageTable) ->
|
||||||
if let Some(rsdp) = RSDP::search(start_addr, end_addr) {
|
if let Some(rsdp) = RSDP::search(start_addr, end_addr) {
|
||||||
println!("{:?}", rsdp);
|
println!("{:?}", rsdp);
|
||||||
|
|
||||||
let mut get_sdt = |sdt_address: usize| -> &'static SDT {
|
let mut get_sdt = |sdt_address: usize| -> &'static Sdt {
|
||||||
if active_table.translate_page(Page::containing_address(VirtualAddress::new(sdt_address))).is_none() {
|
if active_table.translate_page(Page::containing_address(VirtualAddress::new(sdt_address))).is_none() {
|
||||||
let sdt_frame = Frame::containing_address(PhysicalAddress::new(sdt_address));
|
let sdt_frame = Frame::containing_address(PhysicalAddress::new(sdt_address));
|
||||||
active_table.identity_map(sdt_frame, entry::PRESENT | entry::NO_EXECUTE, allocator);
|
active_table.identity_map(sdt_frame, entry::PRESENT | entry::NO_EXECUTE, allocator);
|
||||||
}
|
}
|
||||||
unsafe { &*(sdt_address as *const SDT) }
|
&*(sdt_address as *const Sdt)
|
||||||
};
|
};
|
||||||
|
|
||||||
let rxsdt = get_sdt(rsdp.sdt_address());
|
let rxsdt = get_sdt(rsdp.sdt_address());
|
||||||
|
@ -48,25 +104,13 @@ pub unsafe fn init<A>(allocator: &mut A, active_table: &mut ActivePageTable) ->
|
||||||
print!("{}", c as char);
|
print!("{}", c as char);
|
||||||
}
|
}
|
||||||
println!(":");
|
println!(":");
|
||||||
if let Some(rsdt) = RSDT::new(rxsdt) {
|
if let Some(rsdt) = Rsdt::new(rxsdt) {
|
||||||
println!("{:?}", rsdt);
|
|
||||||
for sdt_address in rsdt.iter() {
|
for sdt_address in rsdt.iter() {
|
||||||
let sdt = get_sdt(sdt_address);
|
init_sdt(get_sdt(sdt_address));
|
||||||
for &c in sdt.signature.iter() {
|
|
||||||
print!("{}", c as char);
|
|
||||||
}
|
}
|
||||||
println!(":");
|
} else if let Some(xsdt) = Xsdt::new(rxsdt) {
|
||||||
println!("{:?}", sdt);
|
|
||||||
}
|
|
||||||
} else if let Some(xsdt) = XSDT::new(rxsdt) {
|
|
||||||
println!("{:?}", xsdt);
|
|
||||||
for sdt_address in xsdt.iter() {
|
for sdt_address in xsdt.iter() {
|
||||||
let sdt = get_sdt(sdt_address);
|
init_sdt(get_sdt(sdt_address));
|
||||||
for &c in sdt.signature.iter() {
|
|
||||||
print!("{}", c as char);
|
|
||||||
}
|
|
||||||
println!(":");
|
|
||||||
println!("{:?}", sdt);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
println!("UNKNOWN RSDT OR XSDT SIGNATURE");
|
println!("UNKNOWN RSDT OR XSDT SIGNATURE");
|
||||||
|
@ -99,7 +143,7 @@ impl RSDP {
|
||||||
/// Search for the RSDP
|
/// Search for the RSDP
|
||||||
pub fn search(start_addr: usize, end_addr: usize) -> Option<RSDP> {
|
pub fn search(start_addr: usize, end_addr: usize) -> Option<RSDP> {
|
||||||
for i in 0 .. (end_addr + 1 - start_addr)/16 {
|
for i in 0 .. (end_addr + 1 - start_addr)/16 {
|
||||||
let mut rsdp = unsafe { &*((start_addr + i * 16) as *const RSDP) };
|
let rsdp = unsafe { &*((start_addr + i * 16) as *const RSDP) };
|
||||||
if &rsdp.signature == b"RSD PTR " {
|
if &rsdp.signature == b"RSD PTR " {
|
||||||
return Some(*rsdp);
|
return Some(*rsdp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,33 +1,33 @@
|
||||||
use core::mem;
|
use core::mem;
|
||||||
|
|
||||||
use super::sdt::SDT;
|
use super::sdt::Sdt;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct RSDT(&'static SDT);
|
pub struct Rsdt(&'static Sdt);
|
||||||
|
|
||||||
impl RSDT {
|
impl Rsdt {
|
||||||
pub fn new(sdt: &'static SDT) -> Option<RSDT> {
|
pub fn new(sdt: &'static Sdt) -> Option<Rsdt> {
|
||||||
if &sdt.signature == b"RSDT" {
|
if &sdt.signature == b"RSDT" {
|
||||||
Some(RSDT(sdt))
|
Some(Rsdt(sdt))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter(&self) -> RSDTIter {
|
pub fn iter(&self) -> RsdtIter {
|
||||||
RSDTIter {
|
RsdtIter {
|
||||||
sdt: self.0,
|
sdt: self.0,
|
||||||
i: 0
|
i: 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct RSDTIter {
|
pub struct RsdtIter {
|
||||||
sdt: &'static SDT,
|
sdt: &'static Sdt,
|
||||||
i: usize
|
i: usize
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Iterator for RSDTIter {
|
impl Iterator for RsdtIter {
|
||||||
type Item = usize;
|
type Item = usize;
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
if self.i < self.sdt.data_len()/mem::size_of::<u32>() {
|
if self.i < self.sdt.data_len()/mem::size_of::<u32>() {
|
||||||
|
|
|
@ -2,7 +2,7 @@ use core::mem;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
#[repr(packed)]
|
#[repr(packed)]
|
||||||
pub struct SDT {
|
pub struct Sdt {
|
||||||
pub signature: [u8; 4],
|
pub signature: [u8; 4],
|
||||||
pub length: u32,
|
pub length: u32,
|
||||||
pub revision: u8,
|
pub revision: u8,
|
||||||
|
@ -14,16 +14,16 @@ pub struct SDT {
|
||||||
pub creator_revision: u32
|
pub creator_revision: u32
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SDT {
|
impl Sdt {
|
||||||
/// Get the address of this tables data
|
/// Get the address of this tables data
|
||||||
pub fn data_address(&'static self) -> usize {
|
pub fn data_address(&'static self) -> usize {
|
||||||
self as *const _ as usize + mem::size_of::<SDT>()
|
self as *const _ as usize + mem::size_of::<Sdt>()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the length of this tables data
|
/// Get the length of this tables data
|
||||||
pub fn data_len(&'static self) -> usize {
|
pub fn data_len(&'static self) -> usize {
|
||||||
let total_size = self.length as usize;
|
let total_size = self.length as usize;
|
||||||
let header_size = mem::size_of::<SDT>();
|
let header_size = mem::size_of::<Sdt>();
|
||||||
if total_size >= header_size {
|
if total_size >= header_size {
|
||||||
total_size - header_size
|
total_size - header_size
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,33 +1,33 @@
|
||||||
use core::mem;
|
use core::mem;
|
||||||
|
|
||||||
use super::sdt::SDT;
|
use super::sdt::Sdt;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct XSDT(&'static SDT);
|
pub struct Xsdt(&'static Sdt);
|
||||||
|
|
||||||
impl XSDT {
|
impl Xsdt {
|
||||||
pub fn new(sdt: &'static SDT) -> Option<XSDT> {
|
pub fn new(sdt: &'static Sdt) -> Option<Xsdt> {
|
||||||
if &sdt.signature == b"XSDT" {
|
if &sdt.signature == b"XSDT" {
|
||||||
Some(XSDT(sdt))
|
Some(Xsdt(sdt))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter(&self) -> XSDTIter {
|
pub fn iter(&self) -> XsdtIter {
|
||||||
XSDTIter {
|
XsdtIter {
|
||||||
sdt: self.0,
|
sdt: self.0,
|
||||||
i: 0
|
i: 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct XSDTIter {
|
pub struct XsdtIter {
|
||||||
sdt: &'static SDT,
|
sdt: &'static Sdt,
|
||||||
i: usize
|
i: usize
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Iterator for XSDTIter {
|
impl Iterator for XsdtIter {
|
||||||
type Item = usize;
|
type Item = usize;
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
if self.i < self.sdt.data_len()/mem::size_of::<u64>() {
|
if self.i < self.sdt.data_len()/mem::size_of::<u64>() {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use core::mem;
|
use core::mem;
|
||||||
|
|
||||||
|
use interrupt::halt;
|
||||||
|
|
||||||
pub static mut IDTR: IdtDescriptor = IdtDescriptor {
|
pub static mut IDTR: IdtDescriptor = IdtDescriptor {
|
||||||
size: 0,
|
size: 0,
|
||||||
offset: 0
|
offset: 0
|
||||||
|
@ -12,6 +14,8 @@ pub unsafe fn init() {
|
||||||
entry.set_flags(IDT_PRESENT | IDT_RING_0 | IDT_INTERRUPT);
|
entry.set_flags(IDT_PRESENT | IDT_RING_0 | IDT_INTERRUPT);
|
||||||
entry.set_offset(8, exception as usize);
|
entry.set_offset(8, exception as usize);
|
||||||
}
|
}
|
||||||
|
IDT[13].set_offset(8, protection_fault as usize);
|
||||||
|
IDT[14].set_offset(8, page_fault as usize);
|
||||||
for entry in IDT[32..].iter_mut() {
|
for entry in IDT[32..].iter_mut() {
|
||||||
entry.set_flags(IDT_PRESENT | IDT_RING_0 | IDT_INTERRUPT);
|
entry.set_flags(IDT_PRESENT | IDT_RING_0 | IDT_INTERRUPT);
|
||||||
entry.set_offset(8, blank as usize);
|
entry.set_offset(8, blank as usize);
|
||||||
|
@ -26,7 +30,24 @@ interrupt!(blank, {
|
||||||
});
|
});
|
||||||
|
|
||||||
interrupt!(exception, {
|
interrupt!(exception, {
|
||||||
panic!("EXCEPTION");
|
println!("EXCEPTION");
|
||||||
|
loop {
|
||||||
|
halt();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
interrupt_error!(protection_fault, {
|
||||||
|
println!("PROTECTION FAULT");
|
||||||
|
loop {
|
||||||
|
halt();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
interrupt_error!(page_fault, {
|
||||||
|
println!("PAGE FAULT");
|
||||||
|
loop {
|
||||||
|
halt();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
|
|
|
@ -39,6 +39,7 @@ macro_rules! interrupt {
|
||||||
($name:ident, $func:block) => {
|
($name:ident, $func:block) => {
|
||||||
#[naked]
|
#[naked]
|
||||||
pub unsafe extern fn $name () {
|
pub unsafe extern fn $name () {
|
||||||
|
#[inline(never)]
|
||||||
unsafe fn inner() {
|
unsafe fn inner() {
|
||||||
$func
|
$func
|
||||||
}
|
}
|
||||||
|
@ -76,6 +77,51 @@ macro_rules! interrupt {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! interrupt_error {
|
||||||
|
($name:ident, $func:block) => {
|
||||||
|
#[naked]
|
||||||
|
pub unsafe extern fn $name () {
|
||||||
|
#[inline(never)]
|
||||||
|
unsafe fn inner() {
|
||||||
|
$func
|
||||||
|
}
|
||||||
|
|
||||||
|
asm!("xchg bx, bx" : : : : "intel", "volatile");
|
||||||
|
|
||||||
|
// Push scratch registers, grab stack pointer
|
||||||
|
asm!("push rax
|
||||||
|
push rcx
|
||||||
|
push rdx
|
||||||
|
push rdi
|
||||||
|
push rsi
|
||||||
|
push r8
|
||||||
|
push r9
|
||||||
|
push r10
|
||||||
|
push r11"
|
||||||
|
: : : : "intel", "volatile");
|
||||||
|
|
||||||
|
|
||||||
|
// Call inner rust function
|
||||||
|
inner();
|
||||||
|
|
||||||
|
// Pop scratch registers, error code, and return
|
||||||
|
asm!("pop r11
|
||||||
|
pop r10
|
||||||
|
pop r9
|
||||||
|
pop r8
|
||||||
|
pop rsi
|
||||||
|
pop rdi
|
||||||
|
pop rdx
|
||||||
|
pop rcx
|
||||||
|
pop rax
|
||||||
|
add rsp, 8
|
||||||
|
iretq"
|
||||||
|
: : : : "intel", "volatile");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// ACPI table parsing
|
/// ACPI table parsing
|
||||||
pub mod acpi;
|
pub mod acpi;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue