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: Vitaly Kuznetsov <vkuzn...@redhat.com>
---
 arch/x86/kvm/hyperv.c | 21 ++++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
index 3cb3bb68db7e..67788d358200 100644
--- a/arch/x86/kvm/hyperv.c
+++ b/arch/x86/kvm/hyperv.c
@@ -1309,7 +1309,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
@@ -1342,28 +1342,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;
-- 
2.14.3

Reply via email to