Re: [PATCH v4 09/10] kvm: arm64: Set up hyp percpu data for nVHE

From: Will Deacon
Date: Tue Sep 29 2020 - 13:50:21 EST


On Tue, Sep 22, 2020 at 09:49:09PM +0100, David Brazdil wrote:
> Add hyp percpu section to linker script and rename the corresponding ELF
> sections of hyp/nvhe object files. This moves all nVHE-specific percpu
> variables to the new hyp percpu section.
>
> Allocate sufficient amount of memory for all percpu hyp regions at global KVM
> init time and create corresponding hyp mappings.
>
> The base addresses of hyp percpu regions are kept in a dynamically allocated
> array in the kernel.
>
> Add NULL checks in PMU event-reset code as it may run before KVM memory is
> initialized.
>
> Signed-off-by: David Brazdil <dbrazdil@xxxxxxxxxx>
> ---
> arch/arm64/include/asm/kvm_asm.h | 19 +++++++++--
> arch/arm64/kernel/vmlinux.lds.S | 8 +++++
> arch/arm64/kvm/arm.c | 55 +++++++++++++++++++++++++++++--
> arch/arm64/kvm/hyp/nvhe/hyp.lds.S | 6 ++++
> arch/arm64/kvm/pmu.c | 5 ++-
> 5 files changed, 87 insertions(+), 6 deletions(-)

Acked-by: Will Deacon <will@xxxxxxxxxx>

But one comment for Marc below...

> diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
> index 911d91787fa0..863f669d4dc8 100644
> --- a/arch/arm64/include/asm/kvm_asm.h
> +++ b/arch/arm64/include/asm/kvm_asm.h
> @@ -66,8 +66,19 @@
> #define CHOOSE_VHE_SYM(sym) sym
> #define CHOOSE_NVHE_SYM(sym) kvm_nvhe_sym(sym)
>
> -#define this_cpu_ptr_nvhe_sym(sym) this_cpu_ptr(&kvm_nvhe_sym(sym))
> -#define per_cpu_ptr_nvhe_sym(sym, cpu) per_cpu_ptr(&kvm_nvhe_sym(sym), cpu)
> +/*
> + * Compute pointer to a symbol defined in nVHE percpu region.
> + * Returns NULL if percpu memory has not been allocated yet.
> + */
> +#define this_cpu_ptr_nvhe_sym(sym) per_cpu_ptr_nvhe_sym(sym, smp_processor_id())
> +#define per_cpu_ptr_nvhe_sym(sym, cpu) \
> + ({ \
> + unsigned long base, off; \
> + base = kvm_arm_hyp_percpu_base[cpu]; \
> + off = (unsigned long)&CHOOSE_NVHE_SYM(sym) - \
> + (unsigned long)&CHOOSE_NVHE_SYM(__per_cpu_start); \
> + base ? (typeof(CHOOSE_NVHE_SYM(sym))*)(base + off) : NULL; \
> + })
>
> #ifndef __KVM_NVHE_HYPERVISOR__
> /*
> @@ -117,6 +128,10 @@ DECLARE_KVM_HYP_SYM(__kvm_hyp_vector);
> #define __kvm_hyp_init CHOOSE_NVHE_SYM(__kvm_hyp_init)
> #define __kvm_hyp_vector CHOOSE_HYP_SYM(__kvm_hyp_vector)
>
> +extern unsigned long kvm_arm_hyp_percpu_base[NR_CPUS];
> +DECLARE_KVM_NVHE_SYM(__per_cpu_start);
> +DECLARE_KVM_NVHE_SYM(__per_cpu_end);
> +
> #ifdef CONFIG_KVM_INDIRECT_VECTORS
> extern atomic_t arm64_el2_vector_last_slot;
> DECLARE_KVM_HYP_SYM(__bp_harden_hyp_vecs);

The changes in this file will collide quite badly with Andrew's "handler"
branch which you've already queued, so you'll probably want to chat with
Andrew and David when you get to resolve that. In particular, I think it
would be good if the this_cpu_ptr_nvhe_sym() macro only ends up in the EL1
block, since I don't think that its use of smp_processor_id() is safe at
EL2. That's not a problem as it stands, as its only used by the host.

Will