[S390] virtualization aware cpu measurement
authorCarsten Otte <cotte@de.ibm.com>
Mon, 17 May 2010 08:00:04 +0000 (10:00 +0200)
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>
Mon, 17 May 2010 08:00:15 +0000 (10:00 +0200)
Use the SPP instruction to set a tag on entry to / exit of the virtual
machine context. This allows the cpu measurement facility to distinguish
the samples from the host and the different guests.

Signed-off-by: Carsten Otte <cotte@de.ibm.com>
arch/s390/include/asm/lowcore.h
arch/s390/include/asm/setup.h
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/early.c
arch/s390/kernel/entry64.S
arch/s390/kernel/setup.c
arch/s390/kvm/Kconfig
arch/s390/kvm/sie64a.S

index 2c02d46c35882d3be99e5e0247f19f9934f166e7..0f97ef2d92acd8324aa3ee342c874a2ad071771b 100644 (file)
@@ -267,7 +267,8 @@ struct _lowcore {
        __u64   vdso_per_cpu_data;              /* 0x0358 */
        __u64   machine_flags;                  /* 0x0360 */
        __u64   ftrace_func;                    /* 0x0368 */
-       __u8    pad_0x0370[0x0380-0x0370];      /* 0x0370 */
+       __u64   sie_hook;                       /* 0x0370 */
+       __u64   cmf_hpp;                        /* 0x0378 */
 
        /* Interrupt response block. */
        __u8    irb[64];                        /* 0x0380 */
index 9ab6bd3a65d10424835a01cc7beedaa21fc7ef5c..25e831d58e1ecde6a3dba239a6befcd7a6bfd808 100644 (file)
@@ -2,7 +2,7 @@
  *  include/asm-s390/setup.h
  *
  *  S390 version
- *    Copyright IBM Corp. 1999,2006
+ *    Copyright IBM Corp. 1999,2010
  */
 
 #ifndef _ASM_S390_SETUP_H
@@ -72,6 +72,7 @@ extern unsigned int user_mode;
 #define MACHINE_FLAG_HPAGE     (1UL << 10)
 #define MACHINE_FLAG_PFMF      (1UL << 11)
 #define MACHINE_FLAG_LPAR      (1UL << 12)
+#define MACHINE_FLAG_SPP       (1UL << 13)
 
 #define MACHINE_IS_VM          (S390_lowcore.machine_flags & MACHINE_FLAG_VM)
 #define MACHINE_IS_KVM         (S390_lowcore.machine_flags & MACHINE_FLAG_KVM)
@@ -88,6 +89,7 @@ extern unsigned int user_mode;
 #define MACHINE_HAS_MVCOS      (0)
 #define MACHINE_HAS_HPAGE      (0)
 #define MACHINE_HAS_PFMF       (0)
+#define MACHINE_HAS_SPP                (0)
 #else /* __s390x__ */
 #define MACHINE_HAS_IEEE       (1)
 #define MACHINE_HAS_CSP                (1)
@@ -97,6 +99,7 @@ extern unsigned int user_mode;
 #define MACHINE_HAS_MVCOS      (S390_lowcore.machine_flags & MACHINE_FLAG_MVCOS)
 #define MACHINE_HAS_HPAGE      (S390_lowcore.machine_flags & MACHINE_FLAG_HPAGE)
 #define MACHINE_HAS_PFMF       (S390_lowcore.machine_flags & MACHINE_FLAG_PFMF)
+#define MACHINE_HAS_SPP                (S390_lowcore.machine_flags & MACHINE_FLAG_SPP)
 #endif /* __s390x__ */
 
 #define ZFCPDUMP_HSA_SIZE      (32UL<<20)
index 816d81f479c067a48bf3d7b0a72093a134f18f96..44a4336d9a3367fd684f92d90717613b3edc1c91 100644 (file)
@@ -131,6 +131,8 @@ int main(void)
        DEFINE(__LC_MCCK_CLOCK, offsetof(struct _lowcore, mcck_clock));
        DEFINE(__LC_MACHINE_FLAGS, offsetof(struct _lowcore, machine_flags));
        DEFINE(__LC_FTRACE_FUNC, offsetof(struct _lowcore, ftrace_func));
+       DEFINE(__LC_SIE_HOOK, offsetof(struct _lowcore, sie_hook));
+       DEFINE(__LC_CMF_HPP, offsetof(struct _lowcore, cmf_hpp));
        DEFINE(__LC_IRB, offsetof(struct _lowcore, irb));
        DEFINE(__LC_CPU_TIMER_SAVE_AREA, offsetof(struct _lowcore, cpu_timer_save_area));
        DEFINE(__LC_CLOCK_COMP_SAVE_AREA, offsetof(struct _lowcore, clock_comp_save_area));
index 2d92c2cf92d71e499fbf6b4a1ac822a4380af3c2..c00856ad4e5a15b00450322053914964122f7cf7 100644 (file)
@@ -356,6 +356,7 @@ static __init void detect_machine_facilities(void)
 {
 #ifdef CONFIG_64BIT
        unsigned int facilities;
+       unsigned long long facility_bits;
 
        facilities = stfl();
        if (facilities & (1 << 28))
@@ -364,6 +365,9 @@ static __init void detect_machine_facilities(void)
                S390_lowcore.machine_flags |= MACHINE_FLAG_PFMF;
        if (facilities & (1 << 4))
                S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS;
+       if ((stfle(&facility_bits, 1) > 0) &&
+           (facility_bits & (1ULL << (63 - 40))))
+               S390_lowcore.machine_flags |= MACHINE_FLAG_SPP;
 #endif
 }
 
index 6536f5ca46f540f09b74439f0aeecf2131c05e60..829b759ba1e1e17c7ea0b2da7b04b5e53ee125fa 100644 (file)
@@ -2,7 +2,7 @@
  *  arch/s390/kernel/entry64.S
  *    S390 low-level entry points.
  *
- *    Copyright (C) IBM Corp. 1999,2006
+ *    Copyright (C) IBM Corp. 1999,2010
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  *              Hartmut Penner (hp@de.ibm.com),
  *              Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
@@ -59,6 +59,16 @@ _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \
 
 #define BASED(name) name-system_call(%r13)
 
+       .macro  HANDLE_SIE_INTERCEPT
+#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
+       lg      %r3,__LC_SIE_HOOK
+       ltgr    %r3,%r3
+       jz      0f
+       basr    %r14,%r3
+       0:
+#endif
+       .endm
+
 #ifdef CONFIG_TRACE_IRQFLAGS
        .macro  TRACE_IRQS_ON
        basr    %r2,%r0
@@ -466,6 +476,7 @@ pgm_check_handler:
        UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
        mvc     __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
 pgm_no_vtime:
+       HANDLE_SIE_INTERCEPT
        TRACE_IRQS_CHECK_OFF
        lg      %r9,__LC_THREAD_INFO    # load pointer to thread_info struct
        mvc     SP_ARGS(8,%r15),__LC_LAST_BREAK
@@ -507,6 +518,7 @@ pgm_per_std:
        UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
        mvc     __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
 pgm_no_vtime2:
+       HANDLE_SIE_INTERCEPT
        TRACE_IRQS_CHECK_OFF
        lg      %r9,__LC_THREAD_INFO    # load pointer to thread_info struct
        lg      %r1,__TI_task(%r9)
@@ -570,6 +582,7 @@ io_int_handler:
        mvc     __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
 io_no_vtime:
        lg      %r9,__LC_THREAD_INFO    # load pointer to thread_info struct
+       HANDLE_SIE_INTERCEPT
        TRACE_IRQS_OFF
        la      %r2,SP_PTREGS(%r15)     # address of register-save area
        brasl   %r14,do_IRQ             # call standard irq handler
@@ -595,15 +608,6 @@ io_done:
 io_work:
        tm      SP_PSW+1(%r15),0x01     # returning to user ?
        jo      io_work_user            # yes -> do resched & signal
-#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
-       lg      %r2,SP_PSW+8(%r15)      # check if current instruction is SIE
-       lh      %r1,0(%r2)
-       chi     %r1,-19948              # signed 16 bit compare with 0xb214
-       jne     0f                      # no -> leave PSW alone
-       aghi    %r2,4                   # yes-> add 4 bytes to leave SIE
-       stg     %r2,SP_PSW+8(%r15)
-0:
-#endif
 #ifdef CONFIG_PREEMPT
        # check for preemptive scheduling
        icm     %r0,15,__TI_precount(%r9)
@@ -712,6 +716,7 @@ ext_int_handler:
        mvc     __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
 ext_no_vtime:
        lg      %r9,__LC_THREAD_INFO    # load pointer to thread_info struct
+       HANDLE_SIE_INTERCEPT
        TRACE_IRQS_OFF
        la      %r2,SP_PTREGS(%r15)     # address of register-save area
        llgh    %r3,__LC_EXT_INT_CODE   # get interruption code
@@ -786,6 +791,7 @@ mcck_no_vtime:
        stosm   __SF_EMPTY(%r15),0x04   # turn dat on
        tm      __TI_flags+7(%r9),_TIF_MCCK_PENDING
        jno     mcck_return
+       HANDLE_SIE_INTERCEPT
        TRACE_IRQS_OFF
        brasl   %r14,s390_handle_mcck
        TRACE_IRQS_ON
index 598752499c3e3b94a1ddc291fe2c4b1d265e7078..7d893248d26507bce1dcc0a2df02f6479a823052 100644 (file)
@@ -2,7 +2,7 @@
  *  arch/s390/kernel/setup.c
  *
  *  S390 version
- *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) IBM Corp. 1999,2010
  *    Author(s): Hartmut Penner (hp@de.ibm.com),
  *               Martin Schwidefsky (schwidefsky@de.ibm.com)
  *
