From f79424aeacc7605f577bd5420abda8b05f9fb079 Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Sat, 18 Mar 2017 16:08:45 +0000 Subject: [PATCH] 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); }