~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/mips/kernel/smp-mt.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  *
  4  * Copyright (C) 2004, 05, 06 MIPS Technologies, Inc.
  5  *    Elizabeth Clarke (beth@mips.com)
  6  *    Ralf Baechle (ralf@linux-mips.org)
  7  * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org)
  8  */
  9 #include <linux/kernel.h>
 10 #include <linux/sched.h>
 11 #include <linux/cpumask.h>
 12 #include <linux/interrupt.h>
 13 #include <linux/compiler.h>
 14 #include <linux/sched/task_stack.h>
 15 #include <linux/smp.h>
 16 
 17 #include <linux/atomic.h>
 18 #include <asm/cacheflush.h>
 19 #include <asm/cpu.h>
 20 #include <asm/processor.h>
 21 #include <asm/hardirq.h>
 22 #include <asm/mmu_context.h>
 23 #include <asm/time.h>
 24 #include <asm/mipsregs.h>
 25 #include <asm/mipsmtregs.h>
 26 #include <asm/mips_mt.h>
 27 #include <asm/mips-cps.h>
 28 
 29 static void __init smvp_copy_vpe_config(void)
 30 {
 31         write_vpe_c0_status(
 32                 (read_c0_status() & ~(ST0_IM | ST0_IE | ST0_KSU)) | ST0_CU0);
 33 
 34         /* set config to be the same as vpe0, particularly kseg0 coherency alg */
 35         write_vpe_c0_config( read_c0_config());
 36 
 37         /* make sure there are no software interrupts pending */
 38         write_vpe_c0_cause(0);
 39 
 40         /* Propagate Config7 */
 41         write_vpe_c0_config7(read_c0_config7());
 42 
 43         write_vpe_c0_count(read_c0_count());
 44 }
 45 
 46 static unsigned int __init smvp_vpe_init(unsigned int tc, unsigned int mvpconf0,
 47         unsigned int ncpu)
 48 {
 49         if (tc >= smp_max_threads ||
 50                 (tc > ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT)))
 51                 return ncpu;
 52 
 53         /* Deactivate all but VPE 0 */
 54         if (tc != 0) {
 55                 unsigned long tmp = read_vpe_c0_vpeconf0();
 56 
 57                 tmp &= ~VPECONF0_VPA;
 58 
 59                 /* master VPE */
 60                 tmp |= VPECONF0_MVP;
 61                 write_vpe_c0_vpeconf0(tmp);
 62 
 63                 /* Record this as available CPU */
 64                 set_cpu_possible(tc, true);
 65                 set_cpu_present(tc, true);
 66                 __cpu_number_map[tc]    = ++ncpu;
 67                 __cpu_logical_map[ncpu] = tc;
 68         }
 69 
 70         /* Disable multi-threading with TC's */
 71         write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() & ~VPECONTROL_TE);
 72 
 73         if (tc != 0)
 74                 smvp_copy_vpe_config();
 75 
 76         cpu_set_vpe_id(&cpu_data[ncpu], tc);
 77 
 78         return ncpu;
 79 }
 80 
 81 static void __init smvp_tc_init(unsigned int tc, unsigned int mvpconf0)
 82 {
 83         unsigned long tmp;
 84 
 85         if (!tc)
 86                 return;
 87 
 88         /* bind a TC to each VPE, May as well put all excess TC's
 89            on the last VPE */
 90         if (tc >= (((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT)+1))
 91                 write_tc_c0_tcbind(read_tc_c0_tcbind() | ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT));
 92         else {
 93                 write_tc_c0_tcbind(read_tc_c0_tcbind() | tc);
 94 
 95                 /* and set XTC */
 96                 write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | (tc << VPECONF0_XTC_SHIFT));
 97         }
 98 
 99         tmp = read_tc_c0_tcstatus();