@@ -401,6 +401,7 @@ setup_lowcore(void)
        lc->io_new_psw.mask = psw_kernel_bits;
        lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler;
        lc->clock_comparator = -1ULL;
+       lc->cmf_hpp = -1ULL;
        lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE;
        lc->async_stack = (unsigned long)
                __alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0) + ASYNC_SIZE;
index a7251580891cfef25483e683460d58f498eb65b6..2f4b687cc7fa094f943daf925bd07c27204c717a 100644 (file)
@@ -33,6 +33,17 @@ config KVM
 
          If unsure, say N.
 
+config KVM_AWARE_CMF
+       depends on KVM
+       bool "KVM aware sampling"
+       ---help---
+         This option enhances the sampling data from the CPU Measurement
+         Facility with additional information, that allows to distinguish
+         guest(s) and host when using the kernel based virtual machine
+         functionality.
+
+         If unsure, say N.
+
 # OK, it's a little counter-intuitive to do this, but it puts it neatly under
 # the virtualization menu.
 source drivers/vhost/Kconfig
index 934fd6a885f69724a00440a714b4fb9498a64c8f..31646bd0e469a6db61f2386de29a2da0bb2b0e0f 100644 (file)
@@ -1,20 +1,60 @@
 /*
  * sie64a.S - low level sie call
  *
- * Copyright IBM Corp. 2008
+ * Copyright IBM Corp. 2008,2010
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License (version 2 only)
  * as published by the Free Software Foundation.
  *
  *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
+ *              Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
  */
 
 #include <linux/errno.h>
 #include <asm/asm-offsets.h>
