Skip to contentSkip to conversation

MIPS: SGI-IP27: Install the cache error vector on every CPU

PATCH In review Imre Kaloz 2 participants 3 messages Oct 26 MIPS

lore
Share & tools
lore

Imre Kaloz

author
#0 lore raw

PATCH v2 1/1 MIPS: SGI-IP27: Install the cache error vector on every CPU

The R10000 drives an uncached attribute on the bus, decoded by the hub. CKSEG1 uses attribute 0, UALIAS, whose low 128K is flipped by CPU slice (UALIAS_FLIP_BIT), so slice 1 reads CKSEG1 0x100 from node memory 0x10100. trap_init() writes the vector only through TO_UNCAC(), attribute 3, unflipped. Copy it on each secondary.

Fixes 1da177e4c3f4 ("Linux-2.6.12-rc2")

---
Changes in v2:
- Rewrote the message to explain the per-slice UALIAS flip that makes CKSEG1 0x100 differ from TO_UNCAC(0x100) on a secondary CPU.
- Stated in the message and in ip27_init_secondary() that the R10000 drives an uncached attribute on the bus that the hub decodes, attribute 0 for CKSEG1 and attribute 3 for TO_UNCAC().
- No code change.

 arch/mips/sgi-ip27/ip27-smp.c | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)
arch/mips/sgi-ip27/ip27-smp.c +17 -1
index 62733e049570..4c9a0d9b4417 100644
@@ -7,11 +7,13 @@
  * Copyright (C) 2000 - 2001 by Silicon Graphics, Inc.
  */
 #include <linux/init.h>
+#include <linux/string.h>
 #include <linux/sched.h>
 #include <linux/sched/task_stack.h>
 #include <linux/topology.h>
 #include <linux/nodemask.h>
 
+#include <asm/addrspace.h>
 #include <asm/page.h>
 #include <asm/processor.h>
 #include <asm/ptrace.h>
@@ -133,6 +135,20 @@ static void ip27_init_cpu(void)
 	per_cpu_init();
 }
 
+static void ip27_init_secondary(void)
+{
+	/*
+	 * The R10000 drives an uncached attribute on the bus and the hub
+	 * decodes it.  The cache error vector is fetched through CKSEG1,
+	 * attribute 0, whose low 128K the hub flips per CPU slice.
+	 * trap_init() wrote it through TO_UNCAC(), attribute 3, which is
+	 * not flipped, so that copy only serves slice 0.
+	 */
+	memcpy((void *)CKSEG1ADDR(0x100), (void *)TO_UNCAC(0x100), 0x80);
+
+	ip27_init_cpu();
+}
+
 static void ip27_smp_finish(void)
 {
 	hub_rt_clock_event_init();
@@ -182,7 +198,7 @@ static void __init ip27_prepare_cpus(unsigned int max_cpus)
 const struct plat_smp_ops ip27_smp_ops = {
 	.send_ipi_single	= ip27_send_ipi_single,
 	.send_ipi_mask		= ip27_send_ipi_mask,
-	.init_secondary		= ip27_init_cpu,
+	.init_secondary		= ip27_init_secondary,
 	.smp_finish		= ip27_smp_finish,
 	.boot_secondary		= ip27_boot_secondary,
 	.smp_setup		= ip27_smp_setup,

base-commit: 24a19b953e2a3d0ea5a8c4951a0ab8f32720c907

Signature · 1 line
2.47.3
#1 lore raw
Quoted 5 lines · Imre Kaloz

The R10000 drives an uncached attribute on the bus, decoded by the hub. CKSEG1 uses attribute 0, UALIAS, whose low 128K is flipped by CPU slice (UALIAS_FLIP_BIT), so slice 1 reads CKSEG1 0x100 from node memory 0x10100. trap_init() writes the vector only through TO_UNCAC(), attribute 3, unflipped. Copy it on each secondary.

OK, slice 1 gets 0xffffffffa0000100 virtual mapped to 0x10100 physical.

So does slice 0 get 0xffffffffa0000100 virtual mapped to 0x100 physical?
How about other slices? "Each secondary" suggests there are more than 2.

Not questioning the validity of the change, but trying to understand the
system topology.

Maciej

author
#2 lore raw
Quoted 11 lines · Maciej W. Rozycki
Quoted 5 lines · Imre Kaloz

The R10000 drives an uncached attribute on the bus, decoded by the hub. CKSEG1 uses attribute 0, UALIAS, whose low 128K is flipped by CPU slice (UALIAS_FLIP_BIT), so slice 1 reads CKSEG1 0x100 from node memory 0x10100. trap_init() writes the vector only through TO_UNCAC(), attribute 3, unflipped. Copy it on each secondary.

OK, slice 1 gets 0xffffffffa0000100 virtual mapped to 0x10100 physical.

So does slice 0 get 0xffffffffa0000100 virtual mapped to 0x100 physical?

Yes, only slice 1 is flipped. UALIAS is node-local, tho: slice 0 on node N reads node N's 0x100 and slice 1 node N's 0x10100.

Quoted 1 line

How about other slices? "Each secondary" suggests there are more than 2.

A hub has two slices, so the flip is the only difference within a node; "each secondary" means every non-boot CPU across all nodes. trap_init() writes node 0's 0x100, and per_hub_init() already copies node 0's low 0x200 bytes into every other node, so slice 0 is covered everywhere and slice 1 on every node was not. Doing the copy on every secondary keeps it simple; on a slice 0 CPU it rewrites what per_hub_init() put there.

Imre