diff mbox series

[4/4] target/arm: Flag PMCNTENCLR with ARM_CP_NO_RAW

Message ID 20250317-raw-v1-4-09e2dfff0e90@daynix.com (mailing list archive)
State New
Headers show
Series target/arm: Flag PMCNTENCLR with ARM_CP_NO_RAW | expand

Commit Message

Akihiko Odaki March 17, 2025, 11:16 a.m. UTC
A normal write to PMCNTENCLR clears written bits so it is not
appropriate for writing a raw value. This kind of situation is usually
handled by setting a raw write function, but flag the register with
ARM_CP_NO_RAW instead to workaround a problem with KVM.

KVM also has the same problem with PMINTENSET so add a comment to
note that. This register is already flagged with ARM_CP_NO_RAW.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 target/arm/helper.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 2dd8f4d56a1e..ee15132aadea 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -1901,12 +1901,21 @@  static const ARMCPRegInfo v7_cp_reginfo[] = {
       .accessfn = pmreg_access,
       .fgt = FGT_PMCNTEN,
       .writefn = pmcntenclr_write,
-      .type = ARM_CP_ALIAS | ARM_CP_IO },
+      /*
+       * Flag PMCNTENCLR with ARM_CP_NO_RAW instead of implementing raw
+       * access to workaround a problem with KVM; KVM applies bit operations
+       * that prevents writing back raw values since Linux 6.7:
+       * https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a45f41d754e0b37de4b7dc1fb3c6b7a1285882fc
+       *
+       * It is fine to lack raw access with PMCNTENCLR because KVM still
+       * exposes PMCNTENSET, which shares the underlying state.
+       */
+      .type = ARM_CP_ALIAS | ARM_CP_IO | ARM_CP_NO_RAW },
     { .name = "PMCNTENCLR_EL0", .state = ARM_CP_STATE_AA64,
       .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 2,
       .access = PL0_RW, .accessfn = pmreg_access,
       .fgt = FGT_PMCNTEN,
-      .type = ARM_CP_ALIAS | ARM_CP_IO,
+      .type = ARM_CP_ALIAS | ARM_CP_IO | ARM_CP_NO_RAW,
       .fieldoffset = offsetof(CPUARMState, cp15.c9_pmcnten),
       .writefn = pmcntenclr_write },
     { .name = "PMOVSR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 3,
@@ -2025,6 +2034,7 @@  static const ARMCPRegInfo v7_cp_reginfo[] = {
     { .name = "PMINTENCLR", .cp = 15, .crn = 9, .crm = 14, .opc1 = 0, .opc2 = 2,
       .access = PL1_RW, .accessfn = access_tpm,
       .fgt = FGT_PMINTEN,
+      /* Flag PMINTENCLR with ARM_CP_NO_RAW, as with PMCNTENCLR. */
       .type = ARM_CP_ALIAS | ARM_CP_IO | ARM_CP_NO_RAW,
       .fieldoffset = offsetof(CPUARMState, cp15.c9_pminten),
       .writefn = pmintenclr_write, },