From 661ebb639031819a198ece2744edf98b2bf6ede4 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Sat, 18 Mar 2017 15:12:42 +0000 Subject: [PATCH 1/2] Saved FADT in a pointer accessible elsewhere in the kernel --- arch/x86_64/src/acpi/mod.rs | 44 +++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/arch/x86_64/src/acpi/mod.rs b/arch/x86_64/src/acpi/mod.rs index 092f609..5b235ce 100644 --- a/arch/x86_64/src/acpi/mod.rs +++ b/arch/x86_64/src/acpi/mod.rs @@ -27,7 +27,13 @@ pub mod xsdt; const TRAMPOLINE: usize = 0x7E00; const AP_STARTUP: usize = TRAMPOLINE + 512; -pub fn init_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) { +pub enum AcpiTable { + fadt(Fadt), + madt(Madt), + dmar(Dmar) +} + +pub fn init_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) -> Option { print!(" "); for &c in sdt.signature.iter() { print!("{}", c as char); @@ -35,6 +41,7 @@ pub fn init_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) { if let Some(fadt) = Fadt::new(sdt) { println!(": {:#?}", fadt); + Some(AcpiTable::fadt(fadt)) } else if let Some(madt) = Madt::new(sdt) { println!(": {:>08X}: {}", madt.local_address, madt.flags); @@ -138,6 +145,7 @@ pub fn init_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) { // Unmap trampoline let result = active_table.unmap(trampoline_page); result.flush(active_table); + Some(AcpiTable::madt(madt)) } else if let Some(dmar) = Dmar::new(sdt) { println!(": {}: {}", dmar.addr_width, dmar.flags); @@ -157,8 +165,10 @@ pub fn init_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) { _ => () } } + Some(AcpiTable::dmar(dmar)) } else { println!(": Unknown"); + None } } @@ -167,6 +177,8 @@ pub unsafe fn init(active_table: &mut ActivePageTable) -> Option { let start_addr = 0xE0000; let end_addr = 0xFFFFF; + let mut theFADT: Option = None; + // Map all of the ACPI RSDP space { let start_frame = Frame::containing_address(PhysicalAddress::new(start_addr)); @@ -212,14 +224,26 @@ pub unsafe fn init(active_table: &mut ActivePageTable) -> Option { if let Some(rsdt) = Rsdt::new(rxsdt) { for sdt_address in rsdt.iter() { let (sdt, mapped) = get_sdt(sdt_address, active_table); - init_sdt(sdt, active_table); - drop_sdt(sdt, mapped, active_table); + + // If we find the FADT, rather than drop it, save a copy of the pointer, as this is needed elsewhere. + // TODO: Eventually, save pointers to all tables containing pertinent information to other parts of + // the kernel + match init_sdt(sdt, active_table) { + Some(AcpiTable::fadt(fadt)) => theFADT = Some(fadt), + _ => drop_sdt(sdt, mapped, active_table) + } } } else if let Some(xsdt) = Xsdt::new(rxsdt) { for sdt_address in xsdt.iter() { let (sdt, mapped) = get_sdt(sdt_address, active_table); - init_sdt(sdt, active_table); - drop_sdt(sdt, mapped, active_table); + + // If we find the FADT, rather than drop it, save a copy of the pointer, as this is needed elsewhere. + // TODO: Eventually, save pointers to all tables containing pertinent information to other parts of + // the kernel + match init_sdt(sdt, active_table) { + Some(AcpiTable::fadt(fadt)) => theFADT = Some(fadt), + _ => drop_sdt(sdt, mapped, active_table) + } } } else { println!("UNKNOWN RSDT OR XSDT SIGNATURE"); @@ -241,10 +265,16 @@ pub unsafe fn init(active_table: &mut ActivePageTable) -> Option { } } - None + if let Some(fadt) = theFADT { + Some(Acpi { fadt: fadt }) + } else { + None + } } -pub struct Acpi; +pub struct Acpi { + pub fadt: Fadt +} /// RSDP #[derive(Copy, Clone, Debug)] From f79424aeacc7605f577bd5420abda8b05f9fb079 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Sat, 18 Mar 2017 16:08:45 +0000 Subject: [PATCH 2/2] Fully implemented reading the RTC century counter, and laid out initial infrastructure for ACPI information to be used across the kernel, in the x86_64 architecture. - Implemented a global variable, ACPI_TABLE, behind a mutex, which contains the ACPI information pertinent to the rest of the kernel, currently solely containing a pointer to the FADT. - Split device initialization into two categories - "core" devices, such as the PIC and local APIC, necessary for initializing the rest of the kernel, and "non-core" devices such as serial and RTC, which are to be initialized last. - Checked for the presence of the century register, and consequentially read from, in the RTC code, now factored into the date calculation. The location of the register is pulled from the "century" field in the FADT. - Modified page unmapping in the ACPI code, such that any tables to be stored globally (currently only the FADT) are not unmapped after reading, such that they can be stored in globally accessible pointers without causing page faults. --- arch/x86_64/src/acpi/mod.rs | 12 +++++++----- arch/x86_64/src/device/mod.rs | 3 +++ arch/x86_64/src/device/rtc.rs | 23 +++++++++++++++++++++-- arch/x86_64/src/start.rs | 5 ++++- 4 files changed, 35 insertions(+), 8 deletions(-) diff --git a/arch/x86_64/src/acpi/mod.rs b/arch/x86_64/src/acpi/mod.rs index 5b235ce..b6c05ff 100644 --- a/arch/x86_64/src/acpi/mod.rs +++ b/arch/x86_64/src/acpi/mod.rs @@ -4,6 +4,8 @@ use core::intrinsics::{atomic_load, atomic_store}; use core::sync::atomic::Ordering; +use spin::Mutex; + use device::local_apic::LOCAL_APIC; use interrupt; use memory::{allocate_frames, Frame}; @@ -173,7 +175,7 @@ pub fn init_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) -> Option } /// Parse the ACPI tables to gather CPU, interrupt, and timer information -pub unsafe fn init(active_table: &mut ActivePageTable) -> Option { +pub unsafe fn init(active_table: &mut ActivePageTable) { let start_addr = 0xE0000; let end_addr = 0xFFFFF; @@ -266,16 +268,16 @@ pub unsafe fn init(active_table: &mut ActivePageTable) -> Option { } if let Some(fadt) = theFADT { - Some(Acpi { fadt: fadt }) - } else { - None + ACPI_TABLE.lock().fadt = Some(fadt); } } pub struct Acpi { - pub fadt: Fadt + pub fadt: Option } +pub static ACPI_TABLE: Mutex = Mutex::new(Acpi { fadt: None }); + /// RSDP #[derive(Copy, Clone, Debug)] #[repr(packed)] diff --git a/arch/x86_64/src/device/mod.rs b/arch/x86_64/src/device/mod.rs index 522b2b4..ef27ccb 100644 --- a/arch/x86_64/src/device/mod.rs +++ b/arch/x86_64/src/device/mod.rs @@ -9,6 +9,9 @@ pub mod serial; pub unsafe fn init(active_table: &mut ActivePageTable){ pic::init(); local_apic::init(active_table); +} + +pub unsafe fn init_noncore() { rtc::init(); serial::init(); } diff --git a/arch/x86_64/src/device/rtc.rs b/arch/x86_64/src/device/rtc.rs index bfef1fc..bed9d75 100644 --- a/arch/x86_64/src/device/rtc.rs +++ b/arch/x86_64/src/device/rtc.rs @@ -1,6 +1,8 @@ use syscall::io::{Io, Pio}; use time; +use acpi; + pub fn init() { let mut rtc = Rtc::new(); time::START.lock().0 = rtc.time(); @@ -45,7 +47,15 @@ impl Rtc { let mut day; let mut month; let mut year; + let mut century; let register_b; + + let century_register = if let Some(ref fadt) = acpi::ACPI_TABLE.lock().fadt { + Some(fadt.century) + } else { + None + }; + unsafe { self.wait(); second = self.read(0) as usize; @@ -54,6 +64,11 @@ impl Rtc { day = self.read(7) as usize; month = self.read(8) as usize; year = self.read(9) as usize; + century = if let Some(century_reg) = century_register { + self.read(century_reg) as usize + } else { + 20 as usize + }; register_b = self.read(0xB); } @@ -64,14 +79,18 @@ impl Rtc { day = cvt_bcd(day); month = cvt_bcd(month); year = cvt_bcd(year); + century = if let Some(century_reg) = century_register { + cvt_bcd(century) + } else { + century + }; } if register_b & 2 != 2 || hour & 0x80 == 0x80 { hour = ((hour & 0x7F) + 12) % 24; } - // TODO: Century Register - year += 2000; + year += century * 100; // Unix time from clock let mut secs: u64 = (year as u64 - 1970) * 31536000; diff --git a/arch/x86_64/src/start.rs b/arch/x86_64/src/start.rs index 4488009..ceab042 100644 --- a/arch/x86_64/src/start.rs +++ b/arch/x86_64/src/start.rs @@ -113,13 +113,16 @@ pub unsafe extern fn kstart() -> ! { // Init the allocator allocator::init(::KERNEL_HEAP_OFFSET, ::KERNEL_HEAP_SIZE); } - + // Initialize devices device::init(&mut active_table); // Read ACPI tables, starts APs acpi::init(&mut active_table); + // Initialize all of the non-core devices not otherwise needed to complete initialization + device::init_noncore(); + BSP_READY.store(true, Ordering::SeqCst); }