diff options
author | Chris Metcalf <cmetcalf@tilera.com> | 2010-10-14 16:00:11 -0400 |
---|---|---|
committer | Chris Metcalf <cmetcalf@tilera.com> | 2010-10-15 15:36:54 -0400 |
commit | bf65e440e8248f22b2eacf8d47961bb9d52260f7 (patch) | |
tree | 49189dfa1bc90732caedc1e872baed9fb360adf0 /arch/tile | |
parent | 4fe938c5134fce1f25e1261eef6252fb47634962 (diff) |
arch/tile: add Tilera's <arch/sim.h> header as an open-source header
This change adds one of the Tilera standard <arch> headers to the set
of headers shipped with Linux. The <arch/sim.h> header provides
methods for programmatically interacting with the Tilera simulator.
The current <arch/sim.h> provides inline assembly for the _sim_syscall
function, so the declaration and definition previously provided
manually in Linux are no longer needed. We now use the standard
sim_validate_lines_evicted() method from <arch/sim.h> rather than
rolling our own direct call to sim_syscall().
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
Diffstat (limited to 'arch/tile')
-rw-r--r-- | arch/tile/include/arch/sim.h | 619 | ||||
-rw-r--r-- | arch/tile/include/asm/system.h | 7 | ||||
-rw-r--r-- | arch/tile/kernel/entry.S | 22 | ||||
-rw-r--r-- | arch/tile/mm/homecache.c | 11 |
4 files changed, 622 insertions, 37 deletions
diff --git a/arch/tile/include/arch/sim.h b/arch/tile/include/arch/sim.h new file mode 100644 index 000000000000..74b7c1624d34 --- /dev/null +++ b/arch/tile/include/arch/sim.h | |||
@@ -0,0 +1,619 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Tilera Corporation. All Rights Reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation, version 2. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, but | ||
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
11 | * NON INFRINGEMENT. See the GNU General Public License for | ||
12 | * more details. | ||
13 | */ | ||
14 | |||
15 | /** | ||
16 | * @file | ||
17 | * | ||
18 | * Provides an API for controlling the simulator at runtime. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @addtogroup arch_sim | ||
23 | * @{ | ||
24 | * | ||
25 | * An API for controlling the simulator at runtime. | ||
26 | * | ||
27 | * The simulator's behavior can be modified while it is running. | ||
28 | * For example, human-readable trace output can be enabled and disabled | ||
29 | * around code of interest. | ||
30 | * | ||
31 | * There are two ways to modify simulator behavior: | ||
32 | * programmatically, by calling various sim_* functions, and | ||
33 | * interactively, by entering commands like "sim set functional true" | ||
34 | * at the tile-monitor prompt. Typing "sim help" at that prompt provides | ||
35 | * a list of interactive commands. | ||
36 | * | ||
37 | * All interactive commands can also be executed programmatically by | ||
38 | * passing a string to the sim_command function. | ||
39 | */ | ||
40 | |||
41 | #ifndef __ARCH_SIM_H__ | ||
42 | #define __ARCH_SIM_H__ | ||
43 | |||
44 | #include <arch/sim_def.h> | ||
45 | #include <arch/abi.h> | ||
46 | |||
47 | #ifndef __ASSEMBLER__ | ||
48 | |||
49 | #include <arch/spr_def.h> | ||
50 | |||
51 | |||
52 | /** | ||
53 | * Return true if the current program is running under a simulator, | ||
54 | * rather than on real hardware. If running on hardware, other "sim_xxx()" | ||
55 | * calls have no useful effect. | ||
56 | */ | ||
57 | static inline int | ||
58 | sim_is_simulator(void) | ||
59 | { | ||
60 | return __insn_mfspr(SPR_SIM_CONTROL) != 0; | ||
61 | } | ||
62 | |||
63 | |||
64 | /** | ||
65 | * Checkpoint the simulator state to a checkpoint file. | ||
66 | * | ||
67 | * The checkpoint file name is either the default or the name specified | ||
68 | * on the command line with "--checkpoint-file". | ||
69 | */ | ||
70 | static __inline void | ||
71 | sim_checkpoint(void) | ||
72 | { | ||
73 | __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_CHECKPOINT); | ||
74 | } | ||
75 | |||
76 | |||
77 | /** | ||
78 | * Report whether or not various kinds of simulator tracing are enabled. | ||
79 | * | ||
80 | * @return The bitwise OR of these values: | ||
81 | * | ||
82 | * SIM_TRACE_CYCLES (--trace-cycles), | ||
83 | * SIM_TRACE_ROUTER (--trace-router), | ||
84 | * SIM_TRACE_REGISTER_WRITES (--trace-register-writes), | ||
85 | * SIM_TRACE_DISASM (--trace-disasm), | ||
86 | * SIM_TRACE_STALL_INFO (--trace-stall-info) | ||
87 | * SIM_TRACE_MEMORY_CONTROLLER (--trace-memory-controller) | ||
88 | * SIM_TRACE_L2_CACHE (--trace-l2) | ||
89 | * SIM_TRACE_LINES (--trace-lines) | ||
90 | */ | ||
91 | static __inline unsigned int | ||
92 | sim_get_tracing(void) | ||
93 | { | ||
94 | return __insn_mfspr(SPR_SIM_CONTROL) & SIM_TRACE_FLAG_MASK; | ||
95 | } | ||
96 | |||
97 | |||
98 | /** | ||
99 | * Turn on or off different kinds of simulator tracing. | ||
100 | * | ||
101 | * @param mask Either one of these special values: | ||
102 | * | ||
103 | * SIM_TRACE_NONE (turns off tracing), | ||
104 | * SIM_TRACE_ALL (turns on all possible tracing). | ||
105 | * | ||
106 | * or the bitwise OR of these values: | ||
107 | * | ||
108 | * SIM_TRACE_CYCLES (--trace-cycles), | ||
109 | * SIM_TRACE_ROUTER (--trace-router), | ||
110 | * SIM_TRACE_REGISTER_WRITES (--trace-register-writes), | ||
111 | * SIM_TRACE_DISASM (--trace-disasm), | ||
112 | * SIM_TRACE_STALL_INFO (--trace-stall-info) | ||
113 | * SIM_TRACE_MEMORY_CONTROLLER (--trace-memory-controller) | ||
114 | * SIM_TRACE_L2_CACHE (--trace-l2) | ||
115 | * SIM_TRACE_LINES (--trace-lines) | ||
116 | */ | ||
117 | static __inline void | ||
118 | sim_set_tracing(unsigned int mask) | ||
119 | { | ||
120 | __insn_mtspr(SPR_SIM_CONTROL, SIM_TRACE_SPR_ARG(mask)); | ||
121 | } | ||
122 | |||
123 | |||
124 | /** | ||
125 | * Request dumping of different kinds of simulator state. | ||
126 | * | ||
127 | * @param mask Either this special value: | ||
128 | * | ||
129 | * SIM_DUMP_ALL (dump all known state) | ||
130 | * | ||
131 | * or the bitwise OR of these values: | ||
132 | * | ||
133 | * SIM_DUMP_REGS (the register file), | ||
134 | * SIM_DUMP_SPRS (the SPRs), | ||
135 | * SIM_DUMP_ITLB (the iTLB), | ||
136 | * SIM_DUMP_DTLB (the dTLB), | ||
137 | * SIM_DUMP_L1I (the L1 I-cache), | ||
138 | * SIM_DUMP_L1D (the L1 D-cache), | ||
139 | * SIM_DUMP_L2 (the L2 cache), | ||
140 | * SIM_DUMP_SNREGS (the switch register file), | ||
141 | * SIM_DUMP_SNITLB (the switch iTLB), | ||
142 | * SIM_DUMP_SNL1I (the switch L1 I-cache), | ||
143 | * SIM_DUMP_BACKTRACE (the current backtrace) | ||
144 | */ | ||
145 | static __inline void | ||
146 | sim_dump(unsigned int mask) | ||
147 | { | ||
148 | __insn_mtspr(SPR_SIM_CONTROL, SIM_DUMP_SPR_ARG(mask)); | ||
149 | } | ||
150 | |||
151 | |||
152 | /** | ||
153 | * Print a string to the simulator stdout. | ||
154 | * | ||
155 | * @param str The string to be written; a newline is automatically added. | ||
156 | */ | ||
157 | static __inline void | ||
158 | sim_print_string(const char* str) | ||
159 | { | ||
160 | int i; | ||
161 | for (i = 0; str[i] != 0; i++) | ||
162 | { | ||
163 | __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PUTC | | ||
164 | (str[i] << _SIM_CONTROL_OPERATOR_BITS)); | ||
165 | } | ||
166 | __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PUTC | | ||
167 | (SIM_PUTC_FLUSH_STRING << _SIM_CONTROL_OPERATOR_BITS)); | ||
168 | } | ||
169 | |||
170 | |||
171 | /** | ||
172 | * Execute a simulator command string. | ||
173 | * | ||
174 | * Type 'sim help' at the tile-monitor prompt to learn what commands | ||
175 | * are available. Note the use of the tile-monitor "sim" command to | ||
176 | * pass commands to the simulator. | ||
177 | * | ||
178 | * The argument to sim_command() does not include the leading "sim" | ||
179 | * prefix used at the tile-monitor prompt; for example, you might call | ||
180 | * sim_command("trace disasm"). | ||
181 | */ | ||
182 | static __inline void | ||
183 | sim_command(const char* str) | ||
184 | { | ||
185 | int c; | ||
186 | do | ||
187 | { | ||
188 | c = *str++; | ||
189 | __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_COMMAND | | ||
190 | (c << _SIM_CONTROL_OPERATOR_BITS)); | ||
191 | } | ||
192 | while (c); | ||
193 | } | ||
194 | |||
195 | |||
196 | |||
197 | #ifndef __DOXYGEN__ | ||
198 | |||
199 | /** | ||
200 | * The underlying implementation of "_sim_syscall()". | ||
201 | * | ||
202 | * We use extra "and" instructions to ensure that all the values | ||
203 | * we are passing to the simulator are actually valid in the registers | ||
204 | * (i.e. returned from memory) prior to the SIM_CONTROL spr. | ||
205 | */ | ||
206 | static __inline int _sim_syscall0(int val) | ||
207 | { | ||
208 | long result; | ||
209 | __asm__ __volatile__ ("mtspr SIM_CONTROL, r0" | ||
210 | : "=R00" (result) : "R00" (val)); | ||
211 | return result; | ||
212 | } | ||
213 | |||
214 | static __inline int _sim_syscall1(int val, long arg1) | ||
215 | { | ||
216 | long result; | ||
217 | __asm__ __volatile__ ("{ and zero, r1, r1; mtspr SIM_CONTROL, r0 }" | ||
218 | : "=R00" (result) : "R00" (val), "R01" (arg1)); | ||
219 | return result; | ||
220 | } | ||
221 | |||
222 | static __inline int _sim_syscall2(int val, long arg1, long arg2) | ||
223 | { | ||
224 | long result; | ||
225 | __asm__ __volatile__ ("{ and zero, r1, r2; mtspr SIM_CONTROL, r0 }" | ||
226 | : "=R00" (result) | ||
227 | : "R00" (val), "R01" (arg1), "R02" (arg2)); | ||
228 | return result; | ||
229 | } | ||
230 | |||
231 | /* Note that _sim_syscall3() and higher are technically at risk of | ||
232 | receiving an interrupt right before the mtspr bundle, in which case | ||
233 | the register values for arguments 3 and up may still be in flight | ||
234 | to the core from a stack frame reload. */ | ||
235 | |||
236 | static __inline int _sim_syscall3(int val, long arg1, long arg2, long arg3) | ||
237 | { | ||
238 | long result; | ||
239 | __asm__ __volatile__ ("{ and zero, r3, r3 };" | ||
240 | "{ and zero, r1, r2; mtspr SIM_CONTROL, r0 }" | ||
241 | : "=R00" (result) | ||
242 | : "R00" (val), "R01" (arg1), "R02" (arg2), | ||
243 | "R03" (arg3)); | ||
244 | return result; | ||
245 | } | ||
246 | |||
247 | static __inline int _sim_syscall4(int val, long arg1, long arg2, long arg3, | ||
248 | long arg4) | ||
249 | { | ||
250 | long result; | ||
251 | __asm__ __volatile__ ("{ and zero, r3, r4 };" | ||
252 | "{ and zero, r1, r2; mtspr SIM_CONTROL, r0 }" | ||
253 | : "=R00" (result) | ||
254 | : "R00" (val), "R01" (arg1), "R02" (arg2), | ||
255 | "R03" (arg3), "R04" (arg4)); | ||
256 | return result; | ||
257 | } | ||
258 | |||
259 | static __inline int _sim_syscall5(int val, long arg1, long arg2, long arg3, | ||
260 | long arg4, long arg5) | ||
261 | { | ||
262 | long result; | ||
263 | __asm__ __volatile__ ("{ and zero, r3, r4; and zero, r5, r5 };" | ||
264 | "{ and zero, r1, r2; mtspr SIM_CONTROL, r0 }" | ||
265 | : "=R00" (result) | ||
266 | : "R00" (val), "R01" (arg1), "R02" (arg2), | ||
267 | "R03" (arg3), "R04" (arg4), "R05" (arg5)); | ||
268 | return result; | ||
269 | } | ||
270 | |||
271 | |||
272 | /** | ||
273 | * Make a special syscall to the simulator itself, if running under | ||
274 | * simulation. This is used as the implementation of other functions | ||
275 | * and should not be used outside this file. | ||
276 | * | ||
277 | * @param syscall_num The simulator syscall number. | ||
278 | * @param nr The number of additional arguments provided. | ||
279 | * | ||
280 | * @return Varies by syscall. | ||
281 | */ | ||
282 | #define _sim_syscall(syscall_num, nr, args...) \ | ||
283 | _sim_syscall##nr( \ | ||
284 | ((syscall_num) << _SIM_CONTROL_OPERATOR_BITS) | SIM_CONTROL_SYSCALL, args) | ||
285 | |||
286 | |||
287 | /* Values for the "access_mask" parameters below. */ | ||
288 | #define SIM_WATCHPOINT_READ 1 | ||
289 | #define SIM_WATCHPOINT_WRITE 2 | ||
290 | #define SIM_WATCHPOINT_EXECUTE 4 | ||
291 | |||
292 | |||
293 | static __inline int | ||
294 | sim_add_watchpoint(unsigned int process_id, | ||
295 | unsigned long address, | ||
296 | unsigned long size, | ||
297 | unsigned int access_mask, | ||
298 | unsigned long user_data) | ||
299 | { | ||
300 | return _sim_syscall(SIM_SYSCALL_ADD_WATCHPOINT, 5, process_id, | ||
301 | address, size, access_mask, user_data); | ||
302 | } | ||
303 | |||
304 | |||
305 | static __inline int | ||
306 | sim_remove_watchpoint(unsigned int process_id, | ||
307 | unsigned long address, | ||
308 | unsigned long size, | ||
309 | unsigned int access_mask, | ||
310 | unsigned long user_data) | ||
311 | { | ||
312 | return _sim_syscall(SIM_SYSCALL_REMOVE_WATCHPOINT, 5, process_id, | ||
313 | address, size, access_mask, user_data); | ||
314 | } | ||
315 | |||
316 | |||
317 | /** | ||
318 | * Return value from sim_query_watchpoint. | ||
319 | */ | ||
320 | struct SimQueryWatchpointStatus | ||
321 | { | ||
322 | /** | ||
323 | * 0 if a watchpoint fired, 1 if no watchpoint fired, or -1 for | ||
324 | * error (meaning a bad process_id). | ||
325 | */ | ||
326 | int syscall_status; | ||
327 | |||
328 | /** | ||
329 | * The address of the watchpoint that fired (this is the address | ||
330 | * passed to sim_add_watchpoint, not an address within that range | ||
331 | * that actually triggered the watchpoint). | ||
332 | */ | ||
333 | unsigned long address; | ||
334 | |||
335 | /** The arbitrary user_data installed by sim_add_watchpoint. */ | ||
336 | unsigned long user_data; | ||
337 | }; | ||
338 | |||
339 | |||
340 | static __inline struct SimQueryWatchpointStatus | ||
341 | sim_query_watchpoint(unsigned int process_id) | ||
342 | { | ||
343 | struct SimQueryWatchpointStatus status; | ||
344 | long val = SIM_CONTROL_SYSCALL | | ||
345 | (SIM_SYSCALL_QUERY_WATCHPOINT << _SIM_CONTROL_OPERATOR_BITS); | ||
346 | __asm__ __volatile__ ("{ and zero, r1, r1; mtspr SIM_CONTROL, r0 }" | ||
347 | : "=R00" (status.syscall_status), | ||
348 | "=R01" (status.address), | ||
349 | "=R02" (status.user_data) | ||
350 | : "R00" (val), "R01" (process_id)); | ||
351 | return status; | ||
352 | } | ||
353 | |||
354 | |||
355 | /* On the simulator, confirm lines have been evicted everywhere. */ | ||
356 | static __inline void | ||
357 | sim_validate_lines_evicted(unsigned long long pa, unsigned long length) | ||
358 | { | ||
359 | #ifdef __LP64__ | ||
360 | _sim_syscall(SIM_SYSCALL_VALIDATE_LINES_EVICTED, 2, pa, length); | ||
361 | #else | ||
362 | _sim_syscall(SIM_SYSCALL_VALIDATE_LINES_EVICTED, 4, | ||
363 | 0 /* dummy */, (long)(pa), (long)(pa >> 32), length); | ||
364 | #endif | ||
365 | } | ||
366 | |||
367 | |||
368 | #endif /* !__DOXYGEN__ */ | ||
369 | |||
370 | |||
371 | |||
372 | |||
373 | /** | ||
374 | * Modify the shaping parameters of a shim. | ||
375 | * | ||
376 | * @param shim The shim to modify. One of: | ||
377 | * SIM_CONTROL_SHAPING_GBE_0 | ||
378 | * SIM_CONTROL_SHAPING_GBE_1 | ||
379 | * SIM_CONTROL_SHAPING_GBE_2 | ||
380 | * SIM_CONTROL_SHAPING_GBE_3 | ||
381 | * SIM_CONTROL_SHAPING_XGBE_0 | ||
382 | * SIM_CONTROL_SHAPING_XGBE_1 | ||
383 | * | ||
384 | * @param type The type of shaping. This should be the same type of | ||
385 | * shaping that is already in place on the shim. One of: | ||
386 | * SIM_CONTROL_SHAPING_MULTIPLIER | ||
387 | * SIM_CONTROL_SHAPING_PPS | ||
388 | * SIM_CONTROL_SHAPING_BPS | ||
389 | * | ||
390 | * @param units The magnitude of the rate. One of: | ||
391 | * SIM_CONTROL_SHAPING_UNITS_SINGLE | ||
392 | * SIM_CONTROL_SHAPING_UNITS_KILO | ||
393 | * SIM_CONTROL_SHAPING_UNITS_MEGA | ||
394 | * SIM_CONTROL_SHAPING_UNITS_GIGA | ||
395 | * | ||
396 | * @param rate The rate to which to change it. This must fit in | ||
397 | * SIM_CONTROL_SHAPING_RATE_BITS bits or a warning is issued and | ||
398 | * the shaping is not changed. | ||
399 | * | ||
400 | * @return 0 if no problems were detected in the arguments to sim_set_shaping | ||
401 | * or 1 if problems were detected (for example, rate does not fit in 17 bits). | ||
402 | */ | ||
403 | static __inline int | ||
404 | sim_set_shaping(unsigned shim, | ||
405 | unsigned type, | ||
406 | unsigned units, | ||
407 | unsigned rate) | ||
408 | { | ||
409 | if ((rate & ~((1 << SIM_CONTROL_SHAPING_RATE_BITS) - 1)) != 0) | ||
410 | return 1; | ||
411 | |||
412 | __insn_mtspr(SPR_SIM_CONTROL, SIM_SHAPING_SPR_ARG(shim, type, units, rate)); | ||
413 | return 0; | ||
414 | } | ||
415 | |||
416 | #ifdef __tilegx__ | ||
417 | |||
418 | /** Enable a set of mPIPE links. Pass a -1 link_mask to enable all links. */ | ||
419 | static __inline void | ||
420 | sim_enable_mpipe_links(unsigned mpipe, unsigned long link_mask) | ||
421 | { | ||
422 | __insn_mtspr(SPR_SIM_CONTROL, | ||
423 | (SIM_CONTROL_ENABLE_MPIPE_LINK_MAGIC_BYTE | | ||
424 | (mpipe << 8) | (1 << 16) | ((uint_reg_t)link_mask << 32))); | ||
425 | } | ||
426 | |||
427 | /** Disable a set of mPIPE links. Pass a -1 link_mask to disable all links. */ | ||
428 | static __inline void | ||
429 | sim_disable_mpipe_links(unsigned mpipe, unsigned long link_mask) | ||
430 | { | ||
431 | __insn_mtspr(SPR_SIM_CONTROL, | ||
432 | (SIM_CONTROL_ENABLE_MPIPE_LINK_MAGIC_BYTE | | ||
433 | (mpipe << 8) | (0 << 16) | ((uint_reg_t)link_mask << 32))); | ||
434 | } | ||
435 | |||
436 | #endif /* __tilegx__ */ | ||
437 | |||
438 | |||
439 | /* | ||
440 | * An API for changing "functional" mode. | ||
441 | */ | ||
442 | |||
443 | #ifndef __DOXYGEN__ | ||
444 | |||
445 | #define sim_enable_functional() \ | ||
446 | __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_ENABLE_FUNCTIONAL) | ||
447 | |||
448 | #define sim_disable_functional() \ | ||
449 | __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_DISABLE_FUNCTIONAL) | ||
450 | |||
451 | #endif /* __DOXYGEN__ */ | ||
452 | |||
453 | |||
454 | /* | ||
455 | * Profiler support. | ||
456 | */ | ||
457 | |||
458 | /** | ||
459 | * Turn profiling on for the current task. | ||
460 | * | ||
461 | * Note that this has no effect if run in an environment without | ||
462 | * profiling support (thus, the proper flags to the simulator must | ||
463 | * be supplied). | ||
464 | */ | ||
465 | static __inline void | ||
466 | sim_profiler_enable(void) | ||
467 | { | ||
468 | __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PROFILER_ENABLE); | ||
469 | } | ||
470 | |||
471 | |||
472 | /** Turn profiling off for the current task. */ | ||
473 | static __inline void | ||
474 | sim_profiler_disable(void) | ||
475 | { | ||
476 | __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PROFILER_DISABLE); | ||
477 | } | ||
478 | |||
479 | |||
480 | /** | ||
481 | * Turn profiling on or off for the current task. | ||
482 | * | ||
483 | * @param enabled If true, turns on profiling. If false, turns it off. | ||
484 | * | ||
485 | * Note that this has no effect if run in an environment without | ||
486 | * profiling support (thus, the proper flags to the simulator must | ||
487 | * be supplied). | ||
488 | */ | ||
489 | static __inline void | ||
490 | sim_profiler_set_enabled(int enabled) | ||
491 | { | ||
492 | int val = | ||
493 | enabled ? SIM_CONTROL_PROFILER_ENABLE : SIM_CONTROL_PROFILER_DISABLE; | ||
494 | __insn_mtspr(SPR_SIM_CONTROL, val); | ||
495 | } | ||
496 | |||
497 | |||
498 | /** | ||
499 | * Return true if and only if profiling is currently enabled | ||
500 | * for the current task. | ||
501 | * | ||
502 | * This returns false even if sim_profiler_enable() was called | ||
503 | * if the current execution environment does not support profiling. | ||
504 | */ | ||
505 | static __inline int | ||
506 | sim_profiler_is_enabled(void) | ||
507 | { | ||
508 | return ((__insn_mfspr(SPR_SIM_CONTROL) & SIM_PROFILER_ENABLED_MASK) != 0); | ||
509 | } | ||
510 | |||
511 | |||
512 | /** | ||
513 | * Reset profiling counters to zero for the current task. | ||
514 | * | ||
515 | * Resetting can be done while profiling is enabled. It does not affect | ||
516 | * the chip-wide profiling counters. | ||
517 | */ | ||
518 | static __inline void | ||
519 | sim_profiler_clear(void) | ||
520 | { | ||
521 | __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PROFILER_CLEAR); | ||
522 | } | ||
523 | |||
524 | |||
525 | /** | ||
526 | * Enable specified chip-level profiling counters. | ||
527 | * | ||
528 | * Does not affect the per-task profiling counters. | ||
529 | * | ||
530 | * @param mask Either this special value: | ||
531 | * | ||
532 | * SIM_CHIP_ALL (enables all chip-level components). | ||
533 | * | ||
534 | * or the bitwise OR of these values: | ||
535 | * | ||
536 | * SIM_CHIP_MEMCTL (enable all memory controllers) | ||
537 | * SIM_CHIP_XAUI (enable all XAUI controllers) | ||
538 | * SIM_CHIP_MPIPE (enable all MPIPE controllers) | ||
539 | */ | ||
540 | static __inline void | ||
541 | sim_profiler_chip_enable(unsigned int mask) | ||
542 | { | ||
543 | __insn_mtspr(SPR_SIM_CONTROL, SIM_PROFILER_CHIP_ENABLE_SPR_ARG(mask)); | ||
544 | } | ||
545 | |||
546 | |||
547 | /** | ||
548 | * Disable specified chip-level profiling counters. | ||
549 | * | ||
550 | * Does not affect the per-task profiling counters. | ||
551 | * | ||
552 | * @param mask Either this special value: | ||
553 | * | ||
554 | * SIM_CHIP_ALL (disables all chip-level components). | ||
555 | * | ||
556 | * or the bitwise OR of these values: | ||
557 | * | ||
558 | * SIM_CHIP_MEMCTL (disable all memory controllers) | ||
559 | * SIM_CHIP_XAUI (disable all XAUI controllers) | ||
560 | * SIM_CHIP_MPIPE (disable all MPIPE controllers) | ||
561 | */ | ||
562 | static __inline void | ||
563 | sim_profiler_chip_disable(unsigned int mask) | ||
564 | { | ||
565 | __insn_mtspr(SPR_SIM_CONTROL, SIM_PROFILER_CHIP_DISABLE_SPR_ARG(mask)); | ||
566 | } | ||
567 | |||
568 | |||
569 | /** | ||
570 | * Reset specified chip-level profiling counters to zero. | ||
571 | * | ||
572 | * Does not affect the per-task profiling counters. | ||
573 | * | ||
574 | * @param mask Either this special value: | ||
575 | * | ||
576 | * SIM_CHIP_ALL (clears all chip-level components). | ||
577 | * | ||
578 | * or the bitwise OR of these values: | ||
579 | * | ||
580 | * SIM_CHIP_MEMCTL (clear all memory controllers) | ||
581 | * SIM_CHIP_XAUI (clear all XAUI controllers) | ||
582 | * SIM_CHIP_MPIPE (clear all MPIPE controllers) | ||
583 | */ | ||
584 | static __inline void | ||
585 | sim_profiler_chip_clear(unsigned int mask) | ||
586 | { | ||
587 | __insn_mtspr(SPR_SIM_CONTROL, SIM_PROFILER_CHIP_CLEAR_SPR_ARG(mask)); | ||
588 | } | ||
589 | |||
590 | |||
591 | /* | ||
592 | * Event support. | ||
593 | */ | ||
594 | |||
595 | #ifndef __DOXYGEN__ | ||
596 | |||
597 | static __inline void | ||
598 | sim_event_begin(unsigned int x) | ||
599 | { | ||
600 | #if defined(__tile__) && !defined(__NO_EVENT_SPR__) | ||
601 | __insn_mtspr(SPR_EVENT_BEGIN, x); | ||
602 | #endif | ||
603 | } | ||
604 | |||
605 | static __inline void | ||
606 | sim_event_end(unsigned int x) | ||
607 | { | ||
608 | #if defined(__tile__) && !defined(__NO_EVENT_SPR__) | ||
609 | __insn_mtspr(SPR_EVENT_END, x); | ||
610 | #endif | ||
611 | } | ||
612 | |||
613 | #endif /* !__DOXYGEN__ */ | ||
614 | |||
615 | #endif /* !__ASSEMBLER__ */ | ||
616 | |||
617 | #endif /* !__ARCH_SIM_H__ */ | ||
618 | |||
619 | /** @} */ | ||
diff --git a/arch/tile/include/asm/system.h b/arch/tile/include/asm/system.h index 96779c805902..fb7ff9574d76 100644 --- a/arch/tile/include/asm/system.h +++ b/arch/tile/include/asm/system.h | |||
@@ -217,13 +217,6 @@ int hardwall_deactivate(struct task_struct *task); | |||
217 | } while (0) | 217 | } while (0) |
218 | #endif | 218 | #endif |
219 | 219 | ||
220 | /* Invoke the simulator "syscall" mechanism (see arch/tile/kernel/entry.S). */ | ||
221 | extern int _sim_syscall(int syscall_num, ...); | ||
222 | #define sim_syscall(syscall_num, ...) \ | ||
223 | _sim_syscall(SIM_CONTROL_SYSCALL + \ | ||
224 | ((syscall_num) << _SIM_CONTROL_OPERATOR_BITS), \ | ||
225 | ## __VA_ARGS__) | ||
226 | |||
227 | /* | 220 | /* |
228 | * Kernel threads can check to see if they need to migrate their | 221 | * Kernel threads can check to see if they need to migrate their |
229 | * stack whenever they return from a context switch; for user | 222 | * stack whenever they return from a context switch; for user |
diff --git a/arch/tile/kernel/entry.S b/arch/tile/kernel/entry.S index 3d01383b1b0e..80d13f013bb2 100644 --- a/arch/tile/kernel/entry.S +++ b/arch/tile/kernel/entry.S | |||
@@ -25,28 +25,6 @@ STD_ENTRY(current_text_addr) | |||
25 | { move r0, lr; jrp lr } | 25 | { move r0, lr; jrp lr } |
26 | STD_ENDPROC(current_text_addr) | 26 | STD_ENDPROC(current_text_addr) |
27 | 27 | ||
28 | STD_ENTRY(_sim_syscall) | ||
29 | /* | ||
30 | * Wait for r0-r9 to be ready (and lr on the off chance we | ||
31 | * want the syscall to locate its caller), then make a magic | ||
32 | * simulator syscall. | ||
33 | * | ||
34 | * We carefully stall until the registers are readable in case they | ||
35 | * are the target of a slow load, etc. so that tile-sim will | ||
36 | * definitely be able to read all of them inside the magic syscall. | ||
37 | * | ||
38 | * Technically this is wrong for r3-r9 and lr, since an interrupt | ||
39 | * could come in and restore the registers with a slow load right | ||
40 | * before executing the mtspr. We may need to modify tile-sim to | ||
41 | * explicitly stall for this case, but we do not yet have | ||
42 | * a way to implement such a stall. | ||
43 | */ | ||
44 | { and zero, lr, r9 ; and zero, r8, r7 } | ||
45 | { and zero, r6, r5 ; and zero, r4, r3 } | ||
46 | { and zero, r2, r1 ; mtspr SIM_CONTROL, r0 } | ||
47 | { jrp lr } | ||
48 | STD_ENDPROC(_sim_syscall) | ||
49 | |||
50 | /* | 28 | /* |
51 | * Implement execve(). The i386 code has a note that forking from kernel | 29 | * Implement execve(). The i386 code has a note that forking from kernel |
52 | * space results in no copy on write until the execve, so we should be | 30 | * space results in no copy on write until the execve, so we should be |
diff --git a/arch/tile/mm/homecache.c b/arch/tile/mm/homecache.c index fb3b4a55cec4..d78df3a6ee15 100644 --- a/arch/tile/mm/homecache.c +++ b/arch/tile/mm/homecache.c | |||
@@ -37,6 +37,8 @@ | |||
37 | #include <asm/pgalloc.h> | 37 | #include <asm/pgalloc.h> |
38 | #include <asm/homecache.h> | 38 | #include <asm/homecache.h> |
39 | 39 | ||
40 | #include <arch/sim.h> | ||
41 | |||
40 | #include "migrate.h" | 42 | #include "migrate.h" |
41 | 43 | ||
42 | 44 | ||
@@ -217,13 +219,6 @@ static unsigned long cache_flush_length(unsigned long length) | |||
217 | return (length >= CHIP_L2_CACHE_SIZE()) ? HV_FLUSH_EVICT_L2 : length; | 219 | return (length >= CHIP_L2_CACHE_SIZE()) ? HV_FLUSH_EVICT_L2 : length; |
218 | } | 220 | } |
219 | 221 | ||
220 | /* On the simulator, confirm lines have been evicted everywhere. */ | ||
221 | static void validate_lines_evicted(unsigned long pfn, size_t length) | ||
222 | { | ||
223 | sim_syscall(SIM_SYSCALL_VALIDATE_LINES_EVICTED, | ||
224 | (HV_PhysAddr)pfn << PAGE_SHIFT, length); | ||
225 | } | ||
226 | |||
227 | /* Flush a page out of whatever cache(s) it is in. */ | 222 | /* Flush a page out of whatever cache(s) it is in. */ |
228 | void homecache_flush_cache(struct page *page, int order) | 223 | void homecache_flush_cache(struct page *page, int order) |
229 | { | 224 | { |
@@ -234,7 +229,7 @@ void homecache_flush_cache(struct page *page, int order) | |||
234 | 229 | ||
235 | homecache_mask(page, pages, &home_mask); | 230 | homecache_mask(page, pages, &home_mask); |
236 | flush_remote(pfn, length, &home_mask, 0, 0, 0, NULL, NULL, 0); | 231 | flush_remote(pfn, length, &home_mask, 0, 0, 0, NULL, NULL, 0); |
237 | validate_lines_evicted(pfn, pages * PAGE_SIZE); | 232 | sim_validate_lines_evicted(PFN_PHYS(pfn), pages * PAGE_SIZE); |
238 | } | 233 | } |
239 | 234 | ||
240 | 235 | ||