100 
101         /* mark not allocated and not dynamically allocatable */
102         tmp &= ~(TCSTATUS_A | TCSTATUS_DA);
103         tmp |= TCSTATUS_IXMT;           /* interrupt exempt */
104         write_tc_c0_tcstatus(tmp);
105 
106         write_tc_c0_tchalt(TCHALT_H);
107 }
108 
109 static void vsmp_init_secondary(void)
110 {
111         /* This is Malta specific: IPI,performance and timer interrupts */
112         if (mips_gic_present())
113                 change_c0_status(ST0_IM, STATUSF_IP2 | STATUSF_IP3 |
114                                          STATUSF_IP4 | STATUSF_IP5 |
115                                          STATUSF_IP6 | STATUSF_IP7);
116         else
117                 change_c0_status(ST0_IM, STATUSF_IP0 | STATUSF_IP1 |
118                                          STATUSF_IP6 | STATUSF_IP7);
119 }
120 
121 static void vsmp_smp_finish(void)
122 {
123         /* CDFIXME: remove this? */
124         write_c0_compare(read_c0_count() + (8* mips_hpt_frequency/HZ));
125 
126 #ifdef CONFIG_MIPS_MT_FPAFF
127         /* If we have an FPU, enroll ourselves in the FPU-full mask */
128         if (cpu_has_fpu)
129                 cpumask_set_cpu(smp_processor_id(), &mt_fpu_cpumask);
130 #endif /* CONFIG_MIPS_MT_FPAFF */
131 
132         local_irq_enable();
133 }
134 
135 /*
136  * Setup the PC, SP, and GP of a secondary processor and start it
137  * running!
138  * smp_bootstrap is the place to resume from
139  * __KSTK_TOS(idle) is apparently the stack pointer
140  * (unsigned long)idle->thread_info the gp
141  * assumes a 1:1 mapping of TC => VPE
142  */
143 static int vsmp_boot_secondary(int cpu, struct task_struct *idle)
144 {
145         struct thread_info *gp = task_thread_info(idle);
146         dvpe();
147         set_c0_mvpcontrol(MVPCONTROL_VPC);
148 
149         settc(cpu);
150 
151         /* restart */
152         write_tc_c0_tcrestart((unsigned long)&smp_bootstrap);
153 
154         /* enable the tc this vpe/cpu will be running */
155         write_tc_c0_tcstatus((read_tc_c0_tcstatus() & ~TCSTATUS_IXMT) | TCSTATUS_A);
156 
157         write_tc_c0_tchalt(0);
158 
159         /* enable the VPE */
160         write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);
161 
162         /* stack pointer */
163         write_tc_gpr_sp( __KSTK_TOS(idle));
164 
165         /* global pointer */
166         write_tc_gpr_gp((unsigned long)gp);
167 
168         flush_icache_range((unsigned long)gp,
169                            (unsigned long)(gp + sizeof(struct thread_info)));
170 
171         /* finally out of configuration and into chaos */
172         clear_c0_mvpcontrol(MVPCONTROL_VPC);
173 
174         evpe(EVPE_ENABLE);
175 
176         return 0;
177 }
178 
179 /*
180  * Common setup before any secondaries are started
181  * Make sure all CPU's are in a sensible state before we boot any of the
182  * secondaries
183  */
184 static void __init vsmp_smp_setup(void)
185 {
186         unsigned int mvpconf0, ntc, tc, ncpu = 0;
187         unsigned int nvpe;
188 
189 #ifdef CONFIG_MIPS_MT_FPAFF
190         /* If we have an FPU, enroll ourselves in the FPU-full mask */
191         if (cpu_has_fpu)
192                 cpumask_set_cpu(0, &mt_fpu_cpumask);
193 #endif /* CONFIG_MIPS_MT_FPAFF */
194         if (!cpu_has_mipsmt)
195                 return;
196 
197         /* disable MT so we can configure */
198         dvpe();
199         dmt();
200 
201         /* Put MVPE's into 'configuration state' */
202         set_c0_mvpcontrol(MVPCONTROL_VPC);
203 
204         mvpconf0 = read_c0_mvpconf0();
205         ntc = (mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT;
206 
207         nvpe = ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1;
208         smp_num_siblings = nvpe;
209 
210         /* we'll always have more TC's than VPE's, so loop setting everything
211            to a sensible state */
212         for (tc = 0; tc <= ntc; tc++) {
213                 settc(tc);
214 
215                 smvp_tc_init(tc, mvpconf0);
216                 ncpu = smvp_vpe_init(tc, mvpconf0, ncpu);
217         }
218 
219         /* Release config state */
220         clear_c0_mvpcontrol(MVPCONTROL_VPC);
221 
222         /* We'll wait until starting the secondaries before starting MVPE */
223 
224         printk(KERN_INFO "Detected %i available secondary CPU(s)\n", ncpu);
225 }
226 
227 static void __init vsmp_prepare_cpus(unsigned int max_cpus)
228 {
229         mips_mt_set_cpuoptions();
230 }
231 
232 const struct plat_smp_ops vsmp_smp_ops = {
233         .send_ipi_single        = mips_smp_send_ipi_single,
234         .send_ipi_mask          = mips_smp_send_ipi_mask,
235         .init_secondary         = vsmp_init_secondary,
236         .smp_finish             = vsmp_smp_finish,
237         .boot_secondary         = vsmp_boot_secondary,
238         .smp_setup              = vsmp_smp_setup,
239         .prepare_cpus           = vsmp_prepare_cpus,
240 };
241 
242 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php