Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
[pandora-kernel.git] / arch / tile / include / arch / sim.h
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 /** @} */