Commit f6e9d014 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull s390 fixes from Alexander Gordeev:

 - Fix perf stat accounting for cryptography counters when multiple
   events are installed concurrently.

 - Prevent installation of unsupported perf events for cryptography
   counters.

 - Treat perf events cpum_cf/CPU_CYCLES/ and cpu_cf/INSTRUCTIONS/
   identical to basic events CPU_CYCLES" and INSTRUCTIONS, since they
   address the same hardware.

 - Restore kcrash operation which was broken by commit 5d8de293
   ("vmcore: convert copy_oldmem_page() to take an iov_iter").

* tag 's390-5.19-4' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
  s390/pai: Fix multiple concurrent event installation
  s390/pai: Prevent invalid event number for pai_crypto PMU
  s390/cpumf: Handle events cycles and instructions identical
  s390/crash: make copy_oldmem_page() return number of bytes copied
  s390/crash: add missing iterator advance in copy_oldmem_page()
parents 2c39d612 21e87644
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -219,6 +219,11 @@ ssize_t copy_oldmem_page(struct iov_iter *iter, unsigned long pfn, size_t csize,
	unsigned long src;
	int rc;

	if (!(iter_is_iovec(iter) || iov_iter_is_kvec(iter)))
		return -EINVAL;
	/* Multi-segment iterators are not supported */
	if (iter->nr_segs > 1)
		return -EINVAL;
	if (!csize)
		return 0;
	src = pfn_to_phys(pfn) + offset;
@@ -228,7 +233,10 @@ ssize_t copy_oldmem_page(struct iov_iter *iter, unsigned long pfn, size_t csize,
		rc = copy_oldmem_user(iter->iov->iov_base, src, csize);
	else
		rc = copy_oldmem_kernel(iter->kvec->iov_base, src, csize);
	if (rc < 0)
		return rc;
	iov_iter_advance(iter, csize);
	return csize;
}

/*
+21 −1
Original line number Diff line number Diff line
@@ -516,6 +516,26 @@ static int __hw_perf_event_init(struct perf_event *event, unsigned int type)
	return err;
}

/* Events CPU_CYLCES and INSTRUCTIONS can be submitted with two different
 * attribute::type values:
 * - PERF_TYPE_HARDWARE:
 * - pmu->type:
 * Handle both type of invocations identical. They address the same hardware.
 * The result is different when event modifiers exclude_kernel and/or
 * exclude_user are also set.
 */
static int cpumf_pmu_event_type(struct perf_event *event)
{
	u64 ev = event->attr.config;

	if (cpumf_generic_events_basic[PERF_COUNT_HW_CPU_CYCLES] == ev ||
	    cpumf_generic_events_basic[PERF_COUNT_HW_INSTRUCTIONS] == ev ||
	    cpumf_generic_events_user[PERF_COUNT_HW_CPU_CYCLES] == ev ||
	    cpumf_generic_events_user[PERF_COUNT_HW_INSTRUCTIONS] == ev)
		return PERF_TYPE_HARDWARE;
	return PERF_TYPE_RAW;
}

static int cpumf_pmu_event_init(struct perf_event *event)
{
	unsigned int type = event->attr.type;
@@ -525,7 +545,7 @@ static int cpumf_pmu_event_init(struct perf_event *event)
		err = __hw_perf_event_init(event, type);
	else if (event->pmu->type == type)
		/* Registered as unknown PMU */
		err = __hw_perf_event_init(event, PERF_TYPE_RAW);
		err = __hw_perf_event_init(event, cpumf_pmu_event_type(event));
	else
		return -ENOENT;

+15 −5
Original line number Diff line number Diff line
@@ -193,8 +193,9 @@ static int paicrypt_event_init(struct perf_event *event)
	/* PAI crypto PMU registered as PERF_TYPE_RAW, check event type */
	if (a->type != PERF_TYPE_RAW && event->pmu->type != a->type)
		return -ENOENT;
	/* PAI crypto event must be valid */
	if (a->config > PAI_CRYPTO_BASE + paicrypt_cnt)
	/* PAI crypto event must be in valid range */
	if (a->config < PAI_CRYPTO_BASE ||
	    a->config > PAI_CRYPTO_BASE + paicrypt_cnt)
		return -EINVAL;
	/* Allow only CPU wide operation, no process context for now. */
	if (event->hw.target || event->cpu == -1)
@@ -208,6 +209,12 @@ static int paicrypt_event_init(struct perf_event *event)
	if (rc)
		return rc;

	/* Event initialization sets last_tag to 0. When later on the events
	 * are deleted and re-added, do not reset the event count value to zero.
	 * Events are added, deleted and re-added when 2 or more events
	 * are active at the same time.
	 */
	event->hw.last_tag = 0;
	cpump->event = event;
	event->destroy = paicrypt_event_destroy;

@@ -242,9 +249,12 @@ static void paicrypt_start(struct perf_event *event, int flags)
{
	u64 sum;

	if (!event->hw.last_tag) {
		event->hw.last_tag = 1;
		sum = paicrypt_getall(event);		/* Get current value */
	local64_set(&event->hw.prev_count, sum);
		local64_set(&event->count, 0);
		local64_set(&event->hw.prev_count, sum);
	}
}

static int paicrypt_add(struct perf_event *event, int flags)