patch-2.4.21 linux-2.4.21/arch/ia64/sn/kernel/misctest.c

Next file: linux-2.4.21/arch/ia64/sn/kernel/setup.c
Previous file: linux-2.4.21/arch/ia64/sn/kernel/mca.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.20/arch/ia64/sn/kernel/misctest.c linux-2.4.21/arch/ia64/sn/kernel/misctest.c
@@ -4,119 +4,368 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2000-2001 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2000-2002 Silicon Graphics, Inc. All rights reserved.
  */
 
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/interrupt.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/sn_cpuid.h>
 #include <asm/processor.h>
 #include <asm/pgtable.h>
-
+#include <asm/page.h>
+#include <asm/timex.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/sn/intr.h>
+#include <asm/hw_irq.h>
+#include <asm/sn/leds.h>
 
 extern	int autotest_enabled;
-int	mcatest=0;
-
+long	mcatest=0, debug0, debug1, debug2, debug3;
 
+#define HDELAY(t)	(IS_RUNNING_ON_SIMULATOR() ? udelay(1) : udelay(t))
 
 /* 
  * mcatest
- *	1 = expected MCA
- *	2 = unexpected MCA
- *	3 = expected MCA + unexpected MCA
- *	4 = INIT
- *	5 = speculative load to garbage memory address
- *	6 = speculative load with ld8.s (needs poison hack in PROM)
- *	7 = speculative load from mis-predicted branch (needs poison hack in PROM)
+ *	mactest contains a decimal number (RPTT) where
+ *		R - flag, if non zero, run forever
+ *
+ *		P - identifies when to run the test
+ *		    0 execute test at cpu 0 early init
+ *		    1 execute test at cpu 0 idle
+ *		    2 execute test at last (highest numbered) cpu idle
+ *		    3 execute test on all cpus at idle
+ *
+ *		TT- identifies test to run
+ *		    01 = MCA via dup TLB dropin
+ *		    02 = MCA via garbage address
+ *		    03 = lfetch via garbage address
+ *		    05 = INIT self
+ *		    06 = INIT other cpu
+ *		    07 = INIT non-existent cpu
+ *		    10 = IPI stress test. Target cpu 0
+ *		    11 = IPI stress test. Target all cpus
+ *		    12 = TLB stress test
+ *		    13 = Park cpu (spinloop)
+ *		    14 = One shot TLB test with tlb spinlock
+ *		    15 = One shot TLB test
+ *		    16 = One shot TLB test sync'ed with RTC
+ *		    20 = set led to the cpuid & spin.
+ *		    21 = Try mixed cache/uncached refs & see what happens
+ *		    22 = Call SAL reboot
+ *		    23 = Call PAL halt
  */
 static int __init set_mcatest(char *str)
 {
-	get_option(&str, &mcatest);
+	int	val;
+	get_option(&str, &val);
+	mcatest = val;
 	return 1;
 }
-
 __setup("mcatest=", set_mcatest);
 
+static int __init set_debug0(char *str)
+{
+	int	val;
+	get_option(&str, &val);
+	debug0 = val;
+	return 1;
+}
+__setup("debug0=", set_debug0);
+
+static int __init set_debug1(char *str)
+{
+	int	val;
+	get_option(&str, &val);
+	debug1 = val;
+	return 1;
+}
+__setup("debug1=", set_debug1);
+
+static int __init set_debug2(char *str)
+{
+	int	val;
+	get_option(&str, &val);
+	debug2 = val;
+	return 1;
+}
+__setup("debug2=", set_debug2);
+
+static int __init set_debug3(char *str)
+{
+	int	val;
+	get_option(&str, &val);
+	debug3 = val;
+	return 1;
+}
+__setup("debug3=", set_debug3);
+
+static volatile int	go;
+
+static void
+do_sync(int pos) {
+	if (pos != 3)
+		return;
+	else if (smp_processor_id() == 0)
+		go = 1;
+	else
+		while (!go);
+}
+
+static void
+sgi_mcatest_bkpt(void)
+{
+}
+
+
+/*
+ * Optional test
+ *	pos - 0 called from early init
+ *	pos - called when cpu about to go idle (fully initialized
+ */
 void
