mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
KVM/arm64 fixes for 7.1, take #5
- Correctly drop the ITS translation cache reference when it actually gets invalidated - Take the SRCU lock for SW page table walks - Restore POR_EL0 access to host EL0, avoiding POR_EL0 becoming inaccessible from EL0 after running a guest - Reassign nested_mmus array behind mmu_lock, ensuring that vcpu init and MMU notifiers are mutually exclusive - Correctly handle FEAT_XNX at stage-2 -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEn9UcU+C1Yxj9lZw9I9DQutE9ekMFAmoi9m8ACgkQI9DQutE9 ekMOqRAAwCXKfCTXWTbWVrzyPvkHHktQUnUANY262VxFmOzvIlxONu0zQK/Saagl YMJ/nfLbwI4Cz2sLeBplxcyh8dVoc6EglDbB+d+7gXIJWVxA5ToM3yt1Yn+g4hpc 4LTIapANeIDlQ+Z8PyR2WdEdo9a89j9qs+goBgscjHF85N2Qh10G3wioeCGQVTYw Z1woVhyx4VlcUOPWYS3Ws3yqbICousxe5zsKLXb2v5nybauBS7fjh7ACbX2pBlmi X4Pip4vIyfv0hyq5rdvcb/m8pjXgXrrdaZ2pJpvm2ioa5MAQ1SvvHo+HDsOPuoCl p0TlDARd9JpMZdNko5/3qmAmMlE2ap9Qqh7zaAlxt/THoI/0G/7NOaKBclGcp/nw +KjDEFriws2Yeqce+Tl8pF0/MBCmNV61BVSa91xGG3pRdxThV/NCxD4oRWLCDMRJ 3UEAwNVV6FZW7rAbdzlG/spjmloMGPzWq4Mg+iu6BunfOBI6RlabHlRqhaU8SZ/O dX82lzfCpouikgETSJNi7Ta/aCBDWLeuM01TuZ05RO5vCfTdB50SFlmXMRO5zjR0 tVCKg5roKkVd2D81g/kssehpGgOsiBqqiNK7LMYhxzEMC0aySobrtbbq6KT0RVez fbQsrLvFFVGUAMp3k84s2BF+K7EXUh98GgqLerwbg2mp7UhqpW0= =8bS2 -----END PGP SIGNATURE----- Merge tag 'kvmarm-fixes-7.1-5' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm into HEAD KVM/arm64 fixes for 7.1, take #5 - Correctly drop the ITS translation cache reference when it actually gets invalidated - Take the SRCU lock for SW page table walks - Restore POR_EL0 access to host EL0, avoiding POR_EL0 becoming inaccessible from EL0 after running a guest - Reassign nested_mmus array behind mmu_lock, ensuring that vcpu init and MMU notifiers are mutually exclusive - Correctly handle FEAT_XNX at stage-2
This commit is contained in:
commit
7ec0360122
|
|
@ -132,7 +132,7 @@ static inline bool kvm_s2_trans_exec_el0(struct kvm *kvm, struct kvm_s2_trans *t
|
|||
u8 xn = FIELD_GET(KVM_PTE_LEAF_ATTR_HI_S2_XN, trans->desc);
|
||||
|
||||
if (!kvm_has_xnx(kvm))
|
||||
xn &= FIELD_PREP(KVM_PTE_LEAF_ATTR_HI_S2_XN, 0b10);
|
||||
xn &= 0b10;
|
||||
|
||||
switch (xn) {
|
||||
case 0b00:
|
||||
|
|
@ -148,7 +148,7 @@ static inline bool kvm_s2_trans_exec_el1(struct kvm *kvm, struct kvm_s2_trans *t
|
|||
u8 xn = FIELD_GET(KVM_PTE_LEAF_ATTR_HI_S2_XN, trans->desc);
|
||||
|
||||
if (!kvm_has_xnx(kvm))
|
||||
xn &= FIELD_PREP(KVM_PTE_LEAF_ATTR_HI_S2_XN, 0b10);
|
||||
xn &= 0b10;
|
||||
|
||||
switch (xn) {
|
||||
case 0b00:
|
||||
|
|
|
|||
|
|
@ -1569,7 +1569,8 @@ int __kvm_at_s12(struct kvm_vcpu *vcpu, u32 op, u64 vaddr)
|
|||
/* Do the stage-2 translation */
|
||||
ipa = (par & GENMASK_ULL(47, 12)) | (vaddr & GENMASK_ULL(11, 0));
|
||||
out.esr = 0;
|
||||
ret = kvm_walk_nested_s2(vcpu, ipa, &out);
|
||||
scoped_guard(srcu, &vcpu->kvm->srcu)
|
||||
ret = kvm_walk_nested_s2(vcpu, ipa, &out);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
|
@ -1665,7 +1666,8 @@ int __kvm_find_s1_desc_level(struct kvm_vcpu *vcpu, u64 va, u64 ipa, int *level)
|
|||
}
|
||||
|
||||
/* Walk the guest's PT, looking for a match along the way */
|
||||
ret = walk_s1(vcpu, &wi, &wr, va);
|
||||
scoped_guard(srcu, &vcpu->kvm->srcu)
|
||||
ret = walk_s1(vcpu, &wi, &wr, va);
|
||||
switch (ret) {
|
||||
case -EINTR:
|
||||
/* We interrupted the walk on a match, return the level */
|
||||
|
|
|
|||
|
|
@ -181,6 +181,8 @@ static inline void __deactivate_cptr_traps_vhe(struct kvm_vcpu *vcpu)
|
|||
val |= CPACR_EL1_ZEN;
|
||||
if (cpus_have_final_cap(ARM64_SME))
|
||||
val |= CPACR_EL1_SMEN;
|
||||
if (cpus_have_final_cap(ARM64_HAS_S1POE))
|
||||
val |= CPACR_EL1_E0POE;
|
||||
|
||||
write_sysreg(val, cpacr_el1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -925,7 +925,9 @@ static bool stage2_pte_cacheable(struct kvm_pgtable *pgt, kvm_pte_t pte)
|
|||
|
||||
static bool stage2_pte_executable(kvm_pte_t pte)
|
||||
{
|
||||
return kvm_pte_valid(pte) && !(pte & KVM_PTE_LEAF_ATTR_HI_S2_XN);
|
||||
enum kvm_pgtable_prot prot = kvm_pgtable_stage2_pte_prot(pte);
|
||||
|
||||
return prot & (KVM_PGTABLE_PROT_UX | KVM_PGTABLE_PROT_PX);
|
||||
}
|
||||
|
||||
static u64 stage2_map_walker_phys_addr(const struct kvm_pgtable_visit_ctx *ctx,
|
||||
|
|
|
|||
|
|
@ -89,21 +89,28 @@ int kvm_vcpu_init_nested(struct kvm_vcpu *vcpu)
|
|||
* again, and there is no reason to affect the whole VM for this.
|
||||
*/
|
||||
num_mmus = atomic_read(&kvm->online_vcpus) * S2_MMU_PER_VCPU;
|
||||
tmp = kvrealloc(kvm->arch.nested_mmus,
|
||||
size_mul(sizeof(*kvm->arch.nested_mmus), num_mmus),
|
||||
GFP_KERNEL_ACCOUNT | __GFP_ZERO);
|
||||
if (!tmp)
|
||||
return -ENOMEM;
|
||||
|
||||
swap(kvm->arch.nested_mmus, tmp);
|
||||
if (num_mmus > kvm->arch.nested_mmus_size) {
|
||||
tmp = kvcalloc(num_mmus, sizeof(*tmp), GFP_KERNEL_ACCOUNT);
|
||||
if (!tmp)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* If we went through a realocation, adjust the MMU back-pointers in
|
||||
* the previously initialised kvm_pgtable structures.
|
||||
*/
|
||||
if (kvm->arch.nested_mmus != tmp)
|
||||
for (int i = 0; i < kvm->arch.nested_mmus_size; i++)
|
||||
kvm->arch.nested_mmus[i].pgt->mmu = &kvm->arch.nested_mmus[i];
|
||||
write_lock(&kvm->mmu_lock);
|
||||
|
||||
if (kvm->arch.nested_mmus_size) {
|
||||
memcpy(tmp, kvm->arch.nested_mmus,
|
||||
size_mul(sizeof(*tmp), kvm->arch.nested_mmus_size));
|
||||
|
||||
for (int i = 0; i < kvm->arch.nested_mmus_size; i++)
|
||||
tmp[i].pgt->mmu = &tmp[i];
|
||||
}
|
||||
|
||||
swap(kvm->arch.nested_mmus, tmp);
|
||||
|
||||
write_unlock(&kvm->mmu_lock);
|
||||
|
||||
kvfree(tmp);
|
||||
}
|
||||
|
||||
for (int i = kvm->arch.nested_mmus_size; !ret && i < num_mmus; i++)
|
||||
ret = init_nested_s2_mmu(kvm, &kvm->arch.nested_mmus[i]);
|
||||
|
|
|
|||
|
|
@ -597,8 +597,10 @@ static void vgic_its_invalidate_cache(struct vgic_its *its)
|
|||
unsigned long idx;
|
||||
|
||||
xa_for_each(&its->translation_cache, idx, irq) {
|
||||
xa_erase(&its->translation_cache, idx);
|
||||
vgic_put_irq(kvm, irq);
|
||||
/* Only the context that erases the entry drops its cache ref. */
|
||||
irq = xa_erase(&its->translation_cache, idx);
|
||||
if (irq)
|
||||
vgic_put_irq(kvm, irq);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user