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>
This commit is contained in:
parent
4fe938c513
commit
bf65e440e8
|
@ -0,0 +1,619 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2010 Tilera Corporation. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation, version 2.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
||||||
|
* NON INFRINGEMENT. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* Provides an API for controlling the simulator at runtime.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup arch_sim
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* An API for controlling the simulator at runtime.
|
||||||
|
*
|
||||||
|
* The simulator's behavior can be modified while it is running.
|
||||||
|
* For example, human-readable trace output can be enabled and disabled
|
||||||
|
* around code of interest.
|
||||||
|
*
|
||||||
|
* There are two ways to modify simulator behavior:
|
||||||
|
* programmatically, by calling various sim_* functions, and
|
||||||
|
* interactively, by entering commands like "sim set functional true"
|
||||||
|
* at the tile-monitor prompt. Typing "sim help" at that prompt provides
|
||||||
|
* a list of interactive commands.
|
||||||
|
*
|
||||||
|
* All interactive commands can also be executed programmatically by
|
||||||
|
* passing a string to the sim_command function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ARCH_SIM_H__
|
||||||
|
#define __ARCH_SIM_H__
|
||||||
|
|
||||||
|
#include <arch/sim_def.h>
|
||||||
|
#include <arch/abi.h>
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLER__
|
||||||
|
|
||||||
|
#include <arch/spr_def.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the current program is running under a simulator,
|
||||||
|
* rather than on real hardware. If running on hardware, other "sim_xxx()"
|
||||||
|
* calls have no useful effect.
|
||||||
|
*/
|
||||||
|
static inline int
|
||||||
|
sim_is_simulator(void)
|
||||||
|
{
|
||||||
|
return __insn_mfspr(SPR_SIM_CONTROL) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checkpoint the simulator state to a checkpoint file.
|
||||||
|
*
|
||||||
|
* The checkpoint file name is either the default or the name specified
|
||||||
|
* on the command line with "--checkpoint-file".
|
||||||
|
*/
|
||||||
|
static __inline void
|
||||||
|
sim_checkpoint(void)
|
||||||
|
{
|
||||||
|
__insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_CHECKPOINT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report whether or not various kinds of simulator tracing are enabled.
|
||||||
|
*
|
||||||
|
* @return The bitwise OR of these values:
|
||||||
|
*
|
||||||
|
* SIM_TRACE_CYCLES (--trace-cycles),
|
||||||
|
* SIM_TRACE_ROUTER (--trace-router),
|
||||||
|
* SIM_TRACE_REGISTER_WRITES (--trace-register-writes),
|
||||||
|
* SIM_TRACE_DISASM (--trace-disasm),
|
||||||
|
* SIM_TRACE_STALL_INFO (--trace-stall-info)
|
||||||
|
* SIM_TRACE_MEMORY_CONTROLLER (--trace-memory-controller)
|
||||||
|
* SIM_TRACE_L2_CACHE (--trace-l2)
|
||||||
|
* SIM_TRACE_LINES (--trace-lines)
|
||||||
|
*/
|
||||||
|
static __inline unsigned int
|
||||||
|
sim_get_tracing(void)
|
||||||
|
{
|
||||||
|
return __insn_mfspr(SPR_SIM_CONTROL) & SIM_TRACE_FLAG_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turn on or off different kinds of simulator tracing.
|
||||||
|
*
|
||||||
|
* @param mask Either one of these special values:
|
||||||
|
*
|
||||||
|
* SIM_TRACE_NONE (turns off tracing),
|
||||||
|
* SIM_TRACE_ALL (turns on all possible tracing).
|
||||||
|
*
|
||||||
|
* or the bitwise OR of these values:
|
||||||
|
*
|
||||||
|
* SIM_TRACE_CYCLES (--trace-cycles),
|
||||||
|
* SIM_TRACE_ROUTER (--trace-router),
|
||||||
|
* SIM_TRACE_REGISTER_WRITES (--trace-register-writes),
|
||||||
|
* SIM_TRACE_DISASM (--trace-disasm),
|
||||||
|
* SIM_TRACE_STALL_INFO (--trace-stall-info)
|
||||||
|
* SIM_TRACE_MEMORY_CONTROLLER (--trace-memory-controller)
|
||||||
|
* SIM_TRACE_L2_CACHE (--trace-l2)
|
||||||
|
* SIM_TRACE_LINES (--trace-lines)
|
||||||
|
*/
|
||||||
|
static __inline void
|
||||||
|
sim_set_tracing(unsigned int mask)
|
||||||
|
{
|
||||||
|
__insn_mtspr(SPR_SIM_CONTROL, SIM_TRACE_SPR_ARG(mask));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request dumping of different kinds of simulator state.
|
||||||
|
*
|
||||||
|
* @param mask Either this special value:
|
||||||
|
*
|
||||||
|
* SIM_DUMP_ALL (dump all known state)
|
||||||
|
*
|
||||||
|
* or the bitwise OR of these values:
|
||||||
|
*
|
||||||
|
* SIM_DUMP_REGS (the register file),
|
||||||
|
* SIM_DUMP_SPRS (the SPRs),
|
||||||
|
* SIM_DUMP_ITLB (the iTLB),
|
||||||
|
* SIM_DUMP_DTLB (the dTLB),
|
||||||
|
* SIM_DUMP_L1I (the L1 I-cache),
|
||||||
|
* SIM_DUMP_L1D (the L1 D-cache),
|
||||||
|
* SIM_DUMP_L2 (the L2 cache),
|
||||||
|
* SIM_DUMP_SNREGS (the switch register file),
|
||||||
|
* SIM_DUMP_SNITLB (the switch iTLB),
|
||||||
|
* SIM_DUMP_SNL1I (the switch L1 I-cache),
|
||||||
|
* SIM_DUMP_BACKTRACE (the current backtrace)
|
||||||
|
*/
|
||||||
|
static __inline void
|
||||||
|
sim_dump(unsigned int mask)
|
||||||
|
{
|
||||||
|
__insn_mtspr(SPR_SIM_CONTROL, SIM_DUMP_SPR_ARG(mask));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print a string to the simulator stdout.
|
||||||
|
*
|
||||||
|
* @param str The string to be written; a newline is automatically added.
|
||||||
|
*/
|
||||||
|
static __inline void
|
||||||
|
sim_print_string(const char* str)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; str[i] != 0; i++)
|
||||||
|
{
|
||||||
|
__insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PUTC |
|
||||||
|
(str[i] << _SIM_CONTROL_OPERATOR_BITS));
|
||||||
|
}
|
||||||
|
__insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PUTC |
|
||||||
|
(SIM_PUTC_FLUSH_STRING << _SIM_CONTROL_OPERATOR_BITS));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute a simulator command string.
|
||||||
|
*
|
||||||
|
* Type 'sim help' at the tile-monitor prompt to learn what commands
|
||||||
|
* are available. Note the use of the tile-monitor "sim" command to
|
||||||
|
* pass commands to the simulator.
|
||||||
|
*
|
||||||
|
* The argument to sim_command() does not include the leading "sim"
|
||||||
|
* prefix used at the tile-monitor prompt; for example, you might call
|
||||||
|
* sim_command("trace disasm").
|
||||||
|
*/
|
||||||
|
static __inline void
|
||||||
|
sim_command(const char* str)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
c = *str++;
|
||||||
|
__insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_COMMAND |
|
||||||
|
(c << _SIM_CONTROL_OPERATOR_BITS));
|
||||||
|
}
|
||||||
|
while (c);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __DOXYGEN__
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The underlying implementation of "_sim_syscall()".
|
||||||
|
*
|
||||||
|
* We use extra "and" instructions to ensure that all the values
|
||||||
|
* we are passing to the simulator are actually valid in the registers
|
||||||
|
* (i.e. returned from memory) prior to the SIM_CONTROL spr.
|
||||||
|
*/
|
||||||
|
static __inline int _sim_syscall0(int val)
|
||||||
|
{
|
||||||
|
long result;
|
||||||
|
__asm__ __volatile__ ("mtspr SIM_CONTROL, r0"
|
||||||
|
: "=R00" (result) : "R00" (val));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline int _sim_syscall1(int val, long arg1)
|
||||||
|
{
|
||||||
|
long result;
|
||||||
|
__asm__ __volatile__ ("{ and zero, r1, r1; mtspr SIM_CONTROL, r0 }"
|
||||||
|
: "=R00" (result) : "R00" (val), "R01" (arg1));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline int _sim_syscall2(int val, long arg1, long arg2)
|
||||||
|
{
|
||||||
|
long result;
|
||||||
|
__asm__ __volatile__ ("{ and zero, r1, r2; mtspr SIM_CONTROL, r0 }"
|
||||||
|
: "=R00" (result)
|
||||||
|
: "R00" (val), "R01" (arg1), "R02" (arg2));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note that _sim_syscall3() and higher are technically at risk of
|
||||||
|
receiving an interrupt right before the mtspr bundle, in which case
|
||||||
|
the register values for arguments 3 and up may still be in flight
|
||||||
|
to the core from a stack frame reload. */
|
||||||
|
|
||||||
|
static __inline int _sim_syscall3(int val, long arg1, long arg2, long arg3)
|
||||||
|
{
|
||||||
|
long result;
|
||||||
|
__asm__ __volatile__ ("{ and zero, r3, r3 };"
|
||||||
|
"{ and zero, r1, r2; mtspr SIM_CONTROL, r0 }"
|
||||||
|
: "=R00" (result)
|
||||||
|
: "R00" (val), "R01" (arg1), "R02" (arg2),
|
||||||
|
"R03" (arg3));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline int _sim_syscall4(int val, long arg1, long arg2, long arg3,
|
||||||
|
long arg4)
|
||||||
|
{
|
||||||
|
long result;
|
||||||
|
__asm__ __volatile__ ("{ and zero, r3, r4 };"
|
||||||
|
"{ and zero, r1, r2; mtspr SIM_CONTROL, r0 }"
|
||||||
|
: "=R00" (result)
|
||||||
|
: "R00" (val), "R01" (arg1), "R02" (arg2),
|
||||||
|
"R03" (arg3), "R04" (arg4));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline int _sim_syscall5(int val, long arg1, long arg2, long arg3,
|
||||||
|
long arg4, long arg5)
|
||||||
|
{
|
||||||
|
long result;
|
||||||
|
__asm__ __volatile__ ("{ and zero, r3, r4; and zero, r5, r5 };"
|
||||||
|
"{ and zero, r1, r2; mtspr SIM_CONTROL, r0 }"
|
||||||
|
: "=R00" (result)
|
||||||
|
: "R00" (val), "R01" (arg1), "R02" (arg2),
|
||||||
|
"R03" (arg3), "R04" (arg4), "R05" (arg5));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a special syscall to the simulator itself, if running under
|
||||||
|
* simulation. This is used as the implementation of other functions
|
||||||
|
* and should not be used outside this file.
|
||||||
|
*
|
||||||
|
* @param syscall_num The simulator syscall number.
|
||||||
|
* @param nr The number of additional arguments provided.
|
||||||
|
*
|
||||||
|
* @return Varies by syscall.
|
||||||
|
*/
|
||||||
|
#define _sim_syscall(syscall_num, nr, args...) \
|
||||||
|
_sim_syscall##nr( \
|
||||||
|
((syscall_num) << _SIM_CONTROL_OPERATOR_BITS) | SIM_CONTROL_SYSCALL, args)
|
||||||
|
|
||||||
|
|
||||||
|
/* Values for the "access_mask" parameters below. */
|
||||||
|
#define SIM_WATCHPOINT_READ 1
|
||||||
|
#define SIM_WATCHPOINT_WRITE 2
|
||||||
|
#define SIM_WATCHPOINT_EXECUTE 4
|
||||||
|
|
||||||
|
|
||||||
|
static __inline int
|
||||||
|
sim_add_watchpoint(unsigned int process_id,
|
||||||
|
unsigned long address,
|
||||||
|
unsigned long size,
|
||||||
|
unsigned int access_mask,
|
||||||
|
unsigned long user_data)
|
||||||
|
{
|
||||||
|
return _sim_syscall(SIM_SYSCALL_ADD_WATCHPOINT, 5, process_id,
|
||||||
|
address, size, access_mask, user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static __inline int
|
||||||
|
sim_remove_watchpoint(unsigned int process_id,
|
||||||
|
unsigned long address,
|
||||||
|
unsigned long size,
|
||||||
|
unsigned int access_mask,
|
||||||
|
unsigned long user_data)
|
||||||
|
{
|
||||||
|
return _sim_syscall(SIM_SYSCALL_REMOVE_WATCHPOINT, 5, process_id,
|
||||||
|
address, size, access_mask, user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return value from sim_query_watchpoint.
|
||||||
|
*/
|
||||||
|
struct SimQueryWatchpointStatus
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 0 if a watchpoint fired, 1 if no watchpoint fired, or -1 for
|
||||||
|
* error (meaning a bad process_id).
|
||||||
|
*/
|
||||||
|
int syscall_status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The address of the watchpoint that fired (this is the address
|
||||||
|
* passed to sim_add_watchpoint, not an address within that range
|
||||||
|
* that actually triggered the watchpoint).
|
||||||
|
*/
|
||||||
|
unsigned long address;
|
||||||
|
|
||||||
|
/** The arbitrary user_data installed by sim_add_watchpoint. */
|
||||||
|
unsigned long user_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static __inline struct SimQueryWatchpointStatus
|
||||||
|
sim_query_watchpoint(unsigned int process_id)
|
||||||
|
{
|
||||||
|
struct SimQueryWatchpointStatus status;
|
||||||
|
long val = SIM_CONTROL_SYSCALL |
|
||||||
|
(SIM_SYSCALL_QUERY_WATCHPOINT << _SIM_CONTROL_OPERATOR_BITS);
|
||||||
|
__asm__ __volatile__ ("{ and zero, r1, r1; mtspr SIM_CONTROL, r0 }"
|
||||||
|
: "=R00" (status.syscall_status),
|
||||||
|
"=R01" (status.address),
|
||||||
|
"=R02" (status.user_data)
|
||||||
|
: "R00" (val), "R01" (process_id));
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* On the simulator, confirm lines have been evicted everywhere. */
|
||||||
|
static __inline void
|
||||||
|
sim_validate_lines_evicted(unsigned long long pa, unsigned long length)
|
||||||
|
{
|
||||||
|
#ifdef __LP64__
|
||||||
|
_sim_syscall(SIM_SYSCALL_VALIDATE_LINES_EVICTED, 2, pa, length);
|
||||||
|
#else
|
||||||
|
_sim_syscall(SIM_SYSCALL_VALIDATE_LINES_EVICTED, 4,
|
||||||
|
0 /* dummy */, (long)(pa), (long)(pa >> 32), length);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* !__DOXYGEN__ */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modify the shaping parameters of a shim.
|
||||||
|
*
|
||||||
|
* @param shim The shim to modify. One of:
|
||||||
|
* SIM_CONTROL_SHAPING_GBE_0
|
||||||
|
* SIM_CONTROL_SHAPING_GBE_1
|
||||||
|
* SIM_CONTROL_SHAPING_GBE_2
|
||||||
|
* SIM_CONTROL_SHAPING_GBE_3
|
||||||
|
* SIM_CONTROL_SHAPING_XGBE_0
|
||||||
|
* SIM_CONTROL_SHAPING_XGBE_1
|
||||||
|
*
|
||||||
|
* @param type The type of shaping. This should be the same type of
|
||||||
|
* shaping that is already in place on the shim. One of:
|
||||||
|
* SIM_CONTROL_SHAPING_MULTIPLIER
|
||||||
|
* SIM_CONTROL_SHAPING_PPS
|
||||||
|
* SIM_CONTROL_SHAPING_BPS
|
||||||
|
*
|
||||||
|
* @param units The magnitude of the rate. One of:
|
||||||
|
* SIM_CONTROL_SHAPING_UNITS_SINGLE
|
||||||
|
* SIM_CONTROL_SHAPING_UNITS_KILO
|
||||||
|
* SIM_CONTROL_SHAPING_UNITS_MEGA
|
||||||
|
* SIM_CONTROL_SHAPING_UNITS_GIGA
|
||||||
|
*
|
||||||
|
* @param rate The rate to which to change it. This must fit in
|
||||||
|
* SIM_CONTROL_SHAPING_RATE_BITS bits or a warning is issued and
|
||||||
|
* the shaping is not changed.
|
||||||
|
*
|
||||||
|
* @return 0 if no problems were detected in the arguments to sim_set_shaping
|
||||||
|
* or 1 if problems were detected (for example, rate does not fit in 17 bits).
|
||||||
|
*/
|
||||||
|
static __inline int
|
||||||
|
sim_set_shaping(unsigned shim,
|
||||||
|
unsigned type,
|
||||||
|
unsigned units,
|
||||||
|
unsigned rate)
|
||||||
|
{
|
||||||
|
if ((rate & ~((1 << SIM_CONTROL_SHAPING_RATE_BITS) - 1)) != 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
__insn_mtspr(SPR_SIM_CONTROL, SIM_SHAPING_SPR_ARG(shim, type, units, rate));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __tilegx__
|
||||||
|
|
||||||
|
/** Enable a set of mPIPE links. Pass a -1 link_mask to enable all links. */
|
||||||
|
static __inline void
|
||||||
|
sim_enable_mpipe_links(unsigned mpipe, unsigned long link_mask)
|
||||||
|
{
|
||||||
|
__insn_mtspr(SPR_SIM_CONTROL,
|
||||||
|
(SIM_CONTROL_ENABLE_MPIPE_LINK_MAGIC_BYTE |
|
||||||
|
(mpipe << 8) | (1 << 16) | ((uint_reg_t)link_mask << 32)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Disable a set of mPIPE links. Pass a -1 link_mask to disable all links. */
|
||||||
|
static __inline void
|
||||||
|
sim_disable_mpipe_links(unsigned mpipe, unsigned long link_mask)
|
||||||
|
{
|
||||||
|
__insn_mtspr(SPR_SIM_CONTROL,
|
||||||
|
(SIM_CONTROL_ENABLE_MPIPE_LINK_MAGIC_BYTE |
|
||||||
|
(mpipe << 8) | (0 << 16) | ((uint_reg_t)link_mask << 32)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __tilegx__ */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* An API for changing "functional" mode.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __DOXYGEN__
|
||||||
|
|
||||||
|
#define sim_enable_functional() \
|
||||||
|
__insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_ENABLE_FUNCTIONAL)
|
||||||
|
|
||||||
|
#define sim_disable_functional() \
|
||||||
|
__insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_DISABLE_FUNCTIONAL)
|
||||||
|
|
||||||
|
#endif /* __DOXYGEN__ */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Profiler support.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turn profiling on for the current task.
|
||||||
|
*
|
||||||
|
* Note that this has no effect if run in an environment without
|
||||||
|
* profiling support (thus, the proper flags to the simulator must
|
||||||
|
* be supplied).
|
||||||
|
*/
|
||||||
|
static __inline void
|
||||||
|
sim_profiler_enable(void)
|
||||||
|
{
|
||||||
|
__insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PROFILER_ENABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Turn profiling off for the current task. */
|
||||||
|
static __inline void
|
||||||
|
sim_profiler_disable(void)
|
||||||
|
{
|
||||||
|
__insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PROFILER_DISABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turn profiling on or off for the current task.
|
||||||
|
*
|
||||||
|
* @param enabled If true, turns on profiling. If false, turns it off.
|
||||||
|
*
|
||||||
|
* Note that this has no effect if run in an environment without
|
||||||
|
* profiling support (thus, the proper flags to the simulator must
|
||||||
|
* be supplied).
|
||||||
|
*/
|
||||||
|
static __inline void
|
||||||
|
sim_profiler_set_enabled(int enabled)
|
||||||
|
{
|
||||||
|
int val =
|
||||||
|
enabled ? SIM_CONTROL_PROFILER_ENABLE : SIM_CONTROL_PROFILER_DISABLE;
|
||||||
|
__insn_mtspr(SPR_SIM_CONTROL, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if and only if profiling is currently enabled
|
||||||
|
* for the current task.
|
||||||
|
*
|
||||||
|
* This returns false even if sim_profiler_enable() was called
|
||||||
|
* if the current execution environment does not support profiling.
|
||||||
|
*/
|
||||||
|
static __inline int
|
||||||
|
sim_profiler_is_enabled(void)
|
||||||
|
{
|
||||||
|
return ((__insn_mfspr(SPR_SIM_CONTROL) & SIM_PROFILER_ENABLED_MASK) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset profiling counters to zero for the current task.
|
||||||
|
*
|
||||||
|
* Resetting can be done while profiling is enabled. It does not affect
|
||||||
|
* the chip-wide profiling counters.
|
||||||
|
*/
|
||||||
|
static __inline void
|
||||||
|
sim_profiler_clear(void)
|
||||||
|
{
|
||||||
|
__insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PROFILER_CLEAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable specified chip-level profiling counters.
|
||||||
|
*
|
||||||
|
* Does not affect the per-task profiling counters.
|
||||||
|
*
|
||||||
|
* @param mask Either this special value:
|
||||||
|
*
|
||||||
|
* SIM_CHIP_ALL (enables all chip-level components).
|
||||||
|
*
|
||||||
|
* or the bitwise OR of these values:
|
||||||
|
*
|
||||||
|
* SIM_CHIP_MEMCTL (enable all memory controllers)
|
||||||
|
* SIM_CHIP_XAUI (enable all XAUI controllers)
|
||||||
|
* SIM_CHIP_MPIPE (enable all MPIPE controllers)
|
||||||
|
*/
|
||||||
|
static __inline void
|
||||||
|
sim_profiler_chip_enable(unsigned int mask)
|
||||||
|
{
|
||||||
|
__insn_mtspr(SPR_SIM_CONTROL, SIM_PROFILER_CHIP_ENABLE_SPR_ARG(mask));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable specified chip-level profiling counters.
|
||||||
|
*
|
||||||
|
* Does not affect the per-task profiling counters.
|
||||||
|
*
|
||||||
|
* @param mask Either this special value:
|
||||||
|
*
|
||||||
|
* SIM_CHIP_ALL (disables all chip-level components).
|
||||||
|
*
|
||||||
|
* or the bitwise OR of these values:
|
||||||
|
*
|
||||||
|
* SIM_CHIP_MEMCTL (disable all memory controllers)
|
||||||
|
* SIM_CHIP_XAUI (disable all XAUI controllers)
|
||||||
|
* SIM_CHIP_MPIPE (disable all MPIPE controllers)
|
||||||
|
*/
|
||||||
|
static __inline void
|
||||||
|
sim_profiler_chip_disable(unsigned int mask)
|
||||||
|
{
|
||||||
|
__insn_mtspr(SPR_SIM_CONTROL, SIM_PROFILER_CHIP_DISABLE_SPR_ARG(mask));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset specified chip-level profiling counters to zero.
|
||||||
|
*
|
||||||
|
* Does not affect the per-task profiling counters.
|
||||||
|
*
|
||||||
|
* @param mask Either this special value:
|
||||||
|
*
|
||||||
|
* SIM_CHIP_ALL (clears all chip-level components).
|
||||||
|
*
|
||||||
|
* or the bitwise OR of these values:
|
||||||
|
*
|
||||||
|
* SIM_CHIP_MEMCTL (clear all memory controllers)
|
||||||
|
* SIM_CHIP_XAUI (clear all XAUI controllers)
|
||||||
|
* SIM_CHIP_MPIPE (clear all MPIPE controllers)
|
||||||
|
*/
|
||||||
|
static __inline void
|
||||||
|
sim_profiler_chip_clear(unsigned int mask)
|
||||||
|
{
|
||||||
|
__insn_mtspr(SPR_SIM_CONTROL, SIM_PROFILER_CHIP_CLEAR_SPR_ARG(mask));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Event support.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __DOXYGEN__
|
||||||
|
|
||||||
|
static __inline void
|
||||||
|
sim_event_begin(unsigned int x)
|
||||||
|
{
|
||||||
|
#if defined(__tile__) && !defined(__NO_EVENT_SPR__)
|
||||||
|
__insn_mtspr(SPR_EVENT_BEGIN, x);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline void
|
||||||
|
sim_event_end(unsigned int x)
|
||||||
|
{
|
||||||
|
#if defined(__tile__) && !defined(__NO_EVENT_SPR__)
|
||||||
|
__insn_mtspr(SPR_EVENT_END, x);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !__DOXYGEN__ */
|
||||||
|
|
||||||
|
#endif /* !__ASSEMBLER__ */
|
||||||
|
|
||||||
|
#endif /* !__ARCH_SIM_H__ */
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -217,13 +217,6 @@ int hardwall_deactivate(struct task_struct *task);
|
||||||
} while (0)
|
} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Invoke the simulator "syscall" mechanism (see arch/tile/kernel/entry.S). */
|
|
||||||
extern int _sim_syscall(int syscall_num, ...);
|
|
||||||
#define sim_syscall(syscall_num, ...) \
|
|
||||||
_sim_syscall(SIM_CONTROL_SYSCALL + \
|
|
||||||
((syscall_num) << _SIM_CONTROL_OPERATOR_BITS), \
|
|
||||||
## __VA_ARGS__)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Kernel threads can check to see if they need to migrate their
|
* Kernel threads can check to see if they need to migrate their
|
||||||
* stack whenever they return from a context switch; for user
|
* stack whenever they return from a context switch; for user
|
||||||
|
|
|
@ -25,28 +25,6 @@ STD_ENTRY(current_text_addr)
|
||||||
{ move r0, lr; jrp lr }
|
{ move r0, lr; jrp lr }
|
||||||
STD_ENDPROC(current_text_addr)
|
STD_ENDPROC(current_text_addr)
|
||||||
|
|
||||||
STD_ENTRY(_sim_syscall)
|
|
||||||
/*
|
|
||||||
* Wait for r0-r9 to be ready (and lr on the off chance we
|
|
||||||
* want the syscall to locate its caller), then make a magic
|
|
||||||
* simulator syscall.
|
|
||||||
*
|
|
||||||
* We carefully stall until the registers are readable in case they
|
|
||||||
* are the target of a slow load, etc. so that tile-sim will
|
|
||||||
* definitely be able to read all of them inside the magic syscall.
|
|
||||||
*
|
|
||||||
* Technically this is wrong for r3-r9 and lr, since an interrupt
|
|
||||||
* could come in and restore the registers with a slow load right
|
|
||||||
* before executing the mtspr. We may need to modify tile-sim to
|
|
||||||
* explicitly stall for this case, but we do not yet have
|
|
||||||
* a way to implement such a stall.
|
|
||||||
*/
|
|
||||||
{ and zero, lr, r9 ; and zero, r8, r7 }
|
|
||||||
{ and zero, r6, r5 ; and zero, r4, r3 }
|
|
||||||
{ and zero, r2, r1 ; mtspr SIM_CONTROL, r0 }
|
|
||||||
{ jrp lr }
|
|
||||||
STD_ENDPROC(_sim_syscall)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Implement execve(). The i386 code has a note that forking from kernel
|
* Implement execve(). The i386 code has a note that forking from kernel
|
||||||
* space results in no copy on write until the execve, so we should be
|
* space results in no copy on write until the execve, so we should be
|
||||||
|
|
|
@ -37,6 +37,8 @@
|
||||||
#include <asm/pgalloc.h>
|
#include <asm/pgalloc.h>
|
||||||
#include <asm/homecache.h>
|
#include <asm/homecache.h>
|
||||||
|
|
||||||
|
#include <arch/sim.h>
|
||||||
|
|
||||||
#include "migrate.h"
|
#include "migrate.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -217,13 +219,6 @@ static unsigned long cache_flush_length(unsigned long length)
|
||||||
return (length >= CHIP_L2_CACHE_SIZE()) ? HV_FLUSH_EVICT_L2 : length;
|
return (length >= CHIP_L2_CACHE_SIZE()) ? HV_FLUSH_EVICT_L2 : length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* On the simulator, confirm lines have been evicted everywhere. */
|
|
||||||
static void validate_lines_evicted(unsigned long pfn, size_t length)
|
|
||||||
{
|
|
||||||
sim_syscall(SIM_SYSCALL_VALIDATE_LINES_EVICTED,
|
|
||||||
(HV_PhysAddr)pfn << PAGE_SHIFT, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Flush a page out of whatever cache(s) it is in. */
|
/* Flush a page out of whatever cache(s) it is in. */
|
||||||
void homecache_flush_cache(struct page *page, int order)
|
void homecache_flush_cache(struct page *page, int order)
|
||||||
{
|
{
|
||||||
|
@ -234,7 +229,7 @@ void homecache_flush_cache(struct page *page, int order)
|
||||||
|
|
||||||
homecache_mask(page, pages, &home_mask);
|
homecache_mask(page, pages, &home_mask);
|
||||||
flush_remote(pfn, length, &home_mask, 0, 0, 0, NULL, NULL, 0);
|
flush_remote(pfn, length, &home_mask, 0, 0, 0, NULL, NULL, 0);
|
||||||
validate_lines_evicted(pfn, pages * PAGE_SIZE);
|
sim_validate_lines_evicted(PFN_PHYS(pfn), pages * PAGE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue