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 | |
| 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>
| -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 | ||
