linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 0/7] kvm/coresight: Support exclude guest and exclude host
@ 2024-02-20 10:09 James Clark
  2024-02-20 10:09 ` [PATCH v5 1/7] arm64: KVM: Fix renamed function in comment James Clark
                   ` (6 more replies)
  0 siblings, 7 replies; 18+ messages in thread
From: James Clark @ 2024-02-20 10:09 UTC (permalink / raw)
  To: coresight, linux-arm-kernel, kvmarm, maz, suzuki.poulose, acme,
	oliver.upton, broonie
  Cc: James Clark, James Morse, Zenghui Yu, Catalin Marinas,
	Will Deacon, Mike Leach, Alexander Shishkin, Anshuman Khandual,
	Miguel Luis, Joey Gouly, Ard Biesheuvel, Greg Kroah-Hartman,
	Mark Rutland, Helge Deller, Arnd Bergmann, Vincent Donnefort,
	Ryan Roberts, Fuad Tabba, Jing Zhang, linux-kernel

This is a combination of the RFC for nVHE here [1] and v3 of VHE version
here [2]. After a few of the review comments it seemed much simpler for
both versions to use the same interface and be in the same patchset.

FEAT_TRF is a Coresight feature that allows trace capture to be
completely filtered at different exception levels, unlike the existing
TRCVICTLR controls which may still emit target addresses of branches,
even if the following trace is filtered.

Without FEAT_TRF, it was possible to start a trace session on a host and
also collect trace from the guest as TRCVICTLR was never programmed to
exclude guests (and it could still emit target addresses even if it
was).

With FEAT_TRF, the current behavior of trace in guests exists depends on
whether nVHE or VHE are being used. Both of the examples below are from
the host's point of view, as Coresight isn't accessible from guests.
This patchset is only relevant to when FEAT_TRF exists, otherwise there
is no change.

  nVHE/pKVM:

  Because the host and the guest are both using TRFCR_EL1, trace will be
  generated in guests depending on the same filter rules the host is
  using. For example if the host is tracing userspace only, then guest
  userspace trace will also be collected.

  (This is further limited by whether TRBE is used because an issue
  with TRBE means that it's completely disabled in nVHE guests, but it's
  possible to have other tracing components.)

  VHE:

  With VHE, the host filters will be in TRFCR_EL2, but the filters in
  TRFCR_EL1 will be active when the guest is running. Because we don't
  write to TRFCR_EL1, guest trace will be completely disabled.

With this change, the guest filtering rules from the Perf session are
now honored for both nVHE and VHE modes. This is done by either writing
to TRFCR_EL12 at the start of the Perf session and doing nothing else
further, or caching the guest value and writing it at guest switch for
nVHE. In pKVM, trace is now be disabled for both protected and
unprotected guests.

---

Changes since V4 [3]:
  * Remove all V3 changes that made it work in pKVM and just disable
    trace there instead
  * Restore PMU host/hyp state sharing back to how it was
    (kvm_pmu_update_vcpu_events())
  * Simplify some of the duplication in the comments and function docs
  * Add a WARN_ON_ONCE() if kvm_etm_set_guest_trfcr() is called when
    the trace filtering feature doesn't exist.
  * Split sysreg change into a tools update followed by the new register
    addition

Changes since V3:
  * Create a new shared area to store the host state instead of copying
    it before each VCPU run
  * Drop commit that moved SPE and trace registers from host_debug_state
    into the kvm sysregs array because the guest values were never used 
  * Document kvm_etm_set_guest_trfcr()
  * Guard kvm_etm_set_guest_trfcr() with a feature check
  * Drop Mark B and Suzuki's review tags on the sysreg patch because it
    turned out that broke the Perf build and needed some unconventional
    changes to fix it (as in: to update the tools copy of the headers in
    the same commit as the kernel changes)

Changes since V2:

  * Add a new iflag to signify presence of FEAT_TRF and keep the
    existing TRBE iflag. This fixes the issue where TRBLIMITR_EL1 was
    being accessed even if TRBE didn't exist
  * Reword a commit message

Changes since V1:

  * Squashed all the arm64/tools/sysreg changes into the first commit
  * Add a new commit to move SPE and TRBE regs into the kvm sysreg array
  * Add a comment above the TRFCR global that it's per host CPU rather
    than vcpu

Changes since nVHE RFC [1]:

 * Re-write just in terms of the register value to be written for the
   host and the guest. This removes some logic from the hyp code and
   a value of kvm_vcpu_arch:trfcr_el1 = 0 no longer means "don't
   restore".
 * Remove all the conditional compilation and new files.
 * Change the kvm_etm_update_vcpu_events macro to a function.
 * Re-use DEBUG_STATE_SAVE_TRFCR so iflags don't need to be expanded
   anymore.
 * Expand the cover letter.

Changes since VHE v3 [2]:

 * Use the same interface as nVHE mode so TRFCR_EL12 is now written by
   kvm.

[1]: https://lore.kernel.org/kvmarm/20230804101317.460697-1-james.clark@arm.com/
[2]: https://lore.kernel.org/kvmarm/20230905102117.2011094-1-james.clark@arm.com/
[3]: https://lore.kernel.org/linux-arm-kernel/20240104162714.1062610-1-james.clark@arm.com/

James Clark (7):
  arm64: KVM: Fix renamed function in comment
  arm64/sysreg/tools: Update tools copy of sysreg.h
  arm64/sysreg/tools: Move TRFCR definitions to sysreg
  arm64: KVM: Add iflag for FEAT_TRF
  arm64: KVM: Add interface to set guest value for TRFCR register
  arm64: KVM: Write TRFCR value on guest switch with nVHE
  coresight: Pass guest TRFCR value to KVM

 arch/arm64/include/asm/kvm_host.h             |   7 +-
 arch/arm64/include/asm/sysreg.h               |  12 -
 arch/arm64/kernel/image-vars.h                |   1 +
 arch/arm64/kvm/debug.c                        |  50 ++-
 arch/arm64/kvm/hyp/nvhe/debug-sr.c            |  53 ++-
 arch/arm64/kvm/hyp/nvhe/setup.c               |   2 +-
 arch/arm64/tools/sysreg                       |  41 ++
 .../coresight/coresight-etm4x-core.c          |  42 +-
 drivers/hwtracing/coresight/coresight-etm4x.h |   2 +-
 drivers/hwtracing/coresight/coresight-priv.h  |   3 +
 tools/arch/arm64/include/asm/sysreg.h         | 375 +++++++++++++++++-
 tools/include/linux/kasan-tags.h              |  15 +
 12 files changed, 541 insertions(+), 62 deletions(-)
 create mode 100644 tools/include/linux/kasan-tags.h

-- 
2.34.1


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v5 1/7] arm64: KVM: Fix renamed function in comment
  2024-02-20 10:09 [PATCH v5 0/7] kvm/coresight: Support exclude guest and exclude host James Clark
@ 2024-02-20 10:09 ` James Clark
  2024-02-20 10:09 ` [PATCH v5 2/7] arm64/sysreg/tools: Update tools copy of sysreg.h James Clark
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 18+ messages in thread
From: James Clark @ 2024-02-20 10:09 UTC (permalink / raw)
  To: coresight, linux-arm-kernel, kvmarm, maz, suzuki.poulose, acme,
	oliver.upton, broonie
  Cc: James Clark, James Morse, Zenghui Yu, Catalin Marinas,
	Will Deacon, Mike Leach, Alexander Shishkin, Anshuman Khandual,
	Miguel Luis, Joey Gouly, Ard Biesheuvel, Greg Kroah-Hartman,
	Helge Deller, Arnd Bergmann, Mark Rutland, Vincent Donnefort,
	Kalesh Singh, Ryan Roberts, Fuad Tabba, Jing Zhang, linux-kernel

