From patchwork Wed Jan 6 00:22:59 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 12000615 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 22A1CC433E0 for ; Wed, 6 Jan 2021 00:25:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D72AC22D74 for ; Wed, 6 Jan 2021 00:25:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726567AbhAFAZi (ORCPT ); Tue, 5 Jan 2021 19:25:38 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37522 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726328AbhAFAZi (ORCPT ); Tue, 5 Jan 2021 19:25:38 -0500 Received: from casper.infradead.org (casper.infradead.org [IPv6:2001:8b0:10b:1236::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3D539C06179E for ; Tue, 5 Jan 2021 16:24:58 -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=rNJwjPQ7Qc7Ainnec/slAm+3+N/HJjvYoiheRUN6QLg=; b=adf91Pk9fRFB2a8juCO2Yx47kB Z5D1EuzrSSaqC+lmkjGkMkYSlZdX9cYOo0PdruMpZq9FAj94HczGTZKX9eK6RxX5VdoV09sJDrWqH u6N5z4P73xA90ORtJklkVgZEuV1kqPeVGGUY/gYS34c45sMPU/aD8FmUfP34lWxdJz7XHkgoaz/JM 9kmJhOTdxZS9FStc9Sr0lEEi0f5TsedLW5zkYLvUCoMlz3PwzsV8EmwdjjwwhRYdxqpd6NY/qrB/r dn9w5P1vbS4TjCJ1WxgoCfaPyX2f0CveJp9PQ0YZIEQXTvGAQe+BD65QbP7bUz/fuFhI97eJP8tYK vZqSTvzA==; Received: from i7.infradead.org ([2001:8b0:10b:1:21e:67ff:fecb:7a92]) by casper.infradead.org with esmtpsa (Exim 4.94 #2 (Red Hat Linux)) id 1kwwbh-001pA4-LS; Wed, 06 Jan 2021 00:23:36 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1kwwbh-001Nin-9W; Wed, 06 Jan 2021 00:23:21 +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, pdurrant@amazon.com, aagch@amazon.com, fandree@amazon.com, hch@infradead.org Subject: [PATCH v4 01/16] KVM: x86/xen: fix Xen hypercall page msr handling Date: Wed, 6 Jan 2021 00:22:59 +0000 Message-Id: <20210106002314.328380-2-dwmw2@infradead.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210106002314.328380-1-dwmw2@infradead.org> References: <20210106002314.328380-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 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 3f7c1fc7a3ce..f219d50b3700 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -3007,6 +3007,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: @@ -3294,8 +3297,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 Wed Jan 6 00:23:00 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 12000611 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 670BAC433DB for ; Wed, 6 Jan 2021 00:25:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1CD5622D74 for ; Wed, 6 Jan 2021 00:25:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726652AbhAFAZQ (ORCPT ); Tue, 5 Jan 2021 19:25:16 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37458 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726352AbhAFAZP (ORCPT ); Tue, 5 Jan 2021 19:25:15 -0500 Received: from casper.infradead.org (casper.infradead.org [IPv6:2001:8b0:10b:1236::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 24CECC061574 for ; Tue, 5 Jan 2021 16:24:32 -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=IwZiUQaBeuJ3EZrnRQhMaXpL8l3rCtuEZiORMI9A9k4=; b=fEXr+QqGF0vDaN/UslEUuBExdS qBNjIoc6RU9jKMwFFxuCXw94yP2Q+VxKCNJyhPDYoTPvzlaE6cFSwV47cD8qh8OvAbFEfW4LR2TwI UxNkVnSNGro0TouAvI2jQyCMpUG3CXkpu0R7IRvXxffx63zdsowuTnu2KMCUua5ZXNa691SYWRg9B zu+QEcvBmIJZx1E8vioRkpNMKmqzY9QcBuG+HTmHJiFlpgeSgYaHX4dWjN+J/IsPITh8dJV2xw02C yHXizoQrxXBC0VD995LEydZPcaNWhKnbcxlfaMySh9gWZZdachkothvctuNqBIMdsdZpVJ4mw+czg knCiQZwQ==; Received: from i7.infradead.org ([2001:8b0:10b:1:21e:67ff:fecb:7a92]) by casper.infradead.org with esmtpsa (Exim 4.94 #2 (Red Hat Linux)) id 1kwwbh-001pA5-MW; Wed, 06 Jan 2021 00:23:36 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1kwwbh-001Niq-AB; Wed, 06 Jan 2021 00:23:21 +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, pdurrant@amazon.com, aagch@amazon.com, fandree@amazon.com, hch@infradead.org Subject: [PATCH v4 02/16] KVM: x86/xen: intercept xen hypercalls if enabled Date: Wed, 6 Jan 2021 00:23:00 +0000 Message-Id: <20210106002314.328380-3-dwmw2@infradead.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210106002314.328380-1-dwmw2@infradead.org> References: <20210106002314.328380-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 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 --- 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 | 2 + tools/testing/selftests/kvm/lib/kvm_util.c | 1 + .../selftests/kvm/x86_64/xen_vmcall_test.c | 123 +++++++++++++++ 10 files changed, 368 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 3ab7b46087b7..2ceda5aecac5 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 @@ -718,6 +723,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 4bd14ab01323..a50041235530 100644 --- a/arch/x86/kvm/Makefile +++ b/arch/x86/kvm/Makefile @@ -14,7 +14,7 @@ kvm-y += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o \ $(KVM)/dirty_ring.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 2de30c20bc26..4527d0fd2d99 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 f219d50b3700..e391f4dfe457 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 @@ -2848,32 +2849,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; @@ -3008,7 +2983,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: @@ -3730,7 +3705,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: @@ -3770,6 +3744,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; @@ -5626,7 +5604,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; @@ -8089,6 +8075,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 886802b8ffba..32b59efc2c30 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 @@ -251,6 +265,7 @@ struct kvm_hyperv_exit { #define KVM_EXIT_X86_RDMSR 29 #define KVM_EXIT_X86_WRMSR 30 #define KVM_EXIT_DIRTY_RING_FULL 31 +#define KVM_EXIT_XEN 32 /* For KVM_EXIT_INTERNAL_ERROR */ /* Emulate instruction failed. */ @@ -427,6 +442,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]; }; @@ -1129,6 +1146,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 c7ca4faba272..140b628f4a5c 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -59,6 +59,8 @@ TEST_GEN_PROGS_x86_64 += x86_64/vmx_tsc_adjust_test 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 88ef7067f1e6..eae37d3141b2 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -1808,6 +1808,7 @@ static struct exit_reason { {KVM_EXIT_DIRTY_RING_FULL, "DIRTY_RING_FULL"}, {KVM_EXIT_X86_RDMSR, "RDMSR"}, {KVM_EXIT_X86_WRMSR, "WRMSR"}, + {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 Wed Jan 6 00:23:01 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 12000607 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 3FC60C433E0 for ; Wed, 6 Jan 2021 00:24:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1423722D74 for ; Wed, 6 Jan 2021 00:24:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726533AbhAFAYt (ORCPT ); Tue, 5 Jan 2021 19:24:49 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37380 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725789AbhAFAYs (ORCPT ); Tue, 5 Jan 2021 19:24:48 -0500 Received: from merlin.infradead.org (merlin.infradead.org [IPv6:2001:8b0:10b:1231::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 13317C0617A4 for ; Tue, 5 Jan 2021 16:23:25 -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=DbomEl/wA7I8yvYafwa6fpPKm5fC2uvDH4uSum5rBiw=; b=TI4fAvWvepLibLrfR2nU4/Arq9 l9awfqJQCHCL2p6uMEzt6axYTrKzSmkZ/oNZ39tKgD9sB4O0rAxWbUG4VVwD+nlOca8IMh34tMIuk sKH9MPNH3wdp8VMllJOLOhC0s4N6MPser99L5CZxEqUOjP+UTsiVqiuaRZkFaKF3kcJwF/5h3PR9Q cOTkko05IqoRqTEhl/8uX1ZirbglN6BG+Hm25MoDY5PaVcKu1YV4SufK0MO/sheGn05MboN4uFtHh 2BJYHx74pkXNxtsB8OqUXbdd/eGwVJ5kAPBWph7X7RRW7jf4N+pHmqGXIDs7FIOg8X8asJE3kgr+8 OF68SvQw==; 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 1kwwbi-0004Zt-DN; Wed, 06 Jan 2021 00:23:22 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1kwwbh-001Nit-BF; Wed, 06 Jan 2021 00:23:21 +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, pdurrant@amazon.com, aagch@amazon.com, fandree@amazon.com, hch@infradead.org Subject: [PATCH v4 03/16] KVM: x86/xen: Fix coexistence of Xen and Hyper-V hypercalls Date: Wed, 6 Jan 2021 00:23:01 +0000 Message-Id: <20210106002314.328380-4-dwmw2@infradead.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210106002314.328380-1-dwmw2@infradead.org> References: <20210106002314.328380-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 922c69dcca4d..5f4487bb7849 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 Wed Jan 6 00:23:02 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 12000595 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 72F35C4332D for ; Wed, 6 Jan 2021 00:24:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 560E0230FC for ; Wed, 6 Jan 2021 00:24:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726472AbhAFAYK (ORCPT ); Tue, 5 Jan 2021 19:24:10 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37276 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726244AbhAFAYK (ORCPT ); Tue, 5 Jan 2021 19:24:10 -0500 Received: from merlin.infradead.org (merlin.infradead.org [IPv6:2001:8b0:10b:1231::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EBB02C06179F for ; Tue, 5 Jan 2021 16:23:25 -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=Bl/X+U+GWKGXkOizMADC+1uhUYiVzybTnXj88JzYPL0=; b=t950RH1JeIhvBMTxymgLPKfBZg aTd8X1FxTkTt3WZlf3/yoEWJi09qa8pqsDuqru0yCLg4dQDFHge4uFTWpsg+S15r/YNJDSQ1x0xnW ozzR3yGP5V6iIOfO+l5udBQ6hffBhteAxSdGuwn7vEo9giEBSS48ldq/K70uC4uwB3/4C1ImdhMX0 O5kqZjKuiRPZJvan+Lxb05GLx8OdIcgCH0KTNuirsw1FTgAxTrZLxTVW4qZi7P0PL8hc6+4tkPA+Q DaCD55dHwJMSXghURp9hKjFtkOoTeIZ8X85uRfDCy2Jv4huRqbjg1wmW3D/L3aHS+MdcqIEEg7T9E o8ysJXsg==; 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 1kwwbi-0004Zu-Dy; Wed, 06 Jan 2021 00:23:22 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1kwwbh-001Niw-By; Wed, 06 Jan 2021 00:23:21 +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, pdurrant@amazon.com, aagch@amazon.com, fandree@amazon.com, hch@infradead.org Subject: [PATCH v4 04/16] KVM: x86/xen: add KVM_XEN_HVM_SET_ATTR/KVM_XEN_HVM_GET_ATTR Date: Wed, 6 Jan 2021 00:23:02 +0000 Message-Id: <20210106002314.328380-5-dwmw2@infradead.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210106002314.328380-1-dwmw2@infradead.org> References: <20210106002314.328380-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 | 2 ++ include/linux/kvm_host.h | 30 +++++++++++++++--------------- include/uapi/linux/kvm.h | 11 +++++++++++ 5 files changed, 72 insertions(+), 15 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index e391f4dfe457..600d2b64928e 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -5618,6 +5618,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..d06b5afcc1f2 100644 --- a/arch/x86/kvm/xen.h +++ b/arch/x86/kvm/xen.h @@ -9,6 +9,8 @@ #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); diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index f3b1013fb22c..398ed0c99606 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 #include @@ -226,21 +241,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 32b59efc2c30..7b5fed0cb2ad 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1583,6 +1583,17 @@ struct kvm_pv_cmd { /* Available with KVM_CAP_DIRTY_LOG_RING */ #define KVM_RESET_DIRTY_RINGS _IO(KVMIO, 0xc7) +#define KVM_XEN_HVM_GET_ATTR _IOWR(KVMIO, 0xc8, struct kvm_xen_hvm_attr) +#define KVM_XEN_HVM_SET_ATTR _IOW(KVMIO, 0xc9, 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 Wed Jan 6 00:23:03 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 12000585 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 14105C433E6 for ; Wed, 6 Jan 2021 00:24:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E12E322EBF for ; Wed, 6 Jan 2021 00:24:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726391AbhAFAYI (ORCPT ); Tue, 5 Jan 2021 19:24:08 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37262 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726231AbhAFAYG (ORCPT ); Tue, 5 Jan 2021 19:24:06 -0500 Received: from merlin.infradead.org (merlin.infradead.org [IPv6:2001:8b0:10b:1231::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DC9EDC06179A for ; Tue, 5 Jan 2021 16:23:25 -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=xO7F7AGN1IW8y6QIXNmMMNfazzRaB+oFtCZEjEKJx9U=; b=oaa6WS9xY7eNxpi7XPj+5MltqB bzlmerVAKCbFievAW7qJcdhsWvCrgwpTnKz1AkEWU4yR1h5P+/ariuXi6WF5F3oLylliAgCmHfQuh Vm/U4IuYisrk3wIuEGwjGb+P4X02LNamHhze2UXR26wfzH2nIfyyqPyU04gJ4UFKhcU1DYNr8CPDl RSrgyK7wDNbGlkAKmCPqNz4jnh2giCdYlw7srReIUk26VbI4+g147AFfmaBMwfH4QMxKa06chPzmS rb/ptDY2TZMyRoSzSfp9qCC/fTLV36Dq1TPWXwu20tiNl1bZmlQmXoXnlksUTKZLNZh59St0l9+Aq FE40WxaQ==; 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 1kwwbi-0004Zv-EZ; Wed, 06 Jan 2021 00:23:22 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1kwwbh-001Niz-CZ; Wed, 06 Jan 2021 00:23:21 +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, pdurrant@amazon.com, aagch@amazon.com, fandree@amazon.com, hch@infradead.org Subject: [PATCH v4 05/16] KVM: x86/xen: latch long_mode when hypercall page is set up Date: Wed, 6 Jan 2021 00:23:03 +0000 Message-Id: <20210106002314.328380-6-dwmw2@infradead.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210106002314.328380-1-dwmw2@infradead.org> References: <20210106002314.328380-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 2ceda5aecac5..4fcb27a9fe36 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -894,6 +894,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 */ @@ -973,6 +978,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 7b5fed0cb2ad..b7cf887c8e4d 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1590,10 +1590,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 Wed Jan 6 00:23:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 12000605 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 0E662C43381 for ; Wed, 6 Jan 2021 00:24:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DE6CF22D74 for ; Wed, 6 Jan 2021 00:24:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726564AbhAFAYt (ORCPT ); Tue, 5 Jan 2021 19:24:49 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37382 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726224AbhAFAYs (ORCPT ); Tue, 5 Jan 2021 19:24:48 -0500 Received: from merlin.infradead.org (merlin.infradead.org [IPv6:2001:8b0:10b:1231::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1772CC0617A5 for ; Tue, 5 Jan 2021 16:23:25 -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=RS+RfrioTQjzStJdTZKjWLCu7R7I1go12LkxDEA+lqY=; b=QouhxfqyxbOGtokxX8rXvp1QD5 h0Jq1b0CKetV/rj98djkgp7ql96thRyiAqlTRNCU4j8ksPLN8pHFtXrs/Idtpib+Z/CWtxDb+hCP7 hyZrR0saGDq8SUCEmws8l+UQsJzUppTww+1GGfzcG2WibvcFm88hsxAHaK+07kJVH08xhlaTIRQ83 GK+V/FsKevGgVOUrbdXrAT8WxtnzSIiCrmkOCSNaazpPO6V4iz5ktCpeSfTsLRfyB8CgF5DDrz/sj 4Ory6qv0QLNyW5NDgo8rnsqDKwG8ammOuOgQOTBeQFUJe5r1xsBPftjcghKtXvLY1OqebJ5D59HR5 lAbjkGnQ==; 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 1kwwbi-0004Zw-Eq; Wed, 06 Jan 2021 00:23:22 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1kwwbh-001Nj2-D7; Wed, 06 Jan 2021 00:23:21 +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, pdurrant@amazon.com, aagch@amazon.com, fandree@amazon.com, hch@infradead.org Subject: [PATCH v4 06/16] KVM: x86/xen: add definitions of compat_shared_info, compat_vcpu_info Date: Wed, 6 Jan 2021 00:23:04 +0000 Message-Id: <20210106002314.328380-7-dwmw2@infradead.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210106002314.328380-1-dwmw2@infradead.org> References: <20210106002314.328380-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 | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/arch/x86/kvm/xen.h b/arch/x86/kvm/xen.h index d06b5afcc1f2..317c1325dade 100644 --- a/arch/x86/kvm/xen.h +++ b/arch/x86/kvm/xen.h @@ -20,4 +20,40 @@ 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 Wed Jan 6 00:23:05 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 12000587 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 5DAC8C433DB for ; Wed, 6 Jan 2021 00:24:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3F3CE230FA for ; Wed, 6 Jan 2021 00:24:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726502AbhAFAYK (ORCPT ); Tue, 5 Jan 2021 19:24:10 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37274 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726224AbhAFAYK (ORCPT ); Tue, 5 Jan 2021 19:24:10 -0500 Received: from merlin.infradead.org (merlin.infradead.org [IPv6:2001:8b0:10b:1231::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E3CA2C06179E for ; Tue, 5 Jan 2021 16:23:25 -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=oJMNalbsZRJeGEAQYvoJXiXmTW0m8wLQLN36OOi7rGU=; b=QASSiJjtskOXLiQ3gaIWv+qE/z 7UkSiw/mr8Xgho0rAs0V8ul8KbiEcyBRBw5EqI3LFCy/bwNpijQ7RvDk785WCInjSwEL49clfIumt 0brhR+/KkUPprBii0CGBsCuN11ZHDeDkQ2ETwu4c1myYOEVGsE4ErK2W/4kIW2WHl4c1QSm0ZH81Q YTRsxoWgyBd0yX/WgBZsF5QXiW0orVSjAmb2/sv9T7DJYJXA9xuJtYILwv2+iwznfkyeUtIkbCFi+ dtaEC1akz6bUaGKTd5qk/QJ17n7b3QSYGvjYyAFyaii0wrps4o9tSZ5A7ljPfdKY2OUz+pqmST7J9 na8quHag==; 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 1kwwbi-0004Zx-FR; Wed, 06 Jan 2021 00:23:22 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1kwwbh-001Nj5-Dc; Wed, 06 Jan 2021 00:23:21 +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, pdurrant@amazon.com, aagch@amazon.com, fandree@amazon.com, hch@infradead.org Subject: [PATCH v4 07/16] KVM: x86/xen: register shared_info page Date: Wed, 6 Jan 2021 00:23:05 +0000 Message-Id: <20210106002314.328380-8-dwmw2@infradead.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210106002314.328380-1-dwmw2@infradead.org> References: <20210106002314.328380-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 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/xen.c | 27 +++++++++++++++++++++++++++ include/uapi/linux/kvm.h | 4 ++++ 3 files changed, 33 insertions(+) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 4fcb27a9fe36..e48dac4f0359 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -897,6 +897,8 @@ struct msr_bitmap_range { /* Xen emulation context */ struct kvm_xen { bool long_mode; + bool shinfo_set; + struct gfn_to_hva_cache shinfo_cache; }; enum kvm_irqchip_mode { diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c index 52cb9e465542..9dd9c42842b8 100644 --- a/arch/x86/kvm/xen.c +++ b/arch/x86/kvm/xen.c @@ -13,9 +13,23 @@ #include #include +#include #include "trace.h" +static int kvm_xen_shared_info_init(struct kvm *kvm, gfn_t gfn) +{ + int ret; + + ret = kvm_gfn_to_hva_cache_init(kvm, &kvm->arch.xen.shinfo_cache, + gfn_to_gpa(gfn), PAGE_SIZE); + if (ret) + return ret; + + kvm->arch.xen.shinfo_set = true; + return 0; +} + int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) { int r = -ENOENT; @@ -28,6 +42,11 @@ 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: + r = kvm_xen_shared_info_init(kvm, data->u.shared_info.gfn); + break; + default: break; } @@ -44,6 +63,14 @@ 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_set) { + data->u.shared_info.gfn = gpa_to_gfn(kvm->arch.xen.shinfo_cache.gpa); + r = 0; + } + break; + default: break; } diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index b7cf887c8e4d..a47097b90fe8 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1591,11 +1591,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 Wed Jan 6 00:23:06 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 12000597 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 524A6C433DB for ; Wed, 6 Jan 2021 00:24:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1BE8F22D74 for ; Wed, 6 Jan 2021 00:24:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726549AbhAFAYt (ORCPT ); Tue, 5 Jan 2021 19:24:49 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37384 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726300AbhAFAYs (ORCPT ); Tue, 5 Jan 2021 19:24:48 -0500 Received: from merlin.infradead.org (merlin.infradead.org [IPv6:2001:8b0:10b:1231::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 197C2C0617A6 for ; Tue, 5 Jan 2021 16:23:25 -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=3ElwfAXENPX7CyKGBaZk7F240zhQf8i1c0BS1eDVtMU=; b=HdqqrYVjJNj48arYOqRQK3rkrh vJVAC+zOuPxNMMUqvwzWMPoI+fogpyskTSJWFIdcYvsvVFTnK1SlzqMPEzcSfJx5Z6tAiARE9tjY1 nxARbiBzGw+hYGH2g1TtjzODGf815OowazqVZ7A0sMyKy4UzsOTzD0CC+9OGeQkK33zSqPTwiWQ5X JEeqynUJjleYnSAQyGgEkzyUaXQG7U5wS3XN2yvj5wBhVngdqRiND5T0fDa7kmKurfibEPH5cP00n iuzs374XJchwK4pfsHJUcs3GD4oUVQ/PJR3EWbcyAp7uR+PZ8Deya/XP1boC0XKPmFh2nC+q3aGMK SQIFtI/w==; 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 1kwwbi-0004Zy-Fu; Wed, 06 Jan 2021 00:23:22 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1kwwbh-001Nj8-E8; Wed, 06 Jan 2021 00:23:21 +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, pdurrant@amazon.com, aagch@amazon.com, fandree@amazon.com, hch@infradead.org Subject: [PATCH v4 08/16] xen: add wc_sec_hi to struct shared_info Date: Wed, 6 Jan 2021 00:23:06 +0000 Message-Id: <20210106002314.328380-9-dwmw2@infradead.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210106002314.328380-1-dwmw2@infradead.org> References: <20210106002314.328380-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 Wed Jan 6 00:23:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 12000593 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 B1675C4332B for ; Wed, 6 Jan 2021 00:24:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 700DD230F9 for ; Wed, 6 Jan 2021 00:24:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726325AbhAFAYI (ORCPT ); Tue, 5 Jan 2021 19:24:08 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37260 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725766AbhAFAYG (ORCPT ); Tue, 5 Jan 2021 19:24:06 -0500 Received: from merlin.infradead.org (merlin.infradead.org [IPv6:2001:8b0:10b:1231::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D5204C061798 for ; Tue, 5 Jan 2021 16:23:25 -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=BtiDty0+5LMtN1T+tryKXDCc1saC6N6/ZQn2ExURKGM=; b=osS6OuYdOl82jm7EeKbP4H/PHN E/uQmhU1QGmBV3J1S474FhRQe9Cnj1i6gs5aKUYRW/quA1ceYUaiB/70QR8RqEXruqwDpfUNI/6AB hRm6vclM0D+odqujyjjkPWjpdm7ujrL/XoJ1gf/397TnWAtRo+BprsKlXsN5yumOISAXW26z5VZ4D yqF+Fg3Gn6UGegdx1PQk4UonloTrDnEbNN5n+LUTjbtoOfmlALIwNlWP2AbbWzeWoO6IUKyH3XzeU 1M2qdaP1+V+A8R4p9xWnNWsaT6PNTZfNu+TOT3nr8jA5mlptlbYbPk/i8xUlqbEsI//NRzNv/I3xc siX5bbdA==; 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 1kwwbi-0004Zz-Gg; Wed, 06 Jan 2021 00:23:22 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1kwwbh-001NjB-Ee; Wed, 06 Jan 2021 00:23:21 +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, pdurrant@amazon.com, aagch@amazon.com, fandree@amazon.com, hch@infradead.org Subject: [PATCH v4 09/16] KVM: x86/xen: update wallclock region Date: Wed, 6 Jan 2021 00:23:07 +0000 Message-Id: <20210106002314.328380-10-dwmw2@infradead.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210106002314.328380-1-dwmw2@infradead.org> References: <20210106002314.328380-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 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 | 28 +++++++++++++++++++++++++++- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 600d2b64928e..761114f19489 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1927,15 +1927,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; @@ -1964,6 +1963,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)); } @@ -3121,13 +3126,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 c5ee0f5ce0f1..8982a7bf2041 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -247,6 +247,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 9dd9c42842b8..e5117a611737 100644 --- a/arch/x86/kvm/xen.c +++ b/arch/x86/kvm/xen.c @@ -19,14 +19,40 @@ 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_gfn_to_hva_cache_init(kvm, &kvm->arch.xen.shinfo_cache, - gfn_to_gpa(gfn), PAGE_SIZE); + gpa, PAGE_SIZE); if (ret) return ret; kvm->arch.xen.shinfo_set = true; + + /* Paranoia checks on the 32-bit struct layout */ + 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_X86_64 + /* Paranoia checks on the 64-bit struct layout */ + 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 Wed Jan 6 00:23:08 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 12000601 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 40C2AC433E0 for ; Wed, 6 Jan 2021 00:24:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 14F7F22D74 for ; Wed, 6 Jan 2021 00:24:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726625AbhAFAYu (ORCPT ); Tue, 5 Jan 2021 19:24:50 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37376 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725890AbhAFAYs (ORCPT ); Tue, 5 Jan 2021 19:24:48 -0500 Received: from merlin.infradead.org (merlin.infradead.org [IPv6:2001:8b0:10b:1231::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 056A2C0617A2 for ; Tue, 5 Jan 2021 16:23:25 -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=hmubuuClET0F4ojWQbkk8GdGWezTNc243Ga5Jo2A21k=; b=citU/qYa6FSgZnaOK5wJk79wHT rYWdLQrkd1aE7kQ2+CmPTgwEjcRFi4Peexqf7RpISXXttJ0d0qiOSu1OzzkKTLqw1fQdWCSSy6/0Y vGxlxhE8CQ4c/WySh1hWN+gdkIKuSIb6eKdvCtgFWWUCLzHCCbrkhb1XKHzGRzh1mzpe7V8InKIeP ybaVbEPp08OZWynZEnolgET82u2S5wgyCF/7q66vJf0hRkO9ncXcjOIkJ1qsDfxHLVUdi7nBP5d+m S8Ak8M7HTK00VHYTjc+ZPM4/q3ndkfX8nAVyAUvjHfAQoNdyVS4NayRF8mBQjsuu0yIFHoc2O8gAM 9tLpr2tw==; 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 1kwwbi-0004a0-HN; Wed, 06 Jan 2021 00:23:22 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1kwwbh-001NjE-FE; Wed, 06 Jan 2021 00:23:21 +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, pdurrant@amazon.com, aagch@amazon.com, fandree@amazon.com, hch@infradead.org Subject: [PATCH v4 10/16] KVM: x86/xen: register vcpu info Date: Wed, 6 Jan 2021 00:23:08 +0000 Message-Id: <20210106002314.328380-11-dwmw2@infradead.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210106002314.328380-1-dwmw2@infradead.org> References: <20210106002314.328380-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/xen.c | 30 ++++++++++++++++++++++++++++++ include/uapi/linux/kvm.h | 5 +++++ 3 files changed, 37 insertions(+) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index e48dac4f0359..eabd0bf0035f 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; + bool vcpu_info_set; + struct gfn_to_hva_cache vcpu_info_cache; }; struct kvm_vcpu_arch { diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c index e5117a611737..4bc72e0b9928 100644 --- a/arch/x86/kvm/xen.c +++ b/arch/x86/kvm/xen.c @@ -58,6 +58,7 @@ static int kvm_xen_shared_info_init(struct kvm *kvm, gfn_t gfn) int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) { + struct kvm_vcpu *v; int r = -ENOENT; switch (data->type) { @@ -73,6 +74,23 @@ int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) r = kvm_xen_shared_info_init(kvm, data->u.shared_info.gfn); break; + case KVM_XEN_ATTR_TYPE_VCPU_INFO: + v = kvm_get_vcpu_by_id(kvm, data->u.vcpu_attr.vcpu_id); + if (!v) + return -EINVAL; + + /* No compat necessary here. */ + BUILD_BUG_ON(sizeof(struct vcpu_info) != + sizeof(struct compat_vcpu_info)); + r = kvm_gfn_to_hva_cache_init(kvm, &v->arch.xen.vcpu_info_cache, + data->u.vcpu_attr.gpa, + sizeof(struct vcpu_info)); + if (r) + return r; + + v->arch.xen.vcpu_info_set = true; + break; + default: break; } @@ -83,6 +101,7 @@ 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 r = -ENOENT; + struct kvm_vcpu *v; switch (data->type) { case KVM_XEN_ATTR_TYPE_LONG_MODE: @@ -97,6 +116,17 @@ int kvm_xen_hvm_get_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) } break; + case KVM_XEN_ATTR_TYPE_VCPU_INFO: + v = kvm_get_vcpu_by_id(kvm, data->u.vcpu_attr.vcpu_id); + if (!v) + return -EINVAL; + + if (v->arch.xen.vcpu_info_set) { + data->u.vcpu_attr.gpa = v->arch.xen.vcpu_info_cache.gpa; + r = 0; + } + break; + default: break; } diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index a47097b90fe8..6a5ff37874f4 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1594,12 +1594,17 @@ struct kvm_xen_hvm_attr { struct { __u64 gfn; } shared_info; + struct { + __u32 vcpu_id; + __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 Wed Jan 6 00:23:09 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 12000609 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 F1521C433E6 for ; Wed, 6 Jan 2021 00:24:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CE5AB22D71 for ; Wed, 6 Jan 2021 00:24:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726519AbhAFAYs (ORCPT ); Tue, 5 Jan 2021 19:24:48 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37374 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725730AbhAFAYs (ORCPT ); Tue, 5 Jan 2021 19:24:48 -0500 Received: from merlin.infradead.org (merlin.infradead.org [IPv6:2001:8b0:10b:1231::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F2C6EC0617A0 for ; Tue, 5 Jan 2021 16:23:25 -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=H++4iIGmYJEXkKGgipIlNb2mRIIAsa9YV93YkufiAww=; b=euZ+vQb4jFIORTrvoLYKYIFLwd uMdM5enDOcf2D5nK6kSqWlyoFnP38n0aAAIfzJPNZMV7yF3+e52rTCDkkMPVczgS1UkFHmmC0+rUS DFIgLx0xTcVek1yYNvqUQ8VwmP+HWMUFPeMSRq6csQAWmyQ+CcWq2rSCYiHUfa+kVzkyvlEZiUsmE 1pSvnTDfrN+7m1pSB2vjBleHLbhRuy3UYZEHQJEB/nCr6FEVGa9tjrfRWJwhL0Q6DtKg17jg2qzK9 T+BbjDfipVYXZb8S5aT5Bl53z3p81TcqJeQE/eR+hQgCZizFQatUzthSQkRDxtMiRY4h7OUmBFz5J 1u7Y93RA==; 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 1kwwbi-0004a1-IC; Wed, 06 Jan 2021 00:23:22 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1kwwbh-001NjH-Fn; Wed, 06 Jan 2021 00:23:21 +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, pdurrant@amazon.com, aagch@amazon.com, fandree@amazon.com, hch@infradead.org Subject: [PATCH v4 11/16] KVM: x86/xen: setup pvclock updates Date: Wed, 6 Jan 2021 00:23:09 +0000 Message-Id: <20210106002314.328380-12-dwmw2@infradead.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210106002314.328380-1-dwmw2@infradead.org> References: <20210106002314.328380-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 Parameterise kvm_setup_pvclock_page() a little bit so that it can be invoked for different gfn_to_hva_cache structures, and with different offsets. Then we can invoke it for the normal KVM pvclock and also for the Xen one in the vcpu_info. Signed-off-by: Joao Martins Signed-off-by: David Woodhouse --- arch/x86/kvm/x86.c | 31 ++++++++++++++++++------------- arch/x86/kvm/xen.c | 4 ++++ 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 761114f19489..228dd5ab9a81 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2588,13 +2588,15 @@ u64 get_kvmclock_ns(struct kvm *kvm) return ret; } -static void kvm_setup_pvclock_page(struct kvm_vcpu *v) +static void kvm_setup_pvclock_page(struct kvm_vcpu *v, + struct gfn_to_hva_cache *cache, + unsigned int offset) { struct kvm_vcpu_arch *vcpu = &v->arch; struct pvclock_vcpu_time_info guest_hv_clock; - if (unlikely(kvm_read_guest_cached(v->kvm, &vcpu->pv_time, - &guest_hv_clock, sizeof(guest_hv_clock)))) + if (unlikely(kvm_read_guest_offset_cached(v->kvm, cache, + &guest_hv_clock, offset, sizeof(guest_hv_clock)))) return; /* This VCPU is paused, but it's legal for a guest to read another @@ -2617,9 +2619,9 @@ static void kvm_setup_pvclock_page(struct kvm_vcpu *v) ++guest_hv_clock.version; /* first time write, random junk */ vcpu->hv_clock.version = guest_hv_clock.version + 1; - kvm_write_guest_cached(v->kvm, &vcpu->pv_time, - &vcpu->hv_clock, - sizeof(vcpu->hv_clock.version)); + kvm_write_guest_offset_cached(v->kvm, cache, + &vcpu->hv_clock, offset, + sizeof(vcpu->hv_clock.version)); smp_wmb(); @@ -2633,16 +2635,16 @@ static void kvm_setup_pvclock_page(struct kvm_vcpu *v) trace_kvm_pvclock_update(v->vcpu_id, &vcpu->hv_clock); - kvm_write_guest_cached(v->kvm, &vcpu->pv_time, - &vcpu->hv_clock, - sizeof(vcpu->hv_clock)); + kvm_write_guest_offset_cached(v->kvm, cache, + &vcpu->hv_clock, offset, + sizeof(vcpu->hv_clock)); smp_wmb(); vcpu->hv_clock.version++; - kvm_write_guest_cached(v->kvm, &vcpu->pv_time, - &vcpu->hv_clock, - sizeof(vcpu->hv_clock.version)); + kvm_write_guest_offset_cached(v->kvm, cache, + &vcpu->hv_clock, offset, + sizeof(vcpu->hv_clock.version)); } static int kvm_guest_time_update(struct kvm_vcpu *v) @@ -2729,7 +2731,10 @@ static int kvm_guest_time_update(struct kvm_vcpu *v) vcpu->hv_clock.flags = pvclock_flags; if (vcpu->pv_time_enabled) - kvm_setup_pvclock_page(v); + kvm_setup_pvclock_page(v, &vcpu->pv_time, 0); + if (vcpu->xen.vcpu_info_set) + kvm_setup_pvclock_page(v, &vcpu->xen.vcpu_info_cache, + offsetof(struct compat_vcpu_info, time)); 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 4bc72e0b9928..d2055b60fdc1 100644 --- a/arch/x86/kvm/xen.c +++ b/arch/x86/kvm/xen.c @@ -82,6 +82,9 @@ int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) /* No compat necessary here. */ 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)); + r = kvm_gfn_to_hva_cache_init(kvm, &v->arch.xen.vcpu_info_cache, data->u.vcpu_attr.gpa, sizeof(struct vcpu_info)); @@ -89,6 +92,7 @@ int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) return r; v->arch.xen.vcpu_info_set = true; + kvm_make_request(KVM_REQ_CLOCK_UPDATE, v); break; default: From patchwork Wed Jan 6 00:23:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 12000591 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=-16.0 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 464B9C43381 for ; Wed, 6 Jan 2021 00:24:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1FB33230FC for ; Wed, 6 Jan 2021 00:24:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726350AbhAFAYI (ORCPT ); Tue, 5 Jan 2021 19:24:08 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37258 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725919AbhAFAYG (ORCPT ); Tue, 5 Jan 2021 19:24:06 -0500 Received: from merlin.infradead.org (merlin.infradead.org [IPv6:2001:8b0:10b:1231::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CD7B3C061796 for ; Tue, 5 Jan 2021 16:23:25 -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=HOAX6gHoW52X2BjPdYIsP1sxh7PY7JwZnVz8J3jMf00=; b=jQDgt6UTIUWS833FoCGi2oHbDN 0+kbj6TGOOMbeXeERSi+BBMXhEqRy9itC8o/OTfysHMeVLdfTCeTuSnF5YrB8Zk+50XQ/feUv08iI I5jZOIz0iNCULSIkRvMRGk5EWmyssyIFB6QftbEQHQnASdcTu+Yrxir/+VBoO/UxRG0GMO8fBEDIl Yj80ADQCB2bgThoKzOvmzaZM3Phx9TlUlWrM6Bh5VQkkhU5DVm8w8b0mz+cmE+0ochKyb6UkikGsY d/MKKre8oAQsAjZM3LYNJOkCfguaizggJL11phYAVePN6MvOq2k22lW/Ez3rinB3pvvpthsGtduAQ MtLz2f2Q==; 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 1kwwbi-0004a2-IT; Wed, 06 Jan 2021 00:23:22 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1kwwbh-001NjK-GM; Wed, 06 Jan 2021 00:23:21 +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, pdurrant@amazon.com, aagch@amazon.com, fandree@amazon.com, hch@infradead.org Subject: [PATCH v4 12/16] KVM: x86/xen: register vcpu time info region Date: Wed, 6 Jan 2021 00:23:10 +0000 Message-Id: <20210106002314.328380-13-dwmw2@infradead.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210106002314.328380-1-dwmw2@infradead.org> References: <20210106002314.328380-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/x86.c | 2 ++ arch/x86/kvm/xen.c | 26 ++++++++++++++++++++++++++ include/uapi/linux/kvm.h | 1 + 4 files changed, 31 insertions(+) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index eabd0bf0035f..bd8c39d08c65 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -524,7 +524,9 @@ struct kvm_vcpu_hv { struct kvm_vcpu_xen { u64 hypercall_rip; bool vcpu_info_set; + bool vcpu_time_info_set; struct gfn_to_hva_cache vcpu_info_cache; + struct gfn_to_hva_cache vcpu_time_info_cache; }; struct kvm_vcpu_arch { diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 228dd5ab9a81..b81d8a0c2154 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2735,6 +2735,8 @@ static int kvm_guest_time_update(struct kvm_vcpu *v) if (vcpu->xen.vcpu_info_set) kvm_setup_pvclock_page(v, &vcpu->xen.vcpu_info_cache, offsetof(struct compat_vcpu_info, time)); + if (vcpu->xen.vcpu_time_info_set) + kvm_setup_pvclock_page(v, &vcpu->xen.vcpu_time_info_cache, 0); 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 d2055b60fdc1..1cca46effec8 100644 --- a/arch/x86/kvm/xen.c +++ b/arch/x86/kvm/xen.c @@ -95,6 +95,21 @@ int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) kvm_make_request(KVM_REQ_CLOCK_UPDATE, v); break; + case KVM_XEN_ATTR_TYPE_VCPU_TIME_INFO: + v = kvm_get_vcpu_by_id(kvm, data->u.vcpu_attr.vcpu_id); + if (!v) + return -EINVAL; + + r = kvm_gfn_to_hva_cache_init(kvm, &v->arch.xen.vcpu_time_info_cache, + data->u.vcpu_attr.gpa, + sizeof(struct pvclock_vcpu_time_info)); + if (r) + return r; + + v->arch.xen.vcpu_time_info_set = true; + kvm_make_request(KVM_REQ_CLOCK_UPDATE, v); + break; + default: break; } @@ -131,6 +146,17 @@ int kvm_xen_hvm_get_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) } break; + case KVM_XEN_ATTR_TYPE_VCPU_TIME_INFO: + v = kvm_get_vcpu_by_id(kvm, data->u.vcpu_attr.vcpu_id); + if (!v) + return -EINVAL; + + if (v->arch.xen.vcpu_time_info_set) { + data->u.vcpu_attr.gpa = v->arch.xen.vcpu_time_info_cache.gpa; + r = 0; + } + break; + default: break; } diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 6a5ff37874f4..32ad196d1834 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1605,6 +1605,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 Wed Jan 6 00:23:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 12000603 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=-16.0 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 65E73C433DB for ; Wed, 6 Jan 2021 00:24:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3E00322D74 for ; Wed, 6 Jan 2021 00:24:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726587AbhAFAYt (ORCPT ); Tue, 5 Jan 2021 19:24:49 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37378 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725917AbhAFAYs (ORCPT ); Tue, 5 Jan 2021 19:24:48 -0500 Received: from merlin.infradead.org (merlin.infradead.org [IPv6:2001:8b0:10b:1231::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0C4F9C0617A3 for ; Tue, 5 Jan 2021 16:23:25 -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=MnHoaZGxUvYNNbuhON+eM5z+rQpY7fMXhJjTuR5vXKI=; b=aS2zWWZxz2ZGIfnZPhdHtO7abw onUqcBgGC6UQjZnF5HYlfBAHoGHmNAHehrIcG0Iv2oYCM5ZgLPJGY1ulxVLTUxvox3cxBGpOPNRj8 G/fJQMZPVwk7nI/QWw6tQ2vLBFCA48KNrsY82vkOB9HSdrqHX+lxaMMtdppNmqek+oZaANcxTSDnS TFosgBkkZnPrNAIvDcYbawCZ6tqBhvoludULYCnUFBAB2q+qyJzObkRb441HkLK829BTIxO3WbzQd jzc6KNTKBS8XX5Sg9FzCqQTxgp258m6DsVQrmKONtG0lhmWAf59IZPI0ku8CDyfboYCyuyWHDODLM 0QTBri4w==; 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 1kwwbi-0004a3-Jr; Wed, 06 Jan 2021 00:23:22 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1kwwbh-001NjN-H6; Wed, 06 Jan 2021 00:23:21 +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, pdurrant@amazon.com, aagch@amazon.com, fandree@amazon.com, hch@infradead.org Subject: [PATCH v4 13/16] KVM: x86/xen: register runstate info Date: Wed, 6 Jan 2021 00:23:11 +0000 Message-Id: <20210106002314.328380-14-dwmw2@infradead.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210106002314.328380-1-dwmw2@infradead.org> References: <20210106002314.328380-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 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 | 148 +++++++++++++++++++++++++++++++- arch/x86/kvm/xen.h | 8 ++ include/uapi/linux/kvm.h | 1 + 5 files changed, 171 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index bd8c39d08c65..3fb236d99e77 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -523,10 +523,15 @@ struct kvm_vcpu_hv { /* Xen HVM per vcpu emulation context */ struct kvm_vcpu_xen { u64 hypercall_rip; + u32 current_runstate; bool vcpu_info_set; bool vcpu_time_info_set; + bool runstate_set; struct gfn_to_hva_cache vcpu_info_cache; struct gfn_to_hva_cache vcpu_time_info_cache; + struct gfn_to_hva_cache runstate_cache; + u64 last_steal; + u64 last_state_ns; }; struct kvm_vcpu_arch { diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index b81d8a0c2154..59e88732f623 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2946,6 +2946,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_set) { + kvm_xen_setup_runstate_page(vcpu); + return; + } + if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED)) return; @@ -3999,6 +4004,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_set) { + 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 1cca46effec8..17cbb4462b7e 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" @@ -56,6 +58,124 @@ static int kvm_xen_shared_info_init(struct kvm *kvm, gfn_t gfn) return 0; } +static void kvm_xen_update_runstate(struct kvm_vcpu *v, int state, u64 steal_ns) +{ + struct kvm_vcpu_xen *vcpu_xen = &v->arch.xen; + struct vcpu_runstate_info runstate; + unsigned int offset = offsetof(struct compat_vcpu_runstate_info, state_entry_time); + u64 now, delta; + + BUILD_BUG_ON(sizeof(struct compat_vcpu_runstate_info) != 0x2c); + +#ifdef CONFIG_X86_64 + /* + * The only difference 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); + + offset = offsetof(struct vcpu_runstate_info, state_entry_time); +#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. + */ + if (kvm_read_guest_offset_cached(v->kvm, &v->arch.xen.runstate_cache, + &runstate.state_entry_time, offset, + sizeof(u64) * 5)) + return; + + runstate.state_entry_time = XEN_RUNSTATE_UPDATE | + (runstate.state_entry_time + 1); + + if (kvm_write_guest_offset_cached(v->kvm, &v->arch.xen.runstate_cache, + &runstate.state_entry_time, offset, + sizeof(u64))) + return; + smp_wmb(); + + 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 (kvm_write_guest_offset_cached(v->kvm, &v->arch.xen.runstate_cache, + &state, + offsetof(struct vcpu_runstate_info, state), + sizeof(runstate.state))) + return; + + now = ktime_get_ns(); + delta = now - vcpu_xen->last_state_ns - steal_ns; + runstate.time[vcpu_xen->current_runstate] += delta; + if (steal_ns) + runstate.time[RUNSTATE_runnable] += steal_ns; + + BUILD_BUG_ON(offsetof(struct vcpu_runstate_info, state_entry_time) != + offsetof(struct vcpu_runstate_info, time) - sizeof(u64)); + BUILD_BUG_ON(offsetof(struct compat_vcpu_runstate_info, state_entry_time) != + offsetof(struct compat_vcpu_runstate_info, time) - sizeof(u64)); + BUILD_BUG_ON(sizeof(((struct vcpu_runstate_info *)0)->time) != + sizeof(((struct compat_vcpu_runstate_info *)0)->time)); + if (kvm_write_guest_offset_cached(v->kvm, &v->arch.xen.runstate_cache, + &runstate.time[0], + offset + sizeof(u64), + sizeof(runstate.time))) + return; + smp_wmb(); + vcpu_xen->current_runstate = state; + vcpu_xen->last_state_ns = now; + + runstate.state_entry_time &= ~XEN_RUNSTATE_UPDATE; + if (kvm_write_guest_offset_cached(v->kvm, &v->arch.xen.runstate_cache, + &runstate.state_entry_time, offset, + sizeof(u64))) + return; +} + +void kvm_xen_runstate_set_preempted(struct kvm_vcpu *v) +{ + struct kvm_vcpu_xen *vcpu_xen = &v->arch.xen; + 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 (v->preempted) { + new_state = RUNSTATE_runnable; + } else { + new_state = RUNSTATE_blocked; + vcpu_xen->last_steal = current->sched_info.run_delay; + } + + kvm_xen_update_runstate(v, new_state, 0); +} + +void kvm_xen_setup_runstate_page(struct kvm_vcpu *v) +{ + struct kvm_vcpu_xen *vcpu_xen = &v->arch.xen; + 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(v, RUNSTATE_running, steal_time); +} + int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) { struct kvm_vcpu *v; @@ -78,7 +198,6 @@ int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) v = kvm_get_vcpu_by_id(kvm, data->u.vcpu_attr.vcpu_id); if (!v) return -EINVAL; - /* No compat necessary here. */ BUILD_BUG_ON(sizeof(struct vcpu_info) != sizeof(struct compat_vcpu_info)); @@ -110,6 +229,22 @@ int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) kvm_make_request(KVM_REQ_CLOCK_UPDATE, v); break; + case KVM_XEN_ATTR_TYPE_VCPU_RUNSTATE: + v = kvm_get_vcpu_by_id(kvm, data->u.vcpu_attr.vcpu_id); + if (!v) + return -EINVAL; + + r = kvm_gfn_to_hva_cache_init(kvm, &v->arch.xen.runstate_cache, + data->u.vcpu_attr.gpa, + sizeof(struct vcpu_runstate_info)); + if (r) + return r; + + v->arch.xen.runstate_set = true; + v->arch.xen.current_runstate = RUNSTATE_blocked; + v->arch.xen.last_state_ns = ktime_get_ns(); + break; + default: break; } @@ -157,6 +292,17 @@ int kvm_xen_hvm_get_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) } break; + case KVM_XEN_ATTR_TYPE_VCPU_RUNSTATE: + v = kvm_get_vcpu_by_id(kvm, data->u.vcpu_attr.vcpu_id); + if (!v) + return -EINVAL; + + if (v->arch.xen.runstate_set) { + data->u.vcpu_attr.gpa = v->arch.xen.runstate_cache.gpa; + r = 0; + } + break; + default: break; } diff --git a/arch/x86/kvm/xen.h b/arch/x86/kvm/xen.h index 317c1325dade..407e717476d6 100644 --- a/arch/x86/kvm/xen.h +++ b/arch/x86/kvm/xen.h @@ -9,6 +9,8 @@ #ifndef __ARCH_X86_KVM_XEN_H__ #define __ARCH_X86_KVM_XEN_H__ +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); @@ -56,4 +58,10 @@ struct compat_shared_info { 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 32ad196d1834..1f8a9380ed18 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1606,6 +1606,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 Wed Jan 6 00:23:12 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 12000599 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 C8C41C433E6 for ; Wed, 6 Jan 2021 00:24:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 93E2722D74 for ; Wed, 6 Jan 2021 00:24:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726605AbhAFAYt (ORCPT ); Tue, 5 Jan 2021 19:24:49 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37386 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726508AbhAFAYs (ORCPT ); Tue, 5 Jan 2021 19:24:48 -0500 Received: from merlin.infradead.org (merlin.infradead.org [IPv6:2001:8b0:10b:1231::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1A38AC0617A7 for ; Tue, 5 Jan 2021 16:23:26 -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=frmRHHq23MqMskRLmwOX1lQPvTSFDwDLAiP6IEmA/+Y=; b=EYAUy7Sx3d1tWboOK4EnGjYpdU uMigku2/tlG6S2Ipo7djdV8VvdUDKrjpGN+CiO/CrG2UUpuQQMTTc0RRuYgYVwZp1eC42j1sQMrAu yGgKtBbgjasHuhJkCfWNkXdFtAF3KrBmxeK4JtovvayEuq+6n6j3RwW2CBGQgJwOGalwjOELDO07/ zYegzfh4IZ5hmCcV+FvrT1txF0/o41KxhuCOcVsOsGIYVh8rYfAMP/uhQvV7XkK93qPGmoGuO5aca Xwd1gzak8dKYn+dFhriYjSCSF7evRSVF7mqrbZntu7dhT2oVzag4BPluOX2npG5iiYJ/LBQCgNzwG 1osdjnbg==; 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 1kwwbi-0004a4-KW; Wed, 06 Jan 2021 00:23:22 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1kwwbh-001NjQ-IX; Wed, 06 Jan 2021 00:23:21 +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, pdurrant@amazon.com, aagch@amazon.com, fandree@amazon.com, hch@infradead.org Subject: [PATCH v4 14/16] KVM: x86: declare Xen HVM shared info capability and add test case Date: Wed, 6 Jan 2021 00:23:12 +0000 Message-Id: <20210106002314.328380-15-dwmw2@infradead.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210106002314.328380-1-dwmw2@infradead.org> References: <20210106002314.328380-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 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 | 194 ++++++++++++++++++ 4 files changed, 200 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 59e88732f623..e7a639e998d5 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -3765,7 +3765,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 1f8a9380ed18..a075d7297da6 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1148,6 +1148,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; @@ -1583,6 +1584,7 @@ struct kvm_pv_cmd { /* Available with KVM_CAP_DIRTY_LOG_RING */ #define KVM_RESET_DIRTY_RINGS _IO(KVMIO, 0xc7) +/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO */ #define KVM_XEN_HVM_GET_ATTR _IOWR(KVMIO, 0xc8, struct kvm_xen_hvm_attr) #define KVM_XEN_HVM_SET_ATTR _IOW(KVMIO, 0xc9, struct kvm_xen_hvm_attr) @@ -1602,6 +1604,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 140b628f4a5c..96a8675d14d0 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -60,6 +60,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..c8c696a6d41c --- /dev/null +++ b/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c @@ -0,0 +1,194 @@ +// 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 vi = { + .type = KVM_XEN_ATTR_TYPE_VCPU_INFO, + .u.vcpu_attr.vcpu_id = VCPU_ID, + .u.vcpu_attr.gpa = SHINFO_REGION_GPA + 40, + }; + vm_ioctl(vm, KVM_XEN_HVM_SET_ATTR, &vi); + + struct kvm_xen_hvm_attr pvclock = { + .type = KVM_XEN_ATTR_TYPE_VCPU_TIME_INFO, + .u.vcpu_attr.vcpu_id = 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_id = 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 + 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 Wed Jan 6 00:23:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 12000589 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 35314C433E9 for ; Wed, 6 Jan 2021 00:24:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 067A0230FA for ; Wed, 6 Jan 2021 00:24:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726419AbhAFAYI (ORCPT ); Tue, 5 Jan 2021 19:24:08 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37256 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726224AbhAFAYG (ORCPT ); Tue, 5 Jan 2021 19:24:06 -0500 Received: from merlin.infradead.org (merlin.infradead.org [IPv6:2001:8b0:10b:1231::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C5DA3C061793 for ; Tue, 5 Jan 2021 16:23:25 -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=h7qf/Q3nRXQPoubj1J0wE5hiTMUDYk1pIYgTMLBIVyU=; b=mdvGmAgrhSQCV+W7Y1nGPH7DXn SHBCRAuC4mEigps0x5EIjQuLpHMlaITjbul8X0mkej10yOGdeCcmFLCKHeLIxxQe4ohz4M2873WyF 2tVLEnxN2KCEstwCSjsWjw1Jkk7K9x4YBw6AIDvB9lmUkrY2xqLxP8ibzGBZURURbMD+L2h8+FVuy 2euxqLWYegDN6uAMZUK7Cu7DaEz2X02fqjKU5a3jJQA29ssrWq3ovyTkqMRC7MBLSXYlXrGems6JT HTIBTkM71HWhL5PIQY3pkaR07oIfz1YEI/NQEMPEIfhVLy7gpfUV4LywGJ0YTSIafqIEF57NuQw2Z Tlj1ln7A==; 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 1kwwbi-0004a5-LR; Wed, 06 Jan 2021 00:23:22 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1kwwbh-001NjT-JF; Wed, 06 Jan 2021 00:23:21 +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, pdurrant@amazon.com, aagch@amazon.com, fandree@amazon.com, hch@infradead.org Subject: [PATCH v4 15/16] KVM: Add documentation for Xen hypercall and shared_info updates Date: Wed, 6 Jan 2021 00:23:13 +0000 Message-Id: <20210106002314.328380-16-dwmw2@infradead.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210106002314.328380-1-dwmw2@infradead.org> References: <20210106002314.328380-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 --- Documentation/virt/kvm/api.rst | 124 ++++++++++++++++++++++++++++++++- 1 file changed, 123 insertions(+), 1 deletion(-) diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst index 70254eaa5229..e8858cca93ab 100644 --- a/Documentation/virt/kvm/api.rst +++ b/Documentation/virt/kvm/api.rst @@ -956,6 +956,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 ------------------ @@ -4825,6 +4832,71 @@ 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_id; + __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. Note that although Xen places vcpu_info for the first + 32 vCPUs in the shared_info page, KVM does not automatically do so + and requires that KVM_XEN_ATTR_TYPE_VCPU_INFO be used explicitly + even when the vcpu_info for a given vCPU resides at the "default" + location in the shared_info page. This is because KVM is not aware + of the Xen CPU id which is used as the index into the vcpu_info[] + array, so cannot know the correct default location. + +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 ======================== @@ -5321,6 +5393,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. */ @@ -6409,7 +6509,6 @@ 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_DIRTY_LOG_RING --------------------------- @@ -6496,3 +6595,26 @@ KVM_GET_DIRTY_LOG and KVM_CLEAR_DIRTY_LOG. After enabling KVM_CAP_DIRTY_LOG_RING with an acceptable dirty ring size, the virtual machine will switch to ring-buffer dirty page tracking and further KVM_GET_DIRTY_LOG or KVM_CLEAR_DIRTY_LOG ioctls will fail. + +8.30 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. From patchwork Wed Jan 6 00:23:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 12000617 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 08CEDC433DB for ; Wed, 6 Jan 2021 00:26:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C82E7230FA for ; Wed, 6 Jan 2021 00:26:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726766AbhAFA01 (ORCPT ); Tue, 5 Jan 2021 19:26:27 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37662 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726680AbhAFA00 (ORCPT ); Tue, 5 Jan 2021 19:26:26 -0500 Received: from casper.infradead.org (casper.infradead.org [IPv6:2001:8b0:10b:1236::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A21E3C0617A0 for ; Tue, 5 Jan 2021 16:25:46 -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=/C8di9xXHodwqGPB90VsDEPR5hgOyNhOqCC0TApGH+s=; b=sr2A30oxxDmPq5QIIKblFcQ/IY 31t/TVxekmbmxSMqa6MTclQf3c7cs3ejgOGUjcJ++DTj19zB4Q/kwphQ3N1CPYWWGKYo6YxdoaqOs unjRKepELHKISR0LaWPbLWeT5lovqvo59sZ8jApwlqdfXjCHWgZhwZ9hiTNypN6WOJrdyvfFsVdhO jDN3sbaC29AbqVUVpkluSznRfsBZPkzBIVgOMJ9ePjKD1nj1z50vNUyP717fi3mN5rPqcKztayrXn Yn6cO/wwzTIUEhb6gRQwZvcBBU791i9nBLZrHMIURpASQMIezXcOL3V0UkvJ59dj7thkAgpZYXAzg +I3xRTIQ==; Received: from i7.infradead.org ([2001:8b0:10b:1:21e:67ff:fecb:7a92]) by casper.infradead.org with esmtpsa (Exim 4.94 #2 (Red Hat Linux)) id 1kwwbh-001pA6-W7; Wed, 06 Jan 2021 00:23:36 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94 #2 (Red Hat Linux)) id 1kwwbh-001NjW-Jw; Wed, 06 Jan 2021 00:23:21 +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, pdurrant@amazon.com, aagch@amazon.com, fandree@amazon.com, hch@infradead.org Subject: [PATCH v4 16/16] KVM: x86/xen: Add event channel interrupt vector upcall Date: Wed, 6 Jan 2021 00:23:14 +0000 Message-Id: <20210106002314.328380-17-dwmw2@infradead.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210106002314.328380-1-dwmw2@infradead.org> References: <20210106002314.328380-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 turns out that we can't handle event channels *entirely* in userspace by delivering them as ExtINT, because KVM is a bit picky about when it accepts ExtINT interrupts from a legacy PIC. The in-kernel local APIC has to have LVT0 configured in APIC_MODE_EXTINT and unmasked, which isn't necessarily the case for Xen guests especially on secondary CPUs. To cope with this, add kvm_xen_get_interrupt() which checks the evtchn_pending_upcall field in the Xen vcpu_info, and delivers the Xen upcall vector (configured by KVM_XEN_ATTR_TYPE_UPCALL_VECTOR) if it's set regardless of LAPIC LVT0 configuration. This gives us the minimum support we need for completely userspace-based implementation of event channels. This does mean that vcpu_enter_guest() needs to check for the evtchn_pending_upcall flag being set, because it can't rely on someone having set KVM_REQ_EVENT unless we were to add some way for userspace to do so manually. But actually, I don't quite see how that works reliably for interrupts injected with KVM_INTERRUPT either. In kvm_vcpu_ioctl_interrupt() the KVM_REQ_EVENT request is set once, but that'll get cleared the first time through vcpu_enter_guest(). So if the first exit is for something *else* without interrupts being enabled yet, won't the KVM_REQ_EVENT request have been consumed already and just be lost? I wonder if my addition of '|| kvm_xen_has_interrupt(vcpu)' should actually be '|| kvm_has_injectable_intr(vcpu)' to fix that pre-existing bug? Signed-off-by: David Woodhouse --- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/irq.c | 7 +++++ arch/x86/kvm/x86.c | 3 +- arch/x86/kvm/xen.c | 52 +++++++++++++++++++++++++++++++++ arch/x86/kvm/xen.h | 1 + include/uapi/linux/kvm.h | 2 ++ 6 files changed, 65 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 3fb236d99e77..51ac9e158396 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -907,6 +907,7 @@ struct msr_bitmap_range { struct kvm_xen { bool long_mode; bool shinfo_set; + u8 upcall_vector; struct gfn_to_hva_cache shinfo_cache; }; diff --git a/arch/x86/kvm/irq.c b/arch/x86/kvm/irq.c index 814698e5b152..24668b51b5c8 100644 --- a/arch/x86/kvm/irq.c +++ b/arch/x86/kvm/irq.c @@ -14,6 +14,7 @@ #include "irq.h" #include "i8254.h" #include "x86.h" +#include "xen.h" /* * check if there are pending timer events @@ -56,6 +57,9 @@ int kvm_cpu_has_extint(struct kvm_vcpu *v) if (!lapic_in_kernel(v)) return v->arch.interrupt.injected; + if (kvm_xen_has_interrupt(v)) + return 1; + if (!kvm_apic_accept_pic_intr(v)) return 0; @@ -110,6 +114,9 @@ static int kvm_cpu_get_extint(struct kvm_vcpu *v) if (!lapic_in_kernel(v)) return v->arch.interrupt.nr; + if (kvm_xen_has_interrupt(v)) + return v->kvm->arch.xen.upcall_vector; + if (irqchip_split(v->kvm)) { int vector = v->arch.pending_external_vector; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index e7a639e998d5..cf1c1db090d2 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -8935,7 +8935,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) kvm_x86_ops.msr_filter_changed(vcpu); } - if (kvm_check_request(KVM_REQ_EVENT, vcpu) || req_int_win) { + if (kvm_check_request(KVM_REQ_EVENT, vcpu) || req_int_win || + kvm_xen_has_interrupt(vcpu)) { ++vcpu->stat.req_event; kvm_apic_accept_events(vcpu); if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) { diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c index 17cbb4462b7e..4bc9da9fcfb8 100644 --- a/arch/x86/kvm/xen.c +++ b/arch/x86/kvm/xen.c @@ -176,6 +176,45 @@ void kvm_xen_setup_runstate_page(struct kvm_vcpu *v) kvm_xen_update_runstate(v, RUNSTATE_running, steal_time); } +int kvm_xen_has_interrupt(struct kvm_vcpu *v) +{ + u8 rc = 0; + + /* + * If the global upcall vector (HVMIRQ_callback_vector) is set and + * the vCPU's evtchn_upcall_pending flag is set, the IRQ is pending. + */ + if (v->arch.xen.vcpu_info_set && v->kvm->arch.xen.upcall_vector) { + struct gfn_to_hva_cache *ghc = &v->arch.xen.vcpu_info_cache; + struct kvm_memslots *slots = kvm_memslots(v->kvm); + unsigned int offset = offsetof(struct vcpu_info, evtchn_upcall_pending); + + /* No need for compat handling here */ + BUILD_BUG_ON(offsetof(struct vcpu_info, evtchn_upcall_pending) != + offsetof(struct compat_vcpu_info, evtchn_upcall_pending)); + BUILD_BUG_ON(sizeof(rc) != + sizeof(((struct vcpu_info *)0)->evtchn_upcall_pending)); + BUILD_BUG_ON(sizeof(rc) != + sizeof(((struct compat_vcpu_info *)0)->evtchn_upcall_pending)); + + /* + * For efficiency, this mirrors the checks for using the valid + * cache in kvm_read_guest_offset_cached(), but just uses + * __get_user() instead. And falls back to the slow path. + */ + if (likely(slots->generation == ghc->generation && + !kvm_is_error_hva(ghc->hva) && ghc->memslot)) { + /* Fast path */ + __get_user(rc, (u8 __user *)ghc->hva + offset); + } else { + /* Slow path */ + kvm_read_guest_offset_cached(v->kvm, ghc, &rc, offset, + sizeof(rc)); + } + } + return rc; +} + int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) { struct kvm_vcpu *v; @@ -245,6 +284,14 @@ int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) v->arch.xen.last_state_ns = ktime_get_ns(); break; + case KVM_XEN_ATTR_TYPE_UPCALL_VECTOR: + if (data->u.vector < 0x10) + return -EINVAL; + + kvm->arch.xen.upcall_vector = data->u.vector; + r = 0; + break; + default: break; } @@ -303,6 +350,11 @@ int kvm_xen_hvm_get_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) } break; + case KVM_XEN_ATTR_TYPE_UPCALL_VECTOR: + data->u.vector = kvm->arch.xen.upcall_vector; + r = 0; + break; + default: break; } diff --git a/arch/x86/kvm/xen.h b/arch/x86/kvm/xen.h index 407e717476d6..d64916ac4a12 100644 --- a/arch/x86/kvm/xen.h +++ b/arch/x86/kvm/xen.h @@ -11,6 +11,7 @@ void kvm_xen_setup_runstate_page(struct kvm_vcpu *vcpu); void kvm_xen_runstate_set_preempted(struct kvm_vcpu *vcpu); +int kvm_xen_has_interrupt(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); diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index a075d7297da6..0926d469b2f7 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1593,6 +1593,7 @@ struct kvm_xen_hvm_attr { union { __u8 long_mode; + __u8 vector; struct { __u64 gfn; } shared_info; @@ -1610,6 +1611,7 @@ struct kvm_xen_hvm_attr { #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 +#define KVM_XEN_ATTR_TYPE_UPCALL_VECTOR 0x5 /* Secure Encrypted Virtualization command */ enum sev_cmd_id {