[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2] xen/arm: Hide PMU registers from the guest, when the vPMU feature is disabled.


  • To: Hirokazu Takahashi <taka@xxxxxxxxxxxxx>, <xen-devel@xxxxxxxxxxxxxxxxxxxx>
  • From: "Orzel, Michal" <michal.orzel@xxxxxxx>
  • Date: Mon, 17 Aug 2026 09:00:26 +0200
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=valinux.co.jp smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0)
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=5RMwhhctxyiEppC1UIO+FGB5fkFikiJdZztxKlN7w5E=; b=PPfmKa15TVDOOaq96ZNjzYxJU6KZTeJPhPRI7axoyfYq+EADlQx3pssfRqVlXBkQ0Bv5AXIuTCXePdXmF+esRX+qdBl3c1UVSLtQT7KuIFWgBUBkEpFziNwFw6WvSwEvOUYUH1v7/DVWXUzyard1HlJ3DBZyutbVWPO6vBTeI37UnMERfKfjAQphGm8d3KM4uDtcDb3O9T1EV1ByWFgTV2CT7eWsm9CU3StIuCi0qh4M7RmaoeYv50YmwdWsHMUBVr0yPvZUHIMJe64XvZCyCPHooWotSAS3a9jnxKdaqu9yH3/8nGJucABZzgJWoD7J8P3vvM2YNjtMOj6X74PapQ==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=IqFgICb//lhB1/UstvqW82JrH/wMO95QyN+mb5jpRDKkGnuGGQCACaUL7Ch5KJ6AsGU4cEzmbIdhIHKH07tqMtwz2xlGrW6Qkx/0IdPA6XMbOC5IE/hN9MJhjJtyyTvqvEDHmuhdwt2B2GPK7alhwsRD5nPO8x8ib2rVwU5mAt43HXyMPZth1jdLAsve724Ny1/QQl81bw5+ifgZKTMJc7sJaCeVXe4jUsbG6wVCvdcU28wrDyjCZBmslJNPCxiQsHmfRT5UcpJotRhEwv3M3lM/3tuR9B7bDCOaiCPHuzY5fQ89GuruKkcNRa4u/ajlfhDy2Z/F9BjTxWARqsWlvg==
  • Authentication-results: eu.smtp.expurgate.cloud; dkim=pass header.s=selector1 header.d=amd.com header.i="@amd.com" header.h="From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck"
  • Cc: Stefano Stabellini <sstabellini@xxxxxxxxxx>, Julien Grall <julien@xxxxxxx>, Bertrand Marquis <bertrand.marquis@xxxxxxx>, Volodymyr Babchuk <Volodymyr_Babchuk@xxxxxxxx>
  • Delivery-date: Mon, 17 Aug 2026 07:00:45 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>


On 13-Aug-26 05:29, Hirokazu Takahashi wrote:
> On ARMv8.4-A and newer platforms, booting Dom0 Linux with ACPI enabled
> causes the domain to probe advanced PMU feature based on system ID
> register ID_AA64DFR0_EL1.During this probe, Linux accesses PMMIR_EL1,
> which causes unhandled register traps and crashes the domain.
> 
> To address this issue, I implement the following:
Please use the imperative mood

> 
> - Hide PMU registers from a guest domain when its vPMU feature is
>   disabled.
> - Proactively make SPE, TRBE, BRBE, and Trace Extensions inaccessible
>   to guest domains, as they could potentially cause similar issues.
> - Add emulation for PMMIR_EL1 register accesses performed by a guest
>   domain when vPMU is enabled. However, similar to reads from other
When vPMU is enabled, there is no trap/emulation

>   PMU registers, the read value returns zero (note that this is a
>   temporary implementation).
> - Emulation for PMSS (PMU Snapshot) register accesses is not yet
>   implemented, because PMSS support is not available in
>   qemu-system-aarch64 and could not be verified.
> 
> Fixes: 07b9acea116e "xen/arm: Add handler for ID registers on arm64"
> Fixes: 3669a1cb9598 "xen/arm: create a cpuinfo structure for guest"
Fixes commit title needs to be in brackets ()