finalize_host_mappings() became fix_host_ownership() in
commit 0d16d12eb26e ("KVM: arm64: Fix-up hyp stage-1 refcounts for all
pages mapped at EL2") so update the comment.

Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: James Clark <james.clark@arm.com>
---
 arch/arm64/kvm/hyp/nvhe/setup.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/hyp/nvhe/setup.c b/arch/arm64/kvm/hyp/nvhe/setup.c
index bc58d1b515af..11d77aa36173 100644
--- a/arch/arm64/kvm/hyp/nvhe/setup.c
+++ b/arch/arm64/kvm/hyp/nvhe/setup.c
@@ -131,7 +131,7 @@ static int recreate_hyp_mappings(phys_addr_t phys, unsigned long size,
 	 * can't be donated or shared with another entity.
 	 *
 	 * The ownership transition requires matching changes in the host
-	 * stage-2. This will be done later (see finalize_host_mappings()) once
+	 * stage-2. This will be done later (see fix_host_ownership()) once
 	 * the hyp_vmemmap is addressable.
 	 */
 	prot = pkvm_mkstate(PAGE_HYP_RO, PKVM_PAGE_SHARED_OWNED);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v5 2/7] arm64/sysreg/tools: Update tools copy of sysreg.h
  2024-02-20 10:09 [PATCH v5 0/7] kvm/coresight: Support exclude guest and exclude host James Clark
  2024-02-20 10:09 ` [PATCH v5 1/7] arm64: KVM: Fix renamed function in comment James Clark
@ 2024-02-20 10:09 ` James Clark
  2024-02-20 16:12   ` Mark Brown
  2024-02-26 10:30   ` Suzuki K Poulose
  2024-02-20 10:09 ` [PATCH v5 3/7] arm64/sysreg/tools: Move TRFCR definitions to sysreg James Clark
                   ` (4 subsequent siblings)
  6 siblings, 2 replies; 18+ messages in thread
From: James Clark @ 2024-02-20 10:09 UTC (permalink / raw)
  To: coresight, linux-arm-kernel, kvmarm, maz, suzuki.poulose, acme,
	oliver.upton, broonie
  Cc: James Clark, James Morse, Zenghui Yu, Catalin Marinas,
	Will Deacon, Mike Leach, Alexander Shishkin, Anshuman Khandual,
	Miguel Luis, Joey Gouly, Ard Biesheuvel, Helge Deller,
	Greg Kroah-Hartman, Arnd Bergmann, Andrew Walbran, Kalesh Singh,
	Vincent Donnefort, Ryan Roberts, Fuad Tabba, Jing Zhang,
	linux-kernel

Created with the following:

  cp include/linux/kasan-tags.h tools/include/linux/
  cp arch/arm64/include/asm/sysreg.h tools/arch/arm64/include/asm/

Update the tools copy of sysreg.h so that the next commit to add a new
register doesn't have unrelated changes in it. Because the new version
of sysreg.h includes kasan-tags.h, that file also now needs to be copied
into tools.

Signed-off-by: James Clark <james.clark@arm.com>
---
 tools/arch/arm64/include/asm/sysreg.h | 363 +++++++++++++++++++++++++-
 tools/include/linux/kasan-tags.h      |  15 ++
 2 files changed, 375 insertions(+), 3 deletions(-)
 create mode 100644 tools/include/linux/kasan-tags.h

diff --git a/tools/arch/arm64/include/asm/sysreg.h b/tools/arch/arm64/include/asm/sysreg.h
index ccc13e991376..9e8999592f3a 100644
--- a/tools/arch/arm64/include/asm/sysreg.h
+++ b/tools/arch/arm64/include/asm/sysreg.h
@@ -11,6 +11,7 @@
 
 #include <linux/bits.h>
 #include <linux/stringify.h>
+#include <linux/kasan-tags.h>
 
 #include <asm/gpr-num.h>
 
@@ -123,6 +124,37 @@
 #define SYS_DC_CIGSW			sys_insn(1, 0, 7, 14, 4)
 #define SYS_DC_CIGDSW			sys_insn(1, 0, 7, 14, 6)
 
+#define SYS_IC_IALLUIS			sys_insn(1, 0, 7, 1, 0)
+#define SYS_IC_IALLU			sys_insn(1, 0, 7, 5, 0)
+#define SYS_IC_IVAU			sys_insn(1, 3, 7, 5, 1)
+
+#define SYS_DC_IVAC			sys_insn(1, 0, 7, 6, 1)
+#define SYS_DC_IGVAC			sys_insn(1, 0, 7, 6, 3)
+#define SYS_DC_IGDVAC			sys_insn(1, 0, 7, 6, 5)
+
+#define SYS_DC_CVAC			sys_insn(1, 3, 7, 10, 1)
+#define SYS_DC_CGVAC			sys_insn(1, 3, 7, 10, 3)
+#define SYS_DC_CGDVAC			sys_insn(1, 3, 7, 10, 5)
+
+#define SYS_DC_CVAU			sys_insn(1, 3, 7, 11, 1)
+
+#define SYS_DC_CVAP			sys_insn(1, 3, 7, 12, 1)
+#define SYS_DC_CGVAP			sys_insn(1, 3, 7, 12, 3)
+#define SYS_DC_CGDVAP			sys_insn(1, 3, 7, 12, 5)
+
+#define SYS_DC_CVADP			sys_insn(1, 3, 7, 13, 1)
+#define SYS_DC_CGVADP			sys_insn(1, 3, 7, 13, 3)
+#define SYS_DC_CGDVADP			sys_insn(1, 3, 7, 13, 5)
+
+#define SYS_DC_CIVAC			sys_insn(1, 3, 7, 14, 1)
+#define SYS_DC_CIGVAC			sys_insn(1, 3, 7, 14, 3)
+#define SYS_DC_CIGDVAC			sys_insn(1, 3, 7, 14, 5)
+
+/* Data cache zero operations */
+#define SYS_DC_ZVA			sys_insn(1, 3, 7, 4, 1)
+#define SYS_DC_GVA			sys_insn(1, 3, 7, 4, 3)
+#define SYS_DC_GZVA			sys_insn(1, 3, 7, 4, 4)
+
 /*
  * Automatically generated definitions for system registers, the
  * manual encodings below are in the process of being converted to
@@ -162,6 +194,84 @@
 #define SYS_DBGDTRTX_EL0		sys_reg(2, 3, 0, 5, 0)
 #define SYS_DBGVCR32_EL2		sys_reg(2, 4, 0, 7, 0)
 
+#define SYS_BRBINF_EL1(n)		sys_reg(2, 1, 8, (n & 15), (((n & 16) >> 2) | 0))
+#define SYS_BRBINFINJ_EL1		sys_reg(2, 1, 9, 1, 0)
+#define SYS_BRBSRC_EL1(n)		sys_reg(2, 1, 8, (n & 15), (((n & 16) >> 2) | 1))
+#define SYS_BRBSRCINJ_EL1		sys_reg(2, 1, 9, 1, 1)
+#define SYS_BRBTGT_EL1(n)		sys_reg(2, 1, 8, (n & 15), (((n & 16) >> 2) | 2))
+#define SYS_BRBTGTINJ_EL1		sys_reg(2, 1, 9, 1, 2)
+#define SYS_BRBTS_EL1			sys_reg(2, 1, 9, 0, 2)
+
+#define SYS_BRBCR_EL1			sys_reg(2, 1, 9, 0, 0)
+#define SYS_BRBFCR_EL1			sys_reg(2, 1, 9, 0, 1)
+#define SYS_BRBIDR0_EL1			sys_reg(2, 1, 9, 2, 0)
+
+#define SYS_TRCITECR_EL1		sys_reg(3, 0, 1, 2, 3)
+#define SYS_TRCACATR(m)			sys_reg(2, 1, 2, ((m & 7) << 1), (2 | (m >> 3)))
+#define SYS_TRCACVR(m)			sys_reg(2, 1, 2, ((m & 7) << 1), (0 | (m >> 3)))
+#define SYS_TRCAUTHSTATUS		sys_reg(2, 1, 7, 14, 6)
+#define SYS_TRCAUXCTLR			sys_reg(2, 1, 0, 6, 0)
+#define SYS_TRCBBCTLR			sys_reg(2, 1, 0, 15, 0)
+#define SYS_TRCCCCTLR			sys_reg(2, 1, 0, 14, 0)
+#define SYS_TRCCIDCCTLR0		sys_reg(2, 1, 3, 0, 2)
+#define SYS_TRCCIDCCTLR1		sys_reg(2, 1, 3, 1, 2)
+#define SYS_TRCCIDCVR(m)		sys_reg(2, 1, 3, ((m & 7) << 1), 0)
+#define SYS_TRCCLAIMCLR			sys_reg(2, 1, 7, 9, 6)
+#define SYS_TRCCLAIMSET			sys_reg(2, 1, 7, 8, 6)
+#define SYS_TRCCNTCTLR(m)		sys_reg(2, 1, 0, (4 | (m & 3)), 5)
+#define SYS_TRCCNTRLDVR(m)		sys_reg(2, 1, 0, (0 | (m & 3)), 5)
+#define SYS_TRCCNTVR(m)			sys_reg(2, 1, 0, (8 | (m & 3)), 5)
+#define SYS_TRCCONFIGR			sys_reg(2, 1, 0, 4, 0)
+#define SYS_TRCDEVARCH			sys_reg(2, 1, 7, 15, 6)
+#define SYS_TRCDEVID			sys_reg(2, 1, 7, 2, 7)
+#define SYS_TRCEVENTCTL0R		sys_reg(2, 1, 0, 8, 0)
+#define SYS_TRCEVENTCTL1R		sys_reg(2, 1, 0, 9, 0)
+#define SYS_TRCEXTINSELR(m)		sys_reg(2, 1, 0, (8 | (m & 3)), 4)
+#define SYS_TRCIDR0			sys_reg(2, 1, 0, 8, 7)
+#define SYS_TRCIDR10			sys_reg(2, 1, 0, 2, 6)
+#define SYS_TRCIDR11			sys_reg(2, 1, 0, 3, 6)
+#define SYS_TRCIDR12			sys_reg(2, 1, 0, 4, 6)
+#define SYS_TRCIDR13			sys_reg(2, 1, 0, 5, 6)
+#define SYS_TRCIDR1			sys_reg(2, 1, 0, 9, 7)
+#define SYS_TRCIDR2			sys_reg(2, 1, 0, 10, 7)
+#define SYS_TRCIDR3			sys_reg(2, 1, 0, 11, 7)
+#define SYS_TRCIDR4			sys_reg(2, 1, 0, 12, 7)
+#define SYS_TRCIDR5			sys_reg(2, 1, 0, 13, 7)
+#define SYS_TRCIDR6			sys_reg(2, 1, 0, 14, 7)
+#define SYS_TRCIDR7			sys_reg(2, 1, 0, 15, 7)
+#define SYS_TRCIDR8			sys_reg(2, 1, 0, 0, 6)
+#define SYS_TRCIDR9			sys_reg(2, 1, 0, 1, 6)
+#define SYS_TRCIMSPEC(m)		sys_reg(2, 1, 0, (m & 7), 7)
+#define SYS_TRCITEEDCR			sys_reg(2, 1, 0, 2, 1)
+#define SYS_TRCOSLSR			sys_reg(2, 1, 1, 1, 4)
+#define SYS_TRCPRGCTLR			sys_reg(2, 1, 0, 1, 0)
+#define SYS_TRCQCTLR			sys_reg(2, 1, 0, 1, 1)
+#define SYS_TRCRSCTLR(m)		sys_reg(2, 1, 1, (m & 15), (0 | (m >> 4)))
+#define SYS_TRCRSR			sys_reg(2, 1, 0, 10, 0)
+#define SYS_TRCSEQEVR(m)		sys_reg(2, 1, 0, (m & 3), 4)
+#define SYS_TRCSEQRSTEVR		sys_reg(2, 1, 0, 6, 4)
+#define SYS_TRCSEQSTR			sys_reg(2, 1, 0, 7, 4)
+#define SYS_TRCSSCCR(m)			sys_reg(2, 1, 1, (m & 7), 2)
+#define SYS_TRCSSCSR(m)			sys_reg(2, 1, 1, (8 | (m & 7)), 2)
+#define SYS_TRCSSPCICR(m)		sys_reg(2, 1, 1, (m & 7), 3)
+#define SYS_TRCSTALLCTLR		sys_reg(2, 1, 0, 11, 0)
+#define SYS_TRCSTATR			sys_reg(2, 1, 0, 3, 0)
+#define SYS_TRCSYNCPR			sys_reg(2, 1, 0, 13, 0)
+#define SYS_TRCTRACEIDR			sys_reg(2, 1, 0, 0, 1)
+#define SYS_TRCTSCTLR			sys_reg(2, 1, 0, 12, 0)
+#define SYS_TRCVICTLR			sys_reg(2, 1, 0, 0, 2)
+#define SYS_TRCVIIECTLR			sys_reg(2, 1, 0, 1, 2)
+#define SYS_TRCVIPCSSCTLR		sys_reg(2, 1, 0, 3, 2)
+#define SYS_TRCVISSCTLR			sys_reg(2, 1, 0, 2, 2)
+#define SYS_TRCVMIDCCTLR0		sys_reg(2, 1, 3, 2, 2)
+#define SYS_TRCVMIDCCTLR1		sys_reg(2, 1, 3, 3, 2)
+#define SYS_TRCVMIDCVR(m)		sys_reg(2, 1, 3, ((m & 7) << 1), 1)
+
+/* ETM */
+#define SYS_TRCOSLAR			sys_reg(2, 1, 1, 0, 4)
+
+#define SYS_BRBCR_EL2			sys_reg(2, 4, 9, 0, 0)
+
 #define SYS_MIDR_EL1			sys_reg(3, 0, 0, 0, 0)
 #define SYS_MPIDR_EL1			sys_reg(3, 0, 0, 0, 5)
 #define SYS_REVIDR_EL1			sys_reg(3, 0, 0, 0, 6)
@@ -202,8 +312,13 @@
 #define SYS_ERXCTLR_EL1			sys_reg(3, 0, 5, 4, 1)
 #define SYS_ERXSTATUS_EL1		sys_reg(3, 0, 5, 4, 2)
 #define SYS_ERXADDR_EL1			sys_reg(3, 0, 5, 4, 3)
+#define SYS_ERXPFGF_EL1			sys_reg(3, 0, 5, 4, 4)
+#define SYS_ERXPFGCTL_EL1		sys_reg(3, 0, 5, 4, 5)
+#define SYS_ERXPFGCDN_EL1		sys_reg(3, 0, 5, 4, 6)
 #define SYS_ERXMISC0_EL1		sys_reg(3, 0, 5, 5, 0)
 #define SYS_ERXMISC1_EL1		sys_reg(3, 0, 5, 5, 1)
+#define SYS_ERXMISC2_EL1		sys_reg(3, 0, 5, 5, 2)
+#define SYS_ERXMISC3_EL1		sys_reg(3, 0, 5, 5, 3)
 #define SYS_TFSR_EL1			sys_reg(3, 0, 5, 6, 0)
 #define SYS_TFSRE0_EL1			sys_reg(3, 0, 5, 6, 1)
 
@@ -274,6 +389,8 @@
 #define SYS_ICC_IGRPEN0_EL1		sys_reg(3, 0, 12, 12, 6)
 #define SYS_ICC_IGRPEN1_EL1		sys_reg(3, 0, 12, 12, 7)
 
+#define SYS_ACCDATA_EL1			sys_reg(3, 0, 13, 0, 5)
+
 #define SYS_CNTKCTL_EL1			sys_reg(3, 0, 14, 1, 0)
 
 #define SYS_AIDR_EL1			sys_reg(3, 1, 0, 0, 7)
@@ -369,6 +486,7 @@
 
 #define SYS_SCTLR_EL2			sys_reg(3, 4, 1, 0, 0)
 #define SYS_ACTLR_EL2			sys_reg(3, 4, 1, 0, 1)
+#define SYS_SCTLR2_EL2			sys_reg(3, 4, 1, 0, 3)
 #define SYS_HCR_EL2			sys_reg(3, 4, 1, 1, 0)
 #define SYS_MDCR_EL2			sys_reg(3, 4, 1, 1, 1)
 #define SYS_CPTR_EL2			sys_reg(3, 4, 1, 1, 2)
@@ -382,12 +500,15 @@
 #define SYS_VTCR_EL2			sys_reg(3, 4, 2, 1, 2)
 
 #define SYS_TRFCR_EL2			sys_reg(3, 4, 1, 2, 1)
-#define SYS_HDFGRTR_EL2			sys_reg(3, 4, 3, 1, 4)
-#define SYS_HDFGWTR_EL2			sys_reg(3, 4, 3, 1, 5)
+#define SYS_VNCR_EL2			sys_reg(3, 4, 2, 2, 0)
 #define SYS_HAFGRTR_EL2			sys_reg(3, 4, 3, 1, 6)
 #define SYS_SPSR_EL2			sys_reg(3, 4, 4, 0, 0)
 #define SYS_ELR_EL2			sys_reg(3, 4, 4, 0, 1)
 #define SYS_SP_EL1			sys_reg(3, 4, 4, 1, 0)
+#define SYS_SPSR_irq			sys_reg(3, 4, 4, 3, 0)
+#define SYS_SPSR_abt			sys_reg(3, 4, 4, 3, 1)
+#define SYS_SPSR_und			sys_reg(3, 4, 4, 3, 2)
+#define SYS_SPSR_fiq			sys_reg(3, 4, 4, 3, 3)
 #define SYS_IFSR32_EL2			sys_reg(3, 4, 5, 0, 1)
 #define SYS_AFSR0_EL2			sys_reg(3, 4, 5, 1, 0)
 #define SYS_AFSR1_EL2			sys_reg(3, 4, 5, 1, 1)
@@ -401,6 +522,18 @@
 
 #define SYS_MAIR_EL2			sys_reg(3, 4, 10, 2, 0)
 #define SYS_AMAIR_EL2			sys_reg(3, 4, 10, 3, 0)
+#define SYS_MPAMHCR_EL2			sys_reg(3, 4, 10, 4, 0)
+#define SYS_MPAMVPMV_EL2		sys_reg(3, 4, 10, 4, 1)
+#define SYS_MPAM2_EL2			sys_reg(3, 4, 10, 5, 0)
+#define __SYS__MPAMVPMx_EL2(x)		sys_reg(3, 4, 10, 6, x)
+#define SYS_MPAMVPM0_EL2		__SYS__MPAMVPMx_EL2(0)
+#define SYS_MPAMVPM1_EL2		__SYS__MPAMVPMx_EL2(1)
+#define SYS_MPAMVPM2_EL2		__SYS__MPAMVPMx_EL2(2)
+#define SYS_MPAMVPM3_EL2		__SYS__MPAMVPMx_EL2(3)
+#define SYS_MPAMVPM4_EL2		__SYS__MPAMVPMx_EL2(4)
+#define SYS_MPAMVPM5_EL2		__SYS__MPAMVPMx_EL2(5)
+#define SYS_MPAMVPM6_EL2		__SYS__MPAMVPMx_EL2(6)
+#define SYS_MPAMVPM7_EL2		__SYS__MPAMVPMx_EL2(7)
 
 #define SYS_VBAR_EL2			sys_reg(3, 4, 12, 0, 0)
 #define SYS_RVBAR_EL2			sys_reg(3, 4, 12, 0, 1)
@@ -449,24 +582,49 @@
 
 #define SYS_CONTEXTIDR_EL2		sys_reg(3, 4, 13, 0, 1)
 #define SYS_TPIDR_EL2			sys_reg(3, 4, 13, 0, 2)
+#define SYS_SCXTNUM_EL2			sys_reg(3, 4, 13, 0, 7)
+
+#define __AMEV_op2(m)			(m & 0x7)
+#define __AMEV_CRm(n, m)		(n | ((m & 0x8) >> 3))
+#define __SYS__AMEVCNTVOFF0n_EL2(m)	sys_reg(3, 4, 13, __AMEV_CRm(0x8, m), __AMEV_op2(m))
+#define SYS_AMEVCNTVOFF0n_EL2(m)	__SYS__AMEVCNTVOFF0n_EL2(m)
+#define __SYS__AMEVCNTVOFF1n_EL2(m)	sys_reg(3, 4, 13, __AMEV_CRm(0xA, m), __AMEV_op2(m))
+#define SYS_AMEVCNTVOFF1n_EL2(m)	__SYS__AMEVCNTVOFF1n_EL2(m)
 
 #define SYS_CNTVOFF_EL2			sys_reg(3, 4, 14, 0, 3)
 #define SYS_CNTHCTL_EL2			sys_reg(3, 4, 14, 1, 0)
+#define SYS_CNTHP_TVAL_EL2		sys_reg(3, 4, 14, 2, 0)
+#define SYS_CNTHP_CTL_EL2		sys_reg(3, 4, 14, 2, 1)
+#define SYS_CNTHP_CVAL_EL2		sys_reg(3, 4, 14, 2, 2)
+#define SYS_CNTHV_TVAL_EL2		sys_reg(3, 4, 14, 3, 0)
+#define SYS_CNTHV_CTL_EL2		sys_reg(3, 4, 14, 3, 1)
+#define SYS_CNTHV_CVAL_EL2		sys_reg(3, 4, 14, 3, 2)
 
 /* VHE encodings for architectural EL0/1 system registers */
+#define SYS_BRBCR_EL12			sys_reg(2, 5, 9, 0, 0)
 #define SYS_SCTLR_EL12			sys_reg(3, 5, 1, 0, 0)
+#define SYS_CPACR_EL12			sys_reg(3, 5, 1, 0, 2)
+#define SYS_SCTLR2_EL12			sys_reg(3, 5, 1, 0, 3)
+#define SYS_ZCR_EL12			sys_reg(3, 5, 1, 2, 0)
+#define SYS_TRFCR_EL12			sys_reg(3, 5, 1, 2, 1)
+#define SYS_SMCR_EL12			sys_reg(3, 5, 1, 2, 6)
 #define SYS_TTBR0_EL12			sys_reg(3, 5, 2, 0, 0)
 #define SYS_TTBR1_EL12			sys_reg(3, 5, 2, 0, 1)
 #define SYS_TCR_EL12			sys_reg(3, 5, 2, 0, 2)
+#define SYS_TCR2_EL12			sys_reg(3, 5, 2, 0, 3)
 #define SYS_SPSR_EL12			sys_reg(3, 5, 4, 0, 0)
 #define SYS_ELR_EL12			sys_reg(3, 5, 4, 0, 1)
 #define SYS_AFSR0_EL12			sys_reg(3, 5, 5, 1, 0)
 #define SYS_AFSR1_EL12			sys_reg(3, 5, 5, 1, 1)
 #define SYS_ESR_EL12			sys_reg(3, 5, 5, 2, 0)
 #define SYS_TFSR_EL12			sys_reg(3, 5, 5, 6, 0)
+#define SYS_FAR_EL12			sys_reg(3, 5, 6, 0, 0)
+#define SYS_PMSCR_EL12			sys_reg(3, 5, 9, 9, 0)
 #define SYS_MAIR_EL12			sys_reg(3, 5, 10, 2, 0)
 #define SYS_AMAIR_EL12			sys_reg(3, 5, 10, 3, 0)
 #define SYS_VBAR_EL12			sys_reg(3, 5, 12, 0, 0)
+#define SYS_CONTEXTIDR_EL12		sys_reg(3, 5, 13, 0, 1)
+#define SYS_SCXTNUM_EL12		sys_reg(3, 5, 13, 0, 7)
 #define SYS_CNTKCTL_EL12		sys_reg(3, 5, 14, 1, 0)
 #define SYS_CNTP_TVAL_EL02		sys_reg(3, 5, 14, 2, 0)
 #define SYS_CNTP_CTL_EL02		sys_reg(3, 5, 14, 2, 1)
@@ -477,6 +635,165 @@
 
 #define SYS_SP_EL2			sys_reg(3, 6,  4, 1, 0)
 
+/* AT instructions */
+#define AT_Op0 1
+#define AT_CRn 7
+
+#define OP_AT_S1E1R	sys_insn(AT_Op0, 0, AT_CRn, 8, 0)
+#define OP_AT_S1E1W	sys_insn(AT_Op0, 0, AT_CRn, 8, 1)
+#define OP_AT_S1E0R	sys_insn(AT_Op0, 0, AT_CRn, 8, 2)
+#define OP_AT_S1E0W	sys_insn(AT_Op0, 0, AT_CRn, 8, 3)
+#define OP_AT_S1E1RP	sys_insn(AT_Op0, 0, AT_CRn, 9, 0)
+#define OP_AT_S1E1WP	sys_insn(AT_Op0, 0, AT_CRn, 9, 1)
+#define OP_AT_S1E1A	sys_insn(AT_Op0, 0, AT_CRn, 9, 2)
+#define OP_AT_S1E2R	sys_insn(AT_Op0, 4, AT_CRn, 8, 0)
+#define OP_AT_S1E2W	sys_insn(AT_Op0, 4, AT_CRn, 8, 1)
+#define OP_AT_S12E1R	sys_insn(AT_Op0, 4, AT_CRn, 8, 4)
+#define OP_AT_S12E1W	sys_insn(AT_Op0, 4, AT_CRn, 8, 5)
+#define OP_AT_S12E0R	sys_insn(AT_Op0, 4, AT_CRn, 8, 6)
+#define OP_AT_S12E0W	sys_insn(AT_Op0, 4, AT_CRn, 8, 7)
+
+/* TLBI instructions */
+#define OP_TLBI_VMALLE1OS		sys_insn(1, 0, 8, 1, 0)
+#define OP_TLBI_VAE1OS			sys_insn(1, 0, 8, 1, 1)
+#define OP_TLBI_ASIDE1OS		sys_insn(1, 0, 8, 1, 2)
+#define OP_TLBI_VAAE1OS			sys_insn(1, 0, 8, 1, 3)
+#define OP_TLBI_VALE1OS			sys_insn(1, 0, 8, 1, 5)
+#define OP_TLBI_VAALE1OS		sys_insn(1, 0, 8, 1, 7)
+#define OP_TLBI_RVAE1IS			sys_insn(1, 0, 8, 2, 1)
+#define OP_TLBI_RVAAE1IS		sys_insn(1, 0, 8, 2, 3)
+#define OP_TLBI_RVALE1IS		sys_insn(1, 0, 8, 2, 5)
+#define OP_TLBI_RVAALE1IS		sys_insn(1, 0, 8, 2, 7)
+#define OP_TLBI_VMALLE1IS		sys_insn(1, 0, 8, 3, 0)
+#define OP_TLBI_VAE1IS			sys_insn(1, 0, 8, 3, 1)
+#define OP_TLBI_ASIDE1IS		sys_insn(1, 0, 8, 3, 2)
+#define OP_TLBI_VAAE1IS			sys_insn(1, 0, 8, 3, 3)
+#define OP_TLBI_VALE1IS			sys_insn(1, 0, 8, 3, 5)
+#define OP_TLBI_VAALE1IS		sys_insn(1, 0, 8, 3, 7)
+#define OP_TLBI_RVAE1OS			sys_insn(1, 0, 8, 5, 1)
+#define OP_TLBI_RVAAE1OS		sys_insn(1, 0, 8, 5, 3)
+#define OP_TLBI_RVALE1OS		sys_insn(1, 0, 8, 5, 5)
+#define OP_TLBI_RVAALE1OS		sys_insn(1, 0, 8, 5, 7)
+#define OP_TLBI_RVAE1			sys_insn(1, 0, 8, 6, 1)
+#define OP_TLBI_RVAAE1			sys_insn(1, 0, 8, 6, 3)
+#define OP_TLBI_RVALE1			sys_insn(1, 0, 8, 6, 5)
+#define OP_TLBI_RVAALE1			sys_insn(1, 0, 8, 6, 7)
+#define OP_TLBI_VMALLE1			sys_insn(1, 0, 8, 7, 0)
+#define OP_TLBI_VAE1			sys_insn(1, 0, 8, 7, 1)
+#define OP_TLBI_ASIDE1			sys_insn(1, 0, 8, 7, 2)
+#define OP_TLBI_VAAE1			sys_insn(1, 0, 8, 7, 3)
+#define OP_TLBI_VALE1			sys_insn(1, 0, 8, 7, 5)
+#define OP_TLBI_VAALE1			sys_insn(1, 0, 8, 7, 7)
+#define OP_TLBI_VMALLE1OSNXS		sys_insn(1, 0, 9, 1, 0)
+#define OP_TLBI_VAE1OSNXS		sys_insn(1, 0, 9, 1, 1)
+#define OP_TLBI_ASIDE1OSNXS		sys_insn(1, 0, 9, 1, 2)
+#define OP_TLBI_VAAE1OSNXS		sys_insn(1, 0, 9, 1, 3)
+#define OP_TLBI_VALE1OSNXS		sys_insn(1, 0, 9, 1, 5)
+#define OP_TLBI_VAALE1OSNXS		sys_insn(1, 0, 9, 1, 7)
+#define OP_TLBI_RVAE1ISNXS		sys_insn(1, 0, 9, 2, 1)
+#define OP_TLBI_RVAAE1ISNXS		sys_insn(1, 0, 9, 2, 3)
+#define OP_TLBI_RVALE1ISNXS		sys_insn(1, 0, 9, 2, 5)
+#define OP_TLBI_RVAALE1ISNXS		sys_insn(1, 0, 9, 2, 7)
+#define OP_TLBI_VMALLE1ISNXS		sys_insn(1, 0, 9, 3, 0)
+#define OP_TLBI_VAE1ISNXS		sys_insn(1, 0, 9, 3, 1)
+#define OP_TLBI_ASIDE1ISNXS		sys_insn(1, 0, 9, 3, 2)
+#define OP_TLBI_VAAE1ISNXS		sys_insn(1, 0, 9, 3, 3)
+#define OP_TLBI_VALE1ISNXS		sys_insn(1, 0, 9, 3, 5)
+#define OP_TLBI_VAALE1ISNXS		sys_insn(1, 0, 9, 3, 7)
+#define OP_TLBI_RVAE1OSNXS		sys_insn(1, 0, 9, 5, 1)
+#define OP_TLBI_RVAAE1OSNXS		sys_insn(1, 0, 9, 5, 3)
+#define OP_TLBI_RVALE1OSNXS		sys_insn(1, 0, 9, 5, 5)
+#define OP_TLBI_RVAALE1OSNXS		sys_insn(1, 0, 9, 5, 7)
+#define OP_TLBI_RVAE1NXS		sys_insn(1, 0, 9, 6, 1)
+#define OP_TLBI_RVAAE1NXS		sys_insn(1, 0, 9, 6, 3)
+#define OP_TLBI_RVALE1NXS		sys_insn(1, 0, 9, 6, 5)
+#define OP_TLBI_RVAALE1NXS		sys_insn(1, 0, 9, 6, 7)
+#define OP_TLBI_VMALLE1NXS		sys_insn(1, 0, 9, 7, 0)
+#define OP_TLBI_VAE1NXS			sys_insn(1, 0, 9, 7, 1)
+#define OP_TLBI_ASIDE1NXS		sys_insn(1, 0, 9, 7, 2)
+#define OP_TLBI_VAAE1NXS		sys_insn(1, 0, 9, 7, 3)
+#define OP_TLBI_VALE1NXS		sys_insn(1, 0, 9, 7, 5)
+#define OP_TLBI_VAALE1NXS		sys_insn(1, 0, 9, 7, 7)
+#define OP_TLBI_IPAS2E1IS		sys_insn(1, 4, 8, 0, 1)
+#define OP_TLBI_RIPAS2E1IS		sys_insn(1, 4, 8, 0, 2)
+#define OP_TLBI_IPAS2LE1IS		sys_insn(1, 4, 8, 0, 5)
+#define OP_TLBI_RIPAS2LE1IS		sys_insn(1, 4, 8, 0, 6)
+#define OP_TLBI_ALLE2OS			sys_insn(1, 4, 8, 1, 0)
+#define OP_TLBI_VAE2OS			sys_insn(1, 4, 8, 1, 1)
+#define OP_TLBI_ALLE1OS			sys_insn(1, 4, 8, 1, 4)
+#define OP_TLBI_VALE2OS			sys_insn(1, 4, 8, 1, 5)
+#define OP_TLBI_VMALLS12E1OS		sys_insn(1, 4, 8, 1, 6)
+#define OP_TLBI_RVAE2IS			sys_insn(1, 4, 8, 2, 1)
+#define OP_TLBI_RVALE2IS		sys_insn(1, 4, 8, 2, 5)
+#define OP_TLBI_ALLE2IS			sys_insn(1, 4, 8, 3, 0)
+#define OP_TLBI_VAE2IS			sys_insn(1, 4, 8, 3, 1)
+#define OP_TLBI_ALLE1IS			sys_insn(1, 4, 8, 3, 4)
+#define OP_TLBI_VALE2IS			sys_insn(1, 4, 8, 3, 5)
+#define OP_TLBI_VMALLS12E1IS		sys_insn(1, 4, 8, 3, 6)
+#define OP_TLBI_IPAS2E1OS		sys_insn(1, 4, 8, 4, 0)
+#define OP_TLBI_IPAS2E1			sys_insn(1, 4, 8, 4, 1)
+#define OP_TLBI_RIPAS2E1		sys_insn(1, 4, 8, 4, 2)
+#define OP_TLBI_RIPAS2E1OS		sys_insn(1, 4, 8, 4, 3)
+#define OP_TLBI_IPAS2LE1OS		sys_insn(1, 4, 8, 4, 4)
+#define OP_TLBI_IPAS2LE1		sys_insn(1, 4, 8, 4, 5)
+#define OP_TLBI_RIPAS2LE1		sys_insn(1, 4, 8, 4, 6)
+#define OP_TLBI_RIPAS2LE1OS		sys_insn(1, 4, 8, 4, 7)
+#define OP_TLBI_RVAE2OS			sys_insn(1, 4, 8, 5, 1)
+#define OP_TLBI_RVALE2OS		sys_insn(1, 4, 8, 5, 5)
+#define OP_TLBI_RVAE2			sys_insn(1, 4, 8, 6, 1)
+#define OP_TLBI_RVALE2			sys_insn(1, 4, 8, 6, 5)
+#define OP_TLBI_ALLE2			sys_insn(1, 4, 8, 7, 0)
+#define OP_TLBI_VAE2			sys_insn(1, 4, 8, 7, 1)
+#define OP_TLBI_ALLE1			sys_insn(1, 4, 8, 7, 4)
+#define OP_TLBI_VALE2			sys_insn(1, 4, 8, 7, 5)
+#define OP_TLBI_VMALLS12E1		sys_insn(1, 4, 8, 7, 6)
+#define OP_TLBI_IPAS2E1ISNXS		sys_insn(1, 4, 9, 0, 1)
+#define OP_TLBI_RIPAS2E1ISNXS		sys_insn(1, 4, 9, 0, 2)
+#define OP_TLBI_IPAS2LE1ISNXS		sys_insn(1, 4, 9, 0, 5)
+#define OP_TLBI_RIPAS2LE1ISNXS		sys_insn(1, 4, 9, 0, 6)
+#define OP_TLBI_ALLE2OSNXS		sys_insn(1, 4, 9, 1, 0)
+#define OP_TLBI_VAE2OSNXS		sys_insn(1, 4, 9, 1, 1)
+#define OP_TLBI_ALLE1OSNXS		sys_insn(1, 4, 9, 1, 4)
+#define OP_TLBI_VALE2OSNXS		sys_insn(1, 4, 9, 1, 5)
+#define OP_TLBI_VMALLS12E1OSNXS		sys_insn(1, 4, 9, 1, 6)
+#define OP_TLBI_RVAE2ISNXS		sys_insn(1, 4, 9, 2, 1)
+#define OP_TLBI_RVALE2ISNXS		sys_insn(1, 4, 9, 2, 5)
+#define OP_TLBI_ALLE2ISNXS		sys_insn(1, 4, 9, 3, 0)
+#define OP_TLBI_VAE2ISNXS		sys_insn(1, 4, 9, 3, 1)
+#define OP_TLBI_ALLE1ISNXS		sys_insn(1, 4, 9, 3, 4)
+#define OP_TLBI_VALE2ISNXS		sys_insn(1, 4, 9, 3, 5)
+#define OP_TLBI_VMALLS12E1ISNXS		sys_insn(1, 4, 9, 3, 6)
+#define OP_TLBI_IPAS2E1OSNXS		sys_insn(1, 4, 9, 4, 0)
+#define OP_TLBI_IPAS2E1NXS		sys_insn(1, 4, 9, 4, 1)
+#define OP_TLBI_RIPAS2E1NXS		sys_insn(1, 4, 9, 4, 2)
+#define OP_TLBI_RIPAS2E1OSNXS		sys_insn(1, 4, 9, 4, 3)
+#define OP_TLBI_IPAS2LE1OSNXS		sys_insn(1, 4, 9, 4, 4)
+#define OP_TLBI_IPAS2LE1NXS		sys_insn(1, 4, 9, 4, 5)
+#define OP_TLBI_RIPAS2LE1NXS		sys_insn(1, 4, 9, 4, 6)
+#define OP_TLBI_RIPAS2LE1OSNXS		sys_insn(1, 4, 9, 4, 7)
+#define OP_TLBI_RVAE2OSNXS		sys_insn(1, 4, 9, 5, 1)
+#define OP_TLBI_RVALE2OSNXS		sys_insn(1, 4, 9, 5, 5)
+#define OP_TLBI_RVAE2NXS		sys_insn(1, 4, 9, 6, 1)
+#define OP_TLBI_RVALE2NXS		sys_insn(1, 4, 9, 6, 5)
+#define OP_TLBI_ALLE2NXS		sys_insn(1, 4, 9, 7, 0)
+#define OP_TLBI_VAE2NXS			sys_insn(1, 4, 9, 7, 1)
+#define OP_TLBI_ALLE1NXS		sys_insn(1, 4, 9, 7, 4)
+#define OP_TLBI_VALE2NXS		sys_insn(1, 4, 9, 7, 5)
+#define OP_TLBI_VMALLS12E1NXS		sys_insn(1, 4, 9, 7, 6)
+
+/* Misc instructions */
+#define OP_GCSPUSHX			sys_insn(1, 0, 7, 7, 4)
+#define OP_GCSPOPCX			sys_insn(1, 0, 7, 7, 5)
+#define OP_GCSPOPX			sys_insn(1, 0, 7, 7, 6)
+#define OP_GCSPUSHM			sys_insn(1, 3, 7, 7, 0)
+
+#define OP_BRB_IALL			sys_insn(1, 1, 7, 2, 4)
+#define OP_BRB_INJ			sys_insn(1, 1, 7, 2, 5)
+#define OP_CFP_RCTX			sys_insn(1, 3, 7, 3, 4)
+#define OP_DVP_RCTX			sys_insn(1, 3, 7, 3, 5)
+#define OP_COSP_RCTX			sys_insn(1, 3, 7, 3, 6)
+#define OP_CPP_RCTX			sys_insn(1, 3, 7, 3, 7)
+
 /* Common SCTLR_ELx flags. */
 #define SCTLR_ELx_ENTP2	(BIT(60))
 #define SCTLR_ELx_DSSBS	(BIT(44))
@@ -561,10 +878,12 @@
 
 /* id_aa64mmfr0 */
 #define ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED_MIN	0x0
+#define ID_AA64MMFR0_EL1_TGRAN4_LPA2		ID_AA64MMFR0_EL1_TGRAN4_52_BIT
 #define ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED_MAX	0x7
 #define ID_AA64MMFR0_EL1_TGRAN64_SUPPORTED_MIN	0x0
 #define ID_AA64MMFR0_EL1_TGRAN64_SUPPORTED_MAX	0x7
 #define ID_AA64MMFR0_EL1_TGRAN16_SUPPORTED_MIN	0x1
+#define ID_AA64MMFR0_EL1_TGRAN16_LPA2		ID_AA64MMFR0_EL1_TGRAN16_52_BIT
 #define ID_AA64MMFR0_EL1_TGRAN16_SUPPORTED_MAX	0xf
 
 #define ARM64_MIN_PARANGE_BITS		32
@@ -572,6 +891,7 @@
 #define ID_AA64MMFR0_EL1_TGRAN_2_SUPPORTED_DEFAULT	0x0
 #define ID_AA64MMFR0_EL1_TGRAN_2_SUPPORTED_NONE		0x1
 #define ID_AA64MMFR0_EL1_TGRAN_2_SUPPORTED_MIN		0x2
+#define ID_AA64MMFR0_EL1_TGRAN_2_SUPPORTED_LPA2		0x3
 #define ID_AA64MMFR0_EL1_TGRAN_2_SUPPORTED_MAX		0x7
 
 #ifdef CONFIG_ARM64_PA_BITS_52
@@ -582,11 +902,13 @@
 
 #if defined(CONFIG_ARM64_4K_PAGES)
 #define ID_AA64MMFR0_EL1_TGRAN_SHIFT		ID_AA64MMFR0_EL1_TGRAN4_SHIFT
+#define ID_AA64MMFR0_EL1_TGRAN_LPA2		ID_AA64MMFR0_EL1_TGRAN4_52_BIT
 #define ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MIN	ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED_MIN
 #define ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MAX	ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED_MAX
 #define ID_AA64MMFR0_EL1_TGRAN_2_SHIFT		ID_AA64MMFR0_EL1_TGRAN4_2_SHIFT
 #elif defined(CONFIG_ARM64_16K_PAGES)
 #define ID_AA64MMFR0_EL1_TGRAN_SHIFT		ID_AA64MMFR0_EL1_TGRAN16_SHIFT
+#define ID_AA64MMFR0_EL1_TGRAN_LPA2		ID_AA64MMFR0_EL1_TGRAN16_52_BIT
 #define ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MIN	ID_AA64MMFR0_EL1_TGRAN16_SUPPORTED_MIN
 #define ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MAX	ID_AA64MMFR0_EL1_TGRAN16_SUPPORTED_MAX
 #define ID_AA64MMFR0_EL1_TGRAN_2_SHIFT		ID_AA64MMFR0_EL1_TGRAN16_2_SHIFT
@@ -610,6 +932,19 @@
 #define SYS_GCR_EL1_RRND	(BIT(16))
 #define SYS_GCR_EL1_EXCL_MASK	0xffffUL
 
+#ifdef CONFIG_KASAN_HW_TAGS
+/*
+ * KASAN always uses a whole byte for its tags. With CONFIG_KASAN_HW_TAGS it
+ * only uses tags in the range 0xF0-0xFF, which we map to MTE tags 0x0-0xF.
+ */
+#define __MTE_TAG_MIN		(KASAN_TAG_MIN & 0xf)
+#define __MTE_TAG_MAX		(KASAN_TAG_MAX & 0xf)
+#define __MTE_TAG_INCL		GENMASK(__MTE_TAG_MAX, __MTE_TAG_MIN)
+#define KERNEL_GCR_EL1_EXCL	(SYS_GCR_EL1_EXCL_MASK & ~__MTE_TAG_INCL)
+#else
+#define KERNEL_GCR_EL1_EXCL	SYS_GCR_EL1_EXCL_MASK
+#endif
+
 #define KERNEL_GCR_EL1		(SYS_GCR_EL1_RRND | KERNEL_GCR_EL1_EXCL)
 
 /* RGSR_EL1 Definitions */
@@ -716,6 +1051,19 @@
 
 #define PIRx_ELx_PERM(idx, perm)	((perm) << ((idx) * 4))
 
+/*
+ * Permission Overlay Extension (POE) permission encodings.
+ */
+#define POE_NONE	UL(0x0)
+#define POE_R		UL(0x1)
+#define POE_X		UL(0x2)
+#define POE_RX		UL(0x3)
+#define POE_W		UL(0x4)
+#define POE_RW		UL(0x5)
+#define POE_XW		UL(0x6)
+#define POE_RXW		UL(0x7)
+#define POE_MASK	UL(0xf)
+
 #define ARM64_FEATURE_FIELD_BITS	4
 
 /* Defined for compatibility only, do not add new users. */
@@ -789,15 +1137,21 @@
 /*
  * For registers without architectural names, or simply unsupported by
  * GAS.
+ *
+ * __check_r forces warnings to be generated by the compiler when
+ * evaluating r which wouldn't normally happen due to being passed to
+ * the assembler via __stringify(r).
  */
 #define read_sysreg_s(r) ({						\
 	u64 __val;							\
+	u32 __maybe_unused __check_r = (u32)(r);			\
 	asm volatile(__mrs_s("%0", r) : "=r" (__val));			\
 	__val;								\
 })
 
 #define write_sysreg_s(v, r) do {					\
 	u64 __val = (u64)(v);						\
