|
@@ -1311,7 +1311,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
|
|
|
{
|
|
|
u64 param, ingpa, outgpa, ret = HV_STATUS_SUCCESS;
|
|
|
uint16_t code, rep_idx, rep_cnt;
|
|
|
- bool fast, longmode;
|
|
|
+ bool fast, longmode, rep;
|
|
|
|
|
|
/*
|
|
|
* hypercall generates UD from non zero cpl and real mode
|
|
@@ -1344,28 +1344,31 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
|
|
|
fast = !!(param & HV_HYPERCALL_FAST_BIT);
|
|
|
rep_cnt = (param >> HV_HYPERCALL_REP_COMP_OFFSET) & 0xfff;
|
|
|
rep_idx = (param >> HV_HYPERCALL_REP_START_OFFSET) & 0xfff;
|
|
|
+ rep = !!(rep_cnt || rep_idx);
|
|
|
|
|
|
trace_kvm_hv_hypercall(code, fast, rep_cnt, rep_idx, ingpa, outgpa);
|
|
|
|
|
|
- /* Hypercall continuation is not supported yet */
|
|
|
- if (rep_cnt || rep_idx) {
|
|
|
- ret = HV_STATUS_INVALID_HYPERCALL_CODE;
|
|
|
- goto set_result;
|
|
|
- }
|
|
|
-
|
|
|
switch (code) {
|
|
|
case HVCALL_NOTIFY_LONG_SPIN_WAIT:
|
|
|
+ if (unlikely(rep)) {
|
|
|
+ ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
|
|
|
+ break;
|
|
|
+ }
|
|
|
kvm_vcpu_on_spin(vcpu, true);
|
|
|
break;
|
|
|
case HVCALL_SIGNAL_EVENT:
|
|
|
+ if (unlikely(rep)) {
|
|
|
+ ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
|
|
|
+ break;
|
|
|
+ }
|
|
|
ret = kvm_hvcall_signal_event(vcpu, fast, ingpa);
|
|
|
if (ret != HV_STATUS_INVALID_PORT_ID)
|
|
|
break;
|
|
|
/* maybe userspace knows this conn_id: fall through */
|
|
|
case HVCALL_POST_MESSAGE:
|
|
|
/* don't bother userspace if it has no way to handle it */
|
|
|
- if (!vcpu_to_synic(vcpu)->active) {
|
|
|
- ret = HV_STATUS_INVALID_HYPERCALL_CODE;
|
|
|
+ if (unlikely(rep || !vcpu_to_synic(vcpu)->active)) {
|
|
|
+ ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
|
|
|
break;
|
|
|
}
|
|
|
vcpu->run->exit_reason = KVM_EXIT_HYPERV;
|