]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
drop a mips patch
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 8 Apr 2026 12:50:37 +0000 (14:50 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 8 Apr 2026 12:50:37 +0000 (14:50 +0200)
queue-6.12/mips-mm-allocate-tlb_vpn-array-atomically.patch
queue-6.12/mips-mm-rewrite-tlb-uniquification-for-the-hidden-bit-feature.patch [deleted file]
queue-6.12/series
queue-6.18/mips-mm-allocate-tlb_vpn-array-atomically.patch
queue-6.18/mips-mm-rewrite-tlb-uniquification-for-the-hidden-bit-feature.patch [deleted file]
queue-6.18/series
queue-6.19/mips-mm-allocate-tlb_vpn-array-atomically.patch
queue-6.19/mips-mm-rewrite-tlb-uniquification-for-the-hidden-bit-feature.patch [deleted file]
queue-6.19/series

index 675adb018155ea59fc164b9ab3043949bf096993..fb2a44505dc313f062e5925d467fad584957fd8b 100644 (file)
@@ -53,7 +53,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 
 --- a/arch/mips/mm/tlb-r4k.c
 +++ b/arch/mips/mm/tlb-r4k.c
-@@ -751,7 +751,7 @@ static void __ref r4k_tlb_uniquify(void)
+@@ -538,7 +538,7 @@ static void __ref r4k_tlb_uniquify(void)
  
        tlb_vpn_size = tlbsize * sizeof(*tlb_vpns);
        tlb_vpns = (use_slab ?
diff --git a/queue-6.12/mips-mm-rewrite-tlb-uniquification-for-the-hidden-bit-feature.patch b/queue-6.12/mips-mm-rewrite-tlb-uniquification-for-the-hidden-bit-feature.patch
deleted file mode 100644 (file)
index 561c912..0000000
+++ /dev/null
@@ -1,373 +0,0 @@
-From 540760b77b8fc49d39d1b2b76196e5ec57711a32 Mon Sep 17 00:00:00 2001
-From: "Maciej W. Rozycki" <macro@orcam.me.uk>
-Date: Fri, 27 Mar 2026 18:57:30 +0000
-Subject: MIPS: mm: Rewrite TLB uniquification for the hidden bit feature
-
-From: Maciej W. Rozycki <macro@orcam.me.uk>
-
-commit 540760b77b8fc49d39d1b2b76196e5ec57711a32 upstream.
-
-Before the introduction of the EHINV feature, which lets software mark
-TLB entries invalid, certain older implementations of the MIPS ISA were
-equipped with an analogous bit, as a vendor extension, which however is
-hidden from software and only ever set at reset, and then any software
-write clears it, making the intended TLB entry valid.
-
-This feature makes it unsafe to read a TLB entry with TLBR, modify the
-page mask, and write the entry back with TLBWI, because this operation
-will implicitly clear the hidden bit and this may create a duplicate
-entry, as with the presence of the hidden bit there is no guarantee all
-the entries across the TLB are unique each.
-
-Usually the firmware has already uniquified TLB entries before handing
-control over, in which case we only need to guarantee at bootstrap no
-clash will happen with the VPN2 values chosen in local_flush_tlb_all().
-
-However with systems such as Mikrotik RB532 we get handed the TLB as at
-reset, with the hidden bit set across the entries and possibly duplicate
-entries present.  This then causes a machine check exception when page
-sizes are reset in r4k_tlb_uniquify() and prevents the system from
-booting.
-
-Rewrite the algorithm used in r4k_tlb_uniquify() then such as to avoid
-the reuse of ASID/VPN values across the TLB.  Get rid of global entries
-first as they may be blocking the entire address space, e.g. 16 256MiB
-pages will exhaust the whole address space of a 32-bit CPU and a single
-big page can exhaust the 32-bit compatibility space on a 64-bit CPU.
-
-Details of the algorithm chosen are given across the code itself.
-
-Fixes: 9f048fa48740 ("MIPS: mm: Prevent a TLB shutdown on initial uniquification")
-Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
-Cc: stable@vger.kernel.org # v6.18+
-Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- arch/mips/mm/tlb-r4k.c |  282 +++++++++++++++++++++++++++++++++++++++----------
- 1 file changed, 228 insertions(+), 54 deletions(-)
-
---- a/arch/mips/mm/tlb-r4k.c
-+++ b/arch/mips/mm/tlb-r4k.c
-@@ -13,6 +13,7 @@
- #include <linux/sched.h>
- #include <linux/smp.h>
- #include <linux/memblock.h>
-+#include <linux/minmax.h>
- #include <linux/mm.h>
- #include <linux/hugetlb.h>
- #include <linux/export.h>
-@@ -24,6 +25,7 @@
- #include <asm/hazards.h>
- #include <asm/mmu_context.h>
- #include <asm/tlb.h>
-+#include <asm/tlbdebug.h>
- #include <asm/tlbex.h>
- #include <asm/tlbmisc.h>
- #include <asm/setup.h>
-@@ -511,12 +513,229 @@ static int __init set_ntlb(char *str)
- __setup("ntlb=", set_ntlb);
--/* Comparison function for EntryHi VPN fields.  */
--static int r4k_vpn_cmp(const void *a, const void *b)
-+/* The start bit position of VPN2 and Mask in EntryHi/PageMask registers.  */
-+#define VPN2_SHIFT 13
-+
-+/* Read full EntryHi even with CONFIG_32BIT.  */
-+static inline unsigned long long read_c0_entryhi_native(void)
-+{
-+      return cpu_has_64bits ? read_c0_entryhi_64() : read_c0_entryhi();
-+}
-+
-+/* Write full EntryHi even with CONFIG_32BIT.  */
-+static inline void write_c0_entryhi_native(unsigned long long v)
-+{
-+      if (cpu_has_64bits)
-+              write_c0_entryhi_64(v);
-+      else
-+              write_c0_entryhi(v);
-+}
-+
-+/* TLB entry state for uniquification.  */
-+struct tlbent {
-+      unsigned long long wired:1;
-+      unsigned long long global:1;
-+      unsigned long long asid:10;
-+      unsigned long long vpn:51;
-+      unsigned long long pagesz:5;
-+      unsigned long long index:14;
-+};
-+
-+/*
-+ * Comparison function for TLB entry sorting.  Place wired entries first,
-+ * then global entries, then order by the increasing VPN/ASID and the
-+ * decreasing page size.  This lets us avoid clashes with wired entries
-+ * easily and get entries for larger pages out of the way first.
-+ *
-+ * We could group bits so as to reduce the number of comparisons, but this
-+ * is seldom executed and not performance-critical, so prefer legibility.
-+ */
-+static int r4k_entry_cmp(const void *a, const void *b)
- {
--      long v = *(unsigned long *)a - *(unsigned long *)b;
--      int s = sizeof(long) > sizeof(int) ? sizeof(long) * 8 - 1: 0;
--      return s ? (v != 0) | v >> s : v;
-+      struct tlbent ea = *(struct tlbent *)a, eb = *(struct tlbent *)b;
-+
-+      if (ea.wired > eb.wired)
-+              return -1;
-+      else if (ea.wired < eb.wired)
-+              return 1;
-+      else if (ea.global > eb.global)
-+              return -1;
-+      else if (ea.global < eb.global)
-+              return 1;
-+      else if (ea.vpn < eb.vpn)
-+              return -1;
-+      else if (ea.vpn > eb.vpn)
-+              return 1;
-+      else if (ea.asid < eb.asid)
-+              return -1;
-+      else if (ea.asid > eb.asid)
-+              return 1;
-+      else if (ea.pagesz > eb.pagesz)
-+              return -1;
-+      else if (ea.pagesz < eb.pagesz)
-+              return 1;
-+      else
-+              return 0;
-+}
-+
-+/*
-+ * Fetch all the TLB entries.  Mask individual VPN values retrieved with
-+ * the corresponding page mask and ignoring any 1KiB extension as we'll
-+ * be using 4KiB pages for uniquification.
-+ */
-+static void __ref r4k_tlb_uniquify_read(struct tlbent *tlb_vpns, int tlbsize)
-+{
-+      int start = num_wired_entries();
-+      unsigned long long vpn_mask;
-+      bool global;
-+      int i;
-+
-+      vpn_mask = GENMASK(current_cpu_data.vmbits - 1, VPN2_SHIFT);
-+      vpn_mask |= cpu_has_64bits ? 3ULL << 62 : 1 << 31;
-+
-+      for (i = 0; i < tlbsize; i++) {
-+              unsigned long long entryhi, vpn, mask, asid;
-+              unsigned int pagesz;
-+
-+              write_c0_index(i);
-+              mtc0_tlbr_hazard();
-+              tlb_read();
-+              tlb_read_hazard();
-+
-+              global = !!(read_c0_entrylo0() & ENTRYLO_G);
-+              entryhi = read_c0_entryhi_native();
-+              mask = read_c0_pagemask();
-+
-+              asid = entryhi & cpu_asid_mask(&current_cpu_data);
-+              vpn = (entryhi & vpn_mask & ~mask) >> VPN2_SHIFT;
-+              pagesz = ilog2((mask >> VPN2_SHIFT) + 1);
-+
-+              tlb_vpns[i].global = global;
-+              tlb_vpns[i].asid = global ? 0 : asid;
-+              tlb_vpns[i].vpn = vpn;
-+              tlb_vpns[i].pagesz = pagesz;
-+              tlb_vpns[i].wired = i < start;
-+              tlb_vpns[i].index = i;
-+      }
-+}
-+
-+/*
-+ * Write unique values to all but the wired TLB entries each, using
-+ * the 4KiB page size.  This size might not be supported with R6, but
-+ * EHINV is mandatory for R6, so we won't ever be called in that case.
-+ *
-+ * A sorted table is supplied with any wired entries at the beginning,
-+ * followed by any global entries, and then finally regular entries.
-+ * We start at the VPN and ASID values of zero and only assign user
-+ * addresses, therefore guaranteeing no clash with addresses produced
-+ * by UNIQUE_ENTRYHI.  We avoid any VPN values used by wired or global
-+ * entries, by increasing the VPN value beyond the span of such entry.
-+ *
-+ * When a VPN/ASID clash is found with a regular entry we increment the
-+ * ASID instead until no VPN/ASID clash has been found or the ASID space
-+ * has been exhausted, in which case we increase the VPN value beyond
-+ * the span of the largest clashing entry.
-+ *
-+ * We do not need to be concerned about FTLB or MMID configurations as
-+ * those are required to implement the EHINV feature.
-+ */
-+static void __ref r4k_tlb_uniquify_write(struct tlbent *tlb_vpns, int tlbsize)
-+{
-+      unsigned long long asid, vpn, vpn_size, pagesz;
-+      int widx, gidx, idx, sidx, lidx, i;
-+
-+      vpn_size = 1ULL << (current_cpu_data.vmbits - VPN2_SHIFT);
-+      pagesz = ilog2((PM_4K >> VPN2_SHIFT) + 1);
-+
-+      write_c0_pagemask(PM_4K);
-+      write_c0_entrylo0(0);
-+      write_c0_entrylo1(0);
-+
-+      asid = 0;
-+      vpn = 0;
-+      widx = 0;
-+      gidx = 0;
-+      for (sidx = 0; sidx < tlbsize && tlb_vpns[sidx].wired; sidx++)
-+              ;
-+      for (lidx = sidx; lidx < tlbsize && tlb_vpns[lidx].global; lidx++)
-+              ;
-+      idx = gidx = sidx + 1;
-+      for (i = sidx; i < tlbsize; i++) {
-+              unsigned long long entryhi, vpn_pagesz = 0;
-+
-+              while (1) {
-+                      if (WARN_ON(vpn >= vpn_size)) {
-+                              dump_tlb_all();
-+                              /* Pray local_flush_tlb_all() will cope.  */
-+                              return;
-+                      }
-+
-+                      /* VPN must be below the next wired entry.  */
-+                      if (widx < sidx && vpn >= tlb_vpns[widx].vpn) {
-+                              vpn = max(vpn,
-+                                        (tlb_vpns[widx].vpn +
-+                                         (1ULL << tlb_vpns[widx].pagesz)));
-+                              asid = 0;
-+                              widx++;
-+                              continue;
-+                      }
-+                      /* VPN must be below the next global entry.  */
-+                      if (gidx < lidx && vpn >= tlb_vpns[gidx].vpn) {
-+                              vpn = max(vpn,
-+                                        (tlb_vpns[gidx].vpn +
-+                                         (1ULL << tlb_vpns[gidx].pagesz)));
-+                              asid = 0;
-+                              gidx++;
-+                              continue;
-+                      }
-+                      /* Try to find a free ASID so as to conserve VPNs.  */
-+                      if (idx < tlbsize && vpn == tlb_vpns[idx].vpn &&
-+                          asid == tlb_vpns[idx].asid) {
-+                              unsigned long long idx_pagesz;
-+
-+                              idx_pagesz = tlb_vpns[idx].pagesz;
-+                              vpn_pagesz = max(vpn_pagesz, idx_pagesz);
-+                              do
-+                                      idx++;
-+                              while (idx < tlbsize &&
-+                                     vpn == tlb_vpns[idx].vpn &&
-+                                     asid == tlb_vpns[idx].asid);
-+                              asid++;
-+                              if (asid > cpu_asid_mask(&current_cpu_data)) {
-+                                      vpn += vpn_pagesz;
-+                                      asid = 0;
-+                                      vpn_pagesz = 0;
-+                              }
-+                              continue;
-+                      }
-+                      /* VPN mustn't be above the next regular entry.  */
-+                      if (idx < tlbsize && vpn > tlb_vpns[idx].vpn) {
-+                              vpn = max(vpn,
-+                                        (tlb_vpns[idx].vpn +
-+                                         (1ULL << tlb_vpns[idx].pagesz)));
-+                              asid = 0;
-+                              idx++;
-+                              continue;
-+                      }
-+                      break;
-+              }
-+
-+              entryhi = (vpn << VPN2_SHIFT) | asid;
-+              write_c0_entryhi_native(entryhi);
-+              write_c0_index(tlb_vpns[i].index);
-+              mtc0_tlbw_hazard();
-+              tlb_write_indexed();
-+
-+              tlb_vpns[i].asid = asid;
-+              tlb_vpns[i].vpn = vpn;
-+              tlb_vpns[i].pagesz = pagesz;
-+
-+              asid++;
-+              if (asid > cpu_asid_mask(&current_cpu_data)) {
-+                      vpn += 1ULL << pagesz;
-+                      asid = 0;
-+              }
-+      }
- }
- /*
-@@ -527,14 +746,8 @@ static void __ref r4k_tlb_uniquify(void)
- {
-       int tlbsize = current_cpu_data.tlbsize;
-       bool use_slab = slab_is_available();
--      int start = num_wired_entries();
-       phys_addr_t tlb_vpn_size;
--      unsigned long *tlb_vpns;
--      unsigned long vpn_mask;
--      int cnt, ent, idx, i;
--
--      vpn_mask = GENMASK(cpu_vmbits - 1, 13);
--      vpn_mask |= IS_ENABLED(CONFIG_64BIT) ? 3ULL << 62 : 1 << 31;
-+      struct tlbent *tlb_vpns;
-       tlb_vpn_size = tlbsize * sizeof(*tlb_vpns);
-       tlb_vpns = (use_slab ?
-@@ -545,52 +758,13 @@ static void __ref r4k_tlb_uniquify(void)
-       htw_stop();
--      for (i = start, cnt = 0; i < tlbsize; i++, cnt++) {
--              unsigned long vpn;
-+      r4k_tlb_uniquify_read(tlb_vpns, tlbsize);
--              write_c0_index(i);
--              mtc0_tlbr_hazard();
--              tlb_read();
--              tlb_read_hazard();
--              vpn = read_c0_entryhi();
--              vpn &= vpn_mask & PAGE_MASK;
--              tlb_vpns[cnt] = vpn;
--
--              /* Prevent any large pages from overlapping regular ones.  */
--              write_c0_pagemask(read_c0_pagemask() & PM_DEFAULT_MASK);
--              mtc0_tlbw_hazard();
--              tlb_write_indexed();
--              tlbw_use_hazard();
--      }
-+      sort(tlb_vpns, tlbsize, sizeof(*tlb_vpns), r4k_entry_cmp, NULL);
--      sort(tlb_vpns, cnt, sizeof(tlb_vpns[0]), r4k_vpn_cmp, NULL);
-+      r4k_tlb_uniquify_write(tlb_vpns, tlbsize);
-       write_c0_pagemask(PM_DEFAULT_MASK);
--      write_c0_entrylo0(0);
--      write_c0_entrylo1(0);
--
--      idx = 0;
--      ent = tlbsize;
--      for (i = start; i < tlbsize; i++)
--              while (1) {
--                      unsigned long entryhi, vpn;
--
--                      entryhi = UNIQUE_ENTRYHI(ent);
--                      vpn = entryhi & vpn_mask & PAGE_MASK;
--
--                      if (idx >= cnt || vpn < tlb_vpns[idx]) {
--                              write_c0_entryhi(entryhi);
--                              write_c0_index(i);
--                              mtc0_tlbw_hazard();
--                              tlb_write_indexed();
--                              ent++;
--                              break;
--                      } else if (vpn == tlb_vpns[idx]) {
--                              ent++;
--                      } else {
--                              idx++;
--                      }
--              }
-       tlbw_use_hazard();
-       htw_start();
index a50945e557a9f3625052a0df81f4fcb6a29da181..7990d2c0892b2295c9f916f211c8c69cd024775e 100644 (file)
@@ -127,7 +127,6 @@ bluetooth-smp-derive-legacy-responder-stk-authentication-from-mitm-state.patch
 bluetooth-smp-force-responder-mitm-requirements-before-building-the-pairing-response.patch
 bluetooth-hci_sync-fix-stack-buffer-overflow-in-hci_le_big_create_sync.patch
 ksmbd-fix-oob-write-in-query_info-for-compound-requests.patch
-mips-mm-rewrite-tlb-uniquification-for-the-hidden-bit-feature.patch
 mips-sibyte-bring-back-cache-initialisation.patch
 mips-fix-the-gcc-version-check-for-__multi3-workaround.patch
 hwmon-occ-fix-division-by-zero-in-occ_show_power_1.patch
index 675adb018155ea59fc164b9ab3043949bf096993..fb2a44505dc313f062e5925d467fad584957fd8b 100644 (file)
@@ -53,7 +53,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 
 --- a/arch/mips/mm/tlb-r4k.c
 +++ b/arch/mips/mm/tlb-r4k.c
-@@ -751,7 +751,7 @@ static void __ref r4k_tlb_uniquify(void)
+@@ -538,7 +538,7 @@ static void __ref r4k_tlb_uniquify(void)
  
        tlb_vpn_size = tlbsize * sizeof(*tlb_vpns);
        tlb_vpns = (use_slab ?
diff --git a/queue-6.18/mips-mm-rewrite-tlb-uniquification-for-the-hidden-bit-feature.patch b/queue-6.18/mips-mm-rewrite-tlb-uniquification-for-the-hidden-bit-feature.patch
deleted file mode 100644 (file)
index 561c912..0000000
+++ /dev/null
@@ -1,373 +0,0 @@
-From 540760b77b8fc49d39d1b2b76196e5ec57711a32 Mon Sep 17 00:00:00 2001
-From: "Maciej W. Rozycki" <macro@orcam.me.uk>
-Date: Fri, 27 Mar 2026 18:57:30 +0000
-Subject: MIPS: mm: Rewrite TLB uniquification for the hidden bit feature
-
-From: Maciej W. Rozycki <macro@orcam.me.uk>
-
-commit 540760b77b8fc49d39d1b2b76196e5ec57711a32 upstream.
-
-Before the introduction of the EHINV feature, which lets software mark
-TLB entries invalid, certain older implementations of the MIPS ISA were
-equipped with an analogous bit, as a vendor extension, which however is
-hidden from software and only ever set at reset, and then any software
-write clears it, making the intended TLB entry valid.
-
-This feature makes it unsafe to read a TLB entry with TLBR, modify the
-page mask, and write the entry back with TLBWI, because this operation
-will implicitly clear the hidden bit and this may create a duplicate
-entry, as with the presence of the hidden bit there is no guarantee all
-the entries across the TLB are unique each.
-
-Usually the firmware has already uniquified TLB entries before handing
-control over, in which case we only need to guarantee at bootstrap no
-clash will happen with the VPN2 values chosen in local_flush_tlb_all().
-
-However with systems such as Mikrotik RB532 we get handed the TLB as at
-reset, with the hidden bit set across the entries and possibly duplicate
-entries present.  This then causes a machine check exception when page
-sizes are reset in r4k_tlb_uniquify() and prevents the system from
-booting.
-
-Rewrite the algorithm used in r4k_tlb_uniquify() then such as to avoid
-the reuse of ASID/VPN values across the TLB.  Get rid of global entries
-first as they may be blocking the entire address space, e.g. 16 256MiB
-pages will exhaust the whole address space of a 32-bit CPU and a single
-big page can exhaust the 32-bit compatibility space on a 64-bit CPU.
-
-Details of the algorithm chosen are given across the code itself.
-
-Fixes: 9f048fa48740 ("MIPS: mm: Prevent a TLB shutdown on initial uniquification")
-Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
-Cc: stable@vger.kernel.org # v6.18+
-Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- arch/mips/mm/tlb-r4k.c |  282 +++++++++++++++++++++++++++++++++++++++----------
- 1 file changed, 228 insertions(+), 54 deletions(-)
-
---- a/arch/mips/mm/tlb-r4k.c
-+++ b/arch/mips/mm/tlb-r4k.c
-@@ -13,6 +13,7 @@
- #include <linux/sched.h>
- #include <linux/smp.h>
- #include <linux/memblock.h>
-+#include <linux/minmax.h>
- #include <linux/mm.h>
- #include <linux/hugetlb.h>
- #include <linux/export.h>
-@@ -24,6 +25,7 @@
- #include <asm/hazards.h>
- #include <asm/mmu_context.h>
- #include <asm/tlb.h>
-+#include <asm/tlbdebug.h>
- #include <asm/tlbex.h>
- #include <asm/tlbmisc.h>
- #include <asm/setup.h>
-@@ -511,12 +513,229 @@ static int __init set_ntlb(char *str)
- __setup("ntlb=", set_ntlb);
--/* Comparison function for EntryHi VPN fields.  */
--static int r4k_vpn_cmp(const void *a, const void *b)
-+/* The start bit position of VPN2 and Mask in EntryHi/PageMask registers.  */
-+#define VPN2_SHIFT 13
-+
-+/* Read full EntryHi even with CONFIG_32BIT.  */
-+static inline unsigned long long read_c0_entryhi_native(void)
-+{
-+      return cpu_has_64bits ? read_c0_entryhi_64() : read_c0_entryhi();
-+}
-+
-+/* Write full EntryHi even with CONFIG_32BIT.  */
-+static inline void write_c0_entryhi_native(unsigned long long v)
-+{
-+      if (cpu_has_64bits)
-+              write_c0_entryhi_64(v);
-+      else
-+              write_c0_entryhi(v);
-+}
-+
-+/* TLB entry state for uniquification.  */
-+struct tlbent {
-+      unsigned long long wired:1;
-+      unsigned long long global:1;
-+      unsigned long long asid:10;
-+      unsigned long long vpn:51;
-+      unsigned long long pagesz:5;
-+      unsigned long long index:14;
-+};
-+
-+/*
-+ * Comparison function for TLB entry sorting.  Place wired entries first,
-+ * then global entries, then order by the increasing VPN/ASID and the
-+ * decreasing page size.  This lets us avoid clashes with wired entries
-+ * easily and get entries for larger pages out of the way first.
-+ *
-+ * We could group bits so as to reduce the number of comparisons, but this
-+ * is seldom executed and not performance-critical, so prefer legibility.
-+ */
-+static int r4k_entry_cmp(const void *a, const void *b)
- {
--      long v = *(unsigned long *)a - *(unsigned long *)b;
--      int s = sizeof(long) > sizeof(int) ? sizeof(long) * 8 - 1: 0;
--      return s ? (v != 0) | v >> s : v;
-+      struct tlbent ea = *(struct tlbent *)a, eb = *(struct tlbent *)b;
-+
-+      if (ea.wired > eb.wired)
-+              return -1;
-+      else if (ea.wired < eb.wired)
-+              return 1;
-+      else if (ea.global > eb.global)
-+              return -1;
-+      else if (ea.global < eb.global)
-+              return 1;
-+      else if (ea.vpn < eb.vpn)
-+              return -1;
-+      else if (ea.vpn > eb.vpn)
-+              return 1;
-+      else if (ea.asid < eb.asid)
-+              return -1;
-+      else if (ea.asid > eb.asid)
-+              return 1;
-+      else if (ea.pagesz > eb.pagesz)
-+              return -1;
-+      else if (ea.pagesz < eb.pagesz)
-+              return 1;
-+      else
-+              return 0;
-+}
-+
-+/*
-+ * Fetch all the TLB entries.  Mask individual VPN values retrieved with
-+ * the corresponding page mask and ignoring any 1KiB extension as we'll
-+ * be using 4KiB pages for uniquification.
-+ */
-+static void __ref r4k_tlb_uniquify_read(struct tlbent *tlb_vpns, int tlbsize)
-+{
-+      int start = num_wired_entries();
-+      unsigned long long vpn_mask;
-+      bool global;
-+      int i;
-+
-+      vpn_mask = GENMASK(current_cpu_data.vmbits - 1, VPN2_SHIFT);
-+      vpn_mask |= cpu_has_64bits ? 3ULL << 62 : 1 << 31;
-+
-+      for (i = 0; i < tlbsize; i++) {
-+              unsigned long long entryhi, vpn, mask, asid;
-+              unsigned int pagesz;
-+
-+              write_c0_index(i);
-+              mtc0_tlbr_hazard();
-+              tlb_read();
-+              tlb_read_hazard();
-+
-+              global = !!(read_c0_entrylo0() & ENTRYLO_G);
-+              entryhi = read_c0_entryhi_native();
-+              mask = read_c0_pagemask();
-+
-+              asid = entryhi & cpu_asid_mask(&current_cpu_data);
-+              vpn = (entryhi & vpn_mask & ~mask) >> VPN2_SHIFT;
-+              pagesz = ilog2((mask >> VPN2_SHIFT) + 1);
-+
-+              tlb_vpns[i].global = global;
-+              tlb_vpns[i].asid = global ? 0 : asid;
-+              tlb_vpns[i].vpn = vpn;
-+              tlb_vpns[i].pagesz = pagesz;
-+              tlb_vpns[i].wired = i < start;
-+              tlb_vpns[i].index = i;
-+      }
-+}
-+
-+/*
-+ * Write unique values to all but the wired TLB entries each, using
-+ * the 4KiB page size.  This size might not be supported with R6, but
-+ * EHINV is mandatory for R6, so we won't ever be called in that case.
-+ *
-+ * A sorted table is supplied with any wired entries at the beginning,
-+ * followed by any global entries, and then finally regular entries.
-+ * We start at the VPN and ASID values of zero and only assign user
-+ * addresses, therefore guaranteeing no clash with addresses produced
-+ * by UNIQUE_ENTRYHI.  We avoid any VPN values used by wired or global
-+ * entries, by increasing the VPN value beyond the span of such entry.
-+ *
-+ * When a VPN/ASID clash is found with a regular entry we increment the
-+ * ASID instead until no VPN/ASID clash has been found or the ASID space
-+ * has been exhausted, in which case we increase the VPN value beyond
-+ * the span of the largest clashing entry.
-+ *
-+ * We do not need to be concerned about FTLB or MMID configurations as
-+ * those are required to implement the EHINV feature.
-+ */
-+static void __ref r4k_tlb_uniquify_write(struct tlbent *tlb_vpns, int tlbsize)
-+{
-+      unsigned long long asid, vpn, vpn_size, pagesz;
-+      int widx, gidx, idx, sidx, lidx, i;
-+
-+      vpn_size = 1ULL << (current_cpu_data.vmbits - VPN2_SHIFT);
-+      pagesz = ilog2((PM_4K >> VPN2_SHIFT) + 1);
-+
-+      write_c0_pagemask(PM_4K);
-+      write_c0_entrylo0(0);
-+      write_c0_entrylo1(0);
-+
-+      asid = 0;
-+      vpn = 0;
-+      widx = 0;
-+      gidx = 0;
-+      for (sidx = 0; sidx < tlbsize && tlb_vpns[sidx].wired; sidx++)
-+              ;
-+      for (lidx = sidx; lidx < tlbsize && tlb_vpns[lidx].global; lidx++)
-+              ;
-+      idx = gidx = sidx + 1;
-+      for (i = sidx; i < tlbsize; i++) {
-+              unsigned long long entryhi, vpn_pagesz = 0;
-+
-+              while (1) {
-+                      if (WARN_ON(vpn >= vpn_size)) {
-+                              dump_tlb_all();
-+                              /* Pray local_flush_tlb_all() will cope.  */
-+                              return;
-+                      }
-+
-+                      /* VPN must be below the next wired entry.  */
-+                      if (widx < sidx && vpn >= tlb_vpns[widx].vpn) {
-+                              vpn = max(vpn,
-+                                        (tlb_vpns[widx].vpn +
-+                                         (1ULL << tlb_vpns[widx].pagesz)));
-+                              asid = 0;
-+                              widx++;
-+                              continue;
-+                      }
-+                      /* VPN must be below the next global entry.  */
-+                      if (gidx < lidx && vpn >= tlb_vpns[gidx].vpn) {
-+                              vpn = max(vpn,
-+                                        (tlb_vpns[gidx].vpn +
-+                                         (1ULL << tlb_vpns[gidx].pagesz)));
-+                              asid = 0;
-+                              gidx++;
-+                              continue;
-+                      }
-+                      /* Try to find a free ASID so as to conserve VPNs.  */
-+                      if (idx < tlbsize && vpn == tlb_vpns[idx].vpn &&
-+                          asid == tlb_vpns[idx].asid) {
-+                              unsigned long long idx_pagesz;
-+
-+                              idx_pagesz = tlb_vpns[idx].pagesz;
-+                              vpn_pagesz = max(vpn_pagesz, idx_pagesz);
-+                              do
-+                                      idx++;
-+                              while (idx < tlbsize &&
-+                                     vpn == tlb_vpns[idx].vpn &&
-+                                     asid == tlb_vpns[idx].asid);
-+                              asid++;
-+                              if (asid > cpu_asid_mask(&current_cpu_data)) {
-+                                      vpn += vpn_pagesz;
-+                                      asid = 0;
-+                                      vpn_pagesz = 0;
-+                              }
-+                              continue;
-+                      }
-+                      /* VPN mustn't be above the next regular entry.  */
-+                      if (idx < tlbsize && vpn > tlb_vpns[idx].vpn) {
-+                              vpn = max(vpn,
-+                                        (tlb_vpns[idx].vpn +
-+                                         (1ULL << tlb_vpns[idx].pagesz)));
-+                              asid = 0;
-+                              idx++;
-+                              continue;
-+                      }
-+                      break;
-+              }
-+
-+              entryhi = (vpn << VPN2_SHIFT) | asid;
-+              write_c0_entryhi_native(entryhi);
-+              write_c0_index(tlb_vpns[i].index);
-+              mtc0_tlbw_hazard();
-+              tlb_write_indexed();
-+
-+              tlb_vpns[i].asid = asid;
-+              tlb_vpns[i].vpn = vpn;
-+              tlb_vpns[i].pagesz = pagesz;
-+
-+              asid++;
-+              if (asid > cpu_asid_mask(&current_cpu_data)) {
-+                      vpn += 1ULL << pagesz;
-+                      asid = 0;
-+              }
-+      }
- }
- /*
-@@ -527,14 +746,8 @@ static void __ref r4k_tlb_uniquify(void)
- {
-       int tlbsize = current_cpu_data.tlbsize;
-       bool use_slab = slab_is_available();
--      int start = num_wired_entries();
-       phys_addr_t tlb_vpn_size;
--      unsigned long *tlb_vpns;
--      unsigned long vpn_mask;
--      int cnt, ent, idx, i;
--
--      vpn_mask = GENMASK(cpu_vmbits - 1, 13);
--      vpn_mask |= IS_ENABLED(CONFIG_64BIT) ? 3ULL << 62 : 1 << 31;
-+      struct tlbent *tlb_vpns;
-       tlb_vpn_size = tlbsize * sizeof(*tlb_vpns);
-       tlb_vpns = (use_slab ?
-@@ -545,52 +758,13 @@ static void __ref r4k_tlb_uniquify(void)
-       htw_stop();
--      for (i = start, cnt = 0; i < tlbsize; i++, cnt++) {
--              unsigned long vpn;
-+      r4k_tlb_uniquify_read(tlb_vpns, tlbsize);
--              write_c0_index(i);
--              mtc0_tlbr_hazard();
--              tlb_read();
--              tlb_read_hazard();
--              vpn = read_c0_entryhi();
--              vpn &= vpn_mask & PAGE_MASK;
--              tlb_vpns[cnt] = vpn;
--
--              /* Prevent any large pages from overlapping regular ones.  */
--              write_c0_pagemask(read_c0_pagemask() & PM_DEFAULT_MASK);
--              mtc0_tlbw_hazard();
--              tlb_write_indexed();
--              tlbw_use_hazard();
--      }
-+      sort(tlb_vpns, tlbsize, sizeof(*tlb_vpns), r4k_entry_cmp, NULL);
--      sort(tlb_vpns, cnt, sizeof(tlb_vpns[0]), r4k_vpn_cmp, NULL);
-+      r4k_tlb_uniquify_write(tlb_vpns, tlbsize);
-       write_c0_pagemask(PM_DEFAULT_MASK);
--      write_c0_entrylo0(0);
--      write_c0_entrylo1(0);
--
--      idx = 0;
--      ent = tlbsize;
--      for (i = start; i < tlbsize; i++)
--              while (1) {
--                      unsigned long entryhi, vpn;
--
--                      entryhi = UNIQUE_ENTRYHI(ent);
--                      vpn = entryhi & vpn_mask & PAGE_MASK;
--
--                      if (idx >= cnt || vpn < tlb_vpns[idx]) {
--                              write_c0_entryhi(entryhi);
--                              write_c0_index(i);
--                              mtc0_tlbw_hazard();
--                              tlb_write_indexed();
--                              ent++;
--                              break;
--                      } else if (vpn == tlb_vpns[idx]) {
--                              ent++;
--                      } else {
--                              idx++;
--                      }
--              }
-       tlbw_use_hazard();
-       htw_start();
index 951153965267de7b4626d9cf146425612a39d19d..dc4e9819ff41ed8ec4449c568b91ddab9f4487c2 100644 (file)
@@ -143,7 +143,6 @@ bluetooth-smp-derive-legacy-responder-stk-authentication-from-mitm-state.patch
 bluetooth-smp-force-responder-mitm-requirements-before-building-the-pairing-response.patch
 bluetooth-hci_sync-fix-stack-buffer-overflow-in-hci_le_big_create_sync.patch
 ksmbd-fix-oob-write-in-query_info-for-compound-requests.patch
-mips-mm-rewrite-tlb-uniquification-for-the-hidden-bit-feature.patch
 mips-sibyte-bring-back-cache-initialisation.patch
 mips-fix-the-gcc-version-check-for-__multi3-workaround.patch
 hwmon-occ-fix-division-by-zero-in-occ_show_power_1.patch
index 675adb018155ea59fc164b9ab3043949bf096993..fb2a44505dc313f062e5925d467fad584957fd8b 100644 (file)
@@ -53,7 +53,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 
 --- a/arch/mips/mm/tlb-r4k.c
 +++ b/arch/mips/mm/tlb-r4k.c
-@@ -751,7 +751,7 @@ static void __ref r4k_tlb_uniquify(void)
+@@ -538,7 +538,7 @@ static void __ref r4k_tlb_uniquify(void)
  
        tlb_vpn_size = tlbsize * sizeof(*tlb_vpns);
        tlb_vpns = (use_slab ?
diff --git a/queue-6.19/mips-mm-rewrite-tlb-uniquification-for-the-hidden-bit-feature.patch b/queue-6.19/mips-mm-rewrite-tlb-uniquification-for-the-hidden-bit-feature.patch
deleted file mode 100644 (file)
index 561c912..0000000
+++ /dev/null
@@ -1,373 +0,0 @@
-From 540760b77b8fc49d39d1b2b76196e5ec57711a32 Mon Sep 17 00:00:00 2001
-From: "Maciej W. Rozycki" <macro@orcam.me.uk>
-Date: Fri, 27 Mar 2026 18:57:30 +0000
-Subject: MIPS: mm: Rewrite TLB uniquification for the hidden bit feature
-
-From: Maciej W. Rozycki <macro@orcam.me.uk>
-
-commit 540760b77b8fc49d39d1b2b76196e5ec57711a32 upstream.
-
-Before the introduction of the EHINV feature, which lets software mark
-TLB entries invalid, certain older implementations of the MIPS ISA were
-equipped with an analogous bit, as a vendor extension, which however is
-hidden from software and only ever set at reset, and then any software
-write clears it, making the intended TLB entry valid.
-
-This feature makes it unsafe to read a TLB entry with TLBR, modify the
-page mask, and write the entry back with TLBWI, because this operation
-will implicitly clear the hidden bit and this may create a duplicate
-entry, as with the presence of the hidden bit there is no guarantee all
-the entries across the TLB are unique each.
-
-Usually the firmware has already uniquified TLB entries before handing
-control over, in which case we only need to guarantee at bootstrap no
-clash will happen with the VPN2 values chosen in local_flush_tlb_all().
-
-However with systems such as Mikrotik RB532 we get handed the TLB as at
-reset, with the hidden bit set across the entries and possibly duplicate
-entries present.  This then causes a machine check exception when page
-sizes are reset in r4k_tlb_uniquify() and prevents the system from
-booting.
-
-Rewrite the algorithm used in r4k_tlb_uniquify() then such as to avoid
-the reuse of ASID/VPN values across the TLB.  Get rid of global entries
-first as they may be blocking the entire address space, e.g. 16 256MiB
-pages will exhaust the whole address space of a 32-bit CPU and a single
-big page can exhaust the 32-bit compatibility space on a 64-bit CPU.
-
-Details of the algorithm chosen are given across the code itself.
-
-Fixes: 9f048fa48740 ("MIPS: mm: Prevent a TLB shutdown on initial uniquification")
-Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
-Cc: stable@vger.kernel.org # v6.18+
-Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- arch/mips/mm/tlb-r4k.c |  282 +++++++++++++++++++++++++++++++++++++++----------
- 1 file changed, 228 insertions(+), 54 deletions(-)
-
---- a/arch/mips/mm/tlb-r4k.c
-+++ b/arch/mips/mm/tlb-r4k.c
-@@ -13,6 +13,7 @@
- #include <linux/sched.h>
- #include <linux/smp.h>
- #include <linux/memblock.h>
-+#include <linux/minmax.h>
- #include <linux/mm.h>
- #include <linux/hugetlb.h>
- #include <linux/export.h>
-@@ -24,6 +25,7 @@
- #include <asm/hazards.h>
- #include <asm/mmu_context.h>
- #include <asm/tlb.h>
-+#include <asm/tlbdebug.h>
- #include <asm/tlbex.h>
- #include <asm/tlbmisc.h>
- #include <asm/setup.h>
-@@ -511,12 +513,229 @@ static int __init set_ntlb(char *str)
- __setup("ntlb=", set_ntlb);
--/* Comparison function for EntryHi VPN fields.  */
--static int r4k_vpn_cmp(const void *a, const void *b)
-+/* The start bit position of VPN2 and Mask in EntryHi/PageMask registers.  */
-+#define VPN2_SHIFT 13
-+
-+/* Read full EntryHi even with CONFIG_32BIT.  */
-+static inline unsigned long long read_c0_entryhi_native(void)
-+{
-+      return cpu_has_64bits ? read_c0_entryhi_64() : read_c0_entryhi();
-+}
-+
-+/* Write full EntryHi even with CONFIG_32BIT.  */
-+static inline void write_c0_entryhi_native(unsigned long long v)
-+{
-+      if (cpu_has_64bits)
-+              write_c0_entryhi_64(v);
-+      else
-+              write_c0_entryhi(v);
-+}
-+
-+/* TLB entry state for uniquification.  */
-+struct tlbent {
-+      unsigned long long wired:1;
-+      unsigned long long global:1;
-+      unsigned long long asid:10;
-+      unsigned long long vpn:51;
-+      unsigned long long pagesz:5;
-+      unsigned long long index:14;
-+};
-+
-+/*
-+ * Comparison function for TLB entry sorting.  Place wired entries first,
-+ * then global entries, then order by the increasing VPN/ASID and the
-+ * decreasing page size.  This lets us avoid clashes with wired entries
-+ * easily and get entries for larger pages out of the way first.
-+ *
-+ * We could group bits so as to reduce the number of comparisons, but this
-+ * is seldom executed and not performance-critical, so prefer legibility.
-+ */
-+static int r4k_entry_cmp(const void *a, const void *b)
- {
--      long v = *(unsigned long *)a - *(unsigned long *)b;
--      int s = sizeof(long) > sizeof(int) ? sizeof(long) * 8 - 1: 0;
--      return s ? (v != 0) | v >> s : v;
-+      struct tlbent ea = *(struct tlbent *)a, eb = *(struct tlbent *)b;
-+
-+      if (ea.wired > eb.wired)
-+              return -1;
-+      else if (ea.wired < eb.wired)
-+              return 1;
-+      else if (ea.global > eb.global)
-+              return -1;
-+      else if (ea.global < eb.global)
-+              return 1;
-+      else if (ea.vpn < eb.vpn)
-+              return -1;
-+      else if (ea.vpn > eb.vpn)
-+              return 1;
-+      else if (ea.asid < eb.asid)
-+              return -1;
-+      else if (ea.asid > eb.asid)
-+              return 1;
-+      else if (ea.pagesz > eb.pagesz)
-+              return -1;
-+      else if (ea.pagesz < eb.pagesz)
-+              return 1;
-+      else
-+              return 0;
-+}
-+
-+/*
-+ * Fetch all the TLB entries.  Mask individual VPN values retrieved with
-+ * the corresponding page mask and ignoring any 1KiB extension as we'll
-+ * be using 4KiB pages for uniquification.
-+ */
-+static void __ref r4k_tlb_uniquify_read(struct tlbent *tlb_vpns, int tlbsize)
-+{
-+      int start = num_wired_entries();
-+      unsigned long long vpn_mask;
-+      bool global;
-+      int i;
-+
-+      vpn_mask = GENMASK(current_cpu_data.vmbits - 1, VPN2_SHIFT);
-+      vpn_mask |= cpu_has_64bits ? 3ULL << 62 : 1 << 31;
-+
-+      for (i = 0; i < tlbsize; i++) {
-+              unsigned long long entryhi, vpn, mask, asid;
-+              unsigned int pagesz;
-+
-+              write_c0_index(i);
-+              mtc0_tlbr_hazard();
-+              tlb_read();
-+              tlb_read_hazard();
-+
-+              global = !!(read_c0_entrylo0() & ENTRYLO_G);
-+              entryhi = read_c0_entryhi_native();
-+              mask = read_c0_pagemask();
-+
-+              asid = entryhi & cpu_asid_mask(&current_cpu_data);
-+              vpn = (entryhi & vpn_mask & ~mask) >> VPN2_SHIFT;
-+              pagesz = ilog2((mask >> VPN2_SHIFT) + 1);
-+
-+              tlb_vpns[i].global = global;
-+              tlb_vpns[i].asid = global ? 0 : asid;
-+              tlb_vpns[i].vpn = vpn;
-+              tlb_vpns[i].pagesz = pagesz;
-+              tlb_vpns[i].wired = i < start;
-+              tlb_vpns[i].index = i;
-+      }
-+}
-+
-+/*
-+ * Write unique values to all but the wired TLB entries each, using
-+ * the 4KiB page size.  This size might not be supported with R6, but
-+ * EHINV is mandatory for R6, so we won't ever be called in that case.
-+ *
-+ * A sorted table is supplied with any wired entries at the beginning,
-+ * followed by any global entries, and then finally regular entries.
-+ * We start at the VPN and ASID values of zero and only assign user
-+ * addresses, therefore guaranteeing no clash with addresses produced
-+ * by UNIQUE_ENTRYHI.  We avoid any VPN values used by wired or global
-+ * entries, by increasing the VPN value beyond the span of such entry.
-+ *
-+ * When a VPN/ASID clash is found with a regular entry we increment the
-+ * ASID instead until no VPN/ASID clash has been found or the ASID space
-+ * has been exhausted, in which case we increase the VPN value beyond
-+ * the span of the largest clashing entry.
-+ *
-+ * We do not need to be concerned about FTLB or MMID configurations as
-+ * those are required to implement the EHINV feature.
-+ */
-+static void __ref r4k_tlb_uniquify_write(struct tlbent *tlb_vpns, int tlbsize)
-+{
-+      unsigned long long asid, vpn, vpn_size, pagesz;
-+      int widx, gidx, idx, sidx, lidx, i;
-+
-+      vpn_size = 1ULL << (current_cpu_data.vmbits - VPN2_SHIFT);
-+      pagesz = ilog2((PM_4K >> VPN2_SHIFT) + 1);
-+
-+      write_c0_pagemask(PM_4K);
-+      write_c0_entrylo0(0);
-+      write_c0_entrylo1(0);
-+
-+      asid = 0;
-+      vpn = 0;
-+      widx = 0;
-+      gidx = 0;
-+      for (sidx = 0; sidx < tlbsize && tlb_vpns[sidx].wired; sidx++)
-+              ;
-+      for (lidx = sidx; lidx < tlbsize && tlb_vpns[lidx].global; lidx++)
-+              ;
-+      idx = gidx = sidx + 1;
-+      for (i = sidx; i < tlbsize; i++) {
-+              unsigned long long entryhi, vpn_pagesz = 0;
-+
-+              while (1) {
-+                      if (WARN_ON(vpn >= vpn_size)) {
-+                              dump_tlb_all();
-+                              /* Pray local_flush_tlb_all() will cope.  */
-+                              return;
-+                      }
-+
-+                      /* VPN must be below the next wired entry.  */
-+                      if (widx < sidx && vpn >= tlb_vpns[widx].vpn) {
-+                              vpn = max(vpn,
-+                                        (tlb_vpns[widx].vpn +
-+                                         (1ULL << tlb_vpns[widx].pagesz)));
-+                              asid = 0;
-+                              widx++;
-+                              continue;
-+                      }
-+                      /* VPN must be below the next global entry.  */
-+                      if (gidx < lidx && vpn >= tlb_vpns[gidx].vpn) {
-+                              vpn = max(vpn,
-+                                        (tlb_vpns[gidx].vpn +
-+                                         (1ULL << tlb_vpns[gidx].pagesz)));
-+                              asid = 0;
-+                              gidx++;
-+                              continue;
-+                      }
-+                      /* Try to find a free ASID so as to conserve VPNs.  */
-+                      if (idx < tlbsize && vpn == tlb_vpns[idx].vpn &&
-+                          asid == tlb_vpns[idx].asid) {
-+                              unsigned long long idx_pagesz;
-+
-+                              idx_pagesz = tlb_vpns[idx].pagesz;
-+                              vpn_pagesz = max(vpn_pagesz, idx_pagesz);
-+                              do
-+                                      idx++;
-+                              while (idx < tlbsize &&
-+                                     vpn == tlb_vpns[idx].vpn &&
-+                                     asid == tlb_vpns[idx].asid);
-+                              asid++;
-+                              if (asid > cpu_asid_mask(&current_cpu_data)) {
-+                                      vpn += vpn_pagesz;
-+                                      asid = 0;
-+                                      vpn_pagesz = 0;
-+                              }
-+                              continue;
-+                      }
-+                      /* VPN mustn't be above the next regular entry.  */
-+                      if (idx < tlbsize && vpn > tlb_vpns[idx].vpn) {
-+                              vpn = max(vpn,
-+                                        (tlb_vpns[idx].vpn +
-+                                         (1ULL << tlb_vpns[idx].pagesz)));
-+                              asid = 0;
-+                              idx++;
-+                              continue;
-+                      }
-+                      break;
-+              }
-+
-+              entryhi = (vpn << VPN2_SHIFT) | asid;
-+              write_c0_entryhi_native(entryhi);
-+              write_c0_index(tlb_vpns[i].index);
-+              mtc0_tlbw_hazard();
-+              tlb_write_indexed();
-+
-+              tlb_vpns[i].asid = asid;
-+              tlb_vpns[i].vpn = vpn;
-+              tlb_vpns[i].pagesz = pagesz;
-+
-+              asid++;
-+              if (asid > cpu_asid_mask(&current_cpu_data)) {
-+                      vpn += 1ULL << pagesz;
-+                      asid = 0;
-+              }
-+      }
- }
- /*
-@@ -527,14 +746,8 @@ static void __ref r4k_tlb_uniquify(void)
- {
-       int tlbsize = current_cpu_data.tlbsize;
-       bool use_slab = slab_is_available();
--      int start = num_wired_entries();
-       phys_addr_t tlb_vpn_size;
--      unsigned long *tlb_vpns;
--      unsigned long vpn_mask;
--      int cnt, ent, idx, i;
--
--      vpn_mask = GENMASK(cpu_vmbits - 1, 13);
--      vpn_mask |= IS_ENABLED(CONFIG_64BIT) ? 3ULL << 62 : 1 << 31;
-+      struct tlbent *tlb_vpns;
-       tlb_vpn_size = tlbsize * sizeof(*tlb_vpns);
-       tlb_vpns = (use_slab ?
-@@ -545,52 +758,13 @@ static void __ref r4k_tlb_uniquify(void)
-       htw_stop();
--      for (i = start, cnt = 0; i < tlbsize; i++, cnt++) {
--              unsigned long vpn;
-+      r4k_tlb_uniquify_read(tlb_vpns, tlbsize);
--              write_c0_index(i);
--              mtc0_tlbr_hazard();
--              tlb_read();
--              tlb_read_hazard();
--              vpn = read_c0_entryhi();
--              vpn &= vpn_mask & PAGE_MASK;
--              tlb_vpns[cnt] = vpn;
--
--              /* Prevent any large pages from overlapping regular ones.  */
--              write_c0_pagemask(read_c0_pagemask() & PM_DEFAULT_MASK);
--              mtc0_tlbw_hazard();
--              tlb_write_indexed();
--              tlbw_use_hazard();
--      }
-+      sort(tlb_vpns, tlbsize, sizeof(*tlb_vpns), r4k_entry_cmp, NULL);
--      sort(tlb_vpns, cnt, sizeof(tlb_vpns[0]), r4k_vpn_cmp, NULL);
-+      r4k_tlb_uniquify_write(tlb_vpns, tlbsize);
-       write_c0_pagemask(PM_DEFAULT_MASK);
--      write_c0_entrylo0(0);
--      write_c0_entrylo1(0);
--
--      idx = 0;
--      ent = tlbsize;
--      for (i = start; i < tlbsize; i++)
--              while (1) {
--                      unsigned long entryhi, vpn;
--
--                      entryhi = UNIQUE_ENTRYHI(ent);
--                      vpn = entryhi & vpn_mask & PAGE_MASK;
--
--                      if (idx >= cnt || vpn < tlb_vpns[idx]) {
--                              write_c0_entryhi(entryhi);
--                              write_c0_index(i);
--                              mtc0_tlbw_hazard();
--                              tlb_write_indexed();
--                              ent++;
--                              break;
--                      } else if (vpn == tlb_vpns[idx]) {
--                              ent++;
--                      } else {
--                              idx++;
--                      }
--              }
-       tlbw_use_hazard();
-       htw_start();
index 63c169a6846ae076ca8aa74300ebe1ba35826f12..a5239eba565b9390e21b3fb0b855777155c81347 100644 (file)
@@ -181,7 +181,6 @@ bluetooth-smp-force-responder-mitm-requirements-before-building-the-pairing-resp
 bluetooth-hci_sync-fix-stack-buffer-overflow-in-hci_le_big_create_sync.patch
 bluetooth-hci_event-move-wake-reason-storage-into-validated-event-handlers.patch
 ksmbd-fix-oob-write-in-query_info-for-compound-requests.patch
-mips-mm-rewrite-tlb-uniquification-for-the-hidden-bit-feature.patch
 mips-sibyte-bring-back-cache-initialisation.patch
 mips-fix-the-gcc-version-check-for-__multi3-workaround.patch
 hwmon-occ-fix-division-by-zero-in-occ_show_power_1.patch