Skip to content

Commit 3d43b98

Browse files
Pu HouMartin Schwidefsky
authored andcommitted
s390/cpumf: remove raw event support in basic-only sampling mode
Raw sample was implemented to export the diagnostic samples. With having this achieved with AUX buffers, there is no requirement for basic samples to export raw data. In particular, most basic sampling information are consumed for creating the perf event sample. Signed-off-by: Pu Hou <bjhoupu@linux.vnet.ibm.com> Reviewed-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
1 parent a3f22d5 commit 3d43b98

File tree

2 files changed

+27
-175
lines changed

2 files changed

+27
-175
lines changed

arch/s390/include/asm/perf_event.h

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -64,27 +64,10 @@ struct perf_sf_sde_regs {
6464
#define REG_OVERFLOW 1
6565
#define OVERFLOW_REG(hwc) ((hwc)->extra_reg.config)
6666
#define SFB_ALLOC_REG(hwc) ((hwc)->extra_reg.alloc)
67-
#define RAWSAMPLE_REG(hwc) ((hwc)->config)
6867
#define TEAR_REG(hwc) ((hwc)->last_tag)
6968
#define SAMPL_RATE(hwc) ((hwc)->event_base)
7069
#define SAMPL_FLAGS(hwc) ((hwc)->config_base)
7170
#define SAMPL_DIAG_MODE(hwc) (SAMPL_FLAGS(hwc) & PERF_CPUM_SF_DIAG_MODE)
7271
#define SDB_FULL_BLOCKS(hwc) (SAMPL_FLAGS(hwc) & PERF_CPUM_SF_FULL_BLOCKS)
7372

74-
/* Structure for sampling data entries to be passed as perf raw sample data
75-
* to user space. Note that raw sample data must be aligned and, thus, might
76-
* be padded with zeros.
77-
*/
78-
struct sf_raw_sample {
79-
#define SF_RAW_SAMPLE_BASIC PERF_CPUM_SF_BASIC_MODE
80-
#define SF_RAW_SAMPLE_DIAG PERF_CPUM_SF_DIAG_MODE
81-
u64 format;
82-
u32 size; /* Size of sf_raw_sample */
83-
u16 bsdes; /* Basic-sampling data entry size */
84-
u16 dsdes; /* Diagnostic-sampling data entry size */
85-
struct hws_basic_entry basic; /* Basic-sampling data entry */
86-
struct hws_diag_entry diag; /* Diagnostic-sampling data entry */
87-
u8 padding[]; /* Padding to next multiple of 8 */
88-
} __packed;
89-
9073
#endif /* _ASM_S390_PERF_EVENT_H */

arch/s390/kernel/perf_cpum_sf.c

Lines changed: 27 additions & 158 deletions
Original file line numberDiff line numberDiff line change
@@ -351,22 +351,6 @@ static void sfb_init_allocs(unsigned long num, struct hw_perf_event *hwc)
351351
sfb_account_allocs(num, hwc);
352352
}
353353

