1 use alloc::vec::Vec;
2 use hashbrown::HashSet;
3
4 use crate::{driver::acpi::acpi_manager, kdebug};
5
6 /// 这是一个临时的函数,用于在acpi、cpu模块被正式实现之前,让原本的C写的smp模块能正常运行
7 ///
8 /// 请注意!这样写会使得smp模块与x86强耦合。正确的做法是:
9 /// - 在sysfs中新增acpi firmware
10 /// - 在acpi初始化的时候,初始化处理器拓扑信息
11 /// - 初始化cpu模块(加入到sysfs,放置在/sys/devices/system下面)
12 /// - smp模块从cpu模块处,获取到与架构无关的处理器拓扑信息
13 /// - smp根据上述信息,初始化指定的处理器(这部分在arch下面实现)
14 ///
15 /// 但是由于acpi、cpu模块还没有被正式实现,所以暂时使用这个函数来代替,接下来会按照上述步骤进行编写代码
16 #[no_mangle]
rs_smp_get_cpus(res: *mut X86CpuInfo) -> usize17 unsafe extern "C" fn rs_smp_get_cpus(res: *mut X86CpuInfo) -> usize {
18 let acpi_table = acpi_manager().tables().unwrap();
19 let platform_info = acpi_table
20 .platform_info()
21 .expect("smp_get_cpu_topology(): failed to get platform info");
22 let processor_info = platform_info
23 .processor_info
24 .expect("smp_get_cpu_topology(): failed to get processor info");
25
26 let mut id_set = HashSet::new();
27 let mut cpu_info = processor_info
28 .application_processors
29 .iter()
30 .filter_map(|ap| {
31 if id_set.contains(&ap.local_apic_id) {
32 return None;
33 }
34 let can_boot = ap.state == acpi::platform::ProcessorState::WaitingForSipi;
35 if !can_boot {
36 return None;
37 }
38
39 id_set.insert(ap.local_apic_id);
40 Some(X86CpuInfo::new(
41 ap.local_apic_id,
42 ap.processor_uid,
43 can_boot,
44 ))
45 })
46 .collect::<Vec<_>>();
47
48 let bsp_info = X86CpuInfo::new(
49 processor_info.boot_processor.local_apic_id,
50 processor_info.boot_processor.processor_uid,
51 processor_info.boot_processor.state == acpi::platform::ProcessorState::WaitingForSipi,
52 );
53 cpu_info.push(bsp_info);
54
55 cpu_info.sort_by(|a, b| a.apic_id.cmp(&b.apic_id));
56 kdebug!("cpu_info: {:?}", cpu_info);
57
58 res.copy_from_nonoverlapping(cpu_info.as_ptr(), cpu_info.len());
59 return cpu_info.len();
60 }
61
62 /// 这个是临时用于传数据给c版本代码的结构体,请勿用作其他用途
63 #[repr(C)]
64 #[derive(Debug)]
65 struct X86CpuInfo {
66 apic_id: u32,
67 core_id: u32,
68 can_boot: core::ffi::c_char,
69 }
70
71 impl X86CpuInfo {
new(apic_id: u32, core_id: u32, can_boot: bool) -> Self72 fn new(apic_id: u32, core_id: u32, can_boot: bool) -> Self {
73 Self {
74 apic_id,
75 core_id,
76 can_boot: can_boot as core::ffi::c_char,
77 }
78 }
79 }
80