^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2007 MIPS Technologies, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Chris Dearman (chris@mips.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #undef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/sched/task_stack.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/smp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/cpumask.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/compiler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/atomic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <asm/cacheflush.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <asm/cpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/processor.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/hardirq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <asm/mmu_context.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <asm/smp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <asm/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <asm/mipsregs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <asm/mipsmtregs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <asm/mips_mt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <asm/amon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static void cmp_init_secondary(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct cpuinfo_mips *c __maybe_unused = ¤t_cpu_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /* Assume GIC is present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) change_c0_status(ST0_IM, STATUSF_IP2 | STATUSF_IP3 | STATUSF_IP4 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) STATUSF_IP5 | STATUSF_IP6 | STATUSF_IP7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /* Enable per-cpu interrupts: platform specific */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #ifdef CONFIG_MIPS_MT_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) if (cpu_has_mipsmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) cpu_set_vpe_id(c, (read_c0_tcbind() >> TCBIND_CURVPE_SHIFT) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) TCBIND_CURVPE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static void cmp_smp_finish(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) pr_debug("SMPCMP: CPU%d: %s\n", smp_processor_id(), __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* CDFIXME: remove this? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) write_c0_compare(read_c0_count() + (8 * mips_hpt_frequency / HZ));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #ifdef CONFIG_MIPS_MT_FPAFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /* If we have an FPU, enroll ourselves in the FPU-full mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (cpu_has_fpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) cpumask_set_cpu(smp_processor_id(), &mt_fpu_cpumask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #endif /* CONFIG_MIPS_MT_FPAFF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) local_irq_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * Setup the PC, SP, and GP of a secondary processor and start it running
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * smp_bootstrap is the place to resume from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * __KSTK_TOS(idle) is apparently the stack pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * (unsigned long)idle->thread_info the gp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static int cmp_boot_secondary(int cpu, struct task_struct *idle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct thread_info *gp = task_thread_info(idle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) unsigned long sp = __KSTK_TOS(idle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) unsigned long pc = (unsigned long)&smp_bootstrap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) unsigned long a0 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) pr_debug("SMPCMP: CPU%d: %s cpu %d\n", smp_processor_id(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) __func__, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* Needed? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) flush_icache_range((unsigned long)gp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) (unsigned long)(gp + sizeof(struct thread_info)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) amon_cpu_start(cpu, pc, sp, (unsigned long)gp, a0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * Common setup before any secondaries are started
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) void __init cmp_smp_setup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) int ncpu = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) pr_debug("SMPCMP: CPU%d: %s\n", smp_processor_id(), __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #ifdef CONFIG_MIPS_MT_FPAFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /* If we have an FPU, enroll ourselves in the FPU-full mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (cpu_has_fpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) cpumask_set_cpu(0, &mt_fpu_cpumask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #endif /* CONFIG_MIPS_MT_FPAFF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) for (i = 1; i < NR_CPUS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (amon_cpu_avail(i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) set_cpu_possible(i, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) __cpu_number_map[i] = ++ncpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) __cpu_logical_map[ncpu] = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (cpu_has_mipsmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) unsigned int nvpe = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #ifdef CONFIG_MIPS_MT_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) unsigned int mvpconf0 = read_c0_mvpconf0();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) nvpe = ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) smp_num_siblings = nvpe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) pr_info("Detected %i available secondary CPU(s)\n", ncpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) void __init cmp_prepare_cpus(unsigned int max_cpus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) pr_debug("SMPCMP: CPU%d: %s max_cpus=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) smp_processor_id(), __func__, max_cpus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #ifdef CONFIG_MIPS_MT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * FIXME: some of these options are per-system, some per-core and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * some per-cpu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) mips_mt_set_cpuoptions();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) const struct plat_smp_ops cmp_smp_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) .send_ipi_single = mips_smp_send_ipi_single,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) .send_ipi_mask = mips_smp_send_ipi_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) .init_secondary = cmp_init_secondary,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) .smp_finish = cmp_smp_finish,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) .boot_secondary = cmp_boot_secondary,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) .smp_setup = cmp_smp_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) .prepare_cpus = cmp_prepare_cpus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) };