forked from Minki/linux
e4b8b3f33f
Allow user-space threads to use runtime instrumentation (RI). To enable RI for a thread there is a new s390 specific system call, sys_s390_runtime_instr, that takes as parameter a realtime signal number. If the RI facility is available the system call sets up a control block for the calling thread with the appropriate permissions for the thread to modify the control block. The user-space thread can then use the store and modify RI instructions to alter the control block and start/stop the instrumentation via RION/RIOFF. If the user specified program buffer runs full RI triggers an external interrupt. The external interrupt is translated to a real-time signal that is delivered to the thread that enabled RI on that CPU. The number of the real-time signal is the number specified in the RI system call. So, user-space can select any available real-time signal number in case the application itself uses real-time signals for other purposes. The kernel saves the RI control blocks on task switch only if the running thread was enabled for RI. Therefore, the performance impact on task switch should be negligible if RI is not used. RI is only enabled for user-space mode and is disabled for the supervisor state. Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Jan Glauber <jang@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
99 lines
2.0 KiB
C
99 lines
2.0 KiB
C
#ifndef _RUNTIME_INSTR_H
|
|
#define _RUNTIME_INSTR_H
|
|
|
|
#define S390_RUNTIME_INSTR_START 0x1
|
|
#define S390_RUNTIME_INSTR_STOP 0x2
|
|
|
|
struct runtime_instr_cb {
|
|
__u64 buf_current;
|
|
__u64 buf_origin;
|
|
__u64 buf_limit;
|
|
|
|
__u32 valid : 1;
|
|
__u32 pstate : 1;
|
|
__u32 pstate_set_buf : 1;
|
|
__u32 home_space : 1;
|
|
__u32 altered : 1;
|
|
__u32 : 3;
|
|
__u32 pstate_sample : 1;
|
|
__u32 sstate_sample : 1;
|
|
__u32 pstate_collect : 1;
|
|
__u32 sstate_collect : 1;
|
|
__u32 : 1;
|
|
__u32 halted_int : 1;
|
|
__u32 int_requested : 1;
|
|
__u32 buffer_full_int : 1;
|
|
__u32 key : 4;
|
|
__u32 : 9;
|
|
__u32 rgs : 3;
|
|
|
|
__u32 mode : 4;
|
|
__u32 next : 1;
|
|
__u32 mae : 1;
|
|
__u32 : 2;
|
|
__u32 call_type_br : 1;
|
|
__u32 return_type_br : 1;
|
|
__u32 other_type_br : 1;
|
|
__u32 bc_other_type : 1;
|
|
__u32 emit : 1;
|
|
__u32 tx_abort : 1;
|
|
__u32 : 2;
|
|
__u32 bp_xn : 1;
|
|
__u32 bp_xt : 1;
|
|
__u32 bp_ti : 1;
|
|
__u32 bp_ni : 1;
|
|
__u32 suppr_y : 1;
|
|
__u32 suppr_z : 1;
|
|
|
|
__u32 dc_miss_extra : 1;
|
|
__u32 lat_lev_ignore : 1;
|
|
__u32 ic_lat_lev : 4;
|
|
__u32 dc_lat_lev : 4;
|
|
|
|
__u64 reserved1;
|
|
__u64 scaling_factor;
|
|
__u64 rsic;
|
|
__u64 reserved2;
|
|
} __packed __aligned(8);
|
|
|
|
extern struct runtime_instr_cb runtime_instr_empty_cb;
|
|
|
|
static inline void load_runtime_instr_cb(struct runtime_instr_cb *cb)
|
|
{
|
|
asm volatile(".insn rsy,0xeb0000000060,0,0,%0" /* LRIC */
|
|
: : "Q" (*cb));
|
|
}
|
|
|
|
static inline void store_runtime_instr_cb(struct runtime_instr_cb *cb)
|
|
{
|
|
asm volatile(".insn rsy,0xeb0000000061,0,0,%0" /* STRIC */
|
|
: "=Q" (*cb) : : "cc");
|
|
}
|
|
|
|
static inline void save_ri_cb(struct runtime_instr_cb *cb_prev)
|
|
{
|
|
#ifdef CONFIG_64BIT
|
|
if (cb_prev)
|
|
store_runtime_instr_cb(cb_prev);
|
|
#endif
|
|
}
|
|
|
|
static inline void restore_ri_cb(struct runtime_instr_cb *cb_next,
|
|
struct runtime_instr_cb *cb_prev)
|
|
{
|
|
#ifdef CONFIG_64BIT
|
|
if (cb_next)
|
|
load_runtime_instr_cb(cb_next);
|
|
else if (cb_prev)
|
|
load_runtime_instr_cb(&runtime_instr_empty_cb);
|
|
#endif
|
|
}
|
|
|
|
#ifdef CONFIG_64BIT
|
|
extern void exit_thread_runtime_instr(void);
|
|
#else
|
|
static inline void exit_thread_runtime_instr(void) { }
|
|
#endif
|
|
|
|
#endif /* _RUNTIME_INSTR_H */
|