+#include <asm/setup.h>
+#include <asm/asm-offsets.h>
+#include <asm/ptrace.h>
+#include <asm/thread_info.h>
+
+_TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
+
+/*
+ * offsets into stackframe
+ * SP_ = offsets into stack sie64 is called with
+ * SPI_ = offsets into irq stack
+ */
+SP_GREGS = __SF_EMPTY
+SP_HOOK  = __SF_EMPTY+8
+SP_GPP  = __SF_EMPTY+16
+SPI_PSW  = STACK_FRAME_OVERHEAD + __PT_PSW
+
 
-SP_R5 =        5 * 8   # offset into stackframe
-SP_R6 =        6 * 8
+       .macro SPP newpp
+#ifdef CONFIG_KVM_AWARE_CMF
+       tm      __LC_MACHINE_FLAGS+6,0x20       # MACHINE_FLAG_SPP
+       jz      0f
+       .insn   s,0xb2800000,\newpp
+       0:
+#endif
+       .endm
+
+sie_irq_handler:
+       SPP     __LC_CMF_HPP                    # set host id
+       larl    %r2,sie_inst
+       clg     %r2,SPI_PSW+8(0,%r15)           # intercepted sie
+       jne     1f
+       xc      __LC_SIE_HOOK(8),__LC_SIE_HOOK
+       lg      %r2,__LC_THREAD_INFO            # pointer thread_info struct
+       tm      __TI_flags+7(%r2),_TIF_EXIT_SIE
+       jz      0f
+       larl    %r2,sie_exit                    # work pending, leave sie
+       stg     %r2,__LC_RETURN_PSW+8
+       br      %r14
+0:     larl    %r2,sie_reenter                 # re-enter with guest id
+       stg     %r2,__LC_RETURN_PSW+8
+1:     br      %r14
 
 /*
  * sie64a calling convention:
@@ -23,23 +63,34 @@ SP_R6 =     6 * 8
  */
        .globl  sie64a
 sie64a:
