From patchwork Thu Oct 25 04:48:30 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Isaku Yamahata X-Patchwork-Id: 10655413 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0D5F3109C for ; Thu, 25 Oct 2018 04:48:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EE8AC2B5FD for ; Thu, 25 Oct 2018 04:48:53 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E30502B604; Thu, 25 Oct 2018 04:48:53 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5B6842B5FD for ; Thu, 25 Oct 2018 04:48:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727319AbeJYNTv (ORCPT ); Thu, 25 Oct 2018 09:19:51 -0400 Received: from mail-pl1-f196.google.com ([209.85.214.196]:46297 "EHLO mail-pl1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727117AbeJYNTv (ORCPT ); Thu, 25 Oct 2018 09:19:51 -0400 Received: by mail-pl1-f196.google.com with SMTP id bb7-v6so3261602plb.13 for ; Wed, 24 Oct 2018 21:48:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=bSjp3s9DLyYbgztrIYqrd3rH843Jpz7kuU78RkYsPyg=; b=nslAKYrFEmyC6wqbMq4R7gQni1ID2ndwldz9VIqfwpNPJJFRH6pWS6X0fjcbnZ/8MG sg4M9AKPh/3mRtmCtQlGyCpSchfnJwOpvEAy//AH74bildTisE17SUyV+zr556yp1jUc W/DQR3rXMrKxayKAo4GOlZPYrt+Z9Eb3s1Dvm8KYUiMRHXhXHefnIGxGjSuhFYA14pxf xWMP4NNXYWMhNNhuSjrhJDTB0cn6gNzlpiYhkju4yNjfOhvJ+srxp8ojAaccUIgDR5mC o5C9VieKFcJEX9NuVzI9BwJVo1b49gXvxT9Sr2LmPiRXxFTC+g7AELfSBfwV2oRyRSWG GdRQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=bSjp3s9DLyYbgztrIYqrd3rH843Jpz7kuU78RkYsPyg=; b=VB2KBlvxOq8keUNT6VkO34/oO/eUwxvdh+9AXbO+vcvQVuFIxRvfJAi/AgDtjM8+Ig AFfBEtnPmcW2uOuPdUOA3JbVxcie4PwhjezkU/ltFCM4wTqoZBHEPlg/yucI2Za7knAp 4zv5rWZu/yMgH2BvXulTPwMHvryvQ+CFGXvc6ecX5VwxQ3kjwW8CUBecPsbeVvzDhYEq O+zZF+foC1RVkd+YNAO6/GCa+PYzrPOjBqmNK3BlqukRhOcl2Kvi+gY6UgZVtXmtA4sM HkZHu6utPgKCqJCBrETX6zM1MqRHcGLsKofFKX7RP6L6nNOWzjquBwoApufMS6tMi6CE nevQ== X-Gm-Message-State: AGRZ1gKbZPZdSaTjUfpxiVWEckmz8b+TBylqcXyTrzg1TaK8qj4fFQH4 WMgpXDrD8loZmzrSi1vRzQOnDRFF X-Google-Smtp-Source: AJdET5ePSw6EbixRYawA+xU+gU5DThisUS0MwJT3G4hpR0JTB8X78SGA5A7NJWvEhjYzPaJz4rnKAw== X-Received: by 2002:a17:902:4222:: with SMTP id g31-v6mr27393pld.281.1540442930964; Wed, 24 Oct 2018 21:48:50 -0700 (PDT) Received: from localhost (c-73-189-176-234.hsd1.ca.comcast.net. [73.189.176.234]) by smtp.gmail.com with ESMTPSA id k132-v6sm12260851pga.28.2018.10.24.21.48.49 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Wed, 24 Oct 2018 21:48:50 -0700 (PDT) From: Isaku Yamahata To: kvm@vger.kernel.org Cc: pbonzini@redhat.com, rkrcmar@redhat.com, vkuznets@redhat.com, kys@microsoft.com, Tianyu.Lan@microsoft.com, yi.y.sun@intel.com, chao.gao@intel.com, isaku.yamahta@intel.com, Isaku Yamahata Subject: [PATCH v2 5/6] x86/kvm/hyperv: implement xmm fast hypercall Date: Wed, 24 Oct 2018 21:48:30 -0700 Message-Id: <07ed3988561beabb9bd8c83c48df6f111227fe50.1540441925.git.isaku.yamahata@gmail.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: References: In-Reply-To: References: Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch makes kvm supports hyper-v xmm fast hypercall. In order to enable guest to use it, qemu needs patch to return appropriate feature bits to cpuid. Signed-off-by: Isaku Yamahata --- arch/x86/kvm/hyperv.c | 101 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 81 insertions(+), 20 deletions(-) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index 01d209ab5481..6408629a1b4c 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -1269,8 +1269,30 @@ static __always_inline int get_sparse_bank_no(u64 valid_bank_mask, int bank_no) return i; } -static u64 kvm_hv_flush_tlb(struct kvm_vcpu *current_vcpu, u64 ingpa, - u16 rep_cnt, bool ex) +static void kvm_hv_get_xmm_input(struct kvm_vcpu *current_vcpu, + u64 rdx, u64 r8, void *input, size_t ibytes) +{ + u64 *tmp = input; + tmp[0] = rdx; + tmp[1] = r8; + memcpy((u8 *)input + 2 * 8, + current_vcpu->arch.guest_fpu.state.fxsave.xmm_space, + ibytes - 2 * 8); +} + +static void kvm_hv_get_xmm_input_cont( + struct kvm_vcpu *current_vcpu, + void *input, size_t offset, size_t ibytes) +{ + u8 *xmm_space = + (u8 *)current_vcpu->arch.guest_fpu.state.fxsave.xmm_space; + memcpy(input, xmm_space + (offset - 2 * 8), ibytes); +} + +static u64 kvm_hv_flush_tlb(struct kvm_vcpu *current_vcpu, + bool fast, u16 varhead_size, u16 rep_cnt, + u64 ingpa, u64 r8, + bool ex) { struct kvm *kvm = current_vcpu->kvm; struct kvm_vcpu_hv *hv_current = ¤t_vcpu->arch.hyperv; @@ -1284,8 +1306,13 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *current_vcpu, u64 ingpa, bool all_cpus; if (!ex) { - if (unlikely(kvm_read_guest(kvm, ingpa, &flush, sizeof(flush)))) - return HV_STATUS_INVALID_HYPERCALL_INPUT; + if (fast) { + kvm_hv_get_xmm_input(current_vcpu, ingpa, r8, + &flush, sizeof(flush)); + } else + if (unlikely(kvm_read_guest(kvm, ingpa, + &flush, sizeof(flush)))) + return HV_STATUS_INVALID_HYPERCALL_INPUT; trace_kvm_hv_flush_tlb(flush.processor_mask, flush.address_space, flush.flags); @@ -1293,9 +1320,16 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *current_vcpu, u64 ingpa, sparse_banks[0] = flush.processor_mask; all_cpus = flush.flags & HV_FLUSH_ALL_PROCESSORS; } else { - if (unlikely(kvm_read_guest(kvm, ingpa, &flush_ex, - sizeof(flush_ex)))) - return HV_STATUS_INVALID_HYPERCALL_INPUT; + if (fast) { + if (unlikely(sizeof(flush_ex) + varhead_size * 8 > + HV_XMM_BYTE_MAX)) + return HV_STATUS_INVALID_HYPERCALL_INPUT; + kvm_hv_get_xmm_input(current_vcpu, ingpa, r8, + &flush_ex, sizeof(flush_ex)); + } else + if (unlikely(kvm_read_guest(kvm, ingpa, &flush_ex, + sizeof(flush_ex)))) + return HV_STATUS_INVALID_HYPERCALL_INPUT; trace_kvm_hv_flush_tlb_ex(flush_ex.hv_vp_set.valid_bank_mask, flush_ex.hv_vp_set.format, @@ -1312,13 +1346,20 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *current_vcpu, u64 ingpa, if (!sparse_banks_len && !all_cpus) goto ret_success; - if (!all_cpus && - kvm_read_guest(kvm, - ingpa + offsetof(struct hv_tlb_flush_ex, - hv_vp_set.bank_contents), - sparse_banks, - sparse_banks_len)) - return HV_STATUS_INVALID_HYPERCALL_INPUT; + if (!all_cpus) { + if (fast) + kvm_hv_get_xmm_input_cont( + current_vcpu, sparse_banks, + sizeof(flush_ex), sparse_banks_len); + else if (kvm_read_guest( + kvm, + ingpa + + offsetof(struct hv_tlb_flush_ex, + hv_vp_set.bank_contents), + sparse_banks, + sparse_banks_len)) + return HV_STATUS_INVALID_HYPERCALL_INPUT; + } } cpumask_clear(&hv_current->tlb_lush); @@ -1443,6 +1484,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) { u64 param, ingpa, outgpa, ret = HV_STATUS_SUCCESS; uint16_t code, rep_idx, rep_cnt; + uint16_t varhead_size; bool fast, longmode, rep; /* @@ -1474,6 +1516,8 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) code = param & 0xffff; fast = !!(param & HV_HYPERCALL_FAST_BIT); + varhead_size = (param & HV_HYPERCALL_VARHEAD_MASK) >> + HV_HYPERCALL_VARHEAD_OFFSET; rep_cnt = (param >> HV_HYPERCALL_REP_COMP_OFFSET) & 0xfff; rep_idx = (param >> HV_HYPERCALL_REP_START_OFFSET) & 0xfff; rep = !!(rep_cnt || rep_idx); @@ -1503,6 +1547,19 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) ret = HV_STATUS_INVALID_HYPERCALL_INPUT; break; } + if (fast) { + u8 payloadsize = outgpa & 0xf; + +/* struct hv_input_post_message isn't exported + offsetof(struct hv_input_post_message, payload) = 16 */ +#define HV_INPUT_POST_MESSAGE_HEADER_SIZE 16 + if (unlikely(HV_INPUT_POST_MESSAGE_HEADER_SIZE + + payloadsize > HV_XMM_BYTE_MAX)) { + ret = HV_STATUS_INVALID_HYPERCALL_INPUT; + break; + } + } + vcpu->run->exit_reason = KVM_EXIT_HYPERV; vcpu->run->hyperv.type = KVM_EXIT_HYPERV_HCALL; vcpu->run->hyperv.u.hcall.input = param; @@ -1516,28 +1573,32 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) ret = HV_STATUS_INVALID_HYPERCALL_INPUT; break; } - ret = kvm_hv_flush_tlb(vcpu, ingpa, rep_cnt, false); + ret = kvm_hv_flush_tlb(vcpu, fast, varhead_size, rep_cnt, + ingpa, outgpa, false); break; case HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE: - if (unlikely(fast || rep)) { + if (unlikely(rep)) { ret = HV_STATUS_INVALID_HYPERCALL_INPUT; break; } - ret = kvm_hv_flush_tlb(vcpu, ingpa, rep_cnt, false); + ret = kvm_hv_flush_tlb(vcpu, fast, varhead_size, rep_cnt, + ingpa, outgpa, false); break; case HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST_EX: if (unlikely(fast || !rep_cnt || rep_idx)) { ret = HV_STATUS_INVALID_HYPERCALL_INPUT; break; } - ret = kvm_hv_flush_tlb(vcpu, ingpa, rep_cnt, true); + ret = kvm_hv_flush_tlb(vcpu, fast, varhead_size, rep_cnt, + ingpa, outgpa, true); break; case HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX: - if (unlikely(fast || rep)) { + if (unlikely(rep)) { ret = HV_STATUS_INVALID_HYPERCALL_INPUT; break; } - ret = kvm_hv_flush_tlb(vcpu, ingpa, rep_cnt, true); + ret = kvm_hv_flush_tlb(vcpu, fast, varhead_size, rep_cnt, + ingpa, outgpa, true); break; default: ret = HV_STATUS_INVALID_HYPERCALL_CODE;