From: William Lee Irwin III <wli@holomorphy.com>
To: sparclinux@vger.kernel.org
Subject: Re: SMP support in 2.6.x kernel for sparc32
Date: Wed, 28 Jul 2004 22:06:03 +0000 [thread overview]
Message-ID: <20040728220603.GZ2334@holomorphy.com> (raw)
In-Reply-To: <001301c474db$af707860$3c01a8c0@cascade>
On Wed, Jul 28, 2004 at 09:47:14PM +0200, Tom Weustink wrote:
> I got this e-mail address from people in #gentoo-sparc over at freenode.net.
> My SparcStation 10 dual CPU machine is having problems running a kernel
> higher then vesion 2.4.23.
> The higher versions don't load, or lock up the machine after a while without
> a log the check on why.
> So, I would like to try out the 2.6.x versions but gentoo has no stable
> support for SMP sparc32.
> I was told I should talk to you since you have some patches (unstable I was
> told) that might do the trick in getting 2.6.x on SMP sparc32 machines.
> Is it possible you can give me your patches to me to try them out?
> Hope to hear back from you.
> With kind regards,
> freshy98
Odd that 2.4.x worked. Anyway, the patch I was sent, against an
uncertain kernel version sometime around 2.6.4, is as follows.
This appears to need debugging.
I expect that this patch will not qualify as stable, esp. given that
there's a follow-on patch that is designed to debug various lockups
said to occur with it.
-- wli
At some point in the past, Keith M Wesolowski wrote:
> Next, the smp32 patch. Applied to ~2.6.4 or so. Needs work. This is
> the actual working version to use. The next one I'll send is a
> debugging one with weird stuff for supersparc-ii only in it, trying to
> debug xcalls and lockups.
=== arch/sparc/kernel/entry.S 1.22 vs edited ==--- 1.22/arch/sparc/kernel/entry.S Sun Mar 21 22:02:59 2004
+++ edited/arch/sparc/kernel/entry.S Sun Mar 21 22:04:27 2004
@@ -350,7 +350,7 @@
* for cross calls. That has a separate entry point below.
*/
maybe_smp4m_msg:
- GET_PROCESSOR_MID(o3)
+ GET_PROCESSOR4M_ID(o3)
set sun4m_interrupts, %l5
ld [%l5], %o5
sethi %hi(0x60000000), %o4
@@ -359,6 +359,7 @@
andcc %o1, %o4, %g0
be,a smp4m_ticker
cmp %l7, 14
+#if 0 /* NO */
sethi %hi(0x40000000), %o2
add %o5, %o3, %o5
andcc %o1, %o2, %g0
@@ -383,6 +384,7 @@
2:
call smp_stop_cpu_irq
nop
+#endif
RESTORE_ALL
.align 4
@@ -390,7 +392,7 @@
linux_trap_ipi15_sun4m:
SAVE_ALL
sethi %hi(0x80000000), %o2
- GET_PROCESSOR_MID(o0)
+ GET_PROCESSOR4M_ID(o0)
set sun4m_interrupts, %l5
ld [%l5], %o5
sll %o0, 12, %o0
=== arch/sparc/kernel/init_task.c 1.9 vs edited ==--- 1.9/arch/sparc/kernel/init_task.c Tue Oct 7 19:53:41 2003
+++ edited/arch/sparc/kernel/init_task.c Sun Mar 21 22:04:28 2004
@@ -21,5 +21,7 @@
* If this is not aligned on a 8k boundry, then you should change code
* in etrap.S which assumes it.
*/
-__asm__(".section \".text\",#alloc\n");
-union thread_union init_thread_union = { INIT_THREAD_INFO(init_task) };
+union thread_union init_thread_union
+ __attribute__((section (".text")))
+ __attribute__((aligned (THREAD_SIZE)))
+ = { INIT_THREAD_INFO(init_task) };
=== arch/sparc/kernel/irq.c 1.28 vs edited ==--- 1.28/arch/sparc/kernel/irq.c Sun Feb 22 14:34:53 2004
+++ edited/arch/sparc/kernel/irq.c Sun Mar 21 22:04:28 2004
@@ -188,7 +188,7 @@
for (j = 0; j < NR_CPUS; j++) {
if (cpu_online(j))
seq_printf(p, "%10u ",
- kstat_cpu(cpu_logical_map(j)).irqs[i]);
+ kstat_cpu(j).irqs[i]);
}
#endif
seq_printf(p, " %c %s",
@@ -289,7 +289,7 @@
void synchronize_irq(unsigned int irq)
{
printk("synchronize_irq says: implement me!\n");
- BUG();
+// BUG();
}
#endif /* SMP */
=== arch/sparc/kernel/setup.c 1.27 vs edited ==--- 1.27/arch/sparc/kernel/setup.c Sun Mar 14 16:45:25 2004
+++ edited/arch/sparc/kernel/setup.c Sun Mar 21 22:04:28 2004
@@ -265,6 +265,8 @@
*cmdline_p = prom_getbootargs();
strcpy(saved_command_line, *cmdline_p);
+ prom_printf("command line copied\n");
+
/* Set sparc_cpu_model */
sparc_cpu_model = sun_unknown;
if(!strcmp(&cputypval,"sun4 ")) { sparc_cpu_model=sun4; }
@@ -306,6 +308,8 @@
break;
};
+ prom_printf("arch printed (%d)\n", sparc_cpu_model);
+
#ifdef CONFIG_DUMMY_CONSOLE
conswitchp = &dummy_con;
#elif defined(CONFIG_PROM_CONSOLE)
@@ -313,11 +317,16 @@
#endif
boot_flags_init(*cmdline_p);
+ prom_printf("boot flags init\n");
+
idprom_init();
+ prom_printf("idprom done\n");
if (ARCH_SUN4C_SUN4)
sun4c_probe_vac();
load_mmu();
+ prom_printf("load mmu done\n");
(void) prom_probe_memory();
+ prom_printf("memory probe done\n");
phys_base = 0xffffffffUL;
highest_paddr = 0UL;
@@ -332,6 +341,8 @@
highest_paddr = top;
}
+ prom_printf("highest_paddr set\n");
+
if (!root_flags)
root_mountflags &= ~MS_RDONLY;
ROOT_DEV = old_decode_dev(root_dev);
@@ -343,16 +354,21 @@
prom_setsync(prom_sync_me);
+ prom_printf("sync set\n");
+
if((boot_flags&BOOTME_DEBUG) && (linux_dbvec!=0) &&
((*(short *)linux_dbvec) != -1)) {
printk("Booted under KADB. Syncing trap table.\n");
(*(linux_dbvec->teach_debugger))();
}
+ prom_printf("debug thing done\n");
+
init_mm.context = (unsigned long) NO_CONTEXT;
init_task.thread.kregs = &fake_swapper_regs;
paging_init();
+ prom_printf("paging_init done\n");
}
static int __init set_preferred_console(void)
=== arch/sparc/kernel/smp.c 1.16 vs edited ==--- 1.16/arch/sparc/kernel/smp.c Tue Mar 16 02:14:48 2004
+++ edited/arch/sparc/kernel/smp.c Sun Mar 21 22:04:29 2004
@@ -35,36 +35,19 @@
#include <asm/tlbflush.h>
#include <asm/cpudata.h>
-volatile int smp_processors_ready = 0;
-int smp_num_cpus = 1;
-int smp_threads_ready=0;
-volatile unsigned long cpu_callin_map[NR_CPUS] __initdata = {0,};
unsigned char boot_cpu_id = 0;
unsigned char boot_cpu_id4 = 0; /* boot_cpu_id << 2 */
-int smp_activated = 0;
-volatile int __cpu_number_map[NR_CPUS];
-volatile int __cpu_logical_map[NR_CPUS];
-cycles_t cacheflush_time = 0; /* XXX */
cpumask_t cpu_online_map = CPU_MASK_NONE;
cpumask_t phys_cpu_present_map = CPU_MASK_NONE;
-
-/* The only guaranteed locking primitive available on all Sparc
- * processors is 'ldstub [%reg + immediate], %dest_reg' which atomically
- * places the current byte at the effective address into dest_reg and
- * places 0xff there afterwards. Pretty lame locking primitive
- * compared to the Alpha and the Intel no? Most Sparcs have 'swap'
- * instruction which is much better...
- */
+cpumask_t smp_commenced_mask = CPU_MASK_NONE;
+cpumask_t cpu_callout_map = CPU_MASK_NONE;
/* Used to make bitops atomic */
unsigned char bitops_spinlock = 0;
volatile unsigned long ipi_count;
-volatile int smp_process_available=0;
-volatile int smp_commenced = 0;
-
void __init smp_store_cpu_info(int id)
{
int cpu_node;
@@ -82,6 +65,17 @@
void __init smp_cpus_done(unsigned int max_cpus)
{
+ unsigned long bogosum = 0;
+ int i;
+
+ for (i = 0; i < NR_CPUS; i++) {
+ if (cpu_online(i))
+ bogosum += cpu_data(i).udelay_val;
+ }
+ printk("Total of %ld processors activated "
+ "(%lu.%02lu BogoMIPS).\n",
+ (long) num_online_cpus(), bogosum/(500000/HZ),
+ (bogosum/(5000/HZ))%100);
}
void cpu_panic(void)
@@ -92,17 +86,6 @@
struct linux_prom_registers smp_penguin_ctable __initdata = { 0 };
-void __init smp_boot_cpus(void)
-{
- extern void smp4m_boot_cpus(void);
- extern void smp4d_boot_cpus(void);
-
- if (sparc_cpu_model = sun4m)
- smp4m_boot_cpus();
- else
- smp4d_boot_cpus();
-}
-
void smp_send_reschedule(int cpu)
{
/* See sparc64 */
@@ -237,8 +220,34 @@
return 0;
}
-void __init smp_prepare_cpus(unsigned int maxcpus)
-{
+/* XXX Yet another unimplemented feature in sparc32 */
+cycles_t cacheflush_time;
+unsigned long cache_decay_ticks = 1000; /* XXX Complete and utter bullshit */
+
+void __init smp_prepare_cpus(unsigned int max_cpus)
+{
+ int instance, mid;
+
+ instance = 0;
+ while (!cpu_find_by_instance(instance, NULL, &mid)) {
+ if (mid < max_cpus)
+ cpu_set(mid, phys_cpu_present_map);
+ instance++;
+ }
+
+ if (num_possible_cpus() > max_cpus) {
+ instance = 0;
+ while (!cpu_find_by_instance(instance, NULL, &mid)) {
+ if (mid != boot_cpu_id) {
+ cpu_clear(mid, phys_cpu_present_map);
+ if (num_possible_cpus() <= max_cpus)
+ break;
+ }
+ instance++;
+ }
+ }
+
+ smp_store_cpu_info(boot_cpu_id);
}
void __devinit smp_prepare_boot_cpu(void)
@@ -250,7 +259,16 @@
int __devinit __cpu_up(unsigned int cpu)
{
- panic("smp doesn't work\n");
+ int ret = smp_boot_one_cpu(cpu);
+
+ if (!ret) {
+ cpu_set(cpu, smp_commenced_mask);
+ while (!cpu_isset(cpu, cpu_online_map))
+ mb();
+ if (!cpu_isset(cpu, cpu_online_map)) /* XXX - unreached? */
+ return -ENODEV;
+ }
+ return ret;
}
void smp_bogo(struct seq_file *m)
=== arch/sparc/kernel/sparc_ksyms.c 1.28 vs edited ==--- 1.28/arch/sparc/kernel/sparc_ksyms.c Tue Mar 16 02:14:48 2004
+++ edited/arch/sparc/kernel/sparc_ksyms.c Tue Mar 23 19:34:44 2004
@@ -158,10 +158,6 @@
#ifdef CONFIG_SMP
/* IRQ implementation. */
EXPORT_SYMBOL(synchronize_irq);
-
-/* Misc SMP information */
-EXPORT_SYMBOL(__cpu_number_map);
-EXPORT_SYMBOL(__cpu_logical_map);
#endif
EXPORT_SYMBOL(__udelay);
@@ -183,7 +179,7 @@
#ifndef CONFIG_SMP
EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(___xchg32));
#else
-EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(__smp_processor_id));
+EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(__hard_smp_processor_id));
#endif
EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(enable_irq));
EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(disable_irq));
=== arch/sparc/kernel/sun4d_irq.c 1.19 vs edited ==--- 1.19/arch/sparc/kernel/sun4d_irq.c Sun Mar 14 16:43:39 2004
+++ edited/arch/sparc/kernel/sun4d_irq.c Sun Mar 21 22:04:29 2004
@@ -106,7 +106,7 @@
for (x = 0; x < NR_CPUS; x++) {
if (cpu_online(x))
seq_printf(p, "%10u ",
- kstat_cpu(cpu_logical_map(x)).irqs[i]);
+ kstat_cpu(x).irqs[i]);
}
#endif
seq_printf(p, "%c %s",
@@ -440,15 +440,11 @@
}
#else
struct sbus_bus *sbus;
- int cpuid = cpu_logical_map(1);
-
- if (cpuid = -1)
- cpuid = cpu_logical_map(0);
for_each_sbus(sbus) {
- sbus_tid[sbus->board] = cpuid;
- set_sbi_tid(sbus->devid, cpuid << 3);
+ sbus_tid[sbus->board] = boot_cpu_id;
+ set_sbi_tid(sbus->devid, boot_cpu_id << 3);
}
- printk("All sbus IRQs directed to CPU%d\n", cpuid);
+ printk("All sbus IRQs directed to CPU%d\n", boot_cpu_id);
#endif
}
#endif
=== arch/sparc/kernel/sun4d_smp.c 1.16 vs edited ==--- 1.16/arch/sparc/kernel/sun4d_smp.c Tue Mar 16 02:14:48 2004
+++ edited/arch/sparc/kernel/sun4d_smp.c Sun Mar 21 22:04:30 2004
@@ -38,6 +38,7 @@
#define IRQ_CROSS_CALL 15
+#if 0
extern ctxd_t *srmmu_ctx_table_phys;
extern void calibrate_delay(void);
@@ -100,7 +101,7 @@
* the SMP initialization the master will be just allowed
* to call the scheduler code.
*/
- init_idle();
+ //init_idle();
/* Get our local ticker going. */
smp_setup_percpu_timer();
@@ -509,3 +510,9 @@
ccall_info.processors_out[i] = 1;
}
}
+#else
+void smp4d_cross_call_irq(void) {}
+void smp4d_percpu_timer_interrupt(struct pt_regs *regs) {}
+void sun4d_init_smp(void) {}
+void smp4d_callin(void) {}
+#endif
=== arch/sparc/kernel/sun4m_smp.c 1.14 vs edited ==--- 1.14/arch/sparc/kernel/sun4m_smp.c Tue Mar 16 02:14:48 2004
+++ edited/arch/sparc/kernel/sun4m_smp.c Sun Mar 21 22:04:30 2004
@@ -36,21 +36,17 @@
#define IRQ_CROSS_CALL 15
extern ctxd_t *srmmu_ctx_table_phys;
-
extern void calibrate_delay(void);
-extern volatile int smp_processors_ready;
-extern unsigned long cpu_present_map;
-extern int smp_num_cpus;
-extern int smp_threads_ready;
-extern volatile unsigned long cpu_callin_map[NR_CPUS];
extern unsigned char boot_cpu_id;
-extern int smp_activated;
-extern volatile int __cpu_number_map[NR_CPUS];
-extern volatile int __cpu_logical_map[NR_CPUS];
+
+extern cpumask_t cpu_online_map;
+extern cpumask_t phys_cpu_present_map;
+extern cpumask_t smp_commenced_mask;
+extern cpumask_t cpu_callout_map;
+
extern volatile unsigned long ipi_count;
-extern volatile int smp_process_available;
-extern volatile int smp_commenced;
+
extern int __smp4m_processor_id(void);
/*#define SMP_DEBUG*/
@@ -69,6 +65,8 @@
return val;
}
+static volatile unsigned long callin_flag = 0;
+
static void smp_setup_percpu_timer(void);
extern void cpu_probe(void);
@@ -79,7 +77,7 @@
local_flush_cache_all();
local_flush_tlb_all();
- set_irq_udt(boot_cpu_id);
+ set_irq_udt(boot_cpu_id); /* XXX - really needed? */
/* Get our local ticker going. */
smp_setup_percpu_timer();
@@ -90,22 +88,13 @@
local_flush_cache_all();
local_flush_tlb_all();
- /*
- * Unblock the master CPU _only_ when the scheduler state
- * of all secondary CPUs will be up-to-date, so after
- * the SMP initialization the master will be just allowed
- * to call the scheduler code.
- */
- init_idle();
-
/* Allow master to continue. */
- swap((unsigned long *)&cpu_callin_map[cpuid], 1);
+ swap(&callin_flag, 1);
+ /* XXX - Why so much flushing? Just defensive or are there bugs?? */
local_flush_cache_all();
local_flush_tlb_all();
- cpu_probe();
-
/* Fix idle thread fields. */
__asm__ __volatile__("ld [%0], %%g6\n\t"
: : "r" (¤t_set[cpuid])
@@ -115,8 +104,10 @@
atomic_inc(&init_mm.mm_count);
current->active_mm = &init_mm;
- while(!smp_commenced)
- barrier();
+ while (!cpu_isset(cpuid, smp_commenced_mask))
+ mb();
+
+ cpu_set(cpuid, cpu_online_map);
local_flush_cache_all();
local_flush_tlb_all();
@@ -125,126 +116,74 @@
}
extern int cpu_idle(void *unused);
-extern void init_IRQ(void);
extern void cpu_panic(void);
-extern int start_secondary(void *unused);
-/*
- * Cycle through the processors asking the PROM to start each one.
- */
-
extern struct linux_prom_registers smp_penguin_ctable;
extern unsigned long trapbase_cpu1[];
extern unsigned long trapbase_cpu2[];
extern unsigned long trapbase_cpu3[];
-void __init smp4m_boot_cpus(void)
+static int __devinit smp4m_boot_one_cpu(unsigned int cpu)
{
- int cpucount = 0;
- int i, mid;
+ extern unsigned long sun4m_cpu_startup;
+ unsigned long entry = (unsigned long)(&sun4m_cpu_startup);
- printk("Entering SMP Mode...\n");
+ struct task_struct *p;
+ int timeout, ret;
- local_irq_enable();
- cpu_present_map = 0;
+ /* XXX set_irq_udt(boot_cpu_id); */
+ /* XXX smp_setup_percpu_timer(); */
- for (i = 0; !cpu_find_by_instance(i, NULL, &mid); i++)
- cpu_present_map |= (1<<mid);
+ /* Let's be sure we're not going to jump off into space. */
+ if (cpu > 3)
+ panic("sun4m only takes 4 penguins, so who's this #%d?", cpu);
+ /* See trampoline.S for details... */
+ entry += (cpu - 1) * 3 * 4;
- for(i=0; i < NR_CPUS; i++) {
- __cpu_number_map[i] = -1;
- __cpu_logical_map[i] = -1;
- }
+ kernel_thread(NULL, NULL, CLONE_IDLETASK);
- __cpu_number_map[boot_cpu_id] = 0;
- __cpu_logical_map[0] = boot_cpu_id;
- current_thread_info()->cpu = boot_cpu_id;
+ p = prev_task(&init_task);
- smp_store_cpu_info(boot_cpu_id);
- set_irq_udt(boot_cpu_id);
- smp_setup_percpu_timer();
+ init_idle(p, cpu);
+
+ current_set[cpu] = p->thread_info; /* XXX - per_cpu? nasty asm */
+
+ unhash_process(p);
+
+ /*
+ * 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 0x%08lx\n", cpu, entry);
local_flush_cache_all();
- if(cpu_find_by_instance(1, NULL, NULL))
- return; /* Not an MP box. */
- for(i = 0; i < NR_CPUS; i++) {
- if(i = boot_cpu_id)
- continue;
+ prom_startcpu(cpu_data(cpu).prom_node, &smp_penguin_ctable,
+ 0, (char *)entry);
- if(cpu_present_map & (1 << i)) {
- extern unsigned long sun4m_cpu_startup;
- unsigned long *entry = &sun4m_cpu_startup;
- struct task_struct *p;
- int timeout;
-
- /* Cook up an idler for this guy. */
- kernel_thread(start_secondary, NULL, CLONE_IDLETASK);
-
- cpucount++;
-
- p = prev_task(&init_task);
-
- init_idle(p, i);
-
- current_set[i] = p->thread_info;
-
- unhash_process(p);
-
- /* 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);
- local_flush_cache_all();
- prom_startcpu(cpu_data(i).prom_node,
- &smp_penguin_ctable, 0, (char *)entry);
-
- /* wheee... it's going... */
- for(timeout = 0; timeout < 10000; timeout++) {
- if(cpu_callin_map[i])
- break;
- udelay(200);
- }
- if(cpu_callin_map[i]) {
- /* Another "Red Snapper". */
- __cpu_number_map[i] = i;
- __cpu_logical_map[i] = i;
- } else {
- cpucount--;
- printk("Processor %d is stuck.\n", i);
- }
- }
- if(!(cpu_callin_map[i])) {
- cpu_present_map &= ~(1 << i);
- __cpu_number_map[i] = -1;
- }
+ /* wheee... it's going... */
+ for (timeout = 0; timeout < 20000; timeout++) {
+ if(callin_flag)
+ break;
+ udelay(100);
}
- local_flush_cache_all();
- if(cpucount = 0) {
- printk("Error: only one Processor found.\n");
- cpu_present_map = (1 << smp_processor_id());
+ if (callin_flag) {
+ ret = 0;
} else {
- unsigned long bogosum = 0;
- for(i = 0; i < NR_CPUS; i++) {
- if(cpu_present_map & (1 << i))
- bogosum += cpu_data(i).udelay_val;
- }
- printk("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n",
- cpucount + 1,
- bogosum/(500000/HZ),
- (bogosum/(5000/HZ))%100);
- smp_activated = 1;
- smp_num_cpus = cpucount + 1;
+ printk("Processor %d is stuck.\n", cpu);
+ cpu_clear(cpu, cpu_callout_map);
+ ret = -ENODEV;
}
+ local_flush_cache_all();
+
+ return ret;
+}
+#if 0
/* Free unneeded trap tables */
if (!(cpu_present_map & (1 << 1))) {
ClearPageReserved(virt_to_page(trapbase_cpu1));
@@ -267,10 +206,7 @@
totalram_pages++;
num_physpages++;
}
-
- /* Ok, they are spinning and ready to go. */
- smp_processors_ready = 1;
-}
+#endif
/* At each hardware IRQ, we get this called to forward IRQ reception
* to the next processor. The caller must disable the IRQ level being
@@ -282,6 +218,7 @@
{
}
+#if 0
/* Cross calls, in order to work efficiently and atomically do all
* the message passing work themselves, only stopcpu and reschedule
* messages come through here.
@@ -323,7 +260,7 @@
printk("Yeeee, trying to send SMP msg(%d) on cpu %d\n", msg, me);
panic("Bogon SMP message pass.");
}
-
+#endif
static struct smp_funcall {
smpfunc_t func;
unsigned long arg1;
@@ -331,77 +268,63 @@
unsigned long arg3;
unsigned long arg4;
unsigned long arg5;
- unsigned long processors_in[NR_CPUS]; /* Set when ipi entered. */
- unsigned long processors_out[NR_CPUS]; /* Set when ipi exited. */
+ cpumask_t processors_in; /* Set when ipi entered. */
+ cpumask_t processors_out; /* Set when ipi exited. */
} ccall_info;
static spinlock_t cross_call_lock = SPIN_LOCK_UNLOCKED;
/* Cross calls must be serialized, at least currently. */
+/* XXX We completely disregard wait, see sparc64 and asm/smp.h. FIXME */
void smp4m_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2,
unsigned long arg3, unsigned long arg4, unsigned long arg5)
{
- if(smp_processors_ready) {
- register int ncpus = smp_num_cpus;
- unsigned long flags;
-
- spin_lock_irqsave(&cross_call_lock, flags);
-
- /* Init function glue. */
- ccall_info.func = func;
- ccall_info.arg1 = arg1;
- ccall_info.arg2 = arg2;
- ccall_info.arg3 = arg3;
- ccall_info.arg4 = arg4;
- ccall_info.arg5 = arg5;
-
- /* Init receive/complete mapping, plus fire the IPI's off. */
- {
- register unsigned long mask;
- register int i;
-
- mask = (cpu_present_map & ~(1 << smp_processor_id()));
- for(i = 0; i < ncpus; i++) {
- if(mask & (1 << i)) {
- ccall_info.processors_in[i] = 0;
- ccall_info.processors_out[i] = 0;
- set_cpu_int(i, IRQ_CROSS_CALL);
- } else {
- ccall_info.processors_in[i] = 1;
- ccall_info.processors_out[i] = 1;
- }
- }
+ int i;
+ unsigned long flags;
+ cpumask_t mask = cpu_online_map;
+
+ cpu_clear(smp_processor_id(), mask);
+
+ spin_lock_irqsave(&cross_call_lock, flags);
+
+ /* Init function glue. */
+ ccall_info.func = func;
+ ccall_info.arg1 = arg1;
+ ccall_info.arg2 = arg2;
+ ccall_info.arg3 = arg3;
+ ccall_info.arg4 = arg4;
+ ccall_info.arg5 = arg5;
+
+ /* Init receive/complete mapping, plus fire the IPI's off. */
+ for(i = 0; i < NR_CPUS; i++) {
+ if(cpu_isset(i, mask)) {
+ cpu_set(i, ccall_info.processors_in);
+ cpu_set(i, ccall_info.processors_out);
+ set_cpu_int(i, IRQ_CROSS_CALL);
+ } else {
+ cpu_clear(i, ccall_info.processors_in);
+ cpu_clear(i, ccall_info.processors_out);
}
+ }
- {
- register int i;
+ while(!cpus_empty(ccall_info.processors_in))
+ barrier();
- i = 0;
- do {
- while(!ccall_info.processors_in[i])
- barrier();
- } while(++i < ncpus);
-
- i = 0;
- do {
- while(!ccall_info.processors_out[i])
- barrier();
- } while(++i < ncpus);
- }
+ while(!cpus_empty(ccall_info.processors_out))
+ barrier();
- spin_unlock_irqrestore(&cross_call_lock, flags);
- }
+ spin_unlock_irqrestore(&cross_call_lock, flags);
}
/* Running cross calls. */
void smp4m_cross_call_irq(void)
{
- int i = smp_processor_id();
+ int cpuid = smp_processor_id();
- ccall_info.processors_in[i] = 1;
+ cpu_clear(cpuid, ccall_info.processors_in);
ccall_info.func(ccall_info.arg1, ccall_info.arg2, ccall_info.arg3,
ccall_info.arg4, ccall_info.arg5);
- ccall_info.processors_out[i] = 1;
+ cpu_clear(cpuid, ccall_info.processors_out);
}
extern void sparc_do_profile(unsigned long pc, unsigned long o7);
@@ -461,9 +384,10 @@
void __init sun4m_init_smp(void)
{
- BTFIXUPSET_BLACKBOX(smp_processor_id, smp4m_blackbox_id);
+ BTFIXUPSET_BLACKBOX(hard_smp_processor_id, smp4m_blackbox_id);
BTFIXUPSET_BLACKBOX(load_current, smp4m_blackbox_current);
BTFIXUPSET_CALL(smp_cross_call, smp4m_cross_call, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(smp_message_pass, smp4m_message_pass, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(__smp_processor_id, __smp4m_processor_id, BTFIXUPCALL_NORM);
+// BTFIXUPSET_CALL(smp_message_pass, smp4m_message_pass, BTFIXUPCALL_NORM);
+ BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4m_processor_id, BTFIXUPCALL_NORM);
+ BTFIXUPSET_CALL(smp_boot_one_cpu, smp4m_boot_one_cpu, BTFIXUPCALL_NORM);
}
=== arch/sparc/prom/printf.c 1.3 vs edited ==--- 1.3/arch/sparc/prom/printf.c Wed Feb 18 19:42:41 2004
+++ edited/arch/sparc/prom/printf.c Tue Mar 23 19:33:34 2004
@@ -32,8 +32,12 @@
}
}
+#if 0
void
-prom_printf(char *fmt, ...)
+#else
+int
+#endif
+prom_printf(const char *fmt, ...)
{
va_list args;
int i;
@@ -43,4 +47,7 @@
va_end(args);
prom_write(ppbuf, i);
+#if 1
+ return i;
+#endif
}
=== include/asm-sparc/asmmacro.h 1.4 vs edited ==--- 1.4/include/asm-sparc/asmmacro.h Tue Mar 16 02:14:48 2004
+++ edited/include/asm-sparc/asmmacro.h Sun Mar 21 22:04:30 2004
@@ -20,14 +20,9 @@
/* Blackbox */
#define GET_PROCESSOR_ID(reg) \
- sethi %hi(___b_smp_processor_id), %reg; \
+ sethi %hi(___b_hard_smp_processor_id), %reg; \
sethi %hi(boot_cpu_id), %reg; \
ldub [%reg + %lo(boot_cpu_id)], %reg;
-
-#define GET_PROCESSOR_MID(reg) \
- rd %tbr, %reg; \
- srl %reg, 12, %reg; \
- and %reg, 3, %reg;
/* All trap entry points _must_ begin with this macro or else you
* lose. It makes sure the kernel has a proper window so that
=== include/asm-sparc/oplib.h 1.4 vs edited ==--- 1.4/include/asm-sparc/oplib.h Sun Mar 14 16:43:40 2004
+++ edited/include/asm-sparc/oplib.h Tue Mar 23 19:33:21 2004
@@ -154,7 +154,12 @@
extern void prom_putchar(char character);
/* Prom's internal routines, don't use in kernel/boot code. */
+#if 0
extern void prom_printf(char *fmt, ...);
+#else
+extern int prom_printf(const char *fmt, ...);
+#endif
+
extern void prom_write(const char *buf, unsigned int len);
/* Query for input device type */
=== include/asm-sparc/smp.h 1.11 vs edited ==--- 1.11/include/asm-sparc/smp.h Tue Mar 16 02:14:49 2004
+++ edited/include/asm-sparc/smp.h Sun Mar 21 22:04:30 2004
@@ -51,12 +51,14 @@
void smp_bogo(struct seq_file *);
void smp_info(struct seq_file *);
+BTFIXUPDEF_CALL(int, smp_boot_one_cpu, unsigned int)
BTFIXUPDEF_CALL(void, smp_cross_call, smpfunc_t, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long)
BTFIXUPDEF_CALL(void, smp_message_pass, int, int, unsigned long, int)
-BTFIXUPDEF_CALL(int, __smp_processor_id, void)
-BTFIXUPDEF_BLACKBOX(smp_processor_id)
+BTFIXUPDEF_CALL(int, __hard_smp_processor_id, void)
+BTFIXUPDEF_BLACKBOX(hard_smp_processor_id)
BTFIXUPDEF_BLACKBOX(load_current)
+#define smp_boot_one_cpu(__cpu) BTFIXUP_CALL(smp_boot_one_cpu)(__cpu)
#define smp_cross_call(func,arg1,arg2,arg3,arg4,arg5) BTFIXUP_CALL(smp_cross_call)(func,arg1,arg2,arg3,arg4,arg5)
#define smp_message_pass(target,msg,data,wait) BTFIXUP_CALL(smp_message_pass)(target,msg,data,wait)
@@ -129,7 +131,7 @@
"=&r" (cpuid));
See btfixup.h and btfixupprep.c to understand how a blackbox works.
*/
- __asm__ __volatile__("sethi %%hi(___b_smp_processor_id), %0\n\t"
+ __asm__ __volatile__("sethi %%hi(___b_hard_smp_processor_id), %0\n\t"
"sethi %%hi(boot_cpu_id), %0\n\t"
"ldub [%0 + %%lo(boot_cpu_id)], %0\n\t" :
"=&r" (cpuid));
@@ -141,7 +143,7 @@
int cpuid;
__asm__ __volatile__("mov %%o7, %%g1\n\t"
- "call ___f___smp_processor_id\n\t"
+ "call ___f___hard_smp_processor_id\n\t"
" nop\n\t"
"mov %%g2, %0\n\t" : "=r"(cpuid) : : "g1", "g2");
return cpuid;
=== include/linux/kernel.h 1.47 vs edited ==--- 1.47/include/linux/kernel.h Wed Mar 10 08:45:49 2004
+++ edited/include/linux/kernel.h Tue Mar 23 19:33:06 2004
@@ -87,8 +87,13 @@
extern int kernel_text_address(unsigned long addr);
extern int session_of_pgrp(int pgrp);
+#if 0
asmlinkage int printk(const char * fmt, ...)
__attribute__ ((format (printf, 1, 2)));
+#else
+extern int prom_printf(const char *fmt, ...);
+#define printk prom_printf
+#endif
unsigned long int_sqrt(unsigned long);
=== init/main.c 1.127 vs edited ==--- 1.127/init/main.c Tue Mar 16 02:10:35 2004
+++ edited/init/main.c Tue Mar 23 19:48:24 2004
@@ -408,10 +408,15 @@
* Interrupts are still disabled. Do necessary setups, then
* enable them
*/
+ prom_printf("start_kernel\n");
lock_kernel();
+ prom_printf("kernel locked\n");
printk(linux_banner);
+ prom_printf("banner printed\n");
setup_arch(&command_line);
+ prom_printf("setup_arch done\n");
setup_per_cpu_areas();
+ prom_printf("percpu areas setup\n");
/*
* Mark the boot cpu "online" so that it can call console drivers in
@@ -419,20 +424,34 @@
*/
smp_prepare_boot_cpu();
+ prom_printf("boot cpu set up\n");
+
build_all_zonelists();
+
+ prom_printf("zonelists built\n");
page_alloc_init();
+ prom_printf("page_alloc init done\n");
printk("Kernel command line: %s\n", saved_command_line);
parse_args("Booting kernel", command_line, __start___param,
__stop___param - __start___param,
&unknown_bootoption);
+ prom_printf("sorting extable...\n");
sort_main_extable();
+ prom_printf("going to do trap_init\n");
trap_init();
+ prom_printf("trap_init done\n");
rcu_init();
+ prom_printf("rcu_init done\n");
init_IRQ();
+ prom_printf("init_IRQ done\n");
pidhash_init();
+ prom_printf("pidhash init complete\n");
sched_init();
+ prom_printf("sched_init done\n");
softirq_init();
+ prom_printf("softirq init done\n");
time_init();
+ prom_printf("time init done\n");
/*
* HACK ALERT! This is early. We're enabling the console before
@@ -440,6 +459,7 @@
* this. But we do want output early, in case something goes wrong.
*/
console_init();
+ prom_printf("console init done\n");
if (panic_later)
panic(panic_later, panic_param);
profile_init();
=== kernel/printk.c 1.35 vs edited ==--- 1.35/kernel/printk.c Mon Mar 8 16:57:46 2004
+++ edited/kernel/printk.c Tue Mar 23 19:28:52 2004
@@ -467,6 +467,7 @@
logged_chars++;
}
+#if 0
/*
* This is printk. It can be called from any context. We want it to work.
*
@@ -553,6 +554,7 @@
return printed_len;
}
EXPORT_SYMBOL(printk);
+#endif
/**
* acquire_console_sem - lock the console system for exclusive use.
--
Keith M Wesolowski
next prev parent reply other threads:[~2004-07-28 22:06 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-07-28 19:47 SMP support in 2.6.x kernel for sparc32 Tom Weustink
2004-07-28 22:06 ` William Lee Irwin III [this message]
2004-07-28 22:35 ` Keith M Wesolowski
2004-07-28 22:42 ` William Lee Irwin III
2004-07-28 23:53 ` William Lee Irwin III
2004-07-29 0:05 ` Ciaran McCreesh
2004-07-29 0:11 ` William Lee Irwin III
2004-07-29 4:42 ` Tom Weustink
2004-07-29 5:48 ` William Lee Irwin III
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20040728220603.GZ2334@holomorphy.com \
--to=wli@holomorphy.com \
--cc=sparclinux@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.