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