- int i;
- int cur_cpu = 0;
-
- smp_num_cpus = prom_setup_smp();
- printk("Detected %d available CPUs \n", smp_num_cpus);
-
- init_new_context(current, &init_mm);
- current->processor = 0;
- cpu_data[0].udelay_val = loops_per_jiffy;
- cpu_data[0].asid_cache = ASID_FIRST_VERSION;
- CPUMASK_CLRALL(cpu_online_map);
- CPUMASK_SETB(cpu_online_map, 0);
- atomic_set(&cpus_booted, 1); /* Master CPU is already booted... */
- init_idle();
-
- __cpu_number_map[0] = 0;
- __cpu_logical_map[0] = 0;
-
- /*
- * This loop attempts to compensate for "holes" in the CPU
- * numbering. It's overkill, but general.
- */
- for (i = 1; i < smp_num_cpus; ) {
- struct task_struct *p;
- struct pt_regs regs;
- int retval;
- printk("Starting CPU %d... \n", i);
-
- /* Spawn a new process normally. Grab a pointer to
- its task struct so we can mess with it */
- do_fork(CLONE_VM|CLONE_PID, 0, ®s, 0);
-
- p = init_task.prev_task;
- if (!p)
- panic("failed fork for CPU %d", i);
-
- /* This is current for the second processor */
- p->processor = i;
- p->cpus_runnable = 1 << i; /* we schedule the first task manually */
- p->thread.reg31 = (unsigned long) start_secondary;
-
- del_from_runqueue(p);
- unhash_process(p);
- init_tasks[i] = p;
-
- __flush_cache_all();
-
- do {
- /* Iterate until we find a CPU that comes up */
- cur_cpu++;
- retval = prom_boot_secondary(cur_cpu,
- (unsigned long)p + KERNEL_STACK_SIZE - 32,
- (unsigned long)p);
-
- } while (!retval && (cur_cpu < NR_CPUS));
- if (retval) {
- __cpu_number_map[cur_cpu] = i;
- __cpu_logical_map[i] = cur_cpu;
- i++;
- } else {
- panic("CPU discovery disaster");
- }
- }
-
- /* Local semaphore to both the CPUs */
-
- *(volatile uint32_t *)(0xbb000a68) = 0x80000000;
- while (*(volatile uint32_t *)(0xbb000a68) != 0x00000000);
-
- smp_threads_ready = 1;
+ /*
+ * Generate an INTMSG so that it can be sent over to the
+ * destination CPU. The INTMSG will put the STATUS bits
+ * based on the action desired. An alternative strategy
+ * is to write to the Interrupt Set register, read the
+ * Interrupt Status register and clear the Interrupt
+ * Clear register. The latter is preffered.
+ */
+ switch (action) {
+ case SMP_RESCHEDULE_YOURSELF:
+ if (cpu == 1)
+ OCD_WRITE(RM9000x2_OCD_INTP1SET3, 4);
+ else
+ OCD_WRITE(RM9000x2_OCD_INTP0SET3, 4);
+ break;
+
+ case SMP_CALL_FUNCTION:
+ if (cpu == 1)
+ OCD_WRITE(RM9000x2_OCD_INTP1SET3, 2);
+ else
+ OCD_WRITE(RM9000x2_OCD_INTP0SET3, 2);
+ break;
+ }