From patchwork Sun Dec 6 11:03:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 11953981 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F1AB1C4361B for ; Sun, 6 Dec 2020 11:05:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C987D22E03 for ; Sun, 6 Dec 2020 11:05:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727357AbgLFLE6 (ORCPT ); Sun, 6 Dec 2020 06:04:58 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41902 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727222AbgLFLE4 (ORCPT ); Sun, 6 Dec 2020 06:04:56 -0500 Received: from casper.infradead.org (casper.infradead.org [IPv6:2001:8b0:10b:1236::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B81D5C08E85E for ; Sun, 6 Dec 2020 03:03:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description; bh=nlfk7fo9/eeQqoeGTfsdj4FxMlsVP85cXV+6FJSJYMM=; b=O2x6d4bPmJGITcMUN77cll6T7y 02NWycxomf8VGEz2y2nzo0WLpbDrUtYORtFqNi0ZDpjWYJuEcLMdLbnSEVob6Nxr79jIHxVqzTG0O 8vevSkUhEAYeN4LHA3cLpuMCtzwGFM/J0NM8e5wWwElkx6QdZdatJ3vWnfsI6dt45IboOs7dl9qJv +E3aCEi3cYG1hN88WA5V33zVa2gZ7h8x4UNv0VpazwHo3ucuMi11cXNmJ70vKFv3axaYadFy9ViXn MJOcwIkTmuSDQBAgQWpoD/JO/bfE942n7RAONqWUqtfzmM6xvejtnudLj7MIGx9+mpEroe3T8Ip64 HvZ89Rgw==; Received: from i7.infradead.org ([2001:8b0:10b:1:21e:67ff:fecb:7a92]) by casper.infradead.org with esmtpsa (Exim 4.92.3 #3 (Red Hat Linux)) id 1klrpE-0006Fo-0H; Sun, 06 Dec 2020 11:03:37 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1klrpD-000jpA-JD; Sun, 06 Dec 2020 11:03:31 +0000 From: David Woodhouse To: kvm@vger.kernel.org Cc: Paolo Bonzini , Ankur Arora , Joao Martins , Boris Ostrovsky , Sean Christopherson , graf@amazon.com, iaslan@amazon.de Subject: [PATCH v2 01/16] KVM: Fix arguments to kvm_{un,}map_gfn() Date: Sun, 6 Dec 2020 11:03:12 +0000 Message-Id: <20201206110327.175629-2-dwmw2@infradead.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201206110327.175629-1-dwmw2@infradead.org> References: <20201206110327.175629-1-dwmw2@infradead.org> MIME-Version: 1.0 Sender: David Woodhouse X-SRS-Rewrite: SMTP reverse-path rewritten from by casper.infradead.org. See http://www.infradead.org/rpr.html Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: David Woodhouse It shouldn't take a vcpu. Signed-off-by: David Woodhouse --- arch/x86/kvm/x86.c | 8 ++++---- include/linux/kvm_host.h | 4 ++-- virt/kvm/kvm_main.c | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index e545a8a613b1..c7f1ba21212e 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2957,7 +2957,7 @@ static void record_steal_time(struct kvm_vcpu *vcpu) return; /* -EAGAIN is returned in atomic context so we can just return. */ - if (kvm_map_gfn(vcpu, vcpu->arch.st.msr_val >> PAGE_SHIFT, + if (kvm_map_gfn(vcpu->kvm, vcpu->arch.st.msr_val >> PAGE_SHIFT, &map, &vcpu->arch.st.cache, false)) return; @@ -2992,7 +2992,7 @@ static void record_steal_time(struct kvm_vcpu *vcpu) st->version += 1; - kvm_unmap_gfn(vcpu, &map, &vcpu->arch.st.cache, true, false); + kvm_unmap_gfn(vcpu->kvm, &map, &vcpu->arch.st.cache, true, false); } int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) @@ -3981,7 +3981,7 @@ static void kvm_steal_time_set_preempted(struct kvm_vcpu *vcpu) if (vcpu->arch.st.preempted) return; - if (kvm_map_gfn(vcpu, vcpu->arch.st.msr_val >> PAGE_SHIFT, &map, + if (kvm_map_gfn(vcpu->kvm, vcpu->arch.st.msr_val >> PAGE_SHIFT, &map, &vcpu->arch.st.cache, true)) return; @@ -3990,7 +3990,7 @@ static void kvm_steal_time_set_preempted(struct kvm_vcpu *vcpu) st->preempted = vcpu->arch.st.preempted = KVM_VCPU_PREEMPTED; - kvm_unmap_gfn(vcpu, &map, &vcpu->arch.st.cache, true, true); + kvm_unmap_gfn(vcpu->kvm, &map, &vcpu->arch.st.cache, true, true); } void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 7f2e2a09ebbd..8eb5eb1399f5 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -806,11 +806,11 @@ struct kvm_memory_slot *kvm_vcpu_gfn_to_memslot(struct kvm_vcpu *vcpu, gfn_t gfn kvm_pfn_t kvm_vcpu_gfn_to_pfn_atomic(struct kvm_vcpu *vcpu, gfn_t gfn); kvm_pfn_t kvm_vcpu_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn); int kvm_vcpu_map(struct kvm_vcpu *vcpu, gpa_t gpa, struct kvm_host_map *map); -int kvm_map_gfn(struct kvm_vcpu *vcpu, gfn_t gfn, struct kvm_host_map *map, +int kvm_map_gfn(struct kvm *kvm, gfn_t gfn, struct kvm_host_map *map, struct gfn_to_pfn_cache *cache, bool atomic); struct page *kvm_vcpu_gfn_to_page(struct kvm_vcpu *vcpu, gfn_t gfn); void kvm_vcpu_unmap(struct kvm_vcpu *vcpu, struct kvm_host_map *map, bool dirty); -int kvm_unmap_gfn(struct kvm_vcpu *vcpu, struct kvm_host_map *map, +int kvm_unmap_gfn(struct kvm *kvm, struct kvm_host_map *map, struct gfn_to_pfn_cache *cache, bool dirty, bool atomic); unsigned long kvm_vcpu_gfn_to_hva(struct kvm_vcpu *vcpu, gfn_t gfn); unsigned long kvm_vcpu_gfn_to_hva_prot(struct kvm_vcpu *vcpu, gfn_t gfn, bool *writable); diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 2541a17ff1c4..f01a8df7806a 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -2181,10 +2181,10 @@ static int __kvm_map_gfn(struct kvm_memslots *slots, gfn_t gfn, return 0; } -int kvm_map_gfn(struct kvm_vcpu *vcpu, gfn_t gfn, struct kvm_host_map *map, +int kvm_map_gfn(struct kvm *kvm, gfn_t gfn, struct kvm_host_map *map, struct gfn_to_pfn_cache *cache, bool atomic) { - return __kvm_map_gfn(kvm_memslots(vcpu->kvm), gfn, map, + return __kvm_map_gfn(kvm_memslots(kvm), gfn, map, cache, atomic); } EXPORT_SYMBOL_GPL(kvm_map_gfn); @@ -2232,10 +2232,10 @@ static void __kvm_unmap_gfn(struct kvm_memory_slot *memslot, map->page = NULL; } -int kvm_unmap_gfn(struct kvm_vcpu *vcpu, struct kvm_host_map *map, +int kvm_unmap_gfn(struct kvm *kvm, struct kvm_host_map *map, struct gfn_to_pfn_cache *cache, bool dirty, bool atomic) { - __kvm_unmap_gfn(gfn_to_memslot(vcpu->kvm, map->gfn), map, + __kvm_unmap_gfn(gfn_to_memslot(kvm, map->gfn), map, cache, dirty, atomic); return 0; } From patchwork Sun Dec 6 11:03:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 11953963 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 37886C433FE for ; Sun, 6 Dec 2020 11:04:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id F407F2312E for ; Sun, 6 Dec 2020 11:04:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726518AbgLFLER (ORCPT ); Sun, 6 Dec 2020 06:04:17 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41786 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725822AbgLFLEQ (ORCPT ); Sun, 6 Dec 2020 06:04:16 -0500 Received: from merlin.infradead.org (merlin.infradead.org [IPv6:2001:8b0:10b:1231::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BC496C061A4F for ; Sun, 6 Dec 2020 03:03:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description; bh=8hfS3XSAx8xJPIi8D8GGgdIke2hQZGCrmW6/wCkicg0=; b=zgdQh5ULh3jseypBfyegNTH9zW WA0PFUmP4NE1wYaOgsUY00m5xW3Gpp0Ztyzgm93msOFbg8tiQD1f3maAGnpiEpUNk7b7Ablf9CSRI dyI+qZNZxq071PDyocALkMPRJ7oWOnNktQNYubNwmTgb3cowM5pD+n7oscjDLDUvaozgjUmOFp9rg tuM0BXo0RaqhCWmctkuZs+lRBPzX0t4ZyUMQLHyKJZfzjMy6Lf7i1xCmjib6phnEQBJfBZ6gPVw6z HOOKAtQ+Yk4UlqyxsRMZ8ZFBVqritVThhx65V2WEpVf/kI/r8NDakWqF8GtCe/KGiYREyRJtzKMxv MqP60m0w==; Received: from i7.infradead.org ([2001:8b0:10b:1:21e:67ff:fecb:7a92]) by merlin.infradead.org with esmtpsa (Exim 4.92.3 #3 (Red Hat Linux)) id 1klrpE-0004tF-Lf; Sun, 06 Dec 2020 11:03:32 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1klrpD-000jpD-Jo; Sun, 06 Dec 2020 11:03:31 +0000 From: David Woodhouse To: kvm@vger.kernel.org Cc: Paolo Bonzini , Ankur Arora , Joao Martins , Boris Ostrovsky , Sean Christopherson , graf@amazon.com, iaslan@amazon.de Subject: [PATCH v2 02/16] KVM: x86/xen: fix Xen hypercall page msr handling Date: Sun, 6 Dec 2020 11:03:13 +0000 Message-Id: <20201206110327.175629-3-dwmw2@infradead.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201206110327.175629-1-dwmw2@infradead.org> References: <20201206110327.175629-1-dwmw2@infradead.org> MIME-Version: 1.0 Sender: David Woodhouse X-SRS-Rewrite: SMTP reverse-path rewritten from by merlin.infradead.org. See http://www.infradead.org/rpr.html Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Joao Martins Xen usually places its MSR at 0x40000000 or 0x40000200 depending on whether it is running in viridian mode or not. Note that this is not ABI guaranteed, so it is possible for Xen to advertise the MSR some place else. Given the way xen_hvm_config() is handled, if the former address is selected, this will conflict with Hyper-V's MSR (HV_X64_MSR_GUEST_OS_ID) which unconditionally uses the same address. Given that the MSR location is arbitrary, move the xen_hvm_config() handling to the top of kvm_set_msr_common() before falling through. Signed-off-by: Joao Martins Signed-off-by: David Woodhouse --- arch/x86/kvm/x86.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index c7f1ba21212e..13ba4a64f748 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -3001,6 +3001,9 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) u32 msr = msr_info->index; u64 data = msr_info->data; + if (msr && (msr == vcpu->kvm->arch.xen_hvm_config.msr)) + return xen_hvm_config(vcpu, data); + switch (msr) { case MSR_AMD64_NB_CFG: case MSR_IA32_UCODE_WRITE: @@ -3288,8 +3291,6 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) vcpu->arch.msr_misc_features_enables = data; break; default: - if (msr && (msr == vcpu->kvm->arch.xen_hvm_config.msr)) - return xen_hvm_config(vcpu, data); if (kvm_pmu_is_valid_msr(vcpu, msr)) return kvm_pmu_set_msr(vcpu, msr_info); return KVM_MSR_RET_INVALID; From patchwork Sun Dec 6 11:03:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 11953989 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2C25CC4167B for ; Sun, 6 Dec 2020 11:05:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0450D22E03 for ; Sun, 6 Dec 2020 11:05:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727345AbgLFLE5 (ORCPT ); Sun, 6 Dec 2020 06:04:57 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41898 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727167AbgLFLE4 (ORCPT ); Sun, 6 Dec 2020 06:04:56 -0500 Received: from merlin.infradead.org (merlin.infradead.org [IPv6:2001:8b0:10b:1231::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E9F11C061A56 for ; Sun, 6 Dec 2020 03:03:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc: To:From:Reply-To:Content-ID:Content-Description; bh=3dWGRrPSkgJj/qyEjMabRSQKP5KEHEP8l3PQx7nFI30=; b=eDbVVOpRErZY9kFnTtDv7mD6sr SbCEqd4A1ns2nHZiqs+SxyTDF8BZQn54M/Ew8tXhXgPsxEVy3sJgj7zPn8GsDyARa3qdMq+60rcEa g0iW2zwCl4BBmigXRWoJvijyRuewf63GtTfcmg2rWDDagpK9pjDPpQNcq+DOcGyClBSGjo8h2flrd 8Jsf8uTc2f7uF9fzwUAVTkk+FGmqMG1ybpEkT7Tl+ZWBPPZWX7lSXBO8yTgYZuU1QNzdTlTb4wESV wA6abbnY4pFNZ3K/k0MwL/C+t8ZezbOlC94RzNP0gLtkvWeVtVQgYJgowsqO6dX8YA/IJncVa3vIS RSFjc41A==; Received: from i7.infradead.org ([2001:8b0:10b:1:21e:67ff:fecb:7a92]) by merlin.infradead.org with esmtpsa (Exim 4.92.3 #3 (Red Hat Linux)) id 1klrpE-0004tG-N2; Sun, 06 Dec 2020 11:03:33 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1klrpD-000jpG-KT; Sun, 06 Dec 2020 11:03:31 +0000 From: David Woodhouse To: kvm@vger.kernel.org Cc: Paolo Bonzini , Ankur Arora , Joao Martins , Boris Ostrovsky , Sean Christopherson , graf@amazon.com, iaslan@amazon.de Subject: [PATCH v2 03/16] KVM: x86/xen: intercept xen hypercalls if enabled Date: Sun, 6 Dec 2020 11:03:14 +0000 Message-Id: <20201206110327.175629-4-dwmw2@infradead.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201206110327.175629-1-dwmw2@infradead.org> References: <20201206110327.175629-1-dwmw2@infradead.org> MIME-Version: 1.0 Sender: David Woodhouse X-SRS-Rewrite: SMTP reverse-path rewritten from by merlin.infradead.org. See http://www.infradead.org/rpr.html Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Joao Martins Add a new exit reason for emulator to handle Xen hypercalls. Since this means KVM owns the ABI, dispense with the facility for the VMM to provide its own copy of the hypercall pages; just fill them in directly using VMCALL/VMMCALL as we do for the Hyper-V hypercall page. This behaviour is enabled by a new INTERCEPT_HCALL flag in the KVM_XEN_HVM_CONFIG ioctl structure, and advertised by the same flag being returned from the KVM_CAP_XEN_HVM check. Add a test case and shift xen_hvm_config() to the nascent xen.c while we're at it. Signed-off-by: Joao Martins Signed-off-by: David Woodhouse Reported-by: kernel test robot --- arch/x86/include/asm/kvm_host.h | 6 + arch/x86/kvm/Makefile | 2 +- arch/x86/kvm/trace.h | 36 +++++ arch/x86/kvm/x86.c | 47 +++--- arch/x86/kvm/xen.c | 140 ++++++++++++++++++ arch/x86/kvm/xen.h | 21 +++ include/uapi/linux/kvm.h | 20 +++ tools/testing/selftests/kvm/Makefile | 1 + tools/testing/selftests/kvm/lib/kvm_util.c | 1 + .../selftests/kvm/x86_64/xen_vmcall_test.c | 123 +++++++++++++++ 10 files changed, 367 insertions(+), 30 deletions(-) create mode 100644 arch/x86/kvm/xen.c create mode 100644 arch/x86/kvm/xen.h create mode 100644 tools/testing/selftests/kvm/x86_64/xen_vmcall_test.c diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 7e5f33a0d0e2..9de3229e91e1 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -520,6 +520,11 @@ struct kvm_vcpu_hv { cpumask_t tlb_flush; }; +/* Xen HVM per vcpu emulation context */ +struct kvm_vcpu_xen { + u64 hypercall_rip; +}; + struct kvm_vcpu_arch { /* * rip and regs accesses must go through @@ -717,6 +722,7 @@ struct kvm_vcpu_arch { unsigned long singlestep_rip; struct kvm_vcpu_hv hyperv; + struct kvm_vcpu_xen xen; cpumask_var_t wbinvd_dirty_mask; diff --git a/arch/x86/kvm/Makefile b/arch/x86/kvm/Makefile index b804444e16d4..8bee4afc1fec 100644 --- a/arch/x86/kvm/Makefile +++ b/arch/x86/kvm/Makefile @@ -13,7 +13,7 @@ kvm-y += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o \ $(KVM)/eventfd.o $(KVM)/irqchip.o $(KVM)/vfio.o kvm-$(CONFIG_KVM_ASYNC_PF) += $(KVM)/async_pf.o -kvm-y += x86.o emulate.o i8259.o irq.o lapic.o \ +kvm-y += x86.o emulate.o i8259.o irq.o lapic.o xen.o \ i8254.o ioapic.o irq_comm.o cpuid.o pmu.o mtrr.o \ hyperv.o debugfs.o mmu/mmu.o mmu/page_track.o \ mmu/spte.o mmu/tdp_iter.o mmu/tdp_mmu.o diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h index aef960f90f26..d28ecb37b62c 100644 --- a/arch/x86/kvm/trace.h +++ b/arch/x86/kvm/trace.h @@ -92,6 +92,42 @@ TRACE_EVENT(kvm_hv_hypercall, __entry->outgpa) ); +/* + * Tracepoint for Xen hypercall. + */ +TRACE_EVENT(kvm_xen_hypercall, + TP_PROTO(unsigned long nr, unsigned long a0, unsigned long a1, + unsigned long a2, unsigned long a3, unsigned long a4, + unsigned long a5), + TP_ARGS(nr, a0, a1, a2, a3, a4, a5), + + TP_STRUCT__entry( + __field(unsigned long, nr) + __field(unsigned long, a0) + __field(unsigned long, a1) + __field(unsigned long, a2) + __field(unsigned long, a3) + __field(unsigned long, a4) + __field(unsigned long, a5) + ), + + TP_fast_assign( + __entry->nr = nr; + __entry->a0 = a0; + __entry->a1 = a1; + __entry->a2 = a2; + __entry->a3 = a3; + __entry->a4 = a4; + __entry->a4 = a5; + ), + + TP_printk("nr 0x%lx a0 0x%lx a1 0x%lx a2 0x%lx a3 0x%lx a4 0x%lx a5 %lx", + __entry->nr, __entry->a0, __entry->a1, __entry->a2, + __entry->a3, __entry->a4, __entry->a5) +); + + + /* * Tracepoint for PIO. */ diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 13ba4a64f748..5394dda3e3b0 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -29,6 +29,7 @@ #include "pmu.h" #include "hyperv.h" #include "lapic.h" +#include "xen.h" #include #include @@ -2842,32 +2843,6 @@ static int set_msr_mce(struct kvm_vcpu *vcpu, struct msr_data *msr_info) return 0; } -static int xen_hvm_config(struct kvm_vcpu *vcpu, u64 data) -{ - struct kvm *kvm = vcpu->kvm; - int lm = is_long_mode(vcpu); - u8 *blob_addr = lm ? (u8 *)(long)kvm->arch.xen_hvm_config.blob_addr_64 - : (u8 *)(long)kvm->arch.xen_hvm_config.blob_addr_32; - u8 blob_size = lm ? kvm->arch.xen_hvm_config.blob_size_64 - : kvm->arch.xen_hvm_config.blob_size_32; - u32 page_num = data & ~PAGE_MASK; - u64 page_addr = data & PAGE_MASK; - u8 *page; - - if (page_num >= blob_size) - return 1; - - page = memdup_user(blob_addr + (page_num * PAGE_SIZE), PAGE_SIZE); - if (IS_ERR(page)) - return PTR_ERR(page); - - if (kvm_vcpu_write_guest(vcpu, page_addr, page, PAGE_SIZE)) { - kfree(page); - return 1; - } - return 0; -} - static inline bool kvm_pv_async_pf_enabled(struct kvm_vcpu *vcpu) { u64 mask = KVM_ASYNC_PF_ENABLED | KVM_ASYNC_PF_DELIVERY_AS_INT; @@ -3002,7 +2977,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) u64 data = msr_info->data; if (msr && (msr == vcpu->kvm->arch.xen_hvm_config.msr)) - return xen_hvm_config(vcpu, data); + return kvm_xen_hvm_config(vcpu, data); switch (msr) { case MSR_AMD64_NB_CFG: @@ -3703,7 +3678,6 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_PIT2: case KVM_CAP_PIT_STATE2: case KVM_CAP_SET_IDENTITY_MAP_ADDR: - case KVM_CAP_XEN_HVM: case KVM_CAP_VCPU_EVENTS: case KVM_CAP_HYPERV: case KVM_CAP_HYPERV_VAPIC: @@ -3742,6 +3716,10 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_ENFORCE_PV_FEATURE_CPUID: r = 1; break; + case KVM_CAP_XEN_HVM: + r = KVM_XEN_HVM_CONFIG_HYPERCALL_MSR | + KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL; + break; case KVM_CAP_SYNC_REGS: r = KVM_SYNC_X86_VALID_FIELDS; break; @@ -5603,7 +5581,15 @@ long kvm_arch_vm_ioctl(struct file *filp, if (copy_from_user(&xhc, argp, sizeof(xhc))) goto out; r = -EINVAL; - if (xhc.flags) + if (xhc.flags & ~KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL) + goto out; + /* + * With hypercall interception the kernel generates its own + * hypercall page so it must not be provided. + */ + if ((xhc.flags & KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL) && + (xhc.blob_addr_32 || xhc.blob_addr_64 || + xhc.blob_size_32 || xhc.blob_size_64)) goto out; memcpy(&kvm->arch.xen_hvm_config, &xhc, sizeof(xhc)); r = 0; @@ -8066,6 +8052,9 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) unsigned long nr, a0, a1, a2, a3, ret; int op_64_bit; + if (kvm_xen_hypercall_enabled(vcpu->kvm)) + return kvm_xen_hypercall(vcpu); + if (kvm_hv_hypercall_enabled(vcpu->kvm)) return kvm_hv_hypercall(vcpu); diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c new file mode 100644 index 000000000000..b76d121a86c0 --- /dev/null +++ b/arch/x86/kvm/xen.c @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright © 2019 Oracle and/or its affiliates. All rights reserved. + * Copyright © 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * KVM Xen emulation + */ + +#include "x86.h" +#include "xen.h" + +#include + +#include + +#include "trace.h" + +int kvm_xen_hvm_config(struct kvm_vcpu *vcpu, u64 data) +{ + struct kvm *kvm = vcpu->kvm; + u32 page_num = data & ~PAGE_MASK; + u64 page_addr = data & PAGE_MASK; + + /* + * If Xen hypercall intercept is enabled, fill the hypercall + * page with VMCALL/VMMCALL instructions since that's what + * we catch. Else the VMM has provided the hypercall pages + * with instructions of its own choosing, so use those. + */ + if (kvm_xen_hypercall_enabled(kvm)) { + u8 instructions[32]; + int i; + + if (page_num) + return 1; + + /* mov imm32, %eax */ + instructions[0] = 0xb8; + + /* vmcall / vmmcall */ + kvm_x86_ops.patch_hypercall(vcpu, instructions + 5); + + /* ret */ + instructions[8] = 0xc3; + + /* int3 to pad */ + memset(instructions + 9, 0xcc, sizeof(instructions) - 9); + + for (i = 0; i < PAGE_SIZE / sizeof(instructions); i++) { + *(u32 *)&instructions[1] = i; + if (kvm_vcpu_write_guest(vcpu, + page_addr + (i * sizeof(instructions)), + instructions, sizeof(instructions))) + return 1; + } + } else { + int lm = is_long_mode(vcpu); + u8 *blob_addr = lm ? (u8 *)(long)kvm->arch.xen_hvm_config.blob_addr_64 + : (u8 *)(long)kvm->arch.xen_hvm_config.blob_addr_32; + u8 blob_size = lm ? kvm->arch.xen_hvm_config.blob_size_64 + : kvm->arch.xen_hvm_config.blob_size_32; + u8 *page; + + if (page_num >= blob_size) + return 1; + + page = memdup_user(blob_addr + (page_num * PAGE_SIZE), PAGE_SIZE); + if (IS_ERR(page)) + return PTR_ERR(page); + + if (kvm_vcpu_write_guest(vcpu, page_addr, page, PAGE_SIZE)) { + kfree(page); + return 1; + } + } + return 0; +} + +static int kvm_xen_hypercall_set_result(struct kvm_vcpu *vcpu, u64 result) +{ + kvm_rax_write(vcpu, result); + return kvm_skip_emulated_instruction(vcpu); +} + +static int kvm_xen_hypercall_complete_userspace(struct kvm_vcpu *vcpu) +{ + struct kvm_run *run = vcpu->run; + + if (unlikely(!kvm_is_linear_rip(vcpu, vcpu->arch.xen.hypercall_rip))) + return 1; + + return kvm_xen_hypercall_set_result(vcpu, run->xen.u.hcall.result); +} + +int kvm_xen_hypercall(struct kvm_vcpu *vcpu) +{ + bool longmode; + u64 input, params[6]; + + input = (u64)kvm_register_read(vcpu, VCPU_REGS_RAX); + + longmode = is_64_bit_mode(vcpu); + if (!longmode) { + params[0] = (u32)kvm_rbx_read(vcpu); + params[1] = (u32)kvm_rcx_read(vcpu); + params[2] = (u32)kvm_rdx_read(vcpu); + params[3] = (u32)kvm_rsi_read(vcpu); + params[4] = (u32)kvm_rdi_read(vcpu); + params[5] = (u32)kvm_rbp_read(vcpu); + } +#ifdef CONFIG_X86_64 + else { + params[0] = (u64)kvm_rdi_read(vcpu); + params[1] = (u64)kvm_rsi_read(vcpu); + params[2] = (u64)kvm_rdx_read(vcpu); + params[3] = (u64)kvm_r10_read(vcpu); + params[4] = (u64)kvm_r8_read(vcpu); + params[5] = (u64)kvm_r9_read(vcpu); + } +#endif + trace_kvm_xen_hypercall(input, params[0], params[1], params[2], + params[3], params[4], params[5]); + + vcpu->run->exit_reason = KVM_EXIT_XEN; + vcpu->run->xen.type = KVM_EXIT_XEN_HCALL; + vcpu->run->xen.u.hcall.longmode = longmode; + vcpu->run->xen.u.hcall.cpl = kvm_x86_ops.get_cpl(vcpu); + vcpu->run->xen.u.hcall.input = input; + vcpu->run->xen.u.hcall.params[0] = params[0]; + vcpu->run->xen.u.hcall.params[1] = params[1]; + vcpu->run->xen.u.hcall.params[2] = params[2]; + vcpu->run->xen.u.hcall.params[3] = params[3]; + vcpu->run->xen.u.hcall.params[4] = params[4]; + vcpu->run->xen.u.hcall.params[5] = params[5]; + vcpu->arch.xen.hypercall_rip = kvm_get_linear_rip(vcpu); + vcpu->arch.complete_userspace_io = + kvm_xen_hypercall_complete_userspace; + + return 0; +} diff --git a/arch/x86/kvm/xen.h b/arch/x86/kvm/xen.h new file mode 100644 index 000000000000..81e12f716d2e --- /dev/null +++ b/arch/x86/kvm/xen.h @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright © 2019 Oracle and/or its affiliates. All rights reserved. + * Copyright © 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * KVM Xen emulation + */ + +#ifndef __ARCH_X86_KVM_XEN_H__ +#define __ARCH_X86_KVM_XEN_H__ + +int kvm_xen_hypercall(struct kvm_vcpu *vcpu); +int kvm_xen_hvm_config(struct kvm_vcpu *vcpu, u64 data); + +static inline bool kvm_xen_hypercall_enabled(struct kvm *kvm) +{ + return kvm->arch.xen_hvm_config.flags & + KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL; +} + +#endif /* __ARCH_X86_KVM_XEN_H__ */ diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index ca41220b40b8..6b593a23cd41 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -216,6 +216,20 @@ struct kvm_hyperv_exit { } u; }; +struct kvm_xen_exit { +#define KVM_EXIT_XEN_HCALL 1 + __u32 type; + union { + struct { + __u32 longmode; + __u32 cpl; + __u64 input; + __u64 result; + __u64 params[6]; + } hcall; + } u; +}; + #define KVM_S390_GET_SKEYS_NONE 1 #define KVM_S390_SKEYS_MAX 1048576 @@ -250,6 +264,7 @@ struct kvm_hyperv_exit { #define KVM_EXIT_ARM_NISV 28 #define KVM_EXIT_X86_RDMSR 29 #define KVM_EXIT_X86_WRMSR 30 +#define KVM_EXIT_XEN 31 /* For KVM_EXIT_INTERNAL_ERROR */ /* Emulate instruction failed. */ @@ -426,6 +441,8 @@ struct kvm_run { __u32 index; /* kernel -> user */ __u64 data; /* kernel <-> user */ } msr; + /* KVM_EXIT_XEN */ + struct kvm_xen_exit xen; /* Fix the size of the union. */ char padding[256]; }; @@ -1126,6 +1143,9 @@ struct kvm_x86_mce { #endif #ifdef KVM_CAP_XEN_HVM +#define KVM_XEN_HVM_CONFIG_HYPERCALL_MSR (1 << 0) +#define KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL (1 << 1) + struct kvm_xen_hvm_config { __u32 flags; __u32 msr; diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index 3d14ef77755e..d94abec627e6 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -59,6 +59,7 @@ TEST_GEN_PROGS_x86_64 += x86_64/xss_msr_test TEST_GEN_PROGS_x86_64 += x86_64/debug_regs TEST_GEN_PROGS_x86_64 += x86_64/tsc_msrs_test TEST_GEN_PROGS_x86_64 += x86_64/user_msr_test +TEST_GEN_PROGS_x86_64 += x86_64/xen_vmcall_test TEST_GEN_PROGS_x86_64 += demand_paging_test TEST_GEN_PROGS_x86_64 += dirty_log_test TEST_GEN_PROGS_x86_64 += dirty_log_perf_test diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c index 126c6727a6b0..6e96ae47d28c 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -1654,6 +1654,7 @@ static struct exit_reason { {KVM_EXIT_INTERNAL_ERROR, "INTERNAL_ERROR"}, {KVM_EXIT_OSI, "OSI"}, {KVM_EXIT_PAPR_HCALL, "PAPR_HCALL"}, + {KVM_EXIT_XEN, "XEN"}, #ifdef KVM_EXIT_MEMORY_NOT_PRESENT {KVM_EXIT_MEMORY_NOT_PRESENT, "MEMORY_NOT_PRESENT"}, #endif diff --git a/tools/testing/selftests/kvm/x86_64/xen_vmcall_test.c b/tools/testing/selftests/kvm/x86_64/xen_vmcall_test.c new file mode 100644 index 000000000000..3f1dd93626e5 --- /dev/null +++ b/tools/testing/selftests/kvm/x86_64/xen_vmcall_test.c @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * svm_vmcall_test + * + * Copyright © 2020 Amazon.com, Inc. or its affiliates. + * + * Userspace hypercall testing + */ + +#include "test_util.h" +#include "kvm_util.h" +#include "processor.h" + +#define VCPU_ID 5 + +#define HCALL_REGION_GPA 0xc0000000ULL +#define HCALL_REGION_SLOT 10 + +static struct kvm_vm *vm; + +#define INPUTVALUE 17 +#define ARGVALUE(x) (0xdeadbeef5a5a0000UL + x) +#define RETVALUE 0xcafef00dfbfbffffUL + +#define XEN_HYPERCALL_MSR 0x40000000 + +static void guest_code(void) +{ + unsigned long rax = INPUTVALUE; + unsigned long rdi = ARGVALUE(1); + unsigned long rsi = ARGVALUE(2); + unsigned long rdx = ARGVALUE(3); + register unsigned long r10 __asm__("r10") = ARGVALUE(4); + register unsigned long r8 __asm__("r8") = ARGVALUE(5); + register unsigned long r9 __asm__("r9") = ARGVALUE(6); + + /* First a direct invocation of 'vmcall' */ + __asm__ __volatile__("vmcall" : + "=a"(rax) : + "a"(rax), "D"(rdi), "S"(rsi), "d"(rdx), + "r"(r10), "r"(r8), "r"(r9)); + GUEST_ASSERT(rax == RETVALUE); + + /* Now fill in the hypercall page */ + __asm__ __volatile__("wrmsr" : : "c" (XEN_HYPERCALL_MSR), + "a" (HCALL_REGION_GPA & 0xffffffff), + "d" (HCALL_REGION_GPA >> 32)); + + /* And invoke the same hypercall that way */ + __asm__ __volatile__("call *%1" : "=a"(rax) : + "r"(HCALL_REGION_GPA + INPUTVALUE * 32), + "a"(rax), "D"(rdi), "S"(rsi), "d"(rdx), + "r"(r10), "r"(r8), "r"(r9)); + GUEST_ASSERT(rax == RETVALUE); + + GUEST_DONE(); +} + +int main(int argc, char *argv[]) +{ + if (!(kvm_check_cap(KVM_CAP_XEN_HVM) & + KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL) ) { + print_skip("KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL not available"); + exit(KSFT_SKIP); + } + + vm = vm_create_default(VCPU_ID, 0, (void *) guest_code); + vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid()); + + struct kvm_xen_hvm_config hvmc = { + .flags = KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL, + .msr = XEN_HYPERCALL_MSR, + }; + vm_ioctl(vm, KVM_XEN_HVM_CONFIG, &hvmc); + + /* Map a region for the hypercall page */ + vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, + HCALL_REGION_GPA, HCALL_REGION_SLOT, + getpagesize(), 0); + virt_map(vm, HCALL_REGION_GPA, HCALL_REGION_GPA, 1, 0); + + for (;;) { + volatile struct kvm_run *run = vcpu_state(vm, VCPU_ID); + struct ucall uc; + + vcpu_run(vm, VCPU_ID); + + if (run->exit_reason == KVM_EXIT_XEN) { + ASSERT_EQ(run->xen.type, KVM_EXIT_XEN_HCALL); + ASSERT_EQ(run->xen.u.hcall.cpl, 0); + ASSERT_EQ(run->xen.u.hcall.longmode, 1); + ASSERT_EQ(run->xen.u.hcall.input, INPUTVALUE); + ASSERT_EQ(run->xen.u.hcall.params[0], ARGVALUE(1)); + ASSERT_EQ(run->xen.u.hcall.params[1], ARGVALUE(2)); + ASSERT_EQ(run->xen.u.hcall.params[2], ARGVALUE(3)); + ASSERT_EQ(run->xen.u.hcall.params[3], ARGVALUE(4)); + ASSERT_EQ(run->xen.u.hcall.params[4], ARGVALUE(5)); + ASSERT_EQ(run->xen.u.hcall.params[5], ARGVALUE(6)); + run->xen.u.hcall.result = RETVALUE; + continue; + } + + TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, + "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n", + run->exit_reason, + exit_reason_str(run->exit_reason)); + + switch (get_ucall(vm, VCPU_ID, &uc)) { + case UCALL_ABORT: + TEST_FAIL("%s", (const char *)uc.args[0]); + /* NOT REACHED */ + case UCALL_SYNC: + break; + case UCALL_DONE: + goto done; + default: + TEST_FAIL("Unknown ucall 0x%lx.", uc.cmd); + } + } +done: + kvm_vm_free(vm); + return 0; +} From patchwork Sun Dec 6 11:03:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 11953969 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 57317C197BF for ; Sun, 6 Dec 2020 11:04:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2878C2313E for ; Sun, 6 Dec 2020 11:04:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726723AbgLFLET (ORCPT ); Sun, 6 Dec 2020 06:04:19 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41790 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726076AbgLFLEQ (ORCPT ); Sun, 6 Dec 2020 06:04:16 -0500 Received: from merlin.infradead.org (merlin.infradead.org [IPv6:2001:8b0:10b:1231::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CD938C061A52 for ; Sun, 6 Dec 2020 03:03:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description; bh=zXcnTM/BxDT1oqD6xZCDg6AyUlQdFYvXAbZCud3KsgY=; b=gUvRjUQoIKWW1z1e6D1IW4y/Oy nV9NTJxwJ00U4BsyTsEX+tTY4XZPJKh0HigbDD4aqykEvsCMJ+GrabIkewRUHNAf92gcy9/C/oCpz sc1DRRjaw3mCbvSHG91ejfj+0wWQDp3hyd/l9qR0hoGAkNqwROrMcZnOc13lNUglyJUo7jrfem6gJ A2K4f46A0dZFCn8U6Tl/wlPvOLjtOO4zvli0jUwLmW8IhDiz4N17sky7FMZPV8WCqHXZSaD98wwua br+qW87ZE+wi2OIXnUgCjjO0p8jG1tTfPR003anJHFv4gPnVcgbZtexjma2TvMY5mfjZdl4s+nY03 WMjbgolA==; Received: from i7.infradead.org ([2001:8b0:10b:1:21e:67ff:fecb:7a92]) by merlin.infradead.org with esmtpsa (Exim 4.92.3 #3 (Red Hat Linux)) id 1klrpE-0004tH-NZ; Sun, 06 Dec 2020 11:03:32 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1klrpD-000jpJ-LW; Sun, 06 Dec 2020 11:03:31 +0000 From: David Woodhouse To: kvm@vger.kernel.org Cc: Paolo Bonzini , Ankur Arora , Joao Martins , Boris Ostrovsky , Sean Christopherson , graf@amazon.com, iaslan@amazon.de Subject: [PATCH v2 04/16] KVM: x86/xen: Fix coexistence of Xen and Hyper-V hypercalls Date: Sun, 6 Dec 2020 11:03:15 +0000 Message-Id: <20201206110327.175629-5-dwmw2@infradead.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201206110327.175629-1-dwmw2@infradead.org> References: <20201206110327.175629-1-dwmw2@infradead.org> MIME-Version: 1.0 Sender: David Woodhouse X-SRS-Rewrite: SMTP reverse-path rewritten from by merlin.infradead.org. See http://www.infradead.org/rpr.html Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: David Woodhouse Disambiguate Xen vs. Hyper-V calls by adding 'orl $0x80000000, %eax' at the start of the Hyper-V hypercall page when Xen hypercalls are also enabled. That bit is reserved in the Hyper-V ABI, and those hypercall numbers will never be used by Xen (because it does precisely the same trick). Switch to using kvm_vcpu_write_guest() while we're at it, instead of open-coding it. Signed-off-by: David Woodhouse --- arch/x86/kvm/hyperv.c | 40 ++++++++++++++----- arch/x86/kvm/xen.c | 6 +++ .../selftests/kvm/x86_64/xen_vmcall_test.c | 39 +++++++++++++++--- 3 files changed, 68 insertions(+), 17 deletions(-) diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index 5c7c4060b45c..347ff9ad70b3 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -23,6 +23,7 @@ #include "ioapic.h" #include "cpuid.h" #include "hyperv.h" +#include "xen.h" #include #include @@ -1139,9 +1140,9 @@ static int kvm_hv_set_msr_pw(struct kvm_vcpu *vcpu, u32 msr, u64 data, hv->hv_hypercall &= ~HV_X64_MSR_HYPERCALL_ENABLE; break; case HV_X64_MSR_HYPERCALL: { - u64 gfn; - unsigned long addr; - u8 instructions[4]; + u8 instructions[9]; + int i = 0; + u64 addr; /* if guest os id is not set hypercall should remain disabled */ if (!hv->hv_guest_os_id) @@ -1150,16 +1151,33 @@ static int kvm_hv_set_msr_pw(struct kvm_vcpu *vcpu, u32 msr, u64 data, hv->hv_hypercall = data; break; } - gfn = data >> HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_SHIFT; - addr = gfn_to_hva(kvm, gfn); - if (kvm_is_error_hva(addr)) - return 1; - kvm_x86_ops.patch_hypercall(vcpu, instructions); - ((unsigned char *)instructions)[3] = 0xc3; /* ret */ - if (__copy_to_user((void __user *)addr, instructions, 4)) + + /* + * If Xen and Hyper-V hypercalls are both enabled, disambiguate + * the same way Xen itself does, by setting the bit 31 of EAX + * which is RsvdZ in the 32-bit Hyper-V hypercall ABI and just + * going to be clobbered on 64-bit. + */ + if (kvm_xen_hypercall_enabled(kvm)) { + /* orl $0x80000000, %eax */ + instructions[i++] = 0x0d; + instructions[i++] = 0x00; + instructions[i++] = 0x00; + instructions[i++] = 0x00; + instructions[i++] = 0x80; + } + + /* vmcall/vmmcall */ + kvm_x86_ops.patch_hypercall(vcpu, instructions + i); + i += 3; + + /* ret */ + ((unsigned char *)instructions)[i++] = 0xc3; + + addr = data & HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_MASK; + if (kvm_vcpu_write_guest(vcpu, addr, instructions, i)) return 1; hv->hv_hypercall = data; - mark_page_dirty(kvm, gfn); break; } case HV_X64_MSR_REFERENCE_TSC: diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c index b76d121a86c0..503935d8212e 100644 --- a/arch/x86/kvm/xen.c +++ b/arch/x86/kvm/xen.c @@ -8,6 +8,7 @@ #include "x86.h" #include "xen.h" +#include "hyperv.h" #include @@ -99,6 +100,11 @@ int kvm_xen_hypercall(struct kvm_vcpu *vcpu) input = (u64)kvm_register_read(vcpu, VCPU_REGS_RAX); + /* Hyper-V hypercalls get bit 31 set in EAX */ + if ((input & 0x80000000) && + kvm_hv_hypercall_enabled(vcpu->kvm)) + return kvm_hv_hypercall(vcpu); + longmode = is_64_bit_mode(vcpu); if (!longmode) { params[0] = (u32)kvm_rbx_read(vcpu); diff --git a/tools/testing/selftests/kvm/x86_64/xen_vmcall_test.c b/tools/testing/selftests/kvm/x86_64/xen_vmcall_test.c index 3f1dd93626e5..24f279e1a66b 100644 --- a/tools/testing/selftests/kvm/x86_64/xen_vmcall_test.c +++ b/tools/testing/selftests/kvm/x86_64/xen_vmcall_test.c @@ -15,6 +15,7 @@ #define HCALL_REGION_GPA 0xc0000000ULL #define HCALL_REGION_SLOT 10 +#define PAGE_SIZE 4096 static struct kvm_vm *vm; @@ -22,7 +23,12 @@ static struct kvm_vm *vm; #define ARGVALUE(x) (0xdeadbeef5a5a0000UL + x) #define RETVALUE 0xcafef00dfbfbffffUL -#define XEN_HYPERCALL_MSR 0x40000000 +#define XEN_HYPERCALL_MSR 0x40000200 +#define HV_GUEST_OS_ID_MSR 0x40000000 +#define HV_HYPERCALL_MSR 0x40000001 + +#define HVCALL_SIGNAL_EVENT 0x005d +#define HV_STATUS_INVALID_ALIGNMENT 4 static void guest_code(void) { @@ -30,6 +36,7 @@ static void guest_code(void) unsigned long rdi = ARGVALUE(1); unsigned long rsi = ARGVALUE(2); unsigned long rdx = ARGVALUE(3); + unsigned long rcx; register unsigned long r10 __asm__("r10") = ARGVALUE(4); register unsigned long r8 __asm__("r8") = ARGVALUE(5); register unsigned long r9 __asm__("r9") = ARGVALUE(6); @@ -41,18 +48,38 @@ static void guest_code(void) "r"(r10), "r"(r8), "r"(r9)); GUEST_ASSERT(rax == RETVALUE); - /* Now fill in the hypercall page */ + /* Fill in the Xen hypercall page */ __asm__ __volatile__("wrmsr" : : "c" (XEN_HYPERCALL_MSR), "a" (HCALL_REGION_GPA & 0xffffffff), "d" (HCALL_REGION_GPA >> 32)); - /* And invoke the same hypercall that way */ + /* Set Hyper-V Guest OS ID */ + __asm__ __volatile__("wrmsr" : : "c" (HV_GUEST_OS_ID_MSR), + "a" (0x5a), "d" (0)); + + /* Hyper-V hypercall page */ + u64 msrval = HCALL_REGION_GPA + PAGE_SIZE + 1; + __asm__ __volatile__("wrmsr" : : "c" (HV_HYPERCALL_MSR), + "a" (msrval & 0xffffffff), + "d" (msrval >> 32)); + + /* Invoke a Xen hypercall */ __asm__ __volatile__("call *%1" : "=a"(rax) : "r"(HCALL_REGION_GPA + INPUTVALUE * 32), "a"(rax), "D"(rdi), "S"(rsi), "d"(rdx), "r"(r10), "r"(r8), "r"(r9)); GUEST_ASSERT(rax == RETVALUE); + /* Invoke a Hyper-V hypercall */ + rax = 0; + rcx = HVCALL_SIGNAL_EVENT; /* code */ + rdx = 0x5a5a5a5a; /* ingpa (badly aligned) */ + __asm__ __volatile__("call *%1" : "=a"(rax) : + "r"(HCALL_REGION_GPA + PAGE_SIZE), + "a"(rax), "c"(rcx), "d"(rdx), + "r"(r8)); + GUEST_ASSERT(rax == HV_STATUS_INVALID_ALIGNMENT); + GUEST_DONE(); } @@ -73,11 +100,11 @@ int main(int argc, char *argv[]) }; vm_ioctl(vm, KVM_XEN_HVM_CONFIG, &hvmc); - /* Map a region for the hypercall page */ + /* Map a region for the hypercall pages */ vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, HCALL_REGION_GPA, HCALL_REGION_SLOT, - getpagesize(), 0); - virt_map(vm, HCALL_REGION_GPA, HCALL_REGION_GPA, 1, 0); + 2 * getpagesize(), 0); + virt_map(vm, HCALL_REGION_GPA, HCALL_REGION_GPA, 2, 0); for (;;) { volatile struct kvm_run *run = vcpu_state(vm, VCPU_ID); From patchwork Sun Dec 6 11:03:16 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 11953967 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 493A1C1B0D8 for ; Sun, 6 Dec 2020 11:04:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 138072313C for ; Sun, 6 Dec 2020 11:04:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726351AbgLFLEQ (ORCPT ); Sun, 6 Dec 2020 06:04:16 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41784 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725804AbgLFLEQ (ORCPT ); Sun, 6 Dec 2020 06:04:16 -0500 Received: from merlin.infradead.org (merlin.infradead.org [IPv6:2001:8b0:10b:1231::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B1D4DC0613D4 for ; Sun, 6 Dec 2020 03:03:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description; bh=RaddUgsDseJfkus5sbsM6ZbzFgc5eINIiXu3UzWp/ys=; b=18bCujpLU6jN9NpUv6x3xoY65k ssAMD05jgCOL8JFUTSK4QgsiN1KpF2gt8IUZZB3F39Dyr+QiIKvei0acyTDVq7V8OkECRu2X1tfWG DEu4c+BvF+kWu7xFl2yQiDdGaCwcPmr8uJSODC2zsWt21Zz7pqrhnyI+g7bOdpWe5C8y0GWQxcm6+ KXbph28DR37OmfEdjHpsaWE3ZjoW+As/CdX9fe9emVWnHXu0k3daQFQ9RUyxA3FPkTy+1ba2J7u/D 7SL6t1m0Oy0XM5wl1B5LspO2N2xoY84sL1+moiQFNW1Ysl+pxOoIAWNiaaAr/huegDqQlZiRdDRfg dhXRGrdA==; Received: from i7.infradead.org ([2001:8b0:10b:1:21e:67ff:fecb:7a92]) by merlin.infradead.org with esmtpsa (Exim 4.92.3 #3 (Red Hat Linux)) id 1klrpE-0004tI-OJ; Sun, 06 Dec 2020 11:03:32 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1klrpD-000jpM-MF; Sun, 06 Dec 2020 11:03:31 +0000 From: David Woodhouse To: kvm@vger.kernel.org Cc: Paolo Bonzini , Ankur Arora , Joao Martins , Boris Ostrovsky , Sean Christopherson , graf@amazon.com, iaslan@amazon.de Subject: [PATCH v2 05/16] KVM: x86/xen: add KVM_XEN_HVM_SET_ATTR/KVM_XEN_HVM_GET_ATTR Date: Sun, 6 Dec 2020 11:03:16 +0000 Message-Id: <20201206110327.175629-6-dwmw2@infradead.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201206110327.175629-1-dwmw2@infradead.org> References: <20201206110327.175629-1-dwmw2@infradead.org> MIME-Version: 1.0 Sender: David Woodhouse X-SRS-Rewrite: SMTP reverse-path rewritten from by merlin.infradead.org. See http://www.infradead.org/rpr.html Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Joao Martins This will be used to set up shared info pages etc. Signed-off-by: Joao Martins Signed-off-by: David Woodhouse --- arch/x86/kvm/x86.c | 20 ++++++++++++++++++++ arch/x86/kvm/xen.c | 24 ++++++++++++++++++++++++ arch/x86/kvm/xen.h | 3 +++ include/linux/kvm_host.h | 30 +++++++++++++++--------------- include/uapi/linux/kvm.h | 11 +++++++++++ 5 files changed, 73 insertions(+), 15 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 5394dda3e3b0..975ef5d6dda1 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -5595,6 +5595,26 @@ long kvm_arch_vm_ioctl(struct file *filp, r = 0; break; } + case KVM_XEN_HVM_GET_ATTR: { + struct kvm_xen_hvm_attr xha; + + r = -EFAULT; + if (copy_from_user(&xha, argp, sizeof(xha))) + goto out; + r = kvm_xen_hvm_get_attr(kvm, &xha); + if (copy_to_user(argp, &xha, sizeof(xha))) + goto out; + break; + } + case KVM_XEN_HVM_SET_ATTR: { + struct kvm_xen_hvm_attr xha; + + r = -EFAULT; + if (copy_from_user(&xha, argp, sizeof(xha))) + goto out; + r = kvm_xen_hvm_set_attr(kvm, &xha); + break; + } case KVM_SET_CLOCK: { struct kvm_clock_data user_ns; u64 now_ns; diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c index 503935d8212e..c0b2c67e0235 100644 --- a/arch/x86/kvm/xen.c +++ b/arch/x86/kvm/xen.c @@ -16,6 +16,30 @@ #include "trace.h" +int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) +{ + int r = -ENOENT; + + switch (data->type) { + default: + break; + } + + return r; +} + +int kvm_xen_hvm_get_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) +{ + int r = -ENOENT; + + switch (data->type) { + default: + break; + } + + return r; +} + int kvm_xen_hvm_config(struct kvm_vcpu *vcpu, u64 data) { struct kvm *kvm = vcpu->kvm; diff --git a/arch/x86/kvm/xen.h b/arch/x86/kvm/xen.h index 81e12f716d2e..afc6dad41fb5 100644 --- a/arch/x86/kvm/xen.h +++ b/arch/x86/kvm/xen.h @@ -9,8 +9,11 @@ #ifndef __ARCH_X86_KVM_XEN_H__ #define __ARCH_X86_KVM_XEN_H__ +int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data); +int kvm_xen_hvm_get_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data); int kvm_xen_hypercall(struct kvm_vcpu *vcpu); int kvm_xen_hvm_config(struct kvm_vcpu *vcpu, u64 data); +void kvm_xen_destroy_vm(struct kvm *kvm); static inline bool kvm_xen_hypercall_enabled(struct kvm *kvm) { diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 8eb5eb1399f5..846a010f5d5f 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -33,6 +33,21 @@ #include +struct kvm_host_map { + /* + * Only valid if the 'pfn' is managed by the host kernel (i.e. There is + * a 'struct page' for it. When using mem= kernel parameter some memory + * can be used as guest memory but they are not managed by host + * kernel). + * If 'pfn' is not managed by the host kernel, this field is + * initialized to KVM_UNMAPPED_PAGE. + */ + struct page *page; + void *hva; + kvm_pfn_t pfn; + kvm_pfn_t gfn; +}; + #include #ifndef KVM_MAX_VCPU_ID @@ -225,21 +240,6 @@ enum { #define KVM_UNMAPPED_PAGE ((void *) 0x500 + POISON_POINTER_DELTA) -struct kvm_host_map { - /* - * Only valid if the 'pfn' is managed by the host kernel (i.e. There is - * a 'struct page' for it. When using mem= kernel parameter some memory - * can be used as guest memory but they are not managed by host - * kernel). - * If 'pfn' is not managed by the host kernel, this field is - * initialized to KVM_UNMAPPED_PAGE. - */ - struct page *page; - void *hva; - kvm_pfn_t pfn; - kvm_pfn_t gfn; -}; - /* * Used to check if the mapping is valid or not. Never use 'kvm_host_map' * directly to check for that. diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 6b593a23cd41..3d9ac2f4dc10 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1577,6 +1577,17 @@ struct kvm_pv_cmd { /* Available with KVM_CAP_X86_MSR_FILTER */ #define KVM_X86_SET_MSR_FILTER _IOW(KVMIO, 0xc6, struct kvm_msr_filter) +#define KVM_XEN_HVM_GET_ATTR _IOWR(KVMIO, 0xc7, struct kvm_xen_hvm_attr) +#define KVM_XEN_HVM_SET_ATTR _IOW(KVMIO, 0xc8, struct kvm_xen_hvm_attr) + +struct kvm_xen_hvm_attr { + __u16 type; + + union { + __u64 pad[4]; + } u; +}; + /* Secure Encrypted Virtualization command */ enum sev_cmd_id { /* Guest initialization commands */ From patchwork Sun Dec 6 11:03:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 11953961 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F3B79C4361B for ; Sun, 6 Dec 2020 11:04:32 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B58E722E03 for ; Sun, 6 Dec 2020 11:04:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726414AbgLFLEQ (ORCPT ); Sun, 6 Dec 2020 06:04:16 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41782 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725767AbgLFLEQ (ORCPT ); Sun, 6 Dec 2020 06:04:16 -0500 Received: from merlin.infradead.org (merlin.infradead.org [IPv6:2001:8b0:10b:1231::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9CA3AC0613D1 for ; Sun, 6 Dec 2020 03:03:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description; bh=tBq69FrBfo3FGfDE8wAnuLV0cMI+RANBkpZW+oLWxTs=; b=ojgQbeRJCwP76EdkbwoRvmbumu PgnApGv07+3OzfO4VVa9uSyagnxH6ZQ1tsI3f1Bib/p3G2GXpzY38ENryvYPQ3du9y/EzmqprbuBz wknzaT5RxITDYL8Mh0nWPoGs7iOCZ5XKlER90twDCs4uF/Xs7Drab30LDartQjzexm1tJkc1sn5Xt pTxrEC+govrmCHaM4o7V5aBdust2jOvzxqk6HeXbHiMuItsFFld/qGzU/J543Vcsn6mKuGxa4Q661 k3lyY6FDlqPrsDi0n3Yimx7OiKXAWW5bHIxUs9dkvKApldtagcYKldUVscYqCm+FC2IyNMIiIFp6T J64x3kZg==; Received: from i7.infradead.org ([2001:8b0:10b:1:21e:67ff:fecb:7a92]) by merlin.infradead.org with esmtpsa (Exim 4.92.3 #3 (Red Hat Linux)) id 1klrpE-0004tJ-Ok; Sun, 06 Dec 2020 11:03:32 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1klrpD-000jpP-Mr; Sun, 06 Dec 2020 11:03:31 +0000 From: David Woodhouse To: kvm@vger.kernel.org Cc: Paolo Bonzini , Ankur Arora , Joao Martins , Boris Ostrovsky , Sean Christopherson , graf@amazon.com, iaslan@amazon.de Subject: [PATCH v2 06/16] KVM: x86/xen: latch long_mode when hypercall page is set up Date: Sun, 6 Dec 2020 11:03:17 +0000 Message-Id: <20201206110327.175629-7-dwmw2@infradead.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201206110327.175629-1-dwmw2@infradead.org> References: <20201206110327.175629-1-dwmw2@infradead.org> MIME-Version: 1.0 Sender: David Woodhouse X-SRS-Rewrite: SMTP reverse-path rewritten from by merlin.infradead.org. See http://www.infradead.org/rpr.html Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: David Woodhouse Signed-off-by: David Woodhouse --- arch/x86/include/asm/kvm_host.h | 6 ++++++ arch/x86/kvm/xen.c | 16 +++++++++++++++- include/uapi/linux/kvm.h | 3 +++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 9de3229e91e1..c9a4feaee2e7 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -890,6 +890,11 @@ struct msr_bitmap_range { unsigned long *bitmap; }; +/* Xen emulation context */ +struct kvm_xen { + bool long_mode; +}; + enum kvm_irqchip_mode { KVM_IRQCHIP_NONE, KVM_IRQCHIP_KERNEL, /* created with KVM_CREATE_IRQCHIP */ @@ -969,6 +974,7 @@ struct kvm_arch { struct hlist_head mask_notifier_list; struct kvm_hv hyperv; + struct kvm_xen xen; #ifdef CONFIG_KVM_MMU_AUDIT int audit_point; diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c index c0b2c67e0235..52cb9e465542 100644 --- a/arch/x86/kvm/xen.c +++ b/arch/x86/kvm/xen.c @@ -21,6 +21,13 @@ int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) int r = -ENOENT; switch (data->type) { + case KVM_XEN_ATTR_TYPE_LONG_MODE: + if (!IS_ENABLED(CONFIG_64BIT) && data->u.long_mode) + return -EINVAL; + + kvm->arch.xen.long_mode = !!data->u.long_mode; + r = 0; + break; default: break; } @@ -33,6 +40,10 @@ int kvm_xen_hvm_get_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) int r = -ENOENT; switch (data->type) { + case KVM_XEN_ATTR_TYPE_LONG_MODE: + data->u.long_mode = kvm->arch.xen.long_mode; + r = 0; + break; default: break; } @@ -45,6 +56,10 @@ int kvm_xen_hvm_config(struct kvm_vcpu *vcpu, u64 data) struct kvm *kvm = vcpu->kvm; u32 page_num = data & ~PAGE_MASK; u64 page_addr = data & PAGE_MASK; + bool lm = is_long_mode(vcpu); + + /* Latch long_mode for shared_info pages etc. */ + vcpu->kvm->arch.xen.long_mode = lm; /* * If Xen hypercall intercept is enabled, fill the hypercall @@ -79,7 +94,6 @@ int kvm_xen_hvm_config(struct kvm_vcpu *vcpu, u64 data) return 1; } } else { - int lm = is_long_mode(vcpu); u8 *blob_addr = lm ? (u8 *)(long)kvm->arch.xen_hvm_config.blob_addr_64 : (u8 *)(long)kvm->arch.xen_hvm_config.blob_addr_32; u8 blob_size = lm ? kvm->arch.xen_hvm_config.blob_size_64 diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 3d9ac2f4dc10..6b556ef98b76 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1584,10 +1584,13 @@ struct kvm_xen_hvm_attr { __u16 type; union { + __u8 long_mode; __u64 pad[4]; } u; }; +#define KVM_XEN_ATTR_TYPE_LONG_MODE 0x0 + /* Secure Encrypted Virtualization command */ enum sev_cmd_id { /* Guest initialization commands */ From patchwork Sun Dec 6 11:03:18 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 11953959 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 04743C4167B for ; Sun, 6 Dec 2020 11:04:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CB2AC2310B for ; Sun, 6 Dec 2020 11:04:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726597AbgLFLER (ORCPT ); Sun, 6 Dec 2020 06:04:17 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41788 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726011AbgLFLEQ (ORCPT ); Sun, 6 Dec 2020 06:04:16 -0500 Received: from merlin.infradead.org (merlin.infradead.org [IPv6:2001:8b0:10b:1231::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C4E4FC061A51 for ; Sun, 6 Dec 2020 03:03:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description; bh=yanMONemVgXNfp/liw6HjKwLpmnJvJ/soapoNao/Ncg=; b=NBkqm+sTVWQNZkMjXZGTlcg32t dXeEoF99sm63YyhTS763q1PmUOqTlhACdlTRFkKm/SFqSODcL5a3bM1WV2ggeHN8KDu6l+QkpVQlW sTqjPr42TelhEGZ1Bh/uRJ8M9M20ZCjhu3PknHHsuRcWAhC5lnRaKWXIkqA7gLtVEfAWP33D3Rs8A 8kIu1jy4wU/4WPeCu1wADg3XLB7iuNACej2O3C4B5nlLnIkSdk1OF6yIgPD442Dv22jMaLcfqdZi9 eXsNcDOVcgjNv/oQwPbUtXDEI1tf0JDeuRg+/VPCsn5yh/RxE3zqWQgLq+dUR5fALN7CFxe8vqwtv lg0c+yqQ==; Received: from i7.infradead.org ([2001:8b0:10b:1:21e:67ff:fecb:7a92]) by merlin.infradead.org with esmtpsa (Exim 4.92.3 #3 (Red Hat Linux)) id 1klrpE-0004tK-PH; Sun, 06 Dec 2020 11:03:32 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1klrpD-000jpS-NL; Sun, 06 Dec 2020 11:03:31 +0000 From: David Woodhouse To: kvm@vger.kernel.org Cc: Paolo Bonzini , Ankur Arora , Joao Martins , Boris Ostrovsky , Sean Christopherson , graf@amazon.com, iaslan@amazon.de Subject: [PATCH v2 07/16] KVM: x86/xen: add definitions of compat_shared_info, compat_vcpu_info Date: Sun, 6 Dec 2020 11:03:18 +0000 Message-Id: <20201206110327.175629-8-dwmw2@infradead.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201206110327.175629-1-dwmw2@infradead.org> References: <20201206110327.175629-1-dwmw2@infradead.org> MIME-Version: 1.0 Sender: David Woodhouse X-SRS-Rewrite: SMTP reverse-path rewritten from by merlin.infradead.org. See http://www.infradead.org/rpr.html Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: David Woodhouse There aren't a lot of differences for the things that the kernel needs to care about, but there are a few. Signed-off-by: David Woodhouse --- arch/x86/kvm/xen.h | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/arch/x86/kvm/xen.h b/arch/x86/kvm/xen.h index afc6dad41fb5..cd3c52b62068 100644 --- a/arch/x86/kvm/xen.h +++ b/arch/x86/kvm/xen.h @@ -21,4 +21,41 @@ static inline bool kvm_xen_hypercall_enabled(struct kvm *kvm) KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL; } + +/* 32-bit compatibility definitions, also used natively in 32-bit build */ +#include +#include + +struct compat_arch_vcpu_info { + unsigned int cr2; + unsigned int pad[5]; +}; + +struct compat_vcpu_info { + uint8_t evtchn_upcall_pending; + uint8_t evtchn_upcall_mask; + uint32_t evtchn_pending_sel; + struct compat_arch_vcpu_info arch; + struct pvclock_vcpu_time_info time; +}; /* 64 bytes (x86) */ + +struct compat_arch_shared_info { + unsigned int max_pfn; + unsigned int pfn_to_mfn_frame_list_list; + unsigned int nmi_reason; + unsigned int p2m_cr3; + unsigned int p2m_vaddr; + unsigned int p2m_generation; + uint32_t wc_sec_hi; +}; + +struct compat_shared_info { + struct compat_vcpu_info vcpu_info[MAX_VIRT_CPUS]; + uint32_t evtchn_pending[32]; + uint32_t evtchn_mask[32]; + struct pvclock_wall_clock wc; + struct compat_arch_shared_info arch; + +}; + #endif /* __ARCH_X86_KVM_XEN_H__ */ From patchwork Sun Dec 6 11:03:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 11953979 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BC90DC19425 for ; Sun, 6 Dec 2020 11:05:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 925172310B for ; Sun, 6 Dec 2020 11:05:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726886AbgLFLE7 (ORCPT ); Sun, 6 Dec 2020 06:04:59 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41918 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727260AbgLFLE5 (ORCPT ); Sun, 6 Dec 2020 06:04:57 -0500 Received: from casper.infradead.org (casper.infradead.org [IPv6:2001:8b0:10b:1236::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C3126C08E864 for ; Sun, 6 Dec 2020 03:03:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description; bh=t0KUyaaKFZUFAriFMzNMP22rzCxgsUgin8OqoaSaQ30=; b=l7thEobluX22jznybbdheEEynL /0wU28IqtDZ6GHcwpGePDvDQ1Y2WjcZUOGTXT54/QVT8Phq6TTSD8mIy7mUAL3B6UDWKqoow/sVBD AXon7V+JVvaWmRDcp9LFOHVgRglSTPFw+V2IFiLvXXmFUMXo/Sb9vZKe6K8r38D4yultXNGrSXxBs 3uQ9Xaql1+2yzWgFaU25wjQBumxOvgZRt6T/z3NFHI9eJIFqqBVMwr+ia9WA/p8WbifcRbjASqxzD zKOUhkfqmn1aR5EeSbILBpHm5egNs6G3wEQNyj8mFHdLx3X06ji1Qt8/nVfJWJg3kmtef1XMmCXE/ kaGsRGVw==; Received: from i7.infradead.org ([2001:8b0:10b:1:21e:67ff:fecb:7a92]) by casper.infradead.org with esmtpsa (Exim 4.92.3 #3 (Red Hat Linux)) id 1klrpE-0006Fp-57; Sun, 06 Dec 2020 11:03:41 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1klrpD-000jpV-No; Sun, 06 Dec 2020 11:03:31 +0000 From: David Woodhouse To: kvm@vger.kernel.org Cc: Paolo Bonzini , Ankur Arora , Joao Martins , Boris Ostrovsky , Sean Christopherson , graf@amazon.com, iaslan@amazon.de Subject: [PATCH v2 08/16] KVM: x86/xen: register shared_info page Date: Sun, 6 Dec 2020 11:03:19 +0000 Message-Id: <20201206110327.175629-9-dwmw2@infradead.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201206110327.175629-1-dwmw2@infradead.org> References: <20201206110327.175629-1-dwmw2@infradead.org> MIME-Version: 1.0 Sender: David Woodhouse X-SRS-Rewrite: SMTP reverse-path rewritten from by casper.infradead.org. See http://www.infradead.org/rpr.html Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Joao Martins We add a new ioctl, XEN_HVM_SHARED_INFO, to allow hypervisor to know where the guest's shared info page is. Signed-off-by: Joao Martins Signed-off-by: David Woodhouse --- arch/x86/include/asm/kvm_host.h | 2 + arch/x86/kvm/x86.c | 1 + arch/x86/kvm/xen.c | 69 +++++++++++++++++++++++++++++++++ include/uapi/linux/kvm.h | 4 ++ 4 files changed, 76 insertions(+) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index c9a4feaee2e7..b6eff9814c6a 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -893,6 +893,8 @@ struct msr_bitmap_range { /* Xen emulation context */ struct kvm_xen { bool long_mode; + struct kvm_host_map shinfo_map; + void *shinfo; }; enum kvm_irqchip_mode { diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 975ef5d6dda1..4a960629687c 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -10446,6 +10446,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm) kvm_mmu_uninit_vm(kvm); kvm_page_track_cleanup(kvm); kvm_hv_destroy_vm(kvm); + kvm_xen_destroy_vm(kvm); } void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *slot) diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c index 52cb9e465542..c156ed1ef972 100644 --- a/arch/x86/kvm/xen.c +++ b/arch/x86/kvm/xen.c @@ -13,9 +13,51 @@ #include #include +#include #include "trace.h" +static int kvm_xen_map_guest_page(struct kvm *kvm, struct kvm_host_map *map, + void **hva, gpa_t gpa, size_t len) +{ + gfn_t gfn = gpa_to_gfn(gpa); + struct kvm_host_map new_map; + bool unmap = !!*hva; + int ret; + + if (offset_in_page(gpa) + len > PAGE_SIZE) + return -EINVAL; + + ret = kvm_map_gfn(kvm, gfn, &new_map, NULL, false); + if (ret) + return ret; + + WRITE_ONCE(*hva, new_map.hva + offset_in_page(gpa)); + + if (unmap) { + synchronize_srcu(&kvm->srcu); + + kvm_unmap_gfn(kvm, map, NULL, true, false); + } + + *map = new_map; + return 0; +} + +static int kvm_xen_shared_info_init(struct kvm *kvm, gfn_t gfn) +{ + gpa_t gpa = gfn_to_gpa(gfn); + int ret; + + ret = kvm_xen_map_guest_page(kvm, &kvm->arch.xen.shinfo_map, + (void **)&kvm->arch.xen.shinfo, gpa, + PAGE_SIZE); + if (ret) + return ret; + + return 0; +} + int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) { int r = -ENOENT; @@ -28,6 +70,14 @@ int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) kvm->arch.xen.long_mode = !!data->u.long_mode; r = 0; break; + + case KVM_XEN_ATTR_TYPE_SHARED_INFO: { + gfn_t gfn = data->u.shared_info.gfn; + + r = kvm_xen_shared_info_init(kvm, gfn); + break; + } + default: break; } @@ -44,6 +94,15 @@ int kvm_xen_hvm_get_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) data->u.long_mode = kvm->arch.xen.long_mode; r = 0; break; + + case KVM_XEN_ATTR_TYPE_SHARED_INFO: { + if (kvm->arch.xen.shinfo) { + data->u.shared_info.gfn = kvm->arch.xen.shinfo_map.gfn; + r = 0; + } + break; + } + default: break; } @@ -182,3 +241,13 @@ int kvm_xen_hypercall(struct kvm_vcpu *vcpu) return 0; } + +void kvm_xen_destroy_vm(struct kvm *kvm) +{ + struct kvm_xen *xen = &kvm->arch.xen; + + if (xen->shinfo) { + kvm_unmap_gfn(kvm, &xen->shinfo_map, NULL, true, false); + xen->shinfo = NULL; + } +} diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 6b556ef98b76..caa9faf3c5ad 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1585,11 +1585,15 @@ struct kvm_xen_hvm_attr { union { __u8 long_mode; + struct { + __u64 gfn; + } shared_info; __u64 pad[4]; } u; }; #define KVM_XEN_ATTR_TYPE_LONG_MODE 0x0 +#define KVM_XEN_ATTR_TYPE_SHARED_INFO 0x1 /* Secure Encrypted Virtualization command */ enum sev_cmd_id { From patchwork Sun Dec 6 11:03:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 11953975 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 507D1C433FE for ; Sun, 6 Dec 2020 11:04:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 26A8022E03 for ; Sun, 6 Dec 2020 11:04:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727355AbgLFLE5 (ORCPT ); Sun, 6 Dec 2020 06:04:57 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41908 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727202AbgLFLE4 (ORCPT ); Sun, 6 Dec 2020 06:04:56 -0500 Received: from casper.infradead.org (casper.infradead.org [IPv6:2001:8b0:10b:1236::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BBB74C08E862 for ; Sun, 6 Dec 2020 03:03:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description; bh=wWbW/z7plT1a0tP1DNYERJVWzen2M3NsSH+vdxLYVlk=; b=Woj2Ff8b/wbgQSj7Th0VUUWXrC ZAVcc0Jg0M9rCNxUltlLbJ/LmIIIJaZXqQxEbLcSC9RTj8yy0KdpYJaOU/IafOdVI6tKzr4YLN6E3 MHSz1ElsavpNU1OQ8d8fZzadABru4oAj7bGZb/QQu52i2QmFeRLp20tO+Ibe0ELog2H1HpHhnsj1+ y7q+Nuvz16oiZLKvl4ud5o2NM0IOUxte1qnObZGPvpM7rjoAJz9V9pPUEvdTJHHMxjOWIT0x/H4TW 7a9UJpwWpHjb0bpyjlH2Lioqq0gR14O9uDN5V535bhfNpplmFBWYmORfW9U4CVSeDZ8okYn1G19v3 98QfZ+0w==; Received: from i7.infradead.org ([2001:8b0:10b:1:21e:67ff:fecb:7a92]) by casper.infradead.org with esmtpsa (Exim 4.92.3 #3 (Red Hat Linux)) id 1klrpE-0006Fq-5s; Sun, 06 Dec 2020 11:03:40 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1klrpD-000jpY-OM; Sun, 06 Dec 2020 11:03:31 +0000 From: David Woodhouse To: kvm@vger.kernel.org Cc: Paolo Bonzini , Ankur Arora , Joao Martins , Boris Ostrovsky , Sean Christopherson , graf@amazon.com, iaslan@amazon.de Subject: [PATCH v2 09/16] KVM: x86/xen: setup pvclock updates Date: Sun, 6 Dec 2020 11:03:20 +0000 Message-Id: <20201206110327.175629-10-dwmw2@infradead.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201206110327.175629-1-dwmw2@infradead.org> References: <20201206110327.175629-1-dwmw2@infradead.org> MIME-Version: 1.0 Sender: David Woodhouse X-SRS-Rewrite: SMTP reverse-path rewritten from by casper.infradead.org. See http://www.infradead.org/rpr.html Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Joao Martins This means when we set shared_info page GPA, and request a master clock update. This will trigger all vcpus to update their respective shared pvclock data with guests. We follow a similar approach as Hyper-V and KVM and adjust it accordingly. Note however that Xen differs a little on how pvclock pages are set up. Specifically KVM assumes 4KiB page alignment and pvclock data starts in the beginning of the page. Whereas Xen you can place that information anywhere in the page. Signed-off-by: Joao Martins Signed-off-by: David Woodhouse --- arch/x86/kvm/x86.c | 2 ++ arch/x86/kvm/xen.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++ arch/x86/kvm/xen.h | 1 + 3 files changed, 62 insertions(+) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 4a960629687c..e9191dfffbbb 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2719,6 +2719,8 @@ static int kvm_guest_time_update(struct kvm_vcpu *v) if (vcpu->pv_time_enabled) kvm_setup_pvclock_page(v); + if (ka->xen.shinfo) + kvm_xen_setup_pvclock_page(v); if (v == kvm_get_vcpu(v->kvm, 0)) kvm_hv_setup_tsc_page(v->kvm, &vcpu->hv_clock); return 0; diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c index c156ed1ef972..5373273e1be9 100644 --- a/arch/x86/kvm/xen.c +++ b/arch/x86/kvm/xen.c @@ -55,9 +55,68 @@ static int kvm_xen_shared_info_init(struct kvm *kvm, gfn_t gfn) if (ret) return ret; + kvm_make_all_cpus_request(kvm, KVM_REQ_MASTERCLOCK_UPDATE); + return 0; } +void kvm_xen_setup_pvclock_page(struct kvm_vcpu *v) +{ + struct kvm_vcpu_arch *vcpu = &v->arch; + struct pvclock_vcpu_time_info *guest_hv_clock; + unsigned int offset; + void *hva; + int idx; + + if (v->vcpu_id >= MAX_VIRT_CPUS) + return; + + BUILD_BUG_ON(offsetof(struct shared_info, vcpu_info) != 0); + BUILD_BUG_ON(offsetof(struct compat_shared_info, vcpu_info) != 0); + BUILD_BUG_ON(sizeof(struct vcpu_info) != sizeof(struct compat_vcpu_info)); + BUILD_BUG_ON(offsetof(struct vcpu_info, time) != + offsetof(struct compat_vcpu_info, time)); + + idx = srcu_read_lock(&v->kvm->srcu); + hva = READ_ONCE(v->kvm->arch.xen.shinfo); + if (!hva) + goto out; + + offset = v->vcpu_id * sizeof(struct vcpu_info); + offset += offsetof(struct vcpu_info, time); + + guest_hv_clock = hva + offset; + + if (guest_hv_clock->version & 1) + ++guest_hv_clock->version; /* first time write, random junk */ + + vcpu->hv_clock.version = guest_hv_clock->version + 1; + guest_hv_clock->version = vcpu->hv_clock.version; + + smp_wmb(); + + /* retain PVCLOCK_GUEST_STOPPED if set in guest copy */ + vcpu->hv_clock.flags |= (guest_hv_clock->flags & PVCLOCK_GUEST_STOPPED); + + if (vcpu->pvclock_set_guest_stopped_request) { + vcpu->hv_clock.flags |= PVCLOCK_GUEST_STOPPED; + vcpu->pvclock_set_guest_stopped_request = false; + } + + trace_kvm_pvclock_update(v->vcpu_id, &vcpu->hv_clock); + + *guest_hv_clock = vcpu->hv_clock; + + smp_wmb(); + + vcpu->hv_clock.version++; + + guest_hv_clock->version = vcpu->hv_clock.version; + + out: + srcu_read_unlock(&v->kvm->srcu, idx); +} + int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) { int r = -ENOENT; diff --git a/arch/x86/kvm/xen.h b/arch/x86/kvm/xen.h index cd3c52b62068..950a364f5b22 100644 --- a/arch/x86/kvm/xen.h +++ b/arch/x86/kvm/xen.h @@ -9,6 +9,7 @@ #ifndef __ARCH_X86_KVM_XEN_H__ #define __ARCH_X86_KVM_XEN_H__ +void kvm_xen_setup_pvclock_page(struct kvm_vcpu *vcpu); int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data); int kvm_xen_hvm_get_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data); int kvm_xen_hypercall(struct kvm_vcpu *vcpu); From patchwork Sun Dec 6 11:03:21 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 11953971 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D27DAC4167B for ; Sun, 6 Dec 2020 11:04:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 999112310B for ; Sun, 6 Dec 2020 11:04:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726985AbgLFLEi (ORCPT ); Sun, 6 Dec 2020 06:04:38 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41850 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726774AbgLFLEh (ORCPT ); Sun, 6 Dec 2020 06:04:37 -0500 Received: from merlin.infradead.org (merlin.infradead.org [IPv6:2001:8b0:10b:1231::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D854EC061A54 for ; Sun, 6 Dec 2020 03:03:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description; bh=Ho04uwHAcTuR5hfCn2RRdkuuvp7fiCKtW3niSHITmGQ=; b=ubZCaL8A/oR4D968BZukdkQ7mp 0NW1GsfvvkSwZ/ejcAYp8tY7VAJwmJfGBYcHva6jKFNLG/5mUkjaszi0dQrKQg2MbIVBbeK/GMSrM m/uEpmknn5PS+EpgbZMqiER9Bwc96QqsO7XmlhXhG/9BjraUYmO/mTkqOBA8LLBODFAZ2wtT4AHo/ oL4M3k4ttZLhr4OXvOd+NZSeZTDB16zBvSohfc8rWo8iJv+frVGOuc+wDe3b+YYmvcQPoGtUu9ieF /d/GSVxGokpUZ3ypztpyF+A1Jb8Z3tM9wcmPAGLLd87+LvS6VqqD4zOTVgG4RJaKhyuO0esNCWere qA00QsIA==; Received: from i7.infradead.org ([2001:8b0:10b:1:21e:67ff:fecb:7a92]) by merlin.infradead.org with esmtpsa (Exim 4.92.3 #3 (Red Hat Linux)) id 1klrpE-0004tL-Qs; Sun, 06 Dec 2020 11:03:32 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1klrpD-000jpb-Ox; Sun, 06 Dec 2020 11:03:31 +0000 From: David Woodhouse To: kvm@vger.kernel.org Cc: Paolo Bonzini , Ankur Arora , Joao Martins , Boris Ostrovsky , Sean Christopherson , graf@amazon.com, iaslan@amazon.de Subject: [PATCH v2 10/16] xen: add wc_sec_hi to struct shared_info Date: Sun, 6 Dec 2020 11:03:21 +0000 Message-Id: <20201206110327.175629-11-dwmw2@infradead.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201206110327.175629-1-dwmw2@infradead.org> References: <20201206110327.175629-1-dwmw2@infradead.org> MIME-Version: 1.0 Sender: David Woodhouse X-SRS-Rewrite: SMTP reverse-path rewritten from by merlin.infradead.org. See http://www.infradead.org/rpr.html Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: David Woodhouse Xen added this in 2015 (Xen 4.6). On x86_64 and arm it fills what was previously a 32-bit hole in the generic shared_info structure; on i386 it had to go at the end of struct arch_shared_info. Signed-off-by: David Woodhouse --- arch/x86/include/asm/xen/interface.h | 3 +++ include/xen/interface/xen.h | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/xen/interface.h b/arch/x86/include/asm/xen/interface.h index 9139b3e86316..baca0b00ef76 100644 --- a/arch/x86/include/asm/xen/interface.h +++ b/arch/x86/include/asm/xen/interface.h @@ -182,6 +182,9 @@ struct arch_shared_info { unsigned long p2m_cr3; /* cr3 value of the p2m address space */ unsigned long p2m_vaddr; /* virtual address of the p2m list */ unsigned long p2m_generation; /* generation count of p2m mapping */ +#ifdef CONFIG_X86_32 + uint32_t wc_sec_hi; +#endif }; #endif /* !__ASSEMBLY__ */ diff --git a/include/xen/interface/xen.h b/include/xen/interface/xen.h index 8bfb242f433e..5ee37a296481 100644 --- a/include/xen/interface/xen.h +++ b/include/xen/interface/xen.h @@ -598,7 +598,9 @@ struct shared_info { * their gettimeofday() syscall on this wallclock-base value. */ struct pvclock_wall_clock wc; - +#ifndef CONFIG_X86_32 + uint32_t wc_sec_hi; +#endif struct arch_shared_info arch; }; From patchwork Sun Dec 6 11:03:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 11953977 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F23CBC4361B for ; Sun, 6 Dec 2020 11:04:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BCA2D2310B for ; Sun, 6 Dec 2020 11:04:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727376AbgLFLE7 (ORCPT ); Sun, 6 Dec 2020 06:04:59 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41904 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727182AbgLFLE4 (ORCPT ); Sun, 6 Dec 2020 06:04:56 -0500 Received: from casper.infradead.org (casper.infradead.org [IPv6:2001:8b0:10b:1236::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BAF18C08E861 for ; Sun, 6 Dec 2020 03:03:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description; bh=4ItpgzQaL1uhHOpRIN30my1KSm9PXmqLlA+glcCFWFk=; b=AnANITDZU7EXYoDo6VbrYZ2iZc qVzUE7qKdFXTjeeMXGf3X1M71AFgRViPp+ryl4BqOGXBHmtd5/PGhLsLoItjOVCmIWTHAfH3hKaOS ubqu+yMDFopCs9+tZxjgaCKrQNp3oExNrZ/Rwl6f3g5tSzvAaMVW6XJnElDmP2HOaZEQBi1yOnCfY uEkMqeSpZxo/xY+BgTbW0t/1XwTB3nJ6sC5qEmduv0p2KvDnKF3qMzQegn5nxXBUvhWVQRv3J5312 Os1jpL9taNgvdioQ9kQWkJUnsFr4NxceYeQYl9Ur0AFaWLpaQEVFfoEYJUiRLv0wmf9M7WsNAhs7j I0eN9Jnw==; Received: from i7.infradead.org ([2001:8b0:10b:1:21e:67ff:fecb:7a92]) by casper.infradead.org with esmtpsa (Exim 4.92.3 #3 (Red Hat Linux)) id 1klrpE-0006Fr-6R; Sun, 06 Dec 2020 11:03:42 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1klrpD-000jpe-PT; Sun, 06 Dec 2020 11:03:31 +0000 From: David Woodhouse To: kvm@vger.kernel.org Cc: Paolo Bonzini , Ankur Arora , Joao Martins , Boris Ostrovsky , Sean Christopherson , graf@amazon.com, iaslan@amazon.de Subject: [PATCH v2 11/16] KVM: x86/xen: update wallclock region Date: Sun, 6 Dec 2020 11:03:22 +0000 Message-Id: <20201206110327.175629-12-dwmw2@infradead.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201206110327.175629-1-dwmw2@infradead.org> References: <20201206110327.175629-1-dwmw2@infradead.org> MIME-Version: 1.0 Sender: David Woodhouse X-SRS-Rewrite: SMTP reverse-path rewritten from by casper.infradead.org. See http://www.infradead.org/rpr.html Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Joao Martins Wallclock on Xen is written in the shared_info page. To that purpose, export kvm_write_wall_clock() and pass on the GPA of its location to populate the shared_info wall clock data. Signed-off-by: Joao Martins Signed-off-by: David Woodhouse --- arch/x86/kvm/x86.c | 17 ++++++++++++----- arch/x86/kvm/x86.h | 1 + arch/x86/kvm/xen.c | 20 ++++++++++++++++++++ 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index e9191dfffbbb..abc4c78a7aa4 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1921,15 +1921,14 @@ static s64 get_kvmclock_base_ns(void) } #endif -static void kvm_write_wall_clock(struct kvm *kvm, gpa_t wall_clock) +void kvm_write_wall_clock(struct kvm *kvm, gpa_t wall_clock, int sec_hi_ofs) { int version; int r; struct pvclock_wall_clock wc; + u32 wc_sec_hi; u64 wall_nsec; - kvm->arch.wall_clock = wall_clock; - if (!wall_clock) return; @@ -1958,6 +1957,12 @@ static void kvm_write_wall_clock(struct kvm *kvm, gpa_t wall_clock) kvm_write_guest(kvm, wall_clock, &wc, sizeof(wc)); + if (sec_hi_ofs) { + wc_sec_hi = wall_nsec >> 32; + kvm_write_guest(kvm, wall_clock + sec_hi_ofs, + &wc_sec_hi, sizeof(wc_sec_hi)); + } + version++; kvm_write_guest(kvm, wall_clock, &version, sizeof(version)); } @@ -3117,13 +3122,15 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) if (!guest_pv_has(vcpu, KVM_FEATURE_CLOCKSOURCE2)) return 1; - kvm_write_wall_clock(vcpu->kvm, data); + vcpu->kvm->arch.wall_clock = data; + kvm_write_wall_clock(vcpu->kvm, data, 0); break; case MSR_KVM_WALL_CLOCK: if (!guest_pv_has(vcpu, KVM_FEATURE_CLOCKSOURCE)) return 1; - kvm_write_wall_clock(vcpu->kvm, data); + vcpu->kvm->arch.wall_clock = data; + kvm_write_wall_clock(vcpu->kvm, data, 0); break; case MSR_KVM_SYSTEM_TIME_NEW: if (!guest_pv_has(vcpu, KVM_FEATURE_CLOCKSOURCE2)) diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index e7ca622a468f..cf8778410015 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -246,6 +246,7 @@ static inline bool kvm_vcpu_latch_init(struct kvm_vcpu *vcpu) return is_smm(vcpu) || kvm_x86_ops.apic_init_signal_blocked(vcpu); } +void kvm_write_wall_clock(struct kvm *kvm, gpa_t wall_clock, int sec_hi_ofs); void kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq, int inc_eip); void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr); diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c index 5373273e1be9..cb2a37cf12da 100644 --- a/arch/x86/kvm/xen.c +++ b/arch/x86/kvm/xen.c @@ -47,6 +47,7 @@ static int kvm_xen_map_guest_page(struct kvm *kvm, struct kvm_host_map *map, static int kvm_xen_shared_info_init(struct kvm *kvm, gfn_t gfn) { gpa_t gpa = gfn_to_gpa(gfn); + int wc_ofs, sec_hi_ofs; int ret; ret = kvm_xen_map_guest_page(kvm, &kvm->arch.xen.shinfo_map, @@ -55,6 +56,25 @@ static int kvm_xen_shared_info_init(struct kvm *kvm, gfn_t gfn) if (ret) return ret; + BUILD_BUG_ON(offsetof(struct compat_shared_info, wc) != 0x900); + BUILD_BUG_ON(offsetof(struct compat_shared_info, arch.wc_sec_hi) != 0x924); + BUILD_BUG_ON(offsetof(struct pvclock_vcpu_time_info, version) != 0); + + /* 32-bit location by default */ + wc_ofs = offsetof(struct compat_shared_info, wc); + sec_hi_ofs = offsetof(struct compat_shared_info, arch.wc_sec_hi); + +#ifdef CONFIG_64BIT + BUILD_BUG_ON(offsetof(struct shared_info, wc) != 0xc00); + BUILD_BUG_ON(offsetof(struct shared_info, wc_sec_hi) != 0xc0c); + + if (kvm->arch.xen.long_mode) { + wc_ofs = offsetof(struct shared_info, wc); + sec_hi_ofs = offsetof(struct shared_info, wc_sec_hi); + } +#endif + + kvm_write_wall_clock(kvm, gpa + wc_ofs, sec_hi_ofs - wc_ofs); kvm_make_all_cpus_request(kvm, KVM_REQ_MASTERCLOCK_UPDATE); return 0; From patchwork Sun Dec 6 11:03:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 11953973 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4D2E0C4361B for ; Sun, 6 Dec 2020 11:04:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1CC7722E03 for ; Sun, 6 Dec 2020 11:04:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727108AbgLFLEi (ORCPT ); Sun, 6 Dec 2020 06:04:38 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41852 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726886AbgLFLEh (ORCPT ); Sun, 6 Dec 2020 06:04:37 -0500 Received: from merlin.infradead.org (merlin.infradead.org [IPv6:2001:8b0:10b:1231::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DCF5AC061A55 for ; Sun, 6 Dec 2020 03:03:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description; bh=RIBLkremV8VRJ8yij0ZrrOY6kMMOGhoTXP3SsJTLyUE=; b=XjCgYKztXC+3Ih5MgV/UvcWHUA Xhoeq1qz309hGalDuLhDth4XTzs3235G0EZK3k//uN95UytSfx3PZdBF6odaycMV7jq+DwEad4DAA jMM2zdCI/z1AxeyamX5qjRZZIDdB21apKu/5KuNLoTChJkX1Tdetgim6oQmiBmki8Yss2TvVkCdda D2VgF6B14NpfWBsv/3zGghDukDybcdLnRAojQ5UDkVwA/6/aPBe9E71VeVjUjWLNJVD45wzsxeChG bEJPcxydXSuP/JWDW+mgWI6QwMWz8iipl7s8ahJbMh2H+V1YA7+Lxi92qdodxgC06wRDtHpvywN33 nwpQ03Lg==; Received: from i7.infradead.org ([2001:8b0:10b:1:21e:67ff:fecb:7a92]) by merlin.infradead.org with esmtpsa (Exim 4.92.3 #3 (Red Hat Linux)) id 1klrpE-0004tM-SG; Sun, 06 Dec 2020 11:03:33 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1klrpD-000jph-Q5; Sun, 06 Dec 2020 11:03:31 +0000 From: David Woodhouse To: kvm@vger.kernel.org Cc: Paolo Bonzini , Ankur Arora , Joao Martins , Boris Ostrovsky , Sean Christopherson , graf@amazon.com, iaslan@amazon.de Subject: [PATCH v2 12/16] KVM: x86/xen: register vcpu info Date: Sun, 6 Dec 2020 11:03:23 +0000 Message-Id: <20201206110327.175629-13-dwmw2@infradead.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201206110327.175629-1-dwmw2@infradead.org> References: <20201206110327.175629-1-dwmw2@infradead.org> MIME-Version: 1.0 Sender: David Woodhouse X-SRS-Rewrite: SMTP reverse-path rewritten from by merlin.infradead.org. See http://www.infradead.org/rpr.html Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Joao Martins The vcpu info supersedes the per vcpu area of the shared info page and the guest vcpus will use this instead. Signed-off-by: Joao Martins Signed-off-by: Ankur Arora Signed-off-by: David Woodhouse --- arch/x86/include/asm/kvm_host.h | 2 + arch/x86/kvm/x86.c | 1 + arch/x86/kvm/xen.c | 96 +++++++++++++++++++++++++++++++-- arch/x86/kvm/xen.h | 14 +++++ include/uapi/linux/kvm.h | 5 ++ 5 files changed, 113 insertions(+), 5 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index b6eff9814c6a..617c120d03a3 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -523,6 +523,8 @@ struct kvm_vcpu_hv { /* Xen HVM per vcpu emulation context */ struct kvm_vcpu_xen { u64 hypercall_rip; + struct kvm_host_map vcpu_info_map; + struct vcpu_info *vcpu_info; }; struct kvm_vcpu_arch { diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index abc4c78a7aa4..27f3a59f45b1 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -10004,6 +10004,7 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) kmem_cache_free(x86_fpu_cache, vcpu->arch.guest_fpu); kvm_hv_vcpu_uninit(vcpu); + kvm_xen_vcpu_uninit(vcpu); kvm_pmu_destroy(vcpu); kfree(vcpu->arch.mce_banks); kvm_free_lapic(vcpu); diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c index cb2a37cf12da..2a160a5c8589 100644 --- a/arch/x86/kvm/xen.c +++ b/arch/x86/kvm/xen.c @@ -80,6 +80,27 @@ static int kvm_xen_shared_info_init(struct kvm *kvm, gfn_t gfn) return 0; } +static void *xen_vcpu_info(struct kvm_vcpu *v) +{ + struct kvm_vcpu_xen *vcpu_xen = vcpu_to_xen_vcpu(v); + struct kvm_xen *kvm = &v->kvm->arch.xen; + void *hva; + + hva = READ_ONCE(vcpu_xen->vcpu_info); + if (hva) + return hva; + + if (v->vcpu_id < MAX_VIRT_CPUS) + hva = READ_ONCE(kvm->shinfo); + + if (hva) { + hva += offsetof(struct shared_info, vcpu_info); + hva += v->vcpu_id * sizeof(struct vcpu_info); + } + + return hva; +} + void kvm_xen_setup_pvclock_page(struct kvm_vcpu *v) { struct kvm_vcpu_arch *vcpu = &v->arch; @@ -88,9 +109,6 @@ void kvm_xen_setup_pvclock_page(struct kvm_vcpu *v) void *hva; int idx; - if (v->vcpu_id >= MAX_VIRT_CPUS) - return; - BUILD_BUG_ON(offsetof(struct shared_info, vcpu_info) != 0); BUILD_BUG_ON(offsetof(struct compat_shared_info, vcpu_info) != 0); BUILD_BUG_ON(sizeof(struct vcpu_info) != sizeof(struct compat_vcpu_info)); @@ -98,7 +116,7 @@ void kvm_xen_setup_pvclock_page(struct kvm_vcpu *v) offsetof(struct compat_vcpu_info, time)); idx = srcu_read_lock(&v->kvm->srcu); - hva = READ_ONCE(v->kvm->arch.xen.shinfo); + hva = xen_vcpu_info(v); if (!hva) goto out; @@ -108,7 +126,7 @@ void kvm_xen_setup_pvclock_page(struct kvm_vcpu *v) guest_hv_clock = hva + offset; if (guest_hv_clock->version & 1) - ++guest_hv_clock->version; /* first time write, random junk */ + ++guest_hv_clock->version; vcpu->hv_clock.version = guest_hv_clock->version + 1; guest_hv_clock->version = vcpu->hv_clock.version; @@ -137,6 +155,20 @@ void kvm_xen_setup_pvclock_page(struct kvm_vcpu *v) srcu_read_unlock(&v->kvm->srcu, idx); } +static int vcpu_attr_loc(struct kvm_vcpu *vcpu, u16 type, + struct kvm_host_map **map, void ***hva, size_t *sz) +{ + switch(type) { + case KVM_XEN_ATTR_TYPE_VCPU_INFO: + *map = &vcpu->arch.xen.vcpu_info_map; + *hva = (void **)&vcpu->arch.xen.vcpu_info; + if (sz) + *sz = sizeof(struct vcpu_info); + return 0; + } + return -EINVAL; +} + int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) { int r = -ENOENT; @@ -157,6 +189,28 @@ int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) break; } + case KVM_XEN_ATTR_TYPE_VCPU_INFO: { + gpa_t gpa = data->u.vcpu_attr.gpa; + struct kvm_host_map *map; + struct kvm_vcpu *v; + size_t sz; + void **hva; + + v = kvm_get_vcpu(kvm, data->u.vcpu_attr.vcpu); + if (!v) + return -EINVAL; + + r = vcpu_attr_loc(v, data->type, &map, &hva, &sz); + if (r) + return r; + + r = kvm_xen_map_guest_page(kvm, map, hva, gpa, sz); + if (!r) + kvm_xen_setup_pvclock_page(v); + + break; + } + default: break; } @@ -182,6 +236,27 @@ int kvm_xen_hvm_get_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) break; } + case KVM_XEN_ATTR_TYPE_VCPU_INFO: { + struct kvm_host_map *map; + struct kvm_vcpu *v; + void **hva; + + v = kvm_get_vcpu(kvm, data->u.vcpu_attr.vcpu); + if (!v) + return -EINVAL; + + r = vcpu_attr_loc(v, data->type, &map, &hva, NULL); + if (r) + return r; + + if (*hva) { + data->u.vcpu_attr.gpa = gfn_to_gpa(map->gfn) + + offset_in_page(*hva); + r = 0; + } + break; + } + default: break; } @@ -321,6 +396,17 @@ int kvm_xen_hypercall(struct kvm_vcpu *vcpu) return 0; } +void kvm_xen_vcpu_uninit(struct kvm_vcpu *vcpu) +{ + struct kvm_vcpu_xen *vcpu_xen = vcpu_to_xen_vcpu(vcpu); + + if (vcpu_xen->vcpu_info) { + kvm_unmap_gfn(vcpu->kvm, &vcpu_xen->vcpu_info_map, + NULL, true, false); + vcpu_xen->vcpu_info = NULL; + } +} + void kvm_xen_destroy_vm(struct kvm *kvm) { struct kvm_xen *xen = &kvm->arch.xen; diff --git a/arch/x86/kvm/xen.h b/arch/x86/kvm/xen.h index 950a364f5b22..a4d80cc21ee4 100644 --- a/arch/x86/kvm/xen.h +++ b/arch/x86/kvm/xen.h @@ -9,12 +9,26 @@ #ifndef __ARCH_X86_KVM_XEN_H__ #define __ARCH_X86_KVM_XEN_H__ +static inline struct kvm_vcpu_xen *vcpu_to_xen_vcpu(struct kvm_vcpu *vcpu) +{ + return &vcpu->arch.xen; +} + +static inline struct kvm_vcpu *xen_vcpu_to_vcpu(struct kvm_vcpu_xen *xen_vcpu) +{ + struct kvm_vcpu_arch *arch; + + arch = container_of(xen_vcpu, struct kvm_vcpu_arch, xen); + return container_of(arch, struct kvm_vcpu, arch); +} + void kvm_xen_setup_pvclock_page(struct kvm_vcpu *vcpu); int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data); int kvm_xen_hvm_get_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data); int kvm_xen_hypercall(struct kvm_vcpu *vcpu); int kvm_xen_hvm_config(struct kvm_vcpu *vcpu, u64 data); void kvm_xen_destroy_vm(struct kvm *kvm); +void kvm_xen_vcpu_uninit(struct kvm_vcpu *vcpu); static inline bool kvm_xen_hypercall_enabled(struct kvm *kvm) { diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index caa9faf3c5ad..8dda080175b6 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1588,12 +1588,17 @@ struct kvm_xen_hvm_attr { struct { __u64 gfn; } shared_info; + struct { + __u32 vcpu; + __u64 gpa; + } vcpu_attr; __u64 pad[4]; } u; }; #define KVM_XEN_ATTR_TYPE_LONG_MODE 0x0 #define KVM_XEN_ATTR_TYPE_SHARED_INFO 0x1 +#define KVM_XEN_ATTR_TYPE_VCPU_INFO 0x2 /* Secure Encrypted Virtualization command */ enum sev_cmd_id { From patchwork Sun Dec 6 11:03:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 11953965 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 15826C19425 for ; Sun, 6 Dec 2020 11:04:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E01F623122 for ; Sun, 6 Dec 2020 11:04:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726682AbgLFLER (ORCPT ); Sun, 6 Dec 2020 06:04:17 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41792 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726077AbgLFLEQ (ORCPT ); Sun, 6 Dec 2020 06:04:16 -0500 Received: from merlin.infradead.org (merlin.infradead.org [IPv6:2001:8b0:10b:1231::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D6555C061A53 for ; Sun, 6 Dec 2020 03:03:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description; bh=G3h2y4HGxsW9vktNlEFOJWEhUUjXG4P3u6KUdNeZZXc=; b=hfxWaIU7G4cN2kK8LsMTucgGEz qPkuGvGhfy1H3yZEWdncbnQyEzUNGmtblez5kZqHxSotKOgLw/zGrm5YmPTU87iUPpTurmjQ0HRU1 E3Nx7xKvfxGELyYrMdEidi1ntw7t4nDsCwU0xshNzXAeG4CokQVf4pL/jpzaQkjzW9XAckYMrRGOz 9B3KSu4aqmdP2wcswj6z/N5PGxY3hiSjXUCcqCPVha+jqckD5dWLT77iV+fZhznW5lyipNGnPog4g id1xNi+NZv/nDwrlnUos/200RNY67Y4bAHOGe+trdWCthgAVQJYeqFzzsKM7EyLX9r5tT7hL+n5pl 4u1K4MCQ==; Received: from i7.infradead.org ([2001:8b0:10b:1:21e:67ff:fecb:7a92]) by merlin.infradead.org with esmtpsa (Exim 4.92.3 #3 (Red Hat Linux)) id 1klrpE-0004tN-Sj; Sun, 06 Dec 2020 11:03:33 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1klrpD-000jpk-Ql; Sun, 06 Dec 2020 11:03:31 +0000 From: David Woodhouse To: kvm@vger.kernel.org Cc: Paolo Bonzini , Ankur Arora , Joao Martins , Boris Ostrovsky , Sean Christopherson , graf@amazon.com, iaslan@amazon.de Subject: [PATCH v2 13/16] KVM: x86/xen: register vcpu time info region Date: Sun, 6 Dec 2020 11:03:24 +0000 Message-Id: <20201206110327.175629-14-dwmw2@infradead.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201206110327.175629-1-dwmw2@infradead.org> References: <20201206110327.175629-1-dwmw2@infradead.org> MIME-Version: 1.0 Sender: David Woodhouse X-SRS-Rewrite: SMTP reverse-path rewritten from by merlin.infradead.org. See http://www.infradead.org/rpr.html Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Joao Martins Allow the Xen emulated guest the ability to register secondary vcpu time information. On Xen guests this is used in order to be mapped to userspace and hence allow vdso gettimeofday to work. In doing so, move kvm_xen_set_pvclock_page() logic to kvm_xen_update_vcpu_time() and have the former a top-level function which updates primary vcpu time info (in struct vcpu_info) and secondary one. Signed-off-by: Joao Martins Signed-off-by: David Woodhouse --- arch/x86/include/asm/kvm_host.h | 2 ++ arch/x86/kvm/xen.c | 62 +++++++++++++++++++++------------ include/uapi/linux/kvm.h | 1 + 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 617c120d03a3..ec9425289209 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -525,6 +525,8 @@ struct kvm_vcpu_xen { u64 hypercall_rip; struct kvm_host_map vcpu_info_map; struct vcpu_info *vcpu_info; + struct kvm_host_map pv_time_map; + struct pvclock_vcpu_time_info *pv_time; }; struct kvm_vcpu_arch { diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c index 2a160a5c8589..74716c2b455f 100644 --- a/arch/x86/kvm/xen.c +++ b/arch/x86/kvm/xen.c @@ -101,29 +101,10 @@ static void *xen_vcpu_info(struct kvm_vcpu *v) return hva; } -void kvm_xen_setup_pvclock_page(struct kvm_vcpu *v) +static void kvm_xen_update_vcpu_time(struct kvm_vcpu *v, + struct pvclock_vcpu_time_info *guest_hv_clock) { struct kvm_vcpu_arch *vcpu = &v->arch; - struct pvclock_vcpu_time_info *guest_hv_clock; - unsigned int offset; - void *hva; - int idx; - - BUILD_BUG_ON(offsetof(struct shared_info, vcpu_info) != 0); - BUILD_BUG_ON(offsetof(struct compat_shared_info, vcpu_info) != 0); - BUILD_BUG_ON(sizeof(struct vcpu_info) != sizeof(struct compat_vcpu_info)); - BUILD_BUG_ON(offsetof(struct vcpu_info, time) != - offsetof(struct compat_vcpu_info, time)); - - idx = srcu_read_lock(&v->kvm->srcu); - hva = xen_vcpu_info(v); - if (!hva) - goto out; - - offset = v->vcpu_id * sizeof(struct vcpu_info); - offset += offsetof(struct vcpu_info, time); - - guest_hv_clock = hva + offset; if (guest_hv_clock->version & 1) ++guest_hv_clock->version; @@ -150,8 +131,31 @@ void kvm_xen_setup_pvclock_page(struct kvm_vcpu *v) vcpu->hv_clock.version++; guest_hv_clock->version = vcpu->hv_clock.version; +} + +void kvm_xen_setup_pvclock_page(struct kvm_vcpu *v) +{ + struct kvm_vcpu_xen *vcpu_xen = vcpu_to_xen_vcpu(v); + struct vcpu_info *vcpu_info; + struct pvclock_vcpu_time_info *pv_info; + int idx; + + BUILD_BUG_ON(offsetof(struct shared_info, vcpu_info) != 0); + BUILD_BUG_ON(offsetof(struct compat_shared_info, vcpu_info) != 0); + BUILD_BUG_ON(sizeof(struct vcpu_info) != sizeof(struct compat_vcpu_info)); + BUILD_BUG_ON(offsetof(struct vcpu_info, time) != + offsetof(struct compat_vcpu_info, time)); + + idx = srcu_read_lock(&v->kvm->srcu); + vcpu_info = xen_vcpu_info(v); + if (likely(vcpu_info)) + kvm_xen_update_vcpu_time(v, &vcpu_info->time); + + /* Update secondary pvclock region if registered */ + pv_info = READ_ONCE(vcpu_xen->pv_time); + if (pv_info) + kvm_xen_update_vcpu_time(v, pv_info); - out: srcu_read_unlock(&v->kvm->srcu, idx); } @@ -165,6 +169,13 @@ static int vcpu_attr_loc(struct kvm_vcpu *vcpu, u16 type, if (sz) *sz = sizeof(struct vcpu_info); return 0; + + case KVM_XEN_ATTR_TYPE_VCPU_TIME_INFO: + *map = &vcpu->arch.xen.pv_time_map; + *hva = (void **)&vcpu->arch.xen.pv_time; + if (sz) + *sz = sizeof(struct pvclock_vcpu_time_info); + return 0; } return -EINVAL; } @@ -189,6 +200,7 @@ int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) break; } + case KVM_XEN_ATTR_TYPE_VCPU_TIME_INFO: case KVM_XEN_ATTR_TYPE_VCPU_INFO: { gpa_t gpa = data->u.vcpu_attr.gpa; struct kvm_host_map *map; @@ -236,6 +248,7 @@ int kvm_xen_hvm_get_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) break; } + case KVM_XEN_ATTR_TYPE_VCPU_TIME_INFO: case KVM_XEN_ATTR_TYPE_VCPU_INFO: { struct kvm_host_map *map; struct kvm_vcpu *v; @@ -405,6 +418,11 @@ void kvm_xen_vcpu_uninit(struct kvm_vcpu *vcpu) NULL, true, false); vcpu_xen->vcpu_info = NULL; } + if (vcpu_xen->pv_time) { + kvm_unmap_gfn(vcpu->kvm, &vcpu_xen->pv_time_map, + NULL, true, false); + vcpu_xen->pv_time = NULL; + } } void kvm_xen_destroy_vm(struct kvm *kvm) diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 8dda080175b6..3ff3f72ac6b3 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1599,6 +1599,7 @@ struct kvm_xen_hvm_attr { #define KVM_XEN_ATTR_TYPE_LONG_MODE 0x0 #define KVM_XEN_ATTR_TYPE_SHARED_INFO 0x1 #define KVM_XEN_ATTR_TYPE_VCPU_INFO 0x2 +#define KVM_XEN_ATTR_TYPE_VCPU_TIME_INFO 0x3 /* Secure Encrypted Virtualization command */ enum sev_cmd_id { From patchwork Sun Dec 6 11:03:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 11953991 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.9 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, UNWANTED_LANGUAGE_BODY,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 601ADC1B0D9 for ; Sun, 6 Dec 2020 11:05:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 48D5F2310B for ; Sun, 6 Dec 2020 11:05:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727343AbgLFLFE (ORCPT ); Sun, 6 Dec 2020 06:05:04 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41912 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727256AbgLFLE4 (ORCPT ); Sun, 6 Dec 2020 06:04:56 -0500 Received: from casper.infradead.org (casper.infradead.org [IPv6:2001:8b0:10b:1236::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B818AC0613D0 for ; Sun, 6 Dec 2020 03:03:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description; bh=66v3z6elS2r1v4Cf9tGY5WsNE/3UjGNklavuTdi9FkA=; b=fTjg25WZ8pqTKN5w7u2C97DLTn LlzLloE5T1uNnYMIjOYnBKCkAViF4YYU2x4xqDXG0P4tt6XtY1//a4fxvjdpj/gfWa+zNEjRdYz1C +pFDAkQp3G5+Mw3T3Y4cfTm3oox4DYXAH/CzekZYuFuSRzOR02avwjV4YbZxBeXTcCHQe0UjoLgxm 67su6UVlRFZgoinhyShIXYwTqTNqLK7utLZmNr9l7YzXOIrG1dz5+Va7ze9Zt5nLV5DYEtLjL3V5T b+8j1aifp5O6wcYZpH28u14XyZ5Gc0MyKW3vQNyBllkDGDGPxNjfjKIwEJ+iQ4QNUWyBoixSr0Mv1 N65xA3nA==; Received: from i7.infradead.org ([2001:8b0:10b:1:21e:67ff:fecb:7a92]) by casper.infradead.org with esmtpsa (Exim 4.92.3 #3 (Red Hat Linux)) id 1klrpE-0006Fs-98; Sun, 06 Dec 2020 11:03:42 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1klrpD-000jpn-RP; Sun, 06 Dec 2020 11:03:31 +0000 From: David Woodhouse To: kvm@vger.kernel.org Cc: Paolo Bonzini , Ankur Arora , Joao Martins , Boris Ostrovsky , Sean Christopherson , graf@amazon.com, iaslan@amazon.de Subject: [PATCH v2 14/16] KVM: x86/xen: register runstate info Date: Sun, 6 Dec 2020 11:03:25 +0000 Message-Id: <20201206110327.175629-15-dwmw2@infradead.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201206110327.175629-1-dwmw2@infradead.org> References: <20201206110327.175629-1-dwmw2@infradead.org> MIME-Version: 1.0 Sender: David Woodhouse X-SRS-Rewrite: SMTP reverse-path rewritten from by casper.infradead.org. See http://www.infradead.org/rpr.html Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Joao Martins Allow emulator to register vcpu runstates which allow Xen guests to use that for steal clock. The 'preempted' state of KVM steal clock equates to 'runnable' state, 'running' has similar meanings for both and 'offline' is used when system admin needs to bring vcpu offline or hotplug. Signed-off-by: Joao Martins Signed-off-by: David Woodhouse --- arch/x86/include/asm/kvm_host.h | 5 ++ arch/x86/kvm/x86.c | 10 +++ arch/x86/kvm/xen.c | 127 +++++++++++++++++++++++++++++++- arch/x86/kvm/xen.h | 9 ++- include/uapi/linux/kvm.h | 1 + 5 files changed, 148 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index ec9425289209..d8716ef27728 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -527,6 +527,11 @@ struct kvm_vcpu_xen { struct vcpu_info *vcpu_info; struct kvm_host_map pv_time_map; struct pvclock_vcpu_time_info *pv_time; + struct kvm_host_map runstate_map; + void *runstate; + uint32_t current_runstate; + uint64_t last_steal; + uint64_t last_state_ns; }; struct kvm_vcpu_arch { diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 27f3a59f45b1..9cbe8ee0de47 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2935,6 +2935,11 @@ static void record_steal_time(struct kvm_vcpu *vcpu) struct kvm_host_map map; struct kvm_steal_time *st; + if (vcpu->arch.xen.runstate) { + kvm_xen_setup_runstate_page(vcpu); + return; + } + if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED)) return; @@ -3963,6 +3968,11 @@ static void kvm_steal_time_set_preempted(struct kvm_vcpu *vcpu) struct kvm_host_map map; struct kvm_steal_time *st; + if (vcpu->arch.xen.runstate) { + kvm_xen_runstate_set_preempted(vcpu); + return; + } + if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED)) return; diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c index 74716c2b455f..4aa776c1ad57 100644 --- a/arch/x86/kvm/xen.c +++ b/arch/x86/kvm/xen.c @@ -11,9 +11,11 @@ #include "hyperv.h" #include +#include #include #include +#include #include "trace.h" @@ -133,6 +135,102 @@ static void kvm_xen_update_vcpu_time(struct kvm_vcpu *v, guest_hv_clock->version = vcpu->hv_clock.version; } +static void kvm_xen_update_runstate(struct kvm_vcpu *vcpu, int state, u64 steal_ns) +{ + struct kvm_vcpu_xen *vcpu_xen = vcpu_to_xen_vcpu(vcpu); + struct compat_vcpu_runstate_info *runstate; + u32 *runstate_state; + u64 now, delta; + int idx; + + BUILD_BUG_ON(sizeof(struct compat_vcpu_runstate_info) != 0x2c); + BUILD_BUG_ON(offsetof(struct vcpu_runstate_info, state) != + offsetof(struct compat_vcpu_runstate_info, state)); + BUILD_BUG_ON(sizeof(((struct vcpu_runstate_info *)0)->state) != + sizeof(((struct compat_vcpu_runstate_info *)0)->state)); + + idx = srcu_read_lock(&vcpu->kvm->srcu); + runstate = READ_ONCE(vcpu_xen->runstate); + runstate_state = &runstate->state; + +#ifdef CONFIG_64BIT + /* + * The only different is alignment of uint64_t in 32-bit. + * So the first field 'state' is accessed via *runstate_state + * which is unmodified, while the other fields are accessed + * through 'runstate->' which we tweak here by adding 4. + */ + BUILD_BUG_ON(offsetof(struct vcpu_runstate_info, state_entry_time) != + offsetof(struct compat_vcpu_runstate_info, state_entry_time) + 4); + BUILD_BUG_ON(offsetof(struct vcpu_runstate_info, time) != + offsetof(struct compat_vcpu_runstate_info, time) + 4); + if (vcpu->kvm->arch.xen.long_mode) + runstate = ((void *)runstate) + 4; +#endif + /* + * Although it's called "state_entry_time" and explicitly documented + * as being "the system time at which the VCPU was last scheduled to + * run", Xen just treats it as a counter for HVM domains too. + */ + runstate->state_entry_time = XEN_RUNSTATE_UPDATE | + (runstate->state_entry_time + 1); + smp_wmb(); + + now = ktime_get_ns(); + delta = now - vcpu_xen->last_state_ns - steal_ns; + + *runstate_state = state; + runstate->time[vcpu_xen->current_runstate] += delta; + if (steal_ns) + runstate->time[RUNSTATE_runnable] += steal_ns; + smp_wmb(); + vcpu_xen->current_runstate = state; + vcpu_xen->last_state_ns = now; + + runstate->state_entry_time &= ~XEN_RUNSTATE_UPDATE; + smp_wmb(); + + srcu_read_unlock(&vcpu->kvm->srcu, idx); +} + +void kvm_xen_runstate_set_preempted(struct kvm_vcpu *vcpu) +{ + struct kvm_vcpu_xen *vcpu_xen = vcpu_to_xen_vcpu(vcpu); + int new_state; + + BUILD_BUG_ON(sizeof(struct compat_vcpu_runstate_info) != 0x2c); + BUILD_BUG_ON(offsetof(struct vcpu_runstate_info, state) != + offsetof(struct compat_vcpu_runstate_info, state)); + BUILD_BUG_ON(sizeof(((struct vcpu_runstate_info *)0)->state) != + sizeof(((struct compat_vcpu_runstate_info *)0)->state)); + + if (vcpu->preempted) { + new_state = RUNSTATE_runnable; + } else { + new_state = RUNSTATE_blocked; + vcpu_xen->last_steal = current->sched_info.run_delay; + } + + kvm_xen_update_runstate(vcpu, new_state, 0); +} + +void kvm_xen_setup_runstate_page(struct kvm_vcpu *vcpu) +{ + struct kvm_vcpu_xen *vcpu_xen = vcpu_to_xen_vcpu(vcpu); + u64 steal_time = 0; + + /* + * If the CPU was blocked when it last stopped, presumably + * it became unblocked at some point because it's being run + * again now. The scheduler run_delay is the runnable time, + * to be subtracted from the blocked time. + */ + if (vcpu_xen->current_runstate == RUNSTATE_blocked) + steal_time = current->sched_info.run_delay - vcpu_xen->last_steal; + + kvm_xen_update_runstate(vcpu, RUNSTATE_running, steal_time); +} + void kvm_xen_setup_pvclock_page(struct kvm_vcpu *v) { struct kvm_vcpu_xen *vcpu_xen = vcpu_to_xen_vcpu(v); @@ -176,6 +274,15 @@ static int vcpu_attr_loc(struct kvm_vcpu *vcpu, u16 type, if (sz) *sz = sizeof(struct pvclock_vcpu_time_info); return 0; + + case KVM_XEN_ATTR_TYPE_VCPU_RUNSTATE: + *map = &vcpu->arch.xen.runstate_map; + *hva = (void **)&vcpu->arch.xen.runstate; + if (sz) + *sz = vcpu->kvm->arch.xen.long_mode ? + sizeof(struct shared_info) : + sizeof(struct compat_shared_info); + return 0; } return -EINVAL; } @@ -200,6 +307,10 @@ int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) break; } + case KVM_XEN_ATTR_TYPE_VCPU_RUNSTATE: + if (unlikely(!sched_info_on())) + return -ENOTSUPP; + /* fallthrough */ case KVM_XEN_ATTR_TYPE_VCPU_TIME_INFO: case KVM_XEN_ATTR_TYPE_VCPU_INFO: { gpa_t gpa = data->u.vcpu_attr.gpa; @@ -217,9 +328,13 @@ int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) return r; r = kvm_xen_map_guest_page(kvm, map, hva, gpa, sz); - if (!r) - kvm_xen_setup_pvclock_page(v); - + if (!r) { + if (data->type == KVM_XEN_ATTR_TYPE_VCPU_RUNSTATE) { + v->arch.xen.current_runstate = RUNSTATE_blocked; + v->arch.xen.last_state_ns = ktime_get_ns(); + } else + kvm_xen_setup_pvclock_page(v); + } break; } @@ -248,6 +363,7 @@ int kvm_xen_hvm_get_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) break; } + case KVM_XEN_ATTR_TYPE_VCPU_RUNSTATE: case KVM_XEN_ATTR_TYPE_VCPU_TIME_INFO: case KVM_XEN_ATTR_TYPE_VCPU_INFO: { struct kvm_host_map *map; @@ -423,6 +539,11 @@ void kvm_xen_vcpu_uninit(struct kvm_vcpu *vcpu) NULL, true, false); vcpu_xen->pv_time = NULL; } + if (vcpu_xen->runstate) { + kvm_unmap_gfn(vcpu->kvm, &vcpu_xen->runstate_map, + NULL, true, false); + vcpu_xen->runstate = NULL; + } } void kvm_xen_destroy_vm(struct kvm *kvm) diff --git a/arch/x86/kvm/xen.h b/arch/x86/kvm/xen.h index a4d80cc21ee4..ccd6002f55bc 100644 --- a/arch/x86/kvm/xen.h +++ b/arch/x86/kvm/xen.h @@ -23,6 +23,8 @@ static inline struct kvm_vcpu *xen_vcpu_to_vcpu(struct kvm_vcpu_xen *xen_vcpu) } void kvm_xen_setup_pvclock_page(struct kvm_vcpu *vcpu); +void kvm_xen_setup_runstate_page(struct kvm_vcpu *vcpu); +void kvm_xen_runstate_set_preempted(struct kvm_vcpu *vcpu); int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data); int kvm_xen_hvm_get_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data); int kvm_xen_hypercall(struct kvm_vcpu *vcpu); @@ -70,7 +72,12 @@ struct compat_shared_info { uint32_t evtchn_mask[32]; struct pvclock_wall_clock wc; struct compat_arch_shared_info arch; - }; +struct compat_vcpu_runstate_info { + int state; + uint64_t state_entry_time; + uint64_t time[4]; +} __attribute__((packed)); + #endif /* __ARCH_X86_KVM_XEN_H__ */ diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 3ff3f72ac6b3..98b6cd747a01 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1600,6 +1600,7 @@ struct kvm_xen_hvm_attr { #define KVM_XEN_ATTR_TYPE_SHARED_INFO 0x1 #define KVM_XEN_ATTR_TYPE_VCPU_INFO 0x2 #define KVM_XEN_ATTR_TYPE_VCPU_TIME_INFO 0x3 +#define KVM_XEN_ATTR_TYPE_VCPU_RUNSTATE 0x4 /* Secure Encrypted Virtualization command */ enum sev_cmd_id { From patchwork Sun Dec 6 11:03:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 11953983 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 18426C433FE for ; Sun, 6 Dec 2020 11:05:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DFF3C2310B for ; Sun, 6 Dec 2020 11:05:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727430AbgLFLE7 (ORCPT ); Sun, 6 Dec 2020 06:04:59 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41916 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727258AbgLFLE5 (ORCPT ); Sun, 6 Dec 2020 06:04:57 -0500 Received: from casper.infradead.org (casper.infradead.org [IPv6:2001:8b0:10b:1236::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BAEB6C08E860 for ; Sun, 6 Dec 2020 03:03:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc: To:From:Reply-To:Content-ID:Content-Description; bh=gMA79Xn0ejz+QUrwMGp2wVSAh5p++VaHyFcySatTnOw=; b=aU23PiCWD8TZqfr79ATgDO5cj8 hV9o9/hDF5N3maJ8D7QeGo+dXxw6zyDeJZG994HfnHaa9koWSXbyhnpuJLvR6vpg1/859P5aFeQCR HuXWtq3PCiMKqXeMoS+qAat7jitk/eJ3NTuQIQpTZjj7SLGkhzp1/hWNMbkuDqODQSsJN+jCtIn4L pPc8fNHDrWSkps6Z33gAhyqKFHqUlE+ZpF1sATfGw6U0VgSDI01xp/ZB8rbqTFICOOYB4SQvuemw6 0XTQAgZcSXSv4wPGtBQh/l9JaQgXuf+jueXCDmRwh8uBSZUAZTN6uL0I64gNqy+5lQpMK0/BdDOUs AokTTiZQ==; Received: from i7.infradead.org ([2001:8b0:10b:1:21e:67ff:fecb:7a92]) by casper.infradead.org with esmtpsa (Exim 4.92.3 #3 (Red Hat Linux)) id 1klrpE-0006Ft-9X; Sun, 06 Dec 2020 11:03:40 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1klrpD-000jpq-SB; Sun, 06 Dec 2020 11:03:31 +0000 From: David Woodhouse To: kvm@vger.kernel.org Cc: Paolo Bonzini , Ankur Arora , Joao Martins , Boris Ostrovsky , Sean Christopherson , graf@amazon.com, iaslan@amazon.de Subject: [PATCH v2 15/16] KVM: x86: declare Xen HVM shared info capability and add test case Date: Sun, 6 Dec 2020 11:03:26 +0000 Message-Id: <20201206110327.175629-16-dwmw2@infradead.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201206110327.175629-1-dwmw2@infradead.org> References: <20201206110327.175629-1-dwmw2@infradead.org> MIME-Version: 1.0 Sender: David Woodhouse X-SRS-Rewrite: SMTP reverse-path rewritten from by casper.infradead.org. See http://www.infradead.org/rpr.html Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: David Woodhouse Instead of adding a plethora of new KVM_CAP_XEN_FOO capabilities, just add bits to the return value of KVM_CAP_XEN_HVM. Signed-off-by: David Woodhouse --- arch/x86/kvm/x86.c | 3 +- include/uapi/linux/kvm.h | 3 + tools/testing/selftests/kvm/Makefile | 1 + .../selftests/kvm/x86_64/xen_shinfo_test.c | 187 ++++++++++++++++++ 4 files changed, 193 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 9cbe8ee0de47..ad9eea8f4f26 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -3732,7 +3732,8 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) break; case KVM_CAP_XEN_HVM: r = KVM_XEN_HVM_CONFIG_HYPERCALL_MSR | - KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL; + KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL | + KVM_XEN_HVM_CONFIG_SHARED_INFO; break; case KVM_CAP_SYNC_REGS: r = KVM_SYNC_X86_VALID_FIELDS; diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 98b6cd747a01..1047364d1adf 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1145,6 +1145,7 @@ struct kvm_x86_mce { #ifdef KVM_CAP_XEN_HVM #define KVM_XEN_HVM_CONFIG_HYPERCALL_MSR (1 << 0) #define KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL (1 << 1) +#define KVM_XEN_HVM_CONFIG_SHARED_INFO (1 << 2) struct kvm_xen_hvm_config { __u32 flags; @@ -1577,6 +1578,7 @@ struct kvm_pv_cmd { /* Available with KVM_CAP_X86_MSR_FILTER */ #define KVM_X86_SET_MSR_FILTER _IOW(KVMIO, 0xc6, struct kvm_msr_filter) +/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO */ #define KVM_XEN_HVM_GET_ATTR _IOWR(KVMIO, 0xc7, struct kvm_xen_hvm_attr) #define KVM_XEN_HVM_SET_ATTR _IOW(KVMIO, 0xc8, struct kvm_xen_hvm_attr) @@ -1596,6 +1598,7 @@ struct kvm_xen_hvm_attr { } u; }; +/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO */ #define KVM_XEN_ATTR_TYPE_LONG_MODE 0x0 #define KVM_XEN_ATTR_TYPE_SHARED_INFO 0x1 #define KVM_XEN_ATTR_TYPE_VCPU_INFO 0x2 diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index d94abec627e6..3d1d93947bda 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -59,6 +59,7 @@ TEST_GEN_PROGS_x86_64 += x86_64/xss_msr_test TEST_GEN_PROGS_x86_64 += x86_64/debug_regs TEST_GEN_PROGS_x86_64 += x86_64/tsc_msrs_test TEST_GEN_PROGS_x86_64 += x86_64/user_msr_test +TEST_GEN_PROGS_x86_64 += x86_64/xen_shinfo_test TEST_GEN_PROGS_x86_64 += x86_64/xen_vmcall_test TEST_GEN_PROGS_x86_64 += demand_paging_test TEST_GEN_PROGS_x86_64 += dirty_log_test diff --git a/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c b/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c new file mode 100644 index 000000000000..911d3f1ed2e0 --- /dev/null +++ b/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c @@ -0,0 +1,187 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * svm_vmcall_test + * + * Copyright © 2020 Amazon.com, Inc. or its affiliates. + * + * Xen shared_info / pvclock testing + */ + +#include "test_util.h" +#include "kvm_util.h" +#include "processor.h" + +#include +#include + +#define VCPU_ID 5 + +#define SHINFO_REGION_GPA 0xc0000000ULL +#define SHINFO_REGION_SLOT 10 +#define PAGE_SIZE 4096 + +#define PVTIME_ADDR (SHINFO_REGION_GPA + PAGE_SIZE) +#define RUNSTATE_ADDR (SHINFO_REGION_GPA + PAGE_SIZE + 0x20) + +static struct kvm_vm *vm; + +#define XEN_HYPERCALL_MSR 0x40000000 + +struct pvclock_vcpu_time_info { + u32 version; + u32 pad0; + u64 tsc_timestamp; + u64 system_time; + u32 tsc_to_system_mul; + s8 tsc_shift; + u8 flags; + u8 pad[2]; +} __attribute__((__packed__)); /* 32 bytes */ + +struct pvclock_wall_clock { + u32 version; + u32 sec; + u32 nsec; +} __attribute__((__packed__)); + +struct vcpu_runstate_info { + uint32_t state; + uint64_t state_entry_time; + uint64_t time[4]; +}; + +static void guest_code(void) +{ + struct vcpu_runstate_info *rs = (void *)RUNSTATE_ADDR; + + /* Scribble on the runstate, just to make sure that... */ + rs->state = 0x5a; + + GUEST_SYNC(1); + + /* ... it is being set to RUNSTATE_running */ + GUEST_ASSERT(rs->state == 0); + GUEST_DONE(); +} + +static int cmp_timespec(struct timespec *a, struct timespec *b) +{ + if (a->tv_sec > b->tv_sec) + return 1; + else if (a->tv_sec < b->tv_sec) + return -1; + else if (a->tv_nsec > b->tv_nsec) + return 1; + else if (a->tv_nsec < b->tv_nsec) + return -1; + else + return 0; +} + +int main(int argc, char *argv[]) +{ + struct timespec min_ts, max_ts, vm_ts; + + if (!(kvm_check_cap(KVM_CAP_XEN_HVM) & + KVM_XEN_HVM_CONFIG_SHARED_INFO) ) { + print_skip("KVM_XEN_HVM_CONFIG_SHARED_INFO not available"); + exit(KSFT_SKIP); + } + + clock_gettime(CLOCK_REALTIME, &min_ts); + + vm = vm_create_default(VCPU_ID, 0, (void *) guest_code); + vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid()); + + /* Map a region for the shared_info page */ + vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, + SHINFO_REGION_GPA, SHINFO_REGION_SLOT, + 2 * getpagesize(), 0); + virt_map(vm, SHINFO_REGION_GPA, SHINFO_REGION_GPA, 2, 0); + + struct kvm_xen_hvm_attr lm = { + .type = KVM_XEN_ATTR_TYPE_LONG_MODE, + .u.long_mode = 1, + }; + vm_ioctl(vm, KVM_XEN_HVM_SET_ATTR, &lm); + + struct kvm_xen_hvm_attr ha = { + .type = KVM_XEN_ATTR_TYPE_SHARED_INFO, + .u.shared_info.gfn = SHINFO_REGION_GPA / PAGE_SIZE, + }; + vm_ioctl(vm, KVM_XEN_HVM_SET_ATTR, &ha); + + struct kvm_xen_hvm_attr pvclock = { + .type = KVM_XEN_ATTR_TYPE_VCPU_TIME_INFO, + .u.vcpu_attr.vcpu = VCPU_ID, + .u.vcpu_attr.gpa = PVTIME_ADDR, + }; + vm_ioctl(vm, KVM_XEN_HVM_SET_ATTR, &pvclock); + + struct kvm_xen_hvm_attr st = { + .type = KVM_XEN_ATTR_TYPE_VCPU_RUNSTATE, + .u.vcpu_attr.vcpu = VCPU_ID, + .u.vcpu_attr.gpa = RUNSTATE_ADDR, + }; + vm_ioctl(vm, KVM_XEN_HVM_SET_ATTR, &st); + + for (;;) { + volatile struct kvm_run *run = vcpu_state(vm, VCPU_ID); + struct ucall uc; + + vcpu_run(vm, VCPU_ID); + + TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, + "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n", + run->exit_reason, + exit_reason_str(run->exit_reason)); + + switch (get_ucall(vm, VCPU_ID, &uc)) { + case UCALL_ABORT: + TEST_FAIL("%s", (const char *)uc.args[0]); + /* NOT REACHED */ + case UCALL_SYNC: + break; + case UCALL_DONE: + goto done; + default: + TEST_FAIL("Unknown ucall 0x%lx.", uc.cmd); + } + } + + done: + clock_gettime(CLOCK_REALTIME, &max_ts); + + /* + * Just a *really* basic check that things are being put in the + * right place. The actual calculations are much the same for + * Xen as they are for the KVM variants, so no need to check. + */ + struct pvclock_wall_clock *wc; + struct pvclock_vcpu_time_info *ti, *ti2; + struct vcpu_runstate_info *rs; + + wc = addr_gva2hva(vm, SHINFO_REGION_GPA + 0xc00); + ti = addr_gva2hva(vm, SHINFO_REGION_GPA + 0x40 * VCPU_ID + 0x20); + ti2 = addr_gva2hva(vm, PVTIME_ADDR); + rs = addr_gva2hva(vm, RUNSTATE_ADDR); + + vm_ts.tv_sec = wc->sec; + vm_ts.tv_nsec = wc->nsec; + TEST_ASSERT(wc->version && !(wc->version & 1), + "Bad wallclock version %x", wc->version); + TEST_ASSERT(cmp_timespec(&min_ts, &vm_ts) <= 0, "VM time too old"); + TEST_ASSERT(cmp_timespec(&max_ts, &vm_ts) >= 0, "VM time too new"); + + TEST_ASSERT(ti->version && !(ti->version & 1), + "Bad time_info version %x", ti->version); + TEST_ASSERT(ti2->version && !(ti2->version & 1), + "Bad time_info version %x", ti->version); + + /* Check for RUNSTATE_blocked */ + TEST_ASSERT(rs->state == 2, "Not RUNSTATE_blocked"); + TEST_ASSERT(rs->time[0], "No RUNSTATE_running time"); + TEST_ASSERT(rs->time[2], "No RUNSTATE_blocked time"); + kvm_vm_free(vm); + return 0; +} From patchwork Sun Dec 6 11:03:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 11953985 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 403F5C197BF for ; Sun, 6 Dec 2020 11:05:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1E4D92310B for ; Sun, 6 Dec 2020 11:05:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727513AbgLFLFF (ORCPT ); Sun, 6 Dec 2020 06:05:05 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41906 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727240AbgLFLE4 (ORCPT ); Sun, 6 Dec 2020 06:04:56 -0500 Received: from casper.infradead.org (casper.infradead.org [IPv6:2001:8b0:10b:1236::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B918FC08E85F for ; Sun, 6 Dec 2020 03:03:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description; bh=8XxLdCU7A7Vak7lE8H6JiELJdPbYpt8d+6b7AeXzX+U=; b=fM5fnBCPRGYhacAjhJ9uKrdHO/ 8xhU+uWXDlL47zkhTjjCl2INZwMiXrSPFPcmx+9A8Cs0D9fBRNkEaOzKJ3jdT1Uxrbo1yx/8ipGwJ Bk3P0A29PhqOYCaTcavCr3ESJVNor05qIAlNyk/80XodMKNBkc2gtkni7sybU2jEwfD3TZtFIbGV+ Wyk7g3v+rOZhofnuoFnnyfBzo/VKoPB6Deq2K7ozDCuy+HmXOxnYjiL6SvXHz3GtEQsxVkULfocKQ hCBixrLeOTDI77b+tm6G5dxsxYbUc122fAX8JCP7xjwskpHc1bVglhMG8mkDq4A64MXRMFzWZnakZ /wsjQHig==; Received: from i7.infradead.org ([2001:8b0:10b:1:21e:67ff:fecb:7a92]) by casper.infradead.org with esmtpsa (Exim 4.92.3 #3 (Red Hat Linux)) id 1klrpE-0006Fu-9w; Sun, 06 Dec 2020 11:03:37 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1klrpD-000jpt-St; Sun, 06 Dec 2020 11:03:31 +0000 From: David Woodhouse To: kvm@vger.kernel.org Cc: Paolo Bonzini , Ankur Arora , Joao Martins , Boris Ostrovsky , Sean Christopherson , graf@amazon.com, iaslan@amazon.de Subject: [PATCH v2 16/16] KVM: Add documentation for Xen hypercall and shared_info updates Date: Sun, 6 Dec 2020 11:03:27 +0000 Message-Id: <20201206110327.175629-17-dwmw2@infradead.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201206110327.175629-1-dwmw2@infradead.org> References: <20201206110327.175629-1-dwmw2@infradead.org> MIME-Version: 1.0 Sender: David Woodhouse X-SRS-Rewrite: SMTP reverse-path rewritten from by casper.infradead.org. See http://www.infradead.org/rpr.html Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: David Woodhouse Signed-off-by: David Woodhouse --- Documentation/virt/kvm/api.rst | 119 +++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst index e00a66d72372..d98c2ff90880 100644 --- a/Documentation/virt/kvm/api.rst +++ b/Documentation/virt/kvm/api.rst @@ -944,6 +944,13 @@ memory. __u8 pad2[30]; }; +If the KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL flag is returned from the +KVM_CAP_XEN_HVM check, it may be set in the flags field of this ioctl. +This requests KVM to generate the contents of the hypercall page +automatically, and also to intercept hypercalls with KVM_EXIT_XEN. +In this case, all of the blob size and address fields must be zero. + +No other flags are currently valid. 4.29 KVM_GET_CLOCK ------------------ @@ -4807,6 +4814,67 @@ into user space. If a vCPU is in running state while this ioctl is invoked, the vCPU may experience inconsistent filtering behavior on MSR accesses. +4.127 KVM_XEN_HVM_SET_ATTR +-------------------------- + +:Capability: KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO +:Architectures: x86 +:Type: vm ioctl +:Parameters: struct kvm_xen_hvm_attr +:Returns: 0 on success, < 0 on error + +:: + + struct kvm_xen_hvm_attr { + __u16 type; + + union { + __u8 long_mode; + struct { + __u64 gfn; + } shared_info; + struct { + __u32 vcpu; + __u64 gpa; + } vcpu_attr; + __u64 pad[4]; + } u; + }; + +type values: + +KVM_XEN_ATTR_TYPE_LONG_MODE + Sets the ABI mode of the VM to 32-bit or 64-bit (long mode). This + determines the layout of the shared info pages exposed to the VM. + +KVM_XEN_ATTR_TYPE_SHARED_INFO + Sets the guest physical frame number at which the Xen "shared info" + page resides. It is the default location for the vcpu_info for the + first 32 vCPUs, and contains other VM-wide data structures shared + between the VM and the host. + +KVM_XEN_ATTR_TYPE_VCPU_INFO + Sets the guest physical address of the vcpu_info for a given vCPU. + +KVM_XEN_ATTR_TYPE_VCPU_TIME_INFO + Sets the guest physical address of an additional pvclock structure + for a given vCPU. This is typically used for guest vsyscall support. + +KVM_XEN_ATTR_TYPE_VCPU_RUNSTATE + Sets the guest physical address of the vcpu_runstate_info for a given + vCPU. This is how a Xen guest tracks CPU state such as steal time. + +4.128 KVM_XEN_HVM_GET_ATTR +-------------------------- + +:Capability: KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO +:Architectures: x86 +:Type: vm ioctl +:Parameters: struct kvm_xen_hvm_attr +:Returns: 0 on success, < 0 on error + +Allows Xen VM attributes to be read. For the structure and types, +see KVM_XEN_HVM_SET_ATTR above. 5. The kvm_run structure ======================== @@ -5303,6 +5371,34 @@ wants to write. Once finished processing the event, user space must continue vCPU execution. If the MSR write was unsuccessful, user space also sets the "error" field to "1". +:: + + + struct kvm_xen_exit { + #define KVM_EXIT_XEN_HCALL 1 + __u32 type; + union { + struct { + __u32 longmode; + __u32 cpl; + __u64 input; + __u64 result; + __u64 params[6]; + } hcall; + } u; + }; + /* KVM_EXIT_XEN */ + struct kvm_hyperv_exit xen; + +Indicates that the VCPU exits into userspace to process some tasks +related to Xen emulation. + +Valid values for 'type' are: + + - KVM_EXIT_XEN_HCALL -- synchronously notify user-space about Xen hypercall. + Userspace is expected to place the hypercall result into the appropriate + field before invoking KVM_RUN again. + :: /* Fix the size of the union. */ @@ -6390,3 +6486,26 @@ When enabled, KVM will disable paravirtual features provided to the guest according to the bits in the KVM_CPUID_FEATURES CPUID leaf (0x40000001). Otherwise, a guest may use the paravirtual features regardless of what has actually been exposed through the CPUID leaf. + +8.29 KVM_CAP_XEN_HVM +-------------------- + +:Architectures: x86 + +This capability indicates the features that Xen supports for hosting Xen +PVHVM guests. Valid flags are:: + + #define KVM_XEN_HVM_CONFIG_HYPERCALL_MSR (1 << 0) + #define KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL (1 << 1) + #define KVM_XEN_HVM_CONFIG_SHARED_INFO (1 << 2) + +The KVM_XEN_HVM_CONFIG_HYPERCALL_MSR flag indicates that the KVM_XEN_HVM_CONFIG +ioctl is available, for the guest to set its hypercall page. + +If KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL is also set, the same flag may also be +provided in the flags to KVM_XEN_HVM_CONFIG, without providing hypercall page +contents, to request that KVM generate hypercall page content automatically +and also enable interception of guest hypercalls with KVM_EXIT_XEN. + +The KVM_XEN_HVM_CONFIG_SHARED_INFO flag indicates the availability of the +KVM_XEN_HVM_SET_ATTR and KVM_XEN_HVM_GET_ATTR ioctls.