Browse Source

初步编写cpu信息获取的代码 (#406)

1. 启动时从acpi获取所有的cpu信息并存到SMP_BOOT_DATA
2. 注册cpu subsystem/bus到sysfs(暂时未添加内容)

todo:
1. build_cpu_map(在X86_64SmpManager中)
2. 实现cpu mask
3. 把cpu设备注册到sysfs
LoGin 1 year ago
parent
commit
d7f5742a20

+ 31 - 0
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(());
+}

+ 8 - 0
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());
+}

+ 3 - 0
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;
 

+ 10 - 0
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(());
+}

+ 82 - 3
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<usize>; 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(());
+    }
+}

+ 22 - 1
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<AcpiHandlerImpl>> {
         unsafe { __ACPI_TABLE.as_ref() }
     }
+
+    /// 从acpi获取平台的信息
+    ///
+    /// 包括:
+    ///
+    /// - PowerProfile
+    /// - InterruptModel
+    /// - ProcessorInfo
+    /// - PmTimer
+    pub fn platform_info(&self) -> Option<PlatformInfo<'_, alloc::alloc::Global>> {
+        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)]

+ 240 - 0
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<dyn Bus>),
+                &(root_device as Arc<dyn Device>),
+            )
+            .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<Self> {
+        let default_weak: Weak<Self> = 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<dyn Bus>)));
+        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<dyn Device>) -> Result<(), SystemError> {
+        todo!()
+    }
+
+    fn shutdown(&self, _device: &Arc<dyn Device>) {
+        todo!()
+    }
+
+    fn resume(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError> {
+        todo!()
+    }
+
+    fn match_device(
+        &self,
+        device: &Arc<dyn Device>,
+        driver: &Arc<dyn Driver>,
+    ) -> Result<bool, SystemError> {
+        // 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<InnerCpuSubSystemFakeRootDevice>,
+    kobj_state: LockedKObjectState,
+}
+
+impl CpuSubSystemFakeRootDevice {
+    pub fn new() -> Arc<Self> {
+        return Arc::new(Self {
+            inner: RwLock::new(InnerCpuSubSystemFakeRootDevice::new()),
+            kobj_state: LockedKObjectState::new(None),
+        });
+    }
+}
+
+#[derive(Debug)]
+struct InnerCpuSubSystemFakeRootDevice {
+    parent_kobj: Option<Weak<dyn KObject>>,
+    bus: Option<Arc<dyn Bus>>,
+    kset: Option<Arc<KSet>>,
+    name: String,
+    kern_inode: Option<Arc<KernFSInode>>,
+    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<Arc<dyn Bus>>) {
+        self.inner.write().bus = bus;
+    }
+
+    fn driver(&self) -> Option<Arc<dyn Driver>> {
+        None
+    }
+
+    fn set_driver(&self, _driver: Option<Weak<dyn Driver>>) {
+        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<Arc<KernFSInode>>) {
+        self.inner.write().kern_inode = inode;
+    }
+
+    fn inode(&self) -> Option<Arc<KernFSInode>> {
+        self.inner.read().kern_inode.clone()
+    }
+
+    fn parent(&self) -> Option<Weak<dyn KObject>> {
+        self.inner.read().parent_kobj.clone()
+    }
+
+    fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
+        self.inner.write().parent_kobj = parent;
+    }
+
+    fn kset(&self) -> Option<Arc<KSet>> {
+        self.inner.read().kset.clone()
+    }
+
+    fn set_kset(&self, kset: Option<Arc<KSet>>) {
+        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<KObjectState> {
+        self.kobj_state.read()
+    }
+
+    fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
+        self.kobj_state.write()
+    }
+
+    fn set_kobj_state(&self, state: KObjectState) {
+        *self.kobj_state_mut() = state;
+    }
+}

+ 63 - 2
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<Arc<dyn Device>> {
+    fn root_device(&self) -> Option<Weak<dyn Device>> {
         None
     }
 
+    fn set_root_device(&self, _dev: Option<Weak<dyn Device>>) {}
+
     /// 总线上的设备的默认属性组
     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<dyn Bus>,
+        fake_root_dev: &Arc<dyn Device>,
+        parent_of_root: &Arc<dyn KObject>,
+    ) -> 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/<name> 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<dyn Bus>,
+        fake_root_dev: &Arc<dyn Device>,
+    ) -> Result<(), SystemError> {
+        return self.subsys_register(
+            subsys,
+            fake_root_dev,
+            &(sys_devices_system_kset() as Arc<dyn KObject>),
+        );
+    }
+}

+ 12 - 1
kernel/src/driver/base/device/mod.rs

@@ -413,6 +413,17 @@ impl DeviceManager {
         return Self;
     }
 
+    pub fn register(&self, device: Arc<dyn Device>) -> Result<(), SystemError> {
+        self.device_initialize(&device);
+        return self.add_device(device);
+    }
+
+    /// device_initialize - init device structure.
+    pub fn device_initialize(&self, device: &Arc<dyn Device>) {
+        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<T: Device>(device: Arc<T>) -> Result<(), SystemError> {
-    return device_manager().add_device(device);
+    return device_manager().register(device);
 }
 
 /// @brief: 设备卸载

+ 2 - 0
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()?;
 
     // 至此,已完成设备驱动模型的初始化
     // 接下来,初始化设备

+ 1 - 0
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;

+ 11 - 6
kernel/src/driver/base/platform/platform_device.rs

@@ -197,6 +197,9 @@ pub struct InnerPlatformBusDevice {
     bus: Option<Arc<dyn Bus>>,
     /// 当前设备已经匹配的驱动
     driver: Option<Weak<dyn Driver>>,
+
+    ktype: Option<&'static dyn KObjType>,
+    kset: Option<Arc<KSet>>,
 }
 
 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<Arc<KSet>> {
-        None
+        self.inner.lock().kset.clone()
     }
 
     fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
@@ -262,8 +267,8 @@ impl KObject for PlatformBusDevice {
         self.inner.lock().name = name;
     }
 
-    fn set_kset(&self, _kset: Option<Arc<KSet>>) {
-        todo!()
+    fn set_kset(&self, kset: Option<Arc<KSet>>) {
+        self.inner.lock().kset = kset;
     }
 
     fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {

+ 6 - 4
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();