Skip to content

Commit 3942650

Browse files
sean-jcbonzini
authored andcommitted
KVM: selftests: Compare insn opcodes directly in fix_hypercall_test
Directly compare the expected versus observed hypercall instructions when verifying that KVM patched in the native hypercall (FIX_HYPERCALL_INSN quirk enabled). gcc rightly complains that doing a 4-byte memcpy() with an "unsigned char" as the source generates an out-of-bounds accesses. Alternatively, "exp" and "obs" could be declared as 3-byte arrays, but there's no known reason to copy locally instead of comparing directly. In function ‘assert_hypercall_insn’, inlined from ‘guest_main’ at x86_64/fix_hypercall_test.c:91:2: x86_64/fix_hypercall_test.c:63:9: error: array subscript ‘unsigned int[0]’ is partly outside array bounds of ‘unsigned char[1]’ [-Werror=array-bounds] 63 | memcpy(&exp, exp_insn, sizeof(exp)); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ x86_64/fix_hypercall_test.c: In function ‘guest_main’: x86_64/fix_hypercall_test.c:42:22: note: object ‘vmx_hypercall_insn’ of size 1 42 | extern unsigned char vmx_hypercall_insn; | ^~~~~~~~~~~~~~~~~~ x86_64/fix_hypercall_test.c:25:22: note: object ‘svm_hypercall_insn’ of size 1 25 | extern unsigned char svm_hypercall_insn; | ^~~~~~~~~~~~~~~~~~ In function ‘assert_hypercall_insn’, inlined from ‘guest_main’ at x86_64/fix_hypercall_test.c:91:2: x86_64/fix_hypercall_test.c:64:9: error: array subscript ‘unsigned int[0]’ is partly outside array bounds of ‘unsigned char[1]’ [-Werror=array-bounds] 64 | memcpy(&obs, obs_insn, sizeof(obs)); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ x86_64/fix_hypercall_test.c: In function ‘guest_main’: x86_64/fix_hypercall_test.c:25:22: note: object ‘svm_hypercall_insn’ of size 1 25 | extern unsigned char svm_hypercall_insn; | ^~~~~~~~~~~~~~~~~~ x86_64/fix_hypercall_test.c:42:22: note: object ‘vmx_hypercall_insn’ of size 1 42 | extern unsigned char vmx_hypercall_insn; | ^~~~~~~~~~~~~~~~~~ cc1: all warnings being treated as errors make: *** [../lib.mk:135: tools/testing/selftests/kvm/x86_64/fix_hypercall_test] Error 1 Fixes: 6c2fa8b ("selftests: KVM: Test KVM_X86_QUIRK_FIX_HYPERCALL_INSN") Cc: Oliver Upton <[email protected]> Signed-off-by: Sean Christopherson <[email protected]> Reviewed-by: Oliver Upton <[email protected]> Message-Id: <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent 6b6f714 commit 3942650

File tree

1 file changed

+16
-18
lines changed

1 file changed

+16
-18
lines changed

tools/testing/selftests/kvm/x86_64/fix_hypercall_test.c

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
#include "kvm_util.h"
1515
#include "processor.h"
1616

17+
/* VMCALL and VMMCALL are both 3-byte opcodes. */
18+
#define HYPERCALL_INSN_SIZE 3
19+
1720
static bool ud_expected;
1821

1922
static void guest_ud_handler(struct ex_regs *regs)
@@ -22,7 +25,7 @@ static void guest_ud_handler(struct ex_regs *regs)
2225
GUEST_DONE();
2326
}
2427

25-
extern unsigned char svm_hypercall_insn;
28+
extern uint8_t svm_hypercall_insn[HYPERCALL_INSN_SIZE];
2629
static uint64_t svm_do_sched_yield(uint8_t apic_id)
2730
{
2831
uint64_t ret;
@@ -39,7 +42,7 @@ static uint64_t svm_do_sched_yield(uint8_t apic_id)
3942
return ret;
4043
}
4144

42-
extern unsigned char vmx_hypercall_insn;
45+
extern uint8_t vmx_hypercall_insn[HYPERCALL_INSN_SIZE];
4346
static uint64_t vmx_do_sched_yield(uint8_t apic_id)
4447
{
4548
uint64_t ret;
@@ -56,39 +59,34 @@ static uint64_t vmx_do_sched_yield(uint8_t apic_id)
5659
return ret;
5760
}
5861

59-
static void assert_hypercall_insn(unsigned char *exp_insn, unsigned char *obs_insn)
60-
{
61-
uint32_t exp = 0, obs = 0;
62-
63-
memcpy(&exp, exp_insn, sizeof(exp));
64-
memcpy(&obs, obs_insn, sizeof(obs));
65-
66-
GUEST_ASSERT_EQ(exp, obs);
67-
}
68-
6962
static void guest_main(void)
7063
{
71-
unsigned char *native_hypercall_insn, *hypercall_insn;
64+
uint8_t *native_hypercall_insn, *hypercall_insn;
7265
uint8_t apic_id;
7366

7467
apic_id = GET_APIC_ID_FIELD(xapic_read_reg(APIC_ID));
7568

7669
if (is_intel_cpu()) {
77-
native_hypercall_insn = &vmx_hypercall_insn;
78-
hypercall_insn = &svm_hypercall_insn;
70+
native_hypercall_insn = vmx_hypercall_insn;
71+
hypercall_insn = svm_hypercall_insn;
7972
svm_do_sched_yield(apic_id);
8073
} else if (is_amd_cpu()) {
81-
native_hypercall_insn = &svm_hypercall_insn;
82-
hypercall_insn = &vmx_hypercall_insn;
74+
native_hypercall_insn = svm_hypercall_insn;
75+
hypercall_insn = vmx_hypercall_insn;
8376
vmx_do_sched_yield(apic_id);
8477
} else {
8578
GUEST_ASSERT(0);
8679
/* unreachable */
8780
return;
8881
}
8982

83+
/*
84+
* The hypercall didn't #UD (guest_ud_handler() signals "done" if a #UD
85+
* occurs). Verify that a #UD is NOT expected and that KVM patched in
86+
* the native hypercall.
87+
*/
9088
GUEST_ASSERT(!ud_expected);
91-
assert_hypercall_insn(native_hypercall_insn, hypercall_insn);
89+
GUEST_ASSERT(!memcmp(native_hypercall_insn, hypercall_insn, HYPERCALL_INSN_SIZE));
9290
GUEST_DONE();
9391
}
9492

0 commit comments

Comments
 (0)