From ebd729fef31620e0bf74cbf8a4c7fda73a2a4e7e Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Mon, 20 Oct 2025 02:11:49 +0100 Subject: [PATCH 1/4] MIPS: Malta: Fix !EVA SOC-it PCI MMIO Fix a regression that has caused accesses to the PCI MMIO window to complete unclaimed in non-EVA configurations with the SOC-it family of system controllers, preventing PCI devices from working that use MMIO. In the non-EVA case PHYS_OFFSET is set to 0, meaning that PCI_BAR0 is set with an empty mask (and PCI_HEAD4 matches addresses starting from 0 accordingly). Consequently all addresses are matched for incoming DMA accesses from PCI. This seems to confuse the system controller's logic and outgoing bus cycles targeting the PCI MMIO window seem not to make it to the intended devices. This happens as well when a wider mask is used with PCI_BAR0, such as 0x80000000 or 0xe0000000, that makes addresses match that overlap with the PCI MMIO window, which starts at 0x10000000 in our configuration. Set the mask in PCI_BAR0 to 0xf0000000 for non-EVA then, covering the non-EVA maximum 256 MiB of RAM, which is what YAMON does and which used to work correctly up to the offending commit. Set PCI_P2SCMSKL to match PCI_BAR0 as required by the system controller's specification, and match PCI_P2SCMAPL to PCI_HEAD4 for identity mapping. Verified with: Core board type/revision = 0x0d (Core74K) / 0x01 System controller/revision = MIPS SOC-it 101 OCP / 1.3 SDR-FW-4:1 Processor Company ID/options = 0x01 (MIPS Technologies, Inc.) / 0x1c Processor ID/revision = 0x97 (MIPS 74Kf) / 0x4c for non-EVA and with: Core board type/revision = 0x0c (CoreFPGA-5) / 0x00 System controller/revision = MIPS ROC-it2 / 0.0 FW-1:1 (CLK_unknown) GIC Processor Company ID/options = 0x01 (MIPS Technologies, Inc.) / 0x00 Processor ID/revision = 0xa0 (MIPS interAptiv UP) / 0x20 for EVA/non-EVA, fixing: defxx 0000:00:12.0: assign IRQ: got 10 defxx: v1.12 2021/03/10 Lawrence V. Stefani and others 0000:00:12.0: Could not read adapter factory MAC address! vs: defxx 0000:00:12.0: assign IRQ: got 10 defxx: v1.12 2021/03/10 Lawrence V. Stefani and others 0000:00:12.0: DEFPA at MMIO addr = 0x10142000, IRQ = 10, Hardware addr = 00-00-f8-xx-xx-xx 0000:00:12.0: registered as fddi0 for non-EVA and causing no change for EVA. Signed-off-by: Maciej W. Rozycki Fixes: 422dd256642b ("MIPS: Malta: Allow PCI devices DMA to lower 2GB physical") Cc: stable@vger.kernel.org # v4.9+ Signed-off-by: Thomas Bogendoerfer --- arch/mips/mti-malta/malta-init.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/arch/mips/mti-malta/malta-init.c b/arch/mips/mti-malta/malta-init.c index 000d6d50520a..82b0fd8576a2 100644 --- a/arch/mips/mti-malta/malta-init.c +++ b/arch/mips/mti-malta/malta-init.c @@ -241,16 +241,22 @@ mips_pci_controller: #endif /* - * Setup the Malta max (2GB) memory for PCI DMA in host bridge - * in transparent addressing mode. + * Set up memory mapping in host bridge for PCI DMA masters, + * in transparent addressing mode. For EVA use the Malta + * maximum of 2 GiB memory in the alias space at 0x80000000 + * as per PHYS_OFFSET. Otherwise use 256 MiB of memory in + * the regular space, avoiding mapping the PCI MMIO window + * for DMA as it seems to confuse the system controller's + * logic, causing PCI MMIO to stop working. */ - mask = PHYS_OFFSET | PCI_BASE_ADDRESS_MEM_PREFETCH; - MSC_WRITE(MSC01_PCI_BAR0, mask); - MSC_WRITE(MSC01_PCI_HEAD4, mask); + mask = PHYS_OFFSET ? PHYS_OFFSET : 0xf0000000; + MSC_WRITE(MSC01_PCI_BAR0, + mask | PCI_BASE_ADDRESS_MEM_PREFETCH); + MSC_WRITE(MSC01_PCI_HEAD4, + PHYS_OFFSET | PCI_BASE_ADDRESS_MEM_PREFETCH); - mask &= MSC01_PCI_BAR0_SIZE_MSK; MSC_WRITE(MSC01_PCI_P2SCMSKL, mask); - MSC_WRITE(MSC01_PCI_P2SCMAPL, mask); + MSC_WRITE(MSC01_PCI_P2SCMAPL, PHYS_OFFSET); /* Don't handle target retries indefinitely. */ if ((data & MSC01_PCI_CFG_MAXRTRY_MSK) == From 09782e72eec451fa14d327595f86cdc338ebe53c Mon Sep 17 00:00:00 2001 From: Aleksander Jan Bajkowski Date: Fri, 17 Oct 2025 20:01:19 +0200 Subject: [PATCH 2/4] mips: dts: econet: fix EN751221 core type In fact, it is a multi-threaded MIPS34Kc, not a single-threaded MIPS24Kc. Fixes: 0ec488700972 ("mips: dts: Add EcoNet DTS with EN751221 and SmartFiber XP8421-B board") Signed-off-by: Aleksander Jan Bajkowski Signed-off-by: Thomas Bogendoerfer --- arch/mips/boot/dts/econet/en751221.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/boot/dts/econet/en751221.dtsi b/arch/mips/boot/dts/econet/en751221.dtsi index 66197e73d4f0..2abeef5b744a 100644 --- a/arch/mips/boot/dts/econet/en751221.dtsi +++ b/arch/mips/boot/dts/econet/en751221.dtsi @@ -18,7 +18,7 @@ cpu@0 { device_type = "cpu"; - compatible = "mips,mips24KEc"; + compatible = "mips,mips34Kc"; reg = <0>; }; }; From 9f048fa487409e364cf866c957cf0b0d782ca5a3 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Thu, 13 Nov 2025 05:21:10 +0000 Subject: [PATCH 3/4] MIPS: mm: Prevent a TLB shutdown on initial uniquification Depending on the particular CPU implementation a TLB shutdown may occur if multiple matching entries are detected upon the execution of a TLBP or the TLBWI/TLBWR instructions. Given that we don't know what entries we have been handed we need to be very careful with the initial TLB setup and avoid all these instructions. Therefore read all the TLB entries one by one with the TLBR instruction, bypassing the content addressing logic, and truncate any large pages in place so as to avoid a case in the second step where an incoming entry for a large page at a lower address overlaps with a replacement entry chosen at another index. Then preinitialize the TLB using addresses outside our usual unique range and avoiding clashes with any entries received, before making the usual call to local_flush_tlb_all(). This fixes (at least) R4x00 cores if TLBP hits multiple matching TLB entries (SGI IP22 PROM for examples sets up all TLBs to the same virtual address). Signed-off-by: Maciej W. Rozycki Fixes: 35ad7e181541 ("MIPS: mm: tlb-r4k: Uniquify TLB entries on init") Cc: stable@vger.kernel.org Reviewed-by: Jiaxun Yang Tested-by: Jiaxun Yang # Boston I6400, M5150 sim Signed-off-by: Thomas Bogendoerfer --- arch/mips/mm/tlb-r4k.c | 102 ++++++++++++++++++++++++++--------------- 1 file changed, 64 insertions(+), 38 deletions(-) diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c index 347126dc010d..3facf7cc6c7d 100644 --- a/arch/mips/mm/tlb-r4k.c +++ b/arch/mips/mm/tlb-r4k.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -508,54 +509,78 @@ static int __init set_ntlb(char *str) __setup("ntlb=", set_ntlb); -/* Initialise all TLB entries with unique values */ + +/* Comparison function for EntryHi VPN fields. */ +static int r4k_vpn_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; +} + +/* + * Initialise all TLB entries with unique values that do not clash with + * what we have been handed over and what we'll be using ourselves. + */ static void r4k_tlb_uniquify(void) { - int entry = num_wired_entries(); + unsigned long tlb_vpns[1 << MIPS_CONF1_TLBS_SIZE]; + int tlbsize = current_cpu_data.tlbsize; + int start = num_wired_entries(); + 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; htw_stop(); + + for (i = start, cnt = 0; i < tlbsize; i++, cnt++) { + unsigned long vpn; + + 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, cnt, sizeof(tlb_vpns[0]), r4k_vpn_cmp, NULL); + + write_c0_pagemask(PM_DEFAULT_MASK); write_c0_entrylo0(0); write_c0_entrylo1(0); - while (entry < current_cpu_data.tlbsize) { - unsigned long asid_mask = cpu_asid_mask(¤t_cpu_data); - unsigned long asid = 0; - int idx; + idx = 0; + ent = tlbsize; + for (i = start; i < tlbsize; i++) + while (1) { + unsigned long entryhi, vpn; - /* Skip wired MMID to make ginvt_mmid work */ - if (cpu_has_mmid) - asid = MMID_KERNEL_WIRED + 1; + entryhi = UNIQUE_ENTRYHI(ent); + vpn = entryhi & vpn_mask & PAGE_MASK; - /* Check for match before using UNIQUE_ENTRYHI */ - do { - if (cpu_has_mmid) { - write_c0_memorymapid(asid); - write_c0_entryhi(UNIQUE_ENTRYHI(entry)); - } else { - write_c0_entryhi(UNIQUE_ENTRYHI(entry) | asid); - } - mtc0_tlbw_hazard(); - tlb_probe(); - tlb_probe_hazard(); - idx = read_c0_index(); - /* No match or match is on current entry */ - if (idx < 0 || idx == entry) + if (idx >= cnt || vpn < tlb_vpns[idx]) { + write_c0_entryhi(entryhi); + write_c0_index(i); + mtc0_tlbw_hazard(); + tlb_write_indexed(); + ent++; break; - /* - * If we hit a match, we need to try again with - * a different ASID. - */ - asid++; - } while (asid < asid_mask); - - if (idx >= 0 && idx != entry) - panic("Unable to uniquify TLB entry %d", idx); - - write_c0_index(entry); - mtc0_tlbw_hazard(); - tlb_write_indexed(); - entry++; - } + } else if (vpn == tlb_vpns[idx]) { + ent++; + } else { + idx++; + } + } tlbw_use_hazard(); htw_start(); @@ -602,6 +627,7 @@ static void r4k_tlb_configure(void) /* From this point on the ARC firmware is dead. */ r4k_tlb_uniquify(); + local_flush_tlb_all(); /* Did I tell you that ARC SUCKS? */ } From 14b46ba92bf547508b4a49370c99aba76cb53b53 Mon Sep 17 00:00:00 2001 From: Thomas Bogendoerfer Date: Thu, 20 Nov 2025 13:10:29 +0100 Subject: [PATCH 4/4] MIPS: kernel: Fix random segmentation faults MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 69896119dc9d ("MIPS: vdso: Switch to generic storage implementation") switches to a generic vdso storage, which increases the number of data pages from 1 to 4. But there is only one page reserved, which causes segementation faults depending where the VDSO area is randomized to. To fix this use the same size of reservation and allocation of the VDSO data pages. Fixes: 69896119dc9d ("MIPS: vdso: Switch to generic storage implementation") Reviewed-by: Thomas Weißschuh Reviewed-by: Huacai Chen Reviewed-by: Thomas Gleixner Signed-off-by: Thomas Bogendoerfer --- arch/mips/kernel/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 29191fa1801e..a3101f2268c6 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -692,7 +692,7 @@ unsigned long mips_stack_top(void) /* Space for the VDSO, data page & GIC user page */ if (current->thread.abi) { top -= PAGE_ALIGN(current->thread.abi->vdso->size); - top -= PAGE_SIZE; + top -= VDSO_NR_PAGES * PAGE_SIZE; top -= mips_gic_present() ? PAGE_SIZE : 0; /* Space to randomize the VDSO base */