From patchwork Wed Dec 12 15:02:15 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Price X-Patchwork-Id: 10726501 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0E2B391E for ; Wed, 12 Dec 2018 15:03:36 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id ECD952B13B for ; Wed, 12 Dec 2018 15:03:35 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DE1722B14C; Wed, 12 Dec 2018 15:03:35 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 453D52B13B for ; Wed, 12 Dec 2018 15:03:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=t58of9AO/acnPn8FwFLtUFA1tFYyztHPdj+wpBDQ/CI=; b=q8cfJvm4jCYvd/ bxX2D44R5rFbSSHctBdvAgtSpT5w1zvWsjJBpJ7L9xWwP38mAoohWasrehzNAttSNrQiO1lYgwley smb86764/1DaO9DAhDqwRnTnTs+zWZJPNcLJTNBSFlsl2EpQf54MDE3ufMD4AExYibiBUcwgJGC3/ xpw4nRIFgEK0GctDcP3qm4FOF6OjOTpgo7OT6evJdhZYiamd/wzEk/eJVRwhZtJ22aS2VeVYvnwys YnKqEDKexfcQuZOSsYaBzfKuhEK5gY5885OZ/OYQYg8qnDiM3TVFZutVIHEwBdKJkV/yjwWsdR+p9 EarAD/i20GeFnExF3yFw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gX62s-0006wi-K1; Wed, 12 Dec 2018 15:03:30 +0000 Received: from usa-sjc-mx-foss1.foss.arm.com ([217.140.101.70] helo=foss.arm.com) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gX62U-0006GX-MT for linux-arm-kernel@lists.infradead.org; Wed, 12 Dec 2018 15:03:09 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id A0C8B1596; Wed, 12 Dec 2018 07:03:00 -0800 (PST) Received: from e112269-lin.arm.com (e112269-lin.cambridge.arm.com [10.1.196.55]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 262FB3F59C; Wed, 12 Dec 2018 07:02:59 -0800 (PST) From: Steven Price To: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH v2 01/12] KVM: arm64: Document PV-time interface Date: Wed, 12 Dec 2018 15:02:15 +0000 Message-Id: <20181212150226.38051-2-steven.price@arm.com> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20181212150226.38051-1-steven.price@arm.com> References: <20181212150226.38051-1-steven.price@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181212_070306_761594_E069139A X-CRM114-Status: GOOD ( 21.36 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mark Rutland , Marc Zyngier , Catalin Marinas , Will Deacon , Christoffer Dall , Steven Price Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP We introduce a paravirtualization interface for KVM/arm64 based on the "Arm Paravirtualized Time for Arm-Base Systems" specification DEN 0057A. User space can specify a reserved area of memory for the guest and inform KVM to populate the memory with information on stolen time and Live Physical Time (LPT) that can be used to derive a stable counter/timer for a guest subject to migration between hosts with different counter frequencies. A hypercall interface is provided for the guest to interrogate the hypervisor's support for this interface and the location of the shared memory structures. Signed-off-by: Steven Price --- Documentation/virtual/kvm/arm/pvtime.txt | 169 +++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 Documentation/virtual/kvm/arm/pvtime.txt diff --git a/Documentation/virtual/kvm/arm/pvtime.txt b/Documentation/virtual/kvm/arm/pvtime.txt new file mode 100644 index 000000000000..1870b904075b --- /dev/null +++ b/Documentation/virtual/kvm/arm/pvtime.txt @@ -0,0 +1,169 @@ +Paravirtualized time support for arm64 +====================================== + +Arm specification DEN0057/A defined a standard for paravirtualised time +support for Aarch64 guests: + +https://developer.arm.com/docs/den0057/a + +KVM/Arm64 implements this specification by providing some hypervisor service +calls to support a paravirtualized guest obtaining a view of the amount of +time stolen from its execution and a concept of Live Physical Time (LPT) which +represents time during which the guest is running and works across migrations. + +Three new SMCCC compatible hypercalls are defined: + +PV_FEATURES 0xC5000020 +PV_TIME_LPT 0xC5000021 +PV_TIME_ST 0xC5000022 + +These are only available in the SMC64/HVC64 calling convention as +paravirtualized time is not available to 32 bit Arm guests. + +PV_FEATURES + Function ID: (uint32) : 0xC5000020 + PV_func_id: (uint32) : Either PV_TIME_LPT or PV_TIME_ST + Return value: (int32) : NOT_SUPPORTED (-1) or SUCCESS (0) if the relevant + PV-time feature is supported by the hypervisor. + +PV_TIME_LPT + Function ID: (uint32) : 0xC5000021 + Flags: (uint32) : Bit[0]: Request migration interrupts + (not currently supported by KVM) + Return value: (int64) : IPA of the shared live physical time data + structure or negative error code on failure: + NOT_SUPPORTED (-1) + INVALID_PARAMETERS (-2) + +PV_TIME_ST + Function ID: (uint32) : 0xC5000022 + Return value: (int64) : IPA of the stolen time data structure for this + (V)CPU. On failure: + NOT_SUPPORTED (-1) + +Live Physical Time +------------------ + +The structure pointed to by the PV_TIME_LPT hypercall is as follows: + + Field | Byte Length | Byte Offset | Description + --------------- | ----------- | ----------- | ------------------------------- + Revision | 4 | 0 | Must be 0 for this revision + Attributes | 4 | 4 | Must be 0 + sequence_number | 8 | 8 | Bit 0: reserved + | | | Bits 1:63 number of migrations + scale_mult | 8 | 16 | Multiplier to scale from native + | | | frequency to PV frequency + shift | 4 | 24 | Shift applied before multiplier + Reserved | 4 | 28 | Must be 0 + Fn | 8 | 32 | Native frequency + Fpv | 8 | 40 | Paravirtualized frequency seen + | | | by guest + div_by_fpv_mult | 8 | 48 | Multiplier to implement fast + | | | divide by Fpv + +Where scale_mult is defined as 2^(64-shift) * Fpv / Fn + +The structure will be updated by the hypervisor whenever the guest is migrated +to a new host. It will be present within a reserved region of the normal +memory given to the guest. The guest should not attempt to write into this +memory. + +Stolen Time +----------- + +The structure pointed to by the PV_TIME_ST hypercall is as follows: + + Field | Byte Length | Byte Offset | Description + ----------- | ----------- | ----------- | -------------------------- + Revision | 4 | 0 | Must be 0 for version 0.1 + Attributes | 4 | 4 | Must be 0 + Stolen time | 8 | 8 | Stolen time in unsigned + | | | nanoseconds indicating how + | | | much time this VCPU thread + | | | was involuntarily not + | | | running on a physical CPU. + +The structure will be updated by the hypervisor periodically as time is stolen +from the VCPU. It will be present within a reserved region of the normal +memory given to the guest. The guest should not attempt to write into this +memory. There is a structure by VCPU of the guest. + +User space interface +==================== + +User space can request that KVM provide the paravirtualized time interface to +a guest by creating a KVM_DEV_TYPE_ARM_PV_TIME device, for example: + + struct kvm_create_device pvtime_device = { + .type = KVM_DEV_TYPE_ARM_PV_TIME, + .attr = 0, + .flags = 0, + }; + + pvtime_fd = ioctl(vm_fd, KVM_CREATE_DEVICE, &pvtime_device); + +The guest IPA of the structures must be given to KVM. This is the address of +the LPT structure and the base address of an array of stolen time structures +(one for each VCPU). For example: + + struct kvm_device_attr lpt_base = { + .group = KVM_DEV_ARM_PV_TIME_PADDR, + .attr = KVM_DEV_ARM_PV_TIME_LPT, + .addr = (u64)(unsigned long)&lpt_paddr + }; + struct kvm_device_attr st_base = { + .group = KVM_DEV_ARM_PV_TIME_PADDR, + .attr = KVM_DEV_ARM_PV_TIME_ST, + .addr = (u64)(unsigned long)&st_paddr + }; + + ioctl(pvtime_fd, KVM_SET_DEVICE_ATTR, &lpt_base); + ioctl(pvtime_fd, KVM_SET_DEVICE_ATTR, &st_base); + +The paravirtualized frequency of the guest can also be set. By default this +will be the counter frequency of the host. However when migrating a guest from +another host, this must be manually set to ensure that the guest sees the same +frequency. + + u32 frequency; + + struct kvm_device_attr lpt_freq = { + .group = KVM_DEV_ARM_PV_TIME_FREQUENCY, + .attr = KVM_DEV_ARM_PV_TIME_LPT, + .addr = (u64)(unsigned long)&frequency + }; + + ioctl(pvtime_fd, KVM_SET_DEVICE_ATTR, &lpt_freq); + +For migration (or save/restore) of a guest it is necessary to save the contents +of the shared pages and later restore them. KVM_DEV_ARM_PV_TIME_STATE_SIZE +provides the size of this data and KVM_DEV_ARM_PV_TIME_STATE allows the state +to be read/written. The state for stolen time and LPT are accessed separately. +It is also necessary for the physical address and frequency to be set +identically when restoring. The kernel will update the structure on first run +of the vCPU(s) to contain the new coefficients. + + void *save_state(int fd, u64 attr, u32 *size) { + struct kvm_device_attr get_size = { + .group = KVM_DEV_ARM_PV_TIME_STATE_SIZE, + .attr = attr, + .addr = (u64)(unsigned long)size + }; + + ioctl(fd, KVM_GET_DEVICE_ATTR, get_size); + + void *buffer = malloc(*size); + + struct kvm_device_attr get_state = { + .group = KVM_DEV_ARM_PV_TIME_STATE, + .attr = attr, + .addr = (u64)(unsigned long)size + }; + + ioctl(fd, KVM_GET_DEVICE_ATTR, buffer); + } + + void *lpt_state = save_state(pvtime_fd, KVM_DEV_ARM_PV_TIME_LPT, &lpt_size); + void *st_state = save_state(pvtime_fd, KVM_DEV_ARM_PV_TIME_ST, &st_size); + From patchwork Wed Dec 12 15:02:16 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Price X-Patchwork-Id: 10726503 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 072C391E for ; Wed, 12 Dec 2018 15:03:53 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E8AFD2B161 for ; Wed, 12 Dec 2018 15:03:52 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DCFE42B16B; Wed, 12 Dec 2018 15:03:52 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 3C4C72B161 for ; Wed, 12 Dec 2018 15:03:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=WHKqc5ixdQS3D4tPzOIV/f/8gmDTC+08c9zxrQTDPq0=; b=re1eXW7hQ52Ypc 2iuYn7ZmzGWEgyzIz/fjvzV5yv4h7C7ZL4oi24hAolHKHcgXYrK+6uuO2pm0gDA7m3WBMEB2vbE9o Oq6vSLEMSfKkvaOvQ7iXsqQCZAm/HVAK5nvCmhZ7nYd7x0SZTWarzQEdJ8JEnKEXvBbMmooyx7FMs 92X3rnuHS/G7c8BuwpDs4VvUMfAp/H5Mn408wg3GFaicQJ0iMCle/+CLM92dBZ5IOz5elUyPWGnIo Wm57f6mTCR4Tglk9PcsK4d8KeS69/ZpUO72QC6o+0n1c+mYoThIJimMyefsUDCVZVtvL3ZNDn5oGM 8jIA+BXjFSYqSsWUH5CQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gX636-0007Aa-23; Wed, 12 Dec 2018 15:03:44 +0000 Received: from foss.arm.com ([217.140.101.70]) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gX62U-0006JD-TH for linux-arm-kernel@lists.infradead.org; Wed, 12 Dec 2018 15:03:12 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 894B415AB; Wed, 12 Dec 2018 07:03:02 -0800 (PST) Received: from e112269-lin.arm.com (e112269-lin.cambridge.arm.com [10.1.196.55]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id DF71C3F59C; Wed, 12 Dec 2018 07:03:00 -0800 (PST) From: Steven Price To: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH v2 02/12] KVM: arm/arm64: Factor out hypercall handling from PSCI code Date: Wed, 12 Dec 2018 15:02:16 +0000 Message-Id: <20181212150226.38051-3-steven.price@arm.com> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20181212150226.38051-1-steven.price@arm.com> References: <20181212150226.38051-1-steven.price@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181212_070307_152870_36D289DE X-CRM114-Status: GOOD ( 17.80 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mark Rutland , Marc Zyngier , Catalin Marinas , Will Deacon , Christoffer Dall , Steven Price Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP From: Christoffer Dall We currently intertwine the KVM PSCI implementation with the general dispatch of hypercall handling, which makes perfect sense because PSCI is the only category of hypercalls we support. However, as we are about to support additional hypercalls, factor out this functionality into a separate hypercall handler file. Signed-off-by: Christoffer Dall [steven.price@arm.com: rebased] Signed-off-by: Steven Price Reviewed-by: Andrew Jones --- arch/arm/kvm/Makefile | 2 +- arch/arm/kvm/handle_exit.c | 2 +- arch/arm64/kvm/Makefile | 1 + arch/arm64/kvm/handle_exit.c | 4 +- include/kvm/arm_hypercalls.h | 43 ++++++++++++++++++++ include/kvm/arm_psci.h | 2 +- virt/kvm/arm/hypercalls.c | 51 ++++++++++++++++++++++++ virt/kvm/arm/psci.c | 76 +----------------------------------- 8 files changed, 102 insertions(+), 79 deletions(-) create mode 100644 include/kvm/arm_hypercalls.h create mode 100644 virt/kvm/arm/hypercalls.c diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile index 48de846f2246..5994f3b3d375 100644 --- a/arch/arm/kvm/Makefile +++ b/arch/arm/kvm/Makefile @@ -24,7 +24,7 @@ obj-y += kvm-arm.o init.o interrupts.o obj-y += handle_exit.o guest.o emulate.o reset.o obj-y += coproc.o coproc_a15.o coproc_a7.o vgic-v3-coproc.o obj-y += $(KVM)/arm/arm.o $(KVM)/arm/mmu.o $(KVM)/arm/mmio.o -obj-y += $(KVM)/arm/psci.o $(KVM)/arm/perf.o +obj-y += $(KVM)/arm/psci.o $(KVM)/arm/perf.o $(KVM)/arm/hypercalls.o obj-y += $(KVM)/arm/aarch32.o obj-y += $(KVM)/arm/vgic/vgic.o diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c index 910bd8dabb3c..404c67a06a2f 100644 --- a/arch/arm/kvm/handle_exit.c +++ b/arch/arm/kvm/handle_exit.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include "trace.h" diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile index 0f2a135ba15b..45bb68f6c161 100644 --- a/arch/arm64/kvm/Makefile +++ b/arch/arm64/kvm/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_KVM_ARM_HOST) += hyp/ kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o $(KVM)/vfio.o kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arm.o $(KVM)/arm/mmu.o $(KVM)/arm/mmio.o kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/psci.o $(KVM)/arm/perf.o +kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hypercalls.o kvm-$(CONFIG_KVM_ARM_HOST) += inject_fault.o regmap.o va_layout.o kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c index 35a81bebd02b..5f5e426cab3b 100644 --- a/arch/arm64/kvm/handle_exit.c +++ b/arch/arm64/kvm/handle_exit.c @@ -22,8 +22,6 @@ #include #include -#include - #include #include #include @@ -33,6 +31,8 @@ #include #include +#include + #define CREATE_TRACE_POINTS #include "trace.h" diff --git a/include/kvm/arm_hypercalls.h b/include/kvm/arm_hypercalls.h new file mode 100644 index 000000000000..e5f7f81196b6 --- /dev/null +++ b/include/kvm/arm_hypercalls.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (C) 2018 Arm Ltd. */ + +#ifndef __KVM_ARM_HYPERCALLS_H +#define __KVM_ARM_HYPERCALLS_H + +#include + +int kvm_hvc_call_handler(struct kvm_vcpu *vcpu); + +static inline u32 smccc_get_function(struct kvm_vcpu *vcpu) +{ + return vcpu_get_reg(vcpu, 0); +} + +static inline unsigned long smccc_get_arg1(struct kvm_vcpu *vcpu) +{ + return vcpu_get_reg(vcpu, 1); +} + +static inline unsigned long smccc_get_arg2(struct kvm_vcpu *vcpu) +{ + return vcpu_get_reg(vcpu, 2); +} + +static inline unsigned long smccc_get_arg3(struct kvm_vcpu *vcpu) +{ + return vcpu_get_reg(vcpu, 3); +} + +static inline void smccc_set_retval(struct kvm_vcpu *vcpu, + unsigned long a0, + unsigned long a1, + unsigned long a2, + unsigned long a3) +{ + vcpu_set_reg(vcpu, 0, a0); + vcpu_set_reg(vcpu, 1, a1); + vcpu_set_reg(vcpu, 2, a2); + vcpu_set_reg(vcpu, 3, a3); +} + +#endif diff --git a/include/kvm/arm_psci.h b/include/kvm/arm_psci.h index 4b1548129fa2..ac8cd19d2456 100644 --- a/include/kvm/arm_psci.h +++ b/include/kvm/arm_psci.h @@ -51,7 +51,7 @@ static inline int kvm_psci_version(struct kvm_vcpu *vcpu, struct kvm *kvm) } -int kvm_hvc_call_handler(struct kvm_vcpu *vcpu); +int kvm_psci_call(struct kvm_vcpu *vcpu); struct kvm_one_reg; diff --git a/virt/kvm/arm/hypercalls.c b/virt/kvm/arm/hypercalls.c new file mode 100644 index 000000000000..153aa7642100 --- /dev/null +++ b/virt/kvm/arm/hypercalls.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Arm Ltd. + +#include +#include + +#include + +#include +#include + +int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) +{ + u32 func_id = smccc_get_function(vcpu); + u32 val = SMCCC_RET_NOT_SUPPORTED; + u32 feature; + + switch (func_id) { + case ARM_SMCCC_VERSION_FUNC_ID: + val = ARM_SMCCC_VERSION_1_1; + break; + case ARM_SMCCC_ARCH_FEATURES_FUNC_ID: + feature = smccc_get_arg1(vcpu); + switch (feature) { + case ARM_SMCCC_ARCH_WORKAROUND_1: + if (kvm_arm_harden_branch_predictor()) + val = SMCCC_RET_SUCCESS; + break; + case ARM_SMCCC_ARCH_WORKAROUND_2: + switch (kvm_arm_have_ssbd()) { + case KVM_SSBD_FORCE_DISABLE: + case KVM_SSBD_UNKNOWN: + break; + case KVM_SSBD_KERNEL: + val = SMCCC_RET_SUCCESS; + break; + case KVM_SSBD_FORCE_ENABLE: + case KVM_SSBD_MITIGATED: + val = SMCCC_RET_NOT_REQUIRED; + break; + } + break; + } + break; + default: + return kvm_psci_call(vcpu); + } + + smccc_set_retval(vcpu, val, 0, 0, 0); + return 1; +} diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c index 9b73d3ad918a..4f24836cb8cd 100644 --- a/virt/kvm/arm/psci.c +++ b/virt/kvm/arm/psci.c @@ -26,6 +26,7 @@ #include #include +#include /* * This is an implementation of the Power State Coordination Interface @@ -34,38 +35,6 @@ #define AFFINITY_MASK(level) ~((0x1UL << ((level) * MPIDR_LEVEL_BITS)) - 1) -static u32 smccc_get_function(struct kvm_vcpu *vcpu) -{ - return vcpu_get_reg(vcpu, 0); -} - -static unsigned long smccc_get_arg1(struct kvm_vcpu *vcpu) -{ - return vcpu_get_reg(vcpu, 1); -} - -static unsigned long smccc_get_arg2(struct kvm_vcpu *vcpu) -{ - return vcpu_get_reg(vcpu, 2); -} - -static unsigned long smccc_get_arg3(struct kvm_vcpu *vcpu) -{ - return vcpu_get_reg(vcpu, 3); -} - -static void smccc_set_retval(struct kvm_vcpu *vcpu, - unsigned long a0, - unsigned long a1, - unsigned long a2, - unsigned long a3) -{ - vcpu_set_reg(vcpu, 0, a0); - vcpu_set_reg(vcpu, 1, a1); - vcpu_set_reg(vcpu, 2, a2); - vcpu_set_reg(vcpu, 3, a3); -} - static unsigned long psci_affinity_mask(unsigned long affinity_level) { if (affinity_level <= 3) @@ -388,7 +357,7 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu) * Errors: * -EINVAL: Unrecognized PSCI function */ -static int kvm_psci_call(struct kvm_vcpu *vcpu) +int kvm_psci_call(struct kvm_vcpu *vcpu) { switch (kvm_psci_version(vcpu, vcpu->kvm)) { case KVM_ARM_PSCI_1_0: @@ -402,47 +371,6 @@ static int kvm_psci_call(struct kvm_vcpu *vcpu) }; } -int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) -{ - u32 func_id = smccc_get_function(vcpu); - u32 val = SMCCC_RET_NOT_SUPPORTED; - u32 feature; - - switch (func_id) { - case ARM_SMCCC_VERSION_FUNC_ID: - val = ARM_SMCCC_VERSION_1_1; - break; - case ARM_SMCCC_ARCH_FEATURES_FUNC_ID: - feature = smccc_get_arg1(vcpu); - switch(feature) { - case ARM_SMCCC_ARCH_WORKAROUND_1: - if (kvm_arm_harden_branch_predictor()) - val = SMCCC_RET_SUCCESS; - break; - case ARM_SMCCC_ARCH_WORKAROUND_2: - switch (kvm_arm_have_ssbd()) { - case KVM_SSBD_FORCE_DISABLE: - case KVM_SSBD_UNKNOWN: - break; - case KVM_SSBD_KERNEL: - val = SMCCC_RET_SUCCESS; - break; - case KVM_SSBD_FORCE_ENABLE: - case KVM_SSBD_MITIGATED: - val = SMCCC_RET_NOT_REQUIRED; - break; - } - break; - } - break; - default: - return kvm_psci_call(vcpu); - } - - smccc_set_retval(vcpu, val, 0, 0, 0); - return 1; -} - int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu) { return 1; /* PSCI version */ From patchwork Wed Dec 12 15:02:17 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Price X-Patchwork-Id: 10726505 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id F35D514BD for ; Wed, 12 Dec 2018 15:04:06 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E0E7F2B14C for ; Wed, 12 Dec 2018 15:04:06 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D1B782B163; Wed, 12 Dec 2018 15:04:06 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id AB3F12B14C for ; Wed, 12 Dec 2018 15:04:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=MNLqBCA4QQPdAb4meCop71TjCpKJFxGuJzlrbrn0yPI=; b=qWMUSnzRojKJh6 mxb70jKuAeUJ92WYRaWAovroLlSpTYEM3QtI8u3MfnRbypAWp/hxmWKKez/P+wSIpSJzBkueK6v4l FTO0bQzJEfADe5PSXDDZF0M8icjn/ZNOoEuQeYb8GuXxW9x/AXauTOP7Ndv9FyoNkJKmOC53CHoTv whEXYWMtU2uF4giOMULRJKpYxpA4zMM4GhGH8/PGWBJefGw76V/4N/k/RVLYQadpYq8wBRUWmmKPl P5mezOeemTXaNVXRZZ4c1Cogm3v/j97oCeRowqWkP+YaHuKuryVXRTyLgFJSL0VlmhvkrUZx/+LdZ ldl1mDXX+PGdPL6RY6Rw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gX63M-0007SY-Fv; Wed, 12 Dec 2018 15:04:00 +0000 Received: from foss.arm.com ([217.140.101.70]) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gX62V-0006Ll-Ht for linux-arm-kernel@lists.infradead.org; Wed, 12 Dec 2018 15:03:13 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 4DFE3165C; Wed, 12 Dec 2018 07:03:04 -0800 (PST) Received: from e112269-lin.arm.com (e112269-lin.cambridge.arm.com [10.1.196.55]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id C7A9D3F59C; Wed, 12 Dec 2018 07:03:02 -0800 (PST) From: Steven Price To: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH v2 03/12] arm/arm64: Provide a wrapper for SMCCC 1.1 calls Date: Wed, 12 Dec 2018 15:02:17 +0000 Message-Id: <20181212150226.38051-4-steven.price@arm.com> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20181212150226.38051-1-steven.price@arm.com> References: <20181212150226.38051-1-steven.price@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181212_070307_796144_2CD9DEBF X-CRM114-Status: GOOD ( 13.71 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mark Rutland , Marc Zyngier , Catalin Marinas , Will Deacon , Christoffer Dall , Steven Price Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP SMCCC 1.1 calls may use either HVC or SMC depending on the PSCI conduit. Rather than coding this in every call site provide a macro which uses the correct instruction. The macro also handles the case where no PSCI conduit is configured returning a not supported error in res, along with returning the conduit used for the call. This allow us to remove some duplicated code and will be useful later when adding paravirtualized time hypervisor calls. Signed-off-by: Steven Price --- include/linux/arm-smccc.h | 44 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h index 18863d56273c..4d5ec5f10a51 100644 --- a/include/linux/arm-smccc.h +++ b/include/linux/arm-smccc.h @@ -311,5 +311,49 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1, #define SMCCC_RET_NOT_SUPPORTED -1 #define SMCCC_RET_NOT_REQUIRED -2 +/* Like arm_smccc_1_1* but always returns SMCCC_RET_NOT_SUPPORTED. + * Used when the PSCI conduit is not defined. The empty asm statement + * avoids compiler warnings about unused variables. + */ +#define __fail_smccc_1_1(...) \ + do { \ + __declare_args(__count_args(__VA_ARGS__), __VA_ARGS__); \ + asm ("" __constraints(__count_args(__VA_ARGS__))); \ + if (___res) \ + ___res->a0 = SMCCC_RET_NOT_SUPPORTED; \ + } while (0) + +/* + * arm_smccc_1_1_call() - make an SMCCC v1.1 compliant call + * + * This is a variadic macro taking one to eight source arguments, and + * an optional return structure. + * + * @a0-a7: arguments passed in registers 0 to 7 + * @res: result values from registers 0 to 3 + * + * This macro will make either an HVC call or an SMC call depending on the + * current PSCI conduit. If no valid conduit is available then -1 + * (SMCCC_RET_NOT_SUPPORTED) is returned in @res.a0 (if supplied). + * + * The return value also provides the conduit that was used. + */ +#define arm_smccc_1_1_call(...) ({ \ + int method = psci_ops.conduit; \ + switch (method) { \ + case PSCI_CONDUIT_HVC: \ + arm_smccc_1_1_hvc(__VA_ARGS__); \ + break; \ + case PSCI_CONDUIT_SMC: \ + arm_smccc_1_1_smc(__VA_ARGS__); \ + break; \ + default: \ + __fail_smccc_1_1(__VA_ARGS__); \ + method = PSCI_CONDUIT_NONE; \ + break; \ + } \ + method; \ + }) + #endif /*__ASSEMBLY__*/ #endif /*__LINUX_ARM_SMCCC_H*/ From patchwork Wed Dec 12 15:02:18 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Price X-Patchwork-Id: 10726513 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4B64316B1 for ; Wed, 12 Dec 2018 15:05:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 394222B164 for ; Wed, 12 Dec 2018 15:05:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2D4232B176; Wed, 12 Dec 2018 15:05:18 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 692212B173 for ; Wed, 12 Dec 2018 15:05:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=ehroeHfQNCbuQaUjDW5afwX7LXhMQf7wvw3rfPZYbLk=; b=SXVxFNqj0nTsDD 4ai9YXgAo2Zt73Dgols5QSgQ8R391ouTCKAYwAXfwSxvFkxhuwDpOG/BfvnisaFS8wrrOG/v3xkcm rRTdk3uPIn9hUtK66DvY135IlyJxMsTZin+sN1QyY4qw3SD91OptVWTecIaQ3Nfq0ZtI6MDjS0EN+ fWSTRnFED0gDhXQp3NFUnNiqmDWW47JBf/D3sv3QrXNTisXoXXtEDZ8bkFZP8/KLReD3Jk9h8GV4S MibhLL0O2EVz0aV+4f9kq9K4+7Rxz1m6/4mC+D5cd3olZzxp1E3cYiZiADFhOGquOCO5kfJgKuWRu X0cG+UbSLJsUcuCJmSkA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gX64X-0000dU-Tq; Wed, 12 Dec 2018 15:05:13 +0000 Received: from foss.arm.com ([217.140.101.70]) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gX62e-0006MR-FT for linux-arm-kernel@lists.infradead.org; Wed, 12 Dec 2018 15:03:31 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 12CCC1684; Wed, 12 Dec 2018 07:03:06 -0800 (PST) Received: from e112269-lin.arm.com (e112269-lin.cambridge.arm.com [10.1.196.55]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 8C6F93F59C; Wed, 12 Dec 2018 07:03:04 -0800 (PST) From: Steven Price To: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH v2 04/12] arm/arm64: Make use of the SMCCC 1.1 wrapper Date: Wed, 12 Dec 2018 15:02:18 +0000 Message-Id: <20181212150226.38051-5-steven.price@arm.com> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20181212150226.38051-1-steven.price@arm.com> References: <20181212150226.38051-1-steven.price@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181212_070317_154077_70E84AB9 X-CRM114-Status: GOOD ( 16.08 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mark Rutland , Marc Zyngier , Catalin Marinas , Will Deacon , Christoffer Dall , Steven Price Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Rather than directly choosing which function to use based on psci_ops.conduit, use the new arm_smccc_1_1 wrapper instead. In some cases we still need to do some operations based on the conduit, but the code duplication is removed. Signed-off-by: Steven Price --- arch/arm/mm/proc-v7-bugs.c | 46 +++++++++++++++------------------ arch/arm64/kernel/cpu_errata.c | 47 +++++++++------------------------- 2 files changed, 32 insertions(+), 61 deletions(-) diff --git a/arch/arm/mm/proc-v7-bugs.c b/arch/arm/mm/proc-v7-bugs.c index 5544b82a2e7a..a9c7474d3e39 100644 --- a/arch/arm/mm/proc-v7-bugs.c +++ b/arch/arm/mm/proc-v7-bugs.c @@ -78,39 +78,33 @@ static void cpu_v7_spectre_init(void) case ARM_CPU_PART_CORTEX_A57: case ARM_CPU_PART_CORTEX_A72: { struct arm_smccc_res res; + int conduit; if (psci_ops.smccc_version == SMCCC_VERSION_1_0) break; - switch (psci_ops.conduit) { - case PSCI_CONDUIT_HVC: - arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, - ARM_SMCCC_ARCH_WORKAROUND_1, &res); - if ((int)res.a0 != 0) - break; + conduit = arm_smccc_1_1_call(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, + ARM_SMCCC_ARCH_WORKAROUND_1, &res); + + if ((int)res.a0 == 0) { if (processor.switch_mm != cpu_v7_hvc_switch_mm && cpu) goto bl_error; - per_cpu(harden_branch_predictor_fn, cpu) = - call_hvc_arch_workaround_1; - processor.switch_mm = cpu_v7_hvc_switch_mm; - spectre_v2_method = "hypervisor"; - break; - - case PSCI_CONDUIT_SMC: - arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, - ARM_SMCCC_ARCH_WORKAROUND_1, &res); - if ((int)res.a0 != 0) + switch (conduit) { + case PSCI_CONDUIT_HVC: + per_cpu(harden_branch_predictor_fn, cpu) = + call_hvc_arch_workaround_1; + processor.switch_mm = cpu_v7_hvc_switch_mm; + spectre_v2_method = "hypervisor"; break; - if (processor.switch_mm != cpu_v7_smc_switch_mm && cpu) - goto bl_error; - per_cpu(harden_branch_predictor_fn, cpu) = - call_smc_arch_workaround_1; - processor.switch_mm = cpu_v7_smc_switch_mm; - spectre_v2_method = "firmware"; - break; - - default: - break; + case PSCI_CONDUIT_SMC: + per_cpu(harden_branch_predictor_fn, cpu) = + call_smc_arch_workaround_1; + processor.switch_mm = cpu_v7_smc_switch_mm; + spectre_v2_method = "firmware"; + break; + default: + break; + } } } #endif diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index a509e35132d2..fee09ee52ec8 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -234,12 +234,14 @@ enable_smccc_arch_workaround_1(const struct arm64_cpu_capabilities *entry) if (psci_ops.smccc_version == SMCCC_VERSION_1_0) return; + arm_smccc_1_1_call(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, + ARM_SMCCC_ARCH_WORKAROUND_1, &res); + + if ((int)res.a0 < 0) + return; + switch (psci_ops.conduit) { case PSCI_CONDUIT_HVC: - arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, - ARM_SMCCC_ARCH_WORKAROUND_1, &res); - if ((int)res.a0 < 0) - return; cb = call_hvc_arch_workaround_1; /* This is a guest, no need to patch KVM vectors */ smccc_start = NULL; @@ -247,10 +249,6 @@ enable_smccc_arch_workaround_1(const struct arm64_cpu_capabilities *entry) break; case PSCI_CONDUIT_SMC: - arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, - ARM_SMCCC_ARCH_WORKAROUND_1, &res); - if ((int)res.a0 < 0) - return; cb = call_smc_arch_workaround_1; smccc_start = __smccc_workaround_1_smc_start; smccc_end = __smccc_workaround_1_smc_end; @@ -343,6 +341,8 @@ void __init arm64_enable_wa2_handling(struct alt_instr *alt, void arm64_set_ssbd_mitigation(bool state) { + int conduit; + if (this_cpu_has_cap(ARM64_SSBS)) { if (state) asm volatile(SET_PSTATE_SSBS(0)); @@ -351,19 +351,9 @@ void arm64_set_ssbd_mitigation(bool state) return; } - switch (psci_ops.conduit) { - case PSCI_CONDUIT_HVC: - arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_2, state, NULL); - break; - - case PSCI_CONDUIT_SMC: - arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2, state, NULL); - break; + conduit = arm_smccc_1_1_call(ARM_SMCCC_ARCH_WORKAROUND_2, state, NULL); - default: - WARN_ON_ONCE(1); - break; - } + WARN_ON_ONCE(conduit == PSCI_CONDUIT_NONE); } static bool has_ssbd_mitigation(const struct arm64_cpu_capabilities *entry, @@ -385,21 +375,8 @@ static bool has_ssbd_mitigation(const struct arm64_cpu_capabilities *entry, return false; } - switch (psci_ops.conduit) { - case PSCI_CONDUIT_HVC: - arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, - ARM_SMCCC_ARCH_WORKAROUND_2, &res); - break; - - case PSCI_CONDUIT_SMC: - arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, - ARM_SMCCC_ARCH_WORKAROUND_2, &res); - break; - - default: - ssbd_state = ARM64_SSBD_UNKNOWN; - return false; - } + arm_smccc_1_1_call(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, + ARM_SMCCC_ARCH_WORKAROUND_2, &res); val = (s32)res.a0; From patchwork Wed Dec 12 15:02:19 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Price X-Patchwork-Id: 10726517 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A75BF91E for ; Wed, 12 Dec 2018 15:05:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 96E842B164 for ; Wed, 12 Dec 2018 15:05:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8B5972B176; Wed, 12 Dec 2018 15:05:50 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 007C12B164 for ; Wed, 12 Dec 2018 15:05:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=L7/xspgfakw7s/dMvN/n5pudWGSE8737AdiZA/vG5XY=; b=t162WNjHOn+SPS e4QnbyPrreRipmDgT0aJnxIsvkJRfPHR/ffzkA8QYitJGfHqq60gv1qwxjszXUnVvXOTUXzk2xw9X iqldYcQvOw19M0c/869IFsEaXMMAdrXf80kT2PtO+tudaaAOWcXD1zN1OS1J0VB918V2D8tr5Y906 ethHDkquWnKB30sMiVEi+z9n1EkqJTmh9pcifSXP0Lsq1d2+n1ivDSMOEU7EpMVQ6zDg4vPE1FAUU vsb41tdEdR+RO8t8jBifV6VnFNQG1dd8v4bnZHHjQ7N/DxO5RrVECpK0AKht8xN6eY9G5p6MyiPaC q5velGPmBqgzQboIYjww==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gX655-0001vL-9h; Wed, 12 Dec 2018 15:05:47 +0000 Received: from foss.arm.com ([217.140.101.70]) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gX62e-0006OL-FU for linux-arm-kernel@lists.infradead.org; Wed, 12 Dec 2018 15:03:32 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id CB1C61688; Wed, 12 Dec 2018 07:03:07 -0800 (PST) Received: from e112269-lin.arm.com (e112269-lin.cambridge.arm.com [10.1.196.55]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 50EF23F59C; Wed, 12 Dec 2018 07:03:06 -0800 (PST) From: Steven Price To: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH v2 05/12] KVM: arm64: Implement PV_FEATURES call Date: Wed, 12 Dec 2018 15:02:19 +0000 Message-Id: <20181212150226.38051-6-steven.price@arm.com> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20181212150226.38051-1-steven.price@arm.com> References: <20181212150226.38051-1-steven.price@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181212_070317_813454_7CCE1F1F X-CRM114-Status: GOOD ( 15.75 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mark Rutland , Marc Zyngier , Catalin Marinas , Will Deacon , Christoffer Dall , Steven Price Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP This provides a mechanism for querying which paravirtualized features are available in this hypervisor. Also add the header file which defines the ABI for the paravirtualized clock features we're about to add. Signed-off-by: Steven Price --- arch/arm64/include/asm/pvclock-abi.h | 32 ++++++++++++++++++++++++++++ include/linux/arm-smccc.h | 20 +++++++++++++++++ virt/kvm/arm/hypercalls.c | 9 ++++++++ 3 files changed, 61 insertions(+) create mode 100644 arch/arm64/include/asm/pvclock-abi.h diff --git a/arch/arm64/include/asm/pvclock-abi.h b/arch/arm64/include/asm/pvclock-abi.h new file mode 100644 index 000000000000..4f710dec6592 --- /dev/null +++ b/arch/arm64/include/asm/pvclock-abi.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (C) 2018 Arm Ltd. */ + +#ifndef __ASM_PVCLOCK_ABI_H +#define __ASM_PVCLOCK_ABI_H + +/* The below structures and constants are defined in ARM DEN0057A */ + +struct pvclock_vm_time_info { + __le32 revision; + __le32 attributes; + __le64 sequence_number; + __le64 scale_mult; + __le32 shift; + __le32 reserved; + __le64 native_freq; + __le64 pv_freq; + __le64 div_by_pv_freq_mult; +} __packed; + +struct pvclock_vcpu_stolen_time_info { + __le32 revision; + __le32 attributes; + __le64 stolen_time; + /* Structure must be 64 byte aligned, pad to that size */ + u8 padding[48]; +} __packed; + +#define PV_VM_TIME_NOT_SUPPORTED -1 +#define PV_VM_TIME_INVALID_PARAMETERS -2 + +#endif diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h index 4d5ec5f10a51..12e88e1ba222 100644 --- a/include/linux/arm-smccc.h +++ b/include/linux/arm-smccc.h @@ -54,6 +54,7 @@ #define ARM_SMCCC_OWNER_SIP 2 #define ARM_SMCCC_OWNER_OEM 3 #define ARM_SMCCC_OWNER_STANDARD 4 +#define ARM_SMCCC_OWNER_STANDARD_HYP 5 #define ARM_SMCCC_OWNER_TRUSTED_APP 48 #define ARM_SMCCC_OWNER_TRUSTED_APP_END 49 #define ARM_SMCCC_OWNER_TRUSTED_OS 50 @@ -355,5 +356,24 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1, method; \ }) +/* Paravirtualised time calls (defined by ARM DEN0057A) */ +#define ARM_SMCCC_HV_PV_FEATURES \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_64, \ + ARM_SMCCC_OWNER_STANDARD_HYP, \ + 0x20) + +#define ARM_SMCCC_HV_PV_TIME_LPT \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_64, \ + ARM_SMCCC_OWNER_STANDARD_HYP, \ + 0x21) + +#define ARM_SMCCC_HV_PV_TIME_ST \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_64, \ + ARM_SMCCC_OWNER_STANDARD_HYP, \ + 0x22) + #endif /*__ASSEMBLY__*/ #endif /*__LINUX_ARM_SMCCC_H*/ diff --git a/virt/kvm/arm/hypercalls.c b/virt/kvm/arm/hypercalls.c index 153aa7642100..ba13b798f0f8 100644 --- a/virt/kvm/arm/hypercalls.c +++ b/virt/kvm/arm/hypercalls.c @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -40,6 +41,14 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) break; } break; + case ARM_SMCCC_HV_PV_FEATURES: + val = SMCCC_RET_SUCCESS; + break; + } + break; + case ARM_SMCCC_HV_PV_FEATURES: + feature = smccc_get_arg1(vcpu); + switch (feature) { } break; default: From patchwork Wed Dec 12 15:02:20 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Price X-Patchwork-Id: 10726515 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7009414BD for ; Wed, 12 Dec 2018 15:05:39 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5A5112B164 for ; Wed, 12 Dec 2018 15:05:39 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4C40D2B176; Wed, 12 Dec 2018 15:05:39 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id AB4692B164 for ; Wed, 12 Dec 2018 15:05:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=+mJVQEqaYtIcFdtWnQcAwTwInO70U3xJL+TLbTfO910=; b=lp+rWqj84DuoHm DTQDZJRyVT2sebKaY9pPql/QzJxPduqQ9PqPfiWqSidC5M+vG1ObAZmB3oCCvqkvgP2RqT/pfg22G n04pOyV0n3UoAv/OCRtGnUpLjYFJFM+yEIuNblJKg3UrJkkPwnpf7r87luFwmQ/OAavVQyR8w7ByO N15qH9TWz2X9AtpjV+o7TYyI/1XqZl8DzLwJ210jAn6sdxoKY5DiCCw3Dmlm+IsYyUpzq4c1sBkze 1s/hlMYOhmf7YRxPXAnTs3QQ9E8LqChMHCxk/NPJd5+gs9QtnzUmelEd6ghem5AKAiaYlm+0bNr22 9iqACpaZlSctnugum6JQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gX64m-0001dY-Ax; Wed, 12 Dec 2018 15:05:28 +0000 Received: from usa-sjc-mx-foss1.foss.arm.com ([217.140.101.70] helo=foss.arm.com) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gX62e-0006QK-FR for linux-arm-kernel@lists.infradead.org; Wed, 12 Dec 2018 15:03:30 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 8FB6D80D; Wed, 12 Dec 2018 07:03:09 -0800 (PST) Received: from e112269-lin.arm.com (e112269-lin.cambridge.arm.com [10.1.196.55]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 157063F59C; Wed, 12 Dec 2018 07:03:07 -0800 (PST) From: Steven Price To: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH v2 06/12] KVM: arm64: Support stolen time reporting via shared structure Date: Wed, 12 Dec 2018 15:02:20 +0000 Message-Id: <20181212150226.38051-7-steven.price@arm.com> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20181212150226.38051-1-steven.price@arm.com> References: <20181212150226.38051-1-steven.price@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181212_070317_211012_13982398 X-CRM114-Status: GOOD ( 21.22 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mark Rutland , Marc Zyngier , Catalin Marinas , Will Deacon , Christoffer Dall , Steven Price Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Implement the service call for configuring a shared structre between a VCPU and the hypervisor in which the hypervisor can write the time stolen from the VCPU's execution time by other tasks on the host. The hypervisor allocates memory which is placed at an IPA chosen by user space. The hypervisor then uses WRITE_ONCE() to update the shared structre ensuring single copy atomicity of the 64-bit unsigned value that reports stolen time in nanoseconds. Whenever stolen time is enabled by the guest, the stolen time counter is reset. The stolen time itself is retrieved from the sched_info structure maintained by the Linux scheduler code. We enable SCHEDSTATS when selecting KVM Kconfig to ensure this value is meaningful. Signed-off-by: Steven Price --- arch/arm64/include/asm/kvm_host.h | 12 ++++++ arch/arm64/kvm/Kconfig | 1 + include/kvm/arm_hypercalls.h | 1 + include/linux/kvm_types.h | 2 + virt/kvm/arm/arm.c | 20 ++++++++- virt/kvm/arm/hypercalls.c | 70 +++++++++++++++++++++++++++++++ 6 files changed, 104 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 52fbc823ff8c..bab7bc720992 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -48,6 +48,7 @@ #define KVM_REQ_SLEEP \ KVM_ARCH_REQ_FLAGS(0, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP) #define KVM_REQ_IRQ_PENDING KVM_ARCH_REQ(1) +#define KVM_REQ_RECORD_STEAL KVM_ARCH_REQ(2) DECLARE_STATIC_KEY_FALSE(userspace_irqchip_in_use); @@ -80,6 +81,11 @@ struct kvm_arch { /* Mandated version of PSCI */ u32 psci_version; + + struct kvm_arch_pvtime { + void *st; + gpa_t st_base; + } pvtime; }; #define KVM_NR_MEM_OBJS 40 @@ -300,6 +306,12 @@ struct kvm_vcpu_arch { /* True when deferrable sysregs are loaded on the physical CPU, * see kvm_vcpu_load_sysregs and kvm_vcpu_put_sysregs. */ bool sysregs_loaded_on_cpu; + + /* Guest PV state */ + struct { + u64 steal; + u64 last_steal; + } steal; }; /* vcpu_arch flags field values: */ diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig index 47b23bf617c7..92676920d671 100644 --- a/arch/arm64/kvm/Kconfig +++ b/arch/arm64/kvm/Kconfig @@ -40,6 +40,7 @@ config KVM select IRQ_BYPASS_MANAGER select HAVE_KVM_IRQ_BYPASS select HAVE_KVM_VCPU_RUN_PID_CHANGE + select SCHEDSTATS ---help--- Support hosting virtualized guest machines. We don't support KVM with 16K page tables yet, due to the multiple diff --git a/include/kvm/arm_hypercalls.h b/include/kvm/arm_hypercalls.h index e5f7f81196b6..2e03e993ad64 100644 --- a/include/kvm/arm_hypercalls.h +++ b/include/kvm/arm_hypercalls.h @@ -7,6 +7,7 @@ #include int kvm_hvc_call_handler(struct kvm_vcpu *vcpu); +int kvm_update_stolen_time(struct kvm_vcpu *vcpu); static inline u32 smccc_get_function(struct kvm_vcpu *vcpu) { diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h index 8bf259dae9f6..ff0e314c7dcd 100644 --- a/include/linux/kvm_types.h +++ b/include/linux/kvm_types.h @@ -49,6 +49,8 @@ typedef unsigned long gva_t; typedef u64 gpa_t; typedef u64 gfn_t; +#define GPA_INVALID (~(gpa_t)0) + typedef unsigned long hva_t; typedef u64 hpa_t; typedef u64 hfn_t; diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c index 23774970c9df..b347ba38cb11 100644 --- a/virt/kvm/arm/arm.c +++ b/virt/kvm/arm/arm.c @@ -32,8 +32,6 @@ #include #include #include -#include -#include #define CREATE_TRACE_POINTS #include "trace.h" @@ -52,6 +50,10 @@ #include #include +#include +#include +#include + #ifdef REQUIRES_VIRT __asm__(".arch_extension virt"); #endif @@ -148,6 +150,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) kvm->arch.max_vcpus = vgic_present ? kvm_vgic_get_max_vcpus() : KVM_MAX_VCPUS; + kvm->arch.pvtime.st_base = GPA_INVALID; return ret; out_free_stage2_pgd: kvm_free_stage2_pgd(kvm); @@ -383,6 +386,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) kvm_timer_vcpu_load(vcpu); kvm_vcpu_load_sysregs(vcpu); kvm_arch_vcpu_load_fp(vcpu); + kvm_make_request(KVM_REQ_RECORD_STEAL, vcpu); if (single_task_running()) vcpu_clear_wfe_traps(vcpu); @@ -629,6 +633,15 @@ static void vcpu_req_sleep(struct kvm_vcpu *vcpu) } } +static void vcpu_req_record_steal(struct kvm_vcpu *vcpu) +{ + int idx; + + idx = srcu_read_lock(&vcpu->kvm->srcu); + kvm_update_stolen_time(vcpu); + srcu_read_unlock(&vcpu->kvm->srcu, idx); +} + static int kvm_vcpu_initialized(struct kvm_vcpu *vcpu) { return vcpu->arch.target >= 0; @@ -645,6 +658,9 @@ static void check_vcpu_requests(struct kvm_vcpu *vcpu) * that a VCPU sees new virtual interrupts. */ kvm_check_request(KVM_REQ_IRQ_PENDING, vcpu); + + if (kvm_check_request(KVM_REQ_RECORD_STEAL, vcpu)) + vcpu_req_record_steal(vcpu); } } diff --git a/virt/kvm/arm/hypercalls.c b/virt/kvm/arm/hypercalls.c index ba13b798f0f8..595d1cf3a871 100644 --- a/virt/kvm/arm/hypercalls.c +++ b/virt/kvm/arm/hypercalls.c @@ -10,6 +10,70 @@ #include #include + +static struct pvclock_vcpu_stolen_time_info *pvtime_get_st( + struct kvm_vcpu *vcpu) +{ + struct pvclock_vcpu_stolen_time_info *st = vcpu->kvm->arch.pvtime.st; + + if (!st) + return NULL; + + return &st[kvm_vcpu_get_idx(vcpu)]; +} + +int kvm_update_stolen_time(struct kvm_vcpu *vcpu) +{ + u64 steal; + struct pvclock_vcpu_stolen_time_info *kaddr; + + if (vcpu->kvm->arch.pvtime.st_base == GPA_INVALID) + return -ENOTSUPP; + + kaddr = pvtime_get_st(vcpu); + + if (!kaddr) + return -ENOTSUPP; + + kaddr->revision = 0; + kaddr->attributes = 0; + + /* Let's do the local bookkeeping */ + steal = vcpu->arch.steal.steal; + steal += current->sched_info.run_delay - vcpu->arch.steal.last_steal; + vcpu->arch.steal.last_steal = current->sched_info.run_delay; + vcpu->arch.steal.steal = steal; + + /* Now write out the value to the shared page */ + WRITE_ONCE(kaddr->stolen_time, cpu_to_le64(steal)); + + return 0; +} + +static int kvm_hypercall_stolen_time(struct kvm_vcpu *vcpu) +{ + u64 ret; + int err; + + /* + * Start counting stolen time from the time the guest requests + * the feature enabled. + */ + vcpu->arch.steal.steal = 0; + vcpu->arch.steal.last_steal = current->sched_info.run_delay; + + err = kvm_update_stolen_time(vcpu); + + if (err) + ret = SMCCC_RET_NOT_SUPPORTED; + else + ret = vcpu->kvm->arch.pvtime.st_base + + (sizeof(struct pvclock_vcpu_stolen_time_info) * + kvm_vcpu_get_idx(vcpu)); + + smccc_set_retval(vcpu, ret, 0, 0, 0); + return 1; +} int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) { u32 func_id = smccc_get_function(vcpu); @@ -49,8 +113,14 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) case ARM_SMCCC_HV_PV_FEATURES: feature = smccc_get_arg1(vcpu); switch (feature) { + case ARM_SMCCC_HV_PV_FEATURES: + case ARM_SMCCC_HV_PV_TIME_ST: + val = SMCCC_RET_SUCCESS; + break; } break; + case ARM_SMCCC_HV_PV_TIME_ST: + return kvm_hypercall_stolen_time(vcpu); default: return kvm_psci_call(vcpu); } From patchwork Wed Dec 12 15:02:21 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Price X-Patchwork-Id: 10726507 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6370514BD for ; Wed, 12 Dec 2018 15:04:20 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 524AD2B173 for ; Wed, 12 Dec 2018 15:04:20 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 466672B176; Wed, 12 Dec 2018 15:04:20 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id C001E2B173 for ; Wed, 12 Dec 2018 15:04:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=14oEP2cbdkprftreDAishbg96W+vw9XdCin2QBLiU8E=; b=kXvbCVsTaYxT0p +8whitIt2sU3MWXwvWpYCklTVxKUst3Dj+H4NdDqmzVWPFb2pli/Qdr1QsSzufN31FmzPgNkpf+hT 1LS/DNZd+pFqYySicQBDWxUp5+AXDibmporrs4Xq7BKQjfph66cV6L2zvVAyAGz3x9tVZKgMylghz NOmHBUzKyjXHtI6yWopftdQBFGvQ2NCe/yWgz9NgbadATp5nDYMotaP0X9cks/cQBl9Jqyx0I++qM /+labm9ggcHPytrsYn4DVkEXRxGwKGmxHknLr0AOOJKUdFks3yN/xwS4vj7kTxWYqNjNk9ikbb1Xx L/FYHiVZEUFA1U8SGbmg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gX63f-0007ld-6T; Wed, 12 Dec 2018 15:04:19 +0000 Received: from usa-sjc-mx-foss1.foss.arm.com ([217.140.101.70] helo=foss.arm.com) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gX62e-0006Rk-Fb for linux-arm-kernel@lists.infradead.org; Wed, 12 Dec 2018 15:03:28 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 54210EBD; Wed, 12 Dec 2018 07:03:11 -0800 (PST) Received: from e112269-lin.arm.com (e112269-lin.cambridge.arm.com [10.1.196.55]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id CE0FA3F59C; Wed, 12 Dec 2018 07:03:09 -0800 (PST) From: Steven Price To: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH v2 07/12] arm64: Retrieve stolen time as paravirtualized guest Date: Wed, 12 Dec 2018 15:02:21 +0000 Message-Id: <20181212150226.38051-8-steven.price@arm.com> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20181212150226.38051-1-steven.price@arm.com> References: <20181212150226.38051-1-steven.price@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181212_070317_022401_15D6129E X-CRM114-Status: GOOD ( 19.72 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mark Rutland , Marc Zyngier , Catalin Marinas , Will Deacon , Christoffer Dall , Steven Price Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Enable paravirtualization features when running under a hypervisor supporting the PV_TIME_ST hypercall. For each (v)CPU, we ask the hypervisor for the location of a shared page which the hypervisor will use to report stolen time to us. We set pv_time_ops to the stolen time function which simply reads the stolen value from the shared page for a VCPU. We guarantee single-copy atomicity using READ_ONCE which means we can also read the stolen time for another VCPU than the currently running one while it is potentially being updated by the hypervisor. Signed-off-by: Steven Price --- arch/arm64/kernel/Makefile | 1 + arch/arm64/kernel/kvm.c | 156 +++++++++++++++++++++++++++++++++++++ include/linux/cpuhotplug.h | 1 + 3 files changed, 158 insertions(+) create mode 100644 arch/arm64/kernel/kvm.c diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index 4c8b13bede80..daaed14ed7a4 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -57,6 +57,7 @@ arm64-obj-$(CONFIG_CRASH_DUMP) += crash_dump.o arm64-obj-$(CONFIG_CRASH_CORE) += crash_core.o arm64-obj-$(CONFIG_ARM_SDE_INTERFACE) += sdei.o arm64-obj-$(CONFIG_ARM64_SSBD) += ssbd.o +arm64-obj-$(CONFIG_PARAVIRT) += kvm.o obj-y += $(arm64-obj-y) vdso/ probes/ obj-m += $(arm64-obj-m) diff --git a/arch/arm64/kernel/kvm.c b/arch/arm64/kernel/kvm.c new file mode 100644 index 000000000000..f7bc1f069dc0 --- /dev/null +++ b/arch/arm64/kernel/kvm.c @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Arm Ltd. + +#define pr_fmt(fmt) "kvmarm-pv: " fmt + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +struct kvmarm_stolen_time_region { + struct pvclock_vcpu_stolen_time_info *kaddr; +}; + +static DEFINE_PER_CPU(struct kvmarm_stolen_time_region, stolen_time_region); + +static bool steal_acc = true; +static int __init parse_no_stealacc(char *arg) +{ + steal_acc = false; + return 0; +} +early_param("no-steal-acc", parse_no_stealacc); + +/* return stolen time in ns by asking the hypervisor */ +static u64 kvm_steal_clock(int cpu) +{ + struct kvmarm_stolen_time_region *reg; + + reg = per_cpu_ptr(&stolen_time_region, cpu); + if (!reg->kaddr) { + pr_warn_once("stolen time enabled but not configued for cpu %d\n", + cpu); + return 0; + } + + return le64_to_cpu(READ_ONCE(reg->kaddr->stolen_time)); +} + +static int disable_stolen_time_current_cpu(void) +{ + struct kvmarm_stolen_time_region *reg; + + reg = this_cpu_ptr(&stolen_time_region); + if (!reg->kaddr) + return 0; + + memunmap(reg->kaddr); + memset(reg, 0, sizeof(*reg)); + + return 0; +} + +static int stolen_time_dying_cpu(unsigned int cpu) +{ + return disable_stolen_time_current_cpu(); +} + +static int init_stolen_time_cpu(unsigned int cpu) +{ + struct kvmarm_stolen_time_region *reg; + int ret; + struct arm_smccc_res res; + + reg = this_cpu_ptr(&stolen_time_region); + + if (reg->kaddr) + return 0; + + ret = arm_smccc_1_1_call(ARM_SMCCC_HV_PV_TIME_ST, &res); + + if ((long)res.a0 < 0) + return -EINVAL; + + reg->kaddr = memremap(res.a0, + sizeof(struct pvclock_vcpu_stolen_time_info), + MEMREMAP_WB); + + if (reg->kaddr == NULL) { + pr_warn("Failed to map stolen time data structure\n"); + return -EINVAL; + } + + if (le32_to_cpu(reg->kaddr->revision) != 0 || + le32_to_cpu(reg->kaddr->attributes) != 0) { + pr_warn("Unexpected revision or attributes in stolen time data\n"); + return -ENXIO; + } + + return 0; +} + +static int kvm_arm_init_stolen_time(void) +{ + int ret; + + ret = cpuhp_setup_state(CPUHP_AP_ARM_KVMPV_STARTING, + "hypervisor/kvmarm/pv:starting", + init_stolen_time_cpu, stolen_time_dying_cpu); + if (ret < 0) + return ret; + return 0; +} + +static bool has_kvm_steal_clock(void) +{ + struct arm_smccc_res res; + + /* To detect the presence of PV time support we require SMCCC 1.1+ */ + if (psci_ops.smccc_version < SMCCC_VERSION_1_1) + return false; + + arm_smccc_1_1_call(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, + ARM_SMCCC_HV_PV_FEATURES, &res); + + if (res.a0 != SMCCC_RET_SUCCESS) + return false; + + arm_smccc_1_1_call(ARM_SMCCC_HV_PV_FEATURES, + ARM_SMCCC_HV_PV_TIME_ST, &res); + + if (res.a0 != SMCCC_RET_SUCCESS) + return false; + + return true; +} + +static int __init kvm_guest_init(void) +{ + int ret = 0; + + if (!has_kvm_steal_clock()) + return 0; + + ret = kvm_arm_init_stolen_time(); + if (ret) + return ret; + + pv_ops.time.steal_clock = kvm_steal_clock; + + static_key_slow_inc(¶virt_steal_enabled); + if (steal_acc) + static_key_slow_inc(¶virt_steal_rq_enabled); + + pr_info("using stolen time PV\n"); + + return 0; +} +early_initcall(kvm_guest_init); diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index e0cd2baa8380..5c176a31deb8 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h @@ -134,6 +134,7 @@ enum cpuhp_state { /* Must be the last timer callback */ CPUHP_AP_DUMMY_TIMER_STARTING, CPUHP_AP_ARM_XEN_STARTING, + CPUHP_AP_ARM_KVMPV_STARTING, CPUHP_AP_ARM_CORESIGHT_STARTING, CPUHP_AP_ARM64_ISNDEP_STARTING, CPUHP_AP_SMPCFD_DYING, From patchwork Wed Dec 12 15:02:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Price X-Patchwork-Id: 10726509 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 852DA91E for ; Wed, 12 Dec 2018 15:04:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7439C2B176 for ; Wed, 12 Dec 2018 15:04:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6893E2B185; Wed, 12 Dec 2018 15:04:44 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 698472B176 for ; Wed, 12 Dec 2018 15:04:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=Vz9epkGh2kBjag0x0BC7gz4DIIIvkCk6llPcbQFN9AM=; b=SdrBkj53qy/4Zd Mf87WDNBw8btq4+YR2Fs+VONerYvxXXSMW4k3UZJdpiw1n6hv+fG/BGH5CRvFK9IPfEor5Mtj/O9C yDCiaKx/HmsnP2c87wZhvr63/GQqyB1soRODf/sl8bF2t/x+kOBqGV2bKHoBOk0/PMe5GeUyLAfJs Lh/i7ChCg3eDIh+VjUyGZmNmv9AFiu4m4Yk20yKuma1m9faEDUrLTEFHFW0qbrJbb7gDKgVhZ5oFU DevdSp5xuMUlvALxPlY4hUqANNkFwnPoK5UE4ZfaKnLkyoWNrV3keVRbPpRxvFH5WmZQTkqPQB+4E bTUZQvy16PFFvTh/3p8Q==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gX640-000843-U7; Wed, 12 Dec 2018 15:04:40 +0000 Received: from usa-sjc-mx-foss1.foss.arm.com ([217.140.101.70] helo=foss.arm.com) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gX62e-0006U4-FW for linux-arm-kernel@lists.infradead.org; Wed, 12 Dec 2018 15:03:29 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 197291596; Wed, 12 Dec 2018 07:03:13 -0800 (PST) Received: from e112269-lin.arm.com (e112269-lin.cambridge.arm.com [10.1.196.55]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 9291B3F59C; Wed, 12 Dec 2018 07:03:11 -0800 (PST) From: Steven Price To: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH v2 08/12] KVM: Allow kvm_device_ops to be const Date: Wed, 12 Dec 2018 15:02:22 +0000 Message-Id: <20181212150226.38051-9-steven.price@arm.com> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20181212150226.38051-1-steven.price@arm.com> References: <20181212150226.38051-1-steven.price@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181212_070317_502022_5CA52D8A X-CRM114-Status: GOOD ( 14.10 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mark Rutland , Marc Zyngier , Catalin Marinas , Will Deacon , Christoffer Dall , Steven Price Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Currently a kvm_device_ops structure cannot be const without triggering compiler warnings. However the structure doesn't need to be written to and, by marking it const, it can be read-only in memory. Add some more const keywords to allow this. Signed-off-by: Steven Price --- include/linux/kvm_host.h | 4 ++-- virt/kvm/kvm_main.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index c926698040e0..e87e4bae3a63 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -1177,7 +1177,7 @@ extern unsigned int halt_poll_ns_grow; extern unsigned int halt_poll_ns_shrink; struct kvm_device { - struct kvm_device_ops *ops; + const struct kvm_device_ops *ops; struct kvm *kvm; void *private; struct list_head vm_node; @@ -1220,7 +1220,7 @@ struct kvm_device_ops { void kvm_device_get(struct kvm_device *dev); void kvm_device_put(struct kvm_device *dev); struct kvm_device *kvm_device_from_filp(struct file *filp); -int kvm_register_device_ops(struct kvm_device_ops *ops, u32 type); +int kvm_register_device_ops(const struct kvm_device_ops *ops, u32 type); void kvm_unregister_device_ops(u32 type); extern struct kvm_device_ops kvm_mpic_ops; diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 2679e476b6c3..d2aebea09fe9 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -2855,14 +2855,14 @@ struct kvm_device *kvm_device_from_filp(struct file *filp) return filp->private_data; } -static struct kvm_device_ops *kvm_device_ops_table[KVM_DEV_TYPE_MAX] = { +static const struct kvm_device_ops *kvm_device_ops_table[KVM_DEV_TYPE_MAX] = { #ifdef CONFIG_KVM_MPIC [KVM_DEV_TYPE_FSL_MPIC_20] = &kvm_mpic_ops, [KVM_DEV_TYPE_FSL_MPIC_42] = &kvm_mpic_ops, #endif }; -int kvm_register_device_ops(struct kvm_device_ops *ops, u32 type) +int kvm_register_device_ops(const struct kvm_device_ops *ops, u32 type) { if (type >= ARRAY_SIZE(kvm_device_ops_table)) return -ENOSPC; @@ -2883,7 +2883,7 @@ void kvm_unregister_device_ops(u32 type) static int kvm_ioctl_create_device(struct kvm *kvm, struct kvm_create_device *cd) { - struct kvm_device_ops *ops = NULL; + const struct kvm_device_ops *ops = NULL; struct kvm_device *dev; bool test = cd->flags & KVM_CREATE_DEVICE_TEST; int ret; From patchwork Wed Dec 12 15:02:23 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Price X-Patchwork-Id: 10726511 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A89BD91E for ; Wed, 12 Dec 2018 15:05:02 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 91C362B176 for ; Wed, 12 Dec 2018 15:05:02 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7F40D2B185; Wed, 12 Dec 2018 15:05:02 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id A7B4B2B176 for ; Wed, 12 Dec 2018 15:05:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=d3RxlXCg7+up6WYXYOpXTjr2IkIemdXczKNsxEN+aDg=; b=SsAIZc2RQXOjHe WXv7M1pYlwunlsvRXpzlZ5a4OFx622k3W8F/ArMrhyYo8Nk9R7brK336pkZGEhoEGaqtMKtQDUmjO jSREFEUqv1B7FggTGwhmvnvGaYd8D4OEwIUmK5IiyhGwjlpIFW3uT9GVvyE0nM4fcLAKs47Akjk0s mJbgHAx72LiOhzMFUGQSvpkNCXKvXYdHHTm7jC2ebITAgxy/VHeBZT23jAfrfUbAR09s9ZBQjatgK dTNGrG358OCIn7Pa+4AY8Cs1cUv5tSTxiPaaAf5mGdsz6xCVbNHZ20gyYbKrsj67FX3bjdPXaXCDX 7LgqoTE5aI6KZp25JS6Q==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gX64D-0008Eu-OI; Wed, 12 Dec 2018 15:04:53 +0000 Received: from usa-sjc-mx-foss1.foss.arm.com ([217.140.101.70] helo=foss.arm.com) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gX62e-0006W0-Fa for linux-arm-kernel@lists.infradead.org; Wed, 12 Dec 2018 15:03:29 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id D270015AB; Wed, 12 Dec 2018 07:03:14 -0800 (PST) Received: from e112269-lin.arm.com (e112269-lin.cambridge.arm.com [10.1.196.55]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 5793A3F59C; Wed, 12 Dec 2018 07:03:13 -0800 (PST) From: Steven Price To: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH v2 09/12] KVM: arm64: Provide a PV_TIME device to user space Date: Wed, 12 Dec 2018 15:02:23 +0000 Message-Id: <20181212150226.38051-10-steven.price@arm.com> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20181212150226.38051-1-steven.price@arm.com> References: <20181212150226.38051-1-steven.price@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181212_070317_501813_C33578A6 X-CRM114-Status: GOOD ( 23.74 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mark Rutland , Marc Zyngier , Catalin Marinas , Will Deacon , Christoffer Dall , Steven Price Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Allow user space to inform the KVM host where in the physical memory map the paravirtualized time structures should be located. A single device is created which provides two base addresses. One is the base of the Live Physical Time (LPT) structure shared with the guest. This must be 64 bytes long. The other is the base of an array of Stolen Time (ST) structures, one for each VCPU. There must be (64 * total number of VCPUs) bytes of memory available at this location. The addresses are given in terms of the physical address visible to the guest and must be 64 byte aligned. The memory should be marked as reserved to the guest to stop it allocating it for other purposes. A method is also provided to change the paravirtualized clock frequency seen by a guest. This can only be changed before the guest has been started, otherwise the guest will become confused. Signed-off-by: Steven Price --- arch/arm64/include/asm/kvm_mmu.h | 2 + arch/arm64/include/uapi/asm/kvm.h | 6 + arch/arm64/kvm/Makefile | 1 + include/uapi/linux/kvm.h | 2 + virt/kvm/arm/mmu.c | 44 +++++++ virt/kvm/arm/pvtime.c | 189 ++++++++++++++++++++++++++++++ 6 files changed, 244 insertions(+) create mode 100644 virt/kvm/arm/pvtime.c diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h index 658657367f2f..3c266521223a 100644 --- a/arch/arm64/include/asm/kvm_mmu.h +++ b/arch/arm64/include/asm/kvm_mmu.h @@ -167,6 +167,8 @@ int kvm_alloc_stage2_pgd(struct kvm *kvm); void kvm_free_stage2_pgd(struct kvm *kvm); int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa, phys_addr_t pa, unsigned long size, bool writable); +int kvm_phys_addr_memremap(struct kvm *kvm, phys_addr_t guest_ipa, + phys_addr_t pa, unsigned long size, bool writable); int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run); diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index 97c3478ee6e7..e1d42ff35430 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -307,6 +307,12 @@ struct kvm_vcpu_events { #define KVM_PSCI_RET_INVAL PSCI_RET_INVALID_PARAMS #define KVM_PSCI_RET_DENIED PSCI_RET_DENIED +/* Device Control API: PV_TIME */ +#define KVM_DEV_ARM_PV_TIME_PADDR 0 +#define KVM_DEV_ARM_PV_TIME_ST 0 +#define KVM_DEV_ARM_PV_TIME_STATE_SIZE 1 +#define KVM_DEV_ARM_PV_TIME_STATE 2 + #endif #endif /* __ARM_KVM_H__ */ diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile index 45bb68f6c161..a3f064f0a51d 100644 --- a/arch/arm64/kvm/Makefile +++ b/arch/arm64/kvm/Makefile @@ -16,6 +16,7 @@ kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/e kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arm.o $(KVM)/arm/mmu.o $(KVM)/arm/mmio.o kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/psci.o $(KVM)/arm/perf.o kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hypercalls.o +kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/pvtime.o kvm-$(CONFIG_KVM_ARM_HOST) += inject_fault.o regmap.o va_layout.o kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 2b7a652c9fa4..494f7ad7987e 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1198,6 +1198,8 @@ enum kvm_device_type { #define KVM_DEV_TYPE_ARM_VGIC_V3 KVM_DEV_TYPE_ARM_VGIC_V3 KVM_DEV_TYPE_ARM_VGIC_ITS, #define KVM_DEV_TYPE_ARM_VGIC_ITS KVM_DEV_TYPE_ARM_VGIC_ITS + KVM_DEV_TYPE_ARM_PV_TIME, +#define KVM_DEV_TYPE_ARM_PV_TIME KVM_DEV_TYPE_ARM_PV_TIME KVM_DEV_TYPE_MAX, }; diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c index 5eca48bdb1a6..17ec31c40039 100644 --- a/virt/kvm/arm/mmu.c +++ b/virt/kvm/arm/mmu.c @@ -1227,6 +1227,50 @@ int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa, return ret; } +/** + * kvm_phys_addr_memremap - map a memory range to guest IPA + * + * @kvm: The KVM pointer + * @guest_ipa: The IPA at which to insert the mapping + * @pa: The physical address of the memory + * @size: The size of the mapping + */ +int kvm_phys_addr_memremap(struct kvm *kvm, phys_addr_t guest_ipa, + phys_addr_t pa, unsigned long size, bool writable) +{ + phys_addr_t addr, end; + int ret = 0; + unsigned long pfn; + struct kvm_mmu_memory_cache cache = { 0, }; + + end = (guest_ipa + size + PAGE_SIZE - 1) & PAGE_MASK; + pfn = __phys_to_pfn(pa); + + for (addr = guest_ipa; addr < end; addr += PAGE_SIZE) { + pte_t pte = pfn_pte(pfn, PAGE_S2); + + if (writable) + pte = kvm_s2pte_mkwrite(pte); + + ret = mmu_topup_memory_cache(&cache, + kvm_mmu_cache_min_pages(kvm), + KVM_NR_MEM_OBJS); + if (ret) + goto out; + spin_lock(&kvm->mmu_lock); + ret = stage2_set_pte(kvm, &cache, addr, &pte, 0); + spin_unlock(&kvm->mmu_lock); + if (ret) + goto out; + + pfn++; + } + +out: + mmu_free_memory_cache(&cache); + return ret; +} + static bool transparent_hugepage_adjust(kvm_pfn_t *pfnp, phys_addr_t *ipap) { kvm_pfn_t pfn = *pfnp; diff --git a/virt/kvm/arm/pvtime.c b/virt/kvm/arm/pvtime.c new file mode 100644 index 000000000000..e033f55e3ee4 --- /dev/null +++ b/virt/kvm/arm/pvtime.c @@ -0,0 +1,189 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Arm Ltd. + +#include +#include + +/* We currently only support PV time on ARM64 */ +#ifdef CONFIG_ARM64 + +#include + +static int max_stolen_size(void) +{ + int size = KVM_MAX_VCPUS * sizeof(struct pvclock_vcpu_stolen_time_info); + + return ALIGN(size, PAGE_SIZE); +} + +static int kvm_arm_pvtime_create(struct kvm_device *dev, u32 type) +{ + struct kvm_arch_pvtime *pvtime = &dev->kvm->arch.pvtime; + + pvtime->st = alloc_pages_exact(max_stolen_size(), + GFP_KERNEL | __GFP_ZERO); + if (!pvtime->st) + return -ENOMEM; + + return 0; +} + +static void kvm_arm_pvtime_destroy(struct kvm_device *dev) +{ + struct kvm_arch_pvtime *pvtime = &dev->kvm->arch.pvtime; + + pvtime->st_base = GPA_INVALID; + free_pages_exact(pvtime->st, max_stolen_size()); +} + +static int pvtime_map_pages(struct kvm *kvm, gpa_t guest_paddr, + void *kaddr, int size) +{ + return kvm_phys_addr_memremap(kvm, guest_paddr, + virt_to_phys(kaddr), + size, false); +} + +static int pvtime_save_state(struct kvm *kvm, u64 type, void __user *user) +{ + void *source; + size_t size; + + switch (type) { + case KVM_DEV_ARM_PV_TIME_ST: + source = kvm->arch.pvtime.st; + size = sizeof(struct pvclock_vcpu_stolen_time_info) * + atomic_read(&kvm->online_vcpus); + break; + default: + return -ENXIO; + } + + if (copy_to_user(user, source, size)) + return -EFAULT; + return 0; +} + +static int pvtime_restore_state(struct kvm *kvm, u64 type, void __user *user) +{ + void *dest; + size_t size; + + switch (type) { + case KVM_DEV_ARM_PV_TIME_ST: + dest = kvm->arch.pvtime.st; + size = sizeof(struct pvclock_vcpu_stolen_time_info) * + atomic_read(&kvm->online_vcpus); + break; + default: + return -ENXIO; + } + + if (copy_from_user(dest, user, size)) + return -EFAULT; + + return 0; +} + +static int kvm_arm_pvtime_set_attr(struct kvm_device *dev, + struct kvm_device_attr *attr) +{ + struct kvm_arch_pvtime *pvtime = &dev->kvm->arch.pvtime; + u64 __user *user = (u64 __user *)attr->addr; + u64 paddr; + int ret; + + switch (attr->group) { + case KVM_DEV_ARM_PV_TIME_PADDR: + if (get_user(paddr, user)) + return -EFAULT; + if (paddr & 63) + return -EINVAL; + switch (attr->attr) { + case KVM_DEV_ARM_PV_TIME_ST: + if (pvtime->st_base != GPA_INVALID) + return -EEXIST; + ret = pvtime_map_pages(dev->kvm, paddr, pvtime->st, + max_stolen_size()); + if (ret) + return ret; + pvtime->st_base = paddr; + return 0; + } + break; + case KVM_DEV_ARM_PV_TIME_STATE_SIZE: + return -EPERM; + case KVM_DEV_ARM_PV_TIME_STATE: + return pvtime_restore_state(dev->kvm, attr->attr, user); + } + return -ENXIO; +} + +static int kvm_arm_pvtime_get_attr(struct kvm_device *dev, + struct kvm_device_attr *attr) +{ + u64 __user *user = (u64 __user *)attr->addr; + u32 size; + + switch (attr->group) { + case KVM_DEV_ARM_PV_TIME_PADDR: + switch (attr->attr) { + case KVM_DEV_ARM_PV_TIME_ST: + if (put_user(dev->kvm->arch.pvtime.st_base, user)) + return -EFAULT; + return 0; + } + break; + case KVM_DEV_ARM_PV_TIME_STATE_SIZE: + switch (attr->attr) { + case KVM_DEV_ARM_PV_TIME_ST: + size = sizeof(struct pvclock_vcpu_stolen_time_info); + size *= atomic_read(&dev->kvm->online_vcpus); + break; + default: + return -ENXIO; + } + if (put_user(size, user)) + return -EFAULT; + return 0; + case KVM_DEV_ARM_PV_TIME_STATE: + return pvtime_save_state(dev->kvm, attr->attr, user); + } + return -ENXIO; +} + +static int kvm_arm_pvtime_has_attr(struct kvm_device *dev, + struct kvm_device_attr *attr) +{ + switch (attr->group) { + case KVM_DEV_ARM_PV_TIME_PADDR: + case KVM_DEV_ARM_PV_TIME_STATE_SIZE: + case KVM_DEV_ARM_PV_TIME_STATE: + switch (attr->attr) { + case KVM_DEV_ARM_PV_TIME_ST: + return 0; + } + break; + } + return -ENXIO; +} + +static const struct kvm_device_ops pvtime_ops = { + "Arm PV time", + .create = kvm_arm_pvtime_create, + .destroy = kvm_arm_pvtime_destroy, + .set_attr = kvm_arm_pvtime_set_attr, + .get_attr = kvm_arm_pvtime_get_attr, + .has_attr = kvm_arm_pvtime_has_attr +}; + +static int __init kvm_pvtime_init(void) +{ + kvm_register_device_ops(&pvtime_ops, KVM_DEV_TYPE_ARM_PV_TIME); + + return 0; +} + +late_initcall(kvm_pvtime_init); + +#endif From patchwork Wed Dec 12 15:02:24 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Price X-Patchwork-Id: 10726519 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8F2BF91E for ; Wed, 12 Dec 2018 15:06:07 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7E7EE2B164 for ; Wed, 12 Dec 2018 15:06:07 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 72C342B176; Wed, 12 Dec 2018 15:06:07 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id D196A2B164 for ; Wed, 12 Dec 2018 15:06:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=49O/HK3bpweH4Apyv4xCfgl1+TnOWFc/bwJpEjOnhCU=; b=gW6pI6Naicv2q2 EKjZX+d8IasyP4/jPqIHZDpS39qmKnc1vnWE4zQWXfmguEQ947k2KT9R151S/Ua/ajwvQuZk9o8pf ELD+IHwye4afehesH+W+l82Hptzbq4lsTNphPJtW7ABCiYUW8i/qxhxfQio/kA7AembzOW9SC4T9a mf4a8Lo5nHEu7tehNTHrf2vhCNNpzn6z1XqJ8CxtzFeNjATweS3OrKkDaqS+PcvNMDyv07EFDk0Uc LzrF8/rhORKMcrROQP3tT0k6XHmnekDDLWMXKMLH+gygd+UrouXOW9HpOpT4MAFCQf788n+x481/3 GzaaCnX8+jdaj34uWicQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gX65J-0002GC-Fr; Wed, 12 Dec 2018 15:06:01 +0000 Received: from usa-sjc-mx-foss1.foss.arm.com ([217.140.101.70] helo=foss.arm.com) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gX62e-0006YB-Qq for linux-arm-kernel@lists.infradead.org; Wed, 12 Dec 2018 15:03:35 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 97721165C; Wed, 12 Dec 2018 07:03:16 -0800 (PST) Received: from e112269-lin.arm.com (e112269-lin.cambridge.arm.com [10.1.196.55]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 1CD443F59C; Wed, 12 Dec 2018 07:03:14 -0800 (PST) From: Steven Price To: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH v2 10/12] KVM: arm64: Support Live Physical Time reporting Date: Wed, 12 Dec 2018 15:02:24 +0000 Message-Id: <20181212150226.38051-11-steven.price@arm.com> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20181212150226.38051-1-steven.price@arm.com> References: <20181212150226.38051-1-steven.price@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181212_070318_046102_ACE4BEFF X-CRM114-Status: GOOD ( 20.63 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mark Rutland , Marc Zyngier , Catalin Marinas , Will Deacon , Christoffer Dall , Steven Price Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Provide a method for a guest to derive a paravirtualized counter/timer which isn't dependent on the host's counter frequency. This allows a guest to be migrated onto a new host which doesn't have the same frequency without the virtual counter being disturbed. The host provides a shared structure which contains coefficients that can be used to map the real counter from the host (the Arm "virtual counter") to a paravirtualized view of time. On migration the new host updates the coefficients to ensure that the guests view of time (after using the coefficients) doesn't change and that the derived counter progresses at the same real frequency. The guest can probe the existence of this support using the PV_FEATURES SMCCC interface provided in a previous patch. Signed-off-by: Steven Price --- arch/arm64/include/asm/kvm_host.h | 4 + include/kvm/arm_arch_timer.h | 2 + virt/kvm/arm/arm.c | 5 ++ virt/kvm/arm/hypercalls.c | 141 ++++++++++++++++++++++++++++++ 4 files changed, 152 insertions(+) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index bab7bc720992..a4efe6699dd3 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -85,6 +85,10 @@ struct kvm_arch { struct kvm_arch_pvtime { void *st; gpa_t st_base; + + void *lpt; + gpa_t lpt_base; + u32 lpt_fpv; } pvtime; }; diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h index 6502feb9524b..c8cdd96052e0 100644 --- a/include/kvm/arm_arch_timer.h +++ b/include/kvm/arm_arch_timer.h @@ -92,6 +92,8 @@ void kvm_timer_init_vhe(void); bool kvm_arch_timer_get_input_level(int vintid); +int kvm_arm_update_lpt_sequence(struct kvm *kvm); + #define vcpu_vtimer(v) (&(v)->arch.timer_cpu.vtimer) #define vcpu_ptimer(v) (&(v)->arch.timer_cpu.ptimer) diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c index b347ba38cb11..e347da3ae123 100644 --- a/virt/kvm/arm/arm.c +++ b/virt/kvm/arm/arm.c @@ -150,7 +150,10 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) kvm->arch.max_vcpus = vgic_present ? kvm_vgic_get_max_vcpus() : KVM_MAX_VCPUS; + /* Set the PV Time addresses to invalid values */ kvm->arch.pvtime.st_base = GPA_INVALID; + kvm->arch.pvtime.lpt_base = GPA_INVALID; + return ret; out_free_stage2_pgd: kvm_free_stage2_pgd(kvm); @@ -591,6 +594,8 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) ret = kvm_arm_pmu_v3_enable(vcpu); + kvm_arm_update_lpt_sequence(kvm); + return ret; } diff --git a/virt/kvm/arm/hypercalls.c b/virt/kvm/arm/hypercalls.c index 595d1cf3a871..69ce87278f36 100644 --- a/virt/kvm/arm/hypercalls.c +++ b/virt/kvm/arm/hypercalls.c @@ -2,6 +2,7 @@ // Copyright (C) 2018 Arm Ltd. #include +#include #include #include @@ -74,6 +75,143 @@ static int kvm_hypercall_stolen_time(struct kvm_vcpu *vcpu) smccc_set_retval(vcpu, ret, 0, 0, 0); return 1; } +#include + +/* + * Returns ((u128)dividend << 64) / divisor + * Precondition: dividend < divisor + */ +static u64 shift64_div(u32 dividend, u32 divisor) +{ + u64 high = (u64)dividend << 32; + u64 low; + u64 rem; + + WARN_ON(dividend >= divisor); + + rem = do_div(high, divisor); + low = rem << 32; + do_div(low, divisor); + + return (high << 32) | low; +} + +/* + * Calculate the relative offset of each vCPU's timer and convert that to the + * new timer rate. + */ +static void update_vtimer_cval(struct kvm *kvm, u32 previous_rate) +{ + u32 current_rate = arch_timer_get_rate(); + u64 current_time = kvm_phys_timer_read(); + int i; + struct kvm_vcpu *vcpu; + u64 rel_cval; + + /* Early out if there's nothing to do */ + if (previous_rate == current_rate) + return; + + kvm_for_each_vcpu(i, vcpu, kvm) { + struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); + u64 cntvct; + u64 new_cntvct; + + /* + * The vtimer should not be already loaded as this function is + * only called on the first run of the first VCPU before any + * timers are loaded. + */ + if (WARN_ON(vtimer->loaded)) + continue; + + cntvct = current_time - vtimer->cntvoff; + new_cntvct = mul_u64_u32_div(cntvct, current_rate, + previous_rate); + vtimer->cntvoff = current_time - new_cntvct; + + rel_cval = vtimer->cnt_cval - cntvct; + + rel_cval = mul_u64_u32_div(rel_cval, current_rate, + previous_rate); + + vtimer->cnt_cval = new_cntvct + rel_cval; + } +} + +int kvm_arm_update_lpt_sequence(struct kvm *kvm) +{ + struct pvclock_vm_time_info *pvclock; + u64 lpt_ipa = kvm->arch.pvtime.lpt_base; + u64 native_freq, pv_freq, scale_mult, div_by_pv_freq_mult; + u64 shift = 0; + u64 sequence_number = 0; + + if (lpt_ipa == GPA_INVALID) + return -EINVAL; + + if (!IS_ALIGNED(lpt_ipa, 64)) + return -EINVAL; + + pvclock = kvm->arch.pvtime.lpt; + + if (!pvclock) + return -EINVAL; + + mutex_lock(&kvm->lock); + + sequence_number = le64_to_cpu(pvclock->sequence_number); + native_freq = le64_to_cpu(pvclock->native_freq); + + if (native_freq) { + /* + * The VM has been migrated, so update the sequence number + * and correct the compare for the timer if the frequency has + * changed + */ + sequence_number = sequence_number + 2; + update_vtimer_cval(kvm, native_freq); + } + + native_freq = arch_timer_get_rate(); + pv_freq = kvm->arch.pvtime.lpt_fpv; + + if (pv_freq >= native_freq) + shift = ilog2(pv_freq / native_freq) + 1; + + WARN_ON(native_freq > U32_MAX); + /* scale_mult = (pv_freq << 64) / (native_freq << shift) */ + scale_mult = shift64_div(pv_freq, native_freq << shift); + /* div_by_pv_freq_mult = (1 << 64) / pv_freq */ + div_by_pv_freq_mult = shift64_div(1, pv_freq); + + pvclock->sequence_number = cpu_to_le64(sequence_number); + pvclock->native_freq = cpu_to_le64(native_freq); + pvclock->pv_freq = cpu_to_le64(pv_freq); + pvclock->shift = cpu_to_le32(shift); + pvclock->scale_mult = cpu_to_le64(scale_mult); + pvclock->div_by_pv_freq_mult = cpu_to_le64(div_by_pv_freq_mult); + + mutex_unlock(&kvm->lock); + + return 0; +} + +static int kvm_hypercall_time_lpt(struct kvm_vcpu *vcpu) +{ + u32 flags; + u64 ret = vcpu->kvm->arch.pvtime.lpt_base; + + flags = smccc_get_arg1(vcpu); + + if (flags) { + /* Currently no support for any flags */ + ret = PV_VM_TIME_INVALID_PARAMETERS; + } + + smccc_set_retval(vcpu, ret, 0, 0, 0); + return 1; +} int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) { u32 func_id = smccc_get_function(vcpu); @@ -115,12 +253,15 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) switch (feature) { case ARM_SMCCC_HV_PV_FEATURES: case ARM_SMCCC_HV_PV_TIME_ST: + case ARM_SMCCC_HV_PV_TIME_LPT: val = SMCCC_RET_SUCCESS; break; } break; case ARM_SMCCC_HV_PV_TIME_ST: return kvm_hypercall_stolen_time(vcpu); + case ARM_SMCCC_HV_PV_TIME_LPT: + return kvm_hypercall_time_lpt(vcpu); default: return kvm_psci_call(vcpu); } From patchwork Wed Dec 12 15:02:25 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Price X-Patchwork-Id: 10726523 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7064814BD for ; Wed, 12 Dec 2018 15:06:46 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5C4D62B164 for ; Wed, 12 Dec 2018 15:06:46 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 504792B176; Wed, 12 Dec 2018 15:06:46 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 6E8472B164 for ; Wed, 12 Dec 2018 15:06:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=NIjhnQWK1s3SMED1wx6VxGX2KAaZtj89Q/w5gnCZvc0=; b=fI9MzW4iN5kWD7 C08eRGViBqXYQU4fPbk5Tlx6jkinFCqVIWq9ZusdTkROIk7smDCsBd3lDgGEJBX0yS5aDNBGmQIMm +kSMFgabNlswgxuWk/dfRn7tWNfPcbYwPB7dx/UCYLqRY3R3iXiDEwoG9qdqWE5HS47u3X/ynRHI/ ukpZHSfuCEnWah2yL8fP6meDF2NK/PfocnVIxna7M/jSVsRJ+VwDVecCz5hq1PsQhbyPZcKr/j7vh lI8ELUvIGguAwHngmDN3t78z5DX1NNyxdEXd7917Mlz7ucDu0mjuSbD8kM3/mctNctwJE4w1RRJYs lyxcIz9ZxLjSpFlEOAjQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gX65o-0002j8-5A; Wed, 12 Dec 2018 15:06:32 +0000 Received: from merlin.infradead.org ([2001:8b0:10b:1231::1]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1gX62z-00073h-RH for linux-arm-kernel@bombadil.infradead.org; Wed, 12 Dec 2018 15:03:38 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=merlin.20170209; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To: Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help: List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=BMeUQpzaHVS0zKav8f2SKKYOPDtyQysmrTEMPfEsayE=; b=GWwYg5qgyOZShccVk8g3u/nOj5 3b1RmUaGzqQJjanJoWmMBrfqIuuVGWy1cjUT8fzJLk0RFy0a8M3McGZ4EFdpIQPLEAOpi2H02un94 z1UhFfpUhvkdBNXKWeVXCraVAgeXrF7SMpczxllPGlEXSxYNxGDhQHwlj+4Dmd7d9v3yCYW3NJ7uQ LVZwONEIA1HHe7HzYG/eJSpwm5BpwrX2Skt+2GiHbEB+NwqTUyN92YPRVdYL7kWCsBIQopJyE1d8U 4GDlF3uOeS7Hs3DkhisDg7JORUTYGxDcYenSE79KFOlgHUZHvipV5lA2nZO94mS4r3ebOY+bqJ8LG 4BWgGrVQ==; Received: from foss.arm.com ([217.140.101.70]) by merlin.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gX62v-0000zG-Hx for linux-arm-kernel@lists.infradead.org; Wed, 12 Dec 2018 15:03:35 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 5CF5D16A3; Wed, 12 Dec 2018 07:03:18 -0800 (PST) Received: from e112269-lin.arm.com (e112269-lin.cambridge.arm.com [10.1.196.55]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id D5DDF3F59C; Wed, 12 Dec 2018 07:03:16 -0800 (PST) From: Steven Price To: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH v2 11/12] clocksource: arm_arch_timer: Use paravirtualized LPT Date: Wed, 12 Dec 2018 15:02:25 +0000 Message-Id: <20181212150226.38051-12-steven.price@arm.com> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20181212150226.38051-1-steven.price@arm.com> References: <20181212150226.38051-1-steven.price@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181212_100333_756217_56579A98 X-CRM114-Status: GOOD ( 25.60 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mark Rutland , Marc Zyngier , Catalin Marinas , Will Deacon , Christoffer Dall , Steven Price Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Enable paravirtualized time to be used in a KVM guest if the host supports it. This allows the guest to derive a counter which is clocked at a persistent rate even when the guest is migrated. If we discover that the system supports SMCCC v1.1 then we probe to determine whether the hypervisor supports paravirtualized features and finally whether it supports "Live Physical Time" reporting. If so a shared structure is made available to the guest containing coefficients to calculate the derived clock. The guest kernel uses the coefficients to present a clock to user space that is always clocked at the same rate whenever the guest is running ('live'), even if the physical clock changes (due to the guest being migrated). The existing workaround framework for CNTVCT is used to disable the VDSO and trap user space accesses to the timer registers so we can present the derived clock. Signed-off-by: Steven Price --- arch/arm64/include/asm/arch_timer.h | 32 ++++- arch/arm64/kernel/cpuinfo.c | 2 +- drivers/clocksource/arm_arch_timer.c | 177 ++++++++++++++++++++++++++- 3 files changed, 205 insertions(+), 6 deletions(-) diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h index f2a234d6516c..ec0e7250c453 100644 --- a/arch/arm64/include/asm/arch_timer.h +++ b/arch/arm64/include/asm/arch_timer.h @@ -20,12 +20,14 @@ #define __ASM_ARCH_TIMER_H #include +#include #include #include #include #include #include +#include #include #include @@ -79,6 +81,19 @@ DECLARE_PER_CPU(const struct arch_timer_erratum_workaround *, _val; \ }) +void pvclock_reg_write_cntv_tval_el0(u32 val); +extern struct static_key_false arch_counter_cntfrq_ool_enabled; +extern u64 pvclock_get_cntfrq(void); +extern struct static_key_false arch_counter_cntvct_ool_enabled; +extern u64 pvclock_get_cntvct(void); + +static __always_inline void __write_cntv_tval_el0(u32 val) +{ + if (static_branch_unlikely(&arch_counter_cntvct_ool_enabled)) + return pvclock_reg_write_cntv_tval_el0(val); + write_sysreg(val, cntv_tval_el0); +} + /* * These register accessors are marked inline so the compiler can * nicely work out which register we want, and chuck away the rest of @@ -102,7 +117,7 @@ void arch_timer_reg_write_cp15(int access, enum arch_timer_reg reg, u32 val) write_sysreg(val, cntv_ctl_el0); break; case ARCH_TIMER_REG_TVAL: - write_sysreg(val, cntv_tval_el0); + __write_cntv_tval_el0(val); break; } } @@ -134,7 +149,10 @@ u32 arch_timer_reg_read_cp15(int access, enum arch_timer_reg reg) static inline u32 arch_timer_get_cntfrq(void) { - return read_sysreg(cntfrq_el0); + if (static_branch_unlikely(&arch_counter_cntfrq_ool_enabled)) + return pvclock_get_cntfrq(); + else + return read_sysreg(cntfrq_el0); } static inline u32 arch_timer_get_cntkctl(void) @@ -154,12 +172,20 @@ static inline u64 arch_counter_get_cntpct(void) return arch_timer_reg_read_stable(cntpct_el0); } -static inline u64 arch_counter_get_cntvct(void) +static inline u64 __arch_counter_get_cntvct(void) { isb(); return arch_timer_reg_read_stable(cntvct_el0); } +static inline u64 arch_counter_get_cntvct(void) +{ + if (static_branch_unlikely(&arch_counter_cntvct_ool_enabled)) + return pvclock_get_cntvct(); + else + return __arch_counter_get_cntvct(); +} + static inline int arch_timer_arch_init(void) { return 0; diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c index bcc2831399cb..74410727829d 100644 --- a/arch/arm64/kernel/cpuinfo.c +++ b/arch/arm64/kernel/cpuinfo.c @@ -324,7 +324,7 @@ static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info) static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info) { - info->reg_cntfrq = arch_timer_get_cntfrq(); + info->reg_cntfrq = read_cpuid(CNTFRQ_EL0); /* * Use the effective value of the CTR_EL0 than the raw value * exposed by the CPU. CTR_E0.IDC field value must be interpreted diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 9a7d4dc00b6e..6e84e1acc4f4 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -11,6 +11,7 @@ #define pr_fmt(fmt) "arm_arch_timer: " fmt +#include #include #include #include @@ -23,6 +24,8 @@ #include #include #include +#include +#include #include #include #include @@ -86,6 +89,171 @@ static int __init early_evtstrm_cfg(char *buf) } early_param("clocksource.arm_arch_timer.evtstrm", early_evtstrm_cfg); +#ifdef CONFIG_ARM64 +/* Paravirtualised time is only supported for 64 bit */ +static struct pvclock_vm_time_info *pvclock_vm_time_info; + +DEFINE_STATIC_KEY_FALSE(arch_counter_cntvct_ool_enabled); +EXPORT_SYMBOL_GPL(arch_counter_cntvct_ool_enabled); +DEFINE_STATIC_KEY_FALSE(arch_counter_cntfrq_ool_enabled); +EXPORT_SYMBOL_GPL(arch_counter_cntfrq_ool_enabled); + +static inline u64 native_to_pv_cycles(const struct pvclock_vm_time_info *info, + u64 cnt) +{ + u32 shift = le32_to_cpu(info->shift); + u64 scale_mult = le64_to_cpu(info->scale_mult); + + cnt <<= shift; + return mul_u64_u64_shr(scale_mult, cnt, 64); +} + +static inline u64 pv_to_native_cycles(const struct pvclock_vm_time_info *info, + u64 cnt) +{ + u64 native_freq = le64_to_cpu(info->native_freq); + u64 pv_freq = le64_to_cpu(info->pv_freq); + u64 div_by_pv_freq_mult = le64_to_cpu(info->div_by_pv_freq_mult); + + cnt = native_freq * cnt + pv_freq - 1; + return mul_u64_u64_shr(div_by_pv_freq_mult, cnt, 64); +} + +u64 pvclock_get_cntvct(void) +{ + u64 cval; + __le64 seq_begin, seq_end; + + do { + seq_begin = READ_ONCE(pvclock_vm_time_info->sequence_number); + + barrier(); + + cval = __arch_counter_get_cntvct(); + cval = native_to_pv_cycles(pvclock_vm_time_info, cval); + + barrier(); + seq_end = READ_ONCE(pvclock_vm_time_info->sequence_number); + } while (unlikely(seq_begin != seq_end)); + + return cval; +} + +u64 pvclock_get_cntfrq(void) +{ + return le64_to_cpu(pvclock_vm_time_info->pv_freq); +} + +static void arch_timer_pvclock_init(void) +{ + struct arm_smccc_res res; + void *kaddr; + + if (psci_ops.smccc_version < SMCCC_VERSION_1_1) + return; + + arm_smccc_1_1_call(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, + ARM_SMCCC_HV_PV_FEATURES, &res); + + if (res.a0 != SMCCC_RET_SUCCESS) + return; + + arm_smccc_1_1_call(ARM_SMCCC_HV_PV_FEATURES, + ARM_SMCCC_HV_PV_TIME_LPT, &res); + + if ((s32)res.a0 < 0) + return; + + arm_smccc_1_1_call(ARM_SMCCC_HV_PV_TIME_LPT, 0, &res); + + if ((s64)res.a0 < 0) + return; + + kaddr = memremap(res.a0, + sizeof(struct pvclock_vm_time_info), + MEMREMAP_WB); + + if (!kaddr) { + pr_warn("Failed to map LPT structure for paravirtualized clock\n"); + return; + } + + pvclock_vm_time_info = kaddr; + + static_branch_enable(&arch_counter_cntvct_ool_enabled); + static_branch_enable(&arch_counter_cntfrq_ool_enabled); + + pr_info("Using paravirtualized clock\n"); +} + +static inline bool pvclock_trap_cntvct(void) +{ + return static_branch_unlikely(&arch_counter_cntvct_ool_enabled); +} + +static inline void arch_timer_reg_write_cntv_tval(u32 val, + struct arch_timer *timer) +{ + __le64 seq_begin, seq_end; + + if (!static_branch_unlikely(&arch_counter_cntvct_ool_enabled)) { + writel_relaxed(val, timer->base + CNTV_TVAL); + return; + } + + do { + u32 n_val; + + seq_begin = READ_ONCE(pvclock_vm_time_info->sequence_number); + + barrier(); + + n_val = pv_to_native_cycles(pvclock_vm_time_info, val); + + writel_relaxed(n_val, timer->base + CNTV_TVAL); + barrier(); + + seq_end = READ_ONCE(pvclock_vm_time_info->sequence_number); + } while (unlikely(seq_begin != seq_end)); +} + +void pvclock_reg_write_cntv_tval_el0(u32 val) +{ + __le64 seq_begin, seq_end; + + do { + u32 n_val; + + seq_begin = READ_ONCE(pvclock_vm_time_info->sequence_number); + + barrier(); + + n_val = pv_to_native_cycles(pvclock_vm_time_info, val); + + write_sysreg(n_val, cntv_tval_el0); + barrier(); + + seq_end = READ_ONCE(pvclock_vm_time_info->sequence_number); + } while (unlikely(seq_begin != seq_end)); +} + +#else /* CONFIG_ARM64 */ +static void arch_timer_pvclock_init(void) +{ +} + +static inline bool pvclock_trap_cntvct(void) +{ + return false; +} + +static inline void arch_timer_reg_write_cntv_tval(u32 val, + struct arch_timer *timer) +{ + writel_relaxed(val, timer->base + CNTV_TVAL); +} +#endif /* CONFIG_ARM64 */ + /* * Architected system timer support. */ @@ -111,7 +279,7 @@ void arch_timer_reg_write(int access, enum arch_timer_reg reg, u32 val, writel_relaxed(val, timer->base + CNTV_CTL); break; case ARCH_TIMER_REG_TVAL: - writel_relaxed(val, timer->base + CNTV_TVAL); + arch_timer_reg_write_cntv_tval(val, timer); break; } } else { @@ -589,6 +757,7 @@ static bool arch_timer_this_cpu_has_cntvct_wa(void) #define erratum_set_next_event_tval_phys(...) ({BUG(); 0;}) #define erratum_handler(fn, r, ...) ({false;}) #define arch_timer_this_cpu_has_cntvct_wa() ({false;}) + #endif /* CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND */ static __always_inline irqreturn_t timer_handler(const int access, @@ -815,7 +984,7 @@ static void arch_counter_set_user_access(void) * need to be workaround. The vdso may have been already * disabled though. */ - if (arch_timer_this_cpu_has_cntvct_wa()) + if (pvclock_trap_cntvct() || arch_timer_this_cpu_has_cntvct_wa()) pr_info("CPU%d: Trapping CNTVCT access\n", smp_processor_id()); else cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN; @@ -1222,6 +1391,8 @@ static int __init arch_timer_of_init(struct device_node *np) arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI]; + arch_timer_pvclock_init(); + rate = arch_timer_get_cntfrq(); arch_timer_of_configure_rate(rate, np); @@ -1552,6 +1723,8 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table) arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI]; + arch_timer_pvclock_init(); + /* * When probing via ACPI, we have no mechanism to override the sysreg * CNTFRQ value. This *must* be correct. From patchwork Wed Dec 12 15:02:26 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Price X-Patchwork-Id: 10726521 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1BCF114BD for ; Wed, 12 Dec 2018 15:06:22 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 087702B164 for ; Wed, 12 Dec 2018 15:06:22 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id F10912B176; Wed, 12 Dec 2018 15:06:21 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 1DD182B164 for ; Wed, 12 Dec 2018 15:06:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=fn7RAdamZznKT/wHIwZw1sJ39yiOPCko9mJA+4g01Rw=; b=ExX9OpPcSGeiY+ +COQkAwRZ4mFik4MZ9KRLz1l935u7/st9TL5OOQRaJo5cey+q/cvTKIdlC6dCyQwvdWtB4pcuTyUw pcR6i1tQCghiJprcqeGK+cSnqEWXO6j4ti9T/M6VZLIe/N7ZBhuNYrAByw5TgGUsc6W/LefVEdy/z 5KEpAKAdG+rpEzJHsjusVPzI2Puusd2GgDyiAuDQb6EVhhWXbcouqXNLauLvOtZ+6Q5hY2dadK204 6VISpg074Ztv79eaxZBN5ETEoanB7OxNjT6xPFcGtuacXnglB+8jQP9HWcGiDhJBwg/teYAEnpgOC 5FjtilMjKZkBSvu/hR2w==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gX65X-0002TO-T3; Wed, 12 Dec 2018 15:06:15 +0000 Received: from merlin.infradead.org ([2001:8b0:10b:1231::1]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1gX631-00075Y-R2 for linux-arm-kernel@bombadil.infradead.org; Wed, 12 Dec 2018 15:03:39 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=merlin.20170209; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To: Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help: List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=S+40wVRbfcuz5+wA8Lkh6qsOi+ppkBJb4+4HzLh+M6Y=; b=xJWsvg6WuZj6lxsgm5YxyjWHXZ HgCgTDSjAM15xgqGtvxYFDz6Sjv42Zo9GISYhUaUM/2fYbBsZWd1Hfd4XFHbL0aAqx1Y6HUcy2L4N tiN6kEnqS0D+CWRS7rldT26HA/EaVoPGYphu0yeBpP6zNZp8n2WRm3cVaF4BzPINgvrlSNFZ9CP1M qaBZ5o3Fy6pzorxagn6C3ezrbzETRf/r+SNUVDnvszB+7A8XV2JjX28HsQs69wUV7YSJyWskIjAXb rq+L+5I0LtLbJPtP5uxvWK0P6Plc/eJL0iFh+g1+I/RLpU62UMQJ7tis425mTKZ+SZ3TJZ0vqZpOz VAGfJulg==; Received: from foss.arm.com ([217.140.101.70]) by merlin.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gX62v-0000zJ-Of for linux-arm-kernel@lists.infradead.org; Wed, 12 Dec 2018 15:03:37 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 222EF1993; Wed, 12 Dec 2018 07:03:20 -0800 (PST) Received: from e112269-lin.arm.com (e112269-lin.cambridge.arm.com [10.1.196.55]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 9AFB03F59C; Wed, 12 Dec 2018 07:03:18 -0800 (PST) From: Steven Price To: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH v2 12/12] KVM: arm64: Export LPT using PV_TIME device Date: Wed, 12 Dec 2018 15:02:26 +0000 Message-Id: <20181212150226.38051-13-steven.price@arm.com> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20181212150226.38051-1-steven.price@arm.com> References: <20181212150226.38051-1-steven.price@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181212_100333_958975_A94E87AA X-CRM114-Status: GOOD ( 16.75 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mark Rutland , Marc Zyngier , Catalin Marinas , Will Deacon , Christoffer Dall , Steven Price Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Extend the PV_TIME device to allow setting up Live Physical Time and saving/restoring the state necessary for migration. Signed-off-by: Steven Price --- arch/arm64/include/uapi/asm/kvm.h | 2 ++ virt/kvm/arm/pvtime.c | 55 +++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index e1d42ff35430..d3b0d70cdd9f 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -310,8 +310,10 @@ struct kvm_vcpu_events { /* Device Control API: PV_TIME */ #define KVM_DEV_ARM_PV_TIME_PADDR 0 #define KVM_DEV_ARM_PV_TIME_ST 0 +#define KVM_DEV_ARM_PV_TIME_LPT 1 #define KVM_DEV_ARM_PV_TIME_STATE_SIZE 1 #define KVM_DEV_ARM_PV_TIME_STATE 2 +#define KVM_DEV_ARM_PV_TIME_FREQUENCY 3 #endif diff --git a/virt/kvm/arm/pvtime.c b/virt/kvm/arm/pvtime.c index e033f55e3ee4..345798aebebf 100644 --- a/virt/kvm/arm/pvtime.c +++ b/virt/kvm/arm/pvtime.c @@ -25,6 +25,14 @@ static int kvm_arm_pvtime_create(struct kvm_device *dev, u32 type) if (!pvtime->st) return -ENOMEM; + pvtime->lpt = (void *)get_zeroed_page(GFP_KERNEL); + if (!pvtime->lpt) { + free_pages_exact(pvtime->st, max_stolen_size()); + return -ENOMEM; + } + + pvtime->lpt_fpv = arch_timer_get_rate(); + return 0; } @@ -32,8 +40,10 @@ static void kvm_arm_pvtime_destroy(struct kvm_device *dev) { struct kvm_arch_pvtime *pvtime = &dev->kvm->arch.pvtime; + pvtime->lpt_base = GPA_INVALID; pvtime->st_base = GPA_INVALID; free_pages_exact(pvtime->st, max_stolen_size()); + free_page((unsigned long)pvtime->lpt); } static int pvtime_map_pages(struct kvm *kvm, gpa_t guest_paddr, @@ -50,6 +60,10 @@ static int pvtime_save_state(struct kvm *kvm, u64 type, void __user *user) size_t size; switch (type) { + case KVM_DEV_ARM_PV_TIME_LPT: + source = kvm->arch.pvtime.lpt; + size = sizeof(struct pvclock_vm_time_info); + break; case KVM_DEV_ARM_PV_TIME_ST: source = kvm->arch.pvtime.st; size = sizeof(struct pvclock_vcpu_stolen_time_info) * @@ -70,6 +84,10 @@ static int pvtime_restore_state(struct kvm *kvm, u64 type, void __user *user) size_t size; switch (type) { + case KVM_DEV_ARM_PV_TIME_LPT: + dest = kvm->arch.pvtime.lpt; + size = sizeof(struct pvclock_vm_time_info); + break; case KVM_DEV_ARM_PV_TIME_ST: dest = kvm->arch.pvtime.st; size = sizeof(struct pvclock_vcpu_stolen_time_info) * @@ -91,6 +109,7 @@ static int kvm_arm_pvtime_set_attr(struct kvm_device *dev, struct kvm_arch_pvtime *pvtime = &dev->kvm->arch.pvtime; u64 __user *user = (u64 __user *)attr->addr; u64 paddr; + u32 frequency; int ret; switch (attr->group) { @@ -100,6 +119,15 @@ static int kvm_arm_pvtime_set_attr(struct kvm_device *dev, if (paddr & 63) return -EINVAL; switch (attr->attr) { + case KVM_DEV_ARM_PV_TIME_LPT: + if (pvtime->lpt_base != GPA_INVALID) + return -EEXIST; + ret = pvtime_map_pages(dev->kvm, paddr, pvtime->lpt, + PAGE_SIZE); + if (ret) + return ret; + pvtime->lpt_base = paddr; + return kvm_arm_update_lpt_sequence(dev->kvm); case KVM_DEV_ARM_PV_TIME_ST: if (pvtime->st_base != GPA_INVALID) return -EEXIST; @@ -111,6 +139,13 @@ static int kvm_arm_pvtime_set_attr(struct kvm_device *dev, return 0; } break; + case KVM_DEV_ARM_PV_TIME_FREQUENCY: + if (attr->attr != KVM_DEV_ARM_PV_TIME_LPT) + break; + if (get_user(frequency, user)) + return -EFAULT; + pvtime->lpt_fpv = frequency; + return kvm_arm_update_lpt_sequence(dev->kvm); case KVM_DEV_ARM_PV_TIME_STATE_SIZE: return -EPERM; case KVM_DEV_ARM_PV_TIME_STATE: @@ -128,14 +163,27 @@ static int kvm_arm_pvtime_get_attr(struct kvm_device *dev, switch (attr->group) { case KVM_DEV_ARM_PV_TIME_PADDR: switch (attr->attr) { + case KVM_DEV_ARM_PV_TIME_LPT: + if (put_user(dev->kvm->arch.pvtime.lpt_base, user)) + return -EFAULT; + return 0; case KVM_DEV_ARM_PV_TIME_ST: if (put_user(dev->kvm->arch.pvtime.st_base, user)) return -EFAULT; return 0; } break; + case KVM_DEV_ARM_PV_TIME_FREQUENCY: + if (attr->attr != KVM_DEV_ARM_PV_TIME_LPT) + break; + if (put_user(dev->kvm->arch.pvtime.lpt_fpv, user)) + return -EFAULT; + return 0; case KVM_DEV_ARM_PV_TIME_STATE_SIZE: switch (attr->attr) { + case KVM_DEV_ARM_PV_TIME_LPT: + size = sizeof(struct pvclock_vm_time_info); + break; case KVM_DEV_ARM_PV_TIME_ST: size = sizeof(struct pvclock_vcpu_stolen_time_info); size *= atomic_read(&dev->kvm->online_vcpus); @@ -160,10 +208,17 @@ static int kvm_arm_pvtime_has_attr(struct kvm_device *dev, case KVM_DEV_ARM_PV_TIME_STATE_SIZE: case KVM_DEV_ARM_PV_TIME_STATE: switch (attr->attr) { + case KVM_DEV_ARM_PV_TIME_LPT: case KVM_DEV_ARM_PV_TIME_ST: return 0; } break; + case KVM_DEV_ARM_PV_TIME_FREQUENCY: + switch (attr->attr) { + case KVM_DEV_ARM_PV_TIME_LPT: + return 0; + } + break; } return -ENXIO; }