aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHendrik Brueckner <brueckner@linux.vnet.ibm.com>2013-12-12 11:54:57 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2013-12-16 08:37:59 -0500
commit443e802bab16916f9a51a34f2213f4dee6e8762c (patch)
tree8481d35917b96ad1dfee837e52ad804e3459e018
parent443d4beb823d4dccaaf964b59df9dd38b4d6aae7 (diff)
s390/cpum_sf: Detect KVM guest samples
The host-program-parameter (hpp) value of basic sample-data-entries designates a SIE control block that is set by the LPP instruction in sie64a(). Non-zero values indicate guest samples, a value of zero indicates a host sample. For perf samples, host and guest samples are distinguished using particular PERF_MISC_* flags. The perf layer calls perf_misc_flags() to set the flags based on the pt_regs content. For each sample-data-entry, the cpum_sf PMU creates a pt_regs structure with the sample-data information. An additional flag structure is added to easily distinguish between host and guest samples. Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--arch/s390/include/asm/perf_event.h6
-rw-r--r--arch/s390/kernel/perf_cpum_sf.c20
-rw-r--r--arch/s390/kernel/perf_event.c25
3 files changed, 50 insertions, 1 deletions
diff --git a/arch/s390/include/asm/perf_event.h b/arch/s390/include/asm/perf_event.h
index 99d7f4e333c2..7667bde37dcb 100644
--- a/arch/s390/include/asm/perf_event.h
+++ b/arch/s390/include/asm/perf_event.h
@@ -42,6 +42,12 @@ extern unsigned long perf_instruction_pointer(struct pt_regs *regs);
42extern unsigned long perf_misc_flags(struct pt_regs *regs); 42extern unsigned long perf_misc_flags(struct pt_regs *regs);
43#define perf_misc_flags(regs) perf_misc_flags(regs) 43#define perf_misc_flags(regs) perf_misc_flags(regs)
44 44
45/* Perf pt_regs extension for sample-data-entry indicators */
46struct perf_sf_sde_regs {
47 unsigned char in_guest:1; /* guest sample */
48 unsigned long reserved:63; /* reserved */
49};
50
45/* Perf PMU definitions for the counter facility */ 51/* Perf PMU definitions for the counter facility */
46#define PERF_CPUM_CF_MAX_CTR 256 52#define PERF_CPUM_CF_MAX_CTR 256
47 53
diff --git a/arch/s390/kernel/perf_cpum_sf.c b/arch/s390/kernel/perf_cpum_sf.c
index 3ab7e67ee2e4..d611facae599 100644
--- a/arch/s390/kernel/perf_cpum_sf.c
+++ b/arch/s390/kernel/perf_cpum_sf.c
@@ -840,6 +840,7 @@ static int perf_push_sample(struct perf_event *event,
840{ 840{
841 int overflow; 841 int overflow;
842 struct pt_regs regs; 842 struct pt_regs regs;
843 struct perf_sf_sde_regs *sde_regs;
843 struct perf_sample_data data; 844 struct perf_sample_data data;
844 845
845 /* Skip samples that are invalid or for which the instruction address 846 /* Skip samples that are invalid or for which the instruction address
@@ -850,7 +851,16 @@ static int perf_push_sample(struct perf_event *event,
850 851
851 perf_sample_data_init(&data, 0, event->hw.last_period); 852 perf_sample_data_init(&data, 0, event->hw.last_period);
852 853
854 /* Setup pt_regs to look like an CPU-measurement external interrupt
855 * using the Program Request Alert code. The regs.int_parm_long
856 * field which is unused contains additional sample-data-entry related
857 * indicators.
858 */
853 memset(&regs, 0, sizeof(regs)); 859 memset(&regs, 0, sizeof(regs));
860 regs.int_code = 0x1407;
861 regs.int_parm = CPU_MF_INT_SF_PRA;
862 sde_regs = (struct perf_sf_sde_regs *) &regs.int_parm_long;
863
854 regs.psw.addr = sample->ia; 864 regs.psw.addr = sample->ia;
855 if (sample->T) 865 if (sample->T)
856 regs.psw.mask |= PSW_MASK_DAT; 866 regs.psw.mask |= PSW_MASK_DAT;
@@ -873,6 +883,16 @@ static int perf_push_sample(struct perf_event *event,
873 break; 883 break;
874 } 884 }
875 885
886 /* The host-program-parameter (hpp) contains the sie control
887 * block that is set by sie64a() in entry64.S. Check if hpp
888 * refers to a valid control block and set sde_regs flags
889 * accordingly. This would allow to use hpp values for other
890 * purposes too.
891 * For now, simply use a non-zero value as guest indicator.
892 */
893 if (sample->hpp)
894 sde_regs->in_guest = 1;
895
876 overflow = 0; 896 overflow = 0;
877 if (perf_event_overflow(event, &data, &regs)) { 897 if (perf_event_overflow(event, &data, &regs)) {
878 overflow = 1; 898 overflow = 1;
diff --git a/arch/s390/kernel/perf_event.c b/arch/s390/kernel/perf_event.c
index 3bd2bf030ad4..60a68261d091 100644
--- a/arch/s390/kernel/perf_event.c
+++ b/arch/s390/kernel/perf_event.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Performance event support for s390x 2 * Performance event support for s390x
3 * 3 *
4 * Copyright IBM Corp. 2012 4 * Copyright IBM Corp. 2012, 2013
5 * Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com> 5 * Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
@@ -89,8 +89,31 @@ static unsigned long perf_misc_guest_flags(struct pt_regs *regs)
89 : PERF_RECORD_MISC_GUEST_KERNEL; 89 : PERF_RECORD_MISC_GUEST_KERNEL;
90} 90}
91 91
92static unsigned long perf_misc_flags_sf(struct pt_regs *regs)
93{
94 struct perf_sf_sde_regs *sde_regs;
95 unsigned long flags;
96
97 sde_regs = (struct perf_sf_sde_regs *) &regs->int_parm_long;
98 if (sde_regs->in_guest)
99 flags = user_mode(regs) ? PERF_RECORD_MISC_GUEST_USER
100 : PERF_RECORD_MISC_GUEST_KERNEL;
101 else
102 flags = user_mode(regs) ? PERF_RECORD_MISC_USER
103 : PERF_RECORD_MISC_KERNEL;
104 return flags;
105}
106
92unsigned long perf_misc_flags(struct pt_regs *regs) 107unsigned long perf_misc_flags(struct pt_regs *regs)
93{ 108{
109 /* Check if the cpum_sf PMU has created the pt_regs structure.
110 * In this case, perf misc flags can be easily extracted. Otherwise,
111 * do regular checks on the pt_regs content.
112 */
113 if (regs->int_code == 0x1407 && regs->int_parm == CPU_MF_INT_SF_PRA)
114 if (!regs->gprs[15])
115 return perf_misc_flags_sf(regs);
116
94 if (is_in_guest(regs)) 117 if (is_in_guest(regs))
95 return perf_misc_guest_flags(regs); 118 return perf_misc_guest_flags(regs);
96 119