From patchwork Tue Oct 27 17:26:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11861163 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7CE38C4363A for ; Tue, 27 Oct 2020 17:28:33 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id E4DE12225C for ; Tue, 27 Oct 2020 17:28:32 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="kBEFdIEi" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org E4DE12225C Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.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=emaxmoKm7nUy89XEgkMsXkPMQLh5hnCFokRFAEod12w=; b=kBEFdIEisNd8fVdHn1cuhR7vK 4NfcXh4xASgd8SfP7Anq76DHxLsxWyVjhuzX7xQlFNAKT9xyIZ5SKSGFthOYKxXzBY6s3TA2Uh6NQ SpcQzM2T7cvGEY+zqr2FhHNphOj4RVORXrFZ9d/U692KVenbu7m6abpqpTrVkS/0cNXK/dWKq5HsY 9B7GJRcT55TWPaYEf2cuhzJuJZds2AZbwqf+KkE94qJKqJF9bxuf73n5f+OBBsJvg97A5BENgdzK2 XVY9fBz7gv6B44TQtjXsEelxNi0tgSSs6YhtkZWSUDnnNe3uJ5BP7H/kan9Fu2gAF4niZhQBI2nCB RtjyUr7xA==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSjx-0004sQ-GK; Tue, 27 Oct 2020 17:26:33 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSji-0004mS-LR for linux-arm-kernel@lists.infradead.org; Tue, 27 Oct 2020 17:26:19 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id AF7D3150C; Tue, 27 Oct 2020 10:26:15 -0700 (PDT) Received: from monolith.localdoman (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 9B53D3F719; Tue, 27 Oct 2020 10:26:14 -0700 (PDT) From: Alexandru Elisei To: linux-arm-kernel@lists.infradead.org, kvmarm@lists.cs.columbia.edu Subject: [RFC PATCH v3 01/16] KVM: arm64: Initialize VCPU mdcr_el2 before loading it Date: Tue, 27 Oct 2020 17:26:50 +0000 Message-Id: <20201027172705.15181-2-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.29.1 In-Reply-To: <20201027172705.15181-1-alexandru.elisei@arm.com> References: <20201027172705.15181-1-alexandru.elisei@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201027_132618_822350_43B00506 X-CRM114-Status: GOOD ( 22.19 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: maz@kernel.org, will@kernel.org, james.morse@arm.com, julien.thierry.kdev@gmail.com, suzuki.poulose@arm.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org When a VCPU is created, the kvm_vcpu struct is initialized to zero in kvm_vm_ioctl_create_vcpu(). On VHE systems, the first time vcpu.arch.mdcr_el2 is loaded on hardware is in vcpu_load(), before it is set to a sensible value in kvm_arm_setup_debug() later in the run loop. The result is that KVM executes for a short time with MDCR_EL2 set to zero. This is mostly harmless as we don't need to trap debug and SPE register accesses from EL1 (we're still running in the host at EL2), but we do set MDCR_EL2.HPMN to 0 which is constrained unpredictable according to ARM DDI 0487F.b, page D13-3620; the required behavior from the hardware in this case is to reserve an unkown number of registers for EL2 and EL3 exclusive use. Initialize mdcr_el2 in kvm_vcpu_vcpu_first_run_init(), so we can avoid the constrained unpredictable behavior and to ensure that the MDCR_EL2 register has the same value after each vcpu_load(), including the first time the VCPU is run. Signed-off-by: Alexandru Elisei --- arch/arm64/include/asm/kvm_host.h | 1 + arch/arm64/kvm/arm.c | 3 +- arch/arm64/kvm/debug.c | 81 +++++++++++++++++++++---------- 3 files changed, 58 insertions(+), 27 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 0aecbab6a7fb..25d326aecded 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -597,6 +597,7 @@ static inline void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu) {} static inline void kvm_arch_vcpu_block_finish(struct kvm_vcpu *vcpu) {} void kvm_arm_init_debug(void); +void kvm_arm_vcpu_init_debug(struct kvm_vcpu *vcpu); void kvm_arm_setup_debug(struct kvm_vcpu *vcpu); void kvm_arm_clear_debug(struct kvm_vcpu *vcpu); void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu); diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index f56122eedffc..e51d8f328c7e 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -544,6 +544,8 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) static_branch_inc(&userspace_irqchip_in_use); } + kvm_arm_vcpu_init_debug(vcpu); + ret = kvm_timer_enable(vcpu); if (ret) return ret; @@ -739,7 +741,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) } kvm_arm_setup_debug(vcpu); - /************************************************************** * Enter the guest */ diff --git a/arch/arm64/kvm/debug.c b/arch/arm64/kvm/debug.c index 7a7e425616b5..22ee448aee2b 100644 --- a/arch/arm64/kvm/debug.c +++ b/arch/arm64/kvm/debug.c @@ -68,6 +68,59 @@ void kvm_arm_init_debug(void) __this_cpu_write(mdcr_el2, kvm_call_hyp_ret(__kvm_get_mdcr_el2)); } +/** + * kvm_arm_setup_mdcr_el2 - configure vcpu mdcr_el2 value + * + * @vcpu: the vcpu pointer + * @host_mdcr: host mdcr_el2 value + * + * This ensures we will trap access to: + * - Performance monitors (MDCR_EL2_TPM/MDCR_EL2_TPMCR) + * - Debug ROM Address (MDCR_EL2_TDRA) + * - OS related registers (MDCR_EL2_TDOSA) + * - Statistical profiler (MDCR_EL2_TPMS/MDCR_EL2_E2PB) + */ +static void kvm_arm_setup_mdcr_el2(struct kvm_vcpu *vcpu, u32 host_mdcr) +{ + bool trap_debug = !(vcpu->arch.flags & KVM_ARM64_DEBUG_DIRTY); + + /* + * This also clears MDCR_EL2_E2PB_MASK to disable guest access + * to the profiling buffer. + */ + vcpu->arch.mdcr_el2 = host_mdcr & MDCR_EL2_HPMN_MASK; + vcpu->arch.mdcr_el2 |= (MDCR_EL2_TPM | + MDCR_EL2_TPMS | + MDCR_EL2_TPMCR | + MDCR_EL2_TDRA | + MDCR_EL2_TDOSA); + + if (vcpu->guest_debug) { + /* Route all software debug exceptions to EL2 */ + vcpu->arch.mdcr_el2 |= MDCR_EL2_TDE; + if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW) + trap_debug = true; + } + + /* Trap debug register access */ + if (trap_debug) + vcpu->arch.mdcr_el2 |= MDCR_EL2_TDA; + + trace_kvm_arm_set_dreg32("MDCR_EL2", vcpu->arch.mdcr_el2); +} + +/** + * kvm_arm_vcpu_init_debug - setup vcpu debug traps + * + * @vcpu: the vcpu pointer + * + * Set vcpu initial mdcr_el2 value. + */ +void kvm_arm_vcpu_init_debug(struct kvm_vcpu *vcpu) +{ + kvm_arm_setup_mdcr_el2(vcpu, this_cpu_read(mdcr_el2)); +} + /** * kvm_arm_reset_debug_ptr - reset the debug ptr to point to the vcpu state */ @@ -83,12 +136,7 @@ void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu) * @vcpu: the vcpu pointer * * This is called before each entry into the hypervisor to setup any - * debug related registers. Currently this just ensures we will trap - * access to: - * - Performance monitors (MDCR_EL2_TPM/MDCR_EL2_TPMCR) - * - Debug ROM Address (MDCR_EL2_TDRA) - * - OS related registers (MDCR_EL2_TDOSA) - * - Statistical profiler (MDCR_EL2_TPMS/MDCR_EL2_E2PB) + * debug related registers. * * Additionally, KVM only traps guest accesses to the debug registers if * the guest is not actively using them (see the KVM_ARM64_DEBUG_DIRTY @@ -100,27 +148,14 @@ void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu) void kvm_arm_setup_debug(struct kvm_vcpu *vcpu) { - bool trap_debug = !(vcpu->arch.flags & KVM_ARM64_DEBUG_DIRTY); unsigned long mdscr, orig_mdcr_el2 = vcpu->arch.mdcr_el2; trace_kvm_arm_setup_debug(vcpu, vcpu->guest_debug); - /* - * This also clears MDCR_EL2_E2PB_MASK to disable guest access - * to the profiling buffer. - */ - vcpu->arch.mdcr_el2 = __this_cpu_read(mdcr_el2) & MDCR_EL2_HPMN_MASK; - vcpu->arch.mdcr_el2 |= (MDCR_EL2_TPM | - MDCR_EL2_TPMS | - MDCR_EL2_TPMCR | - MDCR_EL2_TDRA | - MDCR_EL2_TDOSA); + kvm_arm_setup_mdcr_el2(vcpu, __this_cpu_read(mdcr_el2)); /* Is Guest debugging in effect? */ if (vcpu->guest_debug) { - /* Route all software debug exceptions to EL2 */ - vcpu->arch.mdcr_el2 |= MDCR_EL2_TDE; - /* Save guest debug state */ save_guest_debug_regs(vcpu); @@ -174,7 +209,6 @@ void kvm_arm_setup_debug(struct kvm_vcpu *vcpu) vcpu->arch.debug_ptr = &vcpu->arch.external_debug_state; vcpu->arch.flags |= KVM_ARM64_DEBUG_DIRTY; - trap_debug = true; trace_kvm_arm_set_regset("BKPTS", get_num_brps(), &vcpu->arch.debug_ptr->dbg_bcr[0], @@ -189,10 +223,6 @@ void kvm_arm_setup_debug(struct kvm_vcpu *vcpu) BUG_ON(!vcpu->guest_debug && vcpu->arch.debug_ptr != &vcpu->arch.vcpu_debug_state); - /* Trap debug register access */ - if (trap_debug) - vcpu->arch.mdcr_el2 |= MDCR_EL2_TDA; - /* If KDE or MDE are set, perform a full save/restore cycle. */ if (vcpu_read_sys_reg(vcpu, MDSCR_EL1) & (DBG_MDSCR_KDE | DBG_MDSCR_MDE)) vcpu->arch.flags |= KVM_ARM64_DEBUG_DIRTY; @@ -201,7 +231,6 @@ void kvm_arm_setup_debug(struct kvm_vcpu *vcpu) if (has_vhe() && orig_mdcr_el2 != vcpu->arch.mdcr_el2) write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2); - trace_kvm_arm_set_dreg32("MDCR_EL2", vcpu->arch.mdcr_el2); trace_kvm_arm_set_dreg32("MDSCR_EL1", vcpu_read_sys_reg(vcpu, MDSCR_EL1)); } From patchwork Tue Oct 27 17:26:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11861165 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C7D7DC55179 for ; Tue, 27 Oct 2020 17:28:19 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 596D121D7B for ; Tue, 27 Oct 2020 17:28:19 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="XBWVAgNa" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 596D121D7B Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.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=qja8y5Q81tDRsfdrvBVBxQMOdZxKp/Vc/zAlH8Ty4EU=; b=XBWVAgNaQPReU3erL6hXX+BIG UuITvsV835y+Z/q2NDWH+MSGR/aa0US1XvWvAjE2tVZk9wsCqpe7Up9MmQZp6z7jH86Fhd6+HcjmY rEmTCO+J6jL6+ciqClH/UxaQc92RAv3WPIn4fpoy5w6BZC1lLFu3k/uKmRwOXH5cCa75gOKFskecP FTl0qqzaDD6Y8LuV74wYOtD45zdSQnGjiKi9uR1BbSf89llYqud14PKRZKhEVZm+8Cge3zT0Wi4bg rhEUJvbZYr78hCCaB55W5MPFPM0TDoiKIUo2GV0qZnchaQboN+4avpOjo8W87wuANXEQ1/nZXlFpl HsREgrSgw==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSjp-0004pF-0G; Tue, 27 Oct 2020 17:26:25 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSji-0004ml-2y for linux-arm-kernel@lists.infradead.org; Tue, 27 Oct 2020 17:26:18 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 3577315AB; Tue, 27 Oct 2020 10:26:17 -0700 (PDT) Received: from monolith.localdoman (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id E3BE83F719; Tue, 27 Oct 2020 10:26:15 -0700 (PDT) From: Alexandru Elisei To: linux-arm-kernel@lists.infradead.org, kvmarm@lists.cs.columbia.edu Subject: [RFC PATCH v3 02/16] dt-bindings: ARM SPE: Highlight the need for PPI partitions on heterogeneous systems Date: Tue, 27 Oct 2020 17:26:51 +0000 Message-Id: <20201027172705.15181-3-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.29.1 In-Reply-To: <20201027172705.15181-1-alexandru.elisei@arm.com> References: <20201027172705.15181-1-alexandru.elisei@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201027_132618_209734_A5D44034 X-CRM114-Status: GOOD ( 12.91 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: suzuki.poulose@arm.com, maz@kernel.org, james.morse@arm.com, Sudeep Holla , Andrew Murray , will@kernel.org, julien.thierry.kdev@gmail.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Sudeep Holla It's not entirely clear from the binding document that the only way to express ARM SPE affined to a subset of CPUs on a heterogeneous systems is through the use of PPI partitions available in the interrupt controller bindings. Let's make it clear. Signed-off-by: Sudeep Holla Signed-off-by: Andrew Murray Signed-off-by: Alexandru Elisei --- Documentation/devicetree/bindings/arm/spe-pmu.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/spe-pmu.txt b/Documentation/devicetree/bindings/arm/spe-pmu.txt index 93372f2a7df9..4f4815800f6e 100644 --- a/Documentation/devicetree/bindings/arm/spe-pmu.txt +++ b/Documentation/devicetree/bindings/arm/spe-pmu.txt @@ -9,8 +9,9 @@ performance sample data using an in-memory trace buffer. "arm,statistical-profiling-extension-v1" - interrupts : Exactly 1 PPI must be listed. For heterogeneous systems where - SPE is only supported on a subset of the CPUs, please consult - the arm,gic-v3 binding for details on describing a PPI partition. + SPE is only supported on a subset of the CPUs, a PPI partition + described in the arm,gic-v3 binding must be used to describe + the set of CPUs this interrupt is affine to. ** Example: From patchwork Tue Oct 27 17:26:52 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11861153 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 464D0C55179 for ; Tue, 27 Oct 2020 17:27:11 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C964921D24 for ; Tue, 27 Oct 2020 17:27:10 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="2dfC5nil" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C964921D24 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.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=myIE9L6OhoFAHvi98pw8QOcdC7ywpO5aYpwNnFl+h/w=; b=2dfC5nilhzZ4a65wJaJiO9cWp otBm4x15/CaXluPwA76wfuTYt5QjznXYxpHOoNIVkobMO0PRvy6rk3uDQhmAwW2UmUGHVvm1vhdlg riu6vRKKLAnDyv+fQMmGVxRPd37Bjv/ysf6zx6zGnO2dUQ3j6vXPFlZ7v2GH+2gEK7HRpJhHRlQzF RrJkofoVrYsu39lCSYZHy8oZMh1heQmRc2OKI4vU3LDfoLCY769xvFYVXRCqA0892XdewaStrhIx9 +VClP5AmCFlcwTrrbwR5h8HLio8YFzwPqsYhLXa4CuJ19p9MM02rkjKMlC+vuVG5LDCi4X8Ycc0oB tLFyamRLQ==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSk1-0004tG-Fg; Tue, 27 Oct 2020 17:26:37 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSjj-0004nX-AF for linux-arm-kernel@lists.infradead.org; Tue, 27 Oct 2020 17:26:20 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 9901115AD; Tue, 27 Oct 2020 10:26:18 -0700 (PDT) Received: from monolith.localdoman (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 6EE093F719; Tue, 27 Oct 2020 10:26:17 -0700 (PDT) From: Alexandru Elisei To: linux-arm-kernel@lists.infradead.org, kvmarm@lists.cs.columbia.edu Subject: [RFC PATCH v3 03/16] KVM: arm64: Hide SPE from guests Date: Tue, 27 Oct 2020 17:26:52 +0000 Message-Id: <20201027172705.15181-4-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.29.1 In-Reply-To: <20201027172705.15181-1-alexandru.elisei@arm.com> References: <20201027172705.15181-1-alexandru.elisei@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201027_132619_425965_E747A642 X-CRM114-Status: GOOD ( 14.70 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: maz@kernel.org, will@kernel.org, james.morse@arm.com, julien.thierry.kdev@gmail.com, suzuki.poulose@arm.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org When SPE is not implemented, accesses to the SPE registers cause an undefined exception. KVM advertises the presence of SPE in the ID_AA64DFR0_EL1 register, but configures MDCR_EL2 to trap accesses to the registers and injects an undefined exception when that happens. The architecture doesn't allow trapping access to the PMBIDR_EL1 register, which means the guest will be able to read it even if SPE is not advertised in the ID register. However, since it's usually better for a read to unexpectedly succeed than to cause an exception, let's stop advertising the presence of SPE to guests to better match how KVM emulates the architecture. Signed-off-by: Alexandru Elisei --- arch/arm64/kvm/sys_regs.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index d9117bc56237..aa776c006a2a 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -244,6 +244,12 @@ static bool access_vm_reg(struct kvm_vcpu *vcpu, return true; } +static unsigned int spe_visibility(const struct kvm_vcpu *vcpu, + const struct sys_reg_desc *r) +{ + return REG_HIDDEN_GUEST | REG_HIDDEN_USER; +} + static bool access_actlr(struct kvm_vcpu *vcpu, struct sys_reg_params *p, const struct sys_reg_desc *r) @@ -1143,6 +1149,8 @@ static u64 read_id_reg(const struct kvm_vcpu *vcpu, val = cpuid_feature_cap_perfmon_field(val, ID_AA64DFR0_PMUVER_SHIFT, ID_AA64DFR0_PMUVER_8_1); + /* Don't advertise SPE to guests */ + val &= ~(0xfUL << ID_AA64DFR0_PMSVER_SHIFT); } else if (id == SYS_ID_DFR0_EL1) { /* Limit guests to PMUv3 for ARMv8.1 */ val = cpuid_feature_cap_perfmon_field(val, @@ -1590,6 +1598,17 @@ static const struct sys_reg_desc sys_reg_descs[] = { { SYS_DESC(SYS_FAR_EL1), access_vm_reg, reset_unknown, FAR_EL1 }, { SYS_DESC(SYS_PAR_EL1), NULL, reset_unknown, PAR_EL1 }, + { SYS_DESC(SYS_PMSCR_EL1), .visibility = spe_visibility }, + { SYS_DESC(SYS_PMSICR_EL1), .visibility = spe_visibility }, + { SYS_DESC(SYS_PMSIRR_EL1), .visibility = spe_visibility }, + { SYS_DESC(SYS_PMSFCR_EL1), .visibility = spe_visibility }, + { SYS_DESC(SYS_PMSEVFR_EL1), .visibility = spe_visibility }, + { SYS_DESC(SYS_PMSLATFR_EL1), .visibility = spe_visibility }, + { SYS_DESC(SYS_PMSIDR_EL1), .visibility = spe_visibility }, + { SYS_DESC(SYS_PMBLIMITR_EL1), .visibility = spe_visibility }, + { SYS_DESC(SYS_PMBPTR_EL1), .visibility = spe_visibility }, + { SYS_DESC(SYS_PMBSR_EL1), .visibility = spe_visibility }, + { SYS_DESC(SYS_PMINTENSET_EL1), access_pminten, reset_unknown, PMINTENSET_EL1 }, { SYS_DESC(SYS_PMINTENCLR_EL1), access_pminten, reset_unknown, PMINTENSET_EL1 }, From patchwork Tue Oct 27 17:26:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11861161 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9D5CAC388F9 for ; Tue, 27 Oct 2020 17:27:15 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 3240C21D24 for ; Tue, 27 Oct 2020 17:27:15 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="OSYn3tXM" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3240C21D24 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.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=TMoqV9vMKIhe7dlbQibQ3bDYAgT3h7Ggq5Hzn7JDCO8=; b=OSYn3tXM1KKbCIhUZljop5SHh EvXxDJo9T4yQJPDAeJWJnLcg9AKersxopvNxZBlNvjRykEYN1S384SNfS6+CLolUUo3oiWGyxY9CD vMO4n80twksskW7lMwRZvGkbVTVqx67V5cAdlQpU+pSfZNxjxZls6S7n/7tf/uZjoxUVrzy72Ot/m N2/UkQ1EBMT3AqSPTyq0yk+sfaw16/NIBNeJNgGe7/lJ7pYcVcNcQ4Koz5vZUEwdQQGt4jWl09jqG iIqj6Ooi72PDpT/pSMAMBGPWQ95goXC9d3NMV9EKUDYPzZE0DxUzTYXvQYY1f5FrbdtADLcL3AaPj 2TYP2tAZA==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSk5-0004uw-Px; Tue, 27 Oct 2020 17:26:42 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSjk-0004nw-Cf for linux-arm-kernel@lists.infradead.org; Tue, 27 Oct 2020 17:26:21 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id D469E15AB; Tue, 27 Oct 2020 10:26:19 -0700 (PDT) Received: from monolith.localdoman (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id CD1BE3F719; Tue, 27 Oct 2020 10:26:18 -0700 (PDT) From: Alexandru Elisei To: linux-arm-kernel@lists.infradead.org, kvmarm@lists.cs.columbia.edu Subject: [RFC PATCH v3 04/16] arm64: Introduce CPU SPE feature Date: Tue, 27 Oct 2020 17:26:53 +0000 Message-Id: <20201027172705.15181-5-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.29.1 In-Reply-To: <20201027172705.15181-1-alexandru.elisei@arm.com> References: <20201027172705.15181-1-alexandru.elisei@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201027_132620_579010_D6EC183B X-CRM114-Status: GOOD ( 17.31 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: maz@kernel.org, will@kernel.org, james.morse@arm.com, julien.thierry.kdev@gmail.com, suzuki.poulose@arm.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Detect Statistical Profiling Extension (SPE) support using the cpufeatures framework. The presence of SPE is reported via the ARM64_SPE capability. The feature will be necessary for emulating SPE in KVM, because KVM needs that all CPUs have SPE hardware to avoid scheduling a VCPU on a CPU without support. For this reason, the feature type ARM64_CPUCAP_SYSTEM_FEATURE has been selected to disallow hotplugging a CPU which doesn't support SPE. Signed-off-by: Alexandru Elisei --- arch/arm64/include/asm/cpucaps.h | 3 ++- arch/arm64/kernel/cpufeature.c | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h index 42868dbd29fd..10fd094d9a5b 100644 --- a/arch/arm64/include/asm/cpucaps.h +++ b/arch/arm64/include/asm/cpucaps.h @@ -65,7 +65,8 @@ #define ARM64_HAS_ARMv8_4_TTL 55 #define ARM64_HAS_TLB_RANGE 56 #define ARM64_MTE 57 +#define ARM64_SPE 58 -#define ARM64_NCAPS 58 +#define ARM64_NCAPS 59 #endif /* __ASM_CPUCAPS_H */ diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index dcc165b3fc04..4a0f4dc53824 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -1278,6 +1278,18 @@ has_useable_cnp(const struct arm64_cpu_capabilities *entry, int scope) return has_cpuid_feature(entry, scope); } +static bool __maybe_unused +has_usable_spe(const struct arm64_cpu_capabilities *entry, int scope) +{ + u64 pmbidr; + + if (!has_cpuid_feature(entry, scope)) + return false; + + pmbidr = read_sysreg_s(SYS_PMBIDR_EL1); + return !(pmbidr & BIT(SYS_PMBIDR_EL1_P_SHIFT)); +} + /* * This check is triggered during the early boot before the cpufeature * is initialised. Checking the status on the local CPU allows the boot @@ -2003,6 +2015,18 @@ static const struct arm64_cpu_capabilities arm64_features[] = { .min_field_value = 1, .cpu_enable = cpu_enable_cnp, }, +#endif +#ifdef CONFIG_ARM_SPE_PMU + { + .desc = "Statistical Profiling Extension (SPE)", + .capability = ARM64_SPE, + .type = ARM64_CPUCAP_SYSTEM_FEATURE, + .matches = has_usable_spe, + .sys_reg = SYS_ID_AA64DFR0_EL1, + .sign = FTR_UNSIGNED, + .field_pos = ID_AA64DFR0_PMSVER_SHIFT, + .min_field_value = 1, + }, #endif { .desc = "Speculation barrier (SB)", From patchwork Tue Oct 27 17:26:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11861167 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, UNWANTED_LANGUAGE_BODY,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B3C85C55178 for ; Tue, 27 Oct 2020 17:28:51 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 49FF721D24 for ; Tue, 27 Oct 2020 17:28:51 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="d717RdSl" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 49FF721D24 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.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=Ag4aaz4/6hj7LAmVhWEbutWQTtzddAKTpKH9ON+ozTc=; b=d717RdSlfn9nQU58NDdk4n2Zu dmxPXo131VT/n/mwVd6BgwxI9qHYXG5U/4yCaSpfQYaVk23tFaOW11n8jvU0mEDbb10Gu56QCPsQM DID0/JOZwrjytDcwiL5szhmvlfS95mc3mH05WDPt7fhfrZO6rwj/HnKWhrHPmzfOFTiiare+ySXGC R0IEx8rrPIkW2e4J6jlXir43qLRkQq50PgGL2l3unkIMZon1DlSEShs1hC7qJjJC4+t7nT7LTbv5f SkIF5UNgMzQhQ0inUlOFwU0le7VLRbeOpHJCn5+dn5AxmJGBolBqKK+TjRwOsJhvH2wqgz2HqG5Ry L7qp1B+cA==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSkD-0004vq-JS; Tue, 27 Oct 2020 17:26:49 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSjm-0004oT-25 for linux-arm-kernel@lists.infradead.org; Tue, 27 Oct 2020 17:26:23 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 24709139F; Tue, 27 Oct 2020 10:26:21 -0700 (PDT) Received: from monolith.localdoman (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 1D4683F719; Tue, 27 Oct 2020 10:26:20 -0700 (PDT) From: Alexandru Elisei To: linux-arm-kernel@lists.infradead.org, kvmarm@lists.cs.columbia.edu Subject: [RFC PATCH v3 05/16] KVM: arm64: Introduce VCPU SPE feature Date: Tue, 27 Oct 2020 17:26:54 +0000 Message-Id: <20201027172705.15181-6-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.29.1 In-Reply-To: <20201027172705.15181-1-alexandru.elisei@arm.com> References: <20201027172705.15181-1-alexandru.elisei@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201027_132622_626659_FBA91333 X-CRM114-Status: GOOD ( 12.72 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: maz@kernel.org, will@kernel.org, james.morse@arm.com, julien.thierry.kdev@gmail.com, suzuki.poulose@arm.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Introduce the feature bit, but don't allow userspace to set it yet. Signed-off-by: Alexandru Elisei --- arch/arm64/include/uapi/asm/kvm.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index 1c17c3a24411..489e12304dbb 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -106,6 +106,7 @@ struct kvm_regs { #define KVM_ARM_VCPU_SVE 4 /* enable SVE for this CPU */ #define KVM_ARM_VCPU_PTRAUTH_ADDRESS 5 /* VCPU uses address authentication */ #define KVM_ARM_VCPU_PTRAUTH_GENERIC 6 /* VCPU uses generic authentication */ +#define KVM_ARM_VCPU_SPE 7 /* Enable SPE for this CPU */ struct kvm_vcpu_init { __u32 target; From patchwork Tue Oct 27 17:26:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11861155 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 173B0C55178 for ; Tue, 27 Oct 2020 17:27:36 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 852152076B for ; Tue, 27 Oct 2020 17:27:35 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="KUsfoN9i" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 852152076B Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.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=d525hHOYbzyLp+8/FP7hgaQQ86O61lMFgmBpPB+UaK4=; b=KUsfoN9iuyPQB/FYIcXm5eB8E 9plFUP29bAAJdA34QpN9GUVVWH7fI7EXxQia7vDvkNRLAwmF82WS6IGWYOHRi+M/dIiK56+/y7yP0 4Kx+vpD4kFzL9Pbzv/w/2nEfVCanywYvM1K58RT4ODMKFi3u1eRjxi316vPumTMlX/CKF1cScRqws mhSpXuI8N8QdoibdiZ592yQGiSqAlhw8D8G5dHAlnUd6FLxwhBfwJKcu4WjaiQwM/QPYNna8GFRnC F0OGaIzKiffd9vi7eqHHKLQ/J8KYSe8eHL1hObyLF21G8fPG0U6oBxuDBJzHf3Cnth8fVjfpX1Hv+ B09MH/ivg==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSkK-0004yn-JC; Tue, 27 Oct 2020 17:26:56 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSjn-0004nw-1Y for linux-arm-kernel@lists.infradead.org; Tue, 27 Oct 2020 17:26:24 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 6C7EF15AD; Tue, 27 Oct 2020 10:26:22 -0700 (PDT) Received: from monolith.localdoman (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 593F33F719; Tue, 27 Oct 2020 10:26:21 -0700 (PDT) From: Alexandru Elisei To: linux-arm-kernel@lists.infradead.org, kvmarm@lists.cs.columbia.edu Subject: [RFC PATCH v3 06/16] KVM: arm64: Introduce SPE primitives Date: Tue, 27 Oct 2020 17:26:55 +0000 Message-Id: <20201027172705.15181-7-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.29.1 In-Reply-To: <20201027172705.15181-1-alexandru.elisei@arm.com> References: <20201027172705.15181-1-alexandru.elisei@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201027_132623_234683_D7A36415 X-CRM114-Status: GOOD ( 21.25 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: maz@kernel.org, will@kernel.org, james.morse@arm.com, julien.thierry.kdev@gmail.com, suzuki.poulose@arm.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org KVM SPE emulation depends on the configuration option KVM_ARM_SPE and on on having hardware SPE support on all CPUs. The host driver must be compiled-in because we need the SPE interrupt to be enabled; it will be used to kick us out of the guest when the profiling buffer management interrupt is asserted by the GIC (for example, when the buffer is full). Add a VCPU flag to inform KVM that the guest has SPE enabled. It's worth noting that even though the KVM_ARM_SPE config option is gated by the SPE host driver being compiled-in, we don't actually check that the driver was loaded successfully when we advertise SPE support for guests. That's because we can live with the SPE interrupt being disabled. There is a delay between when the SPE hardware asserts the interrupt and when the GIC samples the interrupt line and asserts it to the CPU. If the SPE interrupt is disabled at the GIC level, this delay will be larger, at most a host timer tick. Signed-off-by: Alexandru Elisei --- arch/arm64/include/asm/kvm_host.h | 9 +++++++++ arch/arm64/kvm/Kconfig | 8 ++++++++ include/kvm/arm_spe.h | 19 +++++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 include/kvm/arm_spe.h diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 25d326aecded..43eee197764f 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -406,6 +406,7 @@ struct kvm_vcpu_arch { #define KVM_ARM64_GUEST_HAS_SVE (1 << 5) /* SVE exposed to guest */ #define KVM_ARM64_VCPU_SVE_FINALIZED (1 << 6) /* SVE config completed */ #define KVM_ARM64_GUEST_HAS_PTRAUTH (1 << 7) /* PTRAUTH exposed to guest */ +#define KVM_ARM64_GUEST_HAS_SPE (1 << 8) /* SPE exposed to guest */ #define vcpu_has_sve(vcpu) (system_supports_sve() && \ ((vcpu)->arch.flags & KVM_ARM64_GUEST_HAS_SVE)) @@ -419,6 +420,14 @@ struct kvm_vcpu_arch { #define vcpu_has_ptrauth(vcpu) false #endif +#ifdef CONFIG_KVM_ARM_SPE +#define vcpu_has_spe(vcpu) \ + (cpus_have_final_cap(ARM64_SPE) && \ + ((vcpu)->arch.flags & KVM_ARM64_GUEST_HAS_SPE)) +#else +#define vcpu_has_spe(vcpu) false +#endif + #define vcpu_gp_regs(v) (&(v)->arch.ctxt.regs) /* diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig index 043756db8f6e..8b35c0b806a7 100644 --- a/arch/arm64/kvm/Kconfig +++ b/arch/arm64/kvm/Kconfig @@ -57,6 +57,14 @@ config KVM_ARM_PMU Adds support for a virtual Performance Monitoring Unit (PMU) in virtual machines. +config KVM_ARM_SPE + bool "Virtual Statistical Profiling Extension (SPE) support" + depends on ARM_SPE_PMU + default y + help + Adds support for a virtual Statistical Profiling Extension (SPE) in + virtual machines. + endif # KVM endif # VIRTUALIZATION diff --git a/include/kvm/arm_spe.h b/include/kvm/arm_spe.h new file mode 100644 index 000000000000..db51ef15bf45 --- /dev/null +++ b/include/kvm/arm_spe.h @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2019 ARM Ltd. + */ + +#ifndef __ASM_ARM_KVM_SPE_H +#define __ASM_ARM_KVM_SPE_H + +#ifdef CONFIG_KVM_ARM_SPE +static inline bool kvm_arm_supports_spe(void) +{ + return cpus_have_final_cap(ARM64_SPE); +} + +#else +#define kvm_arm_supports_spe() false + +#endif /* CONFIG_KVM_ARM_SPE */ +#endif /* __ASM_ARM_KVM_SPE_H */ From patchwork Tue Oct 27 17:26:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11861173 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 04F93C4363A for ; Tue, 27 Oct 2020 17:29:19 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7054C21D42 for ; Tue, 27 Oct 2020 17:29:18 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="mQt4rBkN" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7054C21D42 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.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=f8TFBrv+VkyqcWDbi/js8ZZBCvi1Rx5KMM7qXNc/5dM=; b=mQt4rBkNLSpKwa6ca4TXN4AaY f4fFr4lEyNYb9HbCYEvn5fdPjkC69oDbrsB/H/QuAtcve64xPW3cBJEK/dYucEMI77eN3w+UOSRqz 8VJSmmrddRMhX4xTqZjPoIJMY8+fG2RmvdNb7YoFKxZ2llHKjkmAfmfok2bgM8JHz8nnFBNdog+y6 exeCETXbfRPVQ3zPV2kdCVpV3bbhoxaICDgtKsM4g5Z+DYFpqpOJBP3VV+4x4zo+8CL56X7NZylgS 8WfH+jiVOSb9gqQX9CjEzwazlEAl0Z81fJOjpbB5u4KFZc4PJsIMjWijLZCMOnbj6S4vID39l9vUo i8rFIjaAg==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSkS-00050Z-O7; Tue, 27 Oct 2020 17:27:05 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSjo-0004oT-Ft for linux-arm-kernel@lists.infradead.org; Tue, 27 Oct 2020 17:26:25 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id E63C0139F; Tue, 27 Oct 2020 10:26:23 -0700 (PDT) Received: from monolith.localdoman (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id A2F873F719; Tue, 27 Oct 2020 10:26:22 -0700 (PDT) From: Alexandru Elisei To: linux-arm-kernel@lists.infradead.org, kvmarm@lists.cs.columbia.edu Subject: [RFC PATCH v3 07/16] KVM: arm64: Define SPE data structure for each VCPU Date: Tue, 27 Oct 2020 17:26:56 +0000 Message-Id: <20201027172705.15181-8-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.29.1 In-Reply-To: <20201027172705.15181-1-alexandru.elisei@arm.com> References: <20201027172705.15181-1-alexandru.elisei@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201027_132624_685147_F7A2D3F9 X-CRM114-Status: GOOD ( 14.97 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: suzuki.poulose@arm.com, maz@kernel.org, james.morse@arm.com, Sudeep Holla , Andrew Murray , will@kernel.org, julien.thierry.kdev@gmail.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Sudeep Holla Define basic struct for supporting SPE for guest VCPUs. [Andrew M: Add irq_level, rename irq to irq_num for kvm_spe ] [Alexandru E: Reworked patch ] Signed-off-by: Sudeep Holla Signed-off-by: Andrew Murray Signed-off-by: Alexandru Elisei --- arch/arm64/include/asm/kvm_host.h | 2 ++ include/kvm/arm_spe.h | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 43eee197764f..5b68c06930c6 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -35,6 +35,7 @@ #include #include #include +#include #define KVM_MAX_VCPUS VGIC_V3_MAX_CPUS @@ -329,6 +330,7 @@ struct kvm_vcpu_arch { struct vgic_cpu vgic_cpu; struct arch_timer_cpu timer_cpu; struct kvm_pmu pmu; + struct kvm_spe_cpu spe_cpu; /* * Anything that is not used directly from assembly code goes diff --git a/include/kvm/arm_spe.h b/include/kvm/arm_spe.h index db51ef15bf45..46ec447ed013 100644 --- a/include/kvm/arm_spe.h +++ b/include/kvm/arm_spe.h @@ -12,8 +12,17 @@ static inline bool kvm_arm_supports_spe(void) return cpus_have_final_cap(ARM64_SPE); } +struct kvm_spe_cpu { + int irq_num; /* Guest visibile INTID */ + bool irq_level; /* 'true' if interrupt is asserted to the VGIC */ + bool initialized; /* Feature is initialized on VCPU */ +}; + #else #define kvm_arm_supports_spe() false +struct kvm_spe_cpu { +}; + #endif /* CONFIG_KVM_ARM_SPE */ #endif /* __ASM_ARM_KVM_SPE_H */ From patchwork Tue Oct 27 17:26:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11861159 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 81C01C4363A for ; Tue, 27 Oct 2020 17:28:10 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id F2F8C208B8 for ; Tue, 27 Oct 2020 17:28:09 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="jtgqASUv" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org F2F8C208B8 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.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=UOcXExraZNIAlrpFrZhm3xYnTweq85AlvpH654jBXGo=; b=jtgqASUv91nEU3ogeO/6idr+j 6B6wnpOEMWY15ycz5cfT7FuKMswlQRV+p2GNrU+h4H+5jK3PNsDhepC6Be1Ypy2B8zuO45OjHOeFA WjfvGXvwmp7jKejOnnws6WJ1+TSIUaTBvmIwg2yMSmNq+xmdHpRZMjDAg+jG7/cA5q6mZb4q7oMDi flsqklBwkdyGva22vnuksF7wMQ/N8ax6KFp/fWzCWmciRuchWMXbw2tzUvuZB1QAqUuPhnrV8xkrZ p4+7RiqWK+0FVJojlwnWXiXqHNS03U0que8ROYIqRE26rJRx+9iXZeMvNCljIAPNapmuum0dl8cvO igePZZ82A==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSkf-00055s-Bu; Tue, 27 Oct 2020 17:27:17 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSjq-0004oT-3l for linux-arm-kernel@lists.infradead.org; Tue, 27 Oct 2020 17:26:28 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 4BCA3150C; Tue, 27 Oct 2020 10:26:25 -0700 (PDT) Received: from monolith.localdoman (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 267EF3F719; Tue, 27 Oct 2020 10:26:24 -0700 (PDT) From: Alexandru Elisei To: linux-arm-kernel@lists.infradead.org, kvmarm@lists.cs.columbia.edu Subject: [RFC PATCH v3 08/16] KVM: arm64: Add a new VCPU device control group for SPE Date: Tue, 27 Oct 2020 17:26:57 +0000 Message-Id: <20201027172705.15181-9-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.29.1 In-Reply-To: <20201027172705.15181-1-alexandru.elisei@arm.com> References: <20201027172705.15181-1-alexandru.elisei@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201027_132626_335143_FE1D2CB3 X-CRM114-Status: GOOD ( 27.90 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: suzuki.poulose@arm.com, maz@kernel.org, james.morse@arm.com, Sudeep Holla , will@kernel.org, julien.thierry.kdev@gmail.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Sudeep Holla To configure the virtual SPE buffer management interrupt number, we use a VCPU kvm_device ioctl, encapsulating the KVM_ARM_VCPU_SPE_IRQ attribute within the KVM_ARM_VCPU_SPE_CTRL group. After configuring the SPE, userspace is required to call the VCPU ioctl with the attribute KVM_ARM_VCPU_SPE_INIT to initialize SPE on the VCPU. [Alexandru E: Fixed compilation errors, don't allow userspace to set the VCPU feature, removed unused functions, fixed mismatched descriptions, comments and error codes, reworked logic, rebased on top of v5.10-rc1] Signed-off-by: Sudeep Holla Signed-off-by: Alexandru Elisei --- Documentation/virt/kvm/devices/vcpu.rst | 40 ++++++++ arch/arm64/include/uapi/asm/kvm.h | 3 + arch/arm64/kvm/Makefile | 1 + arch/arm64/kvm/guest.c | 9 ++ arch/arm64/kvm/reset.c | 23 +++++ arch/arm64/kvm/spe.c | 129 ++++++++++++++++++++++++ include/kvm/arm_spe.h | 27 +++++ include/uapi/linux/kvm.h | 1 + 8 files changed, 233 insertions(+) create mode 100644 arch/arm64/kvm/spe.c diff --git a/Documentation/virt/kvm/devices/vcpu.rst b/Documentation/virt/kvm/devices/vcpu.rst index 2acec3b9ef65..6135b9827fbe 100644 --- a/Documentation/virt/kvm/devices/vcpu.rst +++ b/Documentation/virt/kvm/devices/vcpu.rst @@ -161,3 +161,43 @@ Specifies the base address of the stolen time structure for this VCPU. The base address must be 64 byte aligned and exist within a valid guest memory region. See Documentation/virt/kvm/arm/pvtime.rst for more information including the layout of the stolen time structure. + +4. GROUP: KVM_ARM_VCPU_SPE_CTRL +=============================== + +:Architectures: ARM64 + +4.1 ATTRIBUTE: KVM_ARM_VCPU_SPE_IRQ +----------------------------------- + +:Parameters: in kvm_device_attr.addr the address for the SPE buffer management + interrupt is a pointer to an int + +Returns: + + ======= ======================================================== + -EBUSY The SPE buffer management interrupt is already set + -EINVAL Invalid SPE overflow interrupt number + -EFAULT Could not read the buffer management interrupt number + -ENXIO SPE not supported or not properly configured + ======= ======================================================== + +A value describing the SPE (Statistical Profiling Extension) overflow interrupt +number for this vcpu. This interrupt should be a PPI and the interrupt type and +number must be same for each vcpu. + +4.2 ATTRIBUTE: KVM_ARM_VCPU_SPE_INIT +------------------------------------ + +:Parameters: no additional parameter in kvm_device_attr.addr + +Returns: + + ======= ====================================================== + -EBUSY SPE already initialized + -ENODEV GIC not initialized + -ENXIO SPE not supported or not properly configured + ======= ====================================================== + +Request the initialization of the SPE. Must be done after initializing the +in-kernel irqchip and after setting the interrupt number for the VCPU. diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index 489e12304dbb..ca57dfb7abf0 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -360,6 +360,9 @@ struct kvm_vcpu_events { #define KVM_ARM_VCPU_TIMER_IRQ_PTIMER 1 #define KVM_ARM_VCPU_PVTIME_CTRL 2 #define KVM_ARM_VCPU_PVTIME_IPA 0 +#define KVM_ARM_VCPU_SPE_CTRL 3 +#define KVM_ARM_VCPU_SPE_IRQ 0 +#define KVM_ARM_VCPU_SPE_INIT 1 /* KVM_IRQ_LINE irq field index values */ #define KVM_ARM_IRQ_VCPU2_SHIFT 28 diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile index 1504c81fbf5d..f6e76f64ffbe 100644 --- a/arch/arm64/kvm/Makefile +++ b/arch/arm64/kvm/Makefile @@ -25,3 +25,4 @@ kvm-y := $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o \ vgic/vgic-its.o vgic/vgic-debug.o kvm-$(CONFIG_KVM_ARM_PMU) += pmu-emul.o +kvm-$(CONFIG_KVM_ARM_SPE) += spe.o diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index dfb5218137ca..2ba790eeb782 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c @@ -926,6 +926,9 @@ int kvm_arm_vcpu_arch_set_attr(struct kvm_vcpu *vcpu, case KVM_ARM_VCPU_PVTIME_CTRL: ret = kvm_arm_pvtime_set_attr(vcpu, attr); break; + case KVM_ARM_VCPU_SPE_CTRL: + ret = kvm_arm_spe_set_attr(vcpu, attr); + break; default: ret = -ENXIO; break; @@ -949,6 +952,9 @@ int kvm_arm_vcpu_arch_get_attr(struct kvm_vcpu *vcpu, case KVM_ARM_VCPU_PVTIME_CTRL: ret = kvm_arm_pvtime_get_attr(vcpu, attr); break; + case KVM_ARM_VCPU_SPE_CTRL: + ret = kvm_arm_spe_get_attr(vcpu, attr); + break; default: ret = -ENXIO; break; @@ -972,6 +978,9 @@ int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu, case KVM_ARM_VCPU_PVTIME_CTRL: ret = kvm_arm_pvtime_has_attr(vcpu, attr); break; + case KVM_ARM_VCPU_SPE_CTRL: + ret = kvm_arm_spe_has_attr(vcpu, attr); + break; default: ret = -ENXIO; break; diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index f32490229a4c..4dc205fa4be1 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -87,6 +87,9 @@ int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_ARM_PTRAUTH_GENERIC: r = system_has_full_ptr_auth(); break; + case KVM_CAP_ARM_SPE: + r = kvm_arm_supports_spe(); + break; default: r = 0; } @@ -223,6 +226,19 @@ static int kvm_vcpu_enable_ptrauth(struct kvm_vcpu *vcpu) return 0; } +static int kvm_vcpu_enable_spe(struct kvm_vcpu *vcpu) +{ + if (!kvm_arm_supports_spe()) + return -EINVAL; + + /* SPE is disabled if the PE is in AArch32 state */ + if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features)) + return -EINVAL; + + vcpu->arch.flags |= KVM_ARM64_GUEST_HAS_SPE; + return 0; +} + /** * kvm_reset_vcpu - sets core registers and sys_regs to reset value * @vcpu: The VCPU pointer @@ -274,6 +290,13 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu) } } + if (test_bit(KVM_ARM_VCPU_SPE, vcpu->arch.features)) { + if (kvm_vcpu_enable_spe(vcpu)) { + ret = -EINVAL; + goto out; + } + } + switch (vcpu->arch.target) { default: if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features)) { diff --git a/arch/arm64/kvm/spe.c b/arch/arm64/kvm/spe.c new file mode 100644 index 000000000000..f91a52cd7cd3 --- /dev/null +++ b/arch/arm64/kvm/spe.c @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2019 ARM Ltd. + */ + +#include +#include +#include + +#include +#include + +static bool kvm_arm_vcpu_supports_spe(struct kvm_vcpu *vcpu) +{ + if (!vcpu_has_spe(vcpu)) + return false; + + if (!irqchip_in_kernel(vcpu->kvm)) + return false; + + return true; +} + +static int kvm_arm_spe_init(struct kvm_vcpu *vcpu) +{ + if (!kvm_arm_spe_irq_initialized(vcpu)) + return -ENXIO; + + if (!vgic_initialized(vcpu->kvm)) + return -ENODEV; + + if (kvm_arm_spe_vcpu_initialized(vcpu)) + return -EBUSY; + + if (kvm_vgic_set_owner(vcpu, vcpu->arch.spe_cpu.irq_num, &vcpu->arch.spe_cpu)) + return -ENXIO; + + vcpu->arch.spe_cpu.initialized = true; + + return 0; +} + +static bool kvm_arm_spe_irq_is_valid(struct kvm *kvm, int irq) +{ + int i; + struct kvm_vcpu *vcpu; + + /* The SPE overflow interrupt can be a PPI only */ + if (!irq_is_ppi(irq)) + return false; + + kvm_for_each_vcpu(i, vcpu, kvm) { + if (!kvm_arm_spe_irq_initialized(vcpu)) + continue; + + if (vcpu->arch.spe_cpu.irq_num != irq) + return false; + } + + return true; +} + +int kvm_arm_spe_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr) +{ + switch (attr->attr) { + case KVM_ARM_VCPU_SPE_IRQ: { + int __user *uaddr = (int __user *)(long)attr->addr; + int irq; + + if (!kvm_arm_vcpu_supports_spe(vcpu)) + return -ENXIO; + + if (get_user(irq, uaddr)) + return -EFAULT; + + if (!kvm_arm_spe_irq_is_valid(vcpu->kvm, irq)) + return -EINVAL; + + if (kvm_arm_spe_irq_initialized(vcpu)) + return -EBUSY; + + kvm_debug("Set kvm ARM SPE irq: %d\n", irq); + vcpu->arch.spe_cpu.irq_num = irq; + + return 0; + } + case KVM_ARM_VCPU_SPE_INIT: + return kvm_arm_spe_init(vcpu); + } + + return -ENXIO; +} + +int kvm_arm_spe_get_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr) +{ + switch (attr->attr) { + case KVM_ARM_VCPU_SPE_IRQ: { + int __user *uaddr = (int __user *)(long)attr->addr; + int irq; + + if (!kvm_arm_vcpu_supports_spe(vcpu)) + return -ENXIO; + + if (!kvm_arm_spe_irq_initialized(vcpu)) + return -ENXIO; + + irq = vcpu->arch.spe_cpu.irq_num; + if (put_user(irq, uaddr)) + return -EFAULT; + + return 0; + } + } + + return -ENXIO; +} + +int kvm_arm_spe_has_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr) +{ + switch (attr->attr) { + case KVM_ARM_VCPU_SPE_IRQ: + fallthrough; + case KVM_ARM_VCPU_SPE_INIT: + if (kvm_arm_vcpu_supports_spe(vcpu)) + return 0; + } + + return -ENXIO; +} diff --git a/include/kvm/arm_spe.h b/include/kvm/arm_spe.h index 46ec447ed013..0275e8097529 100644 --- a/include/kvm/arm_spe.h +++ b/include/kvm/arm_spe.h @@ -18,11 +18,38 @@ struct kvm_spe_cpu { bool initialized; /* Feature is initialized on VCPU */ }; +#define kvm_arm_spe_irq_initialized(v) \ + ((v)->arch.spe_cpu.irq_num >= VGIC_NR_SGIS && \ + (v)->arch.spe_cpu.irq_num < VGIC_MAX_PRIVATE) +#define kvm_arm_spe_vcpu_initialized(v) ((v)->arch.spe_cpu.initialized) + +int kvm_arm_spe_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr); +int kvm_arm_spe_get_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr); +int kvm_arm_spe_has_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr); + #else #define kvm_arm_supports_spe() false struct kvm_spe_cpu { }; +#define kvm_arm_spe_irq_initialized(v) false +#define kvm_arm_spe_vcpu_initialized(v) false + +static inline int kvm_arm_spe_set_attr(struct kvm_vcpu *vcpu, + struct kvm_device_attr *attr) +{ + return -ENXIO; +} +static inline int kvm_arm_spe_get_attr(struct kvm_vcpu *vcpu, + struct kvm_device_attr *attr) +{ + return -ENXIO; +} +static inline int kvm_arm_spe_has_attr(struct kvm_vcpu *vcpu, + struct kvm_device_attr *attr) +{ + return -ENXIO; +} #endif /* CONFIG_KVM_ARM_SPE */ #endif /* __ASM_ARM_KVM_SPE_H */ diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index ca41220b40b8..96228b823711 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1053,6 +1053,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_X86_USER_SPACE_MSR 188 #define KVM_CAP_X86_MSR_FILTER 189 #define KVM_CAP_ENFORCE_PV_FEATURE_CPUID 190 +#define KVM_CAP_ARM_SPE 191 #ifdef KVM_CAP_IRQ_ROUTING From patchwork Tue Oct 27 17:26:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11861175 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 12E7FC4363A for ; Tue, 27 Oct 2020 17:30:17 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 79A8620657 for ; Tue, 27 Oct 2020 17:30:16 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="ILxQAtfL" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 79A8620657 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.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=s4oo2MRoAp9QmE4nxPp0boa3Vg+3+6+kJ/41QkWZRck=; b=ILxQAtfLC5fMCozvPEh/kubAp XV398BNLKP0vAwJFsCG7Gb5f9WTLcqnZ/64gl437fb43oTkxMltQYH4U/BiNG6fHEO7i2c1KxPfHb TIN6qaHVWMTcZm55+/c6pFdNWyRzLmCzIb2bPan7IiJYYTCKAyExlyw8oscFULMfsWhxXnfFX/e70 4Z8s9Lxrmat4WSxdhrcDnygki/S57NtL7RPLTsrn9VKztZJtT8WcbQUT1pDl48CE8wMjPIspJ201W b/XSE87ENr585KkI2HJfnldTE8eYKOBJfU45ujRwEG2i49ByIcz//cwqF6M0UdcogAk+H3ch4lydY 1WibYdosA==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSl8-0005HE-V3; Tue, 27 Oct 2020 17:27:47 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSjr-0004qJ-8z for linux-arm-kernel@lists.infradead.org; Tue, 27 Oct 2020 17:26:28 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 8A4B2139F; Tue, 27 Oct 2020 10:26:26 -0700 (PDT) Received: from monolith.localdoman (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 7FE1C3F719; Tue, 27 Oct 2020 10:26:25 -0700 (PDT) From: Alexandru Elisei To: linux-arm-kernel@lists.infradead.org, kvmarm@lists.cs.columbia.edu Subject: [RFC PATCH v3 09/16] KVM: arm64: Use separate function for the mapping size in user_mem_abort() Date: Tue, 27 Oct 2020 17:26:58 +0000 Message-Id: <20201027172705.15181-10-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.29.1 In-Reply-To: <20201027172705.15181-1-alexandru.elisei@arm.com> References: <20201027172705.15181-1-alexandru.elisei@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201027_132627_434804_A2EE77F7 X-CRM114-Status: GOOD ( 14.85 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: maz@kernel.org, will@kernel.org, james.morse@arm.com, julien.thierry.kdev@gmail.com, suzuki.poulose@arm.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org user_mem_abort() is already a long and complex function, let's make it slightly easier to understand by abstracting the algorithm for choosing the stage 2 IPA entry size into its own function. This also makes it possible to reuse the code when guest SPE support will be added. Signed-off-by: Alexandru Elisei --- arch/arm64/kvm/mmu.c | 55 ++++++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c index 19aacc7d64de..c3c43555490d 100644 --- a/arch/arm64/kvm/mmu.c +++ b/arch/arm64/kvm/mmu.c @@ -738,12 +738,43 @@ transparent_hugepage_adjust(struct kvm_memory_slot *memslot, return PAGE_SIZE; } +static short stage2_max_pageshift(struct kvm_memory_slot *memslot, + struct vm_area_struct *vma, hva_t hva, + bool *force_pte) +{ + short pageshift; + + *force_pte = false; + + if (is_vm_hugetlb_page(vma)) + pageshift = huge_page_shift(hstate_vma(vma)); + else + pageshift = PAGE_SHIFT; + + if (memslot_is_logging(memslot) || (vma->vm_flags & VM_PFNMAP)) { + *force_pte = true; + pageshift = PAGE_SHIFT; + } + + if (pageshift == PUD_SHIFT && + !fault_supports_stage2_huge_mapping(memslot, hva, PUD_SIZE)) + pageshift = PMD_SHIFT; + + if (pageshift == PMD_SHIFT && + !fault_supports_stage2_huge_mapping(memslot, hva, PMD_SIZE)) { + *force_pte = true; + pageshift = PAGE_SHIFT; + } + + return pageshift; +} + static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, struct kvm_memory_slot *memslot, unsigned long hva, unsigned long fault_status) { int ret = 0; - bool write_fault, writable, force_pte = false; + bool write_fault, writable, force_pte; bool exec_fault; bool device = false; unsigned long mmu_seq; @@ -776,27 +807,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, return -EFAULT; } - if (is_vm_hugetlb_page(vma)) - vma_shift = huge_page_shift(hstate_vma(vma)); - else - vma_shift = PAGE_SHIFT; - - if (logging_active || - (vma->vm_flags & VM_PFNMAP)) { - force_pte = true; - vma_shift = PAGE_SHIFT; - } - - if (vma_shift == PUD_SHIFT && - !fault_supports_stage2_huge_mapping(memslot, hva, PUD_SIZE)) - vma_shift = PMD_SHIFT; - - if (vma_shift == PMD_SHIFT && - !fault_supports_stage2_huge_mapping(memslot, hva, PMD_SIZE)) { - force_pte = true; - vma_shift = PAGE_SHIFT; - } - + vma_shift = stage2_max_pageshift(memslot, vma, hva, &force_pte); vma_pagesize = 1UL << vma_shift; if (vma_pagesize == PMD_SIZE || vma_pagesize == PUD_SIZE) fault_ipa &= ~(vma_pagesize - 1); From patchwork Tue Oct 27 17:26:59 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11861181 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 237C6C4363A for ; Tue, 27 Oct 2020 17:30:53 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A440820878 for ; Tue, 27 Oct 2020 17:30:52 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="LqzVlXk7" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org A440820878 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.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=xSNZqRUB9GDK17hgOOEiKxCT6u4zmCAazZrK8yMhjSU=; b=LqzVlXk7XR9L/IOIjtEddOvYe CSKP/r0t/yMKY1ugdLExVFT3J1BjrjvrQsyFr40snmFKWWmTeK0r1jgJqDCNYDBKfHV+zYekwNyjw 6Gvt/gQbDa0jWJILqDeTAPVlXKbKMYs0rhwI9Rh+UbTABmIj9f9TLTolqwKP/IzecI450wetzr2QZ ukO1LMOsl4ZXXIR13GsCIHIZHbjPSoas7Y19aqeqfN38ASiQDK773zJ00/75hHPdlMjw8JtmK+wNF z5MHbeO0fiD9B3eg3muaWORmK8z/L8Kj+qMAGHK7KnTlkFYl+VUr27S0ari3ljrcfmYekhxh3l21f glRBtS1BQ==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSlc-0005Uw-W3; Tue, 27 Oct 2020 17:28:17 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSjs-0004qg-GZ for linux-arm-kernel@lists.infradead.org; Tue, 27 Oct 2020 17:26:31 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id E507A15AB; Tue, 27 Oct 2020 10:26:27 -0700 (PDT) Received: from monolith.localdoman (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id BEB7F3F719; Tue, 27 Oct 2020 10:26:26 -0700 (PDT) From: Alexandru Elisei To: linux-arm-kernel@lists.infradead.org, kvmarm@lists.cs.columbia.edu Subject: [RFC PATCH v3 10/16] KVM: arm64: Add a new VM device control group for SPE Date: Tue, 27 Oct 2020 17:26:59 +0000 Message-Id: <20201027172705.15181-11-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.29.1 In-Reply-To: <20201027172705.15181-1-alexandru.elisei@arm.com> References: <20201027172705.15181-1-alexandru.elisei@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201027_132628_728274_056EEC0E X-CRM114-Status: GOOD ( 37.33 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: maz@kernel.org, will@kernel.org, james.morse@arm.com, julien.thierry.kdev@gmail.com, suzuki.poulose@arm.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Stage 2 faults triggered by the profiling buffer attempting to write to memory are reported by the SPE hardware by asserting a buffer management event interrupt. Interrupts are by their nature asynchronous, which means that the guest might have changed its stage 1 translation tables since the attempted write. SPE reports the guest virtual address that caused the data abort, but not the IPA, which means that KVM would have to walk the guest's stage 1 tables to find the IPA; using the AT instruction to walk the guest's tables in hardware is not an option because it doesn't report the IPA in the case of a stage 2 fault on a stage 1 table walk. Fix both problems by pre-mapping the guest's memory at stage 2 with write permissions to avoid any faults. Userspace calls mlock() on the VMAs that back the guest's memory, pinning the pages in memory, then tells KVM to map the memory at stage 2 by using the VM control group KVM_ARM_VM_SPE_CTRL with the attribute KVM_ARM_VM_SPE_FINALIZE. KVM will map all writable VMAs which have the VM_LOCKED flag set. Hugetlb VMAs are practically pinned in memory after they are faulted in and mlock() doesn't set the VM_LOCKED flag, and just faults the pages in; KVM will treat hugetlb VMAs like they have the VM_LOCKED flag and will also map them, faulting them in if necessary, when handling the ioctl. VM live migration relies on a bitmap of dirty pages. This bitmap is created by write-protecting a memslot and updating it as KVM handles stage 2 write faults. Because KVM cannot handle stage 2 faults reported by the profiling buffer, it will not pre-map a logging memslot. This effectively means that profiling is not available when the VM is configured for live migration. Signed-off-by: Alexandru Elisei --- Documentation/virt/kvm/devices/vm.rst | 28 +++++ arch/arm64/include/asm/kvm_host.h | 5 + arch/arm64/include/asm/kvm_mmu.h | 2 + arch/arm64/include/uapi/asm/kvm.h | 3 + arch/arm64/kvm/arm.c | 78 +++++++++++- arch/arm64/kvm/guest.c | 48 ++++++++ arch/arm64/kvm/mmu.c | 169 ++++++++++++++++++++++++++ arch/arm64/kvm/spe.c | 81 ++++++++++++ include/kvm/arm_spe.h | 36 ++++++ 9 files changed, 448 insertions(+), 2 deletions(-) diff --git a/Documentation/virt/kvm/devices/vm.rst b/Documentation/virt/kvm/devices/vm.rst index 0aa5b1cfd700..b70798a72d8a 100644 --- a/Documentation/virt/kvm/devices/vm.rst +++ b/Documentation/virt/kvm/devices/vm.rst @@ -314,3 +314,31 @@ Allows userspace to query the status of migration mode. if it is enabled :Returns: -EFAULT if the given address is not accessible from kernel space; 0 in case of success. + +6. GROUP: KVM_ARM_VM_SPE_CTRL +=============================== + +:Architectures: arm64 + +6.1. ATTRIBUTE: KVM_ARM_VM_SPE_FINALIZE +----------------------------------------- + +Finalizes the creation of the SPE feature by mapping the guest memory in the +stage 2 table. Guest memory must be readable, writable and pinned in RAM, which +is achieved with an mlock() system call; the memory can be backed by a hugetlbfs +file. Memory regions from read-only or dirty page logging enabled memslots will +be ignored. After the call, no changes to the guest memory, including to its +contents, are permitted. + +Subsequent KVM_ARM_VCPU_INIT calls will cause the memory to become unmapped and +the feature must be finalized again before any VCPU can run. + +If any VCPUs are run before finalizing the feature, KVM_RUN will return -EPERM. + +:Parameters: none +:Returns: -EAGAIN if guest memory has been modified while the call was + executing + -EBUSY if the feature is already initialized + -EFAULT if an address backing the guest memory is invalid + -ENXIO if SPE is not supported or not properly configured + 0 in case of success diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 5b68c06930c6..27f581750c6e 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -92,6 +92,7 @@ struct kvm_s2_mmu { struct kvm_arch { struct kvm_s2_mmu mmu; + struct kvm_spe spe; /* VTCR_EL2 value for this VM */ u64 vtcr; @@ -612,6 +613,10 @@ void kvm_arm_vcpu_init_debug(struct kvm_vcpu *vcpu); void kvm_arm_setup_debug(struct kvm_vcpu *vcpu); void kvm_arm_clear_debug(struct kvm_vcpu *vcpu); void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu); +int kvm_arm_vm_arch_set_attr(struct kvm *kvm, struct kvm_device_attr *attr); +int kvm_arm_vm_arch_get_attr(struct kvm *kvm, struct kvm_device_attr *attr); +int kvm_arm_vm_arch_has_attr(struct kvm *kvm, struct kvm_device_attr *attr); + int kvm_arm_vcpu_arch_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr); int kvm_arm_vcpu_arch_get_attr(struct kvm_vcpu *vcpu, diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h index 331394306cce..bad94662bbed 100644 --- a/arch/arm64/include/asm/kvm_mmu.h +++ b/arch/arm64/include/asm/kvm_mmu.h @@ -124,6 +124,8 @@ int kvm_init_stage2_mmu(struct kvm *kvm, struct kvm_s2_mmu *mmu); void kvm_free_stage2_pgd(struct kvm_s2_mmu *mmu); int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa, phys_addr_t pa, unsigned long size, bool writable); +int kvm_map_locked_memslot(struct kvm *kvm, struct kvm_memory_slot *memslot, + enum kvm_pgtable_prot prot); int kvm_handle_guest_abort(struct kvm_vcpu *vcpu); diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index ca57dfb7abf0..8876e564ba56 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -350,6 +350,9 @@ struct kvm_vcpu_events { #define KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES 3 #define KVM_DEV_ARM_ITS_CTRL_RESET 4 +#define KVM_ARM_VM_SPE_CTRL 0 +#define KVM_ARM_VM_SPE_FINALIZE 0 + /* Device Control API on vcpu fd */ #define KVM_ARM_VCPU_PMU_V3_CTRL 0 #define KVM_ARM_VCPU_PMU_V3_IRQ 0 diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index e51d8f328c7e..2d98248f2c66 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -41,6 +41,7 @@ #include #include #include +#include #ifdef REQUIRES_VIRT __asm__(".arch_extension virt"); @@ -653,6 +654,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) if (unlikely(!kvm_vcpu_initialized(vcpu))) return -ENOEXEC; + if (vcpu_has_spe(vcpu) && unlikely(!kvm_arm_spe_finalized(vcpu->kvm))) + return -EPERM; + ret = kvm_vcpu_first_run_init(vcpu); if (ret) return ret; @@ -982,12 +986,22 @@ static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu, * ensuring that the data side is always coherent. We still * need to invalidate the I-cache though, as FWB does *not* * imply CTR_EL0.DIC. + * + * If the guest has SPE, we need to unmap the entire address space to + * allow for any changes to the VM memory made by userspace to propagate + * to the stage 2 tables when SPE is re-finalized; this also makes sure + * we keep the userspace and the guest's view of the memory contents + * synchronized. */ if (vcpu->arch.has_run_once) { - if (!cpus_have_final_cap(ARM64_HAS_STAGE2_FWB)) + if (!cpus_have_final_cap(ARM64_HAS_STAGE2_FWB) || + vcpu_has_spe(vcpu)) { stage2_unmap_vm(vcpu->kvm); - else + if (vcpu_has_spe(vcpu)) + kvm_arm_spe_notify_vcpu_init(vcpu); + } else { __flush_icache_all(); + } } vcpu_reset_hcr(vcpu); @@ -1045,6 +1059,45 @@ static int kvm_arm_vcpu_has_attr(struct kvm_vcpu *vcpu, return ret; } +static int kvm_arm_vm_set_attr(struct kvm *kvm, struct kvm_device_attr *attr) +{ + int ret = -ENXIO; + + switch (attr->group) { + default: + ret = kvm_arm_vm_arch_set_attr(kvm, attr); + break; + } + + return ret; +} + +static int kvm_arm_vm_get_attr(struct kvm *kvm, struct kvm_device_attr *attr) +{ + int ret = -ENXIO; + + switch (attr->group) { + default: + ret = kvm_arm_vm_arch_get_attr(kvm, attr); + break; + } + + return ret; +} + +static int kvm_arm_vm_has_attr(struct kvm *kvm, struct kvm_device_attr *attr) +{ + int ret = -ENXIO; + + switch (attr->group) { + default: + ret = kvm_arm_vm_arch_has_attr(kvm, attr); + break; + } + + return ret; +} + static int kvm_arm_vcpu_get_events(struct kvm_vcpu *vcpu, struct kvm_vcpu_events *events) { @@ -1259,6 +1312,27 @@ long kvm_arch_vm_ioctl(struct file *filp, return 0; } + case KVM_SET_DEVICE_ATTR: { + struct kvm_device_attr attr; + + if (copy_from_user(&attr, argp, sizeof(attr))) + return -EFAULT; + return kvm_arm_vm_set_attr(kvm, &attr); + } + case KVM_GET_DEVICE_ATTR: { + struct kvm_device_attr attr; + + if (copy_from_user(&attr, argp, sizeof(attr))) + return -EFAULT; + return kvm_arm_vm_get_attr(kvm, &attr); + } + case KVM_HAS_DEVICE_ATTR: { + struct kvm_device_attr attr; + + if (copy_from_user(&attr, argp, sizeof(attr))) + return -EFAULT; + return kvm_arm_vm_has_attr(kvm, &attr); + } default: return -EINVAL; } diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index 2ba790eeb782..d0dc4bdb8b4a 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c @@ -988,3 +988,51 @@ int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu, return ret; } + +int kvm_arm_vm_arch_set_attr(struct kvm *kvm, struct kvm_device_attr *attr) +{ + int ret; + + switch (attr->group) { + case KVM_ARM_VM_SPE_CTRL: + ret = kvm_arm_vm_spe_set_attr(kvm, attr); + break; + default: + ret = -ENXIO; + break; + } + + return ret; +} + +int kvm_arm_vm_arch_get_attr(struct kvm *kvm, struct kvm_device_attr *attr) +{ + int ret; + + switch (attr->group) { + case KVM_ARM_VM_SPE_CTRL: + ret = kvm_arm_vm_spe_get_attr(kvm, attr); + break; + default: + ret = -ENXIO; + break; + } + + return ret; +} + +int kvm_arm_vm_arch_has_attr(struct kvm *kvm, struct kvm_device_attr *attr) +{ + int ret; + + switch (attr->group) { + case KVM_ARM_VM_SPE_CTRL: + ret = kvm_arm_vm_spe_has_attr(kvm, attr); + break; + default: + ret = -ENXIO; + break; + } + + return ret; +} diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c index c3c43555490d..31b2216a5881 100644 --- a/arch/arm64/kvm/mmu.c +++ b/arch/arm64/kvm/mmu.c @@ -1365,6 +1365,175 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, return ret; } +static int stage2_map_vma(struct kvm *kvm, + struct kvm_memory_slot *memslot, + struct vm_area_struct *vma, + enum kvm_pgtable_prot prot, + unsigned long mmu_seq, hva_t *hvap, + struct kvm_mmu_memory_cache *cache) +{ + struct kvm_pgtable *pgt = kvm->arch.mmu.pgt; + unsigned long stage2_pagesize, remaining; + bool force_pte, writable; + hva_t hva, hva_end; + kvm_pfn_t pfn; + gpa_t gpa; + gfn_t gfn; + int ret; + + hva = max(memslot->userspace_addr, vma->vm_start); + hva_end = min(vma->vm_end, memslot->userspace_addr + + (memslot->npages << PAGE_SHIFT)); + + gpa = (memslot->base_gfn << PAGE_SHIFT) + hva - memslot->userspace_addr; + gfn = gpa >> PAGE_SHIFT; + + stage2_pagesize = 1UL << stage2_max_pageshift(memslot, vma, hva, &force_pte); + + while (hva < hva_end) { + ret = kvm_mmu_topup_memory_cache(cache, + kvm_mmu_cache_min_pages(kvm)); + if (ret) + return ret; + + /* + * We start mapping with the highest possible page size, so the + * gpa and gfn will always be properly aligned to the current + * page size. + */ + pfn = __gfn_to_pfn_memslot(memslot, gfn, false, NULL, true, &writable); + if (pfn == KVM_PFN_ERR_HWPOISON) + return -EFAULT; + if (is_error_noslot_pfn(pfn)) + return -EFAULT; + /* Can only happen if naughty userspace changed the VMA. */ + if (kvm_is_device_pfn(pfn) || !writable) + return -EAGAIN; + + spin_lock(&kvm->mmu_lock); + if (mmu_notifier_retry(kvm, mmu_seq)) { + spin_unlock(&kvm->mmu_lock); + return -EAGAIN; + } + + remaining = hva_end - hva; + if (stage2_pagesize == PUD_SIZE && remaining < PUD_SIZE) + stage2_pagesize = PMD_SIZE; + if (stage2_pagesize == PMD_SIZE && remaining < PMD_SIZE) { + force_pte = true; + stage2_pagesize = PAGE_SIZE; + } + + if (!force_pte && stage2_pagesize == PAGE_SIZE) + /* + * The hva and gpa will always be PMD aligned if + * hva is backed by a transparent huge page. gpa will + * not be modified and it's not necessary to recompute + * hva. + */ + stage2_pagesize = transparent_hugepage_adjust(memslot, hva, &pfn, &gpa); + + ret = kvm_pgtable_stage2_map(pgt, gpa, stage2_pagesize, + __pfn_to_phys(pfn), prot, cache); + spin_unlock(&kvm->mmu_lock); + + kvm_set_pfn_accessed(pfn); + kvm_release_pfn_dirty(pfn); + + if (ret) + return ret; + else if (hva < hva_end) + cond_resched(); + + hva += stage2_pagesize; + gpa += stage2_pagesize; + gfn = gpa >> PAGE_SHIFT; + } + + *hvap = hva; + return 0; +} + +int kvm_map_locked_memslot(struct kvm *kvm, struct kvm_memory_slot *memslot, + enum kvm_pgtable_prot prot) +{ + struct kvm_mmu_memory_cache cache = { 0, __GFP_ZERO, NULL, }; + struct vm_area_struct *vma; + unsigned long mmu_seq; + hva_t hva, hva_memslot_end; + int ret; + + lockdep_assert_held(&kvm->slots_lock); + + if (!(prot & KVM_PGTABLE_PROT_R)) + return -EPERM; + if ((prot & KVM_PGTABLE_PROT_W) && (memslot->flags & KVM_MEM_READONLY)) + return -EPERM; + + hva = memslot->userspace_addr; + hva_memslot_end = memslot->userspace_addr + (memslot->npages << PAGE_SHIFT); + + /* + * Be extra careful here in case userspace is messing with the VMAs + * backing the memslot. + */ + mmu_seq = kvm->mmu_notifier_seq; + smp_rmb(); + + /* + * A memslot might span multiple VMAs and any holes between them, while + * a VMA might span multiple memslots (see + * kvm_arch_prepare_memory_region()). Take the intersection of the VMAs + * with the memslot. + */ + do { + mmap_read_lock(current->mm); + vma = find_vma(current->mm, hva); + /* + * find_vma() returns first VMA with hva < vma->vm_end, which + * means that it is possible for the VMA to start *after* the + * end of the memslot. + */ + if (!vma || vma->vm_start >= hva_memslot_end) { + mmap_read_unlock(current->mm); + return 0; + } + + /* + * VM_LOCKED pages are put in the unevictable LRU list and + * hugetlb pages are not put in any LRU list; both will stay + * pinned in memory. + */ + if (!(vma->vm_flags & VM_LOCKED) && !is_vm_hugetlb_page(vma)) { + /* Go to next VMA. */ + hva = vma->vm_end; + mmap_read_unlock(current->mm); + continue; + } + if (!(vma->vm_flags & VM_READ) || + ((prot & KVM_PGTABLE_PROT_W) && !(vma->vm_flags & VM_WRITE))) { + /* Go to next VMA. */ + hva = vma->vm_end; + mmap_read_unlock(current->mm); + continue; + } + mmap_read_unlock(current->mm); + + ret = stage2_map_vma(kvm, memslot, vma, prot, mmu_seq, &hva, &cache); + if (ret) + return ret; + } while (hva < hva_memslot_end); + + if (!cpus_have_final_cap(ARM64_HAS_STAGE2_FWB)) { + spin_lock(&kvm->mmu_lock); + stage2_flush_memslot(kvm, memslot); + spin_unlock(&kvm->mmu_lock); + } + + return 0; +} + + void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *slot) { } diff --git a/arch/arm64/kvm/spe.c b/arch/arm64/kvm/spe.c index f91a52cd7cd3..316ff8dfed5b 100644 --- a/arch/arm64/kvm/spe.c +++ b/arch/arm64/kvm/spe.c @@ -10,6 +10,13 @@ #include #include +#include + +void kvm_arm_spe_notify_vcpu_init(struct kvm_vcpu *vcpu) +{ + vcpu->kvm->arch.spe.finalized = false; +} + static bool kvm_arm_vcpu_supports_spe(struct kvm_vcpu *vcpu) { if (!vcpu_has_spe(vcpu)) @@ -115,6 +122,50 @@ int kvm_arm_spe_get_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr) return -ENXIO; } +static int kvm_arm_spe_finalize(struct kvm *kvm) +{ + struct kvm_memory_slot *memslot; + enum kvm_pgtable_prot prot; + struct kvm_vcpu *vcpu; + int i, ret; + + kvm_for_each_vcpu(i, vcpu, kvm) { + if (!kvm_arm_spe_vcpu_initialized(vcpu)) + return -ENXIO; + } + + mutex_unlock(&kvm->slots_lock); + if (kvm_arm_spe_finalized(kvm)) { + mutex_unlock(&kvm->slots_lock); + return -EBUSY; + } + + prot = KVM_PGTABLE_PROT_R | KVM_PGTABLE_PROT_W; + kvm_for_each_memslot(memslot, kvm_memslots(kvm)) { + /* Only map memory that SPE can write to. */ + if (memslot->flags & KVM_MEM_READONLY) + continue; + /* + * Dirty page logging will write-protect pages, which breaks + * SPE. + */ + if (memslot->dirty_bitmap) + continue; + ret = kvm_map_locked_memslot(kvm, memslot, prot); + if (ret) + break; + } + + if (!ret) + kvm->arch.spe.finalized = true; + mutex_unlock(&kvm->slots_lock); + + if (ret) + stage2_unmap_vm(kvm); + + return ret; +} + int kvm_arm_spe_has_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr) { switch (attr->attr) { @@ -127,3 +178,33 @@ int kvm_arm_spe_has_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr) return -ENXIO; } + +int kvm_arm_vm_spe_set_attr(struct kvm *kvm, struct kvm_device_attr *attr) +{ + switch (attr->attr) { + case KVM_ARM_VM_SPE_FINALIZE: + return kvm_arm_spe_finalize(kvm); + } + + return -ENXIO; +} + +int kvm_arm_vm_spe_get_attr(struct kvm *kvm, struct kvm_device_attr *attr) +{ + return -ENXIO; +} + +int kvm_arm_vm_spe_has_attr(struct kvm *kvm, struct kvm_device_attr *attr) +{ + struct kvm_vcpu *vcpu; + int i; + + switch (attr->attr) { + case KVM_ARM_VM_SPE_FINALIZE: + kvm_for_each_vcpu(i, vcpu, kvm) + if (kvm_arm_vcpu_supports_spe(vcpu)) + return 0; + } + + return -ENXIO; +} diff --git a/include/kvm/arm_spe.h b/include/kvm/arm_spe.h index 0275e8097529..7f9f3a03aadb 100644 --- a/include/kvm/arm_spe.h +++ b/include/kvm/arm_spe.h @@ -18,23 +18,38 @@ struct kvm_spe_cpu { bool initialized; /* Feature is initialized on VCPU */ }; +struct kvm_spe { + bool finalized; +}; + #define kvm_arm_spe_irq_initialized(v) \ ((v)->arch.spe_cpu.irq_num >= VGIC_NR_SGIS && \ (v)->arch.spe_cpu.irq_num < VGIC_MAX_PRIVATE) #define kvm_arm_spe_vcpu_initialized(v) ((v)->arch.spe_cpu.initialized) +#define kvm_arm_spe_finalized(k) ((k)->arch.spe.finalized) int kvm_arm_spe_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr); int kvm_arm_spe_get_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr); int kvm_arm_spe_has_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr); +int kvm_arm_vm_spe_set_attr(struct kvm *vcpu, struct kvm_device_attr *attr); +int kvm_arm_vm_spe_get_attr(struct kvm *vcpu, struct kvm_device_attr *attr); +int kvm_arm_vm_spe_has_attr(struct kvm *vcpu, struct kvm_device_attr *attr); + +void kvm_arm_spe_notify_vcpu_init(struct kvm_vcpu *vcpu); + #else #define kvm_arm_supports_spe() false struct kvm_spe_cpu { }; +struct kvm_spe { +}; + #define kvm_arm_spe_irq_initialized(v) false #define kvm_arm_spe_vcpu_initialized(v) false +#define kvm_arm_spe_finalized(k) false static inline int kvm_arm_spe_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr) @@ -51,5 +66,26 @@ static inline int kvm_arm_spe_has_attr(struct kvm_vcpu *vcpu, { return -ENXIO; } + +static inline int kvm_arm_vm_spe_set_attr(struct kvm *vcpu, + struct kvm_device_attr *attr) +{ + return -ENXIO; +} + +static inline int kvm_arm_vm_spe_get_attr(struct kvm *vcpu, + struct kvm_device_attr *attr) +{ + return -ENXIO; +} + +static inline int kvm_arm_vm_spe_has_attr(struct kvm *vcpu, + struct kvm_device_attr *attr) +{ + return -ENXIO; +} + +static inline void kvm_arm_spe_notify_vcpu_init(struct kvm_vcpu *vcpu) {} + #endif /* CONFIG_KVM_ARM_SPE */ #endif /* __ASM_ARM_KVM_SPE_H */ From patchwork Tue Oct 27 17:27:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11861169 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, UNWANTED_LANGUAGE_BODY,URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9288BC55179 for ; Tue, 27 Oct 2020 17:28:56 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 3590920657 for ; Tue, 27 Oct 2020 17:28:56 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="WLAODCmg" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3590920657 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.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=1wmgzzJHWH9K83nw/mwes9mnxxRTrfAnY4lYx1r7XNM=; b=WLAODCmg7zowB1+76JXF0P0hE FFR2O/UP7m0hx288WgX/myDAWe9dn1W1Lu2aglZi4fbt6UCjaAPh7QQgxLNUnz/5uBJpYLWvZFDlk A/grtHDCSCMtktq5fqYIXkzphmeA+RX9TV/XlokMZGVzOBOj7RCcHOAZWudiYTAk0BJXk10WW2DA/ urVkVWCeUfhNSRyUFGn9lY3bxEstfndJQ7vRZNm//nn1up/lxZWwvSFiIObsRLJ4g3pWqLWnKBN3H B5Byu1CLhvjsyBTxXceqz3XESYF0vDq+x6jpykwtv5e6tSzR+CicSUzqy5BZNHj0tPgb0VtN79VWJ zCMRolKug==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSlW-0005Po-C6; Tue, 27 Oct 2020 17:28:10 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSjt-0004oT-CR for linux-arm-kernel@lists.infradead.org; Tue, 27 Oct 2020 17:26:31 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 2F387139F; Tue, 27 Oct 2020 10:26:29 -0700 (PDT) Received: from monolith.localdoman (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 265E53F719; Tue, 27 Oct 2020 10:26:28 -0700 (PDT) From: Alexandru Elisei To: linux-arm-kernel@lists.infradead.org, kvmarm@lists.cs.columbia.edu Subject: [RFC PATCH v3 11/16] KVM: arm64: Add SPE system registers to VCPU context Date: Tue, 27 Oct 2020 17:27:00 +0000 Message-Id: <20201027172705.15181-12-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.29.1 In-Reply-To: <20201027172705.15181-1-alexandru.elisei@arm.com> References: <20201027172705.15181-1-alexandru.elisei@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201027_132629_571594_00A57570 X-CRM114-Status: GOOD ( 17.93 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: maz@kernel.org, will@kernel.org, james.morse@arm.com, julien.thierry.kdev@gmail.com, suzuki.poulose@arm.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add the SPE system registers to the VCPU context. Omitted are PMBIDR_EL1, which cannot be trapped, and PMSIR_EL1, which is a read-only register. The registers are simply stored in the sys_regs array on a write, and returned on a read; complete emulation and save/restore on world switch will be added in a future patch. Signed-off-by: Alexandru Elisei --- arch/arm64/include/asm/kvm_host.h | 11 +++++++ arch/arm64/kvm/spe.c | 10 +++++++ arch/arm64/kvm/sys_regs.c | 48 ++++++++++++++++++++++++------- include/kvm/arm_spe.h | 9 ++++++ 4 files changed, 68 insertions(+), 10 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 27f581750c6e..bcecc6224c59 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -194,6 +194,17 @@ enum vcpu_sysreg { CNTP_CVAL_EL0, CNTP_CTL_EL0, + /* Statistical Profiling Extension Registers. */ + PMSCR_EL1, /* Statistical Profiling Control Register */ + PMSICR_EL1, /* Sampling Interval Counter Register */ + PMSIRR_EL1, /* Sampling Interval Reload Register */ + PMSFCR_EL1, /* Sampling Filter Control Register */ + PMSEVFR_EL1, /* Sampling Event Filter Register */ + PMSLATFR_EL1, /* Sampling Latency Filter Register */ + PMBLIMITR_EL1, /* Profiling Buffer Limit Address Register */ + PMBPTR_EL1, /* Profiling Buffer Write Pointer Register */ + PMBSR_EL1, /* Profiling Buffer Status/syndrome Register */ + /* 32bit specific registers. Keep them at the end of the range */ DACR32_EL2, /* Domain Access Control Register */ IFSR32_EL2, /* Instruction Fault Status Register */ diff --git a/arch/arm64/kvm/spe.c b/arch/arm64/kvm/spe.c index 316ff8dfed5b..0e365a51cac7 100644 --- a/arch/arm64/kvm/spe.c +++ b/arch/arm64/kvm/spe.c @@ -12,6 +12,16 @@ #include +void kvm_arm_spe_write_sysreg(struct kvm_vcpu *vcpu, int reg, u64 val) +{ + __vcpu_sys_reg(vcpu, reg) = val; +} + +u64 kvm_arm_spe_read_sysreg(struct kvm_vcpu *vcpu, int reg) +{ + return __vcpu_sys_reg(vcpu, reg); +} + void kvm_arm_spe_notify_vcpu_init(struct kvm_vcpu *vcpu) { vcpu->kvm->arch.spe.finalized = false; diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index aa776c006a2a..2871484993ec 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -244,9 +244,37 @@ static bool access_vm_reg(struct kvm_vcpu *vcpu, return true; } +static bool access_spe_reg(struct kvm_vcpu *vcpu, + struct sys_reg_params *p, + const struct sys_reg_desc *r) +{ + u64 val = p->regval; + int reg = r->reg; + u32 sr = sys_reg((u32)r->Op0, (u32)r->Op1, + (u32)r->CRn, (u32)r->CRm, (u32)r->Op2); + + if (sr == SYS_PMSIDR_EL1) { + /* Ignore writes. */ + if (!p->is_write) + p->regval = read_sysreg_s(SYS_PMSIDR_EL1); + goto out; + } + + if (p->is_write) + kvm_arm_spe_write_sysreg(vcpu, reg, val); + else + p->regval = kvm_arm_spe_read_sysreg(vcpu, reg); + +out: + return true; +} + static unsigned int spe_visibility(const struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { + if (vcpu_has_spe(vcpu)) + return 0; + return REG_HIDDEN_GUEST | REG_HIDDEN_USER; } @@ -1598,16 +1626,16 @@ static const struct sys_reg_desc sys_reg_descs[] = { { SYS_DESC(SYS_FAR_EL1), access_vm_reg, reset_unknown, FAR_EL1 }, { SYS_DESC(SYS_PAR_EL1), NULL, reset_unknown, PAR_EL1 }, - { SYS_DESC(SYS_PMSCR_EL1), .visibility = spe_visibility }, - { SYS_DESC(SYS_PMSICR_EL1), .visibility = spe_visibility }, - { SYS_DESC(SYS_PMSIRR_EL1), .visibility = spe_visibility }, - { SYS_DESC(SYS_PMSFCR_EL1), .visibility = spe_visibility }, - { SYS_DESC(SYS_PMSEVFR_EL1), .visibility = spe_visibility }, - { SYS_DESC(SYS_PMSLATFR_EL1), .visibility = spe_visibility }, - { SYS_DESC(SYS_PMSIDR_EL1), .visibility = spe_visibility }, - { SYS_DESC(SYS_PMBLIMITR_EL1), .visibility = spe_visibility }, - { SYS_DESC(SYS_PMBPTR_EL1), .visibility = spe_visibility }, - { SYS_DESC(SYS_PMBSR_EL1), .visibility = spe_visibility }, + { SYS_DESC(SYS_PMSCR_EL1), access_spe_reg, reset_val, PMSCR_EL1, 0, .visibility = spe_visibility }, + { SYS_DESC(SYS_PMSICR_EL1), access_spe_reg, reset_val, PMSICR_EL1, 0, .visibility = spe_visibility }, + { SYS_DESC(SYS_PMSIRR_EL1), access_spe_reg, reset_val, PMSIRR_EL1, 0, .visibility = spe_visibility }, + { SYS_DESC(SYS_PMSFCR_EL1), access_spe_reg, reset_val, PMSFCR_EL1, 0, .visibility = spe_visibility }, + { SYS_DESC(SYS_PMSEVFR_EL1), access_spe_reg, reset_val, PMSEVFR_EL1, 0, .visibility = spe_visibility }, + { SYS_DESC(SYS_PMSLATFR_EL1), access_spe_reg, reset_val, PMSEVFR_EL1, 0, .visibility = spe_visibility }, + { SYS_DESC(SYS_PMSIDR_EL1), access_spe_reg, .visibility = spe_visibility }, + { SYS_DESC(SYS_PMBLIMITR_EL1), access_spe_reg, reset_val, PMBLIMITR_EL1, 0, .visibility = spe_visibility }, + { SYS_DESC(SYS_PMBPTR_EL1), access_spe_reg, reset_unknown, PMBPTR_EL1, .visibility = spe_visibility }, + { SYS_DESC(SYS_PMBSR_EL1), access_spe_reg, reset_val, PMBSR_EL1, 0, .visibility = spe_visibility }, { SYS_DESC(SYS_PMINTENSET_EL1), access_pminten, reset_unknown, PMINTENSET_EL1 }, { SYS_DESC(SYS_PMINTENCLR_EL1), access_pminten, reset_unknown, PMINTENSET_EL1 }, diff --git a/include/kvm/arm_spe.h b/include/kvm/arm_spe.h index 7f9f3a03aadb..a2429edc4483 100644 --- a/include/kvm/arm_spe.h +++ b/include/kvm/arm_spe.h @@ -38,6 +38,9 @@ int kvm_arm_vm_spe_has_attr(struct kvm *vcpu, struct kvm_device_attr *attr); void kvm_arm_spe_notify_vcpu_init(struct kvm_vcpu *vcpu); +void kvm_arm_spe_write_sysreg(struct kvm_vcpu *vcpu, int reg, u64 val); +u64 kvm_arm_spe_read_sysreg(struct kvm_vcpu *vcpu, int reg); + #else #define kvm_arm_supports_spe() false @@ -87,5 +90,11 @@ static inline int kvm_arm_vm_spe_has_attr(struct kvm *vcpu, static inline void kvm_arm_spe_notify_vcpu_init(struct kvm_vcpu *vcpu) {} +static inline void kvm_arm_spe_write_sysreg(struct kvm_vcpu *vcpu, int reg, u64 val) {} +static inline u64 kvm_arm_spe_read_sysreg(struct kvm_vcpu *vcpu, int reg) +{ + return 0; +} + #endif /* CONFIG_KVM_ARM_SPE */ #endif /* __ASM_ARM_KVM_SPE_H */ From patchwork Tue Oct 27 17:27:01 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11861171 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1D0AFC55178 for ; Tue, 27 Oct 2020 17:29:19 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 703AF21D24 for ; Tue, 27 Oct 2020 17:29:18 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="sz7/TGnw" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 703AF21D24 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.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=ScN/t6Eq9R2FxiLAP9snMkvaTawOV1XhL5ThN/uCgqI=; b=sz7/TGnwguCBjL/m0lgGFz8D4 /AAuK7tHfbmEQQ1iagRoqvn0wf9AscA2JXuqO/nnMPjH4JCB42T7fVcuPCDc/4LQL0Y+NkSZuGUPK CfD92KIlZzk7GlI6WGbw8kKvbIVvi7yo8rg1JBRvWJz0a/kL6AlPGLd5EMh5P5+Bpbo+f5lT7q3Cc q/TLsZKLQbnflMVqiJT0EER3KFuCOOhmlE7XaPq9FkCp6eb2qLK693kYzUaQ2/4sh7TpkYkhu0NA2 838+efwqmJkPxAMpyDYktfm6pQkHxrzggabtQidEPew+fCmARCso3NY2msKuscjmZ++3jAJjSKQPc ZEEFSnaOg==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSlk-0005ZL-GM; Tue, 27 Oct 2020 17:28:24 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSjv-0004ra-3M for linux-arm-kernel@lists.infradead.org; Tue, 27 Oct 2020 17:26:32 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 916E1150C; Tue, 27 Oct 2020 10:26:30 -0700 (PDT) Received: from monolith.localdoman (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 630953F719; Tue, 27 Oct 2020 10:26:29 -0700 (PDT) From: Alexandru Elisei To: linux-arm-kernel@lists.infradead.org, kvmarm@lists.cs.columbia.edu Subject: [RFC PATCH v3 12/16] KVM: arm64: VHE: Clear MDCR_EL2.E2PB in vcpu_put() Date: Tue, 27 Oct 2020 17:27:01 +0000 Message-Id: <20201027172705.15181-13-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.29.1 In-Reply-To: <20201027172705.15181-1-alexandru.elisei@arm.com> References: <20201027172705.15181-1-alexandru.elisei@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201027_132631_287586_07F68CB1 X-CRM114-Status: GOOD ( 12.94 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: suzuki.poulose@arm.com, maz@kernel.org, james.morse@arm.com, Sudeep Holla , will@kernel.org, julien.thierry.kdev@gmail.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Sudeep Holla On VHE systems, the kernel executes at EL2 and configures the profiling buffer to use the EL2&0 translation regime and to trap accesses from the guest by clearing MDCR_EL2.E2PB. In vcpu_put(), KVM does a bitwise or with the E2PB mask, preserving its value. This has been correct so far, since MDCR_EL2.E2B has the same value (0b00) for all VMs. However, this will change when KVM enables support for SPE in guests. For such guests KVM will configure the profiling buffer to use the EL1&0 translation regime, a setting that is obviously undesirable to be preserved for the host running at EL2. Let's avoid this situation by explicitly clearing E2PB in vcpu_put(). [ Alexandru E: Rebased on top of 5.10-rc1, reworded commit ] Signed-off-by: Sudeep Holla Signed-off-by: Alexandru Elisei --- arch/arm64/kvm/hyp/vhe/switch.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c index fe69de16dadc..3f4db1fa388b 100644 --- a/arch/arm64/kvm/hyp/vhe/switch.c +++ b/arch/arm64/kvm/hyp/vhe/switch.c @@ -97,9 +97,7 @@ void deactivate_traps_vhe_put(void) { u64 mdcr_el2 = read_sysreg(mdcr_el2); - mdcr_el2 &= MDCR_EL2_HPMN_MASK | - MDCR_EL2_E2PB_MASK << MDCR_EL2_E2PB_SHIFT | - MDCR_EL2_TPMS; + mdcr_el2 &= MDCR_EL2_HPMN_MASK | MDCR_EL2_TPMS; write_sysreg(mdcr_el2, mdcr_el2); From patchwork Tue Oct 27 17:27:02 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11861183 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0B986C64E90 for ; Tue, 27 Oct 2020 17:31:38 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7B43322265 for ; Tue, 27 Oct 2020 17:31:37 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="PHuqfZ/K" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7B43322265 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.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=qZ5LLCT+thhurnoNUHxYowsOSwj3V6dwKq3i+WbHBLU=; b=PHuqfZ/KZ/5izdM+jda1AY/lJ V00egATFcrhQvNQ+ckAymPj3WRGbi/E26vcgtKn4VBcj7hlD2vtFfinZngVzdSPDf/n3NiVYL3uwS yViSWixS15XNgf1Y42IBg4x+OqVMQHazu1u30mAPB6DjI1hRq53u6yhudvlL7BRI9daHD63eRtvXp gIDmkqXqmCXc1NUTLiN/MCllcZZkbapHtXK43i0efcMdWjehoGOYzV5WHtBLhS0cUYGaM4BjHAIkf pO91kf3jHtaXblgkz7W2KLZzGmVm26YHrTRGNXAR+1oNs9tQD9q2luVQd8gKgPXJFu9eQ+R2t7/O9 B6rQXXmzQ==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSmO-0005q9-Ps; Tue, 27 Oct 2020 17:29:04 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSjv-0004oT-UP for linux-arm-kernel@lists.infradead.org; Tue, 27 Oct 2020 17:26:35 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id CCBAF15AB; Tue, 27 Oct 2020 10:26:31 -0700 (PDT) Received: from monolith.localdoman (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id C5D8A3F719; Tue, 27 Oct 2020 10:26:30 -0700 (PDT) From: Alexandru Elisei To: linux-arm-kernel@lists.infradead.org, kvmarm@lists.cs.columbia.edu Subject: [RFC PATCH v3 13/16] KVM: arm64: Switch SPE context on VM entry/exit Date: Tue, 27 Oct 2020 17:27:02 +0000 Message-Id: <20201027172705.15181-14-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.29.1 In-Reply-To: <20201027172705.15181-1-alexandru.elisei@arm.com> References: <20201027172705.15181-1-alexandru.elisei@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201027_132632_305032_A9CF556F X-CRM114-Status: GOOD ( 32.22 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: maz@kernel.org, will@kernel.org, james.morse@arm.com, julien.thierry.kdev@gmail.com, suzuki.poulose@arm.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org When the host and the guest are using SPE at the same time, KVM will have to save and restore the proper SPE context on VM entry (save host's, restore guest's, and on VM exit (save guest's, restore host's). On systems without VHE, the world switch happens at EL2, while both the guest and the host execute at EL1, and according to ARM DDI 0487F.b, page D9-2807, sampling is disabled in this case: "If the PE takes an exception to an Exception level where the Statistical Profiling Extension is disabled, no new operations are selected for sampling." We still have to disable the buffer before we switch translation regimes because we don't want the SPE buffer to speculate memory accesses using a stale buffer pointer. On VHE systems, the world switch happens at EL2, with the host potentially in the middle of a profiling session and we also need to explicitely disable host sampling. The buffer owning Exception level is determined by MDCR_EL2.E2PB. On systems with VHE, this is the different between the guest (executes at EL1) and the host (executes at EL2). The current behavior of perf is to profile KVM until it drops to the guest at EL1. To preserve this behavior as much as possible, KVM will defer changing the value of MDCR_EL2 until __{activate,deactivate}_traps(). For the purposes of emulating the SPE buffer management interrupt, MDCR_EL2 is configured to trap accesses to the buffer control registers; the guest can access the rest of the registers directly. Signed-off-by: Alexandru Elisei --- arch/arm64/include/asm/kvm_arm.h | 1 + arch/arm64/include/asm/kvm_hyp.h | 28 +++++- arch/arm64/include/asm/sysreg.h | 1 + arch/arm64/kvm/debug.c | 29 +++++- arch/arm64/kvm/hyp/include/hyp/spe-sr.h | 38 ++++++++ arch/arm64/kvm/hyp/include/hyp/switch.h | 1 - arch/arm64/kvm/hyp/nvhe/Makefile | 1 + arch/arm64/kvm/hyp/nvhe/debug-sr.c | 16 ++- arch/arm64/kvm/hyp/nvhe/spe-sr.c | 93 ++++++++++++++++++ arch/arm64/kvm/hyp/nvhe/switch.c | 12 +++ arch/arm64/kvm/hyp/vhe/Makefile | 1 + arch/arm64/kvm/hyp/vhe/spe-sr.c | 124 ++++++++++++++++++++++++ arch/arm64/kvm/hyp/vhe/switch.c | 48 ++++++++- arch/arm64/kvm/hyp/vhe/sysreg-sr.c | 2 +- arch/arm64/kvm/spe.c | 3 + arch/arm64/kvm/sys_regs.c | 1 + 16 files changed, 384 insertions(+), 15 deletions(-) create mode 100644 arch/arm64/kvm/hyp/include/hyp/spe-sr.h create mode 100644 arch/arm64/kvm/hyp/nvhe/spe-sr.c create mode 100644 arch/arm64/kvm/hyp/vhe/spe-sr.c diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h index 64ce29378467..033980a9b3fc 100644 --- a/arch/arm64/include/asm/kvm_arm.h +++ b/arch/arm64/include/asm/kvm_arm.h @@ -280,6 +280,7 @@ #define MDCR_EL2_TPMS (1 << 14) #define MDCR_EL2_E2PB_MASK (UL(0x3)) #define MDCR_EL2_E2PB_SHIFT (UL(12)) +#define MDCR_EL2_E2PB_EL1_TRAP (2 << MDCR_EL2_E2PB_SHIFT); #define MDCR_EL2_TDRA (1 << 11) #define MDCR_EL2_TDOSA (1 << 10) #define MDCR_EL2_TDA (1 << 9) diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h index 6b664de5ec1f..4358cba6784a 100644 --- a/arch/arm64/include/asm/kvm_hyp.h +++ b/arch/arm64/include/asm/kvm_hyp.h @@ -79,6 +79,32 @@ void sysreg_save_guest_state_vhe(struct kvm_cpu_context *ctxt); void sysreg_restore_guest_state_vhe(struct kvm_cpu_context *ctxt); #endif +#ifdef CONFIG_KVM_ARM_SPE +#ifdef __KVM_NVHE_HYPERVISOR__ +void __sysreg_save_spe_host_state_nvhe(struct kvm_cpu_context *ctxt); +void __sysreg_restore_spe_host_state_nvhe(struct kvm_cpu_context *ctxt); +void __sysreg_save_spe_guest_state_nvhe(struct kvm_vcpu *vcpu); +void __sysreg_restore_spe_guest_state_nvhe(struct kvm_vcpu *vcpu); +#else +void sysreg_save_spe_host_state_vhe(struct kvm_cpu_context *ctxt); +void sysreg_restore_spe_host_state_vhe(struct kvm_cpu_context *ctxt); +void sysreg_save_spe_guest_state_vhe(struct kvm_vcpu *vcpu); +void sysreg_restore_spe_guest_state_vhe(struct kvm_vcpu *vcpu); +#endif +#else /* !CONFIG_KVM_ARM_SPE */ +#ifdef __KVM_NVHE_HYPERVISOR__ +void __sysreg_save_spe_host_state_nvhe(struct kvm_cpu_context *ctxt) {} +void __sysreg_restore_spe_host_state_nvhe(struct kvm_cpu_context *ctxt) {} +void __sysreg_save_spe_guest_state_nvhe(struct kvm_vcpu *vcpu) {} +void __sysreg_restore_spe_guest_state_nvhe(struct kvm_vcpu *vcpu) {} +#else +void sysreg_save_spe_host_state_vhe(struct kvm_cpu_context *ctxt) {} +void sysreg_restore_spe_host_state_vhe(struct kvm_cpu_context *ctxt) {} +void sysreg_save_spe_guest_state_vhe(struct kvm_vcpu *vcpu) {} +void sysreg_restore_spe_guest_state_vhe(struct kvm_vcpu *vcpu) {} +#endif +#endif /* CONFIG_KVM_ARM_SPE */ + void __debug_switch_to_guest(struct kvm_vcpu *vcpu); void __debug_switch_to_host(struct kvm_vcpu *vcpu); @@ -87,7 +113,7 @@ void __fpsimd_restore_state(struct user_fpsimd_state *fp_regs); #ifndef __KVM_NVHE_HYPERVISOR__ void activate_traps_vhe_load(struct kvm_vcpu *vcpu); -void deactivate_traps_vhe_put(void); +void deactivate_traps_vhe_put(struct kvm_vcpu *vcpu); #endif u64 __guest_enter(struct kvm_vcpu *vcpu); diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index d52c1b3ce589..20159af17578 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -255,6 +255,7 @@ /* Sampling controls */ #define SYS_PMSCR_EL1 sys_reg(3, 0, 9, 9, 0) +#define SYS_PMSCR_EL12 sys_reg(3, 5, 9, 9, 0) #define SYS_PMSCR_EL1_E0SPE_SHIFT 0 #define SYS_PMSCR_EL1_E1SPE_SHIFT 1 #define SYS_PMSCR_EL1_CX_SHIFT 3 diff --git a/arch/arm64/kvm/debug.c b/arch/arm64/kvm/debug.c index 22ee448aee2b..892ce9cc4079 100644 --- a/arch/arm64/kvm/debug.c +++ b/arch/arm64/kvm/debug.c @@ -84,17 +84,28 @@ static void kvm_arm_setup_mdcr_el2(struct kvm_vcpu *vcpu, u32 host_mdcr) { bool trap_debug = !(vcpu->arch.flags & KVM_ARM64_DEBUG_DIRTY); - /* - * This also clears MDCR_EL2_E2PB_MASK to disable guest access - * to the profiling buffer. - */ vcpu->arch.mdcr_el2 = host_mdcr & MDCR_EL2_HPMN_MASK; vcpu->arch.mdcr_el2 |= (MDCR_EL2_TPM | - MDCR_EL2_TPMS | MDCR_EL2_TPMCR | MDCR_EL2_TDRA | MDCR_EL2_TDOSA); + if (vcpu_has_spe(vcpu)) { + /* + * Use EL1&0 translation regime, trap accesses to the buffer + * control registers, allow guest direct access to the + * statistical profiling control registers by leaving the TPMS + * bit clear. + */ + vcpu->arch.mdcr_el2 |= MDCR_EL2_E2PB_EL1_TRAP; + } else { + /* + * Disable buffer by leaving E2PB zero, trap accesses to all SPE + * registers. + */ + vcpu->arch.mdcr_el2 |= MDCR_EL2_TPMS; + } + if (vcpu->guest_debug) { /* Route all software debug exceptions to EL2 */ vcpu->arch.mdcr_el2 |= MDCR_EL2_TDE; @@ -227,10 +238,18 @@ void kvm_arm_setup_debug(struct kvm_vcpu *vcpu) if (vcpu_read_sys_reg(vcpu, MDSCR_EL1) & (DBG_MDSCR_KDE | DBG_MDSCR_MDE)) vcpu->arch.flags |= KVM_ARM64_DEBUG_DIRTY; + /* + * On VHE systems, when the guest has SPE, MDCR_EL2 write is deferred + * until __activate_traps(). + */ + if (has_vhe() && vcpu_has_spe(vcpu)) + goto out; + /* Write mdcr_el2 changes since vcpu_load on VHE systems */ if (has_vhe() && orig_mdcr_el2 != vcpu->arch.mdcr_el2) write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2); +out: trace_kvm_arm_set_dreg32("MDSCR_EL1", vcpu_read_sys_reg(vcpu, MDSCR_EL1)); } diff --git a/arch/arm64/kvm/hyp/include/hyp/spe-sr.h b/arch/arm64/kvm/hyp/include/hyp/spe-sr.h new file mode 100644 index 000000000000..00ed684c117c --- /dev/null +++ b/arch/arm64/kvm/hyp/include/hyp/spe-sr.h @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2020 - ARM Ltd + * Author: Alexandru Elisei + */ + +#ifndef __ARM64_KVM_HYP_SPE_SR_H__ +#define __ARM64_KVM_HYP_SPE_SR_H__ + +#include + +#include + +#ifdef CONFIG_KVM_ARM_SPE +static inline void __sysreg_save_spe_state_common(struct kvm_cpu_context *ctxt) +{ + ctxt_sys_reg(ctxt, PMSICR_EL1) = read_sysreg_s(SYS_PMSICR_EL1); + ctxt_sys_reg(ctxt, PMSIRR_EL1) = read_sysreg_s(SYS_PMSIRR_EL1); + ctxt_sys_reg(ctxt, PMSFCR_EL1) = read_sysreg_s(SYS_PMSFCR_EL1); + ctxt_sys_reg(ctxt, PMSEVFR_EL1) = read_sysreg_s(SYS_PMSEVFR_EL1); + ctxt_sys_reg(ctxt, PMSLATFR_EL1) = read_sysreg_s(SYS_PMSLATFR_EL1); +} + + +static inline void __sysreg_restore_spe_state_common(struct kvm_cpu_context *ctxt) +{ + write_sysreg_s(ctxt_sys_reg(ctxt, PMSICR_EL1), SYS_PMSICR_EL1); + write_sysreg_s(ctxt_sys_reg(ctxt, PMSIRR_EL1), SYS_PMSIRR_EL1); + write_sysreg_s(ctxt_sys_reg(ctxt, PMSFCR_EL1), SYS_PMSFCR_EL1); + write_sysreg_s(ctxt_sys_reg(ctxt, PMSEVFR_EL1), SYS_PMSEVFR_EL1); + write_sysreg_s(ctxt_sys_reg(ctxt, PMSLATFR_EL1), SYS_PMSLATFR_EL1); +} +#else +static inline void __sysreg_save_spe_state_common(struct kvm_cpu_context *ctxt) {} +static inline void __sysreg_restore_spe_state_common(struct kvm_cpu_context *ctxt) {} + +#endif /* CONFIG_KVM_ARM_SPE */ +#endif /* __ARM64_KVM_HYP_SPE_SR_H__ */ diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h index 313a8fa3c721..c88a40eeb171 100644 --- a/arch/arm64/kvm/hyp/include/hyp/switch.h +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h @@ -90,7 +90,6 @@ static inline void __activate_traps_common(struct kvm_vcpu *vcpu) */ write_sysreg(0, pmselr_el0); write_sysreg(ARMV8_PMU_USERENR_MASK, pmuserenr_el0); - write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2); } static inline void __deactivate_traps_common(void) diff --git a/arch/arm64/kvm/hyp/nvhe/Makefile b/arch/arm64/kvm/hyp/nvhe/Makefile index ddde15fe85f2..fcc33b682a45 100644 --- a/arch/arm64/kvm/hyp/nvhe/Makefile +++ b/arch/arm64/kvm/hyp/nvhe/Makefile @@ -7,6 +7,7 @@ asflags-y := -D__KVM_NVHE_HYPERVISOR__ ccflags-y := -D__KVM_NVHE_HYPERVISOR__ obj-y := timer-sr.o sysreg-sr.o debug-sr.o switch.o tlb.o hyp-init.o host.o hyp-main.o +obj-$(CONFIG_KVM_ARM_SPE) += spe-sr.o obj-y += ../vgic-v3-sr.o ../aarch32.o ../vgic-v2-cpuif-proxy.o ../entry.o \ ../fpsimd.o ../hyp-entry.o diff --git a/arch/arm64/kvm/hyp/nvhe/debug-sr.c b/arch/arm64/kvm/hyp/nvhe/debug-sr.c index 91a711aa8382..af65afca479a 100644 --- a/arch/arm64/kvm/hyp/nvhe/debug-sr.c +++ b/arch/arm64/kvm/hyp/nvhe/debug-sr.c @@ -60,14 +60,24 @@ static void __debug_restore_spe(u64 pmscr_el1) void __debug_switch_to_guest(struct kvm_vcpu *vcpu) { - /* Disable and flush SPE data generation */ - __debug_save_spe(&vcpu->arch.host_debug_state.pmscr_el1); + /* + * If the guest is using SPE, host SPE was disabled when the host state + * was saved. + */ + if (!vcpu_has_spe(vcpu)) + /* Disable and flush SPE data generation */ + __debug_save_spe(&vcpu->arch.host_debug_state.pmscr_el1); __debug_switch_to_guest_common(vcpu); } void __debug_switch_to_host(struct kvm_vcpu *vcpu) { - __debug_restore_spe(vcpu->arch.host_debug_state.pmscr_el1); + /* + * Host SPE state was restored with the rest of the host registers when + * the guest is using SPE. + */ + if (!vcpu_has_spe(vcpu)) + __debug_restore_spe(vcpu->arch.host_debug_state.pmscr_el1); __debug_switch_to_host_common(vcpu); } diff --git a/arch/arm64/kvm/hyp/nvhe/spe-sr.c b/arch/arm64/kvm/hyp/nvhe/spe-sr.c new file mode 100644 index 000000000000..a73ee820b27f --- /dev/null +++ b/arch/arm64/kvm/hyp/nvhe/spe-sr.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2020 - ARM Ltd + * Author: Alexandru Elisei + */ + +#include + +#include + +#include +#include + +/* + * The SPE profiling buffer acts like a separate observer in the system, and we + * need to make sure it's disabled before switching translation regimes (host to + * guest and vice versa). + * + * Sampling is disabled when we're at an higher exception level than the owning + * exception level, and we don't disable sampling on save/restore, like we do in + * the VHE case, where the host is profiling at EL2. + * + * Profiling is enabled when both sampling and the buffer are enabled, as a + * result we don't have to worry about PMBPTR_EL1 restrictions with regard to + * PMBLIMITR_EL1.LIMIT. + */ + +void __sysreg_save_spe_host_state_nvhe(struct kvm_cpu_context *ctxt) +{ + u64 pmblimitr = read_sysreg_s(SYS_PMBLIMITR_EL1); + + if (pmblimitr & BIT(SYS_PMBLIMITR_EL1_E_SHIFT)) { + psb_csync(); + dsb(nsh); + write_sysreg_s(0, SYS_PMBLIMITR_EL1); + isb(); + } + + ctxt_sys_reg(ctxt, PMBPTR_EL1) = read_sysreg_s(SYS_PMBPTR_EL1); + ctxt_sys_reg(ctxt, PMBSR_EL1) = read_sysreg_s(SYS_PMBSR_EL1); + ctxt_sys_reg(ctxt, PMBLIMITR_EL1) = pmblimitr; + ctxt_sys_reg(ctxt, PMSCR_EL1) = read_sysreg_s(SYS_PMSCR_EL1); + + __sysreg_save_spe_state_common(ctxt); +} + +void __sysreg_restore_spe_guest_state_nvhe(struct kvm_vcpu *vcpu) +{ + struct kvm_cpu_context *guest_ctxt = &vcpu->arch.ctxt; + + __sysreg_restore_spe_state_common(guest_ctxt); + + /* Make sure the switch to the guest's stage 1 + stage 2 is visible */ + isb(); + + write_sysreg_s(ctxt_sys_reg(guest_ctxt, PMBPTR_EL1), SYS_PMBPTR_EL1); + /* The guest buffer management event interrupt is always virtual. */ + write_sysreg_s(0, SYS_PMBSR_EL1); + write_sysreg_s(ctxt_sys_reg(guest_ctxt, PMBLIMITR_EL1), SYS_PMBLIMITR_EL1); + write_sysreg_s(ctxt_sys_reg(guest_ctxt, PMSCR_EL1), SYS_PMSCR_EL1); +} + +void __sysreg_save_spe_guest_state_nvhe(struct kvm_vcpu *vcpu) +{ + struct kvm_cpu_context *guest_ctxt = &vcpu->arch.ctxt; + u64 pmblimitr = read_sysreg_s(SYS_PMBLIMITR_EL1); + + if (pmblimitr & BIT(SYS_PMBLIMITR_EL1_E_SHIFT)) { + psb_csync(); + dsb(nsh); + write_sysreg_s(0, SYS_PMBLIMITR_EL1); + isb(); + } + + ctxt_sys_reg(guest_ctxt, PMBPTR_EL1) = read_sysreg_s(SYS_PMBPTR_EL1); + ctxt_sys_reg(guest_ctxt, PMSCR_EL1) = read_sysreg_s(SYS_PMSCR_EL1); + /* PMBLIMITR_EL1 is updated only on trap. */ + + __sysreg_save_spe_state_common(guest_ctxt); +} + +void __sysreg_restore_spe_host_state_nvhe(struct kvm_cpu_context *ctxt) +{ + __sysreg_restore_spe_state_common(ctxt); + + /* Make sure the switch to host's stage 1 is visible */ + isb(); + + write_sysreg_s(ctxt_sys_reg(ctxt, PMBPTR_EL1), SYS_PMBPTR_EL1); + write_sysreg_s(ctxt_sys_reg(ctxt, PMBSR_EL1), SYS_PMBSR_EL1); + write_sysreg_s(ctxt_sys_reg(ctxt, PMBLIMITR_EL1), SYS_PMBLIMITR_EL1); + write_sysreg_s(ctxt_sys_reg(ctxt, PMSCR_EL1), SYS_PMSCR_EL1); +} diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c index a457a0306e03..4fde45c4c805 100644 --- a/arch/arm64/kvm/hyp/nvhe/switch.c +++ b/arch/arm64/kvm/hyp/nvhe/switch.c @@ -39,6 +39,8 @@ static void __activate_traps(struct kvm_vcpu *vcpu) ___activate_traps(vcpu); __activate_traps_common(vcpu); + write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2); + val = CPTR_EL2_DEFAULT; val |= CPTR_EL2_TTA | CPTR_EL2_TZ | CPTR_EL2_TAM; if (!update_fp_enabled(vcpu)) { @@ -188,6 +190,8 @@ int __kvm_vcpu_run(struct kvm_vcpu *vcpu) pmu_switch_needed = __pmu_switch_to_guest(host_ctxt); __sysreg_save_state_nvhe(host_ctxt); + if (vcpu_has_spe(vcpu)) + __sysreg_save_spe_host_state_nvhe(host_ctxt); /* * We must restore the 32-bit state before the sysregs, thanks @@ -203,6 +207,9 @@ int __kvm_vcpu_run(struct kvm_vcpu *vcpu) __load_guest_stage2(kern_hyp_va(vcpu->arch.hw_mmu)); __activate_traps(vcpu); + if (vcpu_has_spe(vcpu)) + __sysreg_restore_spe_guest_state_nvhe(vcpu); + __hyp_vgic_restore_state(vcpu); __timer_enable_traps(vcpu); @@ -216,6 +223,9 @@ int __kvm_vcpu_run(struct kvm_vcpu *vcpu) } while (fixup_guest_exit(vcpu, &exit_code)); __sysreg_save_state_nvhe(guest_ctxt); + if (vcpu_has_spe(vcpu)) + __sysreg_save_spe_guest_state_nvhe(vcpu); + __sysreg32_save_state(vcpu); __timer_disable_traps(vcpu); __hyp_vgic_save_state(vcpu); @@ -224,6 +234,8 @@ int __kvm_vcpu_run(struct kvm_vcpu *vcpu) __load_host_stage2(); __sysreg_restore_state_nvhe(host_ctxt); + if (vcpu_has_spe(vcpu)) + __sysreg_restore_spe_host_state_nvhe(host_ctxt); if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED) __fpsimd_save_fpexc32(vcpu); diff --git a/arch/arm64/kvm/hyp/vhe/Makefile b/arch/arm64/kvm/hyp/vhe/Makefile index 461e97c375cc..daff3119c359 100644 --- a/arch/arm64/kvm/hyp/vhe/Makefile +++ b/arch/arm64/kvm/hyp/vhe/Makefile @@ -7,5 +7,6 @@ asflags-y := -D__KVM_VHE_HYPERVISOR__ ccflags-y := -D__KVM_VHE_HYPERVISOR__ obj-y := timer-sr.o sysreg-sr.o debug-sr.o switch.o tlb.o +obj-$(CONFIG_KVM_ARM_SPE) += spe-sr.o obj-y += ../vgic-v3-sr.o ../aarch32.o ../vgic-v2-cpuif-proxy.o ../entry.o \ ../fpsimd.o ../hyp-entry.o diff --git a/arch/arm64/kvm/hyp/vhe/spe-sr.c b/arch/arm64/kvm/hyp/vhe/spe-sr.c new file mode 100644 index 000000000000..dd947e9f249c --- /dev/null +++ b/arch/arm64/kvm/hyp/vhe/spe-sr.c @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2020 - ARM Ltd + * Author: Alexandru Elisei + */ + +#include + +#include + +#include +#include + +void sysreg_save_spe_host_state_vhe(struct kvm_cpu_context *ctxt) +{ + u64 pmblimitr = read_sysreg_s(SYS_PMBLIMITR_EL1); + u64 pmscr_el2 = read_sysreg_el2(SYS_PMSCR); + + /* Allow guest to select timestamp source, disable sampling. */ + write_sysreg_el2(BIT(SYS_PMSCR_EL1_PCT_SHIFT), SYS_PMSCR); + if (pmscr_el2 & BIT(SYS_PMSCR_EL1_E1SPE_SHIFT)) + isb(); + + if (pmblimitr & BIT(SYS_PMBLIMITR_EL1_E_SHIFT)) { + psb_csync(); + dsb(nsh); + write_sysreg_s(0, SYS_PMBLIMITR_EL1); + isb(); + } + + ctxt_sys_reg(ctxt, PMBPTR_EL1) = read_sysreg_s(SYS_PMBPTR_EL1); + ctxt_sys_reg(ctxt, PMBSR_EL1) = read_sysreg_s(SYS_PMBSR_EL1); + ctxt_sys_reg(ctxt, PMBLIMITR_EL1) = pmblimitr; + /* + * We abuse the context register PMSCR_EL1 to save the host's PMSCR, + * which is actually PMSCR_EL2 because KVM is running at EL2. + */ + ctxt_sys_reg(ctxt, PMSCR_EL1) = pmscr_el2; + + __sysreg_save_spe_state_common(ctxt); +} +NOKPROBE_SYMBOL(sysreg_save_spe_host_state_vhe); + +void sysreg_restore_spe_guest_state_vhe(struct kvm_vcpu *vcpu) +{ + struct kvm_cpu_context *guest_ctxt = &vcpu->arch.ctxt; + + /* + * Make sure the write to MDCR_EL2 which changes the buffer owning + * Exception level is visible. + */ + isb(); + + /* + * Order doesn't matter because sampling is disabled at EL2. However, + * restore guest registers in the same program order as the host for + * consistency. + */ + __sysreg_restore_spe_state_common(guest_ctxt); + + write_sysreg_s(ctxt_sys_reg(guest_ctxt, PMBPTR_EL1), SYS_PMBPTR_EL1); + /* The guest buffer management event interrupt is always virtual. */ + write_sysreg_s(0, SYS_PMBSR_EL1); + write_sysreg_s(ctxt_sys_reg(guest_ctxt, PMBLIMITR_EL1), SYS_PMBLIMITR_EL1); + write_sysreg_el1(ctxt_sys_reg(guest_ctxt, PMSCR_EL1), SYS_PMSCR); +} +NOKPROBE_SYMBOL(sysreg_restore_spe_guest_state_vhe); + +void sysreg_save_spe_guest_state_vhe(struct kvm_vcpu *vcpu) +{ + struct kvm_cpu_context *guest_ctxt = &vcpu->arch.ctxt; + u64 pmblimitr = read_sysreg_s(SYS_PMBLIMITR_EL1); + + /* + * We're going to switch buffer owning Exception level when we restore + * the host MDCR_EL2 value, make sure the buffer is disabled until we + * restore the host registers. + * + * Sampling at EL2 was disabled when we saved the host's SPE state, no + * need to disable it again. + */ + if (pmblimitr & BIT(SYS_PMBLIMITR_EL1_E_SHIFT)) { + /* + * We don't an ISB before PSB CSYNC because exception entry is a + * context synchronization event. + */ + psb_csync(); + dsb(nsh); + write_sysreg_s(0, SYS_PMBLIMITR_EL1); + isb(); + } + + ctxt_sys_reg(guest_ctxt, PMBPTR_EL1) = read_sysreg_s(SYS_PMBPTR_EL1); + ctxt_sys_reg(guest_ctxt, PMSCR_EL1) = read_sysreg_el1(SYS_PMSCR); + /* PMBLIMITR_EL1 is updated only on trap, skip saving it. */ + + __sysreg_save_spe_state_common(guest_ctxt); +} +NOKPROBE_SYMBOL(sysreg_save_spe_guest_state_vhe); + +void sysreg_restore_spe_host_state_vhe(struct kvm_cpu_context *ctxt) +{ + /* + * Order matters now because we're possibly restarting profiling. + * Restore common state first so PMSICR_EL1 is updated before PMSCR_EL2. + */ + __sysreg_restore_spe_state_common(ctxt); + + write_sysreg_s(ctxt_sys_reg(ctxt, PMBPTR_EL1), SYS_PMBPTR_EL1); + /* + * Make sure PMBPTR_EL1 update is seen first, so we don't end up in a + * situation where the buffer is enabled and the pointer passes + * the value of PMBLIMITR_EL1.LIMIT programmed by the guest. + * + * This also serves to make sure the write to MDCR_EL2 which changes the + * buffer owning Exception level is visible; the buffer is still + * disabled until the write to PMBLIMITR_EL1. + */ + isb(); + write_sysreg_s(ctxt_sys_reg(ctxt, PMBSR_EL1), SYS_PMBSR_EL1); + write_sysreg_s(ctxt_sys_reg(ctxt, PMBLIMITR_EL1), SYS_PMBLIMITR_EL1); + write_sysreg_el2(ctxt_sys_reg(ctxt, PMSCR_EL1), SYS_PMSCR); +} +NOKPROBE_SYMBOL(sysreg_restore_host_state_vhe); diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c index 3f4db1fa388b..c7f3c8a004b6 100644 --- a/arch/arm64/kvm/hyp/vhe/switch.c +++ b/arch/arm64/kvm/hyp/vhe/switch.c @@ -64,6 +64,9 @@ static void __activate_traps(struct kvm_vcpu *vcpu) write_sysreg(val, cpacr_el1); + if (vcpu_has_spe(vcpu)) + write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2); + write_sysreg(__this_cpu_read(kvm_hyp_vector), vbar_el1); } NOKPROBE_SYMBOL(__activate_traps); @@ -84,6 +87,13 @@ static void __deactivate_traps(struct kvm_vcpu *vcpu) asm(ALTERNATIVE("nop", "isb", ARM64_WORKAROUND_SPECULATIVE_AT)); write_sysreg(CPACR_EL1_DEFAULT, cpacr_el1); + if (vcpu_has_spe(vcpu)) { + u64 mdcr_el2 = read_sysreg(mdcr_el2); + + mdcr_el2 &= MDCR_EL2_HPMN_MASK | MDCR_EL2_TPMS; + + write_sysreg(mdcr_el2, mdcr_el2); + } write_sysreg(vectors, vbar_el1); } NOKPROBE_SYMBOL(__deactivate_traps); @@ -91,15 +101,36 @@ NOKPROBE_SYMBOL(__deactivate_traps); void activate_traps_vhe_load(struct kvm_vcpu *vcpu) { __activate_traps_common(vcpu); + /* + * When the guest is using SPE, vcpu->arch.mdcr_el2 configures the + * profiling buffer to use the EL1&0 translation regime. If that's + * loaded on the hardware and host has profiling enabled, the SPE buffer + * will start using the guest's EL1&0 translation regime, but without + * stage 2 enabled. That's bad. + * + * We cannot rely on checking here that profiling is enabled because + * perf might install an event on the CPU via an IPI before we + * deactivate interrupts. Instead, we defer loading the guest mdcr_el2 + * until __activate_traps(). + */ + if (vcpu_has_spe(vcpu)) + return; + write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2); } -void deactivate_traps_vhe_put(void) +void deactivate_traps_vhe_put(struct kvm_vcpu *vcpu) { - u64 mdcr_el2 = read_sysreg(mdcr_el2); + /* + * When the guest is using SPE, we load the host MDCR_EL2 value early, + * in __deactivate_traps(). to allow perf to profile KVM. + */ + if (!vcpu_has_spe(vcpu)) { + u64 mdcr_el2 = read_sysreg(mdcr_el2); - mdcr_el2 &= MDCR_EL2_HPMN_MASK | MDCR_EL2_TPMS; + mdcr_el2 &= MDCR_EL2_HPMN_MASK | MDCR_EL2_TPMS; - write_sysreg(mdcr_el2, mdcr_el2); + write_sysreg(mdcr_el2, mdcr_el2); + } __deactivate_traps_common(); } @@ -116,6 +147,8 @@ static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu) guest_ctxt = &vcpu->arch.ctxt; sysreg_save_host_state_vhe(host_ctxt); + if (vcpu_has_spe(vcpu)) + sysreg_save_spe_host_state_vhe(host_ctxt); /* * ARM erratum 1165522 requires us to configure both stage 1 and @@ -132,6 +165,9 @@ static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu) __activate_traps(vcpu); sysreg_restore_guest_state_vhe(guest_ctxt); + if (vcpu_has_spe(vcpu)) + sysreg_restore_spe_guest_state_vhe(vcpu); + __debug_switch_to_guest(vcpu); do { @@ -142,10 +178,14 @@ static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu) } while (fixup_guest_exit(vcpu, &exit_code)); sysreg_save_guest_state_vhe(guest_ctxt); + if (vcpu_has_spe(vcpu)) + sysreg_save_spe_guest_state_vhe(vcpu); __deactivate_traps(vcpu); sysreg_restore_host_state_vhe(host_ctxt); + if (vcpu_has_spe(vcpu)) + sysreg_restore_spe_host_state_vhe(host_ctxt); if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED) __fpsimd_save_fpexc32(vcpu); diff --git a/arch/arm64/kvm/hyp/vhe/sysreg-sr.c b/arch/arm64/kvm/hyp/vhe/sysreg-sr.c index 2a0b8c88d74f..007a12dd4351 100644 --- a/arch/arm64/kvm/hyp/vhe/sysreg-sr.c +++ b/arch/arm64/kvm/hyp/vhe/sysreg-sr.c @@ -101,7 +101,7 @@ void kvm_vcpu_put_sysregs_vhe(struct kvm_vcpu *vcpu) struct kvm_cpu_context *host_ctxt; host_ctxt = &this_cpu_ptr(&kvm_host_data)->host_ctxt; - deactivate_traps_vhe_put(); + deactivate_traps_vhe_put(vcpu); __sysreg_save_el1_state(guest_ctxt); __sysreg_save_user_state(guest_ctxt); diff --git a/arch/arm64/kvm/spe.c b/arch/arm64/kvm/spe.c index 0e365a51cac7..ba80f2716a11 100644 --- a/arch/arm64/kvm/spe.c +++ b/arch/arm64/kvm/spe.c @@ -3,6 +3,7 @@ * Copyright (C) 2019 ARM Ltd. */ +#include #include #include #include @@ -14,11 +15,13 @@ void kvm_arm_spe_write_sysreg(struct kvm_vcpu *vcpu, int reg, u64 val) { + WARN(reg < PMBLIMITR_EL1, "Unexpected trap to SPE register\n"); __vcpu_sys_reg(vcpu, reg) = val; } u64 kvm_arm_spe_read_sysreg(struct kvm_vcpu *vcpu, int reg) { + WARN(reg < PMBLIMITR_EL1, "Unexpected trap to SPE register\n"); return __vcpu_sys_reg(vcpu, reg); } diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 2871484993ec..3a0687602839 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -254,6 +254,7 @@ static bool access_spe_reg(struct kvm_vcpu *vcpu, (u32)r->CRn, (u32)r->CRm, (u32)r->Op2); if (sr == SYS_PMSIDR_EL1) { + WARN(true, "Unexpected trap to SPE register\n"); /* Ignore writes. */ if (!p->is_write) p->regval = read_sysreg_s(SYS_PMSIDR_EL1); From patchwork Tue Oct 27 17:27:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11861177 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 530BDC4363A for ; Tue, 27 Oct 2020 17:30:23 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B831320657 for ; Tue, 27 Oct 2020 17:30:22 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="owYVfM7a" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B831320657 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.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=7Z30kUbvbM8oO2OzN/GK00SM9ngOaQzFKOnjcA95SKQ=; b=owYVfM7and7JEesp68iOD3umw F2EYIQa7tS0Q4CbYHTP0v+zjDjfEj2D6/GEU1TMaEIY1XB/SUTpuw1rdw8xW/K8EMVV3lgSa+bg5f mfttcquHSdM0Ke7ucKvUsgdMANGnwT3owc+NNUE0SB8DJ8RmxvUhsxViYhjT/cAGN0YPjNXGx15N7 mUdFATud3cMR6L5IU5QblnAzH7g9mWoz/T9TyqLFlxUsmArazqBV2mKLIZ+9SAfoutz6IjF+Gxj55 60rjtx3+jeCclSA0/6M+tUtnHVVLZ4fcVVwtOe/eRvvzGvp6umiOdfHlmRMxap6yZmCV5YVqfHR4k doujzpB2g==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSmr-00061Z-IH; Tue, 27 Oct 2020 17:29:34 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSjx-0004ra-8V for linux-arm-kernel@lists.infradead.org; Tue, 27 Oct 2020 17:26:35 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 132DC139F; Tue, 27 Oct 2020 10:26:33 -0700 (PDT) Received: from monolith.localdoman (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 0C94C3F719; Tue, 27 Oct 2020 10:26:31 -0700 (PDT) From: Alexandru Elisei To: linux-arm-kernel@lists.infradead.org, kvmarm@lists.cs.columbia.edu Subject: [RFC PATCH v3 14/16] KVM: arm64: Emulate SPE buffer management interrupt Date: Tue, 27 Oct 2020 17:27:03 +0000 Message-Id: <20201027172705.15181-15-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.29.1 In-Reply-To: <20201027172705.15181-1-alexandru.elisei@arm.com> References: <20201027172705.15181-1-alexandru.elisei@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201027_132633_512698_5FE6980F X-CRM114-Status: GOOD ( 27.60 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: maz@kernel.org, will@kernel.org, james.morse@arm.com, julien.thierry.kdev@gmail.com, suzuki.poulose@arm.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org A profiling buffer management interrupt is asserted when the buffer fills, on a fault or on an external abort. The service bit, PMBSR_EL1.S, is set as long as SPE asserts this interrupt. SPE can also assert the interrupt following a direct write to PMBSR_EL1 that sets the bit. The SPE hardware stops asserting the interrupt only when the service bit is cleared. KVM emulates the interrupt by reading the value of the service bit on each guest exit to determine if the SPE hardware asserted the interrupt (for example, if the buffer was full). Writes to the buffer registers are trapped, to determine when the interrupt should be cleared or when the guest wants to explicitely assert the interrupt by setting the service bit. Signed-off-by: Alexandru Elisei --- arch/arm64/include/asm/sysreg.h | 3 + arch/arm64/kvm/arm.c | 3 + arch/arm64/kvm/hyp/nvhe/spe-sr.c | 20 +++++- arch/arm64/kvm/hyp/vhe/spe-sr.c | 19 +++++- arch/arm64/kvm/spe.c | 101 +++++++++++++++++++++++++++++++ include/kvm/arm_spe.h | 4 ++ 6 files changed, 146 insertions(+), 4 deletions(-) diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index 20159af17578..0398bcba83a6 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -299,6 +299,7 @@ #define SYS_PMBLIMITR_EL1_FM_SHIFT 1 #define SYS_PMBLIMITR_EL1_FM_MASK 0x3UL #define SYS_PMBLIMITR_EL1_FM_STOP_IRQ (0 << SYS_PMBLIMITR_EL1_FM_SHIFT) +#define SYS_PMBLIMITR_EL1_RES0 0xfffffffffffff007UL #define SYS_PMBPTR_EL1 sys_reg(3, 0, 9, 10, 1) @@ -323,6 +324,8 @@ #define SYS_PMBSR_EL1_BUF_BSC_FULL (0x1UL << SYS_PMBSR_EL1_BUF_BSC_SHIFT) +#define SYS_PMBSR_EL1_RES0 0x00000000fc0fffffUL + /*** End of Statistical Profiling Extension ***/ #define SYS_PMINTENSET_EL1 sys_reg(3, 0, 9, 14, 1) diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 2d98248f2c66..c6a675aba71e 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -775,6 +775,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) */ kvm_vgic_sync_hwstate(vcpu); + if (vcpu_has_spe(vcpu)) + kvm_arm_spe_sync_hwstate(vcpu); + /* * Sync the timer hardware state before enabling interrupts as * we don't want vtimer interrupts to race with syncing the diff --git a/arch/arm64/kvm/hyp/nvhe/spe-sr.c b/arch/arm64/kvm/hyp/nvhe/spe-sr.c index a73ee820b27f..2794a7c7fcd9 100644 --- a/arch/arm64/kvm/hyp/nvhe/spe-sr.c +++ b/arch/arm64/kvm/hyp/nvhe/spe-sr.c @@ -47,6 +47,14 @@ void __sysreg_save_spe_host_state_nvhe(struct kvm_cpu_context *ctxt) void __sysreg_restore_spe_guest_state_nvhe(struct kvm_vcpu *vcpu) { struct kvm_cpu_context *guest_ctxt = &vcpu->arch.ctxt; + struct kvm_spe_cpu *spe_cpu = &vcpu->arch.spe_cpu; + u64 pmblimitr; + + /* Disable guest profiling when the interrupt is asserted. */ + if (spe_cpu->irq_level) + pmblimitr = 0; + else + pmblimitr = ctxt_sys_reg(guest_ctxt, PMBLIMITR_EL1); __sysreg_restore_spe_state_common(guest_ctxt); @@ -54,16 +62,24 @@ void __sysreg_restore_spe_guest_state_nvhe(struct kvm_vcpu *vcpu) isb(); write_sysreg_s(ctxt_sys_reg(guest_ctxt, PMBPTR_EL1), SYS_PMBPTR_EL1); - /* The guest buffer management event interrupt is always virtual. */ + /* The guest buffer management interrupt is always virtual. */ write_sysreg_s(0, SYS_PMBSR_EL1); - write_sysreg_s(ctxt_sys_reg(guest_ctxt, PMBLIMITR_EL1), SYS_PMBLIMITR_EL1); + write_sysreg_s(pmblimitr, SYS_PMBLIMITR_EL1); write_sysreg_s(ctxt_sys_reg(guest_ctxt, PMSCR_EL1), SYS_PMSCR_EL1); } void __sysreg_save_spe_guest_state_nvhe(struct kvm_vcpu *vcpu) { struct kvm_cpu_context *guest_ctxt = &vcpu->arch.ctxt; + struct kvm_spe_cpu *spe_cpu = &vcpu->arch.spe_cpu; u64 pmblimitr = read_sysreg_s(SYS_PMBLIMITR_EL1); + u64 pmbsr = read_sysreg_s(SYS_PMBSR_EL1); + + /* Update guest PMBSR_EL1 only when SPE asserts an interrupt. */ + if (pmbsr & BIT(SYS_PMBSR_EL1_S_SHIFT)) { + ctxt_sys_reg(guest_ctxt, PMBSR_EL1) = pmbsr; + spe_cpu->pmbirq_asserted = true; + } if (pmblimitr & BIT(SYS_PMBLIMITR_EL1_E_SHIFT)) { psb_csync(); diff --git a/arch/arm64/kvm/hyp/vhe/spe-sr.c b/arch/arm64/kvm/hyp/vhe/spe-sr.c index dd947e9f249c..24173f838bb1 100644 --- a/arch/arm64/kvm/hyp/vhe/spe-sr.c +++ b/arch/arm64/kvm/hyp/vhe/spe-sr.c @@ -44,6 +44,8 @@ NOKPROBE_SYMBOL(sysreg_save_spe_host_state_vhe); void sysreg_restore_spe_guest_state_vhe(struct kvm_vcpu *vcpu) { struct kvm_cpu_context *guest_ctxt = &vcpu->arch.ctxt; + struct kvm_spe_cpu *spe_cpu = &vcpu->arch.spe_cpu; + u64 pmblimitr; /* * Make sure the write to MDCR_EL2 which changes the buffer owning @@ -51,6 +53,12 @@ void sysreg_restore_spe_guest_state_vhe(struct kvm_vcpu *vcpu) */ isb(); + /* Disable guest profiling when the interrupt is asserted. */ + if (spe_cpu->irq_level) + pmblimitr = 0; + else + pmblimitr = ctxt_sys_reg(guest_ctxt, PMBLIMITR_EL1); + /* * Order doesn't matter because sampling is disabled at EL2. However, * restore guest registers in the same program order as the host for @@ -59,9 +67,9 @@ void sysreg_restore_spe_guest_state_vhe(struct kvm_vcpu *vcpu) __sysreg_restore_spe_state_common(guest_ctxt); write_sysreg_s(ctxt_sys_reg(guest_ctxt, PMBPTR_EL1), SYS_PMBPTR_EL1); - /* The guest buffer management event interrupt is always virtual. */ + /* The guest buffer management interrupt is always virtual. */ write_sysreg_s(0, SYS_PMBSR_EL1); - write_sysreg_s(ctxt_sys_reg(guest_ctxt, PMBLIMITR_EL1), SYS_PMBLIMITR_EL1); + write_sysreg_s(pmblimitr, SYS_PMBLIMITR_EL1); write_sysreg_el1(ctxt_sys_reg(guest_ctxt, PMSCR_EL1), SYS_PMSCR); } NOKPROBE_SYMBOL(sysreg_restore_spe_guest_state_vhe); @@ -69,8 +77,15 @@ NOKPROBE_SYMBOL(sysreg_restore_spe_guest_state_vhe); void sysreg_save_spe_guest_state_vhe(struct kvm_vcpu *vcpu) { struct kvm_cpu_context *guest_ctxt = &vcpu->arch.ctxt; + struct kvm_spe_cpu *spe_cpu = &vcpu->arch.spe_cpu; u64 pmblimitr = read_sysreg_s(SYS_PMBLIMITR_EL1); + u64 pmbsr = read_sysreg_s(SYS_PMBSR_EL1); + /* Update guest PMBSR_EL1 only when SPE asserts an interrupt. */ + if (pmbsr & BIT(SYS_PMBSR_EL1_S_SHIFT)) { + ctxt_sys_reg(guest_ctxt, PMBSR_EL1) = pmbsr; + spe_cpu->pmbirq_asserted = true; + } /* * We're going to switch buffer owning Exception level when we restore * the host MDCR_EL2 value, make sure the buffer is disabled until we diff --git a/arch/arm64/kvm/spe.c b/arch/arm64/kvm/spe.c index ba80f2716a11..243fd621d640 100644 --- a/arch/arm64/kvm/spe.c +++ b/arch/arm64/kvm/spe.c @@ -12,11 +12,112 @@ #include #include +#include + +static void kvm_arm_spe_update_irq(struct kvm_vcpu *vcpu, bool new_level) +{ + struct kvm_spe_cpu *spe_cpu = &vcpu->arch.spe_cpu; + int ret; + + spe_cpu->irq_level = new_level; + ret = kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id, spe_cpu->irq_num, + new_level, spe_cpu); + WARN_ON(ret); +} + +void kvm_arm_spe_sync_hwstate(struct kvm_vcpu *vcpu) +{ + struct kvm_spe_cpu *spe_cpu = &vcpu->arch.spe_cpu; + u64 pmbsr, pmbsr_ec; + + if (!spe_cpu->pmbirq_asserted) + return; + spe_cpu->pmbirq_asserted = false; + + pmbsr = __vcpu_sys_reg(vcpu, PMBSR_EL1); + pmbsr_ec = pmbsr & (SYS_PMBSR_EL1_EC_MASK << SYS_PMBSR_EL1_EC_SHIFT); + + if (pmbsr & BIT(SYS_PMBSR_EL1_EA_SHIFT)) { + /* + * The guest managed to trigger an external abort, something is + * very definitely broken and there is no way for us to recover. + * Treat it like we would if the external abort generated an + * SError and panic now. + */ + panic("KVM SPE External Abort\n"); + cpu_park_loop(); + unreachable(); + } + + switch (pmbsr_ec) { + case SYS_PMBSR_EL1_EC_FAULT_S2: + /* + * If we see this then either the guest memory isn't pinned + * correctly (KVM bug or userspace got it wrong), or the guest + * programmed the buffer pointer with a bogus address. + * PMBPTR_El1 will point to the guest VA that triggered the + * DABT, print it as it might be useful for debugging. + */ + pr_warn_ratelimited("KVM SPE Stage 2 Data Abort, pmbsr=0x%llx, pmbptr=0x%llx\n", + pmbsr, __vcpu_sys_reg(vcpu, PMBPTR_EL1)); + /* + * Convert the stage 2 DABT into a guest SPE buffer synchronous + * external abort. + */ + __vcpu_sys_reg(vcpu, PMBSR_EL1) = BIT(SYS_PMBSR_EL1_S_SHIFT) | + BIT(SYS_PMBSR_EL1_EA_SHIFT); + case SYS_PMBSR_EL1_EC_FAULT_S1: + case SYS_PMBSR_EL1_EC_BUF: + break; + default: + pr_warn_ratelimited("KVM SPE Unknown buffer syndrome, pmbsr=0x%llx, pmbptr=0x%llx\n", + pmbsr, __vcpu_sys_reg(vcpu, PMBPTR_EL1)); + __vcpu_sys_reg(vcpu, PMBSR_EL1) = BIT(SYS_PMBSR_EL1_S_SHIFT) | + BIT(SYS_PMBSR_EL1_EA_SHIFT); + } + + if (spe_cpu->irq_level) + return; + + kvm_arm_spe_update_irq(vcpu, true); +} + +static u64 kvm_arm_spe_get_reg_mask(int reg) +{ + switch (reg) { + case PMBLIMITR_EL1: + return SYS_PMBLIMITR_EL1_RES0; + case PMBPTR_EL1: + return ~0UL; + case PMBSR_EL1: + return SYS_PMBSR_EL1_RES0; + default: + return 0UL; + } +} void kvm_arm_spe_write_sysreg(struct kvm_vcpu *vcpu, int reg, u64 val) { + struct kvm_spe_cpu *spe_cpu = &vcpu->arch.spe_cpu; + bool irq_level; + WARN(reg < PMBLIMITR_EL1, "Unexpected trap to SPE register\n"); + + val &= kvm_arm_spe_get_reg_mask(reg); __vcpu_sys_reg(vcpu, reg) = val; + + if (reg != PMBSR_EL1) + return; + + irq_level = val & BIT(SYS_PMBSR_EL1_S_SHIFT); + /* + * The VGIC configures PPIs as level-sensitive, we need to update the + * interrupt state if it changes. + */ + if (spe_cpu->irq_level == irq_level) + return; + + kvm_arm_spe_update_irq(vcpu, irq_level); } u64 kvm_arm_spe_read_sysreg(struct kvm_vcpu *vcpu, int reg) diff --git a/include/kvm/arm_spe.h b/include/kvm/arm_spe.h index a2429edc4483..d45c17dd157d 100644 --- a/include/kvm/arm_spe.h +++ b/include/kvm/arm_spe.h @@ -16,6 +16,7 @@ struct kvm_spe_cpu { int irq_num; /* Guest visibile INTID */ bool irq_level; /* 'true' if interrupt is asserted to the VGIC */ bool initialized; /* Feature is initialized on VCPU */ + bool pmbirq_asserted; /* Hardware asserted PMBIRQ */ }; struct kvm_spe { @@ -41,6 +42,7 @@ void kvm_arm_spe_notify_vcpu_init(struct kvm_vcpu *vcpu); void kvm_arm_spe_write_sysreg(struct kvm_vcpu *vcpu, int reg, u64 val); u64 kvm_arm_spe_read_sysreg(struct kvm_vcpu *vcpu, int reg); +void kvm_arm_spe_sync_hwstate(struct kvm_vcpu *vcpu); #else #define kvm_arm_supports_spe() false @@ -96,5 +98,7 @@ static inline u64 kvm_arm_spe_read_sysreg(struct kvm_vcpu *vcpu, int reg) return 0; } +static inline void kvm_arm_spe_sync_hwstate(struct kvm_vcpu *vcpu) {} + #endif /* CONFIG_KVM_ARM_SPE */ #endif /* __ASM_ARM_KVM_SPE_H */ From patchwork Tue Oct 27 17:27:04 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11861185 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 90DD9C55179 for ; Tue, 27 Oct 2020 17:31:50 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 36F1D20657 for ; Tue, 27 Oct 2020 17:31:50 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="sacGkzTh" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 36F1D20657 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.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=NFUQCnJZm4f7vL7WksNrm49QmOD7K7vm0HaLy9EB1IU=; b=sacGkzThqdPZ9NW1IJDeAYcPk /pU1cd7luciONFlHt3q49zzAyTrA//ujy0s853XNftWMz4cxVKs3i1RlYgAZq9jXIWm6kedMjWuhJ 6aGHo6mFntC2PPS8BXFFuhIulRJ1SUUbGkNdgn9+Vk2XnxDZOd3Uiow7W26Ot75hW67d1rKrIvurQ dsf6Hr3Ij72Qn6yKXG4/WaMhoqsjkhj5+LEpVwFilHI16E47OyrZm0R5mwogjyjVdQkN05PndJF6i D612gSk3TsXrPyOAWLGG3mevZ1aDgUNiivfCRtThLCEd9+a71jIOfY0rmyIgRXVqxSvaHMhelLOA5 73irJdcsQ==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSnG-0006Jd-0c; Tue, 27 Oct 2020 17:29:58 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSjy-0004ss-L7 for linux-arm-kernel@lists.infradead.org; Tue, 27 Oct 2020 17:26:36 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 4DA1B150C; Tue, 27 Oct 2020 10:26:34 -0700 (PDT) Received: from monolith.localdoman (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 46C783F719; Tue, 27 Oct 2020 10:26:33 -0700 (PDT) From: Alexandru Elisei To: linux-arm-kernel@lists.infradead.org, kvmarm@lists.cs.columbia.edu Subject: [RFC PATCH v3 15/16] KVM: arm64: Enable SPE for guests Date: Tue, 27 Oct 2020 17:27:04 +0000 Message-Id: <20201027172705.15181-16-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.29.1 In-Reply-To: <20201027172705.15181-1-alexandru.elisei@arm.com> References: <20201027172705.15181-1-alexandru.elisei@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201027_132634_834651_D01B56A8 X-CRM114-Status: GOOD ( 14.01 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: maz@kernel.org, will@kernel.org, james.morse@arm.com, julien.thierry.kdev@gmail.com, suzuki.poulose@arm.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org We have all the bits in place to expose SPE to guests, allow userspace to set the feature and advertise the presence of SPE in the ID_AA64DFR0_EL1 register. Signed-off-by: Alexandru Elisei --- arch/arm64/include/asm/kvm_host.h | 2 +- arch/arm64/kvm/sys_regs.c | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index bcecc6224c59..e5504c9847fc 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -39,7 +39,7 @@ #define KVM_MAX_VCPUS VGIC_V3_MAX_CPUS -#define KVM_VCPU_MAX_FEATURES 7 +#define KVM_VCPU_MAX_FEATURES 8 #define KVM_REQ_SLEEP \ KVM_ARCH_REQ_FLAGS(0, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 3a0687602839..076be04d2e28 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -1178,8 +1178,12 @@ static u64 read_id_reg(const struct kvm_vcpu *vcpu, val = cpuid_feature_cap_perfmon_field(val, ID_AA64DFR0_PMUVER_SHIFT, ID_AA64DFR0_PMUVER_8_1); - /* Don't advertise SPE to guests */ - val &= ~(0xfUL << ID_AA64DFR0_PMSVER_SHIFT); + /* + * Don't advertise SPE to guests without SPE. Otherwise, allow + * the guest to detect the hardware SPE version. + */ + if (!vcpu_has_spe(vcpu)) + val &= ~(0xfUL << ID_AA64DFR0_PMSVER_SHIFT); } else if (id == SYS_ID_DFR0_EL1) { /* Limit guests to PMUv3 for ARMv8.1 */ val = cpuid_feature_cap_perfmon_field(val, From patchwork Tue Oct 27 17:27:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11861179 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B4DCFC4363A for ; Tue, 27 Oct 2020 17:30:49 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 3469820657 for ; Tue, 27 Oct 2020 17:30:49 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="23utjFrG" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3469820657 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.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=6E/nA5dqF/5uI14wCX8fQXthmd8Ci+TTYN5QLod+Uks=; b=23utjFrGHARlzZ5huqacgRCRX 3hZ6iJJXNQVPOu2VPBR0ZYm8Ofj9q7L+WilnuX+zRGL3wTkGFxF+25R6oab67icU9irMGQ27i3j7l pxYu9EVzR9Cid3DIVtQ6ep05mTz/0YfXaT7UPdmf7OarOHZwMvARoRt5RLc0CT94PYYcqfVyy18Og 9+TVW/8hff4U788OmERXLghPMUEjKPT8hv3WH6jzYhGp/lCTzrnMhWjzMTVKcNje7238Czp/LZ/Xx EuB+0df27Ev/piQUbnu3p8sWHHCT3yv5fhRxjCfKKfWQaT6cqoWB2ezSLlySFMRFGiYHbYhClYjgt WMpkwUaMQ==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSnR-0006Rz-0o; Tue, 27 Oct 2020 17:30:09 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kXSjz-0004oT-LP for linux-arm-kernel@lists.infradead.org; Tue, 27 Oct 2020 17:26:36 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 87F3115AB; Tue, 27 Oct 2020 10:26:35 -0700 (PDT) Received: from monolith.localdoman (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 814EF3F719; Tue, 27 Oct 2020 10:26:34 -0700 (PDT) From: Alexandru Elisei To: linux-arm-kernel@lists.infradead.org, kvmarm@lists.cs.columbia.edu Subject: [RFC PATCH v3 16/16] Documentation: arm64: Document ARM Neoverse-N1 erratum #1688567 Date: Tue, 27 Oct 2020 17:27:05 +0000 Message-Id: <20201027172705.15181-17-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.29.1 In-Reply-To: <20201027172705.15181-1-alexandru.elisei@arm.com> References: <20201027172705.15181-1-alexandru.elisei@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201027_132635_805601_578B6668 X-CRM114-Status: GOOD ( 12.23 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: maz@kernel.org, will@kernel.org, james.morse@arm.com, julien.thierry.kdev@gmail.com, suzuki.poulose@arm.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org According to erratum #1688567, a SPE buffer write that results in an Access flag fault or Permission fault at stage 2 is reported with an unsupported PMBSR_EL1.FSC code. KVM avoids SPE stage 2 faults altogether by requiring userspace to lock the guest memory in RAM and pre-mapping it in stage 2 before the VM is started. As a result, KVM is not impacted by this erratum. Signed-off-by: Alexandru Elisei --- Documentation/arm64/silicon-errata.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/arm64/silicon-errata.rst b/Documentation/arm64/silicon-errata.rst index d3587805de64..1f6c403fd555 100644 --- a/Documentation/arm64/silicon-errata.rst +++ b/Documentation/arm64/silicon-errata.rst @@ -96,6 +96,8 @@ stable kernels. +----------------+-----------------+-----------------+-----------------------------+ | ARM | Neoverse-N1 | #1542419 | ARM64_ERRATUM_1542419 | +----------------+-----------------+-----------------+-----------------------------+ +| ARM | Neoverse-N1 | #1688567 | N/A | ++----------------+-----------------+-----------------+-----------------------------+ | ARM | MMU-500 | #841119,826419 | N/A | +----------------+-----------------+-----------------+-----------------------------+ +----------------+-----------------+-----------------+-----------------------------+