-       lgr     %r5,%r3
-       stmg    %r5,%r14,SP_R5(%r15)    # save register on entry
-       lgr     %r14,%r2                # pointer to sie control block
-       lmg     %r0,%r13,0(%r3)         # load guest gprs 0-13
+       stg     %r3,SP_GREGS(%r15)              # save guest register save area
+       stmg    %r6,%r14,__SF_GPRS(%r15)        # save registers on entry
+       lgr     %r14,%r2                        # pointer to sie control block
+       larl    %r5,sie_irq_handler
+       stg     %r2,SP_GPP(%r15)
+       stg     %r5,SP_HOOK(%r15)               # save hook target
+       lmg     %r0,%r13,0(%r3)                 # load guest gprs 0-13
+sie_reenter:
+       mvc     __LC_SIE_HOOK(8),SP_HOOK(%r15)
+       SPP     SP_GPP(%r15)                    # set guest id
 sie_inst:
        sie     0(%r14)
-       lg      %r14,SP_R5(%r15)
-       stmg    %r0,%r13,0(%r14)        # save guest gprs 0-13
+       xc      __LC_SIE_HOOK(8),__LC_SIE_HOOK
+       SPP     __LC_CMF_HPP                    # set host id
+sie_exit:
+       lg      %r14,SP_GREGS(%r15)
+       stmg    %r0,%r13,0(%r14)                # save guest gprs 0-13
        lghi    %r2,0
-       lmg     %r6,%r14,SP_R6(%r15)
+       lmg     %r6,%r14,__SF_GPRS(%r15)
        br      %r14
 
 sie_err:
-       lg      %r14,SP_R5(%r15)
-       stmg    %r0,%r13,0(%r14)        # save guest gprs 0-13
+       xc      __LC_SIE_HOOK(8),__LC_SIE_HOOK
+       SPP     __LC_CMF_HPP                    # set host id
+       lg      %r14,SP_GREGS(%r15)
+       stmg    %r0,%r13,0(%r14)                # save guest gprs 0-13
        lghi    %r2,-EFAULT
-       lmg     %r6,%r14,SP_R6(%r15)
+       lmg     %r6,%r14,__SF_GPRS(%r15)
        br      %r14
 
        .section __ex_table,"a"