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