Blame view
arch/mips/kernel/smp-mt.c
7.15 KB
340ee4b98 Virtual SMP suppo... |
1 |
/* |
340ee4b98 Virtual SMP suppo... |
2 3 4 5 6 7 8 9 10 11 12 13 14 |
* This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. * |
41c594ab6 [MIPS] MT: Improv... |
15 16 17 18 |
* Copyright (C) 2004, 05, 06 MIPS Technologies, Inc. * Elizabeth Clarke (beth@mips.com) * Ralf Baechle (ralf@linux-mips.org) * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org) |
340ee4b98 Virtual SMP suppo... |
19 20 21 22 23 24 |
*/ #include <linux/kernel.h> #include <linux/sched.h> #include <linux/cpumask.h> #include <linux/interrupt.h> #include <linux/compiler.h> |
0ab7aefc4 [MIPS] MT: Schedu... |
25 |
#include <linux/smp.h> |
340ee4b98 Virtual SMP suppo... |
26 |
|
60063497a atomic: use <linu... |
27 |
#include <linux/atomic.h> |
41c594ab6 [MIPS] MT: Improv... |
28 |
#include <asm/cacheflush.h> |
340ee4b98 Virtual SMP suppo... |
29 30 31 32 33 |
#include <asm/cpu.h> #include <asm/processor.h> #include <asm/system.h> #include <asm/hardirq.h> #include <asm/mmu_context.h> |
340ee4b98 Virtual SMP suppo... |
34 35 36 |
#include <asm/time.h> #include <asm/mipsregs.h> #include <asm/mipsmtregs.h> |
41c594ab6 [MIPS] MT: Improv... |
37 |
#include <asm/mips_mt.h> |
340ee4b98 Virtual SMP suppo... |
38 |
|
39b8d5254 [MIPS] Add suppor... |
39 |
static void __init smvp_copy_vpe_config(void) |
781b0f8d4 [MIPS] VSMP: Fix ... |
40 41 42 43 44 45 46 47 48 49 50 51 |
{ write_vpe_c0_status( (read_c0_status() & ~(ST0_IM | ST0_IE | ST0_KSU)) | ST0_CU0); /* set config to be the same as vpe0, particularly kseg0 coherency alg */ write_vpe_c0_config( read_c0_config()); /* make sure there are no software interrupts pending */ write_vpe_c0_cause(0); /* Propagate Config7 */ write_vpe_c0_config7(read_c0_config7()); |
70e46f48c [MIPS] VSMP: Sync... |
52 53 |
write_vpe_c0_count(read_c0_count()); |
781b0f8d4 [MIPS] VSMP: Fix ... |
54 |
} |
39b8d5254 [MIPS] Add suppor... |
55 |
static unsigned int __init smvp_vpe_init(unsigned int tc, unsigned int mvpconf0, |
781b0f8d4 [MIPS] VSMP: Fix ... |
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
unsigned int ncpu) { if (tc > ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT)) return ncpu; /* Deactivate all but VPE 0 */ if (tc != 0) { unsigned long tmp = read_vpe_c0_vpeconf0(); tmp &= ~VPECONF0_VPA; /* master VPE */ tmp |= VPECONF0_MVP; write_vpe_c0_vpeconf0(tmp); /* Record this as available CPU */ |
4037ac6e2 cpumask: Use acce... |
72 |
set_cpu_possible(tc, true); |
781b0f8d4 [MIPS] VSMP: Fix ... |
73 74 75 76 77 78 79 80 |
__cpu_number_map[tc] = ++ncpu; __cpu_logical_map[ncpu] = tc; } /* Disable multi-threading with TC's */ write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() & ~VPECONTROL_TE); if (tc != 0) |
39b8d5254 [MIPS] Add suppor... |
81 |
smvp_copy_vpe_config(); |
781b0f8d4 [MIPS] VSMP: Fix ... |
82 83 84 |
return ncpu; } |
39b8d5254 [MIPS] Add suppor... |
85 |
static void __init smvp_tc_init(unsigned int tc, unsigned int mvpconf0) |
781b0f8d4 [MIPS] VSMP: Fix ... |
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
{ unsigned long tmp; if (!tc) return; /* bind a TC to each VPE, May as well put all excess TC's on the last VPE */ if (tc >= (((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT)+1)) write_tc_c0_tcbind(read_tc_c0_tcbind() | ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT)); else { write_tc_c0_tcbind(read_tc_c0_tcbind() | tc); /* and set XTC */ write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | (tc << VPECONF0_XTC_SHIFT)); } tmp = read_tc_c0_tcstatus(); /* mark not allocated and not dynamically allocatable */ tmp &= ~(TCSTATUS_A | TCSTATUS_DA); tmp |= TCSTATUS_IXMT; /* interrupt exempt */ write_tc_c0_tcstatus(tmp); write_tc_c0_tchalt(TCHALT_H); } |
87353d8ac [MIPS] SMP: Call ... |
112 |
static void vsmp_send_ipi_single(int cpu, unsigned int action) |
340ee4b98 Virtual SMP suppo... |
113 |
{ |
87353d8ac [MIPS] SMP: Call ... |
114 115 116 |
int i; unsigned long flags; int vpflags; |
340ee4b98 Virtual SMP suppo... |
117 |
|
87353d8ac [MIPS] SMP: Call ... |
118 |
local_irq_save(flags); |
340ee4b98 Virtual SMP suppo... |
119 |
|
25985edce Fix common misspe... |
120 |
vpflags = dvpe(); /* can't access the other CPU's registers whilst MVPE enabled */ |
340ee4b98 Virtual SMP suppo... |
121 |
|
87353d8ac [MIPS] SMP: Call ... |
122 123 124 125 |
switch (action) { case SMP_CALL_FUNCTION: i = C_SW1; break; |
340ee4b98 Virtual SMP suppo... |
126 |
|
87353d8ac [MIPS] SMP: Call ... |
127 128 129 130 131 |
case SMP_RESCHEDULE_YOURSELF: default: i = C_SW0; break; } |
340ee4b98 Virtual SMP suppo... |
132 |
|
87353d8ac [MIPS] SMP: Call ... |
133 134 135 136 |
/* 1:1 mapping of vpe and tc... */ settc(cpu); write_vpe_c0_cause(read_vpe_c0_cause() | i); evpe(vpflags); |
0ab7aefc4 [MIPS] MT: Schedu... |
137 |
|
87353d8ac [MIPS] SMP: Call ... |
138 139 |
local_irq_restore(flags); } |
340ee4b98 Virtual SMP suppo... |
140 |
|
48a048fed cpumask: arch_sen... |
141 |
static void vsmp_send_ipi_mask(const struct cpumask *mask, unsigned int action) |
87353d8ac [MIPS] SMP: Call ... |
142 143 |
{ unsigned int i; |
340ee4b98 Virtual SMP suppo... |
144 |
|
48a048fed cpumask: arch_sen... |
145 |
for_each_cpu(i, mask) |
87353d8ac [MIPS] SMP: Call ... |
146 147 |
vsmp_send_ipi_single(i, action); } |
340ee4b98 Virtual SMP suppo... |
148 |
|
87353d8ac [MIPS] SMP: Call ... |
149 150 |
static void __cpuinit vsmp_init_secondary(void) { |
39b8d5254 [MIPS] Add suppor... |
151 |
extern int gic_present; |
340ee4b98 Virtual SMP suppo... |
152 |
|
d002aaadf MIPS: MT: Fix typ... |
153 |
/* This is Malta specific: IPI,performance and timer interrupts */ |
39b8d5254 [MIPS] Add suppor... |
154 155 156 157 158 159 |
if (gic_present) change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP4 | STATUSF_IP6 | STATUSF_IP7); else change_c0_status(ST0_IM, STATUSF_IP0 | STATUSF_IP1 | STATUSF_IP6 | STATUSF_IP7); |
41c594ab6 [MIPS] MT: Improv... |
160 |
} |
340ee4b98 Virtual SMP suppo... |
161 |
|
87353d8ac [MIPS] SMP: Call ... |
162 |
static void __cpuinit vsmp_smp_finish(void) |
41c594ab6 [MIPS] MT: Improv... |
163 |
{ |
39b8d5254 [MIPS] Add suppor... |
164 |
/* CDFIXME: remove this? */ |
87353d8ac [MIPS] SMP: Call ... |
165 |
write_c0_compare(read_c0_count() + (8* mips_hpt_frequency/HZ)); |
340ee4b98 Virtual SMP suppo... |
166 |
|
87353d8ac [MIPS] SMP: Call ... |
167 168 169 170 171 |
#ifdef CONFIG_MIPS_MT_FPAFF /* If we have an FPU, enroll ourselves in the FPU-full mask */ if (cpu_has_fpu) cpu_set(smp_processor_id(), mt_fpu_cpumask); #endif /* CONFIG_MIPS_MT_FPAFF */ |
340ee4b98 Virtual SMP suppo... |
172 |
|
87353d8ac [MIPS] SMP: Call ... |
173 174 |
local_irq_enable(); } |
340ee4b98 Virtual SMP suppo... |
175 |
|
87353d8ac [MIPS] SMP: Call ... |
176 177 |
static void vsmp_cpus_done(void) { |
340ee4b98 Virtual SMP suppo... |
178 179 180 181 182 183 184 185 186 187 |
} /* * Setup the PC, SP, and GP of a secondary processor and start it * running! * smp_bootstrap is the place to resume from * __KSTK_TOS(idle) is apparently the stack pointer * (unsigned long)idle->thread_info the gp * assumes a 1:1 mapping of TC => VPE */ |
87353d8ac [MIPS] SMP: Call ... |
188 |
static void __cpuinit vsmp_boot_secondary(int cpu, struct task_struct *idle) |
340ee4b98 Virtual SMP suppo... |
189 |
{ |
dc8f6029c [PATCH] mips: tas... |
190 |
struct thread_info *gp = task_thread_info(idle); |
340ee4b98 Virtual SMP suppo... |
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
dvpe(); set_c0_mvpcontrol(MVPCONTROL_VPC); settc(cpu); /* restart */ write_tc_c0_tcrestart((unsigned long)&smp_bootstrap); /* enable the tc this vpe/cpu will be running */ write_tc_c0_tcstatus((read_tc_c0_tcstatus() & ~TCSTATUS_IXMT) | TCSTATUS_A); write_tc_c0_tchalt(0); /* enable the VPE */ write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA); /* stack pointer */ write_tc_gpr_sp( __KSTK_TOS(idle)); /* global pointer */ |
dc8f6029c [PATCH] mips: tas... |
211 |
write_tc_gpr_gp((unsigned long)gp); |
340ee4b98 Virtual SMP suppo... |
212 |
|
41c594ab6 [MIPS] MT: Improv... |
213 214 |
flush_icache_range((unsigned long)gp, (unsigned long)(gp + sizeof(struct thread_info))); |
340ee4b98 Virtual SMP suppo... |
215 216 217 218 219 220 |
/* finally out of configuration and into chaos */ clear_c0_mvpcontrol(MVPCONTROL_VPC); evpe(EVPE_ENABLE); } |
87353d8ac [MIPS] SMP: Call ... |
221 222 223 |
/* * Common setup before any secondaries are started * Make sure all CPU's are in a sensible state before we boot any of the |
39b8d5254 [MIPS] Add suppor... |
224 |
* secondaries |
87353d8ac [MIPS] SMP: Call ... |
225 226 |
*/ static void __init vsmp_smp_setup(void) |
340ee4b98 Virtual SMP suppo... |
227 |
{ |
87353d8ac [MIPS] SMP: Call ... |
228 229 |
unsigned int mvpconf0, ntc, tc, ncpu = 0; unsigned int nvpe; |
340ee4b98 Virtual SMP suppo... |
230 |
|
f088fc84f [MIPS] FPU affini... |
231 232 233 |
#ifdef CONFIG_MIPS_MT_FPAFF /* If we have an FPU, enroll ourselves in the FPU-full mask */ if (cpu_has_fpu) |
87353d8ac [MIPS] SMP: Call ... |
234 |
cpu_set(0, mt_fpu_cpumask); |
f088fc84f [MIPS] FPU affini... |
235 |
#endif /* CONFIG_MIPS_MT_FPAFF */ |
87353d8ac [MIPS] SMP: Call ... |
236 237 |
if (!cpu_has_mipsmt) return; |
f088fc84f [MIPS] FPU affini... |
238 |
|
87353d8ac [MIPS] SMP: Call ... |
239 240 241 |
/* disable MT so we can configure */ dvpe(); dmt(); |
340ee4b98 Virtual SMP suppo... |
242 |
|
87353d8ac [MIPS] SMP: Call ... |
243 244 |
/* Put MVPE's into 'configuration state' */ set_c0_mvpcontrol(MVPCONTROL_VPC); |
340ee4b98 Virtual SMP suppo... |
245 |
|
87353d8ac [MIPS] SMP: Call ... |
246 247 |
mvpconf0 = read_c0_mvpconf0(); ntc = (mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT; |
340ee4b98 Virtual SMP suppo... |
248 |
|
87353d8ac [MIPS] SMP: Call ... |
249 250 |
nvpe = ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1; smp_num_siblings = nvpe; |
340ee4b98 Virtual SMP suppo... |
251 |
|
87353d8ac [MIPS] SMP: Call ... |
252 253 254 255 |
/* we'll always have more TC's than VPE's, so loop setting everything to a sensible state */ for (tc = 0; tc <= ntc; tc++) { settc(tc); |
340ee4b98 Virtual SMP suppo... |
256 |
|
39b8d5254 [MIPS] Add suppor... |
257 258 |
smvp_tc_init(tc, mvpconf0); ncpu = smvp_vpe_init(tc, mvpconf0, ncpu); |
87353d8ac [MIPS] SMP: Call ... |
259 |
} |
340ee4b98 Virtual SMP suppo... |
260 |
|
87353d8ac [MIPS] SMP: Call ... |
261 262 263 264 265 266 267 268 269 270 271 272 |
/* Release config state */ clear_c0_mvpcontrol(MVPCONTROL_VPC); /* We'll wait until starting the secondaries before starting MVPE */ printk(KERN_INFO "Detected %i available secondary CPU(s) ", ncpu); } static void __init vsmp_prepare_cpus(unsigned int max_cpus) { mips_mt_set_cpuoptions(); |
340ee4b98 Virtual SMP suppo... |
273 |
} |
87353d8ac [MIPS] SMP: Call ... |
274 275 276 277 278 279 280 281 282 283 284 |
struct plat_smp_ops vsmp_smp_ops = { .send_ipi_single = vsmp_send_ipi_single, .send_ipi_mask = vsmp_send_ipi_mask, .init_secondary = vsmp_init_secondary, .smp_finish = vsmp_smp_finish, .cpus_done = vsmp_cpus_done, .boot_secondary = vsmp_boot_secondary, .smp_setup = vsmp_smp_setup, .prepare_cpus = vsmp_prepare_cpus, }; |