]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Drop queue-6.12/kvm-arm64-set-hcr_el2.tid1-unconditionally.patch
authorSasha Levin <sashal@kernel.org>
Thu, 3 Jul 2025 12:54:54 +0000 (08:54 -0400)
committerSasha Levin <sashal@kernel.org>
Thu, 3 Jul 2025 13:13:04 +0000 (09:13 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-6.12/kvm-arm64-set-hcr_el2.tid1-unconditionally.patch [deleted file]
queue-6.12/series

diff --git a/queue-6.12/kvm-arm64-set-hcr_el2.tid1-unconditionally.patch b/queue-6.12/kvm-arm64-set-hcr_el2.tid1-unconditionally.patch
deleted file mode 100644 (file)
index 0a730fe..0000000
+++ /dev/null
@@ -1,336 +0,0 @@
-From 0510d3297a23920caf74a63e3f38c0ede70d6555 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 2 Jul 2025 18:37:48 -0400
-Subject: KVM: arm64: Set HCR_EL2.TID1 unconditionally
-
-[ Upstream commit 4cd48565b0e5df398e7253c0d2d8c0403d69e7bf ]
-
-commit 90807748ca3a ("KVM: arm64: Hide SME system registers from
-guests") added trap handling for SMIDR_EL1, treating it as UNDEFINED as
-KVM does not support SME. This is right for the most part, however KVM
-needs to set HCR_EL2.TID1 to _actually_ trap the register.
-
-Unfortunately, this comes with some collateral damage as TID1 forces
-REVIDR_EL1 and AIDR_EL1 to trap as well. KVM has long treated these
-registers as "invariant" which is an awful term for the following:
-
- - Userspace sees the boot CPU values on all vCPUs
-
- - The guest sees the hardware values of the CPU on which a vCPU is
-   scheduled
-
-Keep the plates spinning by adding trap handling for the affected
-registers and repaint all of the "invariant" crud into terms of
-identifying an implementation. Yes, at this point we only need to
-set TID1 on SME hardware, but REVIDR_EL1 and AIDR_EL1 are about to
-become mutable anyway.
-
-Cc: Mark Brown <broonie@kernel.org>
-Cc: stable@vger.kernel.org
-Fixes: 90807748ca3a ("KVM: arm64: Hide SME system registers from guests")
-[maz: handle traps from 32bit]
-Co-developed-by: Marc Zyngier <maz@kernel.org>
-Signed-off-by: Marc Zyngier <maz@kernel.org>
-Link: https://lore.kernel.org/r/20250225005401.679536-2-oliver.upton@linux.dev
-Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- arch/arm64/include/asm/kvm_arm.h |   4 +-
- arch/arm64/kvm/sys_regs.c        | 184 +++++++++++++++++--------------
- 2 files changed, 101 insertions(+), 87 deletions(-)
-
-diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
-index 109a85ee69100..dd34794cec997 100644
---- a/arch/arm64/include/asm/kvm_arm.h
-+++ b/arch/arm64/include/asm/kvm_arm.h
-@@ -92,12 +92,12 @@
-  * SWIO:      Turn set/way invalidates into set/way clean+invalidate
-  * PTW:               Take a stage2 fault if a stage1 walk steps in device memory
-  * TID3:      Trap EL1 reads of group 3 ID registers
-- * TID2:      Trap CTR_EL0, CCSIDR2_EL1, CLIDR_EL1, and CSSELR_EL1
-+ * TID1:      Trap REVIDR_EL1, AIDR_EL1, and SMIDR_EL1
-  */
- #define HCR_GUEST_FLAGS (HCR_TSC | HCR_TSW | HCR_TWE | HCR_TWI | HCR_VM | \
-                        HCR_BSU_IS | HCR_FB | HCR_TACR | \
-                        HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW | HCR_TLOR | \
--                       HCR_FMO | HCR_IMO | HCR_PTW | HCR_TID3)
-+                       HCR_FMO | HCR_IMO | HCR_PTW | HCR_TID3 | HCR_TID1)
- #define HCR_HOST_NVHE_FLAGS (HCR_RW | HCR_API | HCR_APK | HCR_ATA)
- #define HCR_HOST_NVHE_PROTECTED_FLAGS (HCR_HOST_NVHE_FLAGS | HCR_TSC)
- #define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H)
-diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
-index 42791971f7588..05c6f3c9bce25 100644
---- a/arch/arm64/kvm/sys_regs.c
-+++ b/arch/arm64/kvm/sys_regs.c
-@@ -2323,6 +2323,94 @@ static unsigned int s1poe_visibility(const struct kvm_vcpu *vcpu,
-       return REG_HIDDEN;
- }
-+/*
-+ * For historical (ahem ABI) reasons, KVM treated MIDR_EL1, REVIDR_EL1, and
-+ * AIDR_EL1 as "invariant" registers, meaning userspace cannot change them.
-+ * The values made visible to userspace were the register values of the boot
-+ * CPU.
-+ *
-+ * At the same time, reads from these registers at EL1 previously were not
-+ * trapped, allowing the guest to read the actual hardware value. On big-little
-+ * machines, this means the VM can see different values depending on where a
-+ * given vCPU got scheduled.
-+ *
-+ * These registers are now trapped as collateral damage from SME, and what
-+ * follows attempts to give a user / guest view consistent with the existing
-+ * ABI.
-+ */
-+static bool access_imp_id_reg(struct kvm_vcpu *vcpu,
-+                            struct sys_reg_params *p,
-+                            const struct sys_reg_desc *r)
-+{
-+      if (p->is_write)
-+              return write_to_read_only(vcpu, p, r);
-+
-+      switch (reg_to_encoding(r)) {
-+      case SYS_REVIDR_EL1:
-+              p->regval = read_sysreg(revidr_el1);
-+              break;
-+      case SYS_AIDR_EL1:
-+              p->regval = read_sysreg(aidr_el1);
-+              break;
-+      default:
-+              WARN_ON_ONCE(1);
-+      }
-+
-+      return true;
-+}
-+
-+static u64 __ro_after_init boot_cpu_midr_val;
-+static u64 __ro_after_init boot_cpu_revidr_val;
-+static u64 __ro_after_init boot_cpu_aidr_val;
-+
-+static void init_imp_id_regs(void)
-+{
-+      boot_cpu_midr_val = read_sysreg(midr_el1);
-+      boot_cpu_revidr_val = read_sysreg(revidr_el1);
-+      boot_cpu_aidr_val = read_sysreg(aidr_el1);
-+}
-+
-+static int get_imp_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
-+                        u64 *val)
-+{
-+      switch (reg_to_encoding(r)) {
-+      case SYS_MIDR_EL1:
-+              *val = boot_cpu_midr_val;
-+              break;
-+      case SYS_REVIDR_EL1:
-+              *val = boot_cpu_revidr_val;
-+              break;
-+      case SYS_AIDR_EL1:
-+              *val = boot_cpu_aidr_val;
-+              break;
-+      default:
-+              WARN_ON_ONCE(1);
-+              return -EINVAL;
-+      }
-+
-+      return 0;
-+}
-+
-+static int set_imp_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
-+                        u64 val)
-+{
-+      u64 expected;
-+      int ret;
-+
-+      ret = get_imp_id_reg(vcpu, r, &expected);
-+      if (ret)
-+              return ret;
-+
-+      return (expected == val) ? 0 : -EINVAL;
-+}
-+
-+#define IMPLEMENTATION_ID(reg) {                      \
-+      SYS_DESC(SYS_##reg),                            \
-+      .access = access_imp_id_reg,                    \
-+      .get_user = get_imp_id_reg,                     \
-+      .set_user = set_imp_id_reg,                     \
-+}
-+
- /*
-  * Architected system registers.
-  * Important: Must be sorted ascending by Op0, Op1, CRn, CRm, Op2
-@@ -2371,7 +2459,9 @@ static const struct sys_reg_desc sys_reg_descs[] = {
-       { SYS_DESC(SYS_DBGVCR32_EL2), undef_access, reset_val, DBGVCR32_EL2, 0 },
-+      IMPLEMENTATION_ID(MIDR_EL1),
-       { SYS_DESC(SYS_MPIDR_EL1), NULL, reset_mpidr, MPIDR_EL1 },
-+      IMPLEMENTATION_ID(REVIDR_EL1),
-       /*
-        * ID regs: all ID_SANITISED() entries here must have corresponding
-@@ -2648,6 +2738,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
-         .set_user = set_clidr, .val = ~CLIDR_EL1_RES0 },
-       { SYS_DESC(SYS_CCSIDR2_EL1), undef_access },
-       { SYS_DESC(SYS_SMIDR_EL1), undef_access },
-+      IMPLEMENTATION_ID(AIDR_EL1),
-       { SYS_DESC(SYS_CSSELR_EL1), access_csselr, reset_unknown, CSSELR_EL1 },
-       ID_WRITABLE(CTR_EL0, CTR_EL0_DIC_MASK |
-                            CTR_EL0_IDC_MASK |
-@@ -4060,9 +4151,13 @@ int kvm_handle_cp15_32(struct kvm_vcpu *vcpu)
-        * Certain AArch32 ID registers are handled by rerouting to the AArch64
-        * system register table. Registers in the ID range where CRm=0 are
-        * excluded from this scheme as they do not trivially map into AArch64
--       * system register encodings.
-+       * system register encodings, except for AIDR/REVIDR.
-        */
--      if (params.Op1 == 0 && params.CRn == 0 && params.CRm)
-+      if (params.Op1 == 0 && params.CRn == 0 &&
-+          (params.CRm || params.Op2 == 6 /* REVIDR */))
-+              return kvm_emulate_cp15_id_reg(vcpu, &params);
-+      if (params.Op1 == 1 && params.CRn == 0 &&
-+          params.CRm == 0 && params.Op2 == 7 /* AIDR */)
-               return kvm_emulate_cp15_id_reg(vcpu, &params);
-       return kvm_handle_cp_32(vcpu, &params, cp15_regs, ARRAY_SIZE(cp15_regs));
-@@ -4363,65 +4458,6 @@ id_to_sys_reg_desc(struct kvm_vcpu *vcpu, u64 id,
-       return r;
- }
--/*
-- * These are the invariant sys_reg registers: we let the guest see the
-- * host versions of these, so they're part of the guest state.
-- *
-- * A future CPU may provide a mechanism to present different values to
-- * the guest, or a future kvm may trap them.
-- */
--
--#define FUNCTION_INVARIANT(reg)                                               \
--      static u64 reset_##reg(struct kvm_vcpu *v,                      \
--                             const struct sys_reg_desc *r)            \
--      {                                                               \
--              ((struct sys_reg_desc *)r)->val = read_sysreg(reg);     \
--              return ((struct sys_reg_desc *)r)->val;                 \
--      }
--
--FUNCTION_INVARIANT(midr_el1)
--FUNCTION_INVARIANT(revidr_el1)
--FUNCTION_INVARIANT(aidr_el1)
--
--/* ->val is filled in by kvm_sys_reg_table_init() */
--static struct sys_reg_desc invariant_sys_regs[] __ro_after_init = {
--      { SYS_DESC(SYS_MIDR_EL1), NULL, reset_midr_el1 },
--      { SYS_DESC(SYS_REVIDR_EL1), NULL, reset_revidr_el1 },
--      { SYS_DESC(SYS_AIDR_EL1), NULL, reset_aidr_el1 },
--};
--
--static int get_invariant_sys_reg(u64 id, u64 __user *uaddr)
--{
--      const struct sys_reg_desc *r;
--
--      r = get_reg_by_id(id, invariant_sys_regs,
--                        ARRAY_SIZE(invariant_sys_regs));
--      if (!r)
--              return -ENOENT;
--
--      return put_user(r->val, uaddr);
--}
--
--static int set_invariant_sys_reg(u64 id, u64 __user *uaddr)
--{
--      const struct sys_reg_desc *r;
--      u64 val;
--
--      r = get_reg_by_id(id, invariant_sys_regs,
--                        ARRAY_SIZE(invariant_sys_regs));
--      if (!r)
--              return -ENOENT;
--
--      if (get_user(val, uaddr))
--              return -EFAULT;
--
--      /* This is what we mean by invariant: you can't change it. */
--      if (r->val != val)
--              return -EINVAL;
--
--      return 0;
--}
--
- static int demux_c15_get(struct kvm_vcpu *vcpu, u64 id, void __user *uaddr)
- {
-       u32 val;
-@@ -4503,15 +4539,10 @@ int kvm_sys_reg_get_user(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg,
- int kvm_arm_sys_reg_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
- {
-       void __user *uaddr = (void __user *)(unsigned long)reg->addr;
--      int err;
-       if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_DEMUX)
-               return demux_c15_get(vcpu, reg->id, uaddr);
--      err = get_invariant_sys_reg(reg->id, uaddr);
--      if (err != -ENOENT)
--              return err;
--
-       return kvm_sys_reg_get_user(vcpu, reg,
-                                   sys_reg_descs, ARRAY_SIZE(sys_reg_descs));
- }
-@@ -4547,15 +4578,10 @@ int kvm_sys_reg_set_user(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg,
- int kvm_arm_sys_reg_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
- {
-       void __user *uaddr = (void __user *)(unsigned long)reg->addr;
--      int err;
-       if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_DEMUX)
-               return demux_c15_set(vcpu, reg->id, uaddr);
--      err = set_invariant_sys_reg(reg->id, uaddr);
--      if (err != -ENOENT)
--              return err;
--
-       return kvm_sys_reg_set_user(vcpu, reg,
-                                   sys_reg_descs, ARRAY_SIZE(sys_reg_descs));
- }
-@@ -4644,23 +4670,14 @@ static int walk_sys_regs(struct kvm_vcpu *vcpu, u64 __user *uind)
- unsigned long kvm_arm_num_sys_reg_descs(struct kvm_vcpu *vcpu)
- {
--      return ARRAY_SIZE(invariant_sys_regs)
--              + num_demux_regs()
-+      return num_demux_regs()
-               + walk_sys_regs(vcpu, (u64 __user *)NULL);
- }
- int kvm_arm_copy_sys_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
- {
--      unsigned int i;
-       int err;
--      /* Then give them all the invariant registers' indices. */
--      for (i = 0; i < ARRAY_SIZE(invariant_sys_regs); i++) {
--              if (put_user(sys_reg_to_index(&invariant_sys_regs[i]), uindices))
--                      return -EFAULT;
--              uindices++;
--      }
--
-       err = walk_sys_regs(vcpu, uindices);
-       if (err < 0)
-               return err;
-@@ -4878,15 +4895,12 @@ int __init kvm_sys_reg_table_init(void)
-       valid &= check_sysreg_table(cp14_64_regs, ARRAY_SIZE(cp14_64_regs), true);
-       valid &= check_sysreg_table(cp15_regs, ARRAY_SIZE(cp15_regs), true);
-       valid &= check_sysreg_table(cp15_64_regs, ARRAY_SIZE(cp15_64_regs), true);
--      valid &= check_sysreg_table(invariant_sys_regs, ARRAY_SIZE(invariant_sys_regs), false);
-       valid &= check_sysreg_table(sys_insn_descs, ARRAY_SIZE(sys_insn_descs), false);
-       if (!valid)
-               return -EINVAL;
--      /* We abuse the reset function to overwrite the table itself. */
--      for (i = 0; i < ARRAY_SIZE(invariant_sys_regs); i++)
--              invariant_sys_regs[i].reset(NULL, &invariant_sys_regs[i]);
-+      init_imp_id_regs();
-       ret = populate_nv_trap_config();
--- 
-2.39.5
-
index e11942a0592938d922ce85c7979077501e1e9a95..2da459ee6fa20d24926041f0498604371f67b651 100644 (file)
@@ -208,7 +208,6 @@ arm64-dts-rockchip-add-avdd-hdmi-supplies-to-rockpro.patch
 alsa-hda-realtek-bass-speaker-fixup-for-asus-um5606k.patch
 drm-amdkfd-remove-gfx-12-trap-handler-page-size-cap.patch
 drm-amdkfd-fix-instruction-hazard-in-gfx12-trap-hand.patch
-kvm-arm64-set-hcr_el2.tid1-unconditionally.patch
 net-stmmac-fix-accessing-freed-irq-affinity_hint.patch
 spi-spi-mem-extend-spi-mem-operations-with-a-per-ope.patch
 spi-spi-mem-add-a-new-controller-capability.patch