KVM: x86/xen: add support for 32-bit guests in SCHEDOP_poll
This patch introduces compat version of struct sched_poll for SCHEDOP_poll sub-operation of sched_op hypercall, reads correct amount of data (16 bytes in 32-bit case, 24 bytes otherwise) by using new compat_sched_poll struct, copies it to sched_poll properly, and lets rest of the code run as is. Signed-off-by: Metin Kaya <metikaya@amazon.com> Signed-off-by: David Woodhouse <dwmw@amazon.co.uk> Reviewed-by: Paul Durrant <paul@xen.org>
This commit is contained in:
Родитель
df0bb47baa
Коммит
214b0a88c4
|
@ -1201,20 +1201,45 @@ static bool kvm_xen_schedop_poll(struct kvm_vcpu *vcpu, bool longmode,
|
|||
evtchn_port_t port, *ports;
|
||||
gpa_t gpa;
|
||||
|
||||
if (!longmode || !lapic_in_kernel(vcpu) ||
|
||||
if (!lapic_in_kernel(vcpu) ||
|
||||
!(vcpu->kvm->arch.xen_hvm_config.flags & KVM_XEN_HVM_CONFIG_EVTCHN_SEND))
|
||||
return false;
|
||||
|
||||
idx = srcu_read_lock(&vcpu->kvm->srcu);
|
||||
gpa = kvm_mmu_gva_to_gpa_system(vcpu, param, NULL);
|
||||
srcu_read_unlock(&vcpu->kvm->srcu, idx);
|
||||
|
||||
if (!gpa || kvm_vcpu_read_guest(vcpu, gpa, &sched_poll,
|
||||
sizeof(sched_poll))) {
|
||||
if (!gpa) {
|
||||
*r = -EFAULT;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_64BIT) && !longmode) {
|
||||
struct compat_sched_poll sp32;
|
||||
|
||||
/* Sanity check that the compat struct definition is correct */
|
||||
BUILD_BUG_ON(sizeof(sp32) != 16);
|
||||
|
||||
if (kvm_vcpu_read_guest(vcpu, gpa, &sp32, sizeof(sp32))) {
|
||||
*r = -EFAULT;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a 32-bit pointer to an array of evtchn_port_t which
|
||||
* are uint32_t, so once it's converted no further compat
|
||||
* handling is needed.
|
||||
*/
|
||||
sched_poll.ports = (void *)(unsigned long)(sp32.ports);
|
||||
sched_poll.nr_ports = sp32.nr_ports;
|
||||
sched_poll.timeout = sp32.timeout;
|
||||
} else {
|
||||
if (kvm_vcpu_read_guest(vcpu, gpa, &sched_poll,
|
||||
sizeof(sched_poll))) {
|
||||
*r = -EFAULT;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (unlikely(sched_poll.nr_ports > 1)) {
|
||||
/* Xen (unofficially) limits number of pollers to 128 */
|
||||
if (sched_poll.nr_ports > 128) {
|
||||
|
|
|
@ -207,4 +207,11 @@ struct compat_vcpu_runstate_info {
|
|||
uint64_t time[4];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct compat_sched_poll {
|
||||
/* This is actually a guest virtual address which points to ports. */
|
||||
uint32_t ports;
|
||||
unsigned int nr_ports;
|
||||
uint64_t timeout;
|
||||
};
|
||||
|
||||
#endif /* __ARCH_X86_KVM_XEN_H__ */
|
||||
|
|
Загрузка…
Ссылка в новой задаче