mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-03-16 12:14:06 +00:00
KVM: x86/xen: Add runstate tests for 32-bit mode and crossing page boundary
Torture test the cases where the runstate crosses a page boundary, and and especially the case where it's configured in 32-bit mode and doesn't, but then switching to 64-bit mode makes it go onto the second page. To simplify this, make the KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADJUST ioctl also update the guest runstate area. It already did so if the actual runstate changed, as a side-effect of kvm_xen_update_runstate(). So doing it in the plain adjustment case is making it more consistent, as well as giving us a nice way to trigger the update without actually running the vCPU again and changing the values. Signed-off-by: David Woodhouse <dwmw@amazon.co.uk> Reviewed-by: Paul Durrant <paul@xen.org> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
d8ba8ba4c8
commit
8acc35186e
2 changed files with 96 additions and 19 deletions
|
@ -884,6 +884,8 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data)
|
|||
|
||||
if (data->u.runstate.state <= RUNSTATE_offline)
|
||||
kvm_xen_update_runstate(vcpu, data->u.runstate.state);
|
||||
else if (vcpu->arch.xen.runstate_cache.active)
|
||||
kvm_xen_update_runstate_guest(vcpu, false);
|
||||
r = 0;
|
||||
break;
|
||||
|
||||
|
|
|
@ -88,14 +88,20 @@ struct pvclock_wall_clock {
|
|||
} __attribute__((__packed__));
|
||||
|
||||
struct vcpu_runstate_info {
|
||||
uint32_t state;
|
||||
uint64_t state_entry_time;
|
||||
uint64_t time[4];
|
||||
uint32_t state;
|
||||
uint64_t state_entry_time;
|
||||
uint64_t time[5]; /* Extra field for overrun check */
|
||||
};
|
||||
|
||||
struct compat_vcpu_runstate_info {
|
||||
uint32_t state;
|
||||
uint64_t state_entry_time;
|
||||
uint64_t time[5];
|
||||
} __attribute__((__packed__));;
|
||||
|
||||
struct arch_vcpu_info {
|
||||
unsigned long cr2;
|
||||
unsigned long pad; /* sizeof(vcpu_info_t) == 64 */
|
||||
unsigned long cr2;
|
||||
unsigned long pad; /* sizeof(vcpu_info_t) == 64 */
|
||||
};
|
||||
|
||||
struct vcpu_info {
|
||||
|
@ -1013,22 +1019,91 @@ int main(int argc, char *argv[])
|
|||
runstate_names[i], rs->time[i]);
|
||||
}
|
||||
}
|
||||
TEST_ASSERT(rs->state == rst.u.runstate.state, "Runstate mismatch");
|
||||
TEST_ASSERT(rs->state_entry_time == rst.u.runstate.state_entry_time,
|
||||
"State entry time mismatch");
|
||||
TEST_ASSERT(rs->time[RUNSTATE_running] == rst.u.runstate.time_running,
|
||||
"Running time mismatch");
|
||||
TEST_ASSERT(rs->time[RUNSTATE_runnable] == rst.u.runstate.time_runnable,
|
||||
"Runnable time mismatch");
|
||||
TEST_ASSERT(rs->time[RUNSTATE_blocked] == rst.u.runstate.time_blocked,
|
||||
"Blocked time mismatch");
|
||||
TEST_ASSERT(rs->time[RUNSTATE_offline] == rst.u.runstate.time_offline,
|
||||
"Offline time mismatch");
|
||||
|
||||
TEST_ASSERT(rs->state_entry_time == rs->time[0] +
|
||||
rs->time[1] + rs->time[2] + rs->time[3],
|
||||
"runstate times don't add up");
|
||||
/*
|
||||
* Exercise runstate info at all points across the page boundary, in
|
||||
* 32-bit and 64-bit mode. In particular, test the case where it is
|
||||
* configured in 32-bit mode and then switched to 64-bit mode while
|
||||
* active, which takes it onto the second page.
|
||||
*/
|
||||
unsigned long runstate_addr;
|
||||
struct compat_vcpu_runstate_info *crs;
|
||||
for (runstate_addr = SHINFO_REGION_GPA + PAGE_SIZE + PAGE_SIZE - sizeof(*rs) - 4;
|
||||
runstate_addr < SHINFO_REGION_GPA + PAGE_SIZE + PAGE_SIZE + 4; runstate_addr++) {
|
||||
|
||||
rs = addr_gpa2hva(vm, runstate_addr);
|
||||
crs = (void *)rs;
|
||||
|
||||
memset(rs, 0xa5, sizeof(*rs));
|
||||
|
||||
/* Set to compatibility mode */
|
||||
lm.u.long_mode = 0;
|
||||
vm_ioctl(vm, KVM_XEN_HVM_SET_ATTR, &lm);
|
||||
|
||||
/* Set runstate to new address (kernel will write it) */
|
||||
struct kvm_xen_vcpu_attr st = {
|
||||
.type = KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADDR,
|
||||
.u.gpa = runstate_addr,
|
||||
};
|
||||
vcpu_ioctl(vcpu, KVM_XEN_VCPU_SET_ATTR, &st);
|
||||
|
||||
if (verbose)
|
||||
printf("Compatibility runstate at %08lx\n", runstate_addr);
|
||||
|
||||
TEST_ASSERT(crs->state == rst.u.runstate.state, "Runstate mismatch");
|
||||
TEST_ASSERT(crs->state_entry_time == rst.u.runstate.state_entry_time,
|
||||
"State entry time mismatch");
|
||||
TEST_ASSERT(crs->time[RUNSTATE_running] == rst.u.runstate.time_running,
|
||||
"Running time mismatch");
|
||||
TEST_ASSERT(crs->time[RUNSTATE_runnable] == rst.u.runstate.time_runnable,
|
||||
"Runnable time mismatch");
|
||||
TEST_ASSERT(crs->time[RUNSTATE_blocked] == rst.u.runstate.time_blocked,
|
||||
"Blocked time mismatch");
|
||||
TEST_ASSERT(crs->time[RUNSTATE_offline] == rst.u.runstate.time_offline,
|
||||
"Offline time mismatch");
|
||||
TEST_ASSERT(crs->time[RUNSTATE_offline + 1] == 0xa5a5a5a5a5a5a5a5ULL,
|
||||
"Structure overrun");
|
||||
TEST_ASSERT(crs->state_entry_time == crs->time[0] +
|
||||
crs->time[1] + crs->time[2] + crs->time[3],
|
||||
"runstate times don't add up");
|
||||
|
||||
|
||||
/* Now switch to 64-bit mode */
|
||||
lm.u.long_mode = 1;
|
||||
vm_ioctl(vm, KVM_XEN_HVM_SET_ATTR, &lm);
|
||||
|
||||
memset(rs, 0xa5, sizeof(*rs));
|
||||
|
||||
/* Don't change the address, just trigger a write */
|
||||
struct kvm_xen_vcpu_attr adj = {
|
||||
.type = KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADJUST,
|
||||
.u.runstate.state = (uint64_t)-1
|
||||
};
|
||||
vcpu_ioctl(vcpu, KVM_XEN_VCPU_SET_ATTR, &adj);
|
||||
|
||||
if (verbose)
|
||||
printf("64-bit runstate at %08lx\n", runstate_addr);
|
||||
|
||||
TEST_ASSERT(rs->state == rst.u.runstate.state, "Runstate mismatch");
|
||||
TEST_ASSERT(rs->state_entry_time == rst.u.runstate.state_entry_time,
|
||||
"State entry time mismatch");
|
||||
TEST_ASSERT(rs->time[RUNSTATE_running] == rst.u.runstate.time_running,
|
||||
"Running time mismatch");
|
||||
TEST_ASSERT(rs->time[RUNSTATE_runnable] == rst.u.runstate.time_runnable,
|
||||
"Runnable time mismatch");
|
||||
TEST_ASSERT(rs->time[RUNSTATE_blocked] == rst.u.runstate.time_blocked,
|
||||
"Blocked time mismatch");
|
||||
TEST_ASSERT(rs->time[RUNSTATE_offline] == rst.u.runstate.time_offline,
|
||||
"Offline time mismatch");
|
||||
TEST_ASSERT(rs->time[RUNSTATE_offline + 1] == 0xa5a5a5a5a5a5a5a5ULL,
|
||||
"Structure overrun");
|
||||
|
||||
TEST_ASSERT(rs->state_entry_time == rs->time[0] +
|
||||
rs->time[1] + rs->time[2] + rs->time[3],
|
||||
"runstate times don't add up");
|
||||
}
|
||||
}
|
||||
|
||||
kvm_vm_free(vm);
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue