189a83a0cSDaniel Axtens // SPDX-License-Identifier: GPL-2.0+
289a83a0cSDaniel Axtens
389a83a0cSDaniel Axtens /*
489a83a0cSDaniel Axtens * Copyright 2018 IBM Corporation.
589a83a0cSDaniel Axtens */
689a83a0cSDaniel Axtens
789a83a0cSDaniel Axtens #define __SANE_USERSPACE_TYPES__
889a83a0cSDaniel Axtens
989a83a0cSDaniel Axtens #include <sys/types.h>
1089a83a0cSDaniel Axtens #include <stdint.h>
1189a83a0cSDaniel Axtens #include <malloc.h>
1289a83a0cSDaniel Axtens #include <unistd.h>
1389a83a0cSDaniel Axtens #include <signal.h>
1489a83a0cSDaniel Axtens #include <stdlib.h>
1589a83a0cSDaniel Axtens #include <string.h>
1689a83a0cSDaniel Axtens #include <stdio.h>
1789a83a0cSDaniel Axtens #include "utils.h"
180d239f3bSDaniel Axtens #include "flush_utils.h"
1989a83a0cSDaniel Axtens
entry_flush_test(void)2089a83a0cSDaniel Axtens int entry_flush_test(void)
2189a83a0cSDaniel Axtens {
2289a83a0cSDaniel Axtens char *p;
2389a83a0cSDaniel Axtens int repetitions = 10;
2489a83a0cSDaniel Axtens int fd, passes = 0, iter, rc = 0;
2589a83a0cSDaniel Axtens struct perf_event_read v;
2689a83a0cSDaniel Axtens __u64 l1d_misses_total = 0;
2789a83a0cSDaniel Axtens unsigned long iterations = 100000, zero_size = 24 * 1024;
2889a83a0cSDaniel Axtens unsigned long l1d_misses_expected;
2989a83a0cSDaniel Axtens int rfi_flush_orig;
3089a83a0cSDaniel Axtens int entry_flush, entry_flush_orig;
3189a83a0cSDaniel Axtens
3289a83a0cSDaniel Axtens SKIP_IF(geteuid() != 0);
3389a83a0cSDaniel Axtens
3489a83a0cSDaniel Axtens // The PMU event we use only works on Power7 or later
3589a83a0cSDaniel Axtens SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06));
3689a83a0cSDaniel Axtens
37*121d340bSBenjamin Gray if (read_debugfs_int("powerpc/rfi_flush", &rfi_flush_orig) < 0) {
3889a83a0cSDaniel Axtens perror("Unable to read powerpc/rfi_flush debugfs file");
3989a83a0cSDaniel Axtens SKIP_IF(1);
4089a83a0cSDaniel Axtens }
4189a83a0cSDaniel Axtens
42*121d340bSBenjamin Gray if (read_debugfs_int("powerpc/entry_flush", &entry_flush_orig) < 0) {
4389a83a0cSDaniel Axtens perror("Unable to read powerpc/entry_flush debugfs file");
4489a83a0cSDaniel Axtens SKIP_IF(1);
4589a83a0cSDaniel Axtens }
4689a83a0cSDaniel Axtens
4789a83a0cSDaniel Axtens if (rfi_flush_orig != 0) {
48*121d340bSBenjamin Gray if (write_debugfs_int("powerpc/rfi_flush", 0) < 0) {
4989a83a0cSDaniel Axtens perror("error writing to powerpc/rfi_flush debugfs file");
5089a83a0cSDaniel Axtens FAIL_IF(1);
5189a83a0cSDaniel Axtens }
5289a83a0cSDaniel Axtens }
5389a83a0cSDaniel Axtens
5489a83a0cSDaniel Axtens entry_flush = entry_flush_orig;
5589a83a0cSDaniel Axtens
563a72c94eSRussell Currey fd = perf_event_open_counter(PERF_TYPE_HW_CACHE, PERF_L1D_READ_MISS_CONFIG, -1);
5789a83a0cSDaniel Axtens FAIL_IF(fd < 0);
5889a83a0cSDaniel Axtens
5989a83a0cSDaniel Axtens p = (char *)memalign(zero_size, CACHELINE_SIZE);
6089a83a0cSDaniel Axtens
6189a83a0cSDaniel Axtens FAIL_IF(perf_event_enable(fd));
6289a83a0cSDaniel Axtens
6389a83a0cSDaniel Axtens // disable L1 prefetching
6489a83a0cSDaniel Axtens set_dscr(1);
6589a83a0cSDaniel Axtens
6689a83a0cSDaniel Axtens iter = repetitions;
6789a83a0cSDaniel Axtens
6889a83a0cSDaniel Axtens /*
6989a83a0cSDaniel Axtens * We expect to see l1d miss for each cacheline access when entry_flush
7089a83a0cSDaniel Axtens * is set. Allow a small variation on this.
7189a83a0cSDaniel Axtens */
7289a83a0cSDaniel Axtens l1d_misses_expected = iterations * (zero_size / CACHELINE_SIZE - 2);
7389a83a0cSDaniel Axtens
7489a83a0cSDaniel Axtens again:
7589a83a0cSDaniel Axtens FAIL_IF(perf_event_reset(fd));
7689a83a0cSDaniel Axtens
7789a83a0cSDaniel Axtens syscall_loop(p, iterations, zero_size);
7889a83a0cSDaniel Axtens
7989a83a0cSDaniel Axtens FAIL_IF(read(fd, &v, sizeof(v)) != sizeof(v));
8089a83a0cSDaniel Axtens
8189a83a0cSDaniel Axtens if (entry_flush && v.l1d_misses >= l1d_misses_expected)
8289a83a0cSDaniel Axtens passes++;
8389a83a0cSDaniel Axtens else if (!entry_flush && v.l1d_misses < (l1d_misses_expected / 2))
8489a83a0cSDaniel Axtens passes++;
8589a83a0cSDaniel Axtens
8689a83a0cSDaniel Axtens l1d_misses_total += v.l1d_misses;
8789a83a0cSDaniel Axtens
8889a83a0cSDaniel Axtens while (--iter)
8989a83a0cSDaniel Axtens goto again;
9089a83a0cSDaniel Axtens
9189a83a0cSDaniel Axtens if (passes < repetitions) {
9289a83a0cSDaniel Axtens printf("FAIL (L1D misses with entry_flush=%d: %llu %c %lu) [%d/%d failures]\n",
9389a83a0cSDaniel Axtens entry_flush, l1d_misses_total, entry_flush ? '<' : '>',
9489a83a0cSDaniel Axtens entry_flush ? repetitions * l1d_misses_expected :
9589a83a0cSDaniel Axtens repetitions * l1d_misses_expected / 2,
9689a83a0cSDaniel Axtens repetitions - passes, repetitions);
9789a83a0cSDaniel Axtens rc = 1;
9889a83a0cSDaniel Axtens } else {
9989a83a0cSDaniel Axtens printf("PASS (L1D misses with entry_flush=%d: %llu %c %lu) [%d/%d pass]\n",
10089a83a0cSDaniel Axtens entry_flush, l1d_misses_total, entry_flush ? '>' : '<',
10189a83a0cSDaniel Axtens entry_flush ? repetitions * l1d_misses_expected :
10289a83a0cSDaniel Axtens repetitions * l1d_misses_expected / 2,
10389a83a0cSDaniel Axtens passes, repetitions);
10489a83a0cSDaniel Axtens }
10589a83a0cSDaniel Axtens
10689a83a0cSDaniel Axtens if (entry_flush == entry_flush_orig) {
10789a83a0cSDaniel Axtens entry_flush = !entry_flush_orig;
108*121d340bSBenjamin Gray if (write_debugfs_int("powerpc/entry_flush", entry_flush) < 0) {
10989a83a0cSDaniel Axtens perror("error writing to powerpc/entry_flush debugfs file");
11089a83a0cSDaniel Axtens return 1;
11189a83a0cSDaniel Axtens }
11289a83a0cSDaniel Axtens iter = repetitions;
11389a83a0cSDaniel Axtens l1d_misses_total = 0;
11489a83a0cSDaniel Axtens passes = 0;
11589a83a0cSDaniel Axtens goto again;
11689a83a0cSDaniel Axtens }
11789a83a0cSDaniel Axtens
11889a83a0cSDaniel Axtens perf_event_disable(fd);
11989a83a0cSDaniel Axtens close(fd);
12089a83a0cSDaniel Axtens
12189a83a0cSDaniel Axtens set_dscr(0);
12289a83a0cSDaniel Axtens
123*121d340bSBenjamin Gray if (write_debugfs_int("powerpc/rfi_flush", rfi_flush_orig) < 0) {
12489a83a0cSDaniel Axtens perror("unable to restore original value of powerpc/rfi_flush debugfs file");
12589a83a0cSDaniel Axtens return 1;
12689a83a0cSDaniel Axtens }
12789a83a0cSDaniel Axtens
128*121d340bSBenjamin Gray if (write_debugfs_int("powerpc/entry_flush", entry_flush_orig) < 0) {
12989a83a0cSDaniel Axtens perror("unable to restore original value of powerpc/entry_flush debugfs file");
13089a83a0cSDaniel Axtens return 1;
13189a83a0cSDaniel Axtens }
13289a83a0cSDaniel Axtens
13389a83a0cSDaniel Axtens return rc;
13489a83a0cSDaniel Axtens }
13589a83a0cSDaniel Axtens
main(int argc,char * argv[])13689a83a0cSDaniel Axtens int main(int argc, char *argv[])
13789a83a0cSDaniel Axtens {
13889a83a0cSDaniel Axtens return test_harness(entry_flush_test, "entry_flush_test");
13989a83a0cSDaniel Axtens }
140