From d7f5742a206c6c25ed30009796eb8248429f0a1e Mon Sep 17 00:00:00 2001 From: LoGin Date: Mon, 23 Oct 2023 21:40:39 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E7=BC=96=E5=86=99cpu?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E8=8E=B7=E5=8F=96=E7=9A=84=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=20(#406)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 启动时从acpi获取所有的cpu信息并存到SMP_BOOT_DATA 2. 注册cpu subsystem/bus到sysfs(暂时未添加内容) todo: 1. build_cpu_map(在X86_64SmpManager中) 2. 实现cpu mask 3. 把cpu设备注册到sysfs --- kernel/src/arch/x86_64/acpi.rs | 31 +++ kernel/src/arch/x86_64/c_adapter.rs | 8 + kernel/src/arch/x86_64/mod.rs | 3 + kernel/src/arch/x86_64/setup.rs | 10 + kernel/src/arch/x86_64/smp/mod.rs | 85 ++++++- kernel/src/driver/acpi/mod.rs | 23 +- kernel/src/driver/base/cpu.rs | 240 ++++++++++++++++++ kernel/src/driver/base/device/bus.rs | 65 ++++- kernel/src/driver/base/device/mod.rs | 13 +- kernel/src/driver/base/init.rs | 2 + kernel/src/driver/base/mod.rs | 1 + .../driver/base/platform/platform_device.rs | 17 +- kernel/src/main.c | 10 +- 13 files changed, 491 insertions(+), 17 deletions(-) create mode 100644 kernel/src/arch/x86_64/acpi.rs create mode 100644 kernel/src/arch/x86_64/c_adapter.rs create mode 100644 kernel/src/arch/x86_64/setup.rs create mode 100644 kernel/src/driver/base/cpu.rs diff --git a/kernel/src/arch/x86_64/acpi.rs b/kernel/src/arch/x86_64/acpi.rs new file mode 100644 index 00000000..30dd4e8f --- /dev/null +++ b/kernel/src/arch/x86_64/acpi.rs @@ -0,0 +1,31 @@ +use crate::{driver::acpi::acpi_manager, kinfo, mm::percpu::PerCpu, syscall::SystemError}; + +use super::smp::SMP_BOOT_DATA; + +pub(super) fn early_acpi_boot_init() -> Result<(), SystemError> { + // 在这里解析madt,初始化smp boot data + + let platform_info = acpi_manager().platform_info().ok_or(SystemError::ENODEV)?; + let processor_info = platform_info.processor_info.ok_or(SystemError::ENODEV)?; + + unsafe { + SMP_BOOT_DATA.set_phys_id(0, processor_info.boot_processor.local_apic_id as usize); + let mut cnt = 1; + for ap in processor_info.application_processors.iter() { + if cnt >= PerCpu::MAX_CPU_NUM { + break; + } + SMP_BOOT_DATA.set_phys_id(cnt, ap.local_apic_id as usize); + cnt += 1; + } + SMP_BOOT_DATA.set_cpu_count(cnt); + SMP_BOOT_DATA.mark_initialized(); + } + kinfo!( + "early_acpi_boot_init: cpu_count: {}\n", + SMP_BOOT_DATA.cpu_count() + ); + + // todo!("early_acpi_boot_init") + return Ok(()); +} diff --git a/kernel/src/arch/x86_64/c_adapter.rs b/kernel/src/arch/x86_64/c_adapter.rs new file mode 100644 index 00000000..db9399df --- /dev/null +++ b/kernel/src/arch/x86_64/c_adapter.rs @@ -0,0 +1,8 @@ +use super::setup::setup_arch; + +#[no_mangle] +unsafe extern "C" fn rs_setup_arch() -> i32 { + return setup_arch() + .map(|_| 0) + .unwrap_or_else(|e| e.to_posix_errno()); +} diff --git a/kernel/src/arch/x86_64/mod.rs b/kernel/src/arch/x86_64/mod.rs index 5f3b850d..5bef73d6 100644 --- a/kernel/src/arch/x86_64/mod.rs +++ b/kernel/src/arch/x86_64/mod.rs @@ -1,5 +1,7 @@ #[macro_use] pub mod asm; +mod acpi; +mod c_adapter; pub mod cpu; pub mod fpu; pub mod interrupt; @@ -11,6 +13,7 @@ pub mod pci; pub mod process; pub mod rand; pub mod sched; +pub mod setup; pub mod smp; pub mod syscall; diff --git a/kernel/src/arch/x86_64/setup.rs b/kernel/src/arch/x86_64/setup.rs new file mode 100644 index 00000000..cc432c70 --- /dev/null +++ b/kernel/src/arch/x86_64/setup.rs @@ -0,0 +1,10 @@ +use crate::syscall::SystemError; + +use super::{acpi::early_acpi_boot_init, smp::X86_64_SMP_MANAGER}; + +/// 进行架构相关的初始化工作 +pub fn setup_arch() -> Result<(), SystemError> { + early_acpi_boot_init()?; + X86_64_SMP_MANAGER.build_cpu_map()?; + return Ok(()); +} diff --git a/kernel/src/arch/x86_64/smp/mod.rs b/kernel/src/arch/x86_64/smp/mod.rs index 78900621..3e04c63b 100644 --- a/kernel/src/arch/x86_64/smp/mod.rs +++ b/kernel/src/arch/x86_64/smp/mod.rs @@ -1,11 +1,15 @@ -use core::{arch::asm, hint::spin_loop, sync::atomic::compiler_fence}; +use core::{ + arch::asm, + hint::spin_loop, + sync::atomic::{compiler_fence, AtomicBool, Ordering}, +}; use memoffset::offset_of; use crate::{ arch::process::table::TSSManager, exception::InterruptArch, - include::bindings::bindings::cpu_core_info, kdebug, process::ProcessManager, - smp::core::smp_get_processor_id, + include::bindings::bindings::cpu_core_info, kdebug, libs::rwlock::RwLock, mm::percpu::PerCpu, + process::ProcessManager, smp::core::smp_get_processor_id, syscall::SystemError, }; use super::CurrentIrqArch; @@ -14,6 +18,8 @@ extern "C" { fn smp_ap_start_stage2(); } +pub(super) static X86_64_SMP_MANAGER: X86_64SmpManager = X86_64SmpManager::new(); + #[repr(C)] struct ApStartStackInfo { vaddr: usize, @@ -59,3 +65,76 @@ unsafe extern "C" fn smp_ap_start_stage1() -> ! { spin_loop(); } } + +/// 多核的数据 +#[derive(Debug)] +pub struct SmpBootData { + initialized: AtomicBool, + cpu_count: usize, + /// CPU的物理ID(指的是Local APIC ID) + /// + /// 这里必须保证第0项的是bsp的物理ID + phys_id: [usize; PerCpu::MAX_CPU_NUM], +} + +#[allow(dead_code)] +impl SmpBootData { + pub fn cpu_count(&self) -> usize { + self.cpu_count + } + + /// 获取CPU的物理ID + pub fn phys_id(&self, cpu_id: usize) -> usize { + self.phys_id[cpu_id] + } + + /// 获取BSP的物理ID + pub fn bsp_phys_id(&self) -> usize { + self.phys_id[0] + } + + pub unsafe fn set_cpu_count(&self, cpu_count: usize) { + if self.initialized.load(Ordering::SeqCst) == false { + let p = self as *const SmpBootData as *mut SmpBootData; + (*p).cpu_count = cpu_count; + } + } + + pub unsafe fn set_phys_id(&self, cpu_id: usize, phys_id: usize) { + if self.initialized.load(Ordering::SeqCst) == false { + let p = self as *const SmpBootData as *mut SmpBootData; + (*p).phys_id[cpu_id] = phys_id; + } + } + + /// 标记boot data结构体已经初始化完成 + pub fn mark_initialized(&self) { + self.initialized.store(true, Ordering::SeqCst); + } +} + +pub(super) static SMP_BOOT_DATA: SmpBootData = SmpBootData { + initialized: AtomicBool::new(false), + cpu_count: 0, + phys_id: [0; PerCpu::MAX_CPU_NUM], +}; + +#[allow(dead_code)] +#[derive(Debug)] +pub struct X86_64SmpManager { + ia64_cpu_to_sapicid: RwLock<[Option; PerCpu::MAX_CPU_NUM]>, +} + +impl X86_64SmpManager { + pub const fn new() -> Self { + return Self { + ia64_cpu_to_sapicid: RwLock::new([None; PerCpu::MAX_CPU_NUM]), + }; + } + /// initialize the logical cpu number to APIC ID mapping + pub fn build_cpu_map(&self) -> Result<(), SystemError> { + // 参考:https://opengrok.ringotek.cn/xref/linux-6.1.9/arch/ia64/kernel/smpboot.c?fi=smp_build_cpu_map#496 + // todo!("build_cpu_map") + return Ok(()); + } +} diff --git a/kernel/src/driver/acpi/mod.rs b/kernel/src/driver/acpi/mod.rs index 1a258a1d..db1a3157 100644 --- a/kernel/src/driver/acpi/mod.rs +++ b/kernel/src/driver/acpi/mod.rs @@ -1,6 +1,6 @@ use core::{fmt::Debug, ptr::NonNull}; -use acpi::AcpiHandler; +use acpi::{AcpiHandler, PlatformInfo}; use alloc::{string::ToString, sync::Arc}; use crate::{ @@ -87,6 +87,27 @@ impl AcpiManager { pub fn tables(&self) -> Option<&'static acpi::AcpiTables> { unsafe { __ACPI_TABLE.as_ref() } } + + /// 从acpi获取平台的信息 + /// + /// 包括: + /// + /// - PowerProfile + /// - InterruptModel + /// - ProcessorInfo + /// - PmTimer + pub fn platform_info(&self) -> Option> { + let r = self.tables()?.platform_info(); + if let Err(ref e) = r { + kerror!( + "AcpiManager::platform_info(): failed to get platform info, error: {:?}", + e + ); + return None; + } + + return Some(r.unwrap()); + } } #[derive(Debug, Clone, Copy)] diff --git a/kernel/src/driver/base/cpu.rs b/kernel/src/driver/base/cpu.rs new file mode 100644 index 00000000..6d2611cd --- /dev/null +++ b/kernel/src/driver/base/cpu.rs @@ -0,0 +1,240 @@ +use core::any::Any; + +use alloc::{ + string::{String, ToString}, + sync::{Arc, Weak}, +}; + +use crate::{ + driver::acpi::acpi_manager, + filesystem::kernfs::KernFSInode, + libs::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}, + syscall::SystemError, +}; + +use super::{ + device::{ + bus::{subsystem_manager, Bus}, + driver::Driver, + Device, DeviceNumber, DeviceType, IdTable, + }, + kobject::{KObjType, KObject, KObjectState, LockedKObjectState}, + kset::KSet, + subsys::SubSysPrivate, +}; + +#[inline(always)] +pub fn cpu_device_manager() -> &'static CpuDeviceManager { + return &CpuDeviceManager; +} + +#[derive(Debug)] +pub struct CpuDeviceManager; + +impl CpuDeviceManager { + /// 初始化设备驱动模型的CPU子系统 + /// + /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/cpu.c?fi=get_cpu_device#622 + pub fn init(&self) -> Result<(), SystemError> { + let cpu_subsys = CpuSubSystem::new(); + let root_device = CpuSubSystemFakeRootDevice::new(); + subsystem_manager() + .subsys_system_register( + &(cpu_subsys as Arc), + &(root_device as Arc), + ) + .expect("register cpu subsys failed"); + + return Ok(()); + } +} + +/// cpu子系统 +/// +/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/cpu.c?fi=get_cpu_device#128 +#[derive(Debug)] +struct CpuSubSystem { + subsys_private: SubSysPrivate, +} + +impl CpuSubSystem { + pub fn new() -> Arc { + let default_weak: Weak = Weak::new(); + let bus = Arc::new(Self { + subsys_private: SubSysPrivate::new("cpu".to_string(), default_weak, &[]), + }); + bus.subsystem() + .set_bus(Arc::downgrade(&(bus.clone() as Arc))); + return bus; + } +} + +impl Bus for CpuSubSystem { + fn name(&self) -> String { + "cpu".to_string() + } + + fn dev_name(&self) -> String { + self.name() + } + + fn remove(&self, _device: &Arc) -> Result<(), SystemError> { + todo!() + } + + fn shutdown(&self, _device: &Arc) { + todo!() + } + + fn resume(&self, _device: &Arc) -> Result<(), SystemError> { + todo!() + } + + fn match_device( + &self, + device: &Arc, + driver: &Arc, + ) -> Result { + // ACPI style match is the only one that may succeed. + return acpi_manager().driver_match_device(driver, device); + } + + fn subsystem(&self) -> &SubSysPrivate { + &self.subsys_private + } +} + +#[derive(Debug)] +#[cast_to([sync] Device)] +pub struct CpuSubSystemFakeRootDevice { + inner: RwLock, + kobj_state: LockedKObjectState, +} + +impl CpuSubSystemFakeRootDevice { + pub fn new() -> Arc { + return Arc::new(Self { + inner: RwLock::new(InnerCpuSubSystemFakeRootDevice::new()), + kobj_state: LockedKObjectState::new(None), + }); + } +} + +#[derive(Debug)] +struct InnerCpuSubSystemFakeRootDevice { + parent_kobj: Option>, + bus: Option>, + kset: Option>, + name: String, + kern_inode: Option>, + ktype: Option<&'static dyn KObjType>, +} + +impl InnerCpuSubSystemFakeRootDevice { + pub fn new() -> Self { + return Self { + parent_kobj: None, + bus: None, + kset: None, + name: "".to_string(), + kern_inode: None, + ktype: None, + }; + } +} + +impl Device for CpuSubSystemFakeRootDevice { + fn dev_type(&self) -> DeviceType { + todo!() + } + + fn id_table(&self) -> IdTable { + IdTable::new("cpu".to_string(), DeviceNumber::new(0)) + } + + fn set_bus(&self, bus: Option>) { + self.inner.write().bus = bus; + } + + fn driver(&self) -> Option> { + None + } + + fn set_driver(&self, _driver: Option>) { + todo!() + } + + fn is_dead(&self) -> bool { + false + } + + fn can_match(&self) -> bool { + todo!() + } + + fn set_can_match(&self, _can_match: bool) { + todo!() + } + + fn state_synced(&self) -> bool { + true + } +} + +impl KObject for CpuSubSystemFakeRootDevice { + fn as_any_ref(&self) -> &dyn Any { + self + } + + fn set_inode(&self, inode: Option>) { + self.inner.write().kern_inode = inode; + } + + fn inode(&self) -> Option> { + self.inner.read().kern_inode.clone() + } + + fn parent(&self) -> Option> { + self.inner.read().parent_kobj.clone() + } + + fn set_parent(&self, parent: Option>) { + self.inner.write().parent_kobj = parent; + } + + fn kset(&self) -> Option> { + self.inner.read().kset.clone() + } + + fn set_kset(&self, kset: Option>) { + self.inner.write().kset = kset; + } + + fn kobj_type(&self) -> Option<&'static dyn KObjType> { + self.inner.read().ktype + } + + fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) { + self.inner.write().ktype = ktype; + } + + fn name(&self) -> String { + self.inner.read().name.clone() + } + + fn set_name(&self, name: String) { + self.inner.write().name = name; + } + + fn kobj_state(&self) -> RwLockReadGuard { + self.kobj_state.read() + } + + fn kobj_state_mut(&self) -> RwLockWriteGuard { + self.kobj_state.write() + } + + fn set_kobj_state(&self, state: KObjectState) { + *self.kobj_state_mut() = state; + } +} diff --git a/kernel/src/driver/base/device/bus.rs b/kernel/src/driver/base/device/bus.rs index de14885a..bc5f71f5 100644 --- a/kernel/src/driver/base/device/bus.rs +++ b/kernel/src/driver/base/device/bus.rs @@ -21,7 +21,7 @@ use crate::{ }; use alloc::{ string::{String, ToString}, - sync::Arc, + sync::{Arc, Weak}, }; use core::{ffi::CStr, fmt::Debug, intrinsics::unlikely}; use hashbrown::HashMap; @@ -50,6 +50,11 @@ pub fn bus_manager() -> &'static BusManager { unsafe { BUS_MANAGER_INSTANCE.as_ref().unwrap() } } +#[inline(always)] +pub fn subsystem_manager() -> &'static SubSystemManager { + &SubSystemManager +} + /// @brief: 总线状态 #[derive(Debug, Copy, Clone)] pub enum BusState { @@ -99,10 +104,12 @@ pub trait Bus: Debug + Send + Sync { fn name(&self) -> String; /// Used for subsystems to enumerate devices like ("foo%u", dev->id). fn dev_name(&self) -> String; - fn root_device(&self) -> Option> { + fn root_device(&self) -> Option> { None } + fn set_root_device(&self, _dev: Option>) {} + /// 总线上的设备的默认属性组 fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] { &[] @@ -531,6 +538,9 @@ pub fn buses_init() -> Result<(), SystemError> { devices_system_kset .register(Some(sys_devices_kset())) .expect("devices system kset register failed"); + unsafe { + DEVICES_SYSTEM_KSET_INSTANCE = Some(devices_system_kset); + } } // 初始化总线管理器 @@ -808,3 +818,54 @@ impl Attribute for DriverAttrBind { SysFSOpsSupport::STORE } } + +#[derive(Debug)] +pub struct SubSystemManager; + +impl SubSystemManager { + /// 注册一个子系统,并在`/sys/bus`和指定的父级文件夹下创建子文件夹 + /// + /// ## 参数 + /// + /// - `subsys` - 子系统实例 + /// - `fake_root_dev` - 该子系统的伪根设备 + /// - `parent_of_root` - 该子系统的伪根设备的父级节点 + /// + /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/bus.c?fi=subsys_system_register#1078 + pub fn subsys_register( + &self, + subsys: &Arc, + fake_root_dev: &Arc, + parent_of_root: &Arc, + ) -> Result<(), SystemError> { + bus_manager().register(subsys.clone())?; + fake_root_dev.set_name(subsys.name()); + fake_root_dev.set_parent(Some(Arc::downgrade(parent_of_root))); + + device_manager().register(fake_root_dev.clone())?; + + subsys.set_root_device(Some(Arc::downgrade(fake_root_dev))); + return Ok(()); + } + + /// register a subsystem at /sys/devices/system/ + /// 并且在/sys/bus和/sys/devices下创建文件夹 + /// + /// All 'system' subsystems have a /sys/devices/system/ root device + /// with the name of the subsystem. The root device can carry subsystem- + /// wide attributes. All registered devices are below this single root + /// device and are named after the subsystem with a simple enumeration + /// number appended. The registered devices are not explicitly named; + /// only 'id' in the device needs to be set. + pub fn subsys_system_register( + &self, + subsys: &Arc, + fake_root_dev: &Arc, + ) -> Result<(), SystemError> { + return self.subsys_register( + subsys, + fake_root_dev, + &(sys_devices_system_kset() as Arc), + ); + } +} diff --git a/kernel/src/driver/base/device/mod.rs b/kernel/src/driver/base/device/mod.rs index 42a63025..0d3ecb64 100644 --- a/kernel/src/driver/base/device/mod.rs +++ b/kernel/src/driver/base/device/mod.rs @@ -413,6 +413,17 @@ impl DeviceManager { return Self; } + pub fn register(&self, device: Arc) -> Result<(), SystemError> { + self.device_initialize(&device); + return self.add_device(device); + } + + /// device_initialize - init device structure. + pub fn device_initialize(&self, device: &Arc) { + device.set_kset(Some(sys_devices_kset())); + device.set_kobj_type(Some(&DeviceKObjType)); + } + /// @brief: 添加设备 /// @parameter id_table: 总线标识符,用于唯一标识该总线 /// @parameter dev: 设备实例 @@ -627,7 +638,7 @@ impl DeviceManager { /// @parameter: name: 设备名 /// @return: 操作成功,返回(),操作失败,返回错误码 pub fn device_register(device: Arc) -> Result<(), SystemError> { - return device_manager().add_device(device); + return device_manager().register(device); } /// @brief: 设备卸载 diff --git a/kernel/src/driver/base/init.rs b/kernel/src/driver/base/init.rs index 7c522735..750cf53f 100644 --- a/kernel/src/driver/base/init.rs +++ b/kernel/src/driver/base/init.rs @@ -2,6 +2,7 @@ use crate::{driver::tty::tty_device::tty_init, syscall::SystemError}; use super::{ class::classes_init, + cpu::cpu_device_manager, device::{bus::buses_init, init::devices_init}, firmware::firmware_init, hypervisor::hypervisor_init, @@ -15,6 +16,7 @@ pub(super) fn driver_init() -> Result<(), SystemError> { firmware_init()?; hypervisor_init()?; platform_bus_init()?; + cpu_device_manager().init()?; // 至此,已完成设备驱动模型的初始化 // 接下来,初始化设备 diff --git a/kernel/src/driver/base/mod.rs b/kernel/src/driver/base/mod.rs index 52b86e44..bb8a1faf 100644 --- a/kernel/src/driver/base/mod.rs +++ b/kernel/src/driver/base/mod.rs @@ -2,6 +2,7 @@ pub mod block; pub mod c_adapter; pub mod char; pub mod class; +pub mod cpu; pub mod device; pub mod firmware; pub mod hypervisor; diff --git a/kernel/src/driver/base/platform/platform_device.rs b/kernel/src/driver/base/platform/platform_device.rs index 227d1302..3fa1893c 100644 --- a/kernel/src/driver/base/platform/platform_device.rs +++ b/kernel/src/driver/base/platform/platform_device.rs @@ -197,6 +197,9 @@ pub struct InnerPlatformBusDevice { bus: Option>, /// 当前设备已经匹配的驱动 driver: Option>, + + ktype: Option<&'static dyn KObjType>, + kset: Option>, } impl InnerPlatformBusDevice { @@ -209,6 +212,8 @@ impl InnerPlatformBusDevice { kernfs_inode: None, bus: None, driver: None, + ktype: None, + kset: None, } } } @@ -231,15 +236,15 @@ impl KObject for PlatformBusDevice { } fn kobj_type(&self) -> Option<&'static dyn KObjType> { - None + self.inner.lock().ktype.clone() } - fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) { - todo!("platform_bus_device::set_kobj_type") + fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) { + self.inner.lock().ktype = ktype; } fn kset(&self) -> Option> { - None + self.inner.lock().kset.clone() } fn kobj_state(&self) -> RwLockReadGuard { @@ -262,8 +267,8 @@ impl KObject for PlatformBusDevice { self.inner.lock().name = name; } - fn set_kset(&self, _kset: Option>) { - todo!() + fn set_kset(&self, kset: Option>) { + self.inner.lock().kset = kset; } fn set_parent(&self, parent: Option>) { diff --git a/kernel/src/main.c b/kernel/src/main.c index 72c062be..d911d1b4 100644 --- a/kernel/src/main.c +++ b/kernel/src/main.c @@ -37,6 +37,7 @@ extern void rs_mm_init(); extern void rs_kthread_init(); extern void rs_init_intertrait(); extern void rs_init_before_mem_init(); +extern int rs_setup_arch(); ul bsp_idt_size, bsp_gdt_size; @@ -81,7 +82,7 @@ void system_initialize() rs_load_current_core_tss(); cpu_core_info[0].stack_start = _stack_start; - + // 初始化中断描述符表 sys_vector_init(); // 初始化内存管理单元 @@ -100,10 +101,12 @@ void system_initialize() // kinfo("vaddr:%#018lx", video_frame_buffer_info.vaddr); io_mfence(); vfs_init(); - + rs_driver_init(); - + acpi_init(); + + rs_setup_arch(); io_mfence(); irq_init(); rs_process_init(); @@ -125,7 +128,6 @@ void system_initialize() rs_jiffies_init(); io_mfence(); - rs_kthread_init(); io_mfence();