KVM: arm64: Add helper for last ditch idreg adjustments
We already have to perform a set of last-chance adjustments for NV purposes. We will soon have to do the same for the GIC, so introduce a helper for that exact purpose. Reviewed-by: Oliver Upton <oliver.upton@linux.dev> Link: https://lore.kernel.org/r/20240827152517.3909653-5-maz@kernel.org Signed-off-by: Marc Zyngier <maz@kernel.org>
This commit is contained in:
@@ -46,6 +46,8 @@
|
||||
#include <kvm/arm_pmu.h>
|
||||
#include <kvm/arm_psci.h>
|
||||
|
||||
#include "sys_regs.h"
|
||||
|
||||
static enum kvm_mode kvm_mode = KVM_MODE_DEFAULT;
|
||||
|
||||
enum kvm_wfx_trap_policy {
|
||||
@@ -821,15 +823,13 @@ int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (vcpu_has_nv(vcpu)) {
|
||||
ret = kvm_init_nv_sysregs(vcpu->kvm);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
ret = kvm_finalize_sys_regs(vcpu);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* This needs to happen after NV has imposed its own restrictions on
|
||||
* the feature set
|
||||
* This needs to happen after any restriction has been applied
|
||||
* to the feature set.
|
||||
*/
|
||||
kvm_calculate_traps(vcpu);
|
||||
|
||||
|
||||
+5
-10
@@ -954,19 +954,16 @@ static void set_sysreg_masks(struct kvm *kvm, int sr, u64 res0, u64 res1)
|
||||
int kvm_init_nv_sysregs(struct kvm *kvm)
|
||||
{
|
||||
u64 res0, res1;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&kvm->arch.config_lock);
|
||||
lockdep_assert_held(&kvm->arch.config_lock);
|
||||
|
||||
if (kvm->arch.sysreg_masks)
|
||||
goto out;
|
||||
return 0;
|
||||
|
||||
kvm->arch.sysreg_masks = kzalloc(sizeof(*(kvm->arch.sysreg_masks)),
|
||||
GFP_KERNEL_ACCOUNT);
|
||||
if (!kvm->arch.sysreg_masks) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
if (!kvm->arch.sysreg_masks)
|
||||
return -ENOMEM;
|
||||
|
||||
limit_nv_id_regs(kvm);
|
||||
|
||||
@@ -1195,8 +1192,6 @@ int kvm_init_nv_sysregs(struct kvm *kvm)
|
||||
if (!kvm_has_feat(kvm, ID_AA64PFR0_EL1, AMU, V1P1))
|
||||
res0 |= ~(res0 | res1);
|
||||
set_sysreg_masks(kvm, HAFGRTR_EL2, res0, res1);
|
||||
out:
|
||||
mutex_unlock(&kvm->arch.config_lock);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -4620,6 +4620,29 @@ out:
|
||||
mutex_unlock(&kvm->arch.config_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform last adjustments to the ID registers that are implied by the
|
||||
* configuration outside of the ID regs themselves, as well as any
|
||||
* initialisation that directly depend on these ID registers (such as
|
||||
* RES0/RES1 behaviours). This is not the place to configure traps though.
|
||||
*
|
||||
* Because this can be called once per CPU, changes must be idempotent.
|
||||
*/
|
||||
int kvm_finalize_sys_regs(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm *kvm = vcpu->kvm;
|
||||
|
||||
guard(mutex)(&kvm->arch.config_lock);
|
||||
|
||||
if (vcpu_has_nv(vcpu)) {
|
||||
int ret = kvm_init_nv_sysregs(kvm);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init kvm_sys_reg_table_init(void)
|
||||
{
|
||||
bool valid = true;
|
||||
|
||||
@@ -235,6 +235,8 @@ int kvm_sys_reg_set_user(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg,
|
||||
|
||||
bool triage_sysreg_trap(struct kvm_vcpu *vcpu, int *sr_index);
|
||||
|
||||
int kvm_finalize_sys_regs(struct kvm_vcpu *vcpu);
|
||||
|
||||
#define AA32(_x) .aarch32_map = AA32_##_x
|
||||
#define Op0(_x) .Op0 = _x
|
||||
#define Op1(_x) .Op1 = _x
|
||||
|
||||
Reference in New Issue
Block a user