Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Christian Borntraeger and committed by
Martin Schwidefsky
e22cf8ca 6a62b485

+40 -24
+8 -1
arch/s390/include/asm/lowcore.h
··· 132 132 /* Address space pointer. */ 133 133 __u64 kernel_asce; /* 0x0358 */ 134 134 __u64 user_asce; /* 0x0360 */ 135 - __u64 current_pid; /* 0x0368 */ 135 + 136 + /* 137 + * The lpp and current_pid fields form a 138 + * 64-bit value that is set as program 139 + * parameter with the LPP instruction. 140 + */ 141 + __u32 lpp; /* 0x0368 */ 142 + __u32 current_pid; /* 0x036c */ 136 143 137 144 /* SMP info area */ 138 145 __u32 cpu_nr; /* 0x0370 */
+3
arch/s390/include/asm/setup.h
··· 34 34 #define MACHINE_FLAG_VX _BITUL(18) 35 35 #define MACHINE_FLAG_CAD _BITUL(19) 36 36 37 + #define LPP_MAGIC _BITUL(31) 38 + #define LPP_PFAULT_PID_MASK _AC(0xffffffff, UL) 39 + 37 40 #ifndef __ASSEMBLY__ 38 41 39 42 #include <asm/lowcore.h>
+1
arch/s390/kernel/asm-offsets.c
··· 163 163 OFFSET(__LC_RESTART_DATA, _lowcore, restart_data); 164 164 OFFSET(__LC_RESTART_SOURCE, _lowcore, restart_source); 165 165 OFFSET(__LC_USER_ASCE, _lowcore, user_asce); 166 + OFFSET(__LC_LPP, _lowcore, lpp); 166 167 OFFSET(__LC_CURRENT_PID, _lowcore, current_pid); 167 168 OFFSET(__LC_PERCPU_OFFSET, _lowcore, percpu_offset); 168 169 OFFSET(__LC_VDSO_PER_CPU, _lowcore, vdso_per_cpu_data);
+12 -16
arch/s390/kernel/entry.S
··· 187 187 stg %r15,__LC_KERNEL_STACK # store end of kernel stack 188 188 lg %r15,__THREAD_ksp(%r1) # load kernel stack of next 189 189 lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4 190 - mvc __LC_CURRENT_PID+4(4,%r0),__TASK_pid(%r3) # store pid of next 190 + mvc __LC_CURRENT_PID(4,%r0),__TASK_pid(%r3) # store pid of next 191 191 lmg %r6,%r15,__SF_GPRS(%r15) # load gprs of next task 192 + TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_LPP 193 + bzr %r14 194 + .insn s,0xb2800000,__LC_LPP # set program parameter 192 195 br %r14 193 196 194 197 .L__critical_start: ··· 206 203 stmg %r6,%r14,__SF_GPRS(%r15) # save kernel registers 207 204 stg %r2,__SF_EMPTY(%r15) # save control block pointer 208 205 stg %r3,__SF_EMPTY+8(%r15) # save guest register save area 209 - xc __SF_EMPTY+16(16,%r15),__SF_EMPTY+16(%r15) # host id & reason 206 + xc __SF_EMPTY+16(8,%r15),__SF_EMPTY+16(%r15) # reason code = 0 210 207 TSTMSK __LC_CPU_FLAGS,_CIF_FPU # load guest fp/vx registers ? 211 208 jno .Lsie_load_guest_gprs 212 209 brasl %r14,load_fpu_regs # load guest fp/vx regs ··· 223 220 jnz .Lsie_skip 224 221 TSTMSK __LC_CPU_FLAGS,_CIF_FPU 225 222 jo .Lsie_skip # exit if fp/vx regs changed 226 - TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_LPP 227 - jz .Lsie_enter 228 - .insn s,0xb2800000,__LC_CURRENT_PID # set guest id to pid 229 - .Lsie_enter: 230 223 sie 0(%r14) 231 - TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_LPP 232 - jz .Lsie_skip 233 - .insn s,0xb2800000,__SF_EMPTY+16(%r15)# set host id 234 224 .Lsie_skip: 235 225 ni __SIE_PROG0C+3(%r14),0xfe # no longer in SIE 236 226 lctlg %c1,%c1,__LC_USER_ASCE # load primary asce ··· 240 244 lg %r14,__SF_EMPTY+8(%r15) # load guest register save area 241 245 stmg %r0,%r13,0(%r14) # save guest gprs 0-13 242 246 lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers 243 - lg %r2,__SF_EMPTY+24(%r15) # return exit reason code 247 + lg %r2,__SF_EMPTY+16(%r15) # return exit reason code 244 248 br %r14 245 249 .Lsie_fault: 246 250 lghi %r14,-EFAULT 247 - stg %r14,__SF_EMPTY+24(%r15) # set exit reason code 251 + stg %r14,__SF_EMPTY+16(%r15) # set exit reason code 248 252 j sie_exit 249 253 250 254 EX_TABLE(.Lrewind_pad,.Lsie_fault) ··· 934 938 # PSW restart interrupt handler 935 939 # 936 940 ENTRY(restart_int_handler) 937 - stg %r15,__LC_SAVE_AREA_RESTART 941 + TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_LPP 942 + jz 0f 943 + .insn s,0xb2800000,__LC_LPP 944 + 0: stg %r15,__LC_SAVE_AREA_RESTART 938 945 lg %r15,__LC_RESTART_STACK 939 946 aghi %r15,-__PT_SIZE # create pt_regs on stack 940 947 xc 0(__PT_SIZE,%r15),0(%r15) ··· 1041 1042 1042 1043 .Lcleanup_sie: 1043 1044 lg %r9,__SF_EMPTY(%r15) # get control block pointer 1044 - TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_LPP 1045 - jz 0f 1046 - .insn s,0xb2800000,__SF_EMPTY+16(%r15)# set host id 1047 - 0: ni __SIE_PROG0C+3(%r9),0xfe # no longer in SIE 1045 + ni __SIE_PROG0C+3(%r9),0xfe # no longer in SIE 1048 1046 lctlg %c1,%c1,__LC_USER_ASCE # load primary asce 1049 1047 larl %r9,sie_exit # skip forward to sie_exit 1050 1048 br %r14
+6 -1
arch/s390/kernel/head64.S
··· 16 16 17 17 __HEAD 18 18 ENTRY(startup_continue) 19 - larl %r1,sched_clock_base_cc 19 + tm __LC_STFL_FAC_LIST+6,0x80 # LPP available ? 20 + jz 0f 21 + xc __LC_LPP+1(7,0),__LC_LPP+1 # clear lpp and current_pid 22 + mvi __LC_LPP,0x80 # and set LPP_MAGIC 23 + .insn s,0xb2800000,__LC_LPP # load program parameter 24 + 0: larl %r1,sched_clock_base_cc 20 25 mvc 0(8,%r1),__LC_LAST_UPDATE_CLOCK 21 26 larl %r13,.LPG1 # get base 22 27 lctlg %c0,%c15,.Lctl-.LPG1(%r13) # load control registers
+6 -4
arch/s390/kernel/perf_cpum_sf.c
··· 1019 1019 break; 1020 1020 } 1021 1021 1022 - /* The host-program-parameter (hpp) contains the pid of 1023 - * the CPU thread as set by sie64a() in entry.S. 1024 - * If non-zero assume a guest sample. 1022 + /* 1023 + * A non-zero guest program parameter indicates a guest 1024 + * sample. 1025 + * Note that some early samples might be misaccounted to 1026 + * the host. 1025 1027 */ 1026 - if (sfr->basic.hpp) 1028 + if (sfr->basic.gpp) 1027 1029 sde_regs->in_guest = 1; 1028 1030 1029 1031 overflow = 0;
+2
arch/s390/kernel/smp.c
··· 262 262 + THREAD_SIZE - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs); 263 263 lc->thread_info = (unsigned long) task_thread_info(tsk); 264 264 lc->current_task = (unsigned long) tsk; 265 + lc->lpp = LPP_MAGIC; 266 + lc->current_pid = tsk->pid; 265 267 lc->user_timer = ti->user_timer; 266 268 lc->system_timer = ti->system_timer; 267 269 lc->steal_timer = 0;
+2 -2
arch/s390/mm/fault.c
··· 590 590 .reffcode = 0, 591 591 .refdwlen = 5, 592 592 .refversn = 2, 593 - .refgaddr = __LC_CURRENT_PID, 593 + .refgaddr = __LC_LPP, 594 594 .refselmk = 1ULL << 48, 595 595 .refcmpmk = 1ULL << 48, 596 596 .reserved = __PF_RES_FIELD }; ··· 649 649 return; 650 650 inc_irq_stat(IRQEXT_PFL); 651 651 /* Get the token (= pid of the affected task). */ 652 - pid = param64; 652 + pid = param64 & LPP_PFAULT_PID_MASK; 653 653 rcu_read_lock(); 654 654 tsk = find_task_by_pid_ns(pid, &init_pid_ns); 655 655 if (tsk)