Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fcc77f50 authored by Hendrik Brueckner's avatar Hendrik Brueckner Committed by Martin Schwidefsky
Browse files

s390/cpum_sf: Atomically reset trailer entry fields of sample-data-blocks



Ensure to reset the sample-data-block full indicator and the overflow counter
at the same time.  This must be done atomically because the sampling hardware
is still active while full sample-data-block is processed.

Signed-off-by: default avatarHendrik Brueckner <brueckner@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 69f239ed
Loading
Loading
Loading
Loading
+9 −4
Original line number Diff line number Diff line
@@ -115,10 +115,15 @@ struct hws_data_entry {
} __packed;

struct hws_trailer_entry {
	union {
		struct {
			unsigned int f:1;	/* 0 - Block Full Indicator   */
			unsigned int a:1;	/* 1 - Alert request control  */
			unsigned int t:1;	/* 2 - Timestamp format	      */
			unsigned long long:61;	/* 3 - 63: Reserved	      */
		};
		unsigned long long flags;	/* 0 - 63: All indicators     */
	};
	unsigned long long overflow;	 /* 64 - sample Overflow count	      */
	unsigned long long timestamp;	 /* 16 - time-stamp		      */
	unsigned long long timestamp1;	 /*				      */
+8 −4
Original line number Diff line number Diff line
@@ -953,7 +953,7 @@ static void hw_perf_event_update(struct perf_event *event, int flush_all)
	struct hw_perf_event *hwc = &event->hw;
	struct hws_trailer_entry *te;
	unsigned long *sdbt;
	unsigned long long event_overflow, sampl_overflow, num_sdb;
	unsigned long long event_overflow, sampl_overflow, num_sdb, te_flags;
	int done;

	sdbt = (unsigned long *) TEAR_REG(hwc);
@@ -990,9 +990,13 @@ static void hw_perf_event_update(struct perf_event *event, int flush_all)
		hw_collect_samples(event, sdbt, &event_overflow);
		num_sdb++;

		/* Reset trailer */
		xchg(&te->overflow, 0);
		xchg((unsigned char *) te, 0x40);
		/* Reset trailer (using compare-double-and-swap) */
		do {
			te_flags = te->flags & ~SDB_TE_BUFFER_FULL_MASK;
			te_flags |= SDB_TE_ALERT_REQ_MASK;
		} while (!cmpxchg_double(&te->flags, &te->overflow,
					 te->flags, te->overflow,
					 te_flags, 0ULL));

		/* Advance to next sample-data-block */
		sdbt++;