From dac5c982c38a1787a7633bfa0f0280e4b496bc82 Mon Sep 17 00:00:00 2001 From: Jon Lange Date: Wed, 11 Dec 2024 13:22:06 -0800 Subject: [PATCH] cpu: record an address of `PerCpuShared` that is globally valid The address of a `PerCpuShared` as observed by the local CPU is different than the address of the same `PerCpuShared` observed by other CPUs in the global address space. There are cases where a local CPU needs to know the address that will be used by other CPUs. Signed-off-by: Jon Lange --- kernel/src/cpu/percpu.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/kernel/src/cpu/percpu.rs b/kernel/src/cpu/percpu.rs index e4d75c1ec..15e630c28 100644 --- a/kernel/src/cpu/percpu.rs +++ b/kernel/src/cpu/percpu.rs @@ -322,6 +322,10 @@ pub struct PerCpu { /// Per-CPU storage that might be accessed from other CPUs. shared: PerCpuShared, + /// Reference to the `PerCpuShared` that is valid in the global, shared + /// address space. + shared_global: OnceCell<&'static PerCpuShared>, + /// PerCpu IRQ state tracking irq_state: IrqState, @@ -383,6 +387,7 @@ impl PerCpu { apic: RefCell::new(None), shared: PerCpuShared::new(apic_id, cpu_index), + shared_global: OnceCell::new(), ghcb: OnceCell::new(), hypercall_pages: RefCell::new(None), hv_doorbell: Cell::new(None), @@ -401,6 +406,7 @@ impl PerCpu { let cpu_index = PERCPU_AREAS.next_cpu_index(); let page = PageBox::try_new(Self::new(apic_id, cpu_index))?; let percpu = PageBox::leak(page); + percpu.set_shared_global(); unsafe { PERCPU_AREAS.push(PerCpuInfo::new(apic_id, &percpu.shared)) }; Ok(percpu) } @@ -409,6 +415,14 @@ impl PerCpu { &self.shared } + fn set_shared_global(&'static self) { + self.shared_global.set(&self.shared).expect("shared global set more than once"); + } + + pub fn shared_global(&self) -> &'static PerCpuShared { + self.shared_global.get().unwrap() + } + /// Disables IRQs on the current CPU. Keeps track of the nesting level and /// the original IRQ state. ///