-sgi_mcatest(void)
+sgi_mcatest(int pos)
 {
-	if (mcatest == 1 || mcatest == 3) {
-		long	*p, result, adrs[] = {0xc0000a000f021004UL, 0xc0000a000f026004UL, 0x800000000, 0x500000, 0};
-		long	size[] = {1,2,4,8};
-		int	r, i, j;
-		p = (long*)0xc000000000000000UL;
-		ia64_fc(p);
-		*p = 0x0123456789abcdefL;
-		for (i=0; i<5; i++) {
-			for (j=0; j<4; j++) {
-				printk("Probing 0x%lx, size %ld\n", adrs[i], size[j]);
-				result = -1;
-				r = ia64_sn_probe_io_slot (adrs[i], size[j], &result);
-				printk("    status %d, val 0x%lx\n", r, result); 
+	long	spos, test, repeat;
+	int	cpu, curcpu, i, n;
+
+	//if (IS_RUNNING_ON_SIMULATOR()) mcatest=1323;
+	repeat = mcatest/1000;
+	spos = (mcatest/100)%10;
+	test = mcatest % 100;
+	curcpu = smp_processor_id();
+
+	if ( mcatest == 0 || !((pos == 0 && spos == 0) ||
+		(pos == 1 && spos == 3) ||
+	        (pos == 1 && spos == 1 && curcpu == 0) ||
+	        (pos == 1 && spos == 2 && curcpu == smp_num_cpus-1)))
+		return;
+	     
+again:
+	if (test == 1 || test == 2 || test == 3) {
+		void zzzmca(int);
+		printk("CPU %d: About to cause unexpected MCA\n", curcpu);
+		HDELAY(100000);
+		sgi_mcatest_bkpt();
+		do_sync(spos);
+
+		zzzmca(test-1);
+	
+		HDELAY(100000);
+	}
+
+	if (test == 4) {
+		long    result, adrs[] = {0xe0021000009821e0UL, 0xc0003f3000000000UL, 0xc0000081101c0000UL, 0xc00000180e021004UL,  0xc00000180e022004UL, 0xc00000180e023004UL };
+		long    size[] = {1,2,4,8};
+		int     r, i, j, k;
+
+		for (k=0; k<2; k++) {
+			for (i=0; i<6; i++) {
+				for (j=0; j<4; j++) {
+					printk("Probing 0x%lx, size %ld\n", adrs[i], size[j]);
+					result = -1;
+					r = ia64_sn_probe_io_slot (adrs[i], size[j], &result);
+					printk("    status %d, val 0x%lx\n", r, result);
+					udelay(100000);
+				}
 			}
 		}
+
 	}
-	if (mcatest == 2 || mcatest == 3) {
-		void zzzmca(int, int, int);
-		printk("About to cause unexpected MCA\n");
-		zzzmca(mcatest, 0x32dead, 0x33dead);
-	}
-	if (mcatest == 4) {
-		long	*p;
-		int	delivery_mode = 5;
-		printk("About to try to cause an INIT on cpu 0\n");
-		p = (long*)((0xc0000a0000000000LL | ((long)get_nasid())<<33) | 0x1800080);
-		*p = (delivery_mode << 8);
-		udelay(10000);
-		printk("Returned from INIT\n");
-	}
-	if (mcatest == 5) {
-		int zzzspec(long);
-		int	i;
-		long	psr, dcr, res, val, addr=0xff00000000UL;
-
-		dcr = ia64_get_dcr();
-		for (i=0; i<5; i++) {
-			printk("Default DCR: 0x%lx\n", ia64_get_dcr());
-			printk("zzzspec: 0x%x\n", zzzspec(addr));
-			ia64_set_dcr(0);
-			printk("New     DCR: 0x%lx\n", ia64_get_dcr());
-			printk("zzzspec: 0x%x\n", zzzspec(addr));
-			ia64_set_dcr(dcr);
-			res = ia64_sn_probe_io_slot(0xff00000000UL, 8, &val);
-			printk("zzzspec: probe %ld, 0x%lx\n", res, val);
-			psr = ia64_clear_ic();
-			ia64_itc(0x2, 0xe00000ff00000000UL,
-			          pte_val(mk_pte_phys(0xff00000000UL,
-				  __pgprot(__DIRTY_BITS|_PAGE_PL_0|_PAGE_AR_RW))), _PAGE_SIZE_256M);
-			ia64_set_psr(psr);
-			ia64_srlz_i ();
-		}
 
+	if (test == 5) {
+		cpu =  curcpu;
+		printk("CPU %d: About to send INIT to self (cpu %d)\n", curcpu, cpu);
+		HDELAY(100000);
+		sgi_mcatest_bkpt();
+		do_sync(spos);
+
+		platform_send_ipi(cpu, 0, IA64_IPI_DM_INIT, 0);
+		
+		HDELAY(100000);
+		printk("CPU %d: Returned from INIT\n", curcpu);
+	}
+
+	if (test == 6) {
+		cpu =  curcpu ^ 1;
+		printk("CPU %d: About to send INIT to other cpu (cpu %d)\n", curcpu, cpu);
+		HDELAY(100000);
+		sgi_mcatest_bkpt();
+		do_sync(spos);
+
+		platform_send_ipi(cpu, 0, IA64_IPI_DM_INIT, 0);
+
+		HDELAY(100000);
+		printk("CPU %d: Done\n", curcpu);
+	}
+
+	if (test == 7) {
+		printk("CPU %d: About to send INIT to non-existent cpu\n", curcpu);
+		HDELAY(100000);
+		sgi_mcatest_bkpt();
+		do_sync(spos);
+
+		sn_send_IPI_phys(0xffff, 0, IA64_IPI_DM_INIT);
+
+		HDELAY(100000);
+		printk("CPU %d: Done\n", curcpu);
 	}
-	if (mcatest == 6) {
-		int zzzspec(long);
-		int	i;
-		long	dcr, addr=0xe000000008000000UL;
-
-		dcr = ia64_get_dcr();
-		for (i=0; i<5; i++) {
-			printk("zzzspec: 0x%x\n", zzzspec(addr));
-			ia64_set_dcr(0);
-		}
-		ia64_set_dcr(dcr);
-	}
-	if (mcatest == 7) {
-		int zzzspec2(long, long);
-		int	i;
-		long	addr=0xe000000008000000UL;
-		long	addr2=0xe000000007000000UL;
-
-		for (i=0; i<5; i++) {
-			printk("zzzspec2\n");
-			zzzspec2(addr, addr2);
+
+	if (test == 10) {
+		n = IS_RUNNING_ON_SIMULATOR() ? 10 : 10000000;
+		cpu = 0;
+		printk("CPU %d: IPI stress test. Target cpu 0\n", curcpu);
+		HDELAY(100000);
+		sgi_mcatest_bkpt();
+		do_sync(spos);
+
+		for (i=0; i<n; i++)
+			platform_send_ipi(cpu, IA64_IPI_RESCHEDULE, IA64_IPI_DM_INT, 0);
+
+		HDELAY(100000);
+		printk("CPU %d: Done\n", curcpu);
+	}
+
+	if (test == 11) {
+		n = IS_RUNNING_ON_SIMULATOR() ? 100 : 10000000;
+		printk("CPU %d: IPI stress test. Target all cpus\n", curcpu);
+		HDELAY(100000);
+		sgi_mcatest_bkpt();
+		do_sync(spos);
+
+		for (i=0; i<n; i++)
+			for (cpu=0; cpu<smp_num_cpus; cpu++)
+				if (smp_num_cpus > 2 && cpu != curcpu)
+					platform_send_ipi(cpu, IA64_IPI_RESCHEDULE, IA64_IPI_DM_INT, 0);
+
+		HDELAY(100000);
+		printk("CPU %d: Done\n", curcpu);
+	}
+
+	if (test == 12) {
+		long adr = 0xe002200000000000UL;
+		n = IS_RUNNING_ON_SIMULATOR() ? 1000 : 100000;
+		printk("CPU %d: TLB flush stress test\n", curcpu);
+		HDELAY(100000);
+		sgi_mcatest_bkpt();
+		do_sync(spos);
+
+		for (i=0; i<n; i++)
+			platform_global_tlb_purge(adr, adr+25*PAGE_SIZE, 14);
+
+		HDELAY(100000);
+		printk("CPU %d: Done\n", curcpu);
+	}
+	
+	if (test == 13) {
+		printk("CPU %d: Park cpu in spinloop\n", curcpu);
+		while(1);
+	}
+	if (test == 14 || test == 15 || test == 16 || test == 17) {
+		long adr = 0xe002200000000000UL;
+		static int inited=0;
+		if (inited == 0) {
+			if (debug0 == 0) debug0 = 1;
+			repeat = 1;
+			do_sync(spos);
+			if (curcpu >= smp_num_cpus-2) {
+				printk("Parking cpu %d\n", curcpu);
+				local_irq_disable();
+				while(1);
+			} else {
+				printk("Waiting cpu %d\n", curcpu);
+				HDELAY(1000000);
+			}
+			HDELAY(1000000);
+			inited = 1;
+		}
+		if (test == 16 || test == 17) {
+			unsigned long t, shift, mask;
+			mask =  (smp_num_cpus > 16) ? 0x1f : 0xf;
+			shift = 25-debug1;
+			do {
+				t = get_cycles();
+				if (IS_RUNNING_ON_SIMULATOR())
+					t = (t>>8);
+				else
+					t = (t>>shift);
+				t = t & mask;
+			} while (t == curcpu);
+			do {
+				t = get_cycles();
+				if (IS_RUNNING_ON_SIMULATOR())
+					t = (t>>8);
+				else
+					t = (t>>shift);
+				t = t & mask;
+			} while (t != curcpu);
+		}
+		if(debug3) printk("CPU %d: One TLB start\n", curcpu);
+		if (test != 17) platform_global_tlb_purge(adr, adr+PAGE_SIZE*debug0, 14);
+		if(debug3) printk("CPU %d: One TLB flush done\n", curcpu);
+	}
+	if (test == 20) {
+		local_irq_disable();
+		set_led_bits(smp_processor_id(), 0xff);
+		while(1);
+	}
+	if (test == 21) {
+		extern long ia64_mca_stack[];
+		int		i, n;
+		volatile long	*p, *up;
+		p = (volatile long*)__imva(ia64_mca_stack);
+		up = (volatile long*)(__pa(p) | __IA64_UNCACHED_OFFSET);
+
+		if(!IS_RUNNING_ON_SIMULATOR()) printk("ZZZ get data in cache\n");
+		for (n=0, i=0; i<100; i++)
+			n += *(p+i);
+		if(!IS_RUNNING_ON_SIMULATOR()) printk("ZZZ Make uncached refs to same data\n");
+		for (n=0, i=0; i<100; i++)
+			n += *(up+i);
+		if(!IS_RUNNING_ON_SIMULATOR()) printk("ZZZ dirty the data via cached refs\n");
+		for (n=0, i=0; i<100; i++)
+			*(p+i) = i;
+		if(!IS_RUNNING_ON_SIMULATOR()) printk("ZZZ Make uncached refs to same data\n");
+		for (n=0, i=0; i<100; i++)
+			n += *(up+i);
+		if(!IS_RUNNING_ON_SIMULATOR()) printk("ZZZ Flushing cache\n");
+		for (n=0, i=0; i<100; i++)
+			ia64_fc((void*)(p+i));
+		printk("ZZZ done\n");
+	}
+	if (test == 21) {
+		int i;
+		volatile long tb, t[10];
+		for (i=0; i<10; i++) {
+			tb = debug3+ia64_get_itc();
+			sgi_mcatest_bkpt();
+			t[i] = ia64_get_itc() - tb;
+		}
+		for (i=0; i<10; i++) {
+			printk("ZZZ NULL  0x%lx\n", t[i]);
+		}
+		for (i=0; i<10; i++) {
+			tb = debug3+ia64_get_itc();
+			ia64_pal_call_static(PAL_MC_DRAIN, 0, 0, 0, 0);
+			t[i] = ia64_get_itc() - tb;
 		}
+		for (i=0; i<10; i++) {
+			printk("ZZZ DRAIN 0x%lx\n", t[i]);
+		}
+	}
+	if (test == 22) {
+		extern void machine_restart(char*);
+		printk("ZZZ machine_restart\n");
+		machine_restart(0);
 	}
+	if (test == 23) {
+		printk("ZZZ ia64_pal_halt_light\n");
+		ia64_pal_halt_light();
+	}
+	if (repeat)
+		goto again;
+
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)