ANDROID: KVM: arm64: Fix initializing traps in protected mode

The values of the trapping registers for protected VMs should be
computed from the ground up, and not depend on potentially
preexisting values.

Moreover, non-protected VMs should not be restricted in protected
mode in the same manner as protected VMs.

Signed-off-by: Fuad Tabba <tabba@google.com>
Signed-off-by: Will Deacon <willdeacon@google.com>
Bug: 233587962
Change-Id: I689c6d48e8ebb533a86b78ebd6e1a1416cb8729b
This commit is contained in:
Fuad Tabba
2022-04-27 09:47:55 +00:00
committed by Will Deacon
parent cab2379b5e
commit 82e11002e1

View File

@@ -168,34 +168,49 @@ static void pvm_init_traps_aa64mmfr1(struct kvm_vcpu *vcpu)
*/
static void pvm_init_trap_regs(struct kvm_vcpu *vcpu)
{
const u64 hcr_trap_feat_regs = HCR_TID3;
const u64 hcr_trap_impdef = HCR_TACR | HCR_TIDCP | HCR_TID1;
/*
* Always trap:
* - Feature id registers: to control features exposed to guests
* - Implementation-defined features
*/
vcpu->arch.hcr_el2 |= hcr_trap_feat_regs | hcr_trap_impdef;
vcpu->arch.hcr_el2 = HCR_GUEST_FLAGS |
HCR_TID3 | HCR_TACR | HCR_TIDCP | HCR_TID1;
/* Clear res0 and set res1 bits to trap potential new features. */
vcpu->arch.hcr_el2 &= ~(HCR_RES0);
vcpu->arch.mdcr_el2 &= ~(MDCR_EL2_RES0);
vcpu->arch.cptr_el2 |= CPTR_NVHE_EL2_RES1;
vcpu->arch.cptr_el2 &= ~(CPTR_NVHE_EL2_RES0);
if (cpus_have_const_cap(ARM64_HAS_RAS_EXTN)) {
/* route synchronous external abort exceptions to EL2 */
vcpu->arch.hcr_el2 |= HCR_TEA;
/* trap error record accesses */
vcpu->arch.hcr_el2 |= HCR_TERR;
}
if (cpus_have_const_cap(ARM64_HAS_STAGE2_FWB))
vcpu->arch.hcr_el2 |= HCR_FWB;
if (cpus_have_const_cap(ARM64_MISMATCHED_CACHE_TYPE))
vcpu->arch.hcr_el2 |= HCR_TID2;
}
/*
* Initialize trap register values for protected VMs.
*/
static void pkvm_vcpu_init_traps(struct kvm_vcpu *vcpu)
static void pkvm_vcpu_init_traps(struct pkvm_hyp_vcpu *hyp_vcpu)
{
pvm_init_trap_regs(vcpu);
pvm_init_traps_aa64pfr0(vcpu);
pvm_init_traps_aa64pfr1(vcpu);
pvm_init_traps_aa64dfr0(vcpu);
pvm_init_traps_aa64mmfr0(vcpu);
pvm_init_traps_aa64mmfr1(vcpu);
hyp_vcpu->vcpu.arch.cptr_el2 = CPTR_EL2_DEFAULT;
hyp_vcpu->vcpu.arch.mdcr_el2 = 0;
if (!pkvm_hyp_vcpu_is_protected(hyp_vcpu)) {
u64 hcr = READ_ONCE(hyp_vcpu->host_vcpu->arch.hcr_el2);
hyp_vcpu->vcpu.arch.hcr_el2 = HCR_GUEST_FLAGS | hcr;
return;
}
pvm_init_trap_regs(&hyp_vcpu->vcpu);
pvm_init_traps_aa64pfr0(&hyp_vcpu->vcpu);
pvm_init_traps_aa64pfr1(&hyp_vcpu->vcpu);
pvm_init_traps_aa64dfr0(&hyp_vcpu->vcpu);
pvm_init_traps_aa64mmfr0(&hyp_vcpu->vcpu);
pvm_init_traps_aa64mmfr1(&hyp_vcpu->vcpu);
}
/*
@@ -349,7 +364,7 @@ static int init_pkvm_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu,
hyp_vcpu->vcpu.arch.hw_mmu = &hyp_vm->kvm.arch.mmu;
hyp_vcpu->vcpu.arch.cflags = READ_ONCE(host_vcpu->arch.cflags);
pkvm_vcpu_init_traps(&hyp_vcpu->vcpu);
pkvm_vcpu_init_traps(hyp_vcpu);
done:
if (ret)
unpin_host_vcpu(host_vcpu);