354-
static size_t event_sample_size(struct hw_perf_event *hwc)
355-
{
356-
struct sf_raw_sample *sfr = (struct sf_raw_sample *) RAWSAMPLE_REG(hwc);
357-
size_t sample_size;
358-
359-
/* The sample size depends on the sampling function: The basic-sampling
360-
* function must be always enabled, diagnostic-sampling function is
361-
* optional.
362-
*/
363-
sample_size = sfr->bsdes;
364-
if (SAMPL_DIAG_MODE(hwc))
365-
sample_size += sfr->dsdes;
366-
367-
return sample_size;
368-
}
369-
370354
static void deallocate_buffers(struct cpu_hw_sf *cpuhw)
371355
{
372356
if (cpuhw->sfb.sdbt)
@@ -376,35 +360,7 @@ static void deallocate_buffers(struct cpu_hw_sf *cpuhw)
376360
static int allocate_buffers(struct cpu_hw_sf *cpuhw, struct hw_perf_event *hwc)
377361
{
378362
unsigned long n_sdb, freq, factor;
379-
size_t sfr_size, sample_size;
380-
struct sf_raw_sample *sfr;
381-
382-
/* Allocate raw sample buffer
383-
*
384-
* The raw sample buffer is used to temporarily store sampling data
385-
* entries for perf raw sample processing. The buffer size mainly
386-
* depends on the size of diagnostic-sampling data entries which is
387-
* machine-specific. The exact size calculation includes:
388-
* 1. The first 4 bytes of diagnostic-sampling data entries are
389-
* already reflected in the sf_raw_sample structure. Subtract
390-
* these bytes.
391-
* 2. The perf raw sample data must be 8-byte aligned (u64) and
392-
* perf's internal data size must be considered too. So add
393-
* an additional u32 for correct alignment and subtract before
394-
* allocating the buffer.
395-
* 3. Store the raw sample buffer pointer in the perf event
396-
* hardware structure.
397-
*/
398-
sfr_size = ALIGN((sizeof(*sfr) - sizeof(sfr->diag) + cpuhw->qsi.dsdes) +
399-
sizeof(u32), sizeof(u64));
400-
sfr_size -= sizeof(u32);
401-
sfr = kzalloc(sfr_size, GFP_KERNEL);
402-
if (!sfr)
403-
return -ENOMEM;
404-
sfr->size = sfr_size;
405-
sfr->bsdes = cpuhw->qsi.bsdes;
406-
sfr->dsdes = cpuhw->qsi.dsdes;
407-
RAWSAMPLE_REG(hwc) = (unsigned long) sfr;
363+
size_t sample_size;
408364

409365
/* Calculate sampling buffers using 4K pages
410366
*
@@ -430,7 +386,7 @@ static int allocate_buffers(struct cpu_hw_sf *cpuhw, struct hw_perf_event *hwc)
430386
* ensure a minimum of CPUM_SF_MIN_SDBT (one table can manage up
431387
* to 511 SDBs).
432388
*/
433-
sample_size = event_sample_size(hwc);
389+
sample_size = sizeof(struct hws_basic_entry);
434390
freq = sample_rate_to_freq(&cpuhw->qsi, SAMPL_RATE(hwc));
435391
factor = 1;
436392
n_sdb = DIV_ROUND_UP(freq, factor * ((PAGE_SIZE-64) / sample_size));
@@ -629,10 +585,6 @@ static int reserve_pmc_hardware(void)
629585

630586
static void hw_perf_event_destroy(struct perf_event *event)
631587
{
632-
/* Free raw sample buffer */
633-
if (RAWSAMPLE_REG(&event->hw))
634-
kfree((void *) RAWSAMPLE_REG(&event->hw));
635-
636588
/* Release PMC if this is the last perf event */
637589
if (!atomic_add_unless(&num_events, -1, 1)) {
638590
mutex_lock(&pmc_reserve_mutex);
@@ -652,15 +604,8 @@ static void hw_init_period(struct hw_perf_event *hwc, u64 period)
652604
static void hw_reset_registers(struct hw_perf_event *hwc,
653605
unsigned long *sdbt_origin)
654606
{
655-
struct sf_raw_sample *sfr;
656-
657607
/* (Re)set to first sample-data-block-table */
658608
TEAR_REG(hwc) = (unsigned long) sdbt_origin;
659-
660-
/* (Re)set raw sampling buffer register */
661-
sfr = (struct sf_raw_sample *) RAWSAMPLE_REG(hwc);
662-
memset(&sfr->basic, 0, sizeof(sfr->basic));
663-
memset(&sfr->diag, 0, sfr->dsdes);
664609
}
665610

666611
static unsigned long hw_limit_rate(const struct hws_qsi_info_block *si,
@@ -986,22 +931,16 @@ static int perf_exclude_event(struct perf_event *event, struct pt_regs *regs,
986931
*
987932
* Return non-zero if an event overflow occurred.
988933
*/
989-
static int perf_push_sample(struct perf_event *event, struct sf_raw_sample *sfr)
934+
static int perf_push_sample(struct perf_event *event,
935+
struct hws_basic_entry *basic)
990936
{
991937
int overflow;
992938
struct pt_regs regs;
993939
struct perf_sf_sde_regs *sde_regs;
994940
struct perf_sample_data data;
995-
struct perf_raw_record raw = {
996-
.frag = {
997-
.size = sfr->size,
998-
.data = sfr,
999-
},
1000-
};
1001941

1002942
/* Setup perf sample */
1003943
perf_sample_data_init(&data, 0, event->hw.last_period);
1004-
data.raw = &raw;
1005944

1006945
/* Setup pt_regs to look like an CPU-measurement external interrupt
1007946
* using the Program Request Alert code. The regs.int_parm_long
@@ -1013,11 +952,11 @@ static int perf_push_sample(struct perf_event *event, struct sf_raw_sample *sfr)
1013952
regs.int_parm = CPU_MF_INT_SF_PRA;
1014953
sde_regs = (struct perf_sf_sde_regs *) &regs.int_parm_long;
1015954

1016-
psw_bits(regs.psw).ia = sfr->basic.ia;
1017-
psw_bits(regs.psw).dat = sfr->basic.T;
1018-
psw_bits(regs.psw).wait = sfr->basic.W;
1019-
psw_bits(regs.psw).pstate = sfr->basic.P;
1020-
psw_bits(regs.psw).as = sfr->basic.AS;
955+
psw_bits(regs.psw).ia = basic->ia;
956+
psw_bits(regs.psw).dat = basic->T;
957+
psw_bits(regs.psw).wait = basic->W;
958+
psw_bits(regs.psw).pstate = basic->P;
959+
psw_bits(regs.psw).as = basic->AS;
1021960

1022961
/*
1023962
* Use the hardware provided configuration level to decide if the
@@ -1030,15 +969,15 @@ static int perf_push_sample(struct perf_event *event, struct sf_raw_sample *sfr)
1030969
* If the value differs from 0xffff (the host value), we assume to
1031970
* be a KVM guest.
1032971
*/
1033-
switch (sfr->basic.CL) {
972+
switch (basic->CL) {
1034973
case 1: /* logical partition */
1035974
sde_regs->in_guest = 0;
1036975
break;
1037976
case 2: /* virtual machine */
1038977
sde_regs->in_guest = 1;
1039978
break;
1040979
default: /* old machine, use heuristics */
1041-
if (sfr->basic.gpp || sfr->basic.prim_asn != 0xffff)
980+
if (basic->gpp || basic->prim_asn != 0xffff)
1042981
sde_regs->in_guest = 1;
1043982
break;
1044983
}
@@ -1060,75 +999,12 @@ static void perf_event_count_update(struct perf_event *event, u64 count)
1060999
local64_add(count, &event->count);
10611000
}
10621001

1063-
static int sample_format_is_valid(struct hws_combined_entry *sample,
1064-
unsigned int flags)
1065-
{
1066-
if (likely(flags & PERF_CPUM_SF_BASIC_MODE))
1067-
/* Only basic-sampling data entries with data-entry-format
1068-
* version of 0x0001 can be processed.
1069-
*/
1070-
if (sample->basic.def != 0x0001)
1071-
return 0;
1072-
if (flags & PERF_CPUM_SF_DIAG_MODE)
1073-
/* The data-entry-format number of diagnostic-sampling data
1074-
* entries can vary. Because diagnostic data is just passed
1075-
* through, do only a sanity check on the DEF.
1076-
*/
1077-
if (sample->diag.def < 0x8001)
1078-
return 0;
1079-
return 1;
1080-
}
1081-
1082-
static int sample_is_consistent(struct hws_combined_entry *sample,
1083-
unsigned long flags)
1084-
{
1085-
/* This check applies only to basic-sampling data entries of potentially
1086-
* combined-sampling data entries. Invalid entries cannot be processed
1087-
* by the PMU and, thus, do not deliver an associated
1088-
* diagnostic-sampling data entry.
1089-
*/
1090-
if (unlikely(!(flags & PERF_CPUM_SF_BASIC_MODE)))
1091-
return 0;
1092-
/*
1093-
* Samples are skipped, if they are invalid or for which the
1094-
* instruction address is not predictable, i.e., the wait-state bit is
1095-
* set.
1096-
*/
1097-
if (sample->basic.I || sample->basic.W)
1098-
return 0;
1099-
return 1;
1100-
}
1101-
1102-
static void reset_sample_slot(struct hws_combined_entry *sample,
1103-
unsigned long flags)
1104-
{
1105-
if (likely(flags & PERF_CPUM_SF_BASIC_MODE))
1106-
sample->basic.def = 0;
1107-
if (flags & PERF_CPUM_SF_DIAG_MODE)
1108-
sample->diag.def = 0;
1109-
}
1110-
1111-
static void sfr_store_sample(struct sf_raw_sample *sfr,
1112-
struct hws_combined_entry *sample)
1113-
{
1114-
if (likely(sfr->format & PERF_CPUM_SF_BASIC_MODE))
1115-
sfr->basic = sample->basic;
1116-
if (sfr->format & PERF_CPUM_SF_DIAG_MODE)
1117-
memcpy(&sfr->diag, &sample->diag, sfr->dsdes);
1118-
}
1119-
1120-
static void debug_sample_entry(struct hws_combined_entry *sample,
1121-
struct hws_trailer_entry *te,
1122-
unsigned long flags)
1002+
static void debug_sample_entry(struct hws_basic_entry *sample,
1003+
struct hws_trailer_entry *te)
11231004
{
11241005
debug_sprintf_event(sfdbg, 4, "hw_collect_samples: Found unknown "
1125-
"sampling data entry: te->f=%i basic.def=%04x (%p)"
1126-
" diag.def=%04x (%p)\n", te->f,
1127-
sample->basic.def, &sample->basic,
1128-
(flags & PERF_CPUM_SF_DIAG_MODE)
1129-
? sample->diag.def : 0xFFFF,
1130-
(flags & PERF_CPUM_SF_DIAG_MODE)
1131-
? &sample->diag : NULL);
1006+
"sampling data entry: te->f=%i basic.def=%04x (%p)\n",
1007+
te->f, sample->def, sample);
11321008
}
11331009

11341010
/* hw_collect_samples() - Walk through a sample-data-block and collect samples
@@ -1154,44 +1030,37 @@ static void debug_sample_entry(struct hws_combined_entry *sample,
11541030
static void hw_collect_samples(struct perf_event *event, unsigned long *sdbt,
11551031
unsigned long long *overflow)
11561032
{
1157-
unsigned long flags = SAMPL_FLAGS(&event->hw);
1158-
struct hws_combined_entry *sample;
11591033
struct hws_trailer_entry *te;
1160-
struct sf_raw_sample *sfr;
1161-
size_t sample_size;
1162-
1163-
/* Prepare and initialize raw sample data */
1164-
sfr = (struct sf_raw_sample *) RAWSAMPLE_REG(&event->hw);
1165-
sfr->format = flags & PERF_CPUM_SF_MODE_MASK;
1034+
struct hws_basic_entry *sample;
11661035

1167-
sample_size = event_sample_size(&event->hw);
11681036
te = (struct hws_trailer_entry *) trailer_entry_ptr(*sdbt);
1169-
sample = (struct hws_combined_entry *) *sdbt;
1037+
sample = (struct hws_basic_entry *) *sdbt;
11701038
while ((unsigned long *) sample < (unsigned long *) te) {
11711039
/* Check for an empty sample */
1172-
if (!sample->basic.def)
1040+
if (!sample->def)
11731041
break;
11741042

11751043
/* Update perf event period */
11761044
perf_event_count_update(event, SAMPL_RATE(&event->hw));
11771045

1178-
/* Check sampling data entry */
1179-
if (sample_format_is_valid(sample, flags)) {
1046+
/* Check whether sample is valid */
1047+
if (sample->def == 0x0001) {
11801048
/* If an event overflow occurred, the PMU is stopped to
11811049
* throttle event delivery. Remaining sample data is
11821050
* discarded.
11831051
*/
11841052
if (!*overflow) {
1185-
if (sample_is_consistent(sample, flags)) {
1053+
/* Check whether sample is consistent */
1054+
if (sample->I == 0 && sample->W == 0) {
11861055
/* Deliver sample data to perf */
1187-
sfr_store_sample(sfr, sample);
1188-
*overflow = perf_push_sample(event, sfr);
1056+
*overflow = perf_push_sample(event,
1057+
sample);
11891058
}
11901059
} else
11911060
/* Count discarded samples */
11921061
*overflow += 1;
11931062
} else {
1194-
debug_sample_entry(sample, te, flags);
1063+
debug_sample_entry(sample, te);
11951064
/* Sample slot is not yet written or other record.
11961065
*
11971066
* This condition can occur if the buffer was reused
@@ -1207,8 +1076,8 @@ static void hw_collect_samples(struct perf_event *event, unsigned long *sdbt,
12071076
}
12081077

12091078
/* Reset sample slot and advance to next sample */
1210-
reset_sample_slot(sample, flags);
1211-
sample += sample_size;
1079+
sample->def = 0;
1080+
sample++;
12121081
}
12131082
}
12141083

0 commit comments

Comments
 (0)