Date: Tue, 27 Oct 1998 04:17:23 -0500 (EST)
From: Ion Badulescu <ionut@moisil.cs.columbia.edu>
To: sparclinux@vger.rutgers.edu
Subject: SMP mode on 4/600 w/ 4 CPU's: success
Hello,
I've finally found the bug which prevented 4-CPU machines from booting
under Linux/SPARC in SMP mode. The patch below fixes it, and does a few
other things:
o makes prom_printf() a macro which calls both the old prom_printf
(renamed as real_prom_printf) and printk. This way messages appear both on
dummycon (for debugging) and in dmesg's output for later study.
o changes a bunch of printk's to prom_printf's -- they are called before
the real console is initialized.
o adds a missing \n to a printk
If you have a 4/600 which had problems booting SMP before, I'd love to
hear if this patch fixes those problems.
A similar patch (for the SMP problem) should be applied to the 2.0 tree.
Thanks,
Ion
--
It is better to keep your mouth shut and be thought a fool,
than to open it and remove all doubt.
---------------------------
diff -urNX diff_excludes linux/arch/sparc/kernel/devices.c linux-local/arch/sparc/kernel/devices.c
--- linux/arch/sparc/kernel/devices.c Tue Oct 27 02:22:52 1998
+++ linux-local/arch/sparc/kernel/devices.c Tue Oct 27 00:07:44 1998
@@ -68,11 +68,11 @@
}
}
if(linux_num_cpus == 0) {
- printk("No CPU nodes found, cannot continue.\n");
+ prom_printf("No CPU nodes found, cannot continue.\n");
/* Probably a sun4e, Sun is trying to trick us ;-) */
halt();
}
- printk("Found %d CPU prom device tree node(s).\n", linux_num_cpus);
+ prom_printf("Found %d CPU prom device tree node(s).\n", linux_num_cpus);
};
cpu_probe();
diff -urNX diff_excludes linux/arch/sparc/kernel/idprom.c linux-local/arch/sparc/kernel/idprom.c
--- linux/arch/sparc/kernel/idprom.c Tue Oct 27 02:22:59 1998
+++ linux-local/arch/sparc/kernel/idprom.c Mon Oct 26 18:03:14 1998
@@ -54,11 +54,11 @@
for (i = 0; i < NUM_SUN_MACHINES; i++) {
if(Sun_Machines[i].id_machtype == machtype) {
if (machtype != (SM_SUN4M_OBP | 0x00))
- printk("TYPE: %s\n", Sun_Machines[i].name);
+ prom_printf("TYPE: %s\n", Sun_Machines[i].name);
else {
prom_getproperty(prom_root_node, "banner-name",
sysname, sizeof(sysname));
- printk("TYPE: %s\n", sysname);
+ prom_printf("TYPE: %s\n", sysname);
}
return;
}
@@ -99,7 +99,7 @@
display_system_type(idprom->id_machtype);
- printk("Ethernet address: %x:%x:%x:%x:%x:%x\n",
+ prom_printf("Ethernet address: %x:%x:%x:%x:%x:%x\n",
idprom->id_ethaddr[0], idprom->id_ethaddr[1],
idprom->id_ethaddr[2], idprom->id_ethaddr[3],
idprom->id_ethaddr[4], idprom->id_ethaddr[5]);
diff -urNX diff_excludes linux/arch/sparc/kernel/setup.c linux-local/arch/sparc/kernel/setup.c
--- linux/arch/sparc/kernel/setup.c Tue Oct 27 02:23:04 1998
+++ linux-local/arch/sparc/kernel/setup.c Mon Oct 26 16:54:41 1998
@@ -327,39 +327,39 @@
sparc_cpu_model=ap1000;
strcpy(&cputypval, "ap+");
#endif
- printk("ARCH: ");
+ prom_printf("ARCH: ");
packed = 0;
switch(sparc_cpu_model) {
case sun4:
- printk("SUN4\n");
+ prom_printf("SUN4\n");
packed = 0;
break;
case sun4c:
- printk("SUN4C\n");
+ prom_printf("SUN4C\n");
packed = 0;
break;
case sun4m:
- printk("SUN4M\n");
+ prom_printf("SUN4M\n");
packed = 1;
break;
case sun4d:
- printk("SUN4D\n");
+ prom_printf("SUN4D\n");
packed = 1;
break;
case sun4e:
- printk("SUN4E\n");
+ prom_printf("SUN4E\n");
packed = 0;
break;
case sun4u:
- printk("SUN4U\n");
+ prom_printf("SUN4U\n");
break;
case ap1000:
register_console(&prom_console);
- printk("AP1000\n");
+ prom_printf("AP1000\n");
packed = 1;
break;
default:
- printk("UNKNOWN!\n");
+ prom_printf("UNKNOWN!\n");
break;
};
diff -urNX diff_excludes linux/arch/sparc/kernel/sun4d_smp.c linux-local/arch/sparc/kernel/sun4d_smp.c
--- linux/arch/sparc/kernel/sun4d_smp.c Tue Oct 27 02:23:09 1998
+++ linux-local/arch/sparc/kernel/sun4d_smp.c Tue Oct 27 04:05:28 1998
@@ -166,11 +166,7 @@
int cpucount = 0;
int i = 0;
- printk("Entering SMP Mode...\n");
-
- smp_penguin_ctable.which_io = 0;
- smp_penguin_ctable.phys_addr = (unsigned int) srmmu_ctx_table_phys;
- smp_penguin_ctable.reg_size = 0;
+ prom_printf("Entering SMP Mode...\n");
for (i = 0; i < NR_CPUS; i++)
cpu_offset[i] = (char *)&cpu_data[i] - (char *)&cpu_data;
@@ -216,11 +212,20 @@
p->processor = i;
current_set[i] = p;
-
+
for (no = 0; no < linux_num_cpus; no++)
if (linux_cpus[no].mid == i)
break;
-
+
+ /*
+ * Initialize the contexts table
+ * Since the call to prom_startcpu() trashes the structure,
+ * we need to re-initialize it for each cpu
+ */
+ smp_penguin_ctable.which_io = 0;
+ smp_penguin_ctable.phys_addr = (unsigned int) srmmu_ctx_table_phys;
+ smp_penguin_ctable.reg_size = 0;
+
/* whirrr, whirrr, whirrrrrrrrr... */
SMP_PRINTK(("Starting CPU %d at %p task %d node %08x\n", i, entry, cpucount, linux_cpus[no].prom_node));
local_flush_cache_all();
@@ -230,10 +235,10 @@
SMP_PRINTK(("prom_startcpu returned :)\n"));
/* wheee... it's going... */
- for(timeout = 0; timeout < 5000000; timeout++) {
+ for(timeout = 0; timeout < 10000; timeout++) {
if(cpu_callin_map[i])
break;
- udelay(100);
+ udelay(200);
}
if(cpu_callin_map[i]) {
@@ -242,7 +247,7 @@
__cpu_logical_map[cpucount] = i;
} else {
cpucount--;
- printk("Processor %d is stuck.\n", i);
+ prom_printf("Processor %d is stuck.\n", i);
}
}
if(!(cpu_callin_map[i])) {
@@ -252,7 +257,7 @@
}
local_flush_cache_all();
if(cpucount == 0) {
- printk("Error: only one Processor found.\n");
+ prom_printf("Error: only one Processor found.\n");
cpu_present_map = (1 << hard_smp4d_processor_id());
} else {
unsigned long bogosum = 0;
@@ -264,10 +269,10 @@
}
}
SMP_PRINTK(("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n", cpucount + 1, (bogosum + 2500)/500000, ((bogosum + 2500)/5000)%100));
- printk("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n",
- cpucount + 1,
- (bogosum + 2500)/500000,
- ((bogosum + 2500)/5000)%100);
+ prom_printf("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n",
+ cpucount + 1,
+ (bogosum + 2500)/500000,
+ ((bogosum + 2500)/5000)%100);
smp_activated = 1;
smp_num_cpus = cpucount + 1;
}
diff -urNX diff_excludes linux/arch/sparc/kernel/sun4m_smp.c linux-local/arch/sparc/kernel/sun4m_smp.c
--- linux/arch/sparc/kernel/sun4m_smp.c Tue Oct 27 02:23:10 1998
+++ linux-local/arch/sparc/kernel/sun4m_smp.c Tue Oct 27 00:06:00 1998
@@ -135,17 +135,14 @@
extern unsigned long trapbase_cpu2[];
extern unsigned long trapbase_cpu3[];
+
__initfunc(void smp4m_boot_cpus(void))
{
int cpucount = 0;
int i = 0;
int first, prev;
- printk("Entering SMP Mode...\n");
-
- smp_penguin_ctable.which_io = 0;
- smp_penguin_ctable.phys_addr = (unsigned int) srmmu_ctx_table_phys;
- smp_penguin_ctable.reg_size = 0;
+ prom_printf("Entering SMP Mode...\n");
for (i = 0; i < NR_CPUS; i++)
cpu_offset[i] = (char *)&cpu_data[i] - (char *)&cpu_data;
@@ -189,18 +186,28 @@
/* See trampoline.S for details... */
entry += ((i-1) * 3);
+ /*
+ * Initialize the contexts table
+ * Since the call to prom_startcpu() trashes the structure,
+ * we need to re-initialize it for each cpu
+ */
+ smp_penguin_ctable.which_io = 0;
+ smp_penguin_ctable.phys_addr = (unsigned int) srmmu_ctx_table_phys;
+ smp_penguin_ctable.reg_size = 0;
+
/* whirrr, whirrr, whirrrrrrrrr... */
- printk("Starting CPU %d at %p\n", i, entry);
+ prom_printf("Starting CPU %d at %p\n", i, entry);
mid_xlate[i] = (linux_cpus[i].mid & ~8);
local_flush_cache_all();
prom_startcpu(linux_cpus[i].prom_node,
&smp_penguin_ctable, 0, (char *)entry);
/* wheee... it's going... */
- for(timeout = 0; timeout < 5000000; timeout++) {
+ prom_printf("Waiting for CPU #%d to come online...\n", i);
+ for(timeout = 0; timeout < 10000; timeout++) {
if(cpu_callin_map[i])
break;
- udelay(100);
+ udelay(200);
}
if(cpu_callin_map[i]) {
/* Another "Red Snapper". */
@@ -208,7 +215,7 @@
__cpu_logical_map[i] = i;
} else {
cpucount--;
- printk("Processor %d is stuck.\n", i);
+ prom_printf("Processor %d is stuck.\n", i);
}
}
if(!(cpu_callin_map[i])) {
@@ -218,7 +225,7 @@
}
local_flush_cache_all();
if(cpucount == 0) {
- printk("Error: only one Processor found.\n");
+ prom_printf("Error: only one Processor found.\n");
cpu_present_map = (1 << smp_processor_id());
} else {
unsigned long bogosum = 0;
@@ -226,7 +233,7 @@
if(cpu_present_map & (1 << i))
bogosum += cpu_data[i].udelay_val;
}
- printk("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n",
+ prom_printf("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n",
cpucount + 1,
(bogosum + 2500)/500000,
((bogosum + 2500)/5000)%100);
diff -urNX diff_excludes linux/arch/sparc/mm/fault.c linux-local/arch/sparc/mm/fault.c
--- linux/arch/sparc/mm/fault.c Tue Oct 27 02:23:42 1998
+++ linux-local/arch/sparc/mm/fault.c Mon Oct 26 20:49:09 1998
@@ -140,7 +140,7 @@
{
if((unsigned long) address < PAGE_SIZE) {
printk(KERN_ALERT "Unable to handle kernel NULL "
- "pointer dereference");
+ "pointer dereference\n");
} else {
printk(KERN_ALERT "Unable to handle kernel paging request "
"at virtual address %08lx\n", address);
diff -urNX diff_excludes linux/arch/sparc/prom/init.c linux-local/arch/sparc/prom/init.c
--- linux/arch/sparc/prom/init.c Tue Oct 27 02:24:00 1998
+++ linux-local/arch/sparc/prom/init.c Mon Oct 26 18:03:58 1998
@@ -94,8 +94,8 @@
#ifndef CONFIG_SUN4
/* SUN4 prints this in sun4_prom_init */
- printk("PROMLIB: Sun Boot Prom Version %d Revision %d\n",
- romvec->pv_romvers, prom_rev);
+ prom_printf("PROMLIB: Sun Boot Prom Version %d Revision %d\n",
+ romvec->pv_romvers, prom_rev);
#endif
/* Initialization successful. */
diff -urNX diff_excludes linux/arch/sparc/prom/printf.c linux-local/arch/sparc/prom/printf.c
--- linux/arch/sparc/prom/printf.c Tue Oct 27 02:24:02 1998
+++ linux-local/arch/sparc/prom/printf.c Tue Oct 27 03:51:53 1998
@@ -17,7 +17,7 @@
static char ppbuf[1024];
void
-prom_printf(char *fmt, ...)
+real_prom_printf(char *fmt, ...)
{
va_list args;
char ch, *bptr;
diff -urNX diff_excludes linux/include/asm-sparc/oplib.h linux-local/include/asm-sparc/oplib.h
--- linux/include/asm-sparc/oplib.h Tue Oct 27 02:42:38 1998
+++ linux-local/include/asm-sparc/oplib.h Mon Oct 26 17:37:31 1998
@@ -153,7 +153,12 @@
extern void prom_putchar(char character);
/* Prom's internal printf routine, don't use in kernel/boot code. */
-void prom_printf(char *fmt, ...);
+#define prom_printf(fmt, args...) \
+do { \
+ real_prom_printf(fmt, ##args); \
+ printk(fmt, ##args); \
+} while (0)
+void real_prom_printf(char *fmt, ...);
/* Query for input device type */
-
To unsubscribe from this list: send the line "unsubscribe sparclinux" in
the body of the message to majordomo@vger.rutgers.edu