Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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) }