s390/cpumf: rework program parameter setting to detect guest samples
authorChristian Borntraeger <borntraeger@de.ibm.com>
Tue, 6 Oct 2015 16:06:15 +0000 (18:06 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Wed, 14 Oct 2015 12:32:12 +0000 (14:32 +0200)
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>
arch/s390/include/asm/lowcore.h
arch/s390/include/asm/setup.h
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/entry.S
arch/s390/kernel/head64.S
arch/s390/kernel/perf_cpum_sf.c
arch/s390/kernel/smp.c
arch/s390/mm/fault.c

index 663f23e374605d91844dd952417c4e6c778fd3fa..12af453c3c19f80d21c4c96b198dc4d9464dc8d4 100644 (file)
@@ -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 */
index ab015a7f20d0b859e603880d796c80713a19d9da..23537661da0ed8d00cc8a2c9df4daed83b43eb52 100644 (file)
@@ -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>
index ac857c452be2c0195c94e26350f8def4b03eb751..9cd248f637c7a7bb8a1666df32499858d91e31c1 100644 (file)
@@ -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);
index 2444ea7f7ba42b2853b044f9f2ada7a23014d67f..d653a87d66b58470bad04659d7a94e104fc593ca 100644 (file)
@@ -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
index d7c00507568a73e8f5acb45014f366154f839980..58b719fa8067a5b7e2ec428c0babc758c6dc0eb4 100644 (file)
 
 __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
index b973972f6ba5cf8e995a01ef7ba869a4e520b5e8..3d8da1e742c2b72f7741b8e0a48b8e1b185b4530 100644 (file)
@@ -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;
index dbd40d448294dde8e2149b09d6931efb704fd65e..9062df575afe1cea0b6a15f0ab018d95ecc859b9 100644 (file)
@@ -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;
index 77b3938d6bfac04a874f0b57de30c02bdce491c5..ec1a30d0d11ab474d41ca7d3f9d6cc7e212249d0 100644 (file)
@@ -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)