From f50e186d44c1ee267e270a02ba528553e94c9a0a Mon Sep 17 00:00:00 2001 From: yufeng <321353225@qq.com> Date: Sun, 22 Sep 2024 04:27:12 +0800 Subject: [PATCH] feat: add pci temp --- Cargo.lock | 11 +++++ Cargo.toml | 1 + example/Cargo.lock | 11 +++++ example/Cargo.toml | 2 +- example/Makefile | 1 + example/src/pci.rs | 24 ++++++----- src/components/arch/x86_64.rs | 4 +- src/components/arch/x86_64/acpi.rs | 65 ++++++++++++++++++++++++++++++ src/components/boot/mod.rs | 2 +- src/components/boot/riscv64.rs | 2 +- src/components/boot/x86_64.rs | 12 +++--- src/components/common.rs | 32 ++++++++++++--- src/components/multicore/x86_64.rs | 30 ++++++++++++-- src/utils/init_num.rs | 43 ++++++++++++++++++++ src/utils/mod.rs | 2 + 15 files changed, 212 insertions(+), 30 deletions(-) create mode 100644 src/components/arch/x86_64/acpi.rs create mode 100644 src/utils/init_num.rs diff --git a/Cargo.lock b/Cargo.lock index 44821c7..18dd476 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,6 +11,16 @@ dependencies = [ "tock-registers", ] +[[package]] +name = "acpi" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e248409195304021f61b39ba2628f62a45a3abf6119669d44b3399d60eabe4c3" +dependencies = [ + "bit_field", + "log", +] + [[package]] name = "arm_gicv2" version = "0.1.0" @@ -138,6 +148,7 @@ name = "polyhal" version = "0.1.3" dependencies = [ "aarch64-cpu", + "acpi", "arm_gicv2", "arm_pl011", "bitflags 2.5.0", diff --git a/Cargo.toml b/Cargo.toml index 5fdcc4b..f256900 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,6 +36,7 @@ x86_64 = "0.14" multiboot = "0.8.0" x2apic = "0.4" raw-cpuid = "11.0" +acpi = "5.0.0" [target.'cfg(target_arch = "aarch64")'.dependencies] aarch64-cpu = "9.3" diff --git a/example/Cargo.lock b/example/Cargo.lock index 313a957..44543fa 100644 --- a/example/Cargo.lock +++ b/example/Cargo.lock @@ -11,6 +11,16 @@ dependencies = [ "tock-registers", ] +[[package]] +name = "acpi" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e248409195304021f61b39ba2628f62a45a3abf6119669d44b3399d60eabe4c3" +dependencies = [ + "bit_field", + "log", +] + [[package]] name = "arm_gicv2" version = "0.1.0" @@ -167,6 +177,7 @@ name = "polyhal" version = "0.1.3" dependencies = [ "aarch64-cpu", + "acpi", "arm_gicv2", "arm_pl011", "bitflags 2.6.0", diff --git a/example/Cargo.toml b/example/Cargo.toml index f163373..d0faa3d 100644 --- a/example/Cargo.toml +++ b/example/Cargo.toml @@ -11,7 +11,7 @@ polyhal = { version = "0.1.2", features = [ "logger", "boot", "trap", - "graphic" + # "graphic" ] } log = "0.4" fdt = "0.1.5" diff --git a/example/Makefile b/example/Makefile index 7d77f2d..278dc16 100644 --- a/example/Makefile +++ b/example/Makefile @@ -50,6 +50,7 @@ OBJCOPY := rust-objcopy --binary-architecture=riscv64 ifneq ($(GUI), true) QEMU_EXEC += -nographic else +BUILD_ARGS += --features "polyhal/graphic" QEMU_EXEC += -serial stdio -vga std endif QEMU_EXEC += -smp $(SMP) diff --git a/example/src/pci.rs b/example/src/pci.rs index 9014db5..72adb35 100644 --- a/example/src/pci.rs +++ b/example/src/pci.rs @@ -1,5 +1,5 @@ use log::{info, trace}; -use polyhal::{common::get_fdt, consts::VIRT_ADDR_START}; +use polyhal::{common::get_pci_addr, consts::VIRT_ADDR_START}; use virtio_drivers::transport::pci::{ bus::{Cam, Command, DeviceFunction, HeaderType, PciRoot}, virtio_device_type, @@ -7,16 +7,20 @@ use virtio_drivers::transport::pci::{ /// Initialize PCI Configuration. pub fn init() { - if let Some(fdt) = get_fdt() { - if let Some(pci_node) = fdt.all_nodes().find(|x| x.name.starts_with("pci")) { - let pci_addr = pci_node.reg().map(|mut x| x.next().unwrap()).unwrap(); - log::info!("PCI Address: {:#p}", pci_addr.starting_address); - enumerate_pci((pci_addr.starting_address as usize | VIRT_ADDR_START) as *mut u8); - return; - } + // if let Some(fdt) = get_fdt() { + // if let Some(pci_node) = fdt.all_nodes().find(|x| x.name.starts_with("pci")) { + // let pci_addr = pci_node.reg().map(|mut x| x.next().unwrap()).unwrap(); + // log::info!("PCI Address: {:#p}", pci_addr.starting_address); + // enumerate_pci((pci_addr.starting_address as usize | VIRT_ADDR_START) as *mut u8); + // return; + // } + // } + // #[cfg(target_arch = "x86_64")] + // enumerate_pci((0xb000_0000 | VIRT_ADDR_START) as *mut u8); + if let Some(pci_addr) = get_pci_addr() { + log::info!("PCI Address: {:#x}", pci_addr); + enumerate_pci((pci_addr | VIRT_ADDR_START) as *mut u8); } - #[cfg(target_arch = "x86_64")] - enumerate_pci((0xb000_0000 | VIRT_ADDR_START) as *mut u8); } /// Enumerate the PCI devices diff --git a/src/components/arch/x86_64.rs b/src/components/arch/x86_64.rs index fdbcf2a..e4c9af7 100644 --- a/src/components/arch/x86_64.rs +++ b/src/components/arch/x86_64.rs @@ -1,9 +1,11 @@ pub(crate) mod apic; pub(crate) mod gdt; pub(crate) mod idt; +pub(crate) mod acpi; use core::sync::atomic::AtomicUsize; +use acpi::parse_acpi_info; use alloc::vec::Vec; use multiboot::information::MemoryType; @@ -18,6 +20,7 @@ use crate::components::{ pub(crate) static MBOOT_PTR: AtomicUsize = AtomicUsize::new(0); pub(crate) fn arch_init() { + let _ = parse_acpi_info(); DTB_BIN.init_by(Vec::new()); if let Some(mboot) = use_multiboot(MBOOT_PTR.load(core::sync::atomic::Ordering::SeqCst) as _) { let mut mem_area = Vec::new(); @@ -29,7 +32,6 @@ pub(crate) fn arch_init() { .for_each(|x| { let start = x.base_address() as usize | VIRT_ADDR_START; let size = x.length() as usize; - // ArchInterface::add_memory_region(start, end); mem_area.push((start, size)); }); } diff --git a/src/components/arch/x86_64/acpi.rs b/src/components/arch/x86_64/acpi.rs new file mode 100644 index 0000000..aec85e1 --- /dev/null +++ b/src/components/arch/x86_64/acpi.rs @@ -0,0 +1,65 @@ +use core::ptr::NonNull; + +use acpi::{AcpiError, AcpiHandler, AcpiTables}; + +use crate::{common::{CPU_NUM, PCI_ADDR}, consts::VIRT_ADDR_START}; + +#[derive(Clone)] +struct AcpiImpl; + +impl AcpiHandler for AcpiImpl { + unsafe fn map_physical_region( + &self, + physical_address: usize, + size: usize, + ) -> acpi::PhysicalMapping { + unsafe { + acpi::PhysicalMapping::new( + physical_address, + NonNull::new((physical_address | VIRT_ADDR_START) as *mut T).unwrap(), + size, + size, + AcpiImpl, + ) + } + } + + fn unmap_physical_region(_region: &acpi::PhysicalMapping) {} +} + +/// Detects the address of acpi through acpi_signature. +/// +/// Detects in bios area. +pub(crate) fn detect_acpi() -> Result<(), AcpiError> { + unsafe { + match AcpiTables::search_for_rsdp_bios(AcpiImpl) { + Ok(ref acpi_table) => { + let madt = acpi_table.find_table::()?; + let cpu_count = madt + .entries() + .filter(|x| matches!(x, acpi::madt::MadtEntry::LocalApic(_))) + .count(); + CPU_NUM.init(cpu_count); + } + Err(err) => log::warn!("Not Found Available ACPI: {:#x?}", err), + } + } + Err(AcpiError::NoValidRsdp) +} + +/// Parse informations from acpi table. +pub(crate) fn parse_acpi_info() -> Result<(), AcpiError> { + unsafe { + match AcpiTables::search_for_rsdp_bios(AcpiImpl) { + Ok(ref acpi_table) => { + acpi::PciConfigRegions::new(acpi_table).expect("can't find pci config"); + let pci_addr = acpi::PciConfigRegions::new(acpi_table)? + .physical_address(0, 0, 0, 0) + .ok_or(AcpiError::NoValidRsdp)?; + PCI_ADDR.init(pci_addr as _); + } + Err(err) => log::warn!("Not Found Available ACPI: {:#x?}", err), + } + } + Err(AcpiError::NoValidRsdp) +} diff --git a/src/components/boot/mod.rs b/src/components/boot/mod.rs index 3c5943c..e0bae14 100644 --- a/src/components/boot/mod.rs +++ b/src/components/boot/mod.rs @@ -40,7 +40,7 @@ extern "Rust" { } /// Define the entry point. -/// +/// /// TODO: Support secondary Entry Point for the application core. /// - Implement MultiCore /// - Jump to _secondary_for_arch function in application core. diff --git a/src/components/boot/riscv64.rs b/src/components/boot/riscv64.rs index 81ab504..bc319db 100644 --- a/src/components/boot/riscv64.rs +++ b/src/components/boot/riscv64.rs @@ -132,7 +132,7 @@ pub(crate) fn rust_main(hartid: usize, device_tree: usize) { init_cpu(); let fdt = unsafe { Fdt::from_ptr(device_tree as *const u8) }; - CPU_NUM.init_by(fdt.map(|fdt| fdt.cpus().count()).unwrap_or(1)); + CPU_NUM.init(fdt.map(|fdt| fdt.cpus().count()).unwrap_or(1)); DTB_PTR.init_by(device_tree); diff --git a/src/components/boot/x86_64.rs b/src/components/boot/x86_64.rs index e55dd8b..efd7136 100644 --- a/src/components/boot/x86_64.rs +++ b/src/components/boot/x86_64.rs @@ -7,6 +7,8 @@ use x86_64::registers::control::{Cr0Flags, Cr4, Cr4Flags}; use x86_64::registers::model_specific::EferFlags; use x86_64::registers::xcontrol::{XCr0, XCr0Flags}; +use crate::arch::acpi::detect_acpi; +use crate::common::get_cpu_num; use crate::components::arch::{self, get_com_port, hart_id, MBOOT_PTR}; use crate::components::common::{CPU_ID, CPU_NUM}; use crate::components::consts::VIRT_ADDR_START; @@ -156,8 +158,7 @@ fn rust_tmp_main(magic: usize, mboot_ptr: usize) { } }); - // TODO: This is will be fixed with ACPI support - CPU_NUM.init_by(1); + let _ = detect_acpi(); // Check Multiboot Magic Number. assert_eq!(magic, multiboot::information::SIGNATURE_EAX as usize); @@ -169,11 +170,8 @@ fn rust_tmp_main(magic: usize, mboot_ptr: usize) { println!(include_str!("../../banner.txt")); display_info!("Platform Arch", "x86_64"); if let Some(features) = CpuId::new().get_feature_info() { - display_info!( - "Platform Hart Count", - "{}", - core::cmp::max(1, features.max_logical_processor_ids()) - ); + CPU_NUM.init(core::cmp::max(1, features.max_logical_processor_ids() as _)); + display_info!("Platform Hart Count", "{}", get_cpu_num()); display_info!("Platform FPU Support", "{}", features.has_fpu()); } display_info!("Platform Boot Header", "{mboot_ptr:#018x}"); diff --git a/src/components/common.rs b/src/components/common.rs index 7c8113c..4566b12 100644 --- a/src/components/common.rs +++ b/src/components/common.rs @@ -2,6 +2,7 @@ use alloc::vec::Vec; use fdt::Fdt; use crate::components::arch::arch_init; +use crate::utils::InitNum; use crate::{utils::LazyInit, PhysPage}; use super::debug_console::display_info; @@ -13,6 +14,8 @@ pub(crate) static CPU_ID: usize = 0; #[allow(dead_code)] pub(crate) static DTB_PTR: LazyInit = LazyInit::new(); +pub(crate) static PCI_ADDR: InitNum = InitNum::new(0); + /// Page Allocation trait for privoids that page allocation pub trait PageAlloc: Sync { /// Allocate a physical page @@ -33,7 +36,7 @@ pub fn init(page_alloc: &'static dyn PageAlloc) { } /// Store the number of cpu, this will fill up by startup function. -pub(crate) static CPU_NUM: LazyInit = LazyInit::new(); +pub(crate) static CPU_NUM: InitNum = InitNum::new(0); /// Store the memory area, this will fill up by the arch_init() function in each architecture. pub(crate) static MEM_AREA: LazyInit> = LazyInit::new(); @@ -52,9 +55,14 @@ pub fn get_fdt() -> Option> { unsafe { Fdt::from_ptr(*DTB_PTR.get_unchecked() as *const u8).ok() } } +/// Get the pci area address +pub fn get_pci_addr() -> Option { + PCI_ADDR.get_option() +} + /// Get the number of cpus pub fn get_cpu_num() -> usize { - *CPU_NUM + CPU_NUM.get() } /// alloc a persistent memory page @@ -70,8 +78,8 @@ pub(crate) fn frame_dealloc(ppn: PhysPage) { } /// Parse Information from the device tree binary -/// -/// Display information when booting +/// +/// Display information when booting /// Initialize the variables and memory from device tree #[inline] pub(crate) fn parse_dtb_info() { @@ -91,8 +99,20 @@ pub(crate) fn parse_dtb_info() { display_info!("Boot Args", "{}", fdt.chosen().bootargs().unwrap_or("")); - CPU_NUM.init_by(fdt.cpus().count()); + CPU_NUM.init(fdt.cpus().count()); + + fdt.all_nodes() + .find(|x| x.name.starts_with("pci")) + .inspect(|pci_node| { + PCI_ADDR.init( + pci_node + .reg() + .map(|mut x| x.next().unwrap()) + .unwrap() + .starting_address as _, + ) + }); } else { - CPU_NUM.init_by(1); + CPU_NUM.init(1); } } diff --git a/src/components/multicore/x86_64.rs b/src/components/multicore/x86_64.rs index 1cd88c3..a0a5161 100644 --- a/src/components/multicore/x86_64.rs +++ b/src/components/multicore/x86_64.rs @@ -1,4 +1,28 @@ -// TODO: Boot a core with top pointer of the stack -pub fn boot_core(_hart_id: usize, _sp_top: usize) { - log::error!("Boot Core is not implemented yet for aarch64"); +use core::sync::atomic::{AtomicBool, Ordering}; + +/// TODO: Boot a core with top pointer of the stack +/// Fina a way to pass the stack pointer to core. +pub fn boot_core(hart_id: usize, _sp_top: usize) { + static BOOT_LOCK: AtomicBool = AtomicBool::new(false); + + // Waiting until the previous boot is completed. + while BOOT_LOCK.load(Ordering::SeqCst) {}; + + // Set the boot lock to true and start the boot process. + BOOT_LOCK.store(true, Ordering::SeqCst); + log::error!("Boot Core is not implemented yet for x86_64"); + + let apic_id = crate::arch::apic::raw_apic_id(hart_id as _); + let lapic = crate::arch::apic::local_apic(); + + // This is the + const START_PAGE_IDX: u8 = 6; + + unsafe { + lapic.send_init_ipi(apic_id); + + lapic.send_sipi(START_PAGE_IDX, apic_id); + + lapic.send_sipi(START_PAGE_IDX, apic_id); + } } diff --git a/src/utils/init_num.rs b/src/utils/init_num.rs new file mode 100644 index 0000000..65d5343 --- /dev/null +++ b/src/utils/init_num.rs @@ -0,0 +1,43 @@ +use core::sync::atomic::{AtomicUsize, Ordering}; + +/// Structure Store usize and data like this +/// +/// Initialize in the Boot Stage. Only initialize once. +pub(crate) struct InitNum(AtomicUsize); + +impl InitNum { + /// Create a new InitNum + pub const fn new(num: usize) -> InitNum { + Self(AtomicUsize::new(0)) + } + + /// Get the number of the elements + #[inline] + pub fn is_initialized(&self) -> bool { + self.0.load(Ordering::SeqCst) != 0 + } + + /// Initialize if not already initialized + #[inline] + pub fn init(&self, value: usize) { + let _ = self + .0 + .compare_exchange(0, value, Ordering::Acquire, Ordering::Relaxed); + } + + /// Get the number in the InitNum structure + #[inline] + pub fn get(&self) -> usize { + self.0.load(Ordering::SeqCst) + } + + /// Get the Some(data) if has been initialized, return None otherwise. + #[inline] + pub fn get_option(&self) -> Option { + let data = self.0.load(Ordering::SeqCst); + match data { + 0 => None, + _ => Some(data), + } + } +} diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 8894718..af4aa5f 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,7 +1,9 @@ +mod init_num; mod lazy_init; mod macros; mod mutex_no_irq; +pub(crate) use init_num::InitNum; pub use lazy_init::LazyInit; pub use macros::bit; pub use mutex_no_irq::{MutexNoIrq, MutexNoIrqGuard};