mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-20 05:56:32 +00:00
重写SMP模块 (#633)
* 修复cpumask的迭代器的错误。 * 能进系统(AP核心还没有初始化自身) * 初始化ap core * 修改percpu * 删除无用的cpu.c * riscv64编译通过
This commit is contained in:
@ -1,6 +1,9 @@
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::smp::SMPArch;
|
||||
use crate::smp::{
|
||||
cpu::{CpuHpCpuState, ProcessorId},
|
||||
SMPArch,
|
||||
};
|
||||
|
||||
pub struct RiscV64SMPArch;
|
||||
|
||||
@ -10,7 +13,7 @@ impl SMPArch for RiscV64SMPArch {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn init() -> Result<(), SystemError> {
|
||||
fn start_cpu(cpu_id: ProcessorId, hp_state: &CpuHpCpuState) -> Result<(), SystemError> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
@ -5,4 +5,8 @@ impl TimeArch for RiscV64TimeArch {
|
||||
fn get_cycles() -> usize {
|
||||
riscv::register::cycle::read()
|
||||
}
|
||||
|
||||
fn cal_expire_cycles(ns: usize) -> usize {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ _apu_boot_base = .
|
||||
|
||||
// 设置栈指针
|
||||
movl $(_apu_boot_tmp_stack_end - _apu_boot_base), %esp
|
||||
|
||||
|
||||
// 计算ap处理器引导程序的基地址
|
||||
mov %cs, %ax
|
||||
movzx %ax, %esi
|
||||
|
@ -1,25 +0,0 @@
|
||||
use crate::{sched::SchedArch, time::TimeArch};
|
||||
|
||||
use super::{driver::tsc::TSCManager, syscall::init_syscall_64, CurrentSchedArch, CurrentTimeArch};
|
||||
|
||||
/// 获取当前的时间戳
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn rs_get_cycles() -> u64 {
|
||||
return CurrentTimeArch::get_cycles() as u64;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn rs_tsc_get_cpu_khz() -> u64 {
|
||||
return TSCManager::cpu_khz();
|
||||
}
|
||||
|
||||
/// syscall指令初始化
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn rs_init_syscall_64() {
|
||||
init_syscall_64();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn rs_init_current_core_sched() {
|
||||
CurrentSchedArch::initial_setup_sched_local();
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
use x86::cpuid::{cpuid, CpuIdResult};
|
||||
|
||||
use crate::smp::cpu::{ProcessorId, SmpCpuManager};
|
||||
use crate::smp::cpu::ProcessorId;
|
||||
|
||||
/// 获取当前cpu的apic id
|
||||
#[inline]
|
||||
@ -16,7 +16,3 @@ pub unsafe fn cpu_reset() -> ! {
|
||||
unsafe { x86::io::outb(0x64, 0xfe) };
|
||||
loop {}
|
||||
}
|
||||
|
||||
impl SmpCpuManager {
|
||||
pub fn arch_init(_boot_cpu: ProcessorId) {}
|
||||
}
|
||||
|
@ -1,11 +0,0 @@
|
||||
//
|
||||
// Created by longjin on 2022/1/20.
|
||||
//
|
||||
|
||||
#include <common/cpu.h>
|
||||
|
||||
|
||||
void __init_set_cpu_stack_start(uint32_t cpu, uint64_t stack_start)
|
||||
{
|
||||
cpu_core_info[cpu].stack_start = stack_start;
|
||||
}
|
@ -6,7 +6,6 @@ use x86::dtables::DescriptorTablePointer;
|
||||
use crate::{
|
||||
arch::{interrupt::trap::arch_trap_init, process::table::TSSManager},
|
||||
driver::pci::pci::pci_init,
|
||||
include::bindings::bindings::cpu_init,
|
||||
init::init::start_kernel,
|
||||
kdebug,
|
||||
mm::{MemoryManagementArch, PhysAddr},
|
||||
@ -33,7 +32,6 @@ extern "C" {
|
||||
fn head_stack_start();
|
||||
|
||||
fn multiboot2_init(mb2_info: u64, mb2_magic: u32) -> bool;
|
||||
fn __init_set_cpu_stack_start(cpu: u32, stack_start: u64);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@ -81,7 +79,6 @@ pub fn early_setup_arch() -> Result<(), SystemError> {
|
||||
|
||||
set_current_core_tss(stack_start, 0);
|
||||
unsafe { TSSManager::load_tr() };
|
||||
unsafe { __init_set_cpu_stack_start(0, stack_start as u64) };
|
||||
arch_trap_init().expect("arch_trap_init failed");
|
||||
|
||||
return Ok(());
|
||||
@ -90,10 +87,6 @@ pub fn early_setup_arch() -> Result<(), SystemError> {
|
||||
/// 架构相关的初始化
|
||||
#[inline(never)]
|
||||
pub fn setup_arch() -> Result<(), SystemError> {
|
||||
unsafe {
|
||||
cpu_init();
|
||||
}
|
||||
|
||||
// todo: 将来pci接入设备驱动模型之后,删掉这里。
|
||||
pci_init();
|
||||
return Ok(());
|
||||
|
@ -1,17 +0,0 @@
|
||||
use crate::smp::cpu::ProcessorId;
|
||||
|
||||
use super::ipi::{ipi_send_smp_init, ipi_send_smp_startup};
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn rs_ipi_send_smp_init() -> i32 {
|
||||
return ipi_send_smp_init()
|
||||
.map(|_| 0)
|
||||
.unwrap_or_else(|e| e.to_posix_errno());
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn rs_ipi_send_smp_startup(target_cpu: u32) -> i32 {
|
||||
return ipi_send_smp_startup(ProcessorId::new(target_cpu))
|
||||
.map(|_| 0)
|
||||
.unwrap_or_else(|e| e.to_posix_errno());
|
||||
}
|
@ -160,7 +160,7 @@ pub fn send_ipi(kind: IpiKind, target: IpiTarget) {
|
||||
}
|
||||
|
||||
/// 发送smp初始化IPI
|
||||
pub fn ipi_send_smp_init() -> Result<(), SystemError> {
|
||||
pub fn ipi_send_smp_init() {
|
||||
let target = ArchIpiTarget::Other;
|
||||
let icr = if CurrentApic.x2apic_enabled() {
|
||||
x86::apic::Icr::for_x2apic(
|
||||
@ -186,7 +186,6 @@ pub fn ipi_send_smp_init() -> Result<(), SystemError> {
|
||||
)
|
||||
};
|
||||
CurrentApic.write_icr(icr);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
/// 发送smp启动IPI
|
||||
|
@ -1,4 +1,3 @@
|
||||
mod c_adapter;
|
||||
pub(super) mod entry;
|
||||
mod handle;
|
||||
pub mod ipi;
|
||||
@ -93,6 +92,14 @@ impl InterruptArch for X86_64InterruptArch {
|
||||
fn arch_early_irq_init() -> Result<(), SystemError> {
|
||||
arch_early_irq_init()
|
||||
}
|
||||
|
||||
fn arch_ap_early_irq_init() -> Result<(), SystemError> {
|
||||
if !CurrentApic.init_current_cpu() {
|
||||
return Err(SystemError::ENODEV);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// 中断栈帧结构体
|
||||
|
@ -1,7 +0,0 @@
|
||||
use super::LowAddressRemapping;
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn rs_unmap_at_low_addr() -> usize {
|
||||
LowAddressRemapping::unmap_at_low_address(true);
|
||||
return 0;
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
pub mod barrier;
|
||||
pub mod bump;
|
||||
mod c_adapter;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use hashbrown::HashSet;
|
||||
@ -159,6 +158,7 @@ impl MemoryManagementArch for X86_64MMArch {
|
||||
|
||||
// 初始化内存管理器
|
||||
unsafe { allocator_init() };
|
||||
|
||||
send_to_default_serial8250_port("x86 64 init done\n\0".as_bytes());
|
||||
}
|
||||
|
||||
@ -181,11 +181,10 @@ impl MemoryManagementArch for X86_64MMArch {
|
||||
unsafe fn table(table_kind: PageTableKind) -> PhysAddr {
|
||||
match table_kind {
|
||||
PageTableKind::Kernel | PageTableKind::User => {
|
||||
let paddr: usize;
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
asm!("mov {}, cr3", out(reg) paddr, options(nomem, nostack, preserves_flags));
|
||||
let cr3 = x86::controlregs::cr3() as usize;
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
return PhysAddr::new(paddr);
|
||||
return PhysAddr::new(cr3);
|
||||
}
|
||||
PageTableKind::EPT => {
|
||||
let eptp =
|
||||
@ -461,9 +460,6 @@ unsafe fn allocator_init() {
|
||||
flusher.ignore();
|
||||
}
|
||||
}
|
||||
|
||||
// 添加低地址的映射(在smp完成初始化之前,需要使用低地址的映射.初始化之后需要取消这一段映射)
|
||||
LowAddressRemapping::remap_at_low_address(&mut mapper);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
@ -659,9 +655,7 @@ impl LowAddressRemapping {
|
||||
// 映射64M
|
||||
const REMAP_SIZE: usize = 64 * 1024 * 1024;
|
||||
|
||||
pub unsafe fn remap_at_low_address(
|
||||
mapper: &mut crate::mm::page::PageMapper<MMArch, &mut BumpAllocator<MMArch>>,
|
||||
) {
|
||||
pub unsafe fn remap_at_low_address(mapper: &mut PageMapper) {
|
||||
for i in 0..(Self::REMAP_SIZE / MMArch::PAGE_SIZE) {
|
||||
let paddr = PhysAddr::new(i * MMArch::PAGE_SIZE);
|
||||
let vaddr = VirtAddr::new(i * MMArch::PAGE_SIZE);
|
||||
@ -676,14 +670,10 @@ impl LowAddressRemapping {
|
||||
}
|
||||
|
||||
/// 取消低地址的映射
|
||||
pub unsafe fn unmap_at_low_address(flush: bool) {
|
||||
let mut mapper = KernelMapper::lock();
|
||||
assert!(mapper.as_mut().is_some());
|
||||
pub unsafe fn unmap_at_low_address(mapper: &mut PageMapper, flush: bool) {
|
||||
for i in 0..(Self::REMAP_SIZE / MMArch::PAGE_SIZE) {
|
||||
let vaddr = VirtAddr::new(i * MMArch::PAGE_SIZE);
|
||||
let (_, _, flusher) = mapper
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.unmap_phys(vaddr, true)
|
||||
.expect("Failed to unmap frame");
|
||||
if flush == false {
|
||||
|
@ -1,7 +1,6 @@
|
||||
#[macro_use]
|
||||
pub mod asm;
|
||||
mod acpi;
|
||||
mod c_adapter;
|
||||
pub mod cpu;
|
||||
pub mod driver;
|
||||
pub mod elf;
|
||||
|
@ -1,27 +1,38 @@
|
||||
use core::{
|
||||
arch::asm,
|
||||
hint::spin_loop,
|
||||
sync::atomic::{compiler_fence, AtomicBool, Ordering},
|
||||
sync::atomic::{compiler_fence, fence, AtomicBool, Ordering},
|
||||
};
|
||||
|
||||
use kdepends::memoffset::offset_of;
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::{
|
||||
arch::process::table::TSSManager,
|
||||
arch::{mm::LowAddressRemapping, process::table::TSSManager, MMArch},
|
||||
exception::InterruptArch,
|
||||
include::bindings::bindings::{cpu_core_info, smp_init},
|
||||
kdebug,
|
||||
libs::rwlock::RwLock,
|
||||
mm::percpu::PerCpu,
|
||||
libs::{cpumask::CpuMask, rwlock::RwLock},
|
||||
mm::{percpu::PerCpu, MemoryManagementArch, PhysAddr, VirtAddr, IDLE_PROCESS_ADDRESS_SPACE},
|
||||
process::ProcessManager,
|
||||
smp::{core::smp_get_processor_id, cpu::ProcessorId, SMPArch},
|
||||
smp::{
|
||||
core::smp_get_processor_id,
|
||||
cpu::{smp_cpu_manager, CpuHpCpuState, ProcessorId, SmpCpuManager},
|
||||
init::smp_ap_start_stage2,
|
||||
SMPArch,
|
||||
},
|
||||
};
|
||||
|
||||
use super::{acpi::early_acpi_boot_init, CurrentIrqArch};
|
||||
use super::{
|
||||
acpi::early_acpi_boot_init,
|
||||
interrupt::ipi::{ipi_send_smp_init, ipi_send_smp_startup},
|
||||
CurrentIrqArch,
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
fn smp_ap_start_stage2();
|
||||
/// AP处理器启动时,会将CR3设置为这个值
|
||||
pub static mut __APU_START_CR3: u64;
|
||||
fn _apu_boot_start();
|
||||
fn _apu_boot_end();
|
||||
}
|
||||
|
||||
pub(super) static X86_64_SMP_MANAGER: X86_64SmpManager = X86_64SmpManager::new();
|
||||
@ -35,7 +46,17 @@ struct ApStartStackInfo {
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn smp_ap_start() -> ! {
|
||||
CurrentIrqArch::interrupt_disable();
|
||||
let vaddr = cpu_core_info[smp_get_processor_id().data() as usize].stack_start as usize;
|
||||
let vaddr = if let Some(t) = smp_cpu_manager()
|
||||
.cpuhp_state(smp_get_processor_id())
|
||||
.thread()
|
||||
{
|
||||
t.kernel_stack().stack_max_address().data() - 16
|
||||
} else {
|
||||
// 没有设置ap核心的栈,那么就进入死循环。
|
||||
loop {
|
||||
spin_loop();
|
||||
}
|
||||
};
|
||||
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
||||
let v = ApStartStackInfo { vaddr };
|
||||
smp_init_switch_stack(&v);
|
||||
@ -49,7 +70,7 @@ unsafe extern "sysv64" fn smp_init_switch_stack(st: &ApStartStackInfo) -> ! {
|
||||
jmp {stage1}
|
||||
"),
|
||||
off_rsp = const(offset_of!(ApStartStackInfo, vaddr)),
|
||||
stage1 = sym smp_ap_start_stage1,
|
||||
stage1 = sym smp_ap_start_stage1,
|
||||
options(noreturn));
|
||||
}
|
||||
|
||||
@ -66,10 +87,9 @@ unsafe extern "C" fn smp_ap_start_stage1() -> ! {
|
||||
);
|
||||
TSSManager::load_tr();
|
||||
|
||||
CurrentIrqArch::arch_ap_early_irq_init().expect("arch_ap_early_irq_init failed");
|
||||
|
||||
smp_ap_start_stage2();
|
||||
loop {
|
||||
spin_loop();
|
||||
}
|
||||
}
|
||||
|
||||
/// 多核的数据
|
||||
@ -141,10 +161,34 @@ impl X86_64SmpManager {
|
||||
pub fn build_cpu_map(&self) -> Result<(), SystemError> {
|
||||
// 参考:https://code.dragonos.org.cn/xref/linux-6.1.9/arch/ia64/kernel/smpboot.c?fi=smp_build_cpu_map#496
|
||||
// todo!("build_cpu_map")
|
||||
unsafe {
|
||||
smp_cpu_manager().set_possible_cpu(ProcessorId::new(0), true);
|
||||
smp_cpu_manager().set_present_cpu(ProcessorId::new(0), true);
|
||||
smp_cpu_manager().set_online_cpu(ProcessorId::new(0));
|
||||
}
|
||||
|
||||
for cpu in 1..SMP_BOOT_DATA.cpu_count() {
|
||||
unsafe {
|
||||
smp_cpu_manager().set_possible_cpu(ProcessorId::new(cpu as u32), true);
|
||||
smp_cpu_manager().set_present_cpu(ProcessorId::new(cpu as u32), true);
|
||||
}
|
||||
}
|
||||
|
||||
print_cpus("possible", smp_cpu_manager().possible_cpus());
|
||||
print_cpus("present", smp_cpu_manager().present_cpus());
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
fn print_cpus(s: &str, mask: &CpuMask) {
|
||||
let mut v = vec![];
|
||||
for cpu in mask.iter_cpu() {
|
||||
v.push(cpu.data());
|
||||
}
|
||||
|
||||
kdebug!("{s}: cpus: {v:?}\n");
|
||||
}
|
||||
|
||||
pub struct X86_64SMPArch;
|
||||
|
||||
impl SMPArch for X86_64SMPArch {
|
||||
@ -155,11 +199,87 @@ impl SMPArch for X86_64SMPArch {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn init() -> Result<(), SystemError> {
|
||||
x86::fence::mfence();
|
||||
unsafe { smp_init() };
|
||||
x86::fence::mfence();
|
||||
fn post_init() -> Result<(), SystemError> {
|
||||
// AP核心启动完毕,取消低地址映射
|
||||
unsafe {
|
||||
LowAddressRemapping::unmap_at_low_address(
|
||||
&mut IDLE_PROCESS_ADDRESS_SPACE()
|
||||
.write_irqsave()
|
||||
.user_mapper
|
||||
.utable,
|
||||
true,
|
||||
)
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
fn start_cpu(cpu_id: ProcessorId, _cpu_hpstate: &CpuHpCpuState) -> Result<(), SystemError> {
|
||||
kdebug!("start_cpu: cpu_id: {:#x}\n", cpu_id.data());
|
||||
|
||||
Self::copy_smp_start_code();
|
||||
|
||||
ipi_send_smp_init();
|
||||
fence(Ordering::SeqCst);
|
||||
ipi_send_smp_startup(cpu_id)?;
|
||||
fence(Ordering::SeqCst);
|
||||
ipi_send_smp_startup(cpu_id)?;
|
||||
fence(Ordering::SeqCst);
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
impl X86_64SMPArch {
|
||||
const SMP_CODE_START: usize = 0x20000;
|
||||
/// 复制SMP启动代码到0x20000处
|
||||
fn copy_smp_start_code() -> (VirtAddr, usize) {
|
||||
let apu_boot_size = Self::start_code_size();
|
||||
|
||||
fence(Ordering::SeqCst);
|
||||
unsafe {
|
||||
core::ptr::copy(
|
||||
_apu_boot_start as *const u8,
|
||||
Self::SMP_CODE_START as *mut u8,
|
||||
apu_boot_size,
|
||||
)
|
||||
};
|
||||
fence(Ordering::SeqCst);
|
||||
|
||||
return (VirtAddr::new(Self::SMP_CODE_START), apu_boot_size);
|
||||
}
|
||||
|
||||
fn start_code_size() -> usize {
|
||||
let apu_boot_start = _apu_boot_start as usize;
|
||||
let apu_boot_end = _apu_boot_end as usize;
|
||||
let apu_boot_size = apu_boot_end - apu_boot_start;
|
||||
return apu_boot_size;
|
||||
}
|
||||
}
|
||||
|
||||
impl SmpCpuManager {
|
||||
pub fn arch_init(_boot_cpu: ProcessorId) {
|
||||
assert!(smp_get_processor_id().data() == 0);
|
||||
// 写入APU_START_CR3,这个值会在AP处理器启动时设置到CR3寄存器
|
||||
let addr = IDLE_PROCESS_ADDRESS_SPACE()
|
||||
.read_irqsave()
|
||||
.user_mapper
|
||||
.utable
|
||||
.table()
|
||||
.phys();
|
||||
let vaddr = unsafe {
|
||||
MMArch::phys_2_virt(PhysAddr::new(&mut __APU_START_CR3 as *mut u64 as usize)).unwrap()
|
||||
};
|
||||
let ptr = vaddr.data() as *mut u64;
|
||||
unsafe { *ptr = addr.data() as u64 };
|
||||
|
||||
// 添加低地址映射
|
||||
unsafe {
|
||||
LowAddressRemapping::remap_at_low_address(
|
||||
&mut IDLE_PROCESS_ADDRESS_SPACE()
|
||||
.write_irqsave()
|
||||
.user_mapper
|
||||
.utable,
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,15 @@
|
||||
use crate::time::TimeArch;
|
||||
|
||||
use super::driver::tsc::TSCManager;
|
||||
|
||||
pub struct X86_64TimeArch;
|
||||
|
||||
impl TimeArch for X86_64TimeArch {
|
||||
fn get_cycles() -> usize {
|
||||
unsafe { x86::time::rdtsc() as usize }
|
||||
}
|
||||
|
||||
fn cal_expire_cycles(ns: usize) -> usize {
|
||||
Self::get_cycles() + ns * TSCManager::cpu_khz() as usize / 1000000
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user