Message ID | 20240226113044.228403-8-james.clark@arm.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel+bounces-81274-ouuuleilei=gmail.com@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:a81b:b0:108:e6aa:91d0 with SMTP id bq27csp2010508dyb; Mon, 26 Feb 2024 03:35:55 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCVj7wgR5yWLyTZUS+RDYU7f2flnJsgYp94UZk5rg2E+mSmvfqJ8/2jp7U59/6nf15X31siqpnfCnZoTpKaIM0VUdwRF9Q== X-Google-Smtp-Source: AGHT+IHXULzrbjXTXMe19D5gfMCLJBKcNggriWY7++R19xkwgKsXjqnVeY58QOSdQda5bmnAqtO2 X-Received: by 2002:aa7:d318:0:b0:565:e32e:1bd2 with SMTP id p24-20020aa7d318000000b00565e32e1bd2mr2302427edq.17.1708947355164; Mon, 26 Feb 2024 03:35:55 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1708947355; cv=pass; d=google.com; s=arc-20160816; b=GdxfodMqaFNYB1cQVq53Yuv4u7p9O/ZCTT8HTShVTiUG3a/fGHKSpHKDTMYLtFW3tT RHev5YRcOwd05kYLkLRehDefJGIiQQY/Xo4Wku3lkESqqpZg3fSw8mAwAGuqz2AH5unl YV8fEU4Q8Ugou8YVsPPHZhUw4UBbTW3+e1SUhR9wRlEppft+AKBcRPb7GQWw0QZjrXD2 CDphc3aCFq+8vwwywl2itbXQ3tmWLxquKSY9xxBczd/SpqTmkpoICM0+w/j5IaXOyKVJ wERClOMp6JLYu3GhK0gQM+/GJ0/NqElIa1aqNkqzIakO5KwmZHXRBtDU9UyC0SUuq0DP iZgw== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from; bh=Ky5Jlbt7AcW3pTMHvglTlK4JhSVIuOSZ01gn7bZ4mvs=; fh=+EqktzEB5658j5YkIXhbAYa3C7cHy4wcmaDacmjRqYA=; b=q2o363elGgzFipNMw7y6PAO33+fi0XpY+5ckp9cFYTib9RrOkVggucTaKilB79H3yC X7e8u4CRmuVKCq4NI9A2Gq6neD1N+p7qJeteqGc3bl3RtMZw7QLSkljJuEg6c6vuf9Jj NPXXoML1WSHXUDHh+pFQ0g2gJlRJVXuqU91Q1A8BK8qpg6LDIFMVzg/99kKkyTcutakF o144TwRMZN08UAsVOsRD5zKEKPcuLOBMwojQ2bgY0sjBpCPfk0Y19/uPOamjcUfXKwQB iFnk2VuijtITkXXqtfhsCLa8FiGaOaYsBnlSxIxYKONpy3dkeyukaXfHdi+aUbKVABGU cZkQ==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; arc=pass (i=1 spf=pass spfdomain=arm.com dmarc=pass fromdomain=arm.com); spf=pass (google.com: domain of linux-kernel+bounces-81274-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) smtp.mailfrom="linux-kernel+bounces-81274-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Received: from am.mirrors.kernel.org (am.mirrors.kernel.org. [147.75.80.249]) by mx.google.com with ESMTPS id a9-20020a50c309000000b005640ff07cd1si1949182edb.309.2024.02.26.03.35.54 for <ouuuleilei@gmail.com> (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 26 Feb 2024 03:35:55 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-81274-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) client-ip=147.75.80.249; Authentication-Results: mx.google.com; arc=pass (i=1 spf=pass spfdomain=arm.com dmarc=pass fromdomain=arm.com); spf=pass (google.com: domain of linux-kernel+bounces-81274-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) smtp.mailfrom="linux-kernel+bounces-81274-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by am.mirrors.kernel.org (Postfix) with ESMTPS id C61D21F267BD for <ouuuleilei@gmail.com>; Mon, 26 Feb 2024 11:35:54 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 41FBD487B4; Mon, 26 Feb 2024 11:34:20 +0000 (UTC) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 2A219381BB for <linux-kernel@vger.kernel.org>; Mon, 26 Feb 2024 11:34:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708947258; cv=none; b=VB8a0regWOU/dpYpf6yCCNOQeqOPLX2ljp2YG+F346Wkilow5x9gsHzx1z4c9BqxlpPkX3Ymu/4nr94gnadPzu7ftks5guhYpHUqZagz4L+g/9w6l3Lm3lZRSdZb8eIev5Ufd3XH18jGKVtM5D7AyoJ1Sj8RxlGmDWI037X4Gv8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708947258; c=relaxed/simple; bh=LGfagXEHDuOI+B1csim7lATVyAnQAnwlKn7v1mL/u70=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=sfeNME25J7zb+gQptKISslYSYmQZafuhZSi34krn1ZHtNhTHGN6KncYbjBbdCyOwiiyI1lUNSRd70EJ5diqYjOd97aXxXSD+NGWrw7TZAVNmYReOnS8YVas/WbzwwmYUZJRbRTdJm8oLOLiZm/9yGYHRT3gCk5iR7nAR11J0BZs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com 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 3E6B7DA7; Mon, 26 Feb 2024 03:34:55 -0800 (PST) Received: from e127643.broadband (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 220C53F6C4; Mon, 26 Feb 2024 03:34:13 -0800 (PST) From: James Clark <james.clark@arm.com> To: coresight@lists.linaro.org, linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, maz@kernel.org, suzuki.poulose@arm.com, acme@kernel.org, oliver.upton@linux.dev, broonie@kernel.org Cc: James Clark <james.clark@arm.com>, James Morse <james.morse@arm.com>, Zenghui Yu <yuzenghui@huawei.com>, Catalin Marinas <catalin.marinas@arm.com>, Will Deacon <will@kernel.org>, Mike Leach <mike.leach@linaro.org>, Alexander Shishkin <alexander.shishkin@linux.intel.com>, Anshuman Khandual <anshuman.khandual@arm.com>, Miguel Luis <miguel.luis@oracle.com>, Joey Gouly <joey.gouly@arm.com>, Ard Biesheuvel <ardb@kernel.org>, Javier Martinez Canillas <javierm@redhat.com>, Mark Rutland <mark.rutland@arm.com>, Arnd Bergmann <arnd@arndb.de>, Andrew Walbran <qwandor@google.com>, Vincent Donnefort <vdonnefort@google.com>, Ryan Roberts <ryan.roberts@arm.com>, Fuad Tabba <tabba@google.com>, Jing Zhang <jingzhangos@google.com>, linux-kernel@vger.kernel.org Subject: [PATCH v6 7/8] arm64: KVM: Write TRFCR value on guest switch with nVHE Date: Mon, 26 Feb 2024 11:30:35 +0000 Message-Id: <20240226113044.228403-8-james.clark@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240226113044.228403-1-james.clark@arm.com> References: <20240226113044.228403-1-james.clark@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: <linux-kernel.vger.kernel.org> List-Subscribe: <mailto:linux-kernel+subscribe@vger.kernel.org> List-Unsubscribe: <mailto:linux-kernel+unsubscribe@vger.kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1791961182058477458 X-GMAIL-MSGID: 1791961182058477458 |
Series |
kvm/coresight: Support exclude guest and exclude host
|
|
Commit Message
James Clark
Feb. 26, 2024, 11:30 a.m. UTC
The guest value for TRFCR requested by the Coresight driver is saved in kvm_guest_trfcr. On guest switch this value needs to be written to the register. Currently TRFCR is only modified when we want to disable trace completely in guests due to an issue with TRBE. Expand the __debug_save_trace() function to always write to the register if a different value for guests is required, but also keep the existing TRBE disable behavior if that's required. In pKVM, the kvm_guest_trfcr can't be read and the host isn't trusted, so always disable trace. __debug_restore_trace() now has to restore unconditionally, because even a value of 0 needs to be written to overwrite whatever was set for the guest. Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com> Signed-off-by: James Clark <james.clark@arm.com> --- arch/arm64/kvm/hyp/nvhe/debug-sr.c | 53 +++++++++++++++++------------- 1 file changed, 31 insertions(+), 22 deletions(-)
Comments
On Mon, 26 Feb 2024 11:30:35 +0000, James Clark <james.clark@arm.com> wrote: > > The guest value for TRFCR requested by the Coresight driver is saved in > kvm_guest_trfcr. On guest switch this value needs to be written to > the register. Currently TRFCR is only modified when we want to disable > trace completely in guests due to an issue with TRBE. Expand the > __debug_save_trace() function to always write to the register if a > different value for guests is required, but also keep the existing TRBE > disable behavior if that's required. > > In pKVM, the kvm_guest_trfcr can't be read and the host isn't trusted, > so always disable trace. > > __debug_restore_trace() now has to restore unconditionally, because even > a value of 0 needs to be written to overwrite whatever was set for the > guest. > > Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com> > Signed-off-by: James Clark <james.clark@arm.com> > --- > arch/arm64/kvm/hyp/nvhe/debug-sr.c | 53 +++++++++++++++++------------- > 1 file changed, 31 insertions(+), 22 deletions(-) > > diff --git a/arch/arm64/kvm/hyp/nvhe/debug-sr.c b/arch/arm64/kvm/hyp/nvhe/debug-sr.c > index 4558c02eb352..3adac2e01908 100644 > --- a/arch/arm64/kvm/hyp/nvhe/debug-sr.c > +++ b/arch/arm64/kvm/hyp/nvhe/debug-sr.c > @@ -51,30 +51,39 @@ static void __debug_restore_spe(u64 pmscr_el1) > write_sysreg_s(pmscr_el1, SYS_PMSCR_EL1); > } > > -static void __debug_save_trace(u64 *trfcr_el1) > +static void __debug_save_trace(struct kvm_vcpu *vcpu) > { > - *trfcr_el1 = 0; > - > - /* Check if the TRBE is enabled */ > - if (!(read_sysreg_s(SYS_TRBLIMITR_EL1) & TRBLIMITR_EL1_E)) > - return; > - /* > - * Prohibit trace generation while we are in guest. > - * Since access to TRFCR_EL1 is trapped, the guest can't > - * modify the filtering set by the host. > - */ > - *trfcr_el1 = read_sysreg_s(SYS_TRFCR_EL1); > - write_sysreg_s(0, SYS_TRFCR_EL1); > - isb(); > - /* Drain the trace buffer to memory */ > - tsb_csync(); > + u64 host_trfcr_el1 = read_sysreg_s(SYS_TRFCR_EL1); > + u64 guest_trfcr_el1; > + > + vcpu->arch.host_debug_state.trfcr_el1 = host_trfcr_el1; Huh, this madness has to stop. See patch below. The short story is that we have to stop shoving host state in vcpus. This is gross, and a stupid waste of memory. > + > + /* Check if the TRBE buffer or pKVM is enabled */ > + if (is_protected_kvm_enabled() || > + (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_TRBE) && > + read_sysreg_s(SYS_TRBLIMITR_EL1) & TRBLIMITR_EL1_E)) { > + /* > + * Prohibit trace generation while we are in guest. Since access > + * to TRFCR_EL1 is trapped, the guest can't modify the filtering > + * set by the host. > + */ > + write_sysreg_s(0, SYS_TRFCR_EL1); > + isb(); > + /* Drain the trace buffer to memory */ > + tsb_csync(); > + } else { > + /* > + * Tracing is allowed, apply the filters provided by the > + * Coresight driver. > + */ > + guest_trfcr_el1 = kvm_guest_trfcr[vcpu->cpu]; > + if (host_trfcr_el1 != guest_trfcr_el1) > + write_sysreg_s(guest_trfcr_el1, SYS_TRFCR_EL1); So we have 3 pieces of storage for TRFCR_EL1: - the system register itself - the copy in host_debug_state, which is only used transiently - another version in kvm_guest_trfcr, provided by Coresight Why do we need to save anything if nothing was enabled, which is *all the time*? I'm sorry to break it to you, but nobody uses these features. So I'd like them to have zero cost when not in use. > + } > } > > static void __debug_restore_trace(u64 trfcr_el1) > { > - if (!trfcr_el1) > - return; > - > /* Restore trace filter controls */ > write_sysreg_s(trfcr_el1, SYS_TRFCR_EL1); > } > @@ -85,8 +94,8 @@ void __debug_save_host_buffers_nvhe(struct kvm_vcpu *vcpu) > if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_SPE)) > __debug_save_spe(&vcpu->arch.host_debug_state.pmscr_el1); > /* Disable and flush Self-Hosted Trace generation */ > - if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_TRBE)) > - __debug_save_trace(&vcpu->arch.host_debug_state.trfcr_el1); > + if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_TRFCR)) > + __debug_save_trace(vcpu); The more I read this code, the less I understand why we need these flags. DEBUG_STATE_SAVE_TRFCR really means "I support TRF". But we already have that information in the ID registers, and we could cache it on a per-physical CPU basis instead of per-vcpu. Hell, on an homogeneous system, this could even be a static key. Do we even have systems out there where only half the CPUs support TRF? Then we check whether TRBE is enabled. But if it isn't, we randomly write whatever is in kvm_guest_trfcr[]? Why would we do that? Surely there is something there that should say "yup, tracing" or not (such as the enable bits), which would avoid hitting the sysreg pointlessly? I really think that this logic should be: - strictly based on ID registers or even better, static keys - result in close to 0 system register access when not in use - avoid storing state that doesn't need to be stored Thanks, M. From a3e98d8428d854209f0e97aa38d1bee347c503f2 Mon Sep 17 00:00:00 2001 From: Marc Zyngier <maz@kernel.org> Date: Mon, 26 Feb 2024 15:58:46 +0000 Subject: [PATCH] KVM: arm64: Exclude host_debug_data from vcpu_arch Keeping host_debug_state on a per-vcpu basis is completely pointless. The lifetime of this data is only that of the inner run-loop, which means it is never accessed outside of the core EL2 code. Move the structure into kvm_host_data, and save over 500 bytes per vcpu. Signed-off-by: Marc Zyngier <maz@kernel.org> --- arch/arm64/include/asm/kvm_host.h | 31 +++++++++++++---------- arch/arm64/kvm/hyp/include/hyp/debug-sr.h | 4 +-- arch/arm64/kvm/hyp/nvhe/debug-sr.c | 8 +++--- 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index addf79ba8fa0..599de77a232f 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -601,6 +601,19 @@ struct kvm_cpu_context { struct kvm_host_data { struct kvm_cpu_context host_ctxt; + + /* + * host_debug_state contains the host registers which are + * saved and restored during world switches. + */ + struct { + /* {Break,watch}point registers */ + struct kvm_guest_debug_arch regs; + /* Statistical profiling extension */ + u64 pmscr_el1; + /* Self-hosted trace */ + u64 trfcr_el1; + } host_debug_state; }; struct kvm_host_psci_config { @@ -695,11 +708,10 @@ struct kvm_vcpu_arch { * We maintain more than a single set of debug registers to support * debugging the guest from the host and to maintain separate host and * guest state during world switches. vcpu_debug_state are the debug - * registers of the vcpu as the guest sees them. host_debug_state are - * the host registers which are saved and restored during - * world switches. external_debug_state contains the debug - * values we want to debug the guest. This is set via the - * KVM_SET_GUEST_DEBUG ioctl. + * registers of the vcpu as the guest sees them. + * + * external_debug_state contains the debug values we want to debug the + * guest. This is set via the KVM_SET_GUEST_DEBUG ioctl. * * debug_ptr points to the set of debug registers that should be loaded * onto the hardware when running the guest. @@ -711,15 +723,6 @@ struct kvm_vcpu_arch { struct user_fpsimd_state *host_fpsimd_state; /* hyp VA */ struct task_struct *parent_task; - struct { - /* {Break,watch}point registers */ - struct kvm_guest_debug_arch regs; - /* Statistical profiling extension */ - u64 pmscr_el1; - /* Self-hosted trace */ - u64 trfcr_el1; - } host_debug_state; - /* VGIC state */ struct vgic_cpu vgic_cpu; struct arch_timer_cpu timer_cpu; diff --git a/arch/arm64/kvm/hyp/include/hyp/debug-sr.h b/arch/arm64/kvm/hyp/include/hyp/debug-sr.h index 961bbef104a6..d2a40eb82f15 100644 --- a/arch/arm64/kvm/hyp/include/hyp/debug-sr.h +++ b/arch/arm64/kvm/hyp/include/hyp/debug-sr.h @@ -137,7 +137,7 @@ static inline void __debug_switch_to_guest_common(struct kvm_vcpu *vcpu) host_ctxt = &this_cpu_ptr(&kvm_host_data)->host_ctxt; guest_ctxt = &vcpu->arch.ctxt; - host_dbg = &vcpu->arch.host_debug_state.regs; + host_dbg = &this_cpu_ptr(&kvm_host_data)->host_debug_state.regs; guest_dbg = kern_hyp_va(vcpu->arch.debug_ptr); __debug_save_state(host_dbg, host_ctxt); @@ -156,7 +156,7 @@ static inline void __debug_switch_to_host_common(struct kvm_vcpu *vcpu) host_ctxt = &this_cpu_ptr(&kvm_host_data)->host_ctxt; guest_ctxt = &vcpu->arch.ctxt; - host_dbg = &vcpu->arch.host_debug_state.regs; + host_dbg = &this_cpu_ptr(&kvm_host_data)->host_debug_state.regs; guest_dbg = kern_hyp_va(vcpu->arch.debug_ptr); __debug_save_state(guest_dbg, guest_ctxt); diff --git a/arch/arm64/kvm/hyp/nvhe/debug-sr.c b/arch/arm64/kvm/hyp/nvhe/debug-sr.c index 4558c02eb352..8103f8c695b4 100644 --- a/arch/arm64/kvm/hyp/nvhe/debug-sr.c +++ b/arch/arm64/kvm/hyp/nvhe/debug-sr.c @@ -83,10 +83,10 @@ void __debug_save_host_buffers_nvhe(struct kvm_vcpu *vcpu) { /* Disable and flush SPE data generation */ if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_SPE)) - __debug_save_spe(&vcpu->arch.host_debug_state.pmscr_el1); + __debug_save_spe(&this_cpu_ptr(&kvm_host_data)->host_debug_state.pmscr_el1); /* Disable and flush Self-Hosted Trace generation */ if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_TRBE)) - __debug_save_trace(&vcpu->arch.host_debug_state.trfcr_el1); + __debug_save_trace(&this_cpu_ptr(&kvm_host_data)->host_debug_state.trfcr_el1); } void __debug_switch_to_guest(struct kvm_vcpu *vcpu) @@ -97,9 +97,9 @@ void __debug_switch_to_guest(struct kvm_vcpu *vcpu) void __debug_restore_host_buffers_nvhe(struct kvm_vcpu *vcpu) { if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_SPE)) - __debug_restore_spe(vcpu->arch.host_debug_state.pmscr_el1); + __debug_restore_spe(this_cpu_ptr(&kvm_host_data)->host_debug_state.pmscr_el1); if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_TRBE)) - __debug_restore_trace(vcpu->arch.host_debug_state.trfcr_el1); + __debug_restore_trace(this_cpu_ptr(&kvm_host_data)->host_debug_state.trfcr_el1); } void __debug_switch_to_host(struct kvm_vcpu *vcpu)
On Mon, 26 Feb 2024 11:30:35 +0000, James Clark <james.clark@arm.com> wrote: > > The guest value for TRFCR requested by the Coresight driver is saved in > kvm_guest_trfcr. On guest switch this value needs to be written to > the register. Currently TRFCR is only modified when we want to disable > trace completely in guests due to an issue with TRBE. Expand the > __debug_save_trace() function to always write to the register if a > different value for guests is required, but also keep the existing TRBE > disable behavior if that's required. > > In pKVM, the kvm_guest_trfcr can't be read and the host isn't trusted, > so always disable trace. > > __debug_restore_trace() now has to restore unconditionally, because even > a value of 0 needs to be written to overwrite whatever was set for the > guest. > > Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com> > Signed-off-by: James Clark <james.clark@arm.com> > --- > arch/arm64/kvm/hyp/nvhe/debug-sr.c | 53 +++++++++++++++++------------- > 1 file changed, 31 insertions(+), 22 deletions(-) > > diff --git a/arch/arm64/kvm/hyp/nvhe/debug-sr.c b/arch/arm64/kvm/hyp/nvhe/debug-sr.c > index 4558c02eb352..3adac2e01908 100644 > --- a/arch/arm64/kvm/hyp/nvhe/debug-sr.c > +++ b/arch/arm64/kvm/hyp/nvhe/debug-sr.c > @@ -51,30 +51,39 @@ static void __debug_restore_spe(u64 pmscr_el1) > write_sysreg_s(pmscr_el1, SYS_PMSCR_EL1); > } > > -static void __debug_save_trace(u64 *trfcr_el1) > +static void __debug_save_trace(struct kvm_vcpu *vcpu) > { > - *trfcr_el1 = 0; > - > - /* Check if the TRBE is enabled */ > - if (!(read_sysreg_s(SYS_TRBLIMITR_EL1) & TRBLIMITR_EL1_E)) > - return; > - /* > - * Prohibit trace generation while we are in guest. > - * Since access to TRFCR_EL1 is trapped, the guest can't > - * modify the filtering set by the host. > - */ > - *trfcr_el1 = read_sysreg_s(SYS_TRFCR_EL1); > - write_sysreg_s(0, SYS_TRFCR_EL1); > - isb(); > - /* Drain the trace buffer to memory */ > - tsb_csync(); > + u64 host_trfcr_el1 = read_sysreg_s(SYS_TRFCR_EL1); Ah, and on top of that, this is already broken with hVHE. I'll send a patch. M.
diff --git a/arch/arm64/kvm/hyp/nvhe/debug-sr.c b/arch/arm64/kvm/hyp/nvhe/debug-sr.c index 4558c02eb352..3adac2e01908 100644 --- a/arch/arm64/kvm/hyp/nvhe/debug-sr.c +++ b/arch/arm64/kvm/hyp/nvhe/debug-sr.c @@ -51,30 +51,39 @@ static void __debug_restore_spe(u64 pmscr_el1) write_sysreg_s(pmscr_el1, SYS_PMSCR_EL1); } -static void __debug_save_trace(u64 *trfcr_el1) +static void __debug_save_trace(struct kvm_vcpu *vcpu) { - *trfcr_el1 = 0; - - /* Check if the TRBE is enabled */ - if (!(read_sysreg_s(SYS_TRBLIMITR_EL1) & TRBLIMITR_EL1_E)) - return; - /* - * Prohibit trace generation while we are in guest. - * Since access to TRFCR_EL1 is trapped, the guest can't - * modify the filtering set by the host. - */ - *trfcr_el1 = read_sysreg_s(SYS_TRFCR_EL1); - write_sysreg_s(0, SYS_TRFCR_EL1); - isb(); - /* Drain the trace buffer to memory */ - tsb_csync(); + u64 host_trfcr_el1 = read_sysreg_s(SYS_TRFCR_EL1); + u64 guest_trfcr_el1; + + vcpu->arch.host_debug_state.trfcr_el1 = host_trfcr_el1; + + /* Check if the TRBE buffer or pKVM is enabled */ + if (is_protected_kvm_enabled() || + (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_TRBE) && + read_sysreg_s(SYS_TRBLIMITR_EL1) & TRBLIMITR_EL1_E)) { + /* + * Prohibit trace generation while we are in guest. Since access + * to TRFCR_EL1 is trapped, the guest can't modify the filtering + * set by the host. + */ + write_sysreg_s(0, SYS_TRFCR_EL1); + isb(); + /* Drain the trace buffer to memory */ + tsb_csync(); + } else { + /* + * Tracing is allowed, apply the filters provided by the + * Coresight driver. + */ + guest_trfcr_el1 = kvm_guest_trfcr[vcpu->cpu]; + if (host_trfcr_el1 != guest_trfcr_el1) + write_sysreg_s(guest_trfcr_el1, SYS_TRFCR_EL1); + } } static void __debug_restore_trace(u64 trfcr_el1) { - if (!trfcr_el1) - return; - /* Restore trace filter controls */ write_sysreg_s(trfcr_el1, SYS_TRFCR_EL1); } @@ -85,8 +94,8 @@ void __debug_save_host_buffers_nvhe(struct kvm_vcpu *vcpu) if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_SPE)) __debug_save_spe(&vcpu->arch.host_debug_state.pmscr_el1); /* Disable and flush Self-Hosted Trace generation */ - if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_TRBE)) - __debug_save_trace(&vcpu->arch.host_debug_state.trfcr_el1); + if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_TRFCR)) + __debug_save_trace(vcpu); } void __debug_switch_to_guest(struct kvm_vcpu *vcpu) @@ -98,7 +107,7 @@ void __debug_restore_host_buffers_nvhe(struct kvm_vcpu *vcpu) { if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_SPE)) __debug_restore_spe(vcpu->arch.host_debug_state.pmscr_el1); - if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_TRBE)) + if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_TRFCR)) __debug_restore_trace(vcpu->arch.host_debug_state.trfcr_el1); }