KVM: selftests: Move flds instruction emulation failure handling to header
authorDavid Matlack <dmatlack@google.com>
Wed, 2 Nov 2022 18:46:48 +0000 (11:46 -0700)
committerSean Christopherson <seanjc@google.com>
Thu, 17 Nov 2022 00:58:59 +0000 (16:58 -0800)
Move the flds instruction emulation failure handling code to a header
so it can be re-used in an upcoming test.

No functional change intended.

Signed-off-by: David Matlack <dmatlack@google.com>
Link: https://lore.kernel.org/r/20221102184654.282799-5-dmatlack@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
tools/testing/selftests/kvm/x86_64/flds_emulation.h [new file with mode: 0644]
tools/testing/selftests/kvm/x86_64/smaller_maxphyaddr_emulation_test.c

diff --git a/tools/testing/selftests/kvm/x86_64/flds_emulation.h b/tools/testing/selftests/kvm/x86_64/flds_emulation.h
new file mode 100644 (file)
index 0000000..e43a7df
--- /dev/null
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef SELFTEST_KVM_FLDS_EMULATION_H
+#define SELFTEST_KVM_FLDS_EMULATION_H
+
+#include "kvm_util.h"
+
+#define FLDS_MEM_EAX ".byte 0xd9, 0x00"
+
+/*
+ * flds is an instruction that the KVM instruction emulator is known not to
+ * support. This can be used in guest code along with a mechanism to force
+ * KVM to emulate the instruction (e.g. by providing an MMIO address) to
+ * exercise emulation failures.
+ */
+static inline void flds(uint64_t address)
+{
+       __asm__ __volatile__(FLDS_MEM_EAX :: "a"(address));
+}
+
+static inline void handle_flds_emulation_failure_exit(struct kvm_vcpu *vcpu)
+{
+       struct kvm_run *run = vcpu->run;
+       struct kvm_regs regs;
+       uint8_t *insn_bytes;
+       uint64_t flags;
+
+       TEST_ASSERT(run->exit_reason == KVM_EXIT_INTERNAL_ERROR,
+                   "Unexpected exit reason: %u (%s)",
+                   run->exit_reason,
+                   exit_reason_str(run->exit_reason));
+
+       TEST_ASSERT(run->emulation_failure.suberror == KVM_INTERNAL_ERROR_EMULATION,
+                   "Unexpected suberror: %u",
+                   run->emulation_failure.suberror);
+
+       flags = run->emulation_failure.flags;
+       TEST_ASSERT(run->emulation_failure.ndata >= 3 &&
+                   flags & KVM_INTERNAL_ERROR_EMULATION_FLAG_INSTRUCTION_BYTES,
+                   "run->emulation_failure is missing instruction bytes");
+
+       TEST_ASSERT(run->emulation_failure.insn_size >= 2,
+                   "Expected a 2-byte opcode for 'flds', got %d bytes",
+                   run->emulation_failure.insn_size);
+
+       insn_bytes = run->emulation_failure.insn_bytes;
+       TEST_ASSERT(insn_bytes[0] == 0xd9 && insn_bytes[1] == 0,
+                   "Expected 'flds [eax]', opcode '0xd9 0x00', got opcode 0x%02x 0x%02x\n",
+                   insn_bytes[0], insn_bytes[1]);
+
+       vcpu_regs_get(vcpu, &regs);
+       regs.rip += 2;
+       vcpu_regs_set(vcpu, &regs);
+}
+
+#endif /* !SELFTEST_KVM_FLDS_EMULATION_H */
index b72aeef..a8d0811 100644 (file)
@@ -8,6 +8,8 @@
 
 #define _GNU_SOURCE /* for program_invocation_short_name */
 
+#include "flds_emulation.h"
+
 #include "test_util.h"
 #include "kvm_util.h"
 #include "vmx.h"
 #define MEM_REGION_SLOT        10
 #define MEM_REGION_SIZE PAGE_SIZE
 
-#define FLDS_MEM_EAX ".byte 0xd9, 0x00"
-
 static void guest_code(void)
 {
-       __asm__ __volatile__(FLDS_MEM_EAX :: "a"(MEM_REGION_GVA));
-
+       flds(MEM_REGION_GVA);
        GUEST_DONE();
 }
 
-static void process_exit_on_emulation_error(struct kvm_vcpu *vcpu)
-{
-       struct kvm_run *run = vcpu->run;
-       struct kvm_regs regs;
-       uint8_t *insn_bytes;
-       uint64_t flags;
-
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_INTERNAL_ERROR,
-                   "Unexpected exit reason: %u (%s)",
-                   run->exit_reason,
-                   exit_reason_str(run->exit_reason));
-
-       TEST_ASSERT(run->emulation_failure.suberror == KVM_INTERNAL_ERROR_EMULATION,
-                   "Unexpected suberror: %u",
-                   run->emulation_failure.suberror);
-
-       flags = run->emulation_failure.flags;
-       TEST_ASSERT(run->emulation_failure.ndata >= 3 &&
-                   flags & KVM_INTERNAL_ERROR_EMULATION_FLAG_INSTRUCTION_BYTES,
-                   "run->emulation_failure is missing instruction bytes");
-
-       TEST_ASSERT(run->emulation_failure.insn_size >= 2,
-                   "Expected a 2-byte opcode for 'flds', got %d bytes",
-                   run->emulation_failure.insn_size);
-
-       insn_bytes = run->emulation_failure.insn_bytes;
-       TEST_ASSERT(insn_bytes[0] == 0xd9 && insn_bytes[1] == 0,
-                   "Expected 'flds [eax]', opcode '0xd9 0x00', got opcode 0x%02x 0x%02x\n",
-                   insn_bytes[0], insn_bytes[1]);
-
-       vcpu_regs_get(vcpu, &regs);
-       regs.rip += 2;
-       vcpu_regs_set(vcpu, &regs);
-}
-
 int main(int argc, char *argv[])
 {
        struct kvm_vcpu *vcpu;
@@ -96,7 +60,7 @@ int main(int argc, char *argv[])
        *pte |= BIT_ULL(MAXPHYADDR);
 
        vcpu_run(vcpu);
-       process_exit_on_emulation_error(vcpu);
+       handle_flds_emulation_failure_exit(vcpu);
        vcpu_run(vcpu);
        ASSERT_EQ(get_ucall(vcpu, NULL), UCALL_DONE);