From f79424aeacc7605f577bd5420abda8b05f9fb079 Mon Sep 17 00:00:00 2001 From: Connor Wood <connorwood71@gmail.com> 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 5b235ce9..b6c05ff9 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<Acpi> { +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<Acpi> { } 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<Fadt> } +pub static ACPI_TABLE: Mutex<Acpi> = 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 522b2b48..ef27ccb2 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 bfef1fcb..bed9d755 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 44880095..ceab0426 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); } -- GitLab