Skip to content

Commit 16dbe77

Browse files
LeviYeoReumctmarinas
authored andcommitted
KVM: arm64: Use CAST instruction for swapping guest descriptor
Use the CAST instruction to swap the guest descriptor when FEAT_LSUI is enabled, avoiding the need to clear the PAN bit. FEAT_LSUI is introduced in Armv9.6, where FEAT_PAN is mandatory. However, this assumption may not always hold: - Some CPUs may advertise FEAT_LSUI but lack FEAT_PAN. - Virtualization or ID register overrides may expose invalid feature combinations. Therefore, instead of disabling FEAT_LSUI when FEAT_PAN is absent, wrap LSUI instructions with uaccess_ttbr0_enable()/disable() when ARM64_SW_TTBR0_PAN is enabled. Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com> Reviewed-by: Marc Zyngier <maz@kernel.org> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
1 parent 44adf2b commit 16dbe77

1 file changed

Lines changed: 33 additions & 1 deletion

File tree

arch/arm64/kvm/at.c

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <asm/esr.h>
1010
#include <asm/kvm_hyp.h>
1111
#include <asm/kvm_mmu.h>
12+
#include <asm/lsui.h>
1213

1314
static void fail_s1_walk(struct s1_walk_result *wr, u8 fst, bool s1ptw)
1415
{
@@ -1681,6 +1682,35 @@ int __kvm_find_s1_desc_level(struct kvm_vcpu *vcpu, u64 va, u64 ipa, int *level)
16811682
}
16821683
}
16831684

1685+
static int __lsui_swap_desc(u64 __user *ptep, u64 old, u64 new)
1686+
{
1687+
u64 tmp = old;
1688+
int ret = 0;
1689+
1690+
/*
1691+
* Wrap LSUI instructions with uaccess_ttbr0_enable()/disable(),
1692+
* as PAN toggling is not required.
1693+
*/
1694+
uaccess_ttbr0_enable();
1695+
1696+
asm volatile(__LSUI_PREAMBLE
1697+
"1: cast %[old], %[new], %[addr]\n"
1698+
"2:\n"
1699+
_ASM_EXTABLE_UACCESS_ERR(1b, 2b, %w[ret])
1700+
: [old] "+r" (old), [addr] "+Q" (*ptep), [ret] "+r" (ret)
1701+
: [new] "r" (new)
1702+
: "memory");
1703+
1704+
uaccess_ttbr0_disable();
1705+
1706+
if (ret)
1707+
return ret;
1708+
if (tmp != old)
1709+
return -EAGAIN;
1710+
1711+
return ret;
1712+
}
1713+
16841714
static int __lse_swap_desc(u64 __user *ptep, u64 old, u64 new)
16851715
{
16861716
u64 tmp = old;
@@ -1756,7 +1786,9 @@ int __kvm_at_swap_desc(struct kvm *kvm, gpa_t ipa, u64 old, u64 new)
17561786
return -EPERM;
17571787

17581788
ptep = (u64 __user *)hva + offset;
1759-
if (cpus_have_final_cap(ARM64_HAS_LSE_ATOMICS))
1789+
if (cpus_have_final_cap(ARM64_HAS_LSUI))
1790+
r = __lsui_swap_desc(ptep, old, new);
1791+
else if (cpus_have_final_cap(ARM64_HAS_LSE_ATOMICS))
17601792
r = __lse_swap_desc(ptep, old, new);
17611793
else
17621794
r = __llsc_swap_desc(ptep, old, new);

0 commit comments

Comments
 (0)