Message ID | 20240226113044.228403-6-james.clark@arm.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel+bounces-81270-ouuuleilei=gmail.com@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:a81b:b0:108:e6aa:91d0 with SMTP id bq27csp2010019dyb; Mon, 26 Feb 2024 03:34:48 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCVMMKo78NZTQIDiW431rjKb5Yamx7nwMNtvlSZEQoHhcna2lBA8+KCpojA/lHNef+bJV+L7X7MU6SWEOB3CxIjMWmFDRw== X-Google-Smtp-Source: AGHT+IFHmskqpkSGHBhopcKIy0mngRf6d4hUt74mfELeT0m0ZjetSOms+EHr6RARIed9sMT8if65 X-Received: by 2002:a9d:7996:0:b0:6e4:741b:b0d with SMTP id h22-20020a9d7996000000b006e4741b0b0dmr6188629otm.26.1708947287921; Mon, 26 Feb 2024 03:34:47 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1708947287; cv=pass; d=google.com; s=arc-20160816; b=02t6AQ/E07yqTo484gXZHKzc34YMgfgjTG5+exyJHqkiwlTkNQ5zzMvNEnPDK7nu/4 hREcfDKBcuZBTp+iCnHPBn4zIBUfXgC0ajTL7FFDQAYns4ECFJS4rbisB20yl/xQATmg OBMk7wH8ijgnlFomi6yVj4h96fteLmlPi5BFxcL6TEqvd48Q/wj+fYgzvhocLm/6ft8F ibLMLP2zTmqopkSPgoK7WTwdVGjKD3cvqWIfgOlYR/TwmdbEFglGTpFM8rlrkGhOQxp0 1ivRnE16Ub12ZPM0mHIG7LiMSLWri+JZoB8eedgA4hJa/LKeZm83gAcAIa2mzhU13uv+ 8Dww== 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=mOnqWcvqeqn3ekdsaSi5qwdkBEiKRgs91KldQwI8LgM=; fh=Uw9urSoYJqm5OAaDDYwE3Ep0eSbC21I7/GlPjZ6bKus=; b=MoI0RcaborFidazv/fkEJAXMWHflURgL+IbXjhStG1DxuL7+7WWw7Lnc2WLIA87ttT gaqXP4I2XZ5CU7aXGG/w909TH1qBIBvCgAaAwlxtQsTNzR1NThRLRXoEymj4V2xsxOih gXxA8UCd3gdUIGdS28x9UsHczRWI+iHsjo03/f1Lz5MUMakhYmalmxK7nx7H/Vu/mg5D hYn272Wm4I1fUQVem/OWERWsYBsoy1YYwzHHvaLhGE075bVUWM1NK9gQ1kIr3zTl044D OHkKFqBTKMfVg5OMBSNwLr6P80cf9Fjl9Zvr3VT8BxB3mQ3pybhu+B8tYgZboOYlhAgY Qe/A==; 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-81270-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-81270-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [2604:1380:45e3:2400::1]) by mx.google.com with ESMTPS id r11-20020a63514b000000b005dcc8a3fdc5si3520319pgl.485.2024.02.26.03.34.47 for <ouuuleilei@gmail.com> (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 26 Feb 2024 03:34:47 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-81270-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) client-ip=2604:1380:45e3:2400::1; 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-81270-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-81270-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 sv.mirrors.kernel.org (Postfix) with ESMTPS id 882432894F2 for <ouuuleilei@gmail.com>; Mon, 26 Feb 2024 11:34:47 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 7CCA82C85A; Mon, 26 Feb 2024 11:33:59 +0000 (UTC) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 2F87C22EE0 for <linux-kernel@vger.kernel.org>; Mon, 26 Feb 2024 11:33:56 +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=1708947237; cv=none; b=FMZKd0X9urnXchZrSd2EAUMi9wu/IVnKGjZh7e6EYYCfBklSg/1Z51nr//NeFt65vjyrCXgmd/SKXsBUgXMBRDK9sq5U/gSLB7by4FGMcwpjHv0vMP9zqSoy1sIX4iLSprHhHJQWQyBgji54kWO1SgU1liPTWibPL2Yz2eJoioc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708947237; c=relaxed/simple; bh=+nicV0g2b5jsmt8ZfpewvXZy/UwWJ4BnLx9od6RHkZg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=MZu23AoYkaI6PMt6qR3oFjhP0LQmE31AGjGhPb/hOkUJjZwHQ3HeSbqfvjG1kJ4djgFEdVKDo3b5gkb5W9kkTGv7+Gq6Me/C1hXNPKnA5tvUp0x6wX/O1COO3t7tUaOFWgz4Y6YwlZGu7dOWSWNvF85OiJCZdCfokTaxWXMj4s4= 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 4D2CFDA7; Mon, 26 Feb 2024 03:34:34 -0800 (PST) Received: from e127643.broadband (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 302833F6C4; Mon, 26 Feb 2024 03:33:52 -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>, Quentin Perret <qperret@google.com>, Javier Martinez Canillas <javierm@redhat.com>, Mark Rutland <mark.rutland@arm.com>, Arnd Bergmann <arnd@arndb.de>, 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 5/8] arm64: KVM: Add iflag for FEAT_TRF Date: Mon, 26 Feb 2024 11:30:33 +0000 Message-Id: <20240226113044.228403-6-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: 1791961111526067960 X-GMAIL-MSGID: 1791961111526067960 |
Series |
kvm/coresight: Support exclude guest and exclude host
|
|
Commit Message
James Clark
Feb. 26, 2024, 11:30 a.m. UTC
Add an extra iflag to signify if the TRFCR register is accessible. Because TRBE requires FEAT_TRF, DEBUG_STATE_SAVE_TRBE still has the same behavior even though it's only set when FEAT_TRF is present. The following holes are left in struct kvm_vcpu_arch, but there aren't enough other 8 bit fields to rearrange it to leave any hole smaller than 7 bytes: u8 cflags; /* 2292 1 */ /* XXX 1 byte hole, try to pack */ u16 iflags; /* 2294 2 */ u8 sflags; /* 2296 1 */ bool pause; /* 2297 1 */ /* XXX 6 bytes hole, try to pack */ Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com> Signed-off-by: James Clark <james.clark@arm.com> --- arch/arm64/include/asm/kvm_host.h | 4 +++- arch/arm64/kvm/debug.c | 24 ++++++++++++++++++++---- 2 files changed, 23 insertions(+), 5 deletions(-)
Comments
On Mon, 26 Feb 2024 11:30:33 +0000, James Clark <james.clark@arm.com> wrote: > > Add an extra iflag to signify if the TRFCR register is accessible. That's not what this flag means: it indicates whether TRFCR needs to be saved. At lease that's what the name suggests. > Because TRBE requires FEAT_TRF, DEBUG_STATE_SAVE_TRBE still has the same > behavior even though it's only set when FEAT_TRF is present. This sentence seems completely out of context, because you didn't explain that you were making TRBE *conditional* on TRF being implemented, as per the architecture requirements. > > The following holes are left in struct kvm_vcpu_arch, but there aren't > enough other 8 bit fields to rearrange it to leave any hole smaller than > 7 bytes: > > u8 cflags; /* 2292 1 */ > /* XXX 1 byte hole, try to pack */ > u16 iflags; /* 2294 2 */ > u8 sflags; /* 2296 1 */ > bool pause; /* 2297 1 */ > /* XXX 6 bytes hole, try to pack */ I don't think that's particularly useful in a commit message, but more relevant to the cover letter. However, see below. > > Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com> > Signed-off-by: James Clark <james.clark@arm.com> > --- > arch/arm64/include/asm/kvm_host.h | 4 +++- > arch/arm64/kvm/debug.c | 24 ++++++++++++++++++++---- > 2 files changed, 23 insertions(+), 5 deletions(-) > > diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h > index 21c57b812569..85b5477bd1b4 100644 > --- a/arch/arm64/include/asm/kvm_host.h > +++ b/arch/arm64/include/asm/kvm_host.h > @@ -569,7 +569,7 @@ struct kvm_vcpu_arch { > u8 cflags; > > /* Input flags to the hypervisor code, potentially cleared after use */ > - u8 iflags; > + u16 iflags; > > /* State flags for kernel bookkeeping, unused by the hypervisor code */ > u8 sflags; > @@ -779,6 +779,8 @@ struct kvm_vcpu_arch { > #define DEBUG_STATE_SAVE_TRBE __vcpu_single_flag(iflags, BIT(6)) > /* vcpu running in HYP context */ > #define VCPU_HYP_CONTEXT __vcpu_single_flag(iflags, BIT(7)) > +/* Save trace filter controls */ > +#define DEBUG_STATE_SAVE_TRFCR __vcpu_single_flag(iflags, BIT(8)) I'd rather you cherry-pick [1] and avoid expanding the iflags. [1] https://lore.kernel.org/r/20240226100601.2379693-4-maz@kernel.org Now, I think the whole SPE/TRBE/TRCR flag management should be improved, see below. > > /* SVE enabled for host EL0 */ > #define HOST_SVE_ENABLED __vcpu_single_flag(sflags, BIT(0)) > diff --git a/arch/arm64/kvm/debug.c b/arch/arm64/kvm/debug.c > index ce8886122ed3..49a13e72ddd2 100644 > --- a/arch/arm64/kvm/debug.c > +++ b/arch/arm64/kvm/debug.c > @@ -332,14 +332,30 @@ void kvm_arch_vcpu_load_debug_state_flags(struct kvm_vcpu *vcpu) > !(read_sysreg_s(SYS_PMBIDR_EL1) & BIT(PMBIDR_EL1_P_SHIFT))) > vcpu_set_flag(vcpu, DEBUG_STATE_SAVE_SPE); > > - /* Check if we have TRBE implemented and available at the host */ > - if (cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_TraceBuffer_SHIFT) && > - !(read_sysreg_s(SYS_TRBIDR_EL1) & TRBIDR_EL1_P)) > - vcpu_set_flag(vcpu, DEBUG_STATE_SAVE_TRBE); > + /* > + * Set SAVE_TRFCR flag if FEAT_TRF (TraceFilt) exists. This flag > + * signifies that the exclude_host/exclude_guest settings of any active > + * host Perf session on a core running a VCPU can be written into > + * TRFCR_EL1 on guest switch. > + */ > + if (cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_TraceFilt_SHIFT)) { > + vcpu_set_flag(vcpu, DEBUG_STATE_SAVE_TRFCR); Can we avoid doing this unconditionally? It only makes sense to save the trace crud if it is going to be changed, right? > + /* > + * Check if we have TRBE implemented and available at the host. > + * If it's in use at the time of guest switch then trace will > + * need to be completely disabled. The architecture mandates > + * FEAT_TRF with TRBE, so we only need to check for TRBE after > + * TRF. > + */ > + if (cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_TraceBuffer_SHIFT) && > + !(read_sysreg_s(SYS_TRBIDR_EL1) & TRBIDR_EL1_P)) > + vcpu_set_flag(vcpu, DEBUG_STATE_SAVE_TRBE); > + } > } > > void kvm_arch_vcpu_put_debug_state_flags(struct kvm_vcpu *vcpu) > { > vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE_SPE); > vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE_TRBE); > + vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE_TRFCR); > } Dealing with flags that are strongly coupled in a disjoined way a pretty bad idea. Look at the generated code, and realise we flip the preempt flag on each access. Can we do better? You bet. The vcpu_{set,clear}_flags infrastructure is capable of dealing with multiple flags at once, as demonstrated by the way we deal with exception encoding. Something like: diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index addf79ba8fa0..3e50e535fdd4 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -885,6 +885,10 @@ struct kvm_vcpu_arch { #define DEBUG_STATE_SAVE_SPE __vcpu_single_flag(iflags, BIT(5)) /* Save TRBE context if active */ #define DEBUG_STATE_SAVE_TRBE __vcpu_single_flag(iflags, BIT(6)) +/* Save Trace Filter Controls */ +#define DEBUG_STATE_SAVE_TRFCR __vcpu_single_flag(iflags, BIT(7)) +/* Global debug mask */ +#define DEBUG_STATE_SAVE_MASK __vcpu_single_flag(iflags, GENMASK(7, 5)) /* SVE enabled for host EL0 */ #define HOST_SVE_ENABLED __vcpu_single_flag(sflags, BIT(0)) diff --git a/arch/arm64/kvm/debug.c b/arch/arm64/kvm/debug.c index 8725291cb00a..f9b197a00582 100644 --- a/arch/arm64/kvm/debug.c +++ b/arch/arm64/kvm/debug.c @@ -339,6 +339,6 @@ void kvm_arch_vcpu_load_debug_state_flags(struct kvm_vcpu *vcpu) void kvm_arch_vcpu_put_debug_state_flags(struct kvm_vcpu *vcpu) { - vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE_SPE); - vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE_TRBE); + if (!has_vhe()) + vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE_MASK); } Thanks, M.
On 26/02/2024 13:35, Marc Zyngier wrote: > On Mon, 26 Feb 2024 11:30:33 +0000, > James Clark <james.clark@arm.com> wrote: >> >> Add an extra iflag to signify if the TRFCR register is accessible. > > That's not what this flag means: it indicates whether TRFCR needs to > be saved. At lease that's what the name suggests. > >> Because TRBE requires FEAT_TRF, DEBUG_STATE_SAVE_TRBE still has the same >> behavior even though it's only set when FEAT_TRF is present. > > This sentence seems completely out of context, because you didn't > explain that you were making TRBE *conditional* on TRF being > implemented, as per the architecture requirements. > >> >> The following holes are left in struct kvm_vcpu_arch, but there aren't >> enough other 8 bit fields to rearrange it to leave any hole smaller than >> 7 bytes: >> >> u8 cflags; /* 2292 1 */ >> /* XXX 1 byte hole, try to pack */ >> u16 iflags; /* 2294 2 */ >> u8 sflags; /* 2296 1 */ >> bool pause; /* 2297 1 */ >> /* XXX 6 bytes hole, try to pack */ > > I don't think that's particularly useful in a commit message, but more > relevant to the cover letter. However, see below. > >> >> Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com> >> Signed-off-by: James Clark <james.clark@arm.com> >> --- >> arch/arm64/include/asm/kvm_host.h | 4 +++- >> arch/arm64/kvm/debug.c | 24 ++++++++++++++++++++---- >> 2 files changed, 23 insertions(+), 5 deletions(-) >> >> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h >> index 21c57b812569..85b5477bd1b4 100644 >> --- a/arch/arm64/include/asm/kvm_host.h >> +++ b/arch/arm64/include/asm/kvm_host.h >> @@ -569,7 +569,7 @@ struct kvm_vcpu_arch { >> u8 cflags; >> >> /* Input flags to the hypervisor code, potentially cleared after use */ >> - u8 iflags; >> + u16 iflags; >> >> /* State flags for kernel bookkeeping, unused by the hypervisor code */ >> u8 sflags; >> @@ -779,6 +779,8 @@ struct kvm_vcpu_arch { >> #define DEBUG_STATE_SAVE_TRBE __vcpu_single_flag(iflags, BIT(6)) >> /* vcpu running in HYP context */ >> #define VCPU_HYP_CONTEXT __vcpu_single_flag(iflags, BIT(7)) >> +/* Save trace filter controls */ >> +#define DEBUG_STATE_SAVE_TRFCR __vcpu_single_flag(iflags, BIT(8)) > > I'd rather you cherry-pick [1] and avoid expanding the iflags. > > [1] https://lore.kernel.org/r/20240226100601.2379693-4-maz@kernel.org > > Now, I think the whole SPE/TRBE/TRCR flag management should be > improved, see below. > >> >> /* SVE enabled for host EL0 */ >> #define HOST_SVE_ENABLED __vcpu_single_flag(sflags, BIT(0)) >> diff --git a/arch/arm64/kvm/debug.c b/arch/arm64/kvm/debug.c >> index ce8886122ed3..49a13e72ddd2 100644 >> --- a/arch/arm64/kvm/debug.c >> +++ b/arch/arm64/kvm/debug.c >> @@ -332,14 +332,30 @@ void kvm_arch_vcpu_load_debug_state_flags(struct kvm_vcpu *vcpu) >> !(read_sysreg_s(SYS_PMBIDR_EL1) & BIT(PMBIDR_EL1_P_SHIFT))) >> vcpu_set_flag(vcpu, DEBUG_STATE_SAVE_SPE); >> >> - /* Check if we have TRBE implemented and available at the host */ >> - if (cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_TraceBuffer_SHIFT) && >> - !(read_sysreg_s(SYS_TRBIDR_EL1) & TRBIDR_EL1_P)) >> - vcpu_set_flag(vcpu, DEBUG_STATE_SAVE_TRBE); >> + /* >> + * Set SAVE_TRFCR flag if FEAT_TRF (TraceFilt) exists. This flag >> + * signifies that the exclude_host/exclude_guest settings of any active >> + * host Perf session on a core running a VCPU can be written into >> + * TRFCR_EL1 on guest switch. >> + */ >> + if (cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_TraceFilt_SHIFT)) { >> + vcpu_set_flag(vcpu, DEBUG_STATE_SAVE_TRFCR); > > Can we avoid doing this unconditionally? It only makes sense to save > the trace crud if it is going to be changed, right? > Do you mean to see if kvm_guest_trfcr was non-zero (and would have to be changed) at VCPU load? I assumed that it could be modified between load and switch. That would mean there is no way to do it conditionally. I also assumed that's the reason SPE and TRBE were implemented like this, with the feat check at load and the enabled check at switch. It doesn't feel like TRFCR is any different to those two. Or do you mean to only set DEBUG_STATE_SAVE_TRFCR on switch if tracing was enabled? I suppose the names DEBUG_STATE_SAVE_SPE and DEBUG_STATE_SAVE_TRBE are slightly misleading because neither are actually saved if they weren't enabled. They're more like DEBUG_STATE_HAS_SPE and DEBUG_STATE_HAS_TRBE. >> + /* >> + * Check if we have TRBE implemented and available at the host. >> + * If it's in use at the time of guest switch then trace will >> + * need to be completely disabled. The architecture mandates >> + * FEAT_TRF with TRBE, so we only need to check for TRBE after >> + * TRF. >> + */ >> + if (cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_TraceBuffer_SHIFT) && >> + !(read_sysreg_s(SYS_TRBIDR_EL1) & TRBIDR_EL1_P)) >> + vcpu_set_flag(vcpu, DEBUG_STATE_SAVE_TRBE); >> + } >> } >> >> void kvm_arch_vcpu_put_debug_state_flags(struct kvm_vcpu *vcpu) >> { >> vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE_SPE); >> vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE_TRBE); >> + vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE_TRFCR); >> } > > Dealing with flags that are strongly coupled in a disjoined way a > pretty bad idea. Look at the generated code, and realise we flip the > preempt flag on each access. > > Can we do better? You bet. The vcpu_{set,clear}_flags infrastructure > is capable of dealing with multiple flags at once, as demonstrated by > the way we deal with exception encoding. > Oops yeah I didn't realize that this was more than a bit set/clear. I will combine them. I think I could probably combine the TRBE/TRF set as well. Agree with the rest of the comments too. Thanks James > Something like: > > diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h > index addf79ba8fa0..3e50e535fdd4 100644 > --- a/arch/arm64/include/asm/kvm_host.h > +++ b/arch/arm64/include/asm/kvm_host.h > @@ -885,6 +885,10 @@ struct kvm_vcpu_arch { > #define DEBUG_STATE_SAVE_SPE __vcpu_single_flag(iflags, BIT(5)) > /* Save TRBE context if active */ > #define DEBUG_STATE_SAVE_TRBE __vcpu_single_flag(iflags, BIT(6)) > +/* Save Trace Filter Controls */ > +#define DEBUG_STATE_SAVE_TRFCR __vcpu_single_flag(iflags, BIT(7)) > +/* Global debug mask */ > +#define DEBUG_STATE_SAVE_MASK __vcpu_single_flag(iflags, GENMASK(7, 5)) > > /* SVE enabled for host EL0 */ > #define HOST_SVE_ENABLED __vcpu_single_flag(sflags, BIT(0)) > diff --git a/arch/arm64/kvm/debug.c b/arch/arm64/kvm/debug.c > index 8725291cb00a..f9b197a00582 100644 > --- a/arch/arm64/kvm/debug.c > +++ b/arch/arm64/kvm/debug.c > @@ -339,6 +339,6 @@ void kvm_arch_vcpu_load_debug_state_flags(struct kvm_vcpu *vcpu) > > void kvm_arch_vcpu_put_debug_state_flags(struct kvm_vcpu *vcpu) > { > - vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE_SPE); > - vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE_TRBE); > + if (!has_vhe()) > + vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE_MASK); > } > > Thanks, > > M. >
On Mon, 26 Feb 2024 15:41:02 +0000, James Clark <james.clark@arm.com> wrote: > > > > On 26/02/2024 13:35, Marc Zyngier wrote: > > On Mon, 26 Feb 2024 11:30:33 +0000, > > James Clark <james.clark@arm.com> wrote: [...] > >> diff --git a/arch/arm64/kvm/debug.c b/arch/arm64/kvm/debug.c > >> index ce8886122ed3..49a13e72ddd2 100644 > >> --- a/arch/arm64/kvm/debug.c > >> +++ b/arch/arm64/kvm/debug.c > >> @@ -332,14 +332,30 @@ void kvm_arch_vcpu_load_debug_state_flags(struct kvm_vcpu *vcpu) > >> !(read_sysreg_s(SYS_PMBIDR_EL1) & BIT(PMBIDR_EL1_P_SHIFT))) > >> vcpu_set_flag(vcpu, DEBUG_STATE_SAVE_SPE); > >> > >> - /* Check if we have TRBE implemented and available at the host */ > >> - if (cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_TraceBuffer_SHIFT) && > >> - !(read_sysreg_s(SYS_TRBIDR_EL1) & TRBIDR_EL1_P)) > >> - vcpu_set_flag(vcpu, DEBUG_STATE_SAVE_TRBE); > >> + /* > >> + * Set SAVE_TRFCR flag if FEAT_TRF (TraceFilt) exists. This flag > >> + * signifies that the exclude_host/exclude_guest settings of any active > >> + * host Perf session on a core running a VCPU can be written into > >> + * TRFCR_EL1 on guest switch. > >> + */ > >> + if (cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_TraceFilt_SHIFT)) { > >> + vcpu_set_flag(vcpu, DEBUG_STATE_SAVE_TRFCR); > > > > Can we avoid doing this unconditionally? It only makes sense to save > > the trace crud if it is going to be changed, right? > > > > Do you mean to see if kvm_guest_trfcr was non-zero (and would have to be > changed) at VCPU load? I assumed that it could be modified between load > and switch. That would mean there is no way to do it conditionally. What's the problem? If you change the value behind the vcpu's back, you get what you deserve: garbage. I'm baffled that you consider that randomly changing a value without proper synchronisation (such as with an IPI) is a valid approach. Please look at what is being done for the PMU in the same context. > I also assumed that's the reason SPE and TRBE were implemented like > this, with the feat check at load and the enabled check at switch. It > doesn't feel like TRFCR is any different to those two. Well, that' doesn't make it right. Having just looked at the debug stuff, I'm ashamed to have let that stuff in. > Or do you mean to only set DEBUG_STATE_SAVE_TRFCR on switch if tracing > was enabled? I don't think there should be any flag. The discriminant should be: - does the HW support TRF? - is the in-guest tracing enabled? If both are true, and that this requires a change of configuration, *then* you perform the change. Same thing on exit. No flag. And a static key for TRF support, which should really be valid on all CPUs. M.
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 21c57b812569..85b5477bd1b4 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -569,7 +569,7 @@ struct kvm_vcpu_arch { u8 cflags; /* Input flags to the hypervisor code, potentially cleared after use */ - u8 iflags; + u16 iflags; /* State flags for kernel bookkeeping, unused by the hypervisor code */ u8 sflags; @@ -779,6 +779,8 @@ struct kvm_vcpu_arch { #define DEBUG_STATE_SAVE_TRBE __vcpu_single_flag(iflags, BIT(6)) /* vcpu running in HYP context */ #define VCPU_HYP_CONTEXT __vcpu_single_flag(iflags, BIT(7)) +/* Save trace filter controls */ +#define DEBUG_STATE_SAVE_TRFCR __vcpu_single_flag(iflags, BIT(8)) /* SVE enabled for host EL0 */ #define HOST_SVE_ENABLED __vcpu_single_flag(sflags, BIT(0)) diff --git a/arch/arm64/kvm/debug.c b/arch/arm64/kvm/debug.c index ce8886122ed3..49a13e72ddd2 100644 --- a/arch/arm64/kvm/debug.c +++ b/arch/arm64/kvm/debug.c @@ -332,14 +332,30 @@ void kvm_arch_vcpu_load_debug_state_flags(struct kvm_vcpu *vcpu) !(read_sysreg_s(SYS_PMBIDR_EL1) & BIT(PMBIDR_EL1_P_SHIFT))) vcpu_set_flag(vcpu, DEBUG_STATE_SAVE_SPE); - /* Check if we have TRBE implemented and available at the host */ - if (cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_TraceBuffer_SHIFT) && - !(read_sysreg_s(SYS_TRBIDR_EL1) & TRBIDR_EL1_P)) - vcpu_set_flag(vcpu, DEBUG_STATE_SAVE_TRBE); + /* + * Set SAVE_TRFCR flag if FEAT_TRF (TraceFilt) exists. This flag + * signifies that the exclude_host/exclude_guest settings of any active + * host Perf session on a core running a VCPU can be written into + * TRFCR_EL1 on guest switch. + */ + if (cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_TraceFilt_SHIFT)) { + vcpu_set_flag(vcpu, DEBUG_STATE_SAVE_TRFCR); + /* + * Check if we have TRBE implemented and available at the host. + * If it's in use at the time of guest switch then trace will + * need to be completely disabled. The architecture mandates + * FEAT_TRF with TRBE, so we only need to check for TRBE after + * TRF. + */ + if (cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_TraceBuffer_SHIFT) && + !(read_sysreg_s(SYS_TRBIDR_EL1) & TRBIDR_EL1_P)) + vcpu_set_flag(vcpu, DEBUG_STATE_SAVE_TRBE); + } } void kvm_arch_vcpu_put_debug_state_flags(struct kvm_vcpu *vcpu) { vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE_SPE); vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE_TRBE); + vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE_TRFCR); }