File Index
Files and directories
Sign in
FILE

entry_flush.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/powerpc/security/entry_flush.c C
  1// SPDX-License-Identifier: GPL-2.0+
  2
  3/*
  4 * Copyright 2018 IBM Corporation.
  5 */
  6
  7#define __SANE_USERSPACE_TYPES__
  8
  9#include <sys/types.h>
 10#include <stdint.h>
 11#include <malloc.h>
 12#include <unistd.h>
 13#include <signal.h>
 14#include <stdlib.h>
 15#include <string.h>
 16#include <stdio.h>
 17#include "utils.h"
 18#include "flush_utils.h"
 19
 20int entry_flush_test(void)
 21{
 22	char *p;
 23	int repetitions = 10;
 24	int fd, passes = 0, iter, rc = 0;
 25	struct perf_event_read v;
 26	__u64 l1d_misses_total = 0;
 27	unsigned long iterations = 100000, zero_size = 24 * 1024;
 28	unsigned long l1d_misses_expected;
 29	int rfi_flush_orig;
 30	int entry_flush, entry_flush_orig;
 31
 32	SKIP_IF(geteuid() != 0);
 33
 34	// The PMU event we use only works on Power7 or later
 35	SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06));
 36
 37	if (read_debugfs_int("powerpc/rfi_flush", &rfi_flush_orig) < 0) {
 38		perror("Unable to read powerpc/rfi_flush debugfs file");
 39		SKIP_IF(1);
 40	}
 41
 42	if (read_debugfs_int("powerpc/entry_flush", &entry_flush_orig) < 0) {
 43		perror("Unable to read powerpc/entry_flush debugfs file");
 44		SKIP_IF(1);
 45	}
 46
 47	if (rfi_flush_orig != 0) {
 48		if (write_debugfs_int("powerpc/rfi_flush", 0) < 0) {
 49			perror("error writing to powerpc/rfi_flush debugfs file");
 50			FAIL_IF(1);
 51		}
 52	}
 53
 54	entry_flush = entry_flush_orig;
 55
 56	fd = perf_event_open_counter(PERF_TYPE_HW_CACHE, PERF_L1D_READ_MISS_CONFIG, -1);
 57	FAIL_IF(fd < 0);
 58
 59	p = (char *)memalign(zero_size, CACHELINE_SIZE);
 60
 61	FAIL_IF(perf_event_enable(fd));
 62
 63	// disable L1 prefetching
 64	set_dscr(1);
 65
 66	iter = repetitions;
 67
 68	/*
 69	 * We expect to see l1d miss for each cacheline access when entry_flush
 70	 * is set. Allow a small variation on this.
 71	 */
 72	l1d_misses_expected = iterations * (zero_size / CACHELINE_SIZE - 2);
 73
 74again:
 75	FAIL_IF(perf_event_reset(fd));
 76
 77	syscall_loop(p, iterations, zero_size);
 78
 79	FAIL_IF(read(fd, &v, sizeof(v)) != sizeof(v));
 80
 81	if (entry_flush && v.l1d_misses >= l1d_misses_expected)
 82		passes++;
 83	else if (!entry_flush && v.l1d_misses < (l1d_misses_expected / 2))
 84		passes++;
 85
 86	l1d_misses_total += v.l1d_misses;
 87
 88	while (--iter)
 89		goto again;
 90
 91	if (passes < repetitions) {
 92		printf("FAIL (L1D misses with entry_flush=%d: %llu %c %lu) [%d/%d failures]\n",
 93		       entry_flush, l1d_misses_total, entry_flush ? '<' : '>',
 94		       entry_flush ? repetitions * l1d_misses_expected :
 95		       repetitions * l1d_misses_expected / 2,
 96		       repetitions - passes, repetitions);
 97		rc = 1;
 98	} else {
 99		printf("PASS (L1D misses with entry_flush=%d: %llu %c %lu) [%d/%d pass]\n",
100		       entry_flush, l1d_misses_total, entry_flush ? '>' : '<',
101		       entry_flush ? repetitions * l1d_misses_expected :
102		       repetitions * l1d_misses_expected / 2,
103		       passes, repetitions);
104	}
105
106	if (entry_flush == entry_flush_orig) {
107		entry_flush = !entry_flush_orig;
108		if (write_debugfs_int("powerpc/entry_flush", entry_flush) < 0) {
109			perror("error writing to powerpc/entry_flush debugfs file");
110			return 1;
111		}
112		iter = repetitions;
113		l1d_misses_total = 0;
114		passes = 0;
115		goto again;
116	}
117
118	perf_event_disable(fd);
119	close(fd);
120
121	set_dscr(0);
122
123	if (write_debugfs_int("powerpc/rfi_flush", rfi_flush_orig) < 0) {
124		perror("unable to restore original value of powerpc/rfi_flush debugfs file");
125		return 1;
126	}
127
128	if (write_debugfs_int("powerpc/entry_flush", entry_flush_orig) < 0) {
129		perror("unable to restore original value of powerpc/entry_flush debugfs file");
130		return 1;
131	}
132
133	return rc;
134}
135
136int main(int argc, char *argv[])
137{
138	return test_harness(entry_flush_test, "entry_flush_test");
139}
~/ Read-only file preview.