0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <asm/head.h>
0010
0011 #include <linux/kernel.h>
0012 #include <linux/sched.h>
0013 #include <linux/threads.h>
0014 #include <linux/smp.h>
0015 #include <linux/interrupt.h>
0016 #include <linux/kernel_stat.h>
0017 #include <linux/init.h>
0018 #include <linux/spinlock.h>
0019 #include <linux/mm.h>
0020 #include <linux/fs.h>
0021 #include <linux/seq_file.h>
0022 #include <linux/cache.h>
0023 #include <linux/delay.h>
0024 #include <linux/profile.h>
0025 #include <linux/cpu.h>
0026
0027 #include <asm/ptrace.h>
0028 #include <linux/atomic.h>
0029
0030 #include <asm/irq.h>
0031 #include <asm/page.h>
0032 #include <asm/oplib.h>
0033 #include <asm/cacheflush.h>
0034 #include <asm/tlbflush.h>
0035 #include <asm/cpudata.h>
0036 #include <asm/timer.h>
0037 #include <asm/leon.h>
0038
0039 #include "kernel.h"
0040 #include "irq.h"
0041
0042 volatile unsigned long cpu_callin_map[NR_CPUS] = {0,};
0043
0044 cpumask_t smp_commenced_mask = CPU_MASK_NONE;
0045
0046 const struct sparc32_ipi_ops *sparc32_ipi_ops;
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056 void smp_store_cpu_info(int id)
0057 {
0058 int cpu_node;
0059 int mid;
0060
0061 cpu_data(id).udelay_val = loops_per_jiffy;
0062
0063 cpu_find_by_mid(id, &cpu_node);
0064 cpu_data(id).clock_tick = prom_getintdefault(cpu_node,
0065 "clock-frequency", 0);
0066 cpu_data(id).prom_node = cpu_node;
0067 mid = cpu_get_hwmid(cpu_node);
0068
0069 if (mid < 0) {
0070 printk(KERN_NOTICE "No MID found for CPU%d at node 0x%08x", id, cpu_node);
0071 mid = 0;
0072 }
0073 cpu_data(id).mid = mid;
0074 }
0075
0076 void __init smp_cpus_done(unsigned int max_cpus)
0077 {
0078 unsigned long bogosum = 0;
0079 int cpu, num = 0;
0080
0081 for_each_online_cpu(cpu) {
0082 num++;
0083 bogosum += cpu_data(cpu).udelay_val;
0084 }
0085
0086 printk("Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
0087 num, bogosum/(500000/HZ),
0088 (bogosum/(5000/HZ))%100);
0089
0090 switch(sparc_cpu_model) {
0091 case sun4m:
0092 smp4m_smp_done();
0093 break;
0094 case sun4d:
0095 smp4d_smp_done();
0096 break;
0097 case sparc_leon:
0098 leon_smp_done();
0099 break;
0100 case sun4e:
0101 printk("SUN4E\n");
0102 BUG();
0103 break;
0104 case sun4u:
0105 printk("SUN4U\n");
0106 BUG();
0107 break;
0108 default:
0109 printk("UNKNOWN!\n");
0110 BUG();
0111 break;
0112 }
0113 }
0114
0115 void cpu_panic(void)
0116 {
0117 printk("CPU[%d]: Returns from cpu_idle!\n", smp_processor_id());
0118 panic("SMP bolixed\n");
0119 }
0120
0121 struct linux_prom_registers smp_penguin_ctable = { 0 };
0122
0123 void smp_send_reschedule(int cpu)
0124 {
0125
0126
0127
0128
0129
0130 sparc32_ipi_ops->resched(cpu);
0131 }
0132
0133 void smp_send_stop(void)
0134 {
0135 }
0136
0137 void arch_send_call_function_single_ipi(int cpu)
0138 {
0139
0140 sparc32_ipi_ops->single(cpu);
0141 }
0142
0143 void arch_send_call_function_ipi_mask(const struct cpumask *mask)
0144 {
0145 int cpu;
0146
0147
0148 for_each_cpu(cpu, mask)
0149 sparc32_ipi_ops->mask_one(cpu);
0150 }
0151
0152 void smp_resched_interrupt(void)
0153 {
0154 irq_enter();
0155 scheduler_ipi();
0156 local_cpu_data().irq_resched_count++;
0157 irq_exit();
0158
0159 }
0160
0161 void smp_call_function_single_interrupt(void)
0162 {
0163 irq_enter();
0164 generic_smp_call_function_single_interrupt();
0165 local_cpu_data().irq_call_count++;
0166 irq_exit();
0167 }
0168
0169 void smp_call_function_interrupt(void)
0170 {
0171 irq_enter();
0172 generic_smp_call_function_interrupt();
0173 local_cpu_data().irq_call_count++;
0174 irq_exit();
0175 }
0176
0177 void __init smp_prepare_cpus(unsigned int max_cpus)
0178 {
0179 int i, cpuid, extra;
0180
0181 printk("Entering SMP Mode...\n");
0182
0183 extra = 0;
0184 for (i = 0; !cpu_find_by_instance(i, NULL, &cpuid); i++) {
0185 if (cpuid >= NR_CPUS)
0186 extra++;
0187 }
0188
0189 if (extra && max_cpus > i - extra)
0190 printk("Warning: NR_CPUS is too low to start all cpus\n");
0191
0192 smp_store_cpu_info(boot_cpu_id);
0193
0194 switch(sparc_cpu_model) {
0195 case sun4m:
0196 smp4m_boot_cpus();
0197 break;
0198 case sun4d:
0199 smp4d_boot_cpus();
0200 break;
0201 case sparc_leon:
0202 leon_boot_cpus();
0203 break;
0204 case sun4e:
0205 printk("SUN4E\n");
0206 BUG();
0207 break;
0208 case sun4u:
0209 printk("SUN4U\n");
0210 BUG();
0211 break;
0212 default:
0213 printk("UNKNOWN!\n");
0214 BUG();
0215 break;
0216 }
0217 }
0218
0219
0220
0221
0222
0223 void __init smp_setup_cpu_possible_map(void)
0224 {
0225 int instance, mid;
0226
0227 instance = 0;
0228 while (!cpu_find_by_instance(instance, NULL, &mid)) {
0229 if (mid < NR_CPUS) {
0230 set_cpu_possible(mid, true);
0231 set_cpu_present(mid, true);
0232 }
0233 instance++;
0234 }
0235 }
0236
0237 void __init smp_prepare_boot_cpu(void)
0238 {
0239 int cpuid = hard_smp_processor_id();
0240
0241 if (cpuid >= NR_CPUS) {
0242 prom_printf("Serious problem, boot cpu id >= NR_CPUS\n");
0243 prom_halt();
0244 }
0245 if (cpuid != 0)
0246 printk("boot cpu id != 0, this could work but is untested\n");
0247
0248 current_thread_info()->cpu = cpuid;
0249 set_cpu_online(cpuid, true);
0250 set_cpu_possible(cpuid, true);
0251 }
0252
0253 int __cpu_up(unsigned int cpu, struct task_struct *tidle)
0254 {
0255 int ret=0;
0256
0257 switch(sparc_cpu_model) {
0258 case sun4m:
0259 ret = smp4m_boot_one_cpu(cpu, tidle);
0260 break;
0261 case sun4d:
0262 ret = smp4d_boot_one_cpu(cpu, tidle);
0263 break;
0264 case sparc_leon:
0265 ret = leon_boot_one_cpu(cpu, tidle);
0266 break;
0267 case sun4e:
0268 printk("SUN4E\n");
0269 BUG();
0270 break;
0271 case sun4u:
0272 printk("SUN4U\n");
0273 BUG();
0274 break;
0275 default:
0276 printk("UNKNOWN!\n");
0277 BUG();
0278 break;
0279 }
0280
0281 if (!ret) {
0282 cpumask_set_cpu(cpu, &smp_commenced_mask);
0283 while (!cpu_online(cpu))
0284 mb();
0285 }
0286 return ret;
0287 }
0288
0289 static void arch_cpu_pre_starting(void *arg)
0290 {
0291 local_ops->cache_all();
0292 local_ops->tlb_all();
0293
0294 switch(sparc_cpu_model) {
0295 case sun4m:
0296 sun4m_cpu_pre_starting(arg);
0297 break;
0298 case sun4d:
0299 sun4d_cpu_pre_starting(arg);
0300 break;
0301 case sparc_leon:
0302 leon_cpu_pre_starting(arg);
0303 break;
0304 default:
0305 BUG();
0306 }
0307 }
0308
0309 static void arch_cpu_pre_online(void *arg)
0310 {
0311 unsigned int cpuid = hard_smp_processor_id();
0312
0313 register_percpu_ce(cpuid);
0314
0315 calibrate_delay();
0316 smp_store_cpu_info(cpuid);
0317
0318 local_ops->cache_all();
0319 local_ops->tlb_all();
0320
0321 switch(sparc_cpu_model) {
0322 case sun4m:
0323 sun4m_cpu_pre_online(arg);
0324 break;
0325 case sun4d:
0326 sun4d_cpu_pre_online(arg);
0327 break;
0328 case sparc_leon:
0329 leon_cpu_pre_online(arg);
0330 break;
0331 default:
0332 BUG();
0333 }
0334 }
0335
0336 static void sparc_start_secondary(void *arg)
0337 {
0338 unsigned int cpu;
0339
0340
0341
0342
0343
0344 arch_cpu_pre_starting(arg);
0345
0346 cpu = smp_processor_id();
0347
0348 notify_cpu_starting(cpu);
0349 arch_cpu_pre_online(arg);
0350
0351
0352 set_cpu_online(cpu, true);
0353
0354
0355 local_irq_enable();
0356
0357 wmb();
0358 cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
0359
0360
0361 BUG();
0362 }
0363
0364 void smp_callin(void)
0365 {
0366 sparc_start_secondary(NULL);
0367 }
0368
0369 void smp_bogo(struct seq_file *m)
0370 {
0371 int i;
0372
0373 for_each_online_cpu(i) {
0374 seq_printf(m,
0375 "Cpu%dBogo\t: %lu.%02lu\n",
0376 i,
0377 cpu_data(i).udelay_val/(500000/HZ),
0378 (cpu_data(i).udelay_val/(5000/HZ))%100);
0379 }
0380 }
0381
0382 void smp_info(struct seq_file *m)
0383 {
0384 int i;
0385
0386 seq_printf(m, "State:\n");
0387 for_each_online_cpu(i)
0388 seq_printf(m, "CPU%d\t\t: online\n", i);
0389 }