Commit 56b9ae78 authored by Vitaly Kuznetsov's avatar Vitaly Kuznetsov Committed by Radim Krčmář

KVM: x86: hyperv: do rep check for each hypercall separately

Prepare to support TLB flush hypercalls, some of which are REP hypercalls.
Also, return HV_STATUS_INVALID_HYPERCALL_INPUT as it seems more
appropriate.
Signed-off-by: default avatarVitaly Kuznetsov <vkuznets@redhat.com>
Signed-off-by: default avatarRadim Krčmář <rkrcmar@redhat.com>
parent 142c95da
...@@ -1311,7 +1311,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) ...@@ -1311,7 +1311,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
{ {
u64 param, ingpa, outgpa, ret = HV_STATUS_SUCCESS; u64 param, ingpa, outgpa, ret = HV_STATUS_SUCCESS;
uint16_t code, rep_idx, rep_cnt; uint16_t code, rep_idx, rep_cnt;
bool fast, longmode; bool fast, longmode, rep;
/* /*
* hypercall generates UD from non zero cpl and real mode * hypercall generates UD from non zero cpl and real mode
...@@ -1344,28 +1344,31 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) ...@@ -1344,28 +1344,31 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
fast = !!(param & HV_HYPERCALL_FAST_BIT); fast = !!(param & HV_HYPERCALL_FAST_BIT);
rep_cnt = (param >> HV_HYPERCALL_REP_COMP_OFFSET) & 0xfff; rep_cnt = (param >> HV_HYPERCALL_REP_COMP_OFFSET) & 0xfff;
rep_idx = (param >> HV_HYPERCALL_REP_START_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); 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) { switch (code) {
case HVCALL_NOTIFY_LONG_SPIN_WAIT: case HVCALL_NOTIFY_LONG_SPIN_WAIT:
if (unlikely(rep)) {
ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
break;
}
kvm_vcpu_on_spin(vcpu, true); kvm_vcpu_on_spin(vcpu, true);
break; break;
case HVCALL_SIGNAL_EVENT: case HVCALL_SIGNAL_EVENT:
if (unlikely(rep)) {
ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
break;
}
ret = kvm_hvcall_signal_event(vcpu, fast, ingpa); ret = kvm_hvcall_signal_event(vcpu, fast, ingpa);
if (ret != HV_STATUS_INVALID_PORT_ID) if (ret != HV_STATUS_INVALID_PORT_ID)
break; break;
/* maybe userspace knows this conn_id: fall through */ /* maybe userspace knows this conn_id: fall through */
case HVCALL_POST_MESSAGE: case HVCALL_POST_MESSAGE:
/* don't bother userspace if it has no way to handle it */ /* don't bother userspace if it has no way to handle it */
if (!vcpu_to_synic(vcpu)->active) { if (unlikely(rep || !vcpu_to_synic(vcpu)->active)) {
ret = HV_STATUS_INVALID_HYPERCALL_CODE; ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
break; break;
} }
vcpu->run->exit_reason = KVM_EXIT_HYPERV; vcpu->run->exit_reason = KVM_EXIT_HYPERV;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment