| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- use core::pin::Pin;
- use riscv::register::{
- mhartid,
- sscratch,
- sstatus
- };
- use sbi::PhysicalAddress;
- use eonix_preempt::PreemptGuard;
- use eonix_sync_base::LazyLock;
- /// TODO:
- /// CPU 的一些函数
- ///
- #[eonix_percpu::define_percpu]
- static LOCAL_CPU: LazyLock<CPU> = LazyLock::new(CPU::new);
- use super::{
- config::smp::get_num_harts,
- mm::setup_kernel_satp,
- trap::setup_kernel_trap,
- interrupt::InterruptControl
- };
- #[derive(Debug, Clone)]
- pub enum UserTLS {
- Base(u32),
- }
- /// RISC-V Hart
- pub struct CPU {
- hart_id: usize,
- interrupt: InterruptControl,
- }
- impl UserTLS {
- #[allow(unused_variables)]
- pub fn new32(base: u32, _limit: u32, _is_limit_in_pages: bool) -> (Self, u32) {
- (Self::Base(base), 0)
- }
- }
- impl CPU {
- pub fn new() -> Self {
- let hart_id = read_hart_id();
- Self {
- hart_id: hart_id,
- interrupt: InterruptControl::new(hart_id),
- }
- }
- /// Load CPU specific configurations for the current Hart.
- ///
- /// # Safety
- /// This function performs low-level hardware initialization and should
- /// only be called once per Hart during its boot sequence.
- pub unsafe fn init(self: Pin<&mut Self>) {
- let self_mut = self.get_unchecked_mut();
- sscratch::write(self_mut.hart_id as usize);
- setup_kernel_trap();
- // CLINT, 10_000 ms
- self_mut.interrupt.setup_timer(10_000);
- // Supervisor Mode Status Register (sstatus)
- // SUM (Supervisor User Memory access): support S-mode access user memory
- // MXR (Make Executable Readable)
- // SIE (Supervisor Interrupt Enable): enable S-mode interrupt
- let mut current_sstatus = sstatus::read();
- current_sstatus.set_spp(sstatus::SPP::Supervisor);
- current_sstatus.set_sum(true);
- current_sstatus.set_mxr(true);
- current_sstatus.set_sie(true);
- sstatus::write(current_sstatus);
- // setup kernel page table and flush tlb
- setup_kernel_satp();
- }
- /// Boot all other hart.
- pub unsafe fn bootstrap_cpus(&self) {
- unsafe extern "C" {
- fn ap_boot_entry();
- }
- let total_harts = get_num_harts();
- let ap_entry_point = PhysicalAddress::new(ap_boot_entry as usize);
- for i in 1..total_harts {
- sbi::hsm::hart_start(i, ap_entry_point, 0)
- .expect("Failed to start secondary hart via SBI");
- }
- }
- // TODO:
- pub unsafe fn load_interrupt_stack(self: Pin<&mut Self>, rsp: u64) {
- /*unsafe {
- self.map_unchecked_mut(|me| &mut me.tss).set_rsp0(rsp);
- }*/
- }
- pub fn end_of_interrupt(self: Pin<&mut Self>) {
- unsafe {
- // TODO: 不知道写的对不对。。。
- self.map_unchecked_mut(|me| &mut me.interrupt)
- .clear_soft_interrupt_pending();
- }
- }
- pub fn local() -> PreemptGuard<Pin<&'static mut Self>> {
- unsafe {
- // SAFETY: We pass the reference into a `PreemptGuard`, which ensures
- // that preemption is disabled.
- PreemptGuard::new(Pin::new_unchecked(LOCAL_CPU.as_mut().get_mut()))
- }
- }
- pub fn cpuid(&self) -> usize {
- self.hart_id
- }
- }
- fn read_hart_id() -> usize {
- mhartid::read()
- }
- #[macro_export]
- macro_rules! define_smp_bootstrap {
- ($cpu_count:literal, $ap_entry:ident, $alloc_kstack:tt) => {
- #[no_mangle]
- static BOOT_SEMAPHORE: core::sync::atomic::AtomicU64 =
- core::sync::atomic::AtomicU64::new(0);
- #[no_mangle]
- static BOOT_STACK: core::sync::atomic::AtomicU64 =
- core::sync::atomic::AtomicU64::new(0);
- #[no_mangle]
- static CPU_COUNT: core::sync::atomic::AtomicU64 =
- core::sync::atomic::AtomicU64::new(0);
- core::arch::global_asm!(
- r#"
- .section .text.ap_boot
- .globl ap_boot_entry
- ap_boot_entry:
- csrr a0, mhartid
- 1:
- lw t0, AP_BOOT_STACK.addr
- beqz t0, 1b
- li t1, 0
- sw t1, AP_BOOT_STACK.addr
- mv sp, t0
- 2:
- lw t0, AP_BOOT_SEMAPHORE.addr
- beqz t0, 2b
- li t1, 0
- sw t1, AP_BOOT_SEMAPHORE.addr
- li t0, 1
- amoswap.w.aq rl t0, a0, ONLINE_HART_COUNT.addr
- call $ap_entry
- j .
- "#,
- BOOT_SEMAPHORE = sym BOOT_SEMAPHORE,
- BOOT_STACK = sym BOOT_STACK,
- CPU_COUNT = sym CPU_COUNT,
- AP_ENTRY = sym $ap_entry,
- );
- pub unsafe fn wait_cpus_online() {
- use core::sync::atomic::Ordering;
- while CPU_COUNT.load(Ordering::Acquire) != $cpu_count - 1 {
- if BOOT_STACK.load(Ordering::Acquire) == 0 {
- let stack_bottom = $alloc_kstack as u64;
- BOOT_STACK.store(stack_bottom, Ordering::Release);
- }
- $crate::pause();
- }
- }
- };
- }
|