nSVM: Add a test for NPF due to P=0 in NPT entry

If the P (present) bit in an NPT entry is cleared, accesses to the
corresponding guest physical address will fail and the guest will exit to
the host with an exit code of 0x400 (#NPF). The test checks for bits 2
and 32 to be set (respectively because all NPT accesses are considered
user accesses, and because the test encounters the P=0 entry while
translating the final guest physical address and not a guest page table.

Signed-off-by: Krish Sadhukhan <krish.sadhukhan@oracle.com>
Message-Id: <20200829005720.5325-1-krish.sadhukhan@oracle.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
diff --git a/x86/svm_tests.c b/x86/svm_tests.c
index 1908c7c..e9f178a 100644
--- a/x86/svm_tests.c
+++ b/x86/svm_tests.c
@@ -720,6 +720,32 @@
            && (vmcb->control.exit_info_1 == 0x100000015ULL);
 }
 
+static void npt_np_prepare(struct svm_test *test)
+{
+    u64 *pte;
+
+    scratch_page = alloc_page();
+    vmcb_ident(vmcb);
+    pte = npt_get_pte((u64)scratch_page);
+
+    *pte &= ~1ULL;
+}
+
+static void npt_np_test(struct svm_test *test)
+{
+    (void) *(volatile u64 *)scratch_page;
+}
+
+static bool npt_np_check(struct svm_test *test)
+{
+    u64 *pte = npt_get_pte((u64)scratch_page);
+
+    *pte |= 1ULL;
+
+    return (vmcb->control.exit_code == SVM_EXIT_NPF)
+           && (vmcb->control.exit_info_1 == 0x100000004ULL);
+}
+
 static void npt_us_prepare(struct svm_test *test)
 {
     u64 *pte;
@@ -2119,6 +2145,9 @@
     { "npt_nx", npt_supported, npt_nx_prepare,
       default_prepare_gif_clear, null_test,
       default_finished, npt_nx_check },
+    { "npt_np", npt_supported, npt_np_prepare,
+      default_prepare_gif_clear, npt_np_test,
+      default_finished, npt_np_check },
     { "npt_us", npt_supported, npt_us_prepare,
       default_prepare_gif_clear, npt_us_test,
       default_finished, npt_us_check },