Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* smp.c: Sparc SMP support.
0003  *
0004  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
0005  * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
0006  * Copyright (C) 2004 Keith M Wesolowski (wesolows@foobazco.org)
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 /* The only guaranteed locking primitive available on all Sparc
0049  * processors is 'ldstub [%reg + immediate], %dest_reg' which atomically
0050  * places the current byte at the effective address into dest_reg and
0051  * places 0xff there afterwards.  Pretty lame locking primitive
0052  * compared to the Alpha and the Intel no?  Most Sparcs have 'swap'
0053  * instruction which is much better...
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      * CPU model dependent way of implementing IPI generation targeting
0127      * a single CPU. The trap handler needs only to do trap entry/return
0128      * to call schedule.
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     /* trigger one IPI single call on one CPU */
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     /* trigger IPI mask call on each CPU */
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     /* re-schedule routine called by interrupt return code. */
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     /* i = number of cpus */
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 /* Set this up early so that things like the scheduler can init
0220  * properly.  We use the same cpu mask for both the present and
0221  * possible cpu map.
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      * SMP booting is extremely fragile in some architectures. So run
0342      * the cpu initialization code first before anything else.
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     /* Set the CPU in the cpu_online_mask */
0352     set_cpu_online(cpu, true);
0353 
0354     /* Enable local interrupts now */
0355     local_irq_enable();
0356 
0357     wmb();
0358     cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
0359 
0360     /* We should never reach here! */
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 }