[S390] virtualization aware cpu measurement
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>
This commit is contained in:
parent
6377981faf
commit
cd3b70f5d4
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
||||
SP_R5 = 5 * 8 # offset into stackframe
|
||||
SP_R6 = 6 * 8
|
||||
_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
|
||||
|
||||
|
||||
.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"
|
||||
|
|
Loading…
Reference in New Issue