cpu.rs 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. use alloc::vec::Vec;
  2. use crate::{
  3. init::boot_params,
  4. kdebug,
  5. mm::percpu::{PerCpu, PerCpuVar},
  6. smp::cpu::{ProcessorId, SmpCpuManager},
  7. };
  8. /// 获取当前cpu的id
  9. #[inline]
  10. pub fn current_cpu_id() -> ProcessorId {
  11. let ptr: *const LocalContext = riscv::register::sscratch::read() as *const LocalContext;
  12. if core::intrinsics::unlikely(ptr.is_null()) {
  13. return boot_params().read_irqsave().arch.boot_hartid;
  14. }
  15. unsafe { (*ptr).current_cpu() }
  16. }
  17. /// 重置cpu
  18. pub unsafe fn cpu_reset() -> ! {
  19. sbi_rt::system_reset(sbi_rt::WarmReboot, sbi_rt::NoReason);
  20. unimplemented!("RiscV64 reset failed, manual override expected ...")
  21. }
  22. static mut LOCAL_CONTEXT: Option<PerCpuVar<LocalContext>> = None;
  23. #[inline(always)]
  24. pub(super) fn local_context() -> &'static PerCpuVar<LocalContext> {
  25. unsafe { LOCAL_CONTEXT.as_ref().unwrap() }
  26. }
  27. /// Per cpu的上下文数据
  28. ///
  29. /// 每个CPU的sscratch寄存器指向这个结构体
  30. #[derive(Debug)]
  31. pub(super) struct LocalContext {
  32. /// 当前cpu的id
  33. current_cpu: ProcessorId,
  34. }
  35. impl LocalContext {
  36. fn new(cpu: ProcessorId) -> Self {
  37. Self { current_cpu: cpu }
  38. }
  39. pub fn current_cpu(&self) -> ProcessorId {
  40. self.current_cpu
  41. }
  42. pub fn set_current_cpu(&mut self, cpu: ProcessorId) {
  43. self.current_cpu = cpu;
  44. }
  45. fn sync_to_cpu(&self) {
  46. let ptr = self as *const Self as usize;
  47. riscv::register::sscratch::write(ptr);
  48. }
  49. }
  50. /// 初始化本地上下文
  51. #[inline(never)]
  52. pub(super) fn init_local_context() {
  53. kdebug!("init_local_context");
  54. let mut data = Vec::new();
  55. for i in 0..PerCpu::MAX_CPU_NUM {
  56. data.push(LocalContext::new(ProcessorId::new(i)));
  57. }
  58. let ctx = PerCpuVar::new(data).unwrap();
  59. unsafe {
  60. LOCAL_CONTEXT = Some(ctx);
  61. }
  62. let hartid = boot_params().read().arch.boot_hartid;
  63. let ctx = unsafe { local_context().force_get(hartid) };
  64. ctx.sync_to_cpu();
  65. }
  66. impl SmpCpuManager {
  67. pub fn arch_init(boot_cpu: ProcessorId) {
  68. // todo: 读取所有可用的CPU
  69. }
  70. }