mirror of
https://github.com/torvalds/linux.git
synced 2026-05-26 16:12:59 +02:00
KVM: selftests: Move flds instruction emulation failure handling to header
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>
This commit is contained in:
parent
50824c6eee
commit
19a2b32f5d
55
tools/testing/selftests/kvm/x86_64/flds_emulation.h
Normal file
55
tools/testing/selftests/kvm/x86_64/flds_emulation.h
Normal file
|
|
@ -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, ®s);
|
||||
regs.rip += 2;
|
||||
vcpu_regs_set(vcpu, ®s);
|
||||
}
|
||||
|
||||
#endif /* !SELFTEST_KVM_FLDS_EMULATION_H */
|
||||
|
|
@ -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"
|
||||
|
|
@ -19,50 +21,12 @@
|
|||
#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, ®s);
|
||||
regs.rip += 2;
|
||||
vcpu_regs_set(vcpu, ®s);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user