mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 20:22:09 +00:00
KVM: selftests: do not blindly clobber registers in guest asm
The guest_code of sync_regs_test is assuming that the compiler will not touch %r11 outside the asm that increments it, which is a bit brittle. Instead, we can increment a variable and use a dummy asm to ensure the increment is not optimized away. However, we also need to use a callee-save register or the compiler will insert a save/restore around the vmexit, breaking the whole idea behind the test. (Yes, "if it ain't broken...", but I would like the test to be clean before it is copied into the upcoming s390 selftests). Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
12e9612cae
commit
204c91eff7
@ -25,9 +25,15 @@
|
|||||||
|
|
||||||
void guest_code(void)
|
void guest_code(void)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* use a callee-save register, otherwise the compiler
|
||||||
|
* saves it around the call to GUEST_SYNC.
|
||||||
|
*/
|
||||||
|
register u32 stage asm("rbx");
|
||||||
for (;;) {
|
for (;;) {
|
||||||
GUEST_SYNC(0);
|
GUEST_SYNC(0);
|
||||||
asm volatile ("inc %r11");
|
stage++;
|
||||||
|
asm volatile ("" : : "r" (stage));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +153,7 @@ int main(int argc, char *argv[])
|
|||||||
compare_vcpu_events(&events, &run->s.regs.events);
|
compare_vcpu_events(&events, &run->s.regs.events);
|
||||||
|
|
||||||
/* Set and verify various register values. */
|
/* Set and verify various register values. */
|
||||||
run->s.regs.regs.r11 = 0xBAD1DEA;
|
run->s.regs.regs.rbx = 0xBAD1DEA;
|
||||||
run->s.regs.sregs.apic_base = 1 << 11;
|
run->s.regs.sregs.apic_base = 1 << 11;
|
||||||
/* TODO run->s.regs.events.XYZ = ABC; */
|
/* TODO run->s.regs.events.XYZ = ABC; */
|
||||||
|
|
||||||
@ -158,9 +164,9 @@ int main(int argc, char *argv[])
|
|||||||
"Unexpected exit reason: %u (%s),\n",
|
"Unexpected exit reason: %u (%s),\n",
|
||||||
run->exit_reason,
|
run->exit_reason,
|
||||||
exit_reason_str(run->exit_reason));
|
exit_reason_str(run->exit_reason));
|
||||||
TEST_ASSERT(run->s.regs.regs.r11 == 0xBAD1DEA + 1,
|
TEST_ASSERT(run->s.regs.regs.rbx == 0xBAD1DEA + 1,
|
||||||
"r11 sync regs value incorrect 0x%llx.",
|
"rbx sync regs value incorrect 0x%llx.",
|
||||||
run->s.regs.regs.r11);
|
run->s.regs.regs.rbx);
|
||||||
TEST_ASSERT(run->s.regs.sregs.apic_base == 1 << 11,
|
TEST_ASSERT(run->s.regs.sregs.apic_base == 1 << 11,
|
||||||
"apic_base sync regs value incorrect 0x%llx.",
|
"apic_base sync regs value incorrect 0x%llx.",
|
||||||
run->s.regs.sregs.apic_base);
|
run->s.regs.sregs.apic_base);
|
||||||
@ -179,15 +185,15 @@ int main(int argc, char *argv[])
|
|||||||
*/
|
*/
|
||||||
run->kvm_valid_regs = TEST_SYNC_FIELDS;
|
run->kvm_valid_regs = TEST_SYNC_FIELDS;
|
||||||
run->kvm_dirty_regs = 0;
|
run->kvm_dirty_regs = 0;
|
||||||
run->s.regs.regs.r11 = 0xDEADBEEF;
|
run->s.regs.regs.rbx = 0xDEADBEEF;
|
||||||
rv = _vcpu_run(vm, VCPU_ID);
|
rv = _vcpu_run(vm, VCPU_ID);
|
||||||
TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
|
TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
|
||||||
"Unexpected exit reason: %u (%s),\n",
|
"Unexpected exit reason: %u (%s),\n",
|
||||||
run->exit_reason,
|
run->exit_reason,
|
||||||
exit_reason_str(run->exit_reason));
|
exit_reason_str(run->exit_reason));
|
||||||
TEST_ASSERT(run->s.regs.regs.r11 != 0xDEADBEEF,
|
TEST_ASSERT(run->s.regs.regs.rbx != 0xDEADBEEF,
|
||||||
"r11 sync regs value incorrect 0x%llx.",
|
"rbx sync regs value incorrect 0x%llx.",
|
||||||
run->s.regs.regs.r11);
|
run->s.regs.regs.rbx);
|
||||||
|
|
||||||
/* Clear kvm_valid_regs bits and kvm_dirty_bits.
|
/* Clear kvm_valid_regs bits and kvm_dirty_bits.
|
||||||
* Verify s.regs values are not overwritten with existing guest values
|
* Verify s.regs values are not overwritten with existing guest values
|
||||||
@ -195,21 +201,21 @@ int main(int argc, char *argv[])
|
|||||||
*/
|
*/
|
||||||
run->kvm_valid_regs = 0;
|
run->kvm_valid_regs = 0;
|
||||||
run->kvm_dirty_regs = 0;
|
run->kvm_dirty_regs = 0;
|
||||||
run->s.regs.regs.r11 = 0xAAAA;
|
run->s.regs.regs.rbx = 0xAAAA;
|
||||||
regs.r11 = 0xBAC0;
|
regs.rbx = 0xBAC0;
|
||||||
vcpu_regs_set(vm, VCPU_ID, ®s);
|
vcpu_regs_set(vm, VCPU_ID, ®s);
|
||||||
rv = _vcpu_run(vm, VCPU_ID);
|
rv = _vcpu_run(vm, VCPU_ID);
|
||||||
TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
|
TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
|
||||||
"Unexpected exit reason: %u (%s),\n",
|
"Unexpected exit reason: %u (%s),\n",
|
||||||
run->exit_reason,
|
run->exit_reason,
|
||||||
exit_reason_str(run->exit_reason));
|
exit_reason_str(run->exit_reason));
|
||||||
TEST_ASSERT(run->s.regs.regs.r11 == 0xAAAA,
|
TEST_ASSERT(run->s.regs.regs.rbx == 0xAAAA,
|
||||||
"r11 sync regs value incorrect 0x%llx.",
|
"rbx sync regs value incorrect 0x%llx.",
|
||||||
run->s.regs.regs.r11);
|
run->s.regs.regs.rbx);
|
||||||
vcpu_regs_get(vm, VCPU_ID, ®s);
|
vcpu_regs_get(vm, VCPU_ID, ®s);
|
||||||
TEST_ASSERT(regs.r11 == 0xBAC0 + 1,
|
TEST_ASSERT(regs.rbx == 0xBAC0 + 1,
|
||||||
"r11 guest value incorrect 0x%llx.",
|
"rbx guest value incorrect 0x%llx.",
|
||||||
regs.r11);
|
regs.rbx);
|
||||||
|
|
||||||
/* Clear kvm_valid_regs bits. Verify s.regs values are not overwritten
|
/* Clear kvm_valid_regs bits. Verify s.regs values are not overwritten
|
||||||
* with existing guest values but that guest values are overwritten
|
* with existing guest values but that guest values are overwritten
|
||||||
@ -217,19 +223,19 @@ int main(int argc, char *argv[])
|
|||||||
*/
|
*/
|
||||||
run->kvm_valid_regs = 0;
|
run->kvm_valid_regs = 0;
|
||||||
run->kvm_dirty_regs = TEST_SYNC_FIELDS;
|
run->kvm_dirty_regs = TEST_SYNC_FIELDS;
|
||||||
run->s.regs.regs.r11 = 0xBBBB;
|
run->s.regs.regs.rbx = 0xBBBB;
|
||||||
rv = _vcpu_run(vm, VCPU_ID);
|
rv = _vcpu_run(vm, VCPU_ID);
|
||||||
TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
|
TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
|
||||||
"Unexpected exit reason: %u (%s),\n",
|
"Unexpected exit reason: %u (%s),\n",
|
||||||
run->exit_reason,
|
run->exit_reason,
|
||||||
exit_reason_str(run->exit_reason));
|
exit_reason_str(run->exit_reason));
|
||||||
TEST_ASSERT(run->s.regs.regs.r11 == 0xBBBB,
|
TEST_ASSERT(run->s.regs.regs.rbx == 0xBBBB,
|
||||||
"r11 sync regs value incorrect 0x%llx.",
|
"rbx sync regs value incorrect 0x%llx.",
|
||||||
run->s.regs.regs.r11);
|
run->s.regs.regs.rbx);
|
||||||
vcpu_regs_get(vm, VCPU_ID, ®s);
|
vcpu_regs_get(vm, VCPU_ID, ®s);
|
||||||
TEST_ASSERT(regs.r11 == 0xBBBB + 1,
|
TEST_ASSERT(regs.rbx == 0xBBBB + 1,
|
||||||
"r11 guest value incorrect 0x%llx.",
|
"rbx guest value incorrect 0x%llx.",
|
||||||
regs.r11);
|
regs.rbx);
|
||||||
|
|
||||||
kvm_vm_free(vm);
|
kvm_vm_free(vm);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user