> Signed-off-by: Hirokazu Takahashi <taka@xxxxxxxxxxxxx>
> ---
> Changes in v2:
>  * Instead of unconditionally hiding the PMU feature from guests,
>    we now determine whether to expose PMU to a guest domain based on
>    its configuration.
> 
>  xen/arch/arm/arm64/vsysreg.c          | 31 +++++++++++++++++++++++++--
>  xen/arch/arm/cpufeature.c             |  8 +++++++
>  xen/arch/arm/include/asm/arm64/hsr.h  |  1 +
>  xen/arch/arm/include/asm/cpufeature.h | 14 ++++++------
>  4 files changed, 46 insertions(+), 8 deletions(-)
> 
> diff --git a/xen/arch/arm/arm64/vsysreg.c b/xen/arch/arm/arm64/vsysreg.c
> index d14258290f..520faa02ca 100644
> --- a/xen/arch/arm/arm64/vsysreg.c
> +++ b/xen/arch/arm/arm64/vsysreg.c
> @@ -229,6 +229,7 @@ void do_sysreg(struct cpu_user_regs *regs,
>       */
>      case HSR_SYSREG_PMINTENSET_EL1:
>      case HSR_SYSREG_PMINTENCLR_EL1:
> +    case HSR_SYSREG_PMMIR_EL1:
What about AArch32 PMMIR?

>          /*
>           * Accessible from EL1 only, but if EL0 trap happens handle as
>           * undef.
> @@ -306,7 +307,6 @@ void do_sysreg(struct cpu_user_regs *regs,
>      GENERATE_TID3_INFO(ID_PFR0_EL1, pfr32, 0)
>      GENERATE_TID3_INFO(ID_PFR1_EL1, pfr32, 1)
>      GENERATE_TID3_INFO(ID_PFR2_EL1, pfr32, 2)
> -    GENERATE_TID3_INFO(ID_DFR0_EL1, dbg32, 0)
>      GENERATE_TID3_INFO(ID_DFR1_EL1, dbg32, 1)
>      GENERATE_TID3_INFO(ID_AFR0_EL1, aux32, 0)
>      GENERATE_TID3_INFO(ID_MMFR0_EL1, mm32, 0)
> @@ -326,6 +326,18 @@ void do_sysreg(struct cpu_user_regs *regs,
>      GENERATE_TID3_INFO(MVFR1_EL1, mvfr, 1)
>      GENERATE_TID3_INFO(MVFR2_EL1, mvfr, 2)
>  
> +    case HSR_SYSREG_ID_DFR0_EL1:
You only cover AArch64. What about AArch32 DFR0?

> +    {
> +        struct domain *d = current->domain;
Use v->domain instead like the surrounding code

> +        union cpuinfo_dbg32 info_dbg32 = domain_cpuinfo.dbg32;
> +
> +        if ( !(d->options & XEN_DOMCTL_CDF_vpmu) )
> +            info_dbg32.perfmon = 0;
> +
> +        return handle_ro_read_val(regs, regidx, hsr.sysreg.read, hsr, 1,
> +                                  info_dbg32.bits[0]);
> +    }
> +
>      case HSR_SYSREG_ID_AA64PFR0_EL1:
>      {
>          register_t guest_reg_value = domain_cpuinfo.pfr64.bits[0];
> @@ -348,7 +360,6 @@ void do_sysreg(struct cpu_user_regs *regs,
>      }
>  
>      GENERATE_TID3_INFO(ID_AA64PFR1_EL1, pfr64, 1)
> -    GENERATE_TID3_INFO(ID_AA64DFR0_EL1, dbg64, 0)
>      GENERATE_TID3_INFO(ID_AA64DFR1_EL1, dbg64, 1)
What about DFR1 fields like PMICNTR? They suffer from the same problem.

>      GENERATE_TID3_INFO(ID_AA64ISAR0_EL1, isa64, 0)
>      GENERATE_TID3_INFO(ID_AA64ISAR1_EL1, isa64, 1)
> @@ -358,6 +369,22 @@ void do_sysreg(struct cpu_user_regs *regs,
>      GENERATE_TID3_INFO(ID_AA64AFR0_EL1, aux64, 0)
>      GENERATE_TID3_INFO(ID_AA64AFR1_EL1, aux64, 1)
>  
> +    case HSR_SYSREG_ID_AA64DFR0_EL1:
Please adhere to the order in which the cases were originally placed
> +    {
> +        struct domain *d = current->domain;
> +        union cpuinfo_dbg64 info_dbg64 = domain_cpuinfo.dbg64;
> +
> +        if ( !(d->options & XEN_DOMCTL_CDF_vpmu) )
To avoid duplication, please introduce is_vpmu_domain
> +        {
> +            info_dbg64.pmu_ver = 0;
> +            info_dbg64.mtpmu = 0;
> +            info_dbg64.pmss = 0;
> +        }
> +
> +        return handle_ro_read_val(regs, regidx, hsr.sysreg.read, hsr, 1,
> +                                  info_dbg64.bits[0]);
> +    }
> +
>      case HSR_SYSREG_ID_AA64ZFR0_EL1:
>      {
>          /*
> diff --git a/xen/arch/arm/cpufeature.c b/xen/arch/arm/cpufeature.c
> index 94d14fb6a9..0e9bf15ca5 100644
> --- a/xen/arch/arm/cpufeature.c
> +++ b/xen/arch/arm/cpufeature.c
> @@ -219,6 +219,14 @@ static int __init create_domain_cpuinfo(void)
>      domain_cpuinfo.isa64.api = 0;
>      domain_cpuinfo.isa64.gpa = 0;
>      domain_cpuinfo.isa64.gpi = 0;
> +
> +    /* Hide SPE, TRBE, BRBE, and Trace Extensions */
> +    domain_cpuinfo.dbg64.pms_ver = 0;
> +    domain_cpuinfo.dbg64.trace_ver = 0;
> +    domain_cpuinfo.dbg64.trace_filt = 0;
> +    domain_cpuinfo.dbg64.trace_buffer = 0;
> +    domain_cpuinfo.dbg64.ext_trc_buff = 0;
> +    domain_cpuinfo.dbg64.brbe = 0;
>  #endif
>  
>      /* Hide AMU support */
> diff --git a/xen/arch/arm/include/asm/arm64/hsr.h 
> b/xen/arch/arm/include/asm/arm64/hsr.h
> index 1495ccddea..ed18184cc7 100644
> --- a/xen/arch/arm/include/asm/arm64/hsr.h
> +++ b/xen/arch/arm/include/asm/arm64/hsr.h
> @@ -84,6 +84,7 @@
>  #define HSR_SYSREG_FAR_EL1        HSR_SYSREG(3,0,c6, c0,0)
>  #define HSR_SYSREG_PMINTENSET_EL1 HSR_SYSREG(3,0,c9,c14,1)
>  #define HSR_SYSREG_PMINTENCLR_EL1 HSR_SYSREG(3,0,c9,c14,2)
> +#define HSR_SYSREG_PMMIR_EL1      HSR_SYSREG(3,0,c9,c14,6)
>  #define HSR_SYSREG_MAIR_EL1       HSR_SYSREG(3,0,c10,c2,0)
>  #define HSR_SYSREG_AMAIR_EL1      HSR_SYSREG(3,0,c10,c3,0)
>  #define HSR_SYSREG_ICC_SGI1R_EL1  HSR_SYSREG(3,0,c12,c11,5)
> diff --git a/xen/arch/arm/include/asm/cpufeature.h 
> b/xen/arch/arm/include/asm/cpufeature.h
> index bf902a3970..ce8b58458f 100644
> --- a/xen/arch/arm/include/asm/cpufeature.h
> +++ b/xen/arch/arm/include/asm/cpufeature.h
> @@ -208,7 +208,7 @@ struct cpuinfo_arm {
>          };
>      } pfr64;
>  
> -    union {
> +    union cpuinfo_dbg64 {
>          register_t bits[2];
>          struct {
>              /* DFR0 */
> @@ -216,16 +216,18 @@ struct cpuinfo_arm {
>              unsigned long trace_ver:4;
>              unsigned long pmu_ver:4;
>              unsigned long brps:4;
> -            unsigned long __res0:4;
> +            unsigned long pmss:4;
>              unsigned long wrps:4;
> -            unsigned long __res1:4;
> +            unsigned long sebep:4;
Where did you take this field from? I can't see it in the latest Arm ARM:
https://support.arm.com/documentation/ddi0487/mc/-Part-D-The-AArch64-System-Level-Architecture/-Chapter-D24-AArch64-System-Register-Descriptions/-D24-2-General-system-control-registers/-D24-2-79-ID-AA64DFR0-EL1--AArch64-Debug-Feature-Register-0?lang=en

>              unsigned long ctx_cmps:4;
>              unsigned long pms_ver:4;
>              unsigned long double_lock:4;
>              unsigned long trace_filt:4;
> -            unsigned long __res2:4;
> +            unsigned long trace_buffer:4;
>              unsigned long mtpmu:4;
> -            unsigned long __res3:12;
> +            unsigned long brbe:4;
> +            unsigned long ext_trc_buff:4;
> +            unsigned long hpmn0:4;
>  
>              /* DFR1 */
>              unsigned long __res4:64;
> @@ -408,7 +410,7 @@ struct cpuinfo_arm {
>          };
>      } pfr32;
>  
> -    union {
> +    union cpuinfo_dbg32 {
>          register_t bits[2];
>          struct {
>              /* DFR0 */

~Michal




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.