cpu.rs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. use core::pin::Pin;
  2. use riscv::register::{
  3. mhartid,
  4. sscratch,
  5. sstatus
  6. };
  7. use sbi::PhysicalAddress;
  8. use eonix_preempt::PreemptGuard;
  9. use eonix_sync_base::LazyLock;
  10. /// TODO:
  11. /// CPU 的一些函数
  12. ///
  13. #[eonix_percpu::define_percpu]
  14. static LOCAL_CPU: LazyLock<CPU> = LazyLock::new(CPU::new);
  15. use super::{
  16. config::smp::get_num_harts,
  17. mm::setup_kernel_satp,
  18. trap::setup_kernel_trap,
  19. interrupt::InterruptControl
  20. };
  21. #[derive(Debug, Clone)]
  22. pub enum UserTLS {
  23. Base(u32),
  24. }
  25. /// RISC-V Hart
  26. pub struct CPU {
  27. hart_id: usize,
  28. interrupt: InterruptControl,
  29. }
  30. impl UserTLS {
  31. #[allow(unused_variables)]
  32. pub fn new32(base: u32, _limit: u32, _is_limit_in_pages: bool) -> (Self, u32) {
  33. (Self::Base(base), 0)
  34. }
  35. }
  36. impl CPU {
  37. pub fn new() -> Self {
  38. let hart_id = read_hart_id();
  39. Self {
  40. hart_id: hart_id,
  41. interrupt: InterruptControl::new(hart_id),
  42. }
  43. }
  44. /// Load CPU specific configurations for the current Hart.
  45. ///
  46. /// # Safety
  47. /// This function performs low-level hardware initialization and should
  48. /// only be called once per Hart during its boot sequence.
  49. pub unsafe fn init(self: Pin<&mut Self>) {
  50. let self_mut = self.get_unchecked_mut();
  51. sscratch::write(self_mut.hart_id as usize);
  52. setup_kernel_trap();
  53. // CLINT, 10_000 ms
  54. self_mut.interrupt.setup_timer(10_000);
  55. // Supervisor Mode Status Register (sstatus)
  56. // SUM (Supervisor User Memory access): support S-mode access user memory
  57. // MXR (Make Executable Readable)
  58. // SIE (Supervisor Interrupt Enable): enable S-mode interrupt
  59. let mut current_sstatus = sstatus::read();
  60. current_sstatus.set_spp(sstatus::SPP::Supervisor);
  61. current_sstatus.set_sum(true);
  62. current_sstatus.set_mxr(true);
  63. current_sstatus.set_sie(true);
  64. sstatus::write(current_sstatus);
  65. // setup kernel page table and flush tlb
  66. setup_kernel_satp();
  67. }
  68. /// Boot all other hart.
  69. pub unsafe fn bootstrap_cpus(&self) {
  70. unsafe extern "C" {
  71. fn ap_boot_entry();
  72. }
  73. let total_harts = get_num_harts();
  74. let ap_entry_point = PhysicalAddress::new(ap_boot_entry as usize);
  75. for i in 1..total_harts {
  76. sbi::hsm::hart_start(i, ap_entry_point, 0)
  77. .expect("Failed to start secondary hart via SBI");
  78. }
  79. }
  80. // TODO:
  81. pub unsafe fn load_interrupt_stack(self: Pin<&mut Self>, rsp: u64) {
  82. /*unsafe {
  83. self.map_unchecked_mut(|me| &mut me.tss).set_rsp0(rsp);
  84. }*/
  85. }
  86. pub fn end_of_interrupt(self: Pin<&mut Self>) {
  87. unsafe {
  88. // TODO: 不知道写的对不对。。。
  89. self.map_unchecked_mut(|me| &mut me.interrupt)
  90. .clear_soft_interrupt_pending();
  91. }
  92. }
  93. pub fn local() -> PreemptGuard<Pin<&'static mut Self>> {
  94. unsafe {
  95. // SAFETY: We pass the reference into a `PreemptGuard`, which ensures
  96. // that preemption is disabled.
  97. PreemptGuard::new(Pin::new_unchecked(LOCAL_CPU.as_mut().get_mut()))
  98. }
  99. }
  100. pub fn cpuid(&self) -> usize {
  101. self.hart_id
  102. }
  103. }
  104. fn read_hart_id() -> usize {
  105. mhartid::read()
  106. }
  107. #[macro_export]
  108. macro_rules! define_smp_bootstrap {
  109. ($cpu_count:literal, $ap_entry:ident, $alloc_kstack:tt) => {
  110. #[no_mangle]
  111. static BOOT_SEMAPHORE: core::sync::atomic::AtomicU64 =
  112. core::sync::atomic::AtomicU64::new(0);
  113. #[no_mangle]
  114. static BOOT_STACK: core::sync::atomic::AtomicU64 =
  115. core::sync::atomic::AtomicU64::new(0);
  116. #[no_mangle]
  117. static CPU_COUNT: core::sync::atomic::AtomicU64 =
  118. core::sync::atomic::AtomicU64::new(0);
  119. core::arch::global_asm!(
  120. r#"
  121. .section .text.ap_boot
  122. .globl ap_boot_entry
  123. ap_boot_entry:
  124. csrr a0, mhartid
  125. 1:
  126. lw t0, AP_BOOT_STACK.addr
  127. beqz t0, 1b
  128. li t1, 0
  129. sw t1, AP_BOOT_STACK.addr
  130. mv sp, t0
  131. 2:
  132. lw t0, AP_BOOT_SEMAPHORE.addr
  133. beqz t0, 2b
  134. li t1, 0
  135. sw t1, AP_BOOT_SEMAPHORE.addr
  136. li t0, 1
  137. amoswap.w.aq rl t0, a0, ONLINE_HART_COUNT.addr
  138. call $ap_entry
  139. j .
  140. "#,
  141. BOOT_SEMAPHORE = sym BOOT_SEMAPHORE,
  142. BOOT_STACK = sym BOOT_STACK,
  143. CPU_COUNT = sym CPU_COUNT,
  144. AP_ENTRY = sym $ap_entry,
  145. );
  146. pub unsafe fn wait_cpus_online() {
  147. use core::sync::atomic::Ordering;
  148. while CPU_COUNT.load(Ordering::Acquire) != $cpu_count - 1 {
  149. if BOOT_STACK.load(Ordering::Acquire) == 0 {
  150. let stack_bottom = $alloc_kstack as u64;
  151. BOOT_STACK.store(stack_bottom, Ordering::Release);
  152. }
  153. $crate::pause();
  154. }
  155. }
  156. };
  157. }