+	u32 __maybe_unused __check_r = (u32)(r);			\
 	asm volatile(__msr_s(r, "%x0") : : "rZ" (__val));		\
 } while (0)
 
@@ -827,6 +1181,8 @@
 	par;								\
 })
 
+#define SYS_FIELD_VALUE(reg, field, val)	reg##_##field##_##val
+
 #define SYS_FIELD_GET(reg, field, val)		\
 		 FIELD_GET(reg##_##field##_MASK, val)
 
@@ -834,7 +1190,8 @@
 		 FIELD_PREP(reg##_##field##_MASK, val)
 
 #define SYS_FIELD_PREP_ENUM(reg, field, val)		\
-		 FIELD_PREP(reg##_##field##_MASK, reg##_##field##_##val)
+		 FIELD_PREP(reg##_##field##_MASK,	\
+			    SYS_FIELD_VALUE(reg, field, val))
 
 #endif
 
diff --git a/tools/include/linux/kasan-tags.h b/tools/include/linux/kasan-tags.h
new file mode 100644
index 000000000000..4f85f562512c
--- /dev/null
+++ b/tools/include/linux/kasan-tags.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_KASAN_TAGS_H
+#define _LINUX_KASAN_TAGS_H
+
+#define KASAN_TAG_KERNEL	0xFF /* native kernel pointers tag */
+#define KASAN_TAG_INVALID	0xFE /* inaccessible memory tag */
+#define KASAN_TAG_MAX		0xFD /* maximum value for random tags */
+
+#ifdef CONFIG_KASAN_HW_TAGS
+#define KASAN_TAG_MIN		0xF0 /* minimum value for random tags */
+#else
+#define KASAN_TAG_MIN		0x00 /* minimum value for random tags */
+#endif
+
+#endif /* LINUX_KASAN_TAGS_H */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v5 3/7] arm64/sysreg/tools: Move TRFCR definitions to sysreg
  2024-02-20 10:09 [PATCH v5 0/7] kvm/coresight: Support exclude guest and exclude host James Clark
  2024-02-20 10:09 ` [PATCH v5 1/7] arm64: KVM: Fix renamed function in comment James Clark
  2024-02-20 10:09 ` [PATCH v5 2/7] arm64/sysreg/tools: Update tools copy of sysreg.h James Clark
@ 2024-02-20 10:09 ` James Clark
  2024-02-20 16:11   ` Mark Brown
  2024-02-20 10:09 ` [PATCH v5 4/7] arm64: KVM: Add iflag for FEAT_TRF James Clark
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 18+ messages in thread
From: James Clark @ 2024-02-20 10:09 UTC (permalink / raw)
  To: coresight, linux-arm-kernel, kvmarm, maz, suzuki.poulose, acme,
	oliver.upton, broonie
  Cc: James Clark, James Morse, Zenghui Yu, Catalin Marinas,
	Will Deacon, Mike Leach, Alexander Shishkin, Anshuman Khandual,
	Miguel Luis, Joey Gouly, Ard Biesheuvel, Greg Kroah-Hartman,
	Arnd Bergmann, Mark Rutland, Kalesh Singh, Vincent Donnefort,
	Ryan Roberts, Fuad Tabba, Jing Zhang, linux-kernel

Add separate definitions for ELx and EL2 as TRFCR_EL1 doesn't have CX.
This also mirrors the previous definition so no code change is required.

Also add TRFCR_EL12 which will start to be used in a later commit.

Unfortunately, to avoid breaking the Perf build with duplicate
definition errors, the tools copy of the sysreg.h header needs to be
updated at the same time rather than the usual second commit. This is
because the generated version of sysreg
(arch/arm64/include/generated/asm/sysreg-defs.h), is currently shared
and tools/ does not have its own copy.

Signed-off-by: James Clark <james.clark@arm.com>
---
 arch/arm64/include/asm/sysreg.h       | 12 --------
 arch/arm64/tools/sysreg               | 41 +++++++++++++++++++++++++++
 tools/arch/arm64/include/asm/sysreg.h | 12 --------
 3 files changed, 41 insertions(+), 24 deletions(-)

diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 9e8999592f3a..35890cf3c49f 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -280,8 +280,6 @@
 #define SYS_RGSR_EL1			sys_reg(3, 0, 1, 0, 5)
 #define SYS_GCR_EL1			sys_reg(3, 0, 1, 0, 6)
 
-#define SYS_TRFCR_EL1			sys_reg(3, 0, 1, 2, 1)
-
 #define SYS_TCR_EL1			sys_reg(3, 0, 2, 0, 2)
 
 #define SYS_APIAKEYLO_EL1		sys_reg(3, 0, 2, 1, 0)
@@ -499,7 +497,6 @@
 #define SYS_VTTBR_EL2			sys_reg(3, 4, 2, 1, 0)
 #define SYS_VTCR_EL2			sys_reg(3, 4, 2, 1, 2)
 
-#define SYS_TRFCR_EL2			sys_reg(3, 4, 1, 2, 1)
 #define SYS_VNCR_EL2			sys_reg(3, 4, 2, 2, 0)
 #define SYS_HAFGRTR_EL2			sys_reg(3, 4, 3, 1, 6)
 #define SYS_SPSR_EL2			sys_reg(3, 4, 4, 0, 0)
@@ -961,15 +958,6 @@
 /* Safe value for MPIDR_EL1: Bit31:RES1, Bit30:U:0, Bit24:MT:0 */
 #define SYS_MPIDR_SAFE_VAL	(BIT(31))
 
-#define TRFCR_ELx_TS_SHIFT		5
-#define TRFCR_ELx_TS_MASK		((0x3UL) << TRFCR_ELx_TS_SHIFT)
-#define TRFCR_ELx_TS_VIRTUAL		((0x1UL) << TRFCR_ELx_TS_SHIFT)
-#define TRFCR_ELx_TS_GUEST_PHYSICAL	((0x2UL) << TRFCR_ELx_TS_SHIFT)
-#define TRFCR_ELx_TS_PHYSICAL		((0x3UL) << TRFCR_ELx_TS_SHIFT)
-#define TRFCR_EL2_CX			BIT(3)
-#define TRFCR_ELx_ExTRE			BIT(1)
-#define TRFCR_ELx_E0TRE			BIT(0)
-
 /* GIC Hypervisor interface registers */
 /* ICH_MISR_EL2 bit definitions */
 #define ICH_MISR_EOI		(1 << 0)
diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg
index fa3fe0856880..c4a6b77d2756 100644
--- a/arch/arm64/tools/sysreg
+++ b/arch/arm64/tools/sysreg
@@ -2970,3 +2970,44 @@ Field	5	F
 Field	4	P
 Field	3:0	Align
 EndSysreg
+
+SysregFields TRFCR_EL2
+Res0	63:7
+UnsignedEnum	6:5	TS
+	0b0000	USE_TRFCR_EL1_TS
+	0b0001	VIRTUAL
+	0b0010	GUEST_PHYSICAL
+	0b0011	PHYSICAL
+EndEnum
+Res0	4
+Field	3	CX
+Res0	2
+Field	1	E2TRE
+Field	0	E0HTRE
+EndSysregFields
+
+# TRFCR_EL1 doesn't have the CX bit so redefine it without CX instead of
+# using a shared definition between TRFCR_EL2 and TRFCR_EL1
+SysregFields TRFCR_ELx
+Res0	63:7
+UnsignedEnum	6:5	TS
+	0b0001	VIRTUAL
+	0b0010	GUEST_PHYSICAL
+	0b0011	PHYSICAL
+EndEnum
+Res0	4:2
+Field	1	ExTRE
+Field	0	E0TRE
+EndSysregFields
+
+Sysreg	TRFCR_EL1	3	0	1	2	1
+Fields	TRFCR_ELx
+EndSysreg
+
+Sysreg	TRFCR_EL2	3	4	1	2	1
+Fields	TRFCR_EL2
+EndSysreg
+
+Sysreg	TRFCR_EL12	3	5	1	2	1
+Fields	TRFCR_ELx
+EndSysreg
diff --git a/tools/arch/arm64/include/asm/sysreg.h b/tools/arch/arm64/include/asm/sysreg.h
index 9e8999592f3a..35890cf3c49f 100644
--- a/tools/arch/arm64/include/asm/sysreg.h
+++ b/tools/arch/arm64/include/asm/sysreg.h
@@ -280,8 +280,6 @@
 #define SYS_RGSR_EL1			sys_reg(3, 0, 1, 0, 5)
 #define SYS_GCR_EL1			sys_reg(3, 0, 1, 0, 6)
 
-#define SYS_TRFCR_EL1			sys_reg(3, 0, 1, 2, 1)
-
 #define SYS_TCR_EL1			sys_reg(3, 0, 2, 0, 2)
 
 #define SYS_APIAKEYLO_EL1		sys_reg(3, 0, 2, 1, 0)
@@ -499,7 +497,6 @@
 #define SYS_VTTBR_EL2			sys_reg(3, 4, 2, 1, 0)
 #define SYS_VTCR_EL2			sys_reg(3, 4, 2, 1, 2)
 
-#define SYS_TRFCR_EL2			sys_reg(3, 4, 1, 2, 1)
 #define SYS_VNCR_EL2			sys_reg(3, 4, 2, 2, 0)
 #define SYS_HAFGRTR_EL2			sys_reg(3, 4, 3, 1, 6)
 #define SYS_SPSR_EL2			sys_reg(3, 4, 4, 0, 0)
@@ -961,15 +958,6 @@
 /* Safe value for MPIDR_EL1: Bit31:RES1, Bit30:U:0, Bit24:MT:0 */
 #define SYS_MPIDR_SAFE_VAL	(BIT(31))
 
-#define TRFCR_ELx_TS_SHIFT		5
-#define TRFCR_ELx_TS_MASK		((0x3UL) << TRFCR_ELx_TS_SHIFT)
-#define TRFCR_ELx_TS_VIRTUAL		((0x1UL) << TRFCR_ELx_TS_SHIFT)
-#define TRFCR_ELx_TS_GUEST_PHYSICAL	((0x2UL) << TRFCR_ELx_TS_SHIFT)
-#define TRFCR_ELx_TS_PHYSICAL		((0x3UL) << TRFCR_ELx_TS_SHIFT)
-#define TRFCR_EL2_CX			BIT(3)
-#define TRFCR_ELx_ExTRE			BIT(1)
-#define TRFCR_ELx_E0TRE			BIT(0)
-
 /* GIC Hypervisor interface registers */
 /* ICH_MISR_EL2 bit definitions */
 #define ICH_MISR_EOI		(1 << 0)
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v5 4/7] arm64: KVM: Add iflag for FEAT_TRF
  2024-02-20 10:09 [PATCH v5 0/7] kvm/coresight: Support exclude guest and exclude host James Clark
                   ` (2 preceding siblings ...)
  2024-02-20 10:09 ` [PATCH v5 3/7] arm64/sysreg/tools: Move TRFCR definitions to sysreg James Clark
@ 2024-02-20 10:09 ` James Clark
  2024-02-20 10:09 ` [PATCH v5 5/7] arm64: KVM: Add interface to set guest value for TRFCR register James Clark
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 18+ messages in thread
From: James Clark @ 2024-02-20 10:09 UTC (permalink / raw)
  To: coresight, linux-arm-kernel, kvmarm, maz, suzuki.poulose, acme,
	oliver.upton, broonie
  Cc: James Clark, James Morse, Zenghui Yu, Catalin Marinas,
	Will Deacon, Mike Leach, Alexander Shishkin, Anshuman Khandual,
	Miguel Luis, Joey Gouly, Ard Biesheuvel, Mark Rutland,
	Greg Kroah-Hartman, Arnd Bergmann, Javier Martinez Canillas,
	Vincent Donnefort, Ryan Roberts, Fuad Tabba, Jing Zhang,
	linux-kernel

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(-)

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);
 }
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v5 5/7] arm64: KVM: Add interface to set guest value for TRFCR register
  2024-02-20 10:09 [PATCH v5 0/7] kvm/coresight: Support exclude guest and exclude host James Clark
                   ` (3 preceding siblings ...)
  2024-02-20 10:09 ` [PATCH v5 4/7] arm64: KVM: Add iflag for FEAT_TRF James Clark
@ 2024-02-20 10:09 ` James Clark
  2024-02-23 10:03   ` Suzuki K Poulose
  2024-02-20 10:09 ` [PATCH v5 6/7] arm64: KVM: Write TRFCR value on guest switch with nVHE James Clark
  2024-02-20 10:09 ` [PATCH v5 7/7] coresight: Pass guest TRFCR value to KVM James Clark
  6 siblings, 1 reply; 18+ messages in thread
From: James Clark @ 2024-02-20 10:09 UTC (permalink / raw)
  To: coresight, linux-arm-kernel, kvmarm, maz, suzuki.poulose, acme,
	oliver.upton, broonie
  Cc: James Clark, James Morse, Zenghui Yu, Catalin Marinas,
	Will Deacon, Mike Leach, Alexander Shishkin, Anshuman Khandual,
	Miguel Luis, Joey Gouly, Ard Biesheuvel, Greg Kroah-Hartman,
	Arnd Bergmann, Helge Deller, Andrew Walbran, Vincent Donnefort,
	Ryan Roberts, Fuad Tabba, Jing Zhang, linux-kernel

Add an interface for the Coresight driver to use to set the value of the
TRFCR register for the guest. This register controls the exclude
settings for trace at different exception levels, and is used to honor
the exclude_host and exclude_guest parameters from the Perf session.
This will be used to later write TRFCR_EL1 on nVHE at guest switch. For
VHE, the host trace is controlled by TRFCR_EL2 and thus we can write to
the TRFCR_EL1 immediately. Because guest writes to the register are
trapped, the value will persist and can't be modified.

Instead of adding a load of infrastructure to share the host's per-cpu
offsets with the hypervisor, just define the new storage as a NR_CPUS
array.

Signed-off-by: James Clark <james.clark@arm.com>
---
 arch/arm64/include/asm/kvm_host.h |  3 +++
 arch/arm64/kernel/image-vars.h    |  1 +
 arch/arm64/kvm/debug.c            | 26 ++++++++++++++++++++++++++
 3 files changed, 30 insertions(+)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 85b5477bd1b4..56b7f7eca195 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -509,6 +509,7 @@ struct kvm_host_psci_config {
 	bool psci_0_1_cpu_off_implemented;
 	bool psci_0_1_migrate_implemented;
 };
+extern u64 ____cacheline_aligned kvm_guest_trfcr[NR_CPUS];
 
 extern struct kvm_host_psci_config kvm_nvhe_sym(kvm_host_psci_config);
 #define kvm_host_psci_config CHOOSE_NVHE_SYM(kvm_host_psci_config)
@@ -1174,6 +1175,7 @@ void kvm_arch_vcpu_put_debug_state_flags(struct kvm_vcpu *vcpu);
 void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr);
 void kvm_clr_pmu_events(u32 clr);
 bool kvm_set_pmuserenr(u64 val);
+void kvm_etm_set_guest_trfcr(u64 trfcr_guest);
 #else
 static inline void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr) {}
 static inline void kvm_clr_pmu_events(u32 clr) {}
@@ -1181,6 +1183,7 @@ static inline bool kvm_set_pmuserenr(u64 val)
 {
 	return false;
 }
+static inline void kvm_etm_set_guest_trfcr(u64 trfcr_guest) {}
 #endif
 
 void kvm_vcpu_load_vhe(struct kvm_vcpu *vcpu);
diff --git a/arch/arm64/kernel/image-vars.h b/arch/arm64/kernel/image-vars.h
index 5e4dc72ab1bd..a451e4f10804 100644
--- a/arch/arm64/kernel/image-vars.h
+++ b/arch/arm64/kernel/image-vars.h
@@ -59,6 +59,7 @@ KVM_NVHE_ALIAS(alt_cb_patch_nops);
 
 /* Global kernel state accessed by nVHE hyp code. */
 KVM_NVHE_ALIAS(kvm_vgic_global_state);
+KVM_NVHE_ALIAS(kvm_guest_trfcr);
 
 /* Kernel symbols used to call panic() from nVHE hyp code (via ERET). */
 KVM_NVHE_ALIAS(nvhe_hyp_panic_handler);
diff --git a/arch/arm64/kvm/debug.c b/arch/arm64/kvm/debug.c
index 49a13e72ddd2..c8d936ce6e2b 100644
--- a/arch/arm64/kvm/debug.c
+++ b/arch/arm64/kvm/debug.c
@@ -22,6 +22,7 @@
 				DBG_MDSCR_MDE)
 
 static DEFINE_PER_CPU(u64, mdcr_el2);
+u64 ____cacheline_aligned kvm_guest_trfcr[NR_CPUS];
 
 /*
  * save/restore_guest_debug_regs
@@ -359,3 +360,28 @@ void kvm_arch_vcpu_put_debug_state_flags(struct kvm_vcpu *vcpu)
 	vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE_TRBE);
 	vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE_TRFCR);
 }
+
+/*
+ * Interface for the Coresight driver to use to set the value of the TRFCR
+ * register for the guest. This register controls the exclude settings for trace
+ * at different exception levels, and is used to honor the exclude_host and
+ * exclude_guest parameters from the Perf session.
+ *
+ * This will be used to later write TRFCR_EL1 on nVHE at guest switch. For VHE,
+ * the host trace is controlled by TRFCR_EL2 and thus we can write to the
+ * TRFCR_EL1 immediately. Because guest writes to the register are trapped, the
+ * value will persist and can't be modified. For pKVM, kvm_guest_trfcr can't
+ * be read by the hypervisor, so don't bother writing it.
+ */
+void kvm_etm_set_guest_trfcr(u64 trfcr_guest)
+{
+	if (WARN_ON_ONCE(!cpuid_feature_extract_unsigned_field(read_sysreg(id_aa64dfr0_el1),
+							       ID_AA64DFR0_EL1_TraceFilt_SHIFT)))
+		return;
+
+	if (has_vhe())
+		write_sysreg_s(trfcr_guest, SYS_TRFCR_EL12);
+	else if (!is_protected_kvm_enabled())
+		kvm_guest_trfcr[smp_processor_id()] = trfcr_guest;
+}
+EXPORT_SYMBOL_GPL(kvm_etm_set_guest_trfcr);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v5 6/7] arm64: KVM: Write TRFCR value on guest switch with nVHE
  2024-02-20 10:09 [PATCH v5 0/7] kvm/coresight: Support exclude guest and exclude host James Clark
                   ` (4 preceding siblings ...)
  2024-02-20 10:09 ` [PATCH v5 5/7] arm64: KVM: Add interface to set guest value for TRFCR register James Clark
@ 2024-02-20 10:09 ` James Clark
  2024-02-26 10:14   ` Suzuki K Poulose
  2024-02-20 10:09 ` [PATCH v5 7/7] coresight: Pass guest TRFCR value to KVM James Clark
  6 siblings, 1 reply; 18+ messages in thread
From: James Clark @ 2024-02-20 10:09 UTC (permalink / raw)
  To: coresight, linux-arm-kernel, kvmarm, maz, suzuki.poulose, acme,
	oliver.upton, broonie
  Cc: James Clark, James Morse, Zenghui Yu, Catalin Marinas,
	Will Deacon, Mike Leach, Alexander Shishkin, Anshuman Khandual,
	Miguel Luis, Joey Gouly, Ard Biesheuvel, Arnd Bergmann,
	Helge Deller, Greg Kroah-Hartman, Mark Rutland, Kalesh Singh,
	Ryan Roberts, Vincent Donnefort, Fuad Tabba, Jing Zhang,
	linux-kernel

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.

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;
+
+	/* 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);
 }
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v5 7/7] coresight: Pass guest TRFCR value to KVM
  2024-02-20 10:09 [PATCH v5 0/7] kvm/coresight: Support exclude guest and exclude host James Clark
                   ` (5 preceding siblings ...)
  2024-02-20 10:09 ` [PATCH v5 6/7] arm64: KVM: Write TRFCR value on guest switch with nVHE James Clark
@ 2024-02-20 10:09 ` James Clark
  6 siblings, 0 replies; 18+ messages in thread
From: James Clark @ 2024-02-20 10:09 UTC (permalink / raw)
  To: coresight, linux-arm-kernel, kvmarm, maz, suzuki.poulose, acme,
	oliver.upton, broonie
  Cc: James Clark, James Morse, Zenghui Yu, Catalin Marinas,
	Will Deacon, Mike Leach, Alexander Shishkin, Anshuman Khandual,
	Miguel Luis, Joey Gouly, Ard Biesheuvel, Arnd Bergmann,
	Helge Deller, Greg Kroah-Hartman, Kalesh Singh,
	Vincent Donnefort, Ryan Roberts, Fuad Tabba, Jing Zhang,
	linux-kernel

Currently the userspace and kernel filters for guests are never set, so
no trace will be generated for them. Add support for tracing guests by
passing the desired TRFCR value to KVM so it can be applied to the
guest.

By writing either E1TRE or E0TRE, filtering on either guest kernel or
guest userspace is also supported. And if both E1TRE and E0TRE are
cleared when exclude_guest is set, that option is supported too. This
change also brings exclude_host support which is difficult to add as a
separate commit without excess churn and resulting in no trace at all.

Testing
=======

The addresses were counted with the following:

  $ perf report -D | grep -Eo 'EL2|EL1|EL0' | sort | uniq -c

Guest kernel only:

  $ perf record -e cs_etm//Gk -a -- true
    535 EL1
      1 EL2

Guest user only (only 5 addresses because the guest runs slowly in the
model):

  $ perf record -e cs_etm//Gu -a -- true
    5 EL0

Host kernel only:

  $  perf record -e cs_etm//Hk -a -- true
   3501 EL2

Host userspace only:

  $  perf record -e cs_etm//Hu -a -- true
    408 EL0
      1 EL2

Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: James Clark <james.clark@arm.com>
---
 .../coresight/coresight-etm4x-core.c          | 42 ++++++++++++++++---
 drivers/hwtracing/coresight/coresight-etm4x.h |  2 +-
 drivers/hwtracing/coresight/coresight-priv.h  |  3 ++
 3 files changed, 40 insertions(+), 7 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index ce1995a2827f..45a69bfdc6b5 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -6,6 +6,7 @@
 #include <linux/acpi.h>
 #include <linux/bitops.h>
 #include <linux/kernel.h>
+#include <linux/kvm_host.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/types.h>
@@ -271,9 +272,22 @@ static void etm4x_prohibit_trace(struct etmv4_drvdata *drvdata)
 	/* If the CPU doesn't support FEAT_TRF, nothing to do */
 	if (!drvdata->trfcr)
 		return;
+	kvm_etm_set_guest_trfcr(0);
 	cpu_prohibit_trace();
 }
 
+static u64 etm4x_get_kern_user_filter(struct etmv4_drvdata *drvdata)
+{
+	u64 trfcr = drvdata->trfcr;
+
+	if (drvdata->config.mode & ETM_MODE_EXCL_KERN)
+		trfcr &= ~TRFCR_ELx_ExTRE;
+	if (drvdata->config.mode & ETM_MODE_EXCL_USER)
+		trfcr &= ~TRFCR_ELx_E0TRE;
+
+	return trfcr;
+}
+
 /*
  * etm4x_allow_trace - Allow CPU tracing in the respective ELs,
  * as configured by the drvdata->config.mode for the current
@@ -286,18 +300,28 @@ static void etm4x_prohibit_trace(struct etmv4_drvdata *drvdata)
  */
 static void etm4x_allow_trace(struct etmv4_drvdata *drvdata)
 {
-	u64 trfcr = drvdata->trfcr;
+	u64 trfcr;
 
 	/* If the CPU doesn't support FEAT_TRF, nothing to do */
-	if (!trfcr)
+	if (!drvdata->trfcr)
 		return;
 
-	if (drvdata->config.mode & ETM_MODE_EXCL_KERN)
-		trfcr &= ~TRFCR_ELx_ExTRE;
-	if (drvdata->config.mode & ETM_MODE_EXCL_USER)
-		trfcr &= ~TRFCR_ELx_E0TRE;
+	if (drvdata->config.mode & ETM_MODE_EXCL_HOST)
+		trfcr = drvdata->trfcr & ~(TRFCR_ELx_ExTRE | TRFCR_ELx_E0TRE);
+	else
+		trfcr = etm4x_get_kern_user_filter(drvdata);
 
 	write_trfcr(trfcr);
+
+	/* Set filters for guests and pass to KVM */
+	if (drvdata->config.mode & ETM_MODE_EXCL_GUEST)
+		trfcr = drvdata->trfcr & ~(TRFCR_ELx_ExTRE | TRFCR_ELx_E0TRE);
+	else
+		trfcr = etm4x_get_kern_user_filter(drvdata);
+
+	/* TRFCR_EL1 doesn't have CX so mask it out. */
+	trfcr &= ~TRFCR_EL2_CX;
+	kvm_etm_set_guest_trfcr(trfcr);
 }
 
 #ifdef CONFIG_ETM4X_IMPDEF_FEATURE
@@ -655,6 +679,12 @@ static int etm4_parse_event_config(struct coresight_device *csdev,
 	if (attr->exclude_user)
 		config->mode = ETM_MODE_EXCL_USER;
 
+	if (attr->exclude_host)
+		config->mode |= ETM_MODE_EXCL_HOST;
+
+	if (attr->exclude_guest)
+		config->mode |= ETM_MODE_EXCL_GUEST;
+
 	/* Always start from the default config */
 	etm4_set_default_config(config);
 
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
index da17b6c49b0f..70c29e91f4b5 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.h
+++ b/drivers/hwtracing/coresight/coresight-etm4x.h
@@ -841,7 +841,7 @@ enum etm_impdef_type {
  * @s_ex_level: Secure ELs where tracing is supported.
  */
 struct etmv4_config {
-	u32				mode;
+	u64				mode;
 	u32				pe_sel;
 	u32				cfg;
 	u32				eventctrl0;
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index 767076e07970..727dd27ba800 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -39,6 +39,9 @@
 
 #define ETM_MODE_EXCL_KERN	BIT(30)
 #define ETM_MODE_EXCL_USER	BIT(31)
+#define ETM_MODE_EXCL_HOST	BIT(32)
+#define ETM_MODE_EXCL_GUEST	BIT(33)
+
 struct cs_pair_attribute {
 	struct device_attribute attr;
 	u32 lo_off;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH v5 3/7] arm64/sysreg/tools: Move TRFCR definitions to sysreg
  2024-02-20 10:09 ` [PATCH v5 3/7] arm64/sysreg/tools: Move TRFCR definitions to sysreg James Clark
@ 2024-02-20 16:11   ` Mark Brown
  2024-02-21 10:10     ` James Clark
  0 siblings, 1 reply; 18+ messages in thread
From: Mark Brown @ 2024-02-20 16:11 UTC (permalink / raw)
  To: James Clark
  Cc: coresight, linux-arm-kernel, kvmarm, maz, suzuki.poulose, acme,
	oliver.upton, James Morse, Zenghui Yu, Catalin Marinas,
	Will Deacon, Mike Leach, Alexander Shishkin, Anshuman Khandual,
	Miguel Luis, Joey Gouly, Ard Biesheuvel, Greg Kroah-Hartman,
	Arnd Bergmann, Mark Rutland, Kalesh Singh, Vincent Donnefort,
	Ryan Roberts, Fuad Tabba, Jing Zhang, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1095 bytes --]

On Tue, Feb 20, 2024 at 10:09:13AM +0000, James Clark wrote:
> Add separate definitions for ELx and EL2 as TRFCR_EL1 doesn't have CX.
> This also mirrors the previous definition so no code change is required.

This is also converting to automatic generation in the process.

> +SysregFields TRFCR_EL2
> +Res0	63:7
> +UnsignedEnum	6:5	TS
> +	0b0000	USE_TRFCR_EL1_TS
> +	0b0001	VIRTUAL
> +	0b0010	GUEST_PHYSICAL
> +	0b0011	PHYSICAL
> +EndEnum
> +Res0	4
> +Field	3	CX
> +Res0	2
> +Field	1	E2TRE
> +Field	0	E0HTRE
> +EndSysregFields

This has exactly one user and I'd not expect more so why have a separate
SysregFields?

> +# TRFCR_EL1 doesn't have the CX bit so redefine it without CX instead of
> +# using a shared definition between TRFCR_EL2 and TRFCR_EL1

This comment is reflecting the default state?

> +Sysreg	TRFCR_EL1	3	0	1	2	1
> +Fields	TRFCR_ELx
> +EndSysreg
> +
> +Sysreg	TRFCR_EL2	3	4	1	2	1
> +Fields	TRFCR_EL2
> +EndSysreg
> +
> +Sysreg	TRFCR_EL12	3	5	1	2	1
> +Fields	TRFCR_ELx
> +EndSysreg

These are generally sorted by encoding (simiarly to how sysreg.h was
sorted historically).

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v5 2/7] arm64/sysreg/tools: Update tools copy of sysreg.h
  2024-02-20 10:09 ` [PATCH v5 2/7] arm64/sysreg/tools: Update tools copy of sysreg.h James Clark
@ 2024-02-20 16:12   ` Mark Brown
  2024-02-26 10:30   ` Suzuki K Poulose
  1 sibling, 0 replies; 18+ messages in thread
From: Mark Brown @ 2024-02-20 16:12 UTC (permalink / raw)
  To: James Clark
  Cc: coresight, linux-arm-kernel, kvmarm, maz, suzuki.poulose, acme,
	oliver.upton, James Morse, Zenghui Yu, Catalin Marinas,
	Will Deacon, Mike Leach, Alexander Shishkin, Anshuman Khandual,
	Miguel Luis, Joey Gouly, Ard Biesheuvel, Helge Deller,
	Greg Kroah-Hartman, Arnd Bergmann, Andrew Walbran, Kalesh Singh,
	Vincent Donnefort, Ryan Roberts, Fuad Tabba, Jing Zhang,
	linux-kernel

[-- Attachment #1: Type: text/plain, Size: 511 bytes --]

On Tue, Feb 20, 2024 at 10:09:12AM +0000, James Clark wrote:
> Created with the following:
> 
>   cp include/linux/kasan-tags.h tools/include/linux/
>   cp arch/arm64/include/asm/sysreg.h tools/arch/arm64/include/asm/
> 
> Update the tools copy of sysreg.h so that the next commit to add a new
> register doesn't have unrelated changes in it. Because the new version
> of sysreg.h includes kasan-tags.h, that file also now needs to be copied
> into tools.

Acked-by: Mark Brown <broonie@kernel.org>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v5 3/7] arm64/sysreg/tools: Move TRFCR definitions to sysreg
  2024-02-20 16:11   ` Mark Brown
@ 2024-02-21 10:10     ` James Clark
  2024-02-21 12:56       ` Mark Brown
  0 siblings, 1 reply; 18+ messages in thread
From: James Clark @ 2024-02-21 10:10 UTC (permalink / raw)
  To: Mark Brown
  Cc: coresight, linux-arm-kernel, kvmarm, maz, suzuki.poulose, acme,
	oliver.upton, James Morse, Zenghui Yu, Catalin Marinas,
	Will Deacon, Mike Leach, Alexander Shishkin, Anshuman Khandual,
	Miguel Luis, Joey Gouly, Ard Biesheuvel, Greg Kroah-Hartman,
	Arnd Bergmann, Mark Rutland, Kalesh Singh, Vincent Donnefort,
	Ryan Roberts, Fuad Tabba, Jing Zhang, linux-kernel



On 20/02/2024 16:11, Mark Brown wrote:
> On Tue, Feb 20, 2024 at 10:09:13AM +0000, James Clark wrote:
>> Add separate definitions for ELx and EL2 as TRFCR_EL1 doesn't have CX.
>> This also mirrors the previous definition so no code change is required.
> 
> This is also converting to automatic generation in the process.
> 
>> +SysregFields TRFCR_EL2
>> +Res0	63:7
>> +UnsignedEnum	6:5	TS
>> +	0b0000	USE_TRFCR_EL1_TS
>> +	0b0001	VIRTUAL
>> +	0b0010	GUEST_PHYSICAL
>> +	0b0011	PHYSICAL
>> +EndEnum
>> +Res0	4
>> +Field	3	CX
>> +Res0	2
>> +Field	1	E2TRE
>> +Field	0	E0HTRE
>> +EndSysregFields
> 
> This has exactly one user and I'd not expect more so why have a separate
> SysregFields?
> 

No reason, probably just a copy paste thing. I'll change it to a Sysreg.

>> +# TRFCR_EL1 doesn't have the CX bit so redefine it without CX instead of
>> +# using a shared definition between TRFCR_EL2 and TRFCR_EL1
> 
> This comment is reflecting the default state?
> 

True, will remove.

>> +Sysreg	TRFCR_EL1	3	0	1	2	1
>> +Fields	TRFCR_ELx
>> +EndSysreg
>> +
>> +Sysreg	TRFCR_EL2	3	4	1	2	1
>> +Fields	TRFCR_EL2
>> +EndSysreg
>> +
>> +Sysreg	TRFCR_EL12	3	5	1	2	1
>> +Fields	TRFCR_ELx
>> +EndSysreg
> 
> These are generally sorted by encoding (simiarly to how sysreg.h was
> sorted historically).

Ah I didn't know that. Can I add a comment to the top of the file saying
that it should be kept sorted?

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v5 3/7] arm64/sysreg/tools: Move TRFCR definitions to sysreg
  2024-02-21 10:10     ` James Clark
@ 2024-02-21 12:56       ` Mark Brown
  0 siblings, 0 replies; 18+ messages in thread
From: Mark Brown @ 2024-02-21 12:56 UTC (permalink / raw)
  To: James Clark
  Cc: coresight, linux-arm-kernel, kvmarm, maz, suzuki.poulose, acme,
	oliver.upton, James Morse, Zenghui Yu, Catalin Marinas,
	Will Deacon, Mike Leach, Alexander Shishkin, Anshuman Khandual,
	Miguel Luis, Joey Gouly, Ard Biesheuvel, Greg Kroah-Hartman,
	Arnd Bergmann, Mark Rutland, Kalesh Singh, Vincent Donnefort,
	Ryan Roberts, Fuad Tabba, Jing Zhang, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 318 bytes --]

On Wed, Feb 21, 2024 at 10:10:18AM +0000, James Clark wrote:
> On 20/02/2024 16:11, Mark Brown wrote:

> > These are generally sorted by encoding (simiarly to how sysreg.h was
> > sorted historically).

> Ah I didn't know that. Can I add a comment to the top of the file saying
> that it should be kept sorted?

Sure.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v5 5/7] arm64: KVM: Add interface to set guest value for TRFCR register
  2024-02-20 10:09 ` [PATCH v5 5/7] arm64: KVM: Add interface to set guest value for TRFCR register James Clark
@ 2024-02-23 10:03   ` Suzuki K Poulose
  2024-02-23 16:39     ` James Clark
  0 siblings, 1 reply; 18+ messages in thread
From: Suzuki K Poulose @ 2024-02-23 10:03 UTC (permalink / raw)
  To: James Clark, coresight, linux-arm-kernel, kvmarm, maz, acme,
	oliver.upton, broonie
  Cc: James Morse, Zenghui Yu, Catalin Marinas, Will Deacon,
	Mike Leach, Alexander Shishkin, Anshuman Khandual, Miguel Luis,
	Joey Gouly, Ard Biesheuvel, Greg Kroah-Hartman, Arnd Bergmann,
	Helge Deller, Andrew Walbran, Vincent Donnefort, Ryan Roberts,
	Fuad Tabba, Jing Zhang, linux-kernel

On 20/02/2024 10:09, James Clark wrote:
> Add an interface for the Coresight driver to use to set the value of the
> TRFCR register for the guest. This register controls the exclude
> settings for trace at different exception levels, and is used to honor
> the exclude_host and exclude_guest parameters from the Perf session.
> This will be used to later write TRFCR_EL1 on nVHE at guest switch. For
> VHE, the host trace is controlled by TRFCR_EL2 and thus we can write to
> the TRFCR_EL1 immediately. Because guest writes to the register are
> trapped, the value will persist and can't be modified.
> 
> Instead of adding a load of infrastructure to share the host's per-cpu
> offsets with the hypervisor, just define the new storage as a NR_CPUS
> array.
> 
> Signed-off-by: James Clark <james.clark@arm.com>
> ---
>   arch/arm64/include/asm/kvm_host.h |  3 +++
>   arch/arm64/kernel/image-vars.h    |  1 +
>   arch/arm64/kvm/debug.c            | 26 ++++++++++++++++++++++++++
>   3 files changed, 30 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index 85b5477bd1b4..56b7f7eca195 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -509,6 +509,7 @@ struct kvm_host_psci_config {
>   	bool psci_0_1_cpu_off_implemented;
>   	bool psci_0_1_migrate_implemented;
>   };
> +extern u64 ____cacheline_aligned kvm_guest_trfcr[NR_CPUS];
>   
>   extern struct kvm_host_psci_config kvm_nvhe_sym(kvm_host_psci_config);
>   #define kvm_host_psci_config CHOOSE_NVHE_SYM(kvm_host_psci_config)
> @@ -1174,6 +1175,7 @@ void kvm_arch_vcpu_put_debug_state_flags(struct kvm_vcpu *vcpu);
>   void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr);
>   void kvm_clr_pmu_events(u32 clr);
>   bool kvm_set_pmuserenr(u64 val);
> +void kvm_etm_set_guest_trfcr(u64 trfcr_guest);
>   #else
>   static inline void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr) {}
>   static inline void kvm_clr_pmu_events(u32 clr) {}
> @@ -1181,6 +1183,7 @@ static inline bool kvm_set_pmuserenr(u64 val)
>   {
>   	return false;
>   }
> +static inline void kvm_etm_set_guest_trfcr(u64 trfcr_guest) {}
>   #endif
>   
>   void kvm_vcpu_load_vhe(struct kvm_vcpu *vcpu);
> diff --git a/arch/arm64/kernel/image-vars.h b/arch/arm64/kernel/image-vars.h
> index 5e4dc72ab1bd..a451e4f10804 100644
> --- a/arch/arm64/kernel/image-vars.h
> +++ b/arch/arm64/kernel/image-vars.h
> @@ -59,6 +59,7 @@ KVM_NVHE_ALIAS(alt_cb_patch_nops);
>   
>   /* Global kernel state accessed by nVHE hyp code. */
>   KVM_NVHE_ALIAS(kvm_vgic_global_state);
> +KVM_NVHE_ALIAS(kvm_guest_trfcr);
>   
>   /* Kernel symbols used to call panic() from nVHE hyp code (via ERET). */
>   KVM_NVHE_ALIAS(nvhe_hyp_panic_handler);
> diff --git a/arch/arm64/kvm/debug.c b/arch/arm64/kvm/debug.c
> index 49a13e72ddd2..c8d936ce6e2b 100644
> --- a/arch/arm64/kvm/debug.c
> +++ b/arch/arm64/kvm/debug.c
> @@ -22,6 +22,7 @@
>   				DBG_MDSCR_MDE)
>   
>   static DEFINE_PER_CPU(u64, mdcr_el2);
> +u64 ____cacheline_aligned kvm_guest_trfcr[NR_CPUS];
>   
>   /*
>    * save/restore_guest_debug_regs
> @@ -359,3 +360,28 @@ void kvm_arch_vcpu_put_debug_state_flags(struct kvm_vcpu *vcpu)
>   	vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE_TRBE);
>   	vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE_TRFCR);
>   }
> +
> +/*
> + * Interface for the Coresight driver to use to set the value of the TRFCR
> + * register for the guest. This register controls the exclude settings for trace
> + * at different exception levels, and is used to honor the exclude_host and
> + * exclude_guest parameters from the Perf session.
> + *
> + * This will be used to later write TRFCR_EL1 on nVHE at guest switch. For VHE,
> + * the host trace is controlled by TRFCR_EL2 and thus we can write to the
> + * TRFCR_EL1 immediately. Because guest writes to the register are trapped, the
> + * value will persist and can't be modified. For pKVM, kvm_guest_trfcr can't
> + * be read by the hypervisor, so don't bother writing it.
> + */
> +void kvm_etm_set_guest_trfcr(u64 trfcr_guest)
> +{
> +	if (WARN_ON_ONCE(!cpuid_feature_extract_unsigned_field(read_sysreg(id_aa64dfr0_el1),
> +							       ID_AA64DFR0_EL1_TraceFilt_SHIFT)))
> +		return;
> +
> +	if (has_vhe())
> +		write_sysreg_s(trfcr_guest, SYS_TRFCR_EL12);
> +	else if (!is_protected_kvm_enabled())
> +		kvm_guest_trfcr[smp_processor_id()] = trfcr_guest;

smp_processor_id() could sleep in some configurations ? Should we switch 
to raw_smp_processor_id() to be safer ?

Otherwise looks good to me.

Suzuki

> +}
> +EXPORT_SYMBOL_GPL(kvm_etm_set_guest_trfcr);


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v5 5/7] arm64: KVM: Add interface to set guest value for TRFCR register
  2024-02-23 10:03   ` Suzuki K Poulose
@ 2024-02-23 16:39     ` James Clark
  2024-02-26  9:52       ` Suzuki K Poulose
  0 siblings, 1 reply; 18+ messages in thread
From: James Clark @ 2024-02-23 16:39 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: James Morse, Zenghui Yu, Catalin Marinas, Will Deacon,
	Mike Leach, Alexander Shishkin, Anshuman Khandual, Miguel Luis,
	Joey Gouly, Ard Biesheuvel, Greg Kroah-Hartman, Arnd Bergmann,
	Helge Deller, Andrew Walbran, Vincent Donnefort, Ryan Roberts,
	Fuad Tabba, Jing Zhang, linux-kernel, coresight,
	linux-arm-kernel, kvmarm, maz, acme, oliver.upton, broonie



On 23/02/2024 10:03, Suzuki K Poulose wrote:
> On 20/02/2024 10:09, James Clark wrote:
>> Add an interface for the Coresight driver to use to set the value of the
>> TRFCR register for the guest. This register controls the exclude
>> settings for trace at different exception levels, and is used to honor
>> the exclude_host and exclude_guest parameters from the Perf session.
>> This will be used to later write TRFCR_EL1 on nVHE at guest switch. For
>> VHE, the host trace is controlled by TRFCR_EL2 and thus we can write to
>> the TRFCR_EL1 immediately. Because guest writes to the register are
>> trapped, the value will persist and can't be modified.
>>
>> Instead of adding a load of infrastructure to share the host's per-cpu
>> offsets with the hypervisor, just define the new storage as a NR_CPUS
>> array.
>>
>> Signed-off-by: James Clark <james.clark@arm.com>
>> ---
>>   arch/arm64/include/asm/kvm_host.h |  3 +++
>>   arch/arm64/kernel/image-vars.h    |  1 +
>>   arch/arm64/kvm/debug.c            | 26 ++++++++++++++++++++++++++
>>   3 files changed, 30 insertions(+)
>>
>> diff --git a/arch/arm64/include/asm/kvm_host.h
>> b/arch/arm64/include/asm/kvm_host.h
>> index 85b5477bd1b4..56b7f7eca195 100644
>> --- a/arch/arm64/include/asm/kvm_host.h
>> +++ b/arch/arm64/include/asm/kvm_host.h
>> @@ -509,6 +509,7 @@ struct kvm_host_psci_config {
>>       bool psci_0_1_cpu_off_implemented;
>>       bool psci_0_1_migrate_implemented;
>>   };
>> +extern u64 ____cacheline_aligned kvm_guest_trfcr[NR_CPUS];
>>     extern struct kvm_host_psci_config
>> kvm_nvhe_sym(kvm_host_psci_config);
>>   #define kvm_host_psci_config CHOOSE_NVHE_SYM(kvm_host_psci_config)
>> @@ -1174,6 +1175,7 @@ void kvm_arch_vcpu_put_debug_state_flags(struct
>> kvm_vcpu *vcpu);
>>   void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr);
>>   void kvm_clr_pmu_events(u32 clr);
>>   bool kvm_set_pmuserenr(u64 val);
>> +void kvm_etm_set_guest_trfcr(u64 trfcr_guest);
>>   #else
>>   static inline void kvm_set_pmu_events(u32 set, struct
>> perf_event_attr *attr) {}
>>   static inline void kvm_clr_pmu_events(u32 clr) {}
>> @@ -1181,6 +1183,7 @@ static inline bool kvm_set_pmuserenr(u64 val)
>>   {
>>       return false;
>>   }
>> +static inline void kvm_etm_set_guest_trfcr(u64 trfcr_guest) {}
>>   #endif
>>     void kvm_vcpu_load_vhe(struct kvm_vcpu *vcpu);
>> diff --git a/arch/arm64/kernel/image-vars.h
>> b/arch/arm64/kernel/image-vars.h
>> index 5e4dc72ab1bd..a451e4f10804 100644
>> --- a/arch/arm64/kernel/image-vars.h
>> +++ b/arch/arm64/kernel/image-vars.h
>> @@ -59,6 +59,7 @@ KVM_NVHE_ALIAS(alt_cb_patch_nops);
>>     /* Global kernel state accessed by nVHE hyp code. */
>>   KVM_NVHE_ALIAS(kvm_vgic_global_state);
>> +KVM_NVHE_ALIAS(kvm_guest_trfcr);
>>     /* Kernel symbols used to call panic() from nVHE hyp code (via
>> ERET). */
>>   KVM_NVHE_ALIAS(nvhe_hyp_panic_handler);
>> diff --git a/arch/arm64/kvm/debug.c b/arch/arm64/kvm/debug.c
>> index 49a13e72ddd2..c8d936ce6e2b 100644
>> --- a/arch/arm64/kvm/debug.c
>> +++ b/arch/arm64/kvm/debug.c
>> @@ -22,6 +22,7 @@
>>                   DBG_MDSCR_MDE)
>>     static DEFINE_PER_CPU(u64, mdcr_el2);
>> +u64 ____cacheline_aligned kvm_guest_trfcr[NR_CPUS];
>>     /*
>>    * save/restore_guest_debug_regs
>> @@ -359,3 +360,28 @@ void kvm_arch_vcpu_put_debug_state_flags(struct
>> kvm_vcpu *vcpu)
>>       vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE_TRBE);
>>       vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE_TRFCR);
>>   }
>> +
>> +/*
>> + * Interface for the Coresight driver to use to set the value of the
>> TRFCR
>> + * register for the guest. This register controls the exclude
>> settings for trace
>> + * at different exception levels, and is used to honor the
>> exclude_host and
>> + * exclude_guest parameters from the Perf session.
>> + *
>> + * This will be used to later write TRFCR_EL1 on nVHE at guest
>> switch. For VHE,
>> + * the host trace is controlled by TRFCR_EL2 and thus we can write to
>> the
>> + * TRFCR_EL1 immediately. Because guest writes to the register are
>> trapped, the
>> + * value will persist and can't be modified. For pKVM,
>> kvm_guest_trfcr can't
>> + * be read by the hypervisor, so don't bother writing it.
>> + */
>> +void kvm_etm_set_guest_trfcr(u64 trfcr_guest)
>> +{
>> +    if
>> (WARN_ON_ONCE(!cpuid_feature_extract_unsigned_field(read_sysreg(id_aa64dfr0_el1),
>> +                                   ID_AA64DFR0_EL1_TraceFilt_SHIFT)))
>> +        return;
>> +
>> +    if (has_vhe())
>> +        write_sysreg_s(trfcr_guest, SYS_TRFCR_EL12);
>> +    else if (!is_protected_kvm_enabled())
>> +        kvm_guest_trfcr[smp_processor_id()] = trfcr_guest;
> 
> smp_processor_id() could sleep in some configurations ? Should we switch
> to raw_smp_processor_id() to be safer ?
> 

I don't think so, it's #defined to raw_smp_processor_id() anyway. Unless
DEBUG_PREEMPT is on, then it's still raw_smp_processor_id() but it
validates that preemption is disabled so the value isn't stale.

We actually want that validation, so should leave it as
smp_processor_id(). I can add a comment saying that this function should
only be called with preemption disabled, but I wouldn't add any extra
validation. Every smp_processor_id() call is already checked when
DEBUG_PREEMPT is on and this one doesn't seem to be special in any way.

I also checked that the warning isn't triggered with DEBUG_PREEMPT on,
and there are also a lot of other smp_processor_id() calls on similar
paths in the Coresight driver.

> Otherwise looks good to me.
> 
> Suzuki
> 
>> +}
>> +EXPORT_SYMBOL_GPL(kvm_etm_set_guest_trfcr);
> 

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v5 5/7] arm64: KVM: Add interface to set guest value for TRFCR register
  2024-02-23 16:39     ` James Clark
@ 2024-02-26  9:52       ` Suzuki K Poulose
  2024-02-26 11:36         ` James Clark
  0 siblings, 1 reply; 18+ messages in thread
From: Suzuki K Poulose @ 2024-02-26  9:52 UTC (permalink / raw)
  To: James Clark
  Cc: James Morse, Zenghui Yu, Catalin Marinas, Will Deacon,
	Mike Leach, Alexander Shishkin, Anshuman Khandual, Miguel Luis,
	Joey Gouly, Ard Biesheuvel, Greg Kroah-Hartman, Arnd Bergmann,
	Helge Deller, Andrew Walbran, Vincent Donnefort, Ryan Roberts,
	Fuad Tabba, Jing Zhang, linux-kernel, coresight,
	linux-arm-kernel, kvmarm, maz, acme, oliver.upton, broonie

On 23/02/2024 16:39, James Clark wrote:
> 
> 
> On 23/02/2024 10:03, Suzuki K Poulose wrote:
>> On 20/02/2024 10:09, James Clark wrote:
>>> Add an interface for the Coresight driver to use to set the value of the
>>> TRFCR register for the guest. This register controls the exclude
>>> settings for trace at different exception levels, and is used to honor
>>> the exclude_host and exclude_guest parameters from the Perf session.
>>> This will be used to later write TRFCR_EL1 on nVHE at guest switch. For
>>> VHE, the host trace is controlled by TRFCR_EL2 and thus we can write to
>>> the TRFCR_EL1 immediately. Because guest writes to the register are
>>> trapped, the value will persist and can't be modified.
>>>
>>> Instead of adding a load of infrastructure to share the host's per-cpu
>>> offsets with the hypervisor, just define the new storage as a NR_CPUS
>>> array.
>>>
>>> Signed-off-by: James Clark <james.clark@arm.com>
>>> ---
>>>    arch/arm64/include/asm/kvm_host.h |  3 +++
>>>    arch/arm64/kernel/image-vars.h    |  1 +
>>>    arch/arm64/kvm/debug.c            | 26 ++++++++++++++++++++++++++
>>>    3 files changed, 30 insertions(+)
>>>
>>> diff --git a/arch/arm64/include/asm/kvm_host.h
>>> b/arch/arm64/include/asm/kvm_host.h
>>> index 85b5477bd1b4..56b7f7eca195 100644
>>> --- a/arch/arm64/include/asm/kvm_host.h
>>> +++ b/arch/arm64/include/asm/kvm_host.h
>>> @@ -509,6 +509,7 @@ struct kvm_host_psci_config {
>>>        bool psci_0_1_cpu_off_implemented;
>>>        bool psci_0_1_migrate_implemented;
>>>    };
>>> +extern u64 ____cacheline_aligned kvm_guest_trfcr[NR_CPUS];
>>>      extern struct kvm_host_psci_config
>>> kvm_nvhe_sym(kvm_host_psci_config);
>>>    #define kvm_host_psci_config CHOOSE_NVHE_SYM(kvm_host_psci_config)
>>> @@ -1174,6 +1175,7 @@ void kvm_arch_vcpu_put_debug_state_flags(struct
>>> kvm_vcpu *vcpu);
>>>    void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr);
>>>    void kvm_clr_pmu_events(u32 clr);
>>>    bool kvm_set_pmuserenr(u64 val);
>>> +void kvm_etm_set_guest_trfcr(u64 trfcr_guest);
>>>    #else
>>>    static inline void kvm_set_pmu_events(u32 set, struct
>>> perf_event_attr *attr) {}
>>>    static inline void kvm_clr_pmu_events(u32 clr) {}
>>> @@ -1181,6 +1183,7 @@ static inline bool kvm_set_pmuserenr(u64 val)
>>>    {
>>>        return false;
>>>    }
>>> +static inline void kvm_etm_set_guest_trfcr(u64 trfcr_guest) {}
>>>    #endif
>>>      void kvm_vcpu_load_vhe(struct kvm_vcpu *vcpu);
>>> diff --git a/arch/arm64/kernel/image-vars.h
>>> b/arch/arm64/kernel/image-vars.h
>>> index 5e4dc72ab1bd..a451e4f10804 100644
>>> --- a/arch/arm64/kernel/image-vars.h
>>> +++ b/arch/arm64/kernel/image-vars.h
>>> @@ -59,6 +59,7 @@ KVM_NVHE_ALIAS(alt_cb_patch_nops);
>>>      /* Global kernel state accessed by nVHE hyp code. */
>>>    KVM_NVHE_ALIAS(kvm_vgic_global_state);
>>> +KVM_NVHE_ALIAS(kvm_guest_trfcr);
>>>      /* Kernel symbols used to call panic() from nVHE hyp code (via
>>> ERET). */
>>>    KVM_NVHE_ALIAS(nvhe_hyp_panic_handler);
>>> diff --git a/arch/arm64/kvm/debug.c b/arch/arm64/kvm/debug.c
>>> index 49a13e72ddd2..c8d936ce6e2b 100644
>>> --- a/arch/arm64/kvm/debug.c
>>> +++ b/arch/arm64/kvm/debug.c
>>> @@ -22,6 +22,7 @@
>>>                    DBG_MDSCR_MDE)
>>>      static DEFINE_PER_CPU(u64, mdcr_el2);
>>> +u64 ____cacheline_aligned kvm_guest_trfcr[NR_CPUS];
>>>      /*
>>>     * save/restore_guest_debug_regs
>>> @@ -359,3 +360,28 @@ void kvm_arch_vcpu_put_debug_state_flags(struct
>>> kvm_vcpu *vcpu)
>>>        vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE_TRBE);
>>>        vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE_TRFCR);
>>>    }
>>> +
>>> +/*
>>> + * Interface for the Coresight driver to use to set the value of the
>>> TRFCR
>>> + * register for the guest. This register controls the exclude
>>> settings for trace
>>> + * at different exception levels, and is used to honor the
>>> exclude_host and
>>> + * exclude_guest parameters from the Perf session.
>>> + *
>>> + * This will be used to later write TRFCR_EL1 on nVHE at guest
>>> switch. For VHE,
>>> + * the host trace is controlled by TRFCR_EL2 and thus we can write to
>>> the
>>> + * TRFCR_EL1 immediately. Because guest writes to the register are
>>> trapped, the
>>> + * value will persist and can't be modified. For pKVM,
>>> kvm_guest_trfcr can't
>>> + * be read by the hypervisor, so don't bother writing it.
>>> + */
>>> +void kvm_etm_set_guest_trfcr(u64 trfcr_guest)
>>> +{
>>> +    if
>>> (WARN_ON_ONCE(!cpuid_feature_extract_unsigned_field(read_sysreg(id_aa64dfr0_el1),
>>> +                                   ID_AA64DFR0_EL1_TraceFilt_SHIFT)))
>>> +        return;
>>> +
>>> +    if (has_vhe())
>>> +        write_sysreg_s(trfcr_guest, SYS_TRFCR_EL12);
>>> +    else if (!is_protected_kvm_enabled())
>>> +        kvm_guest_trfcr[smp_processor_id()] = trfcr_guest;
>>
>> smp_processor_id() could sleep in some configurations ? Should we switch
>> to raw_smp_processor_id() to be safer ?
>>
> 
> I don't think so, it's #defined to raw_smp_processor_id() anyway. Unless
> DEBUG_PREEMPT is on, then it's still raw_smp_processor_id() but it
> validates that preemption is disabled so the value isn't stale. >
> We actually want that validation, so should leave it as

This is actually what we want. i.e., We don't want the coresight drivers
to make this call from a non-premptible context. Relying on the 
DEBUG_PREEMPT for detecting such erroneous uses is not a good idea, 
production kernels may not do this and a comment doesn't go far.
So, I think we need a :

WARN_ON(preemptible()) in here and use smp_processor_id()

> smp_processor_id(). I can add a comment saying that this function should
> only be called with preemption disabled, but I wouldn't add any extra
> validation. Every smp_processor_id() call is already checked when
> DEBUG_PREEMPT is on and this one doesn't seem to be special in any way.
> 
> I also checked that the warning isn't triggered with DEBUG_PREEMPT on,
> and there are also a lot of other smp_processor_id() calls on similar
> paths in the Coresight driver.

Here, we are setting something for the KVM to program and if we set the
filters on the wrong Physical CPU, then we mess up the tracing.

Suzuki

> 
>> Otherwise looks good to me.
>>
>> Suzuki
>>
>>> +}
>>> +EXPORT_SYMBOL_GPL(kvm_etm_set_guest_trfcr);
>>


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v5 6/7] arm64: KVM: Write TRFCR value on guest switch with nVHE
  2024-02-20 10:09 ` [PATCH v5 6/7] arm64: KVM: Write TRFCR value on guest switch with nVHE James Clark
@ 2024-02-26 10:14   ` Suzuki K Poulose
  0 siblings, 0 replies; 18+ messages in thread
From: Suzuki K Poulose @ 2024-02-26 10:14 UTC (permalink / raw)
  To: James Clark, coresight, linux-arm-kernel, kvmarm, maz, acme,
	oliver.upton, broonie
  Cc: James Morse, Zenghui Yu, Catalin Marinas, Will Deacon,
	Mike Leach, Alexander Shishkin, Anshuman Khandual, Miguel Luis,
	Joey Gouly, Ard Biesheuvel, Arnd Bergmann, Helge Deller,
	Greg Kroah-Hartman, Mark Rutland, Kalesh Singh, Ryan Roberts,
	Vincent Donnefort, Fuad Tabba, Jing Zhang, linux-kernel

On 20/02/2024 10:09, James Clark 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.
> 
> Signed-off-by: James Clark <james.clark@arm.com>

Reviewed-by: Suzuki K Poulose <suzuki.poulose@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;
> +
> +	/* 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);
>   }
>   


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v5 2/7] arm64/sysreg/tools: Update tools copy of sysreg.h
  2024-02-20 10:09 ` [PATCH v5 2/7] arm64/sysreg/tools: Update tools copy of sysreg.h James Clark
  2024-02-20 16:12   ` Mark Brown
@ 2024-02-26 10:30   ` Suzuki K Poulose
  1 sibling, 0 replies; 18+ messages in thread
From: Suzuki K Poulose @ 2024-02-26 10:30 UTC (permalink / raw)
  To: James Clark, coresight, linux-arm-kernel, kvmarm, maz, acme,
	oliver.upton, broonie
  Cc: James Morse, Zenghui Yu, Catalin Marinas, Will Deacon,
	Mike Leach, Alexander Shishkin, Anshuman Khandual, Miguel Luis,
	Joey Gouly, Ard Biesheuvel, Helge Deller, Greg Kroah-Hartman,
	Arnd Bergmann, Andrew Walbran, Kalesh Singh, Vincent Donnefort,
	Ryan Roberts, Fuad Tabba, Jing Zhang, linux-kernel

On 20/02/2024 10:09, James Clark wrote:

Super minor nit: Subject:

"tools: arm64: Update sysreg.h header files"


> Created with the following:
> 
>    cp include/linux/kasan-tags.h tools/include/linux/
>    cp arch/arm64/include/asm/sysreg.h tools/arch/arm64/include/asm/
> 
> Update the tools copy of sysreg.h so that the next commit to add a new
> register doesn't have unrelated changes in it. Because the new version
> of sysreg.h includes kasan-tags.h, that file also now needs to be copied
> into tools.
> 
> Signed-off-by: James Clark <james.clark@arm.com>

Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>


> ---
>   tools/arch/arm64/include/asm/sysreg.h | 363 +++++++++++++++++++++++++-
>   tools/include/linux/kasan-tags.h      |  15 ++
>   2 files changed, 375 insertions(+), 3 deletions(-)
>   create mode 100644 tools/include/linux/kasan-tags.h
> 
> diff --git a/tools/arch/arm64/include/asm/sysreg.h b/tools/arch/arm64/include/asm/sysreg.h
> index ccc13e991376..9e8999592f3a 100644
> --- a/tools/arch/arm64/include/asm/sysreg.h
> +++ b/tools/arch/arm64/include/asm/sysreg.h
> @@ -11,6 +11,7 @@
>   
>   #include <linux/bits.h>
>   #include <linux/stringify.h>
> +#include <linux/kasan-tags.h>
>   
>   #include <asm/gpr-num.h>
>   
> @@ -123,6 +124,37 @@
>   #define SYS_DC_CIGSW			sys_insn(1, 0, 7, 14, 4)
>   #define SYS_DC_CIGDSW			sys_insn(1, 0, 7, 14, 6)
>   
> +#define SYS_IC_IALLUIS			sys_insn(1, 0, 7, 1, 0)
> +#define SYS_IC_IALLU			sys_insn(1, 0, 7, 5, 0)
> +#define SYS_IC_IVAU			sys_insn(1, 3, 7, 5, 1)
> +
> +#define SYS_DC_IVAC			sys_insn(1, 0, 7, 6, 1)
> +#define SYS_DC_IGVAC			sys_insn(1, 0, 7, 6, 3)
> +#define SYS_DC_IGDVAC			sys_insn(1, 0, 7, 6, 5)
> +
> +#define SYS_DC_CVAC			sys_insn(1, 3, 7, 10, 1)
> +#define SYS_DC_CGVAC			sys_insn(1, 3, 7, 10, 3)
> +#define SYS_DC_CGDVAC			sys_insn(1, 3, 7, 10, 5)
> +
> +#define SYS_DC_CVAU			sys_insn(1, 3, 7, 11, 1)
> +
> +#define SYS_DC_CVAP			sys_insn(1, 3, 7, 12, 1)
> +#define SYS_DC_CGVAP			sys_insn(1, 3, 7, 12, 3)
> +#define SYS_DC_CGDVAP			sys_insn(1, 3, 7, 12, 5)
> +
> +#define SYS_DC_CVADP			sys_insn(1, 3, 7, 13, 1)
> +#define SYS_DC_CGVADP			sys_insn(1, 3, 7, 13, 3)
> +#define SYS_DC_CGDVADP			sys_insn(1, 3, 7, 13, 5)
> +
> +#define SYS_DC_CIVAC			sys_insn(1, 3, 7, 14, 1)
> +#define SYS_DC_CIGVAC			sys_insn(1, 3, 7, 14, 3)
> +#define SYS_DC_CIGDVAC			sys_insn(1, 3, 7, 14, 5)
> +
> +/* Data cache zero operations */
> +#define SYS_DC_ZVA			sys_insn(1, 3, 7, 4, 1)
> +#define SYS_DC_GVA			sys_insn(1, 3, 7, 4, 3)
> +#define SYS_DC_GZVA			sys_insn(1, 3, 7, 4, 4)
> +
>   /*
>    * Automatically generated definitions for system registers, the
>    * manual encodings below are in the process of being converted to
> @@ -162,6 +194,84 @@
>   #define SYS_DBGDTRTX_EL0		sys_reg(2, 3, 0, 5, 0)
>   #define SYS_DBGVCR32_EL2		sys_reg(2, 4, 0, 7, 0)
>   
> +#define SYS_BRBINF_EL1(n)		sys_reg(2, 1, 8, (n & 15), (((n & 16) >> 2) | 0))
> +#define SYS_BRBINFINJ_EL1		sys_reg(2, 1, 9, 1, 0)
> +#define SYS_BRBSRC_EL1(n)		sys_reg(2, 1, 8, (n & 15), (((n & 16) >> 2) | 1))
> +#define SYS_BRBSRCINJ_EL1		sys_reg(2, 1, 9, 1, 1)
> +#define SYS_BRBTGT_EL1(n)		sys_reg(2, 1, 8, (n & 15), (((n & 16) >> 2) | 2))
> +#define SYS_BRBTGTINJ_EL1		sys_reg(2, 1, 9, 1, 2)
> +#define SYS_BRBTS_EL1			sys_reg(2, 1, 9, 0, 2)
> +
> +#define SYS_BRBCR_EL1			sys_reg(2, 1, 9, 0, 0)
> +#define SYS_BRBFCR_EL1			sys_reg(2, 1, 9, 0, 1)
> +#define SYS_BRBIDR0_EL1			sys_reg(2, 1, 9, 2, 0)
> +
> +#define SYS_TRCITECR_EL1		sys_reg(3, 0, 1, 2, 3)
> +#define SYS_TRCACATR(m)			sys_reg(2, 1, 2, ((m & 7) << 1), (2 | (m >> 3)))
> +#define SYS_TRCACVR(m)			sys_reg(2, 1, 2, ((m & 7) << 1), (0 | (m >> 3)))
> +#define SYS_TRCAUTHSTATUS		sys_reg(2, 1, 7, 14, 6)
> +#define SYS_TRCAUXCTLR			sys_reg(2, 1, 0, 6, 0)
> +#define SYS_TRCBBCTLR			sys_reg(2, 1, 0, 15, 0)
> +#define SYS_TRCCCCTLR			sys_reg(2, 1, 0, 14, 0)
> +#define SYS_TRCCIDCCTLR0		sys_reg(2, 1, 3, 0, 2)
> +#define SYS_TRCCIDCCTLR1		sys_reg(2, 1, 3, 1, 2)
> +#define SYS_TRCCIDCVR(m)		sys_reg(2, 1, 3, ((m & 7) << 1), 0)
> +#define SYS_TRCCLAIMCLR			sys_reg(2, 1, 7, 9, 6)
> +#define SYS_TRCCLAIMSET			sys_reg(2, 1, 7, 8, 6)
> +#define SYS_TRCCNTCTLR(m)		sys_reg(2, 1, 0, (4 | (m & 3)), 5)
> +#define SYS_TRCCNTRLDVR(m)		sys_reg(2, 1, 0, (0 | (m & 3)), 5)
> +#define SYS_TRCCNTVR(m)			sys_reg(2, 1, 0, (8 | (m & 3)), 5)
> +#define SYS_TRCCONFIGR			sys_reg(2, 1, 0, 4, 0)
> +#define SYS_TRCDEVARCH			sys_reg(2, 1, 7, 15, 6)
> +#define SYS_TRCDEVID			sys_reg(2, 1, 7, 2, 7)
> +#define SYS_TRCEVENTCTL0R		sys_reg(2, 1, 0, 8, 0)
> +#define SYS_TRCEVENTCTL1R		sys_reg(2, 1, 0, 9, 0)
> +#define SYS_TRCEXTINSELR(m)		sys_reg(2, 1, 0, (8 | (m & 3)), 4)
> +#define SYS_TRCIDR0			sys_reg(2, 1, 0, 8, 7)
> +#define SYS_TRCIDR10			sys_reg(2, 1, 0, 2, 6)
> +#define SYS_TRCIDR11			sys_reg(2, 1, 0, 3, 6)
> +#define SYS_TRCIDR12			sys_reg(2, 1, 0, 4, 6)
> +#define SYS_TRCIDR13			sys_reg(2, 1, 0, 5, 6)
> +#define SYS_TRCIDR1			sys_reg(2, 1, 0, 9, 7)
> +#define SYS_TRCIDR2			sys_reg(2, 1, 0, 10, 7)
> +#define SYS_TRCIDR3			sys_reg(2, 1, 0, 11, 7)
> +#define SYS_TRCIDR4			sys_reg(2, 1, 0, 12, 7)
> +#define SYS_TRCIDR5			sys_reg(2, 1, 0, 13, 7)
> +#define SYS_TRCIDR6			sys_reg(2, 1, 0, 14, 7)
> +#define SYS_TRCIDR7			sys_reg(2, 1, 0, 15, 7)
> +#define SYS_TRCIDR8			sys_reg(2, 1, 0, 0, 6)
> +#define SYS_TRCIDR9			sys_reg(2, 1, 0, 1, 6)
> +#define SYS_TRCIMSPEC(m)		sys_reg(2, 1, 0, (m & 7), 7)
> +#define SYS_TRCITEEDCR			sys_reg(2, 1, 0, 2, 1)
> +#define SYS_TRCOSLSR			sys_reg(2, 1, 1, 1, 4)
> +#define SYS_TRCPRGCTLR			sys_reg(2, 1, 0, 1, 0)
> +#define SYS_TRCQCTLR			sys_reg(2, 1, 0, 1, 1)
> +#define SYS_TRCRSCTLR(m)		sys_reg(2, 1, 1, (m & 15), (0 | (m >> 4)))
> +#define SYS_TRCRSR			sys_reg(2, 1, 0, 10, 0)
> +#define SYS_TRCSEQEVR(m)		sys_reg(2, 1, 0, (m & 3), 4)
> +#define SYS_TRCSEQRSTEVR		sys_reg(2, 1, 0, 6, 4)
> +#define SYS_TRCSEQSTR			sys_reg(2, 1, 0, 7, 4)
> +#define SYS_TRCSSCCR(m)			sys_reg(2, 1, 1, (m & 7), 2)
> +#define SYS_TRCSSCSR(m)			sys_reg(2, 1, 1, (8 | (m & 7)), 2)
> +#define SYS_TRCSSPCICR(m)		sys_reg(2, 1, 1, (m & 7), 3)
> +#define SYS_TRCSTALLCTLR		sys_reg(2, 1, 0, 11, 0)
> +#define SYS_TRCSTATR			sys_reg(2, 1, 0, 3, 0)
> +#define SYS_TRCSYNCPR			sys_reg(2, 1, 0, 13, 0)
> +#define SYS_TRCTRACEIDR			sys_reg(2, 1, 0, 0, 1)
> +#define SYS_TRCTSCTLR			sys_reg(2, 1, 0, 12, 0)
> +#define SYS_TRCVICTLR			sys_reg(2, 1, 0, 0, 2)
> +#define SYS_TRCVIIECTLR			sys_reg(2, 1, 0, 1, 2)
> +#define SYS_TRCVIPCSSCTLR		sys_reg(2, 1, 0, 3, 2)
> +#define SYS_TRCVISSCTLR			sys_reg(2, 1, 0, 2, 2)
> +#define SYS_TRCVMIDCCTLR0		sys_reg(2, 1, 3, 2, 2)
> +#define SYS_TRCVMIDCCTLR1		sys_reg(2, 1, 3, 3, 2)
> +#define SYS_TRCVMIDCVR(m)		sys_reg(2, 1, 3, ((m & 7) << 1), 1)
> +
> +/* ETM */
> +#define SYS_TRCOSLAR			sys_reg(2, 1, 1, 0, 4)
> +
> +#define SYS_BRBCR_EL2			sys_reg(2, 4, 9, 0, 0)
> +
>   #define SYS_MIDR_EL1			sys_reg(3, 0, 0, 0, 0)
>   #define SYS_MPIDR_EL1			sys_reg(3, 0, 0, 0, 5)
>   #define SYS_REVIDR_EL1			sys_reg(3, 0, 0, 0, 6)
> @@ -202,8 +312,13 @@
>   #define SYS_ERXCTLR_EL1			sys_reg(3, 0, 5, 4, 1)
>   #define SYS_ERXSTATUS_EL1		sys_reg(3, 0, 5, 4, 2)
>   #define SYS_ERXADDR_EL1			sys_reg(3, 0, 5, 4, 3)
> +#define SYS_ERXPFGF_EL1			sys_reg(3, 0, 5, 4, 4)
> +#define SYS_ERXPFGCTL_EL1		sys_reg(3, 0, 5, 4, 5)
> +#define SYS_ERXPFGCDN_EL1		sys_reg(3, 0, 5, 4, 6)
>   #define SYS_ERXMISC0_EL1		sys_reg(3, 0, 5, 5, 0)
>   #define SYS_ERXMISC1_EL1		sys_reg(3, 0, 5, 5, 1)
> +#define SYS_ERXMISC2_EL1		sys_reg(3, 0, 5, 5, 2)
> +#define SYS_ERXMISC3_EL1		sys_reg(3, 0, 5, 5, 3)
>   #define SYS_TFSR_EL1			sys_reg(3, 0, 5, 6, 0)
>   #define SYS_TFSRE0_EL1			sys_reg(3, 0, 5, 6, 1)
>   
> @@ -274,6 +389,8 @@
>   #define SYS_ICC_IGRPEN0_EL1		sys_reg(3, 0, 12, 12, 6)
>   #define SYS_ICC_IGRPEN1_EL1		sys_reg(3, 0, 12, 12, 7)
>   
> +#define SYS_ACCDATA_EL1			sys_reg(3, 0, 13, 0, 5)
> +
>   #define SYS_CNTKCTL_EL1			sys_reg(3, 0, 14, 1, 0)
>   
>   #define SYS_AIDR_EL1			sys_reg(3, 1, 0, 0, 7)
> @@ -369,6 +486,7 @@
>   
>   #define SYS_SCTLR_EL2			sys_reg(3, 4, 1, 0, 0)
>   #define SYS_ACTLR_EL2			sys_reg(3, 4, 1, 0, 1)
> +#define SYS_SCTLR2_EL2			sys_reg(3, 4, 1, 0, 3)
>   #define SYS_HCR_EL2			sys_reg(3, 4, 1, 1, 0)
>   #define SYS_MDCR_EL2			sys_reg(3, 4, 1, 1, 1)
>   #define SYS_CPTR_EL2			sys_reg(3, 4, 1, 1, 2)
> @@ -382,12 +500,15 @@
>   #define SYS_VTCR_EL2			sys_reg(3, 4, 2, 1, 2)
>   
>   #define SYS_TRFCR_EL2			sys_reg(3, 4, 1, 2, 1)
> -#define SYS_HDFGRTR_EL2			sys_reg(3, 4, 3, 1, 4)
> -#define SYS_HDFGWTR_EL2			sys_reg(3, 4, 3, 1, 5)
> +#define SYS_VNCR_EL2			sys_reg(3, 4, 2, 2, 0)
>   #define SYS_HAFGRTR_EL2			sys_reg(3, 4, 3, 1, 6)
>   #define SYS_SPSR_EL2			sys_reg(3, 4, 4, 0, 0)
>   #define SYS_ELR_EL2			sys_reg(3, 4, 4, 0, 1)
>   #define SYS_SP_EL1			sys_reg(3, 4, 4, 1, 0)
> +#define SYS_SPSR_irq			sys_reg(3, 4, 4, 3, 0)
> +#define SYS_SPSR_abt			sys_reg(3, 4, 4, 3, 1)
> +#define SYS_SPSR_und			sys_reg(3, 4, 4, 3, 2)
> +#define SYS_SPSR_fiq			sys_reg(3, 4, 4, 3, 3)
>   #define SYS_IFSR32_EL2			sys_reg(3, 4, 5, 0, 1)
>   #define SYS_AFSR0_EL2			sys_reg(3, 4, 5, 1, 0)
>   #define SYS_AFSR1_EL2			sys_reg(3, 4, 5, 1, 1)
> @@ -401,6 +522,18 @@
>   
>   #define SYS_MAIR_EL2			sys_reg(3, 4, 10, 2, 0)
>   #define SYS_AMAIR_EL2			sys_reg(3, 4, 10, 3, 0)
> +#define SYS_MPAMHCR_EL2			sys_reg(3, 4, 10, 4, 0)
> +#define SYS_MPAMVPMV_EL2		sys_reg(3, 4, 10, 4, 1)
> +#define SYS_MPAM2_EL2			sys_reg(3, 4, 10, 5, 0)
> +#define __SYS__MPAMVPMx_EL2(x)		sys_reg(3, 4, 10, 6, x)
> +#define SYS_MPAMVPM0_EL2		__SYS__MPAMVPMx_EL2(0)
> +#define SYS_MPAMVPM1_EL2		__SYS__MPAMVPMx_EL2(1)
> +#define SYS_MPAMVPM2_EL2		__SYS__MPAMVPMx_EL2(2)
> +#define SYS_MPAMVPM3_EL2		__SYS__MPAMVPMx_EL2(3)
> +#define SYS_MPAMVPM4_EL2		__SYS__MPAMVPMx_EL2(4)
> +#define SYS_MPAMVPM5_EL2		__SYS__MPAMVPMx_EL2(5)
> +#define SYS_MPAMVPM6_EL2		__SYS__MPAMVPMx_EL2(6)
> +#define SYS_MPAMVPM7_EL2		__SYS__MPAMVPMx_EL2(7)
>   
>   #define SYS_VBAR_EL2			sys_reg(3, 4, 12, 0, 0)
>   #define SYS_RVBAR_EL2			sys_reg(3, 4, 12, 0, 1)
> @@ -449,24 +582,49 @@
>   
>   #define SYS_CONTEXTIDR_EL2		sys_reg(3, 4, 13, 0, 1)
>   #define SYS_TPIDR_EL2			sys_reg(3, 4, 13, 0, 2)
> +#define SYS_SCXTNUM_EL2			sys_reg(3, 4, 13, 0, 7)
> +
> +#define __AMEV_op2(m)			(m & 0x7)
> +#define __AMEV_CRm(n, m)		(n | ((m & 0x8) >> 3))
> +#define __SYS__AMEVCNTVOFF0n_EL2(m)	sys_reg(3, 4, 13, __AMEV_CRm(0x8, m), __AMEV_op2(m))
> +#define SYS_AMEVCNTVOFF0n_EL2(m)	__SYS__AMEVCNTVOFF0n_EL2(m)
> +#define __SYS__AMEVCNTVOFF1n_EL2(m)	sys_reg(3, 4, 13, __AMEV_CRm(0xA, m), __AMEV_op2(m))
> +#define SYS_AMEVCNTVOFF1n_EL2(m)	__SYS__AMEVCNTVOFF1n_EL2(m)
>   
>   #define SYS_CNTVOFF_EL2			sys_reg(3, 4, 14, 0, 3)
>   #define SYS_CNTHCTL_EL2			sys_reg(3, 4, 14, 1, 0)
> +#define SYS_CNTHP_TVAL_EL2		sys_reg(3, 4, 14, 2, 0)
> +#define SYS_CNTHP_CTL_EL2		sys_reg(3, 4, 14, 2, 1)
> +#define SYS_CNTHP_CVAL_EL2		sys_reg(3, 4, 14, 2, 2)
> +#define SYS_CNTHV_TVAL_EL2		sys_reg(3, 4, 14, 3, 0)
> +#define SYS_CNTHV_CTL_EL2		sys_reg(3, 4, 14, 3, 1)
> +#define SYS_CNTHV_CVAL_EL2		sys_reg(3, 4, 14, 3, 2)
>   
>   /* VHE encodings for architectural EL0/1 system registers */
> +#define SYS_BRBCR_EL12			sys_reg(2, 5, 9, 0, 0)
>   #define SYS_SCTLR_EL12			sys_reg(3, 5, 1, 0, 0)
> +#define SYS_CPACR_EL12			sys_reg(3, 5, 1, 0, 2)
> +#define SYS_SCTLR2_EL12			sys_reg(3, 5, 1, 0, 3)
> +#define SYS_ZCR_EL12			sys_reg(3, 5, 1, 2, 0)
> +#define SYS_TRFCR_EL12			sys_reg(3, 5, 1, 2, 1)
> +#define SYS_SMCR_EL12			sys_reg(3, 5, 1, 2, 6)
>   #define SYS_TTBR0_EL12			sys_reg(3, 5, 2, 0, 0)
>   #define SYS_TTBR1_EL12			sys_reg(3, 5, 2, 0, 1)
>   #define SYS_TCR_EL12			sys_reg(3, 5, 2, 0, 2)
> +#define SYS_TCR2_EL12			sys_reg(3, 5, 2, 0, 3)
>   #define SYS_SPSR_EL12			sys_reg(3, 5, 4, 0, 0)
>   #define SYS_ELR_EL12			sys_reg(3, 5, 4, 0, 1)
>   #define SYS_AFSR0_EL12			sys_reg(3, 5, 5, 1, 0)
>   #define SYS_AFSR1_EL12			sys_reg(3, 5, 5, 1, 1)
>   #define SYS_ESR_EL12			sys_reg(3, 5, 5, 2, 0)
>   #define SYS_TFSR_EL12			sys_reg(3, 5, 5, 6, 0)
> +#define SYS_FAR_EL12			sys_reg(3, 5, 6, 0, 0)
> +#define SYS_PMSCR_EL12			sys_reg(3, 5, 9, 9, 0)
>   #define SYS_MAIR_EL12			sys_reg(3, 5, 10, 2, 0)
>   #define SYS_AMAIR_EL12			sys_reg(3, 5, 10, 3, 0)
>   #define SYS_VBAR_EL12			sys_reg(3, 5, 12, 0, 0)
> +#define SYS_CONTEXTIDR_EL12		sys_reg(3, 5, 13, 0, 1)
> +#define SYS_SCXTNUM_EL12		sys_reg(3, 5, 13, 0, 7)
>   #define SYS_CNTKCTL_EL12		sys_reg(3, 5, 14, 1, 0)
>   #define SYS_CNTP_TVAL_EL02		sys_reg(3, 5, 14, 2, 0)
>   #define SYS_CNTP_CTL_EL02		sys_reg(3, 5, 14, 2, 1)
> @@ -477,6 +635,165 @@
>   
>   #define SYS_SP_EL2			sys_reg(3, 6,  4, 1, 0)
>   
> +/* AT instructions */
> +#define AT_Op0 1
> +#define AT_CRn 7
> +
> +#define OP_AT_S1E1R	sys_insn(AT_Op0, 0, AT_CRn, 8, 0)
> +#define OP_AT_S1E1W	sys_insn(AT_Op0, 0, AT_CRn, 8, 1)
> +#define OP_AT_S1E0R	sys_insn(AT_Op0, 0, AT_CRn, 8, 2)
> +#define OP_AT_S1E0W	sys_insn(AT_Op0, 0, AT_CRn, 8, 3)
> +#define OP_AT_S1E1RP	sys_insn(AT_Op0, 0, AT_CRn, 9, 0)
> +#define OP_AT_S1E1WP	sys_insn(AT_Op0, 0, AT_CRn, 9, 1)
> +#define OP_AT_S1E1A	sys_insn(AT_Op0, 0, AT_CRn, 9, 2)
> +#define OP_AT_S1E2R	sys_insn(AT_Op0, 4, AT_CRn, 8, 0)
> +#define OP_AT_S1E2W	sys_insn(AT_Op0, 4, AT_CRn, 8, 1)
> +#define OP_AT_S12E1R	sys_insn(AT_Op0, 4, AT_CRn, 8, 4)
> +#define OP_AT_S12E1W	sys_insn(AT_Op0, 4, AT_CRn, 8, 5)
> +#define OP_AT_S12E0R	sys_insn(AT_Op0, 4, AT_CRn, 8, 6)
> +#define OP_AT_S12E0W	sys_insn(AT_Op0, 4, AT_CRn, 8, 7)
> +
> +/* TLBI instructions */
> +#define OP_TLBI_VMALLE1OS		sys_insn(1, 0, 8, 1, 0)
> +#define OP_TLBI_VAE1OS			sys_insn(1, 0, 8, 1, 1)
> +#define OP_TLBI_ASIDE1OS		sys_insn(1, 0, 8, 1, 2)
> +#define OP_TLBI_VAAE1OS			sys_insn(1, 0, 8, 1, 3)
> +#define OP_TLBI_VALE1OS			sys_insn(1, 0, 8, 1, 5)
> +#define OP_TLBI_VAALE1OS		sys_insn(1, 0, 8, 1, 7)
> +#define OP_TLBI_RVAE1IS			sys_insn(1, 0, 8, 2, 1)
> +#define OP_TLBI_RVAAE1IS		sys_insn(1, 0, 8, 2, 3)
> +#define OP_TLBI_RVALE1IS		sys_insn(1, 0, 8, 2, 5)
> +#define OP_TLBI_RVAALE1IS		sys_insn(1, 0, 8, 2, 7)
> +#define OP_TLBI_VMALLE1IS		sys_insn(1, 0, 8, 3, 0)
> +#define OP_TLBI_VAE1IS			sys_insn(1, 0, 8, 3, 1)
> +#define OP_TLBI_ASIDE1IS		sys_insn(1, 0, 8, 3, 2)
> +#define OP_TLBI_VAAE1IS			sys_insn(1, 0, 8, 3, 3)
> +#define OP_TLBI_VALE1IS			sys_insn(1, 0, 8, 3, 5)
> +#define OP_TLBI_VAALE1IS		sys_insn(1, 0, 8, 3, 7)
> +#define OP_TLBI_RVAE1OS			sys_insn(1, 0, 8, 5, 1)
> +#define OP_TLBI_RVAAE1OS		sys_insn(1, 0, 8, 5, 3)
> +#define OP_TLBI_RVALE1OS		sys_insn(1, 0, 8, 5, 5)
> +#define OP_TLBI_RVAALE1OS		sys_insn(1, 0, 8, 5, 7)
> +#define OP_TLBI_RVAE1			sys_insn(1, 0, 8, 6, 1)
> +#define OP_TLBI_RVAAE1			sys_insn(1, 0, 8, 6, 3)
> +#define OP_TLBI_RVALE1			sys_insn(1, 0, 8, 6, 5)
> +#define OP_TLBI_RVAALE1			sys_insn(1, 0, 8, 6, 7)
> +#define OP_TLBI_VMALLE1			sys_insn(1, 0, 8, 7, 0)
> +#define OP_TLBI_VAE1			sys_insn(1, 0, 8, 7, 1)
> +#define OP_TLBI_ASIDE1			sys_insn(1, 0, 8, 7, 2)
> +#define OP_TLBI_VAAE1			sys_insn(1, 0, 8, 7, 3)
> +#define OP_TLBI_VALE1			sys_insn(1, 0, 8, 7, 5)
> +#define OP_TLBI_VAALE1			sys_insn(1, 0, 8, 7, 7)
> +#define OP_TLBI_VMALLE1OSNXS		sys_insn(1, 0, 9, 1, 0)
> +#define OP_TLBI_VAE1OSNXS		sys_insn(1, 0, 9, 1, 1)
> +#define OP_TLBI_ASIDE1OSNXS		sys_insn(1, 0, 9, 1, 2)
> +#define OP_TLBI_VAAE1OSNXS		sys_insn(1, 0, 9, 1, 3)
> +#define OP_TLBI_VALE1OSNXS		sys_insn(1, 0, 9, 1, 5)
> +#define OP_TLBI_VAALE1OSNXS		sys_insn(1, 0, 9, 1, 7)
> +#define OP_TLBI_RVAE1ISNXS		sys_insn(1, 0, 9, 2, 1)
> +#define OP_TLBI_RVAAE1ISNXS		sys_insn(1, 0, 9, 2, 3)
> +#define OP_TLBI_RVALE1ISNXS		sys_insn(1, 0, 9, 2, 5)
> +#define OP_TLBI_RVAALE1ISNXS		sys_insn(1, 0, 9, 2, 7)
> +#define OP_TLBI_VMALLE1ISNXS		sys_insn(1, 0, 9, 3, 0)
> +#define OP_TLBI_VAE1ISNXS		sys_insn(1, 0, 9, 3, 1)
> +#define OP_TLBI_ASIDE1ISNXS		sys_insn(1, 0, 9, 3, 2)
> +#define OP_TLBI_VAAE1ISNXS		sys_insn(1, 0, 9, 3, 3)
> +#define OP_TLBI_VALE1ISNXS		sys_insn(1, 0, 9, 3, 5)
> +#define OP_TLBI_VAALE1ISNXS		sys_insn(1, 0, 9, 3, 7)
> +#define OP_TLBI_RVAE1OSNXS		sys_insn(1, 0, 9, 5, 1)
> +#define OP_TLBI_RVAAE1OSNXS		sys_insn(1, 0, 9, 5, 3)
> +#define OP_TLBI_RVALE1OSNXS		sys_insn(1, 0, 9, 5, 5)
> +#define OP_TLBI_RVAALE1OSNXS		sys_insn(1, 0, 9, 5, 7)
> +#define OP_TLBI_RVAE1NXS		sys_insn(1, 0, 9, 6, 1)
> +#define OP_TLBI_RVAAE1NXS		sys_insn(1, 0, 9, 6, 3)
> +#define OP_TLBI_RVALE1NXS		sys_insn(1, 0, 9, 6, 5)
> +#define OP_TLBI_RVAALE1NXS		sys_insn(1, 0, 9, 6, 7)
> +#define OP_TLBI_VMALLE1NXS		sys_insn(1, 0, 9, 7, 0)
> +#define OP_TLBI_VAE1NXS			sys_insn(1, 0, 9, 7, 1)
> +#define OP_TLBI_ASIDE1NXS		sys_insn(1, 0, 9, 7, 2)
> +#define OP_TLBI_VAAE1NXS		sys_insn(1, 0, 9, 7, 3)
> +#define OP_TLBI_VALE1NXS		sys_insn(1, 0, 9, 7, 5)
> +#define OP_TLBI_VAALE1NXS		sys_insn(1, 0, 9, 7, 7)
> +#define OP_TLBI_IPAS2E1IS		sys_insn(1, 4, 8, 0, 1)
> +#define OP_TLBI_RIPAS2E1IS		sys_insn(1, 4, 8, 0, 2)
> +#define OP_TLBI_IPAS2LE1IS		sys_insn(1, 4, 8, 0, 5)
> +#define OP_TLBI_RIPAS2LE1IS		sys_insn(1, 4, 8, 0, 6)
> +#define OP_TLBI_ALLE2OS			sys_insn(1, 4, 8, 1, 0)
> +#define OP_TLBI_VAE2OS			sys_insn(1, 4, 8, 1, 1)
> +#define OP_TLBI_ALLE1OS			sys_insn(1, 4, 8, 1, 4)
> +#define OP_TLBI_VALE2OS			sys_insn(1, 4, 8, 1, 5)
> +#define OP_TLBI_VMALLS12E1OS		sys_insn(1, 4, 8, 1, 6)
> +#define OP_TLBI_RVAE2IS			sys_insn(1, 4, 8, 2, 1)
> +#define OP_TLBI_RVALE2IS		sys_insn(1, 4, 8, 2, 5)
> +#define OP_TLBI_ALLE2IS			sys_insn(1, 4, 8, 3, 0)
> +#define OP_TLBI_VAE2IS			sys_insn(1, 4, 8, 3, 1)
> +#define OP_TLBI_ALLE1IS			sys_insn(1, 4, 8, 3, 4)
> +#define OP_TLBI_VALE2IS			sys_insn(1, 4, 8, 3, 5)
> +#define OP_TLBI_VMALLS12E1IS		sys_insn(1, 4, 8, 3, 6)
> +#define OP_TLBI_IPAS2E1OS		sys_insn(1, 4, 8, 4, 0)
> +#define OP_TLBI_IPAS2E1			sys_insn(1, 4, 8, 4, 1)
> +#define OP_TLBI_RIPAS2E1		sys_insn(1, 4, 8, 4, 2)
> +#define OP_TLBI_RIPAS2E1OS		sys_insn(1, 4, 8, 4, 3)
> +#define OP_TLBI_IPAS2LE1OS		sys_insn(1, 4, 8, 4, 4)
> +#define OP_TLBI_IPAS2LE1		sys_insn(1, 4, 8, 4, 5)
> +#define OP_TLBI_RIPAS2LE1		sys_insn(1, 4, 8, 4, 6)
> +#define OP_TLBI_RIPAS2LE1OS		sys_insn(1, 4, 8, 4, 7)
> +#define OP_TLBI_RVAE2OS			sys_insn(1, 4, 8, 5, 1)
> +#define OP_TLBI_RVALE2OS		sys_insn(1, 4, 8, 5, 5)
> +#define OP_TLBI_RVAE2			sys_insn(1, 4, 8, 6, 1)
> +#define OP_TLBI_RVALE2			sys_insn(1, 4, 8, 6, 5)
> +#define OP_TLBI_ALLE2			sys_insn(1, 4, 8, 7, 0)
> +#define OP_TLBI_VAE2			sys_insn(1, 4, 8, 7, 1)
> +#define OP_TLBI_ALLE1			sys_insn(1, 4, 8, 7, 4)
> +#define OP_TLBI_VALE2			sys_insn(1, 4, 8, 7, 5)
> +#define OP_TLBI_VMALLS12E1		sys_insn(1, 4, 8, 7, 6)
> +#define OP_TLBI_IPAS2E1ISNXS		sys_insn(1, 4, 9, 0, 1)
> +#define OP_TLBI_RIPAS2E1ISNXS		sys_insn(1, 4, 9, 0, 2)
> +#define OP_TLBI_IPAS2LE1ISNXS		sys_insn(1, 4, 9, 0, 5)
> +#define OP_TLBI_RIPAS2LE1ISNXS		sys_insn(1, 4, 9, 0, 6)
> +#define OP_TLBI_ALLE2OSNXS		sys_insn(1, 4, 9, 1, 0)
> +#define OP_TLBI_VAE2OSNXS		sys_insn(1, 4, 9, 1, 1)
> +#define OP_TLBI_ALLE1OSNXS		sys_insn(1, 4, 9, 1, 4)
> +#define OP_TLBI_VALE2OSNXS		sys_insn(1, 4, 9, 1, 5)
> +#define OP_TLBI_VMALLS12E1OSNXS		sys_insn(1, 4, 9, 1, 6)
> +#define OP_TLBI_RVAE2ISNXS		sys_insn(1, 4, 9, 2, 1)
> +#define OP_TLBI_RVALE2ISNXS		sys_insn(1, 4, 9, 2, 5)
> +#define OP_TLBI_ALLE2ISNXS		sys_insn(1, 4, 9, 3, 0)
> +#define OP_TLBI_VAE2ISNXS		sys_insn(1, 4, 9, 3, 1)
> +#define OP_TLBI_ALLE1ISNXS		sys_insn(1, 4, 9, 3, 4)
> +#define OP_TLBI_VALE2ISNXS		sys_insn(1, 4, 9, 3, 5)
> +#define OP_TLBI_VMALLS12E1ISNXS		sys_insn(1, 4, 9, 3, 6)
> +#define OP_TLBI_IPAS2E1OSNXS		sys_insn(1, 4, 9, 4, 0)
> +#define OP_TLBI_IPAS2E1NXS		sys_insn(1, 4, 9, 4, 1)
> +#define OP_TLBI_RIPAS2E1NXS		sys_insn(1, 4, 9, 4, 2)
> +#define OP_TLBI_RIPAS2E1OSNXS		sys_insn(1, 4, 9, 4, 3)
> +#define OP_TLBI_IPAS2LE1OSNXS		sys_insn(1, 4, 9, 4, 4)
> +#define OP_TLBI_IPAS2LE1NXS		sys_insn(1, 4, 9, 4, 5)
> +#define OP_TLBI_RIPAS2LE1NXS		sys_insn(1, 4, 9, 4, 6)
> +#define OP_TLBI_RIPAS2LE1OSNXS		sys_insn(1, 4, 9, 4, 7)
> +#define OP_TLBI_RVAE2OSNXS		sys_insn(1, 4, 9, 5, 1)
> +#define OP_TLBI_RVALE2OSNXS		sys_insn(1, 4, 9, 5, 5)
> +#define OP_TLBI_RVAE2NXS		sys_insn(1, 4, 9, 6, 1)
> +#define OP_TLBI_RVALE2NXS		sys_insn(1, 4, 9, 6, 5)
> +#define OP_TLBI_ALLE2NXS		sys_insn(1, 4, 9, 7, 0)
> +#define OP_TLBI_VAE2NXS			sys_insn(1, 4, 9, 7, 1)
> +#define OP_TLBI_ALLE1NXS		sys_insn(1, 4, 9, 7, 4)
> +#define OP_TLBI_VALE2NXS		sys_insn(1, 4, 9, 7, 5)
> +#define OP_TLBI_VMALLS12E1NXS		sys_insn(1, 4, 9, 7, 6)
> +
> +/* Misc instructions */
> +#define OP_GCSPUSHX			sys_insn(1, 0, 7, 7, 4)
> +#define OP_GCSPOPCX			sys_insn(1, 0, 7, 7, 5)
> +#define OP_GCSPOPX			sys_insn(1, 0, 7, 7, 6)
> +#define OP_GCSPUSHM			sys_insn(1, 3, 7, 7, 0)
> +
> +#define OP_BRB_IALL			sys_insn(1, 1, 7, 2, 4)
> +#define OP_BRB_INJ			sys_insn(1, 1, 7, 2, 5)
> +#define OP_CFP_RCTX			sys_insn(1, 3, 7, 3, 4)
> +#define OP_DVP_RCTX			sys_insn(1, 3, 7, 3, 5)
> +#define OP_COSP_RCTX			sys_insn(1, 3, 7, 3, 6)
> +#define OP_CPP_RCTX			sys_insn(1, 3, 7, 3, 7)
> +
>   /* Common SCTLR_ELx flags. */
>   #define SCTLR_ELx_ENTP2	(BIT(60))
>   #define SCTLR_ELx_DSSBS	(BIT(44))
> @@ -561,10 +878,12 @@
>   
>   /* id_aa64mmfr0 */
>   #define ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED_MIN	0x0
> +#define ID_AA64MMFR0_EL1_TGRAN4_LPA2		ID_AA64MMFR0_EL1_TGRAN4_52_BIT
>   #define ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED_MAX	0x7
>   #define ID_AA64MMFR0_EL1_TGRAN64_SUPPORTED_MIN	0x0
>   #define ID_AA64MMFR0_EL1_TGRAN64_SUPPORTED_MAX	0x7
>   #define ID_AA64MMFR0_EL1_TGRAN16_SUPPORTED_MIN	0x1
> +#define ID_AA64MMFR0_EL1_TGRAN16_LPA2		ID_AA64MMFR0_EL1_TGRAN16_52_BIT
>   #define ID_AA64MMFR0_EL1_TGRAN16_SUPPORTED_MAX	0xf
>   
>   #define ARM64_MIN_PARANGE_BITS		32
> @@ -572,6 +891,7 @@
>   #define ID_AA64MMFR0_EL1_TGRAN_2_SUPPORTED_DEFAULT	0x0
>   #define ID_AA64MMFR0_EL1_TGRAN_2_SUPPORTED_NONE		0x1
>   #define ID_AA64MMFR0_EL1_TGRAN_2_SUPPORTED_MIN		0x2
> +#define ID_AA64MMFR0_EL1_TGRAN_2_SUPPORTED_LPA2		0x3
>   #define ID_AA64MMFR0_EL1_TGRAN_2_SUPPORTED_MAX		0x7
>   
>   #ifdef CONFIG_ARM64_PA_BITS_52
> @@ -582,11 +902,13 @@
>   
>   #if defined(CONFIG_ARM64_4K_PAGES)
>   #define ID_AA64MMFR0_EL1_TGRAN_SHIFT		ID_AA64MMFR0_EL1_TGRAN4_SHIFT
> +#define ID_AA64MMFR0_EL1_TGRAN_LPA2		ID_AA64MMFR0_EL1_TGRAN4_52_BIT
>   #define ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MIN	ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED_MIN
>   #define ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MAX	ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED_MAX
>   #define ID_AA64MMFR0_EL1_TGRAN_2_SHIFT		ID_AA64MMFR0_EL1_TGRAN4_2_SHIFT
>   #elif defined(CONFIG_ARM64_16K_PAGES)
>   #define ID_AA64MMFR0_EL1_TGRAN_SHIFT		ID_AA64MMFR0_EL1_TGRAN16_SHIFT
> +#define ID_AA64MMFR0_EL1_TGRAN_LPA2		ID_AA64MMFR0_EL1_TGRAN16_52_BIT
>   #define ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MIN	ID_AA64MMFR0_EL1_TGRAN16_SUPPORTED_MIN
>   #define ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MAX	ID_AA64MMFR0_EL1_TGRAN16_SUPPORTED_MAX
>   #define ID_AA64MMFR0_EL1_TGRAN_2_SHIFT		ID_AA64MMFR0_EL1_TGRAN16_2_SHIFT
> @@ -610,6 +932,19 @@
>   #define SYS_GCR_EL1_RRND	(BIT(16))
>   #define SYS_GCR_EL1_EXCL_MASK	0xffffUL
>   
> +#ifdef CONFIG_KASAN_HW_TAGS
> +/*
> + * KASAN always uses a whole byte for its tags. With CONFIG_KASAN_HW_TAGS it
> + * only uses tags in the range 0xF0-0xFF, which we map to MTE tags 0x0-0xF.
> + */
> +#define __MTE_TAG_MIN		(KASAN_TAG_MIN & 0xf)
> +#define __MTE_TAG_MAX		(KASAN_TAG_MAX & 0xf)
> +#define __MTE_TAG_INCL		GENMASK(__MTE_TAG_MAX, __MTE_TAG_MIN)
> +#define KERNEL_GCR_EL1_EXCL	(SYS_GCR_EL1_EXCL_MASK & ~__MTE_TAG_INCL)
> +#else
> +#define KERNEL_GCR_EL1_EXCL	SYS_GCR_EL1_EXCL_MASK
> +#endif
> +
>   #define KERNEL_GCR_EL1		(SYS_GCR_EL1_RRND | KERNEL_GCR_EL1_EXCL)
>   
>   /* RGSR_EL1 Definitions */
> @@ -716,6 +1051,19 @@
>   
>   #define PIRx_ELx_PERM(idx, perm)	((perm) << ((idx) * 4))
>   
> +/*
> + * Permission Overlay Extension (POE) permission encodings.
> + */
> +#define POE_NONE	UL(0x0)
> +#define POE_R		UL(0x1)
> +#define POE_X		UL(0x2)
> +#define POE_RX		UL(0x3)
> +#define POE_W		UL(0x4)
> +#define POE_RW		UL(0x5)
> +#define POE_XW		UL(0x6)
> +#define POE_RXW		UL(0x7)
> +#define POE_MASK	UL(0xf)
> +
>   #define ARM64_FEATURE_FIELD_BITS	4
>   
>   /* Defined for compatibility only, do not add new users. */
> @@ -789,15 +1137,21 @@
>   /*
>    * For registers without architectural names, or simply unsupported by
>    * GAS.
> + *
> + * __check_r forces warnings to be generated by the compiler when
> + * evaluating r which wouldn't normally happen due to being passed to
> + * the assembler via __stringify(r).
>    */
>   #define read_sysreg_s(r) ({						\
>   	u64 __val;							\
> +	u32 __maybe_unused __check_r = (u32)(r);			\
>   	asm volatile(__mrs_s("%0", r) : "=r" (__val));			\
>   	__val;								\
>   })
>   
>   #define write_sysreg_s(v, r) do {					\
>   	u64 __val = (u64)(v);						\
> +	u32 __maybe_unused __check_r = (u32)(r);			\
>   	asm volatile(__msr_s(r, "%x0") : : "rZ" (__val));		\
>   } while (0)
>   
> @@ -827,6 +1181,8 @@
>   	par;								\
>   })
>   
> +#define SYS_FIELD_VALUE(reg, field, val)	reg##_##field##_##val
> +
>   #define SYS_FIELD_GET(reg, field, val)		\
>   		 FIELD_GET(reg##_##field##_MASK, val)
>   
> @@ -834,7 +1190,8 @@
>   		 FIELD_PREP(reg##_##field##_MASK, val)
>   
>   #define SYS_FIELD_PREP_ENUM(reg, field, val)		\
> -		 FIELD_PREP(reg##_##field##_MASK, reg##_##field##_##val)
> +		 FIELD_PREP(reg##_##field##_MASK,	\
> +			    SYS_FIELD_VALUE(reg, field, val))
>   
>   #endif
>   
> diff --git a/tools/include/linux/kasan-tags.h b/tools/include/linux/kasan-tags.h
> new file mode 100644
> index 000000000000..4f85f562512c
> --- /dev/null
> +++ b/tools/include/linux/kasan-tags.h
> @@ -0,0 +1,15 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef _LINUX_KASAN_TAGS_H
> +#define _LINUX_KASAN_TAGS_H
> +
> +#define KASAN_TAG_KERNEL	0xFF /* native kernel pointers tag */
> +#define KASAN_TAG_INVALID	0xFE /* inaccessible memory tag */
> +#define KASAN_TAG_MAX		0xFD /* maximum value for random tags */
> +
> +#ifdef CONFIG_KASAN_HW_TAGS
> +#define KASAN_TAG_MIN		0xF0 /* minimum value for random tags */
> +#else
> +#define KASAN_TAG_MIN		0x00 /* minimum value for random tags */
> +#endif
> +
> +#endif /* LINUX_KASAN_TAGS_H */


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v5 5/7] arm64: KVM: Add interface to set guest value for TRFCR register
  2024-02-26  9:52       ` Suzuki K Poulose
@ 2024-02-26 11:36         ` James Clark
  0 siblings, 0 replies; 18+ messages in thread
From: James Clark @ 2024-02-26 11:36 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: James Morse, Zenghui Yu, Catalin Marinas, Will Deacon,
	Mike Leach, Alexander Shishkin, Anshuman Khandual, Miguel Luis,
	Joey Gouly, Ard Biesheuvel, Greg Kroah-Hartman, Arnd Bergmann,
	Helge Deller, Andrew Walbran, Vincent Donnefort, Ryan Roberts,
	Fuad Tabba, Jing Zhang, linux-kernel, coresight,
	linux-arm-kernel, kvmarm, maz, acme, oliver.upton, broonie



On 26/02/2024 09:52, Suzuki K Poulose wrote:
> On 23/02/2024 16:39, James Clark wrote:
>>
>>
>> On 23/02/2024 10:03, Suzuki K Poulose wrote:
>>> On 20/02/2024 10:09, James Clark wrote:
>>>> Add an interface for the Coresight driver to use to set the value of
>>>> the
>>>> TRFCR register for the guest. This register controls the exclude
>>>> settings for trace at different exception levels, and is used to honor
>>>> the exclude_host and exclude_guest parameters from the Perf session.
>>>> This will be used to later write TRFCR_EL1 on nVHE at guest switch. For
>>>> VHE, the host trace is controlled by TRFCR_EL2 and thus we can write to
>>>> the TRFCR_EL1 immediately. Because guest writes to the register are
>>>> trapped, the value will persist and can't be modified.
>>>>
>>>> Instead of adding a load of infrastructure to share the host's per-cpu
>>>> offsets with the hypervisor, just define the new storage as a NR_CPUS
>>>> array.
>>>>
>>>> Signed-off-by: James Clark <james.clark@arm.com>
>>>> ---
>>>>    arch/arm64/include/asm/kvm_host.h |  3 +++
>>>>    arch/arm64/kernel/image-vars.h    |  1 +
>>>>    arch/arm64/kvm/debug.c            | 26 ++++++++++++++++++++++++++
>>>>    3 files changed, 30 insertions(+)
>>>>
>>>> diff --git a/arch/arm64/include/asm/kvm_host.h
>>>> b/arch/arm64/include/asm/kvm_host.h
>>>> index 85b5477bd1b4..56b7f7eca195 100644
>>>> --- a/arch/arm64/include/asm/kvm_host.h
>>>> +++ b/arch/arm64/include/asm/kvm_host.h
>>>> @@ -509,6 +509,7 @@ struct kvm_host_psci_config {
>>>>        bool psci_0_1_cpu_off_implemented;
>>>>        bool psci_0_1_migrate_implemented;
>>>>    };
>>>> +extern u64 ____cacheline_aligned kvm_guest_trfcr[NR_CPUS];
>>>>      extern struct kvm_host_psci_config
>>>> kvm_nvhe_sym(kvm_host_psci_config);
>>>>    #define kvm_host_psci_config CHOOSE_NVHE_SYM(kvm_host_psci_config)
>>>> @@ -1174,6 +1175,7 @@ void kvm_arch_vcpu_put_debug_state_flags(struct
>>>> kvm_vcpu *vcpu);
>>>>    void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr);
>>>>    void kvm_clr_pmu_events(u32 clr);
>>>>    bool kvm_set_pmuserenr(u64 val);
>>>> +void kvm_etm_set_guest_trfcr(u64 trfcr_guest);
>>>>    #else
>>>>    static inline void kvm_set_pmu_events(u32 set, struct
>>>> perf_event_attr *attr) {}
>>>>    static inline void kvm_clr_pmu_events(u32 clr) {}
>>>> @@ -1181,6 +1183,7 @@ static inline bool kvm_set_pmuserenr(u64 val)
>>>>    {
>>>>        return false;
>>>>    }
>>>> +static inline void kvm_etm_set_guest_trfcr(u64 trfcr_guest) {}
>>>>    #endif
>>>>      void kvm_vcpu_load_vhe(struct kvm_vcpu *vcpu);
>>>> diff --git a/arch/arm64/kernel/image-vars.h
>>>> b/arch/arm64/kernel/image-vars.h
>>>> index 5e4dc72ab1bd..a451e4f10804 100644
>>>> --- a/arch/arm64/kernel/image-vars.h
>>>> +++ b/arch/arm64/kernel/image-vars.h
>>>> @@ -59,6 +59,7 @@ KVM_NVHE_ALIAS(alt_cb_patch_nops);
>>>>      /* Global kernel state accessed by nVHE hyp code. */
>>>>    KVM_NVHE_ALIAS(kvm_vgic_global_state);
>>>> +KVM_NVHE_ALIAS(kvm_guest_trfcr);
>>>>      /* Kernel symbols used to call panic() from nVHE hyp code (via
>>>> ERET). */
>>>>    KVM_NVHE_ALIAS(nvhe_hyp_panic_handler);
>>>> diff --git a/arch/arm64/kvm/debug.c b/arch/arm64/kvm/debug.c
>>>> index 49a13e72ddd2..c8d936ce6e2b 100644
>>>> --- a/arch/arm64/kvm/debug.c
>>>> +++ b/arch/arm64/kvm/debug.c
>>>> @@ -22,6 +22,7 @@
>>>>                    DBG_MDSCR_MDE)
>>>>      static DEFINE_PER_CPU(u64, mdcr_el2);
>>>> +u64 ____cacheline_aligned kvm_guest_trfcr[NR_CPUS];
>>>>      /*
>>>>     * save/restore_guest_debug_regs
>>>> @@ -359,3 +360,28 @@ void kvm_arch_vcpu_put_debug_state_flags(struct
>>>> kvm_vcpu *vcpu)
>>>>        vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE_TRBE);
>>>>        vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE_TRFCR);
>>>>    }
>>>> +
>>>> +/*
>>>> + * Interface for the Coresight driver to use to set the value of the
>>>> TRFCR
>>>> + * register for the guest. This register controls the exclude
>>>> settings for trace
>>>> + * at different exception levels, and is used to honor the
>>>> exclude_host and
>>>> + * exclude_guest parameters from the Perf session.
>>>> + *
>>>> + * This will be used to later write TRFCR_EL1 on nVHE at guest
>>>> switch. For VHE,
>>>> + * the host trace is controlled by TRFCR_EL2 and thus we can write to
>>>> the
>>>> + * TRFCR_EL1 immediately. Because guest writes to the register are
>>>> trapped, the
>>>> + * value will persist and can't be modified. For pKVM,
>>>> kvm_guest_trfcr can't
>>>> + * be read by the hypervisor, so don't bother writing it.
>>>> + */
>>>> +void kvm_etm_set_guest_trfcr(u64 trfcr_guest)
>>>> +{
>>>> +    if
>>>> (WARN_ON_ONCE(!cpuid_feature_extract_unsigned_field(read_sysreg(id_aa64dfr0_el1),
>>>> +                                   ID_AA64DFR0_EL1_TraceFilt_SHIFT)))
>>>> +        return;
>>>> +
>>>> +    if (has_vhe())
>>>> +        write_sysreg_s(trfcr_guest, SYS_TRFCR_EL12);
>>>> +    else if (!is_protected_kvm_enabled())
>>>> +        kvm_guest_trfcr[smp_processor_id()] = trfcr_guest;
>>>
>>> smp_processor_id() could sleep in some configurations ? Should we switch
>>> to raw_smp_processor_id() to be safer ?
>>>
>>
>> I don't think so, it's #defined to raw_smp_processor_id() anyway. Unless
>> DEBUG_PREEMPT is on, then it's still raw_smp_processor_id() but it
>> validates that preemption is disabled so the value isn't stale. >
>> We actually want that validation, so should leave it as
> 
> This is actually what we want. i.e., We don't want the coresight drivers
> to make this call from a non-premptible context. Relying on the
> DEBUG_PREEMPT for detecting such erroneous uses is not a good idea,
> production kernels may not do this and a comment doesn't go far.
> So, I think we need a :
> 
> WARN_ON(preemptible()) in here and use smp_processor_id()
> 

Ok yeah that's easy enough to add. I was worried it would be redundant
with DEBUG_PREEMPT but I suppose it doesn't really cost anything.

>> smp_processor_id(). I can add a comment saying that this function should
>> only be called with preemption disabled, but I wouldn't add any extra
>> validation. Every smp_processor_id() call is already checked when
>> DEBUG_PREEMPT is on and this one doesn't seem to be special in any way.
>>
>> I also checked that the warning isn't triggered with DEBUG_PREEMPT on,
>> and there are also a lot of other smp_processor_id() calls on similar
>> paths in the Coresight driver.
> 
> Here, we are setting something for the KVM to program and if we set the
> filters on the wrong Physical CPU, then we mess up the tracing.
> 
> Suzuki
> 
>>
>>> Otherwise looks good to me.
>>>
>>> Suzuki
>>>
>>>> +}
>>>> +EXPORT_SYMBOL_GPL(kvm_etm_set_guest_trfcr);
>>>
> 

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2024-02-26 11:36 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-02-20 10:09 [PATCH v5 0/7] kvm/coresight: Support exclude guest and exclude host James Clark
2024-02-20 10:09 ` [PATCH v5 1/7] arm64: KVM: Fix renamed function in comment James Clark
2024-02-20 10:09 ` [PATCH v5 2/7] arm64/sysreg/tools: Update tools copy of sysreg.h James Clark
2024-02-20 16:12   ` Mark Brown
2024-02-26 10:30   ` Suzuki K Poulose
2024-02-20 10:09 ` [PATCH v5 3/7] arm64/sysreg/tools: Move TRFCR definitions to sysreg James Clark
2024-02-20 16:11   ` Mark Brown
2024-02-21 10:10     ` James Clark
2024-02-21 12:56       ` Mark Brown
2024-02-20 10:09 ` [PATCH v5 4/7] arm64: KVM: Add iflag for FEAT_TRF James Clark
2024-02-20 10:09 ` [PATCH v5 5/7] arm64: KVM: Add interface to set guest value for TRFCR register James Clark
2024-02-23 10:03   ` Suzuki K Poulose
2024-02-23 16:39     ` James Clark
2024-02-26  9:52       ` Suzuki K Poulose
2024-02-26 11:36         ` James Clark
2024-02-20 10:09 ` [PATCH v5 6/7] arm64: KVM: Write TRFCR value on guest switch with nVHE James Clark
2024-02-26 10:14   ` Suzuki K Poulose
2024-02-20 10:09 ` [PATCH v5 7/7] coresight: Pass guest TRFCR value to KVM James Clark

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).