patch-2.2.15 linux/arch/sparc64/kernel/smp.c
Next file: linux/arch/sparc64/kernel/sparc64_ksyms.c
Previous file: linux/arch/sparc64/kernel/signal32.c
Back to the patch index
Back to the overall index
- Lines: 204
- Date:
Fri Apr 21 12:45:48 2000
- Orig file:
v2.2.14/arch/sparc64/kernel/smp.c
- Orig date:
Tue Jan 4 21:18:43 2000
diff -u --new-file --recursive --exclude-from ../../exclude v2.2.14/arch/sparc64/kernel/smp.c linux/arch/sparc64/kernel/smp.c
@@ -119,6 +119,7 @@
__initfunc(void smp_callin(void))
{
int cpuid = hard_smp_processor_id();
+ unsigned long pstate;
inherit_locked_prom_mappings(0);
@@ -127,18 +128,37 @@
cpu_probe();
- /* Master did this already, now is the time for us to do it. */
+ /* Guarentee that the following sequences execute
+ * uninterrupted.
+ */
+ __asm__ __volatile__("rdpr %%pstate, %0\n\t"
+ "wrpr %0, %1, %%pstate"
+ : "=r" (pstate)
+ : "i" (PSTATE_IE));
+
+ /* Set things up so user can access tick register for profiling
+ * purposes. Also workaround BB_ERRATA_1 by doing a dummy
+ * read back of %tick after writing it.
+ */
__asm__ __volatile__("
sethi %%hi(0x80000000), %%g1
- sllx %%g1, 32, %%g1
- rd %%tick, %%g2
+ ba,pt %%xcc, 1f
+ sllx %%g1, 32, %%g1
+ .align 64
+1: rd %%tick, %%g2
add %%g2, 6, %%g2
andn %%g2, %%g1, %%g2
wrpr %%g2, 0, %%tick
-" : /* no outputs */
+ rdpr %%tick, %%g0"
+ : /* no outputs */
: /* no inputs */
: "g1", "g2");
+ /* Restore PSTATE_IE. */
+ __asm__ __volatile__("wrpr %0, 0x0, %%pstate"
+ : /* no outputs */
+ : "r" (pstate));
+
smp_setup_percpu_timer();
__sti();
@@ -159,7 +179,7 @@
}
extern int cpu_idle(void *unused);
-extern void init_IRQ(void);
+extern unsigned long init_IRQ(unsigned long);
void initialize_secondary(void)
{
@@ -168,7 +188,8 @@
int start_secondary(void *unused)
{
trap_init();
- init_IRQ();
+ /* No memory allocation allowed on slave IRQ init */
+ init_IRQ(0UL);
smp_callin();
return cpu_idle(NULL);
}
@@ -280,6 +301,13 @@
smp_processor_id(), data0, data1, data2, target);
#endif
again:
+ /* Ok, this is the real Spitfire Errata #54.
+ * One must read back from a UDB internal register
+ * after writes to the UDB interrupt dispatch, but
+ * before the membar Sync for that write.
+ * So we use the high UDB control register (ASI 0x7f,
+ * ADDR 0x20) for the dummy read. -DaveM
+ */
__asm__ __volatile__("
wrpr %0, %1, %%pstate
wr %%g0, %2, %%asi
@@ -288,10 +316,14 @@
stxa %5, [0x60] %%asi
membar #Sync
stxa %%g0, [%6] %%asi
+ membar #Sync
+ mov 0x20, %%g1
+ ldxa [%%g1] 0x7f, %%g0
membar #Sync"
: /* No outputs */
: "r" (pstate), "i" (PSTATE_IE), "i" (ASI_UDB_INTR_W),
- "r" (data0), "r" (data1), "r" (data2), "r" (target));
+ "r" (data0), "r" (data1), "r" (data2), "r" (target)
+ : "g1");
/* NOTE: PSTATE_IE is still clear. */
stuck = 100000;
@@ -589,7 +621,7 @@
void smp_percpu_timer_interrupt(struct pt_regs *regs)
{
- unsigned long compare, tick;
+ unsigned long compare, tick, pstate;
int cpu = smp_processor_id();
int user = user_mode(regs);
@@ -655,27 +687,87 @@
prof_counter(cpu) = prof_multiplier(cpu);
}
+ /* Guarentee that the following sequences execute
+ * uninterrupted.
+ */
+ __asm__ __volatile__("rdpr %%pstate, %0\n\t"
+ "wrpr %0, %1, %%pstate"
+ : "=r" (pstate)
+ : "i" (PSTATE_IE));
+
+ /* Workaround for Spitfire Errata (#54 I think??), I discovered
+ * this via Sun BugID 4008234, mentioned in Solaris-2.5.1 patch
+ * number 103640.
+ *
+ * On Blackbird writes to %tick_cmpr can fail, the
+ * workaround seems to be to execute the wr instruction
+ * at the start of an I-cache line, and perform a dummy
+ * read back from %tick_cmpr right after writing to it. -DaveM
+ *
+ * Just to be anal we add a workaround for Spitfire
+ * Errata 50 by preventing pipeline bypasses on the
+ * final read of the %tick register into a compare
+ * instruction. The Errata 50 description states
+ * that %tick is not prone to this bug, but I am not
+ * taking any chances.
+ */
__asm__ __volatile__("rd %%tick_cmpr, %0\n\t"
- "add %0, %2, %0\n\t"
- "wr %0, 0x0, %%tick_cmpr\n\t"
- "rd %%tick, %1"
+ "ba,pt %%xcc, 1f\n\t"
+ " add %0, %2, %0\n\t"
+ ".align 64\n"
+ "1: wr %0, 0x0, %%tick_cmpr\n\t"
+ "rd %%tick_cmpr, %%g0\n\t"
+ "rd %%tick, %1\n\t"
+ "mov %1, %1"
: "=&r" (compare), "=r" (tick)
: "r" (current_tick_offset));
+
+ /* Restore PSTATE_IE. */
+ __asm__ __volatile__("wrpr %0, 0x0, %%pstate"
+ : /* no outputs */
+ : "r" (pstate));
} while (tick >= compare);
}
__initfunc(static void smp_setup_percpu_timer(void))
{
int cpu = smp_processor_id();
+ unsigned long pstate;
prof_counter(cpu) = prof_multiplier(cpu) = 1;
- __asm__ __volatile__("rd %%tick, %%g1\n\t"
- "add %%g1, %0, %%g1\n\t"
- "wr %%g1, 0x0, %%tick_cmpr"
+ /* Guarentee that the following sequences execute
+ * uninterrupted.
+ */
+ __asm__ __volatile__("rdpr %%pstate, %0\n\t"
+ "wrpr %0, %1, %%pstate"
+ : "=r" (pstate)
+ : "i" (PSTATE_IE));
+
+ /* Workaround for Spitfire Errata (#54 I think??), I discovered
+ * this via Sun BugID 4008234, mentioned in Solaris-2.5.1 patch
+ * number 103640.
+ *
+ * On Blackbird writes to %tick_cmpr can fail, the
+ * workaround seems to be to execute the wr instruction
+ * at the start of an I-cache line, and perform a dummy
+ * read back from %tick_cmpr right after writing to it. -DaveM
+ */
+ __asm__ __volatile__("
+ rd %%tick, %%g1
+ ba,pt %%xcc, 1f
+ add %%g1, %0, %%g1
+ .align 64
+ 1: wr %%g1, 0x0, %%tick_cmpr
+ rd %%tick_cmpr, %%g0"
+ : /* no outputs */
+ : "r" (current_tick_offset)
+ : "g1");
+
+ /* Restore PSTATE_IE. */
+ __asm__ __volatile__("wrpr %0, 0x0, %%pstate"
: /* no outputs */
- : "r" (current_tick_offset)
- : "g1");
+ : "r" (pstate));
}
__initfunc(void smp_tick_init(void))
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)