[kvm-unit-tests PATCH] x86: access: Add tests for reserved bits of guest physical address

From: Mohammed Gamal
Date: Thu Feb 27 2020 - 12:28:51 EST


This extends the access tests to also test for reserved bits
in guest physical addresses.

Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx>
Signed-off-by: Mohammed Gamal <mgamal@xxxxxxxxxx>
---
x86/access.c | 31 +++++++++++++++++++++++++++++--
1 file changed, 29 insertions(+), 2 deletions(-)

diff --git a/x86/access.c b/x86/access.c
index 7303fc3..b98b403 100644
--- a/x86/access.c
+++ b/x86/access.c
@@ -47,6 +47,7 @@ enum {
AC_PTE_DIRTY_BIT,
AC_PTE_NX_BIT,
AC_PTE_BIT51_BIT,
+ AC_PTE_BIT40_BIT,

AC_PDE_PRESENT_BIT,
AC_PDE_WRITABLE_BIT,
@@ -56,6 +57,7 @@ enum {
AC_PDE_PSE_BIT,
AC_PDE_NX_BIT,
AC_PDE_BIT51_BIT,
+ AC_PDE_BIT40_BIT,
AC_PDE_BIT13_BIT,

AC_PKU_AD_BIT,
@@ -82,6 +84,7 @@ enum {
#define AC_PTE_DIRTY_MASK (1 << AC_PTE_DIRTY_BIT)
#define AC_PTE_NX_MASK (1 << AC_PTE_NX_BIT)
#define AC_PTE_BIT51_MASK (1 << AC_PTE_BIT51_BIT)
+#define AC_PTE_BIT40_MASK (1 << AC_PTE_BIT40_BIT)

#define AC_PDE_PRESENT_MASK (1 << AC_PDE_PRESENT_BIT)
#define AC_PDE_WRITABLE_MASK (1 << AC_PDE_WRITABLE_BIT)
@@ -91,6 +94,7 @@ enum {
#define AC_PDE_PSE_MASK (1 << AC_PDE_PSE_BIT)
#define AC_PDE_NX_MASK (1 << AC_PDE_NX_BIT)
#define AC_PDE_BIT51_MASK (1 << AC_PDE_BIT51_BIT)
+#define AC_PDE_BIT40_MASK (1 << AC_PDE_BIT40_BIT)
#define AC_PDE_BIT13_MASK (1 << AC_PDE_BIT13_BIT)

#define AC_PKU_AD_MASK (1 << AC_PKU_AD_BIT)
@@ -115,6 +119,7 @@ const char *ac_names[] = {
[AC_PTE_DIRTY_BIT] = "pte.d",
[AC_PTE_NX_BIT] = "pte.nx",
[AC_PTE_BIT51_BIT] = "pte.51",
+ [AC_PTE_BIT40_BIT] = "pte.40",
[AC_PDE_PRESENT_BIT] = "pde.p",
[AC_PDE_ACCESSED_BIT] = "pde.a",
[AC_PDE_WRITABLE_BIT] = "pde.rw",
@@ -123,6 +128,7 @@ const char *ac_names[] = {
[AC_PDE_PSE_BIT] = "pde.pse",
[AC_PDE_NX_BIT] = "pde.nx",
[AC_PDE_BIT51_BIT] = "pde.51",
+ [AC_PDE_BIT40_BIT] = "pde.40",
[AC_PDE_BIT13_BIT] = "pde.13",
[AC_PKU_AD_BIT] = "pkru.ad",
[AC_PKU_WD_BIT] = "pkru.wd",
@@ -289,6 +295,14 @@ static _Bool ac_test_legal(ac_test_t *at)
if (!F(AC_PDE_PSE) && F(AC_PDE_BIT13))
return false;

+ /*
+ * Shorten the test by avoiding testing too many reserved bit combinations
+ */
+ if ((F(AC_PDE_BIT51) + F(AC_PDE_BIT40) + F(AC_PDE_BIT13)) > 1)
+ return false;
+ if ((F(AC_PTE_BIT51) + F(AC_PTE_BIT40)) > 1)
+ return false;
+
return true;
}

@@ -375,7 +389,7 @@ static void ac_emulate_access(ac_test_t *at, unsigned flags)
at->ignore_pde = PT_ACCESSED_MASK;

pde_valid = F(AC_PDE_PRESENT)
- && !F(AC_PDE_BIT51) && !F(AC_PDE_BIT13)
+ && !F(AC_PDE_BIT51) && !F(AC_PDE_BIT40) && !F(AC_PDE_BIT13)
&& !(F(AC_PDE_NX) && !F(AC_CPU_EFER_NX));

if (!pde_valid) {
@@ -401,7 +415,7 @@ static void ac_emulate_access(ac_test_t *at, unsigned flags)
at->expected_pde |= PT_ACCESSED_MASK;

pte_valid = F(AC_PTE_PRESENT)
- && !F(AC_PTE_BIT51)
+ && !F(AC_PTE_BIT51) && !F(AC_PTE_BIT40)
&& !(F(AC_PTE_NX) && !F(AC_CPU_EFER_NX));

if (!pte_valid) {
@@ -510,6 +524,8 @@ static void __ac_setup_specific_pages(ac_test_t *at, ac_pool_t *pool,
pte |= PT64_NX_MASK;
if (F(AC_PDE_BIT51))
pte |= 1ull << 51;
+ if (F(AC_PDE_BIT40))
+ pte |= 1ull << 40;
if (F(AC_PDE_BIT13))
pte |= 1ull << 13;
at->pdep = &vroot[index];
@@ -532,6 +548,8 @@ static void __ac_setup_specific_pages(ac_test_t *at, ac_pool_t *pool,
pte |= PT64_NX_MASK;
if (F(AC_PTE_BIT51))
pte |= 1ull << 51;
+ if (F(AC_PTE_BIT40))
+ pte |= 1ull << 40;
at->ptep = &vroot[index];
break;
}
@@ -935,6 +953,15 @@ static int ac_test_run(void)
printf("run\n");
tests = successes = 0;

+ if (cpuid_maxphyaddr() >= 52) {
+ invalid_mask |= AC_PDE_BIT51_MASK;
+ invalid_mask |= AC_PTE_BIT51_MASK;
+ }
+ if (cpuid_maxphyaddr() >= 41) {
+ invalid_mask |= AC_PDE_BIT40_MASK;
+ invalid_mask |= AC_PTE_BIT40_MASK;
+ }
+
if (this_cpu_has(X86_FEATURE_PKU)) {
set_cr4_pke(1);
set_cr4_pke(0);
--
2.21.1