^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* smp.c: Sparc SMP support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2004 Keith M Wesolowski (wesolows@foobazco.org)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <asm/head.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/threads.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/smp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/kernel_stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/cache.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/profile.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/cpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <asm/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/atomic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <asm/page.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <asm/oplib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <asm/cacheflush.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <asm/tlbflush.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <asm/cpudata.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <asm/timer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <asm/leon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include "kernel.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include "irq.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) volatile unsigned long cpu_callin_map[NR_CPUS] = {0,};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) cpumask_t smp_commenced_mask = CPU_MASK_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) const struct sparc32_ipi_ops *sparc32_ipi_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* The only guaranteed locking primitive available on all Sparc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * processors is 'ldstub [%reg + immediate], %dest_reg' which atomically
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * places the current byte at the effective address into dest_reg and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * places 0xff there afterwards. Pretty lame locking primitive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * compared to the Alpha and the Intel no? Most Sparcs have 'swap'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * instruction which is much better...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) void smp_store_cpu_info(int id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) int cpu_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) int mid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) cpu_data(id).udelay_val = loops_per_jiffy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) cpu_find_by_mid(id, &cpu_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) cpu_data(id).clock_tick = prom_getintdefault(cpu_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) "clock-frequency", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) cpu_data(id).prom_node = cpu_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) mid = cpu_get_hwmid(cpu_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (mid < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) printk(KERN_NOTICE "No MID found for CPU%d at node 0x%08x", id, cpu_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) mid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) cpu_data(id).mid = mid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) void __init smp_cpus_done(unsigned int max_cpus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) unsigned long bogosum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) int cpu, num = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) for_each_online_cpu(cpu) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) num++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) bogosum += cpu_data(cpu).udelay_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) printk("Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) num, bogosum/(500000/HZ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) (bogosum/(5000/HZ))%100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) switch(sparc_cpu_model) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) case sun4m:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) smp4m_smp_done();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) case sun4d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) smp4d_smp_done();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) case sparc_leon:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) leon_smp_done();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) case sun4e:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) printk("SUN4E\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) case sun4u:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) printk("SUN4U\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) printk("UNKNOWN!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) void cpu_panic(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) printk("CPU[%d]: Returns from cpu_idle!\n", smp_processor_id());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) panic("SMP bolixed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct linux_prom_registers smp_penguin_ctable = { 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) void smp_send_reschedule(int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * CPU model dependent way of implementing IPI generation targeting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * a single CPU. The trap handler needs only to do trap entry/return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * to call schedule.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) sparc32_ipi_ops->resched(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) void smp_send_stop(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) void arch_send_call_function_single_ipi(int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) /* trigger one IPI single call on one CPU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) sparc32_ipi_ops->single(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) void arch_send_call_function_ipi_mask(const struct cpumask *mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /* trigger IPI mask call on each CPU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) for_each_cpu(cpu, mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) sparc32_ipi_ops->mask_one(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) void smp_resched_interrupt(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) irq_enter();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) scheduler_ipi();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) local_cpu_data().irq_resched_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) irq_exit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /* re-schedule routine called by interrupt return code. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) void smp_call_function_single_interrupt(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) irq_enter();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) generic_smp_call_function_single_interrupt();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) local_cpu_data().irq_call_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) irq_exit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) void smp_call_function_interrupt(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) irq_enter();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) generic_smp_call_function_interrupt();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) local_cpu_data().irq_call_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) irq_exit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) int setup_profiling_timer(unsigned int multiplier)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) void __init smp_prepare_cpus(unsigned int max_cpus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) int i, cpuid, extra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) printk("Entering SMP Mode...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) extra = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) for (i = 0; !cpu_find_by_instance(i, NULL, &cpuid); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (cpuid >= NR_CPUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) extra++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) /* i = number of cpus */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (extra && max_cpus > i - extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) printk("Warning: NR_CPUS is too low to start all cpus\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) smp_store_cpu_info(boot_cpu_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) switch(sparc_cpu_model) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) case sun4m:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) smp4m_boot_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) case sun4d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) smp4d_boot_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) case sparc_leon:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) leon_boot_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) case sun4e:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) printk("SUN4E\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) case sun4u:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) printk("SUN4U\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) printk("UNKNOWN!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) /* Set this up early so that things like the scheduler can init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * properly. We use the same cpu mask for both the present and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) * possible cpu map.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) void __init smp_setup_cpu_possible_map(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) int instance, mid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) instance = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) while (!cpu_find_by_instance(instance, NULL, &mid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (mid < NR_CPUS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) set_cpu_possible(mid, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) set_cpu_present(mid, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) instance++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) void __init smp_prepare_boot_cpu(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) int cpuid = hard_smp_processor_id();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (cpuid >= NR_CPUS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) prom_printf("Serious problem, boot cpu id >= NR_CPUS\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) prom_halt();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (cpuid != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) printk("boot cpu id != 0, this could work but is untested\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) current_thread_info()->cpu = cpuid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) set_cpu_online(cpuid, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) set_cpu_possible(cpuid, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) int __cpu_up(unsigned int cpu, struct task_struct *tidle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) int ret=0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) switch(sparc_cpu_model) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) case sun4m:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) ret = smp4m_boot_one_cpu(cpu, tidle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) case sun4d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) ret = smp4d_boot_one_cpu(cpu, tidle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) case sparc_leon:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) ret = leon_boot_one_cpu(cpu, tidle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) case sun4e:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) printk("SUN4E\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) case sun4u:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) printk("SUN4U\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) printk("UNKNOWN!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) cpumask_set_cpu(cpu, &smp_commenced_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) while (!cpu_online(cpu))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) static void arch_cpu_pre_starting(void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) local_ops->cache_all();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) local_ops->tlb_all();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) switch(sparc_cpu_model) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) case sun4m:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) sun4m_cpu_pre_starting(arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) case sun4d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) sun4d_cpu_pre_starting(arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) case sparc_leon:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) leon_cpu_pre_starting(arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) static void arch_cpu_pre_online(void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) unsigned int cpuid = hard_smp_processor_id();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) register_percpu_ce(cpuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) calibrate_delay();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) smp_store_cpu_info(cpuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) local_ops->cache_all();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) local_ops->tlb_all();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) switch(sparc_cpu_model) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) case sun4m:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) sun4m_cpu_pre_online(arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) case sun4d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) sun4d_cpu_pre_online(arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) case sparc_leon:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) leon_cpu_pre_online(arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) static void sparc_start_secondary(void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) unsigned int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) * SMP booting is extremely fragile in some architectures. So run
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) * the cpu initialization code first before anything else.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) arch_cpu_pre_starting(arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) cpu = smp_processor_id();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) notify_cpu_starting(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) arch_cpu_pre_online(arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) /* Set the CPU in the cpu_online_mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) set_cpu_online(cpu, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) /* Enable local interrupts now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) local_irq_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) /* We should never reach here! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) void smp_callin(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) sparc_start_secondary(NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) void smp_bogo(struct seq_file *m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) for_each_online_cpu(i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) seq_printf(m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) "Cpu%dBogo\t: %lu.%02lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) cpu_data(i).udelay_val/(500000/HZ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) (cpu_data(i).udelay_val/(5000/HZ))%100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) void smp_info(struct seq_file *m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) seq_printf(m, "State:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) for_each_online_cpu(i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) seq_printf(m, "CPU%d\t\t: online\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }