patch-2.3.49 linux/arch/sparc64/kernel/smp.c

Next file: linux/arch/sparc64/kernel/sys_sparc32.c
Previous file: linux/arch/sparc64/kernel/process.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.48/linux/arch/sparc64/kernel/smp.c linux/arch/sparc64/kernel/smp.c
@@ -119,6 +119,7 @@
 void __init 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();
@@ -598,7 +618,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);
 
@@ -664,27 +684,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);
 }
 
 static void __init 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));
 }
 
 void __init 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)