mirror of
https://github.com/torvalds/linux.git
synced 2024-11-15 16:41:58 +00:00
s390/cpumf: rework program parameter setting to detect guest samples
The program parameter can be used to mark hardware samples with some token. Previously, it was used to mark guest samples only. Improve the program parameter doubleword by combining two parts, the leftmost LPP part and the rightmost PID part. Set the PID part for processes by using the task PID. To distinguish host and guest samples for the kernel (PID part is zero), the guest must always set the program paramater to a non-zero value. Use the leftmost bit in the LPP part of the program parameter to be able to detect guest kernel samples. [brueckner@linux.vnet.ibm.com]: Split __LC_CURRENT and introduced __LC_LPP. Corrected __LC_CURRENT users and adjusted assembler parts. And updated the commit message accordingly. Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com> Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com> Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
parent
6a62b485ea
commit
e22cf8ca6f
@ -132,7 +132,14 @@ struct _lowcore {
|
||||
/* Address space pointer. */
|
||||
__u64 kernel_asce; /* 0x0358 */
|
||||
__u64 user_asce; /* 0x0360 */
|
||||
__u64 current_pid; /* 0x0368 */
|
||||
|
||||
/*
|
||||
* The lpp and current_pid fields form a
|
||||
* 64-bit value that is set as program
|
||||
* parameter with the LPP instruction.
|
||||
*/
|
||||
__u32 lpp; /* 0x0368 */
|
||||
__u32 current_pid; /* 0x036c */
|
||||
|
||||
/* SMP info area */
|
||||
__u32 cpu_nr; /* 0x0370 */
|
||||
|
@ -34,6 +34,9 @@
|
||||
#define MACHINE_FLAG_VX _BITUL(18)
|
||||
#define MACHINE_FLAG_CAD _BITUL(19)
|
||||
|
||||
#define LPP_MAGIC _BITUL(31)
|
||||
#define LPP_PFAULT_PID_MASK _AC(0xffffffff, UL)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <asm/lowcore.h>
|
||||
|
@ -163,6 +163,7 @@ int main(void)
|
||||
OFFSET(__LC_RESTART_DATA, _lowcore, restart_data);
|
||||
OFFSET(__LC_RESTART_SOURCE, _lowcore, restart_source);
|
||||
OFFSET(__LC_USER_ASCE, _lowcore, user_asce);
|
||||
OFFSET(__LC_LPP, _lowcore, lpp);
|
||||
OFFSET(__LC_CURRENT_PID, _lowcore, current_pid);
|
||||
OFFSET(__LC_PERCPU_OFFSET, _lowcore, percpu_offset);
|
||||
OFFSET(__LC_VDSO_PER_CPU, _lowcore, vdso_per_cpu_data);
|
||||
|
@ -187,8 +187,11 @@ ENTRY(__switch_to)
|
||||
stg %r15,__LC_KERNEL_STACK # store end of kernel stack
|
||||
lg %r15,__THREAD_ksp(%r1) # load kernel stack of next
|
||||
lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4
|
||||
mvc __LC_CURRENT_PID+4(4,%r0),__TASK_pid(%r3) # store pid of next
|
||||
mvc __LC_CURRENT_PID(4,%r0),__TASK_pid(%r3) # store pid of next
|
||||
lmg %r6,%r15,__SF_GPRS(%r15) # load gprs of next task
|
||||
TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_LPP
|
||||
bzr %r14
|
||||
.insn s,0xb2800000,__LC_LPP # set program parameter
|
||||
br %r14
|
||||
|
||||
.L__critical_start:
|
||||
@ -203,7 +206,7 @@ ENTRY(sie64a)
|
||||
stmg %r6,%r14,__SF_GPRS(%r15) # save kernel registers
|
||||
stg %r2,__SF_EMPTY(%r15) # save control block pointer
|
||||
stg %r3,__SF_EMPTY+8(%r15) # save guest register save area
|
||||
xc __SF_EMPTY+16(16,%r15),__SF_EMPTY+16(%r15) # host id & reason
|
||||
xc __SF_EMPTY+16(8,%r15),__SF_EMPTY+16(%r15) # reason code = 0
|
||||
TSTMSK __LC_CPU_FLAGS,_CIF_FPU # load guest fp/vx registers ?
|
||||
jno .Lsie_load_guest_gprs
|
||||
brasl %r14,load_fpu_regs # load guest fp/vx regs
|
||||
@ -220,14 +223,7 @@ ENTRY(sie64a)
|
||||
jnz .Lsie_skip
|
||||
TSTMSK __LC_CPU_FLAGS,_CIF_FPU
|
||||
jo .Lsie_skip # exit if fp/vx regs changed
|
||||
TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_LPP
|
||||
jz .Lsie_enter
|
||||
.insn s,0xb2800000,__LC_CURRENT_PID # set guest id to pid
|
||||
.Lsie_enter:
|
||||
sie 0(%r14)
|
||||
TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_LPP
|
||||
jz .Lsie_skip
|
||||
.insn s,0xb2800000,__SF_EMPTY+16(%r15)# set host id
|
||||
.Lsie_skip:
|
||||
ni __SIE_PROG0C+3(%r14),0xfe # no longer in SIE
|
||||
lctlg %c1,%c1,__LC_USER_ASCE # load primary asce
|
||||
@ -244,11 +240,11 @@ sie_exit:
|
||||
lg %r14,__SF_EMPTY+8(%r15) # load guest register save area
|
||||
stmg %r0,%r13,0(%r14) # save guest gprs 0-13
|
||||
lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers
|
||||
lg %r2,__SF_EMPTY+24(%r15) # return exit reason code
|
||||
lg %r2,__SF_EMPTY+16(%r15) # return exit reason code
|
||||
br %r14
|
||||
.Lsie_fault:
|
||||
lghi %r14,-EFAULT
|
||||
stg %r14,__SF_EMPTY+24(%r15) # set exit reason code
|
||||
stg %r14,__SF_EMPTY+16(%r15) # set exit reason code
|
||||
j sie_exit
|
||||
|
||||
EX_TABLE(.Lrewind_pad,.Lsie_fault)
|
||||
@ -938,7 +934,10 @@ ENTRY(mcck_int_handler)
|
||||
# PSW restart interrupt handler
|
||||
#
|
||||
ENTRY(restart_int_handler)
|
||||
stg %r15,__LC_SAVE_AREA_RESTART
|
||||
TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_LPP
|
||||
jz 0f
|
||||
.insn s,0xb2800000,__LC_LPP
|
||||
0: stg %r15,__LC_SAVE_AREA_RESTART
|
||||
lg %r15,__LC_RESTART_STACK
|
||||
aghi %r15,-__PT_SIZE # create pt_regs on stack
|
||||
xc 0(__PT_SIZE,%r15),0(%r15)
|
||||
@ -1042,10 +1041,7 @@ cleanup_critical:
|
||||
|
||||
.Lcleanup_sie:
|
||||
lg %r9,__SF_EMPTY(%r15) # get control block pointer
|
||||
TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_LPP
|
||||
jz 0f
|
||||
.insn s,0xb2800000,__SF_EMPTY+16(%r15)# set host id
|
||||
0: ni __SIE_PROG0C+3(%r9),0xfe # no longer in SIE
|
||||
ni __SIE_PROG0C+3(%r9),0xfe # no longer in SIE
|
||||
lctlg %c1,%c1,__LC_USER_ASCE # load primary asce
|
||||
larl %r9,sie_exit # skip forward to sie_exit
|
||||
br %r14
|
||||
|
@ -16,7 +16,12 @@
|
||||
|
||||
__HEAD
|
||||
ENTRY(startup_continue)
|
||||
larl %r1,sched_clock_base_cc
|
||||
tm __LC_STFL_FAC_LIST+6,0x80 # LPP available ?
|
||||
jz 0f
|
||||
xc __LC_LPP+1(7,0),__LC_LPP+1 # clear lpp and current_pid
|
||||
mvi __LC_LPP,0x80 # and set LPP_MAGIC
|
||||
.insn s,0xb2800000,__LC_LPP # load program parameter
|
||||
0: larl %r1,sched_clock_base_cc
|
||||
mvc 0(8,%r1),__LC_LAST_UPDATE_CLOCK
|
||||
larl %r13,.LPG1 # get base
|
||||
lctlg %c0,%c15,.Lctl-.LPG1(%r13) # load control registers
|
||||
|
@ -1019,11 +1019,13 @@ static int perf_push_sample(struct perf_event *event, struct sf_raw_sample *sfr)
|
||||
break;
|
||||
}
|
||||
|
||||
/* The host-program-parameter (hpp) contains the pid of
|
||||
* the CPU thread as set by sie64a() in entry.S.
|
||||
* If non-zero assume a guest sample.
|
||||
/*
|
||||
* A non-zero guest program parameter indicates a guest
|
||||
* sample.
|
||||
* Note that some early samples might be misaccounted to
|
||||
* the host.
|
||||
*/
|
||||
if (sfr->basic.hpp)
|
||||
if (sfr->basic.gpp)
|
||||
sde_regs->in_guest = 1;
|
||||
|
||||
overflow = 0;
|
||||
|
@ -262,6 +262,8 @@ static void pcpu_attach_task(struct pcpu *pcpu, struct task_struct *tsk)
|
||||
+ THREAD_SIZE - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs);
|
||||
lc->thread_info = (unsigned long) task_thread_info(tsk);
|
||||
lc->current_task = (unsigned long) tsk;
|
||||
lc->lpp = LPP_MAGIC;
|
||||
lc->current_pid = tsk->pid;
|
||||
lc->user_timer = ti->user_timer;
|
||||
lc->system_timer = ti->system_timer;
|
||||
lc->steal_timer = 0;
|
||||
|
@ -590,7 +590,7 @@ int pfault_init(void)
|
||||
.reffcode = 0,
|
||||
.refdwlen = 5,
|
||||
.refversn = 2,
|
||||
.refgaddr = __LC_CURRENT_PID,
|
||||
.refgaddr = __LC_LPP,
|
||||
.refselmk = 1ULL << 48,
|
||||
.refcmpmk = 1ULL << 48,
|
||||
.reserved = __PF_RES_FIELD };
|
||||
@ -649,7 +649,7 @@ static void pfault_interrupt(struct ext_code ext_code,
|
||||
return;
|
||||
inc_irq_stat(IRQEXT_PFL);
|
||||
/* Get the token (= pid of the affected task). */
|
||||
pid = param64;
|
||||
pid = param64 & LPP_PFAULT_PID_MASK;
|
||||
rcu_read_lock();
|
||||
tsk = find_task_by_pid_ns(pid, &init_pid_ns);
|
||||
if (tsk)
|
||||
|
Loading…
Reference in New Issue
Block a user