]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
s390/cpumf: simplify detection of guest samples
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Tue, 4 Apr 2017 10:55:11 +0000 (12:55 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Wed, 5 Apr 2017 08:11:38 +0000 (10:11 +0200)
There are three different code levels in regard to the identification
of guest samples. They differ in the way the LPP instruction is used.

1) Old kernels without the LPP instruction. The guest program parameter
   is always zero.
2) Newer kernels load the process pid into the program parameter with LPP.
   The guest program parameter is non-zero if the guest executes in a
   process != idle.
3) The latest kernels load ((1UL << 31) | pid) with LPP to make the value
   non-zero even for the idle task. The guest program parameter is non-zero
   if the guest is running.

All kernels load the process pid to CR4 on context switch. The CPU sampling
code uses the value in CR4 to decide between guest and host samples in case
the guest program parameter is zero. The three cases:

1) CR4==pid, gpp==0
2) CR4==pid, gpp==pid
3) CR4==pid, gpp==((1UL << 31) | pid)

The load-control instruction to load the pid into CR4 is expensive and the
goal is to remove it. To distinguish the host CR4 from the guest pid for
the idle process the maximum value 0xffff for the PASN is used.
This adds a fourth case for a guest OS with an updated kernel:

4) CR4==0xffff, gpp=((1UL << 31) | pid)

The host kernel will have CR4==0xffff and will use (gpp!=0 || CR4!==0xffff)
to identify guest samples. This works nicely with all 4 cases, the only
possible issue would be a guest with an old kernel (gpp==0) and a process
pid of 0xffff. Well, don't do that..

Suggested-by: Christian Borntraeger <borntraeger@de.ibm.com>
Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/kernel/entry.S
arch/s390/kernel/head64.S
arch/s390/kernel/perf_cpum_sf.c

index 02f11018e2df1f99cfb4772088ec805be9c609cf..c6cf338c932704dd13a95af4e64ce2d50d940c13 100644 (file)
@@ -189,10 +189,6 @@ ENTRY(__switch_to)
        stg     %r3,__LC_CURRENT                # store task struct of next
        stg     %r15,__LC_KERNEL_STACK          # store end of kernel stack
        lg      %r15,__THREAD_ksp(%r1)          # load kernel stack of next
-       /* c4 is used in guest detection: arch/s390/kernel/perf_cpum_sf.c */
-       xc      __SF_EMPTY(8,%r15),__SF_EMPTY(%r15)
-       mvc     __SF_EMPTY+4(4,%r15),__TASK_pid(%r3)
-       lctlg   %c4,%c4,__SF_EMPTY(%r15)        # load pid to control reg. 4
        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
index 482d3526e32b290311151a17954f2c55ce41e15b..31c91f24e5624389b34017c45fd44dad3b11114f 100644 (file)
@@ -52,7 +52,7 @@ ENTRY(startup_continue)
        .quad   0                       # cr1: primary space segment table
        .quad   .Lduct                  # cr2: dispatchable unit control table
        .quad   0                       # cr3: instruction authorization
-       .quad   0                       # cr4: instruction authorization
+       .quad   0xffff                  # cr4: instruction authorization
        .quad   .Lduct                  # cr5: primary-aste origin
        .quad   0                       # cr6:  I/O interrupts
        .quad   0                       # cr7:  secondary space segment table
index 1c0b58545c04d6f5c44e0f07838fcc35901e0cf5..9a4f279d25ca9675a711d604f0a9ec7c633cae7b 100644 (file)
@@ -1009,8 +1009,8 @@ static int perf_push_sample(struct perf_event *event, struct sf_raw_sample *sfr)
         * sample. Some early samples or samples from guests without
         * lpp usage would be misaccounted to the host. We use the asn
         * value as an addon heuristic to detect most of these guest samples.
-        * If the value differs from the host hpp value, we assume to be a
-        * KVM guest.
+        * If the value differs from 0xffff (the host value), we assume to
+        * be a KVM guest.
         */
        switch (sfr->basic.CL) {
        case 1: /* logical partition */
@@ -1020,8 +1020,7 @@ static int perf_push_sample(struct perf_event *event, struct sf_raw_sample *sfr)
                sde_regs->in_guest = 1;
                break;
        default: /* old machine, use heuristics */
-               if (sfr->basic.gpp ||
-                   sfr->basic.prim_asn != (u16)sfr->basic.hpp)
+               if (sfr->basic.gpp || sfr->basic.prim_asn != 0xffff)
                        sde_regs->in_guest = 1;
                break;
        }