1 // SPDX-License-Identifier: GPL-2.0 1 // SPDX-License-Identifier: GPL-2.0 2 /* 2 /* 3 * fill_buf benchmark 3 * fill_buf benchmark 4 * 4 * 5 * Copyright (C) 2018 Intel Corporation 5 * Copyright (C) 2018 Intel Corporation 6 * 6 * 7 * Authors: 7 * Authors: 8 * Sai Praneeth Prakhya <sai.praneeth.prakh 8 * Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>, 9 * Fenghua Yu <fenghua.yu@intel.com> 9 * Fenghua Yu <fenghua.yu@intel.com> 10 */ 10 */ 11 #include <stdio.h> 11 #include <stdio.h> 12 #include <unistd.h> 12 #include <unistd.h> 13 #include <stdlib.h> 13 #include <stdlib.h> 14 #include <sys/types.h> 14 #include <sys/types.h> 15 #include <sys/wait.h> 15 #include <sys/wait.h> 16 #include <inttypes.h> 16 #include <inttypes.h> >> 17 #include <malloc.h> 17 #include <string.h> 18 #include <string.h> 18 19 19 #include "resctrl.h" 20 #include "resctrl.h" 20 21 21 #define CL_SIZE (64) 22 #define CL_SIZE (64) 22 #define PAGE_SIZE (4 * 1024) 23 #define PAGE_SIZE (4 * 1024) 23 #define MB (1024 * 1024) 24 #define MB (1024 * 1024) 24 25 >> 26 static unsigned char *startptr; >> 27 25 static void sb(void) 28 static void sb(void) 26 { 29 { 27 #if defined(__i386) || defined(__x86_64) 30 #if defined(__i386) || defined(__x86_64) 28 asm volatile("sfence\n\t" 31 asm volatile("sfence\n\t" 29 : : : "memory"); 32 : : : "memory"); 30 #endif 33 #endif 31 } 34 } 32 35 >> 36 static void ctrl_handler(int signo) >> 37 { >> 38 free(startptr); >> 39 printf("\nEnding\n"); >> 40 sb(); >> 41 exit(EXIT_SUCCESS); >> 42 } >> 43 33 static void cl_flush(void *p) 44 static void cl_flush(void *p) 34 { 45 { 35 #if defined(__i386) || defined(__x86_64) 46 #if defined(__i386) || defined(__x86_64) 36 asm volatile("clflush (%0)\n\t" 47 asm volatile("clflush (%0)\n\t" 37 : : "r"(p) : "memory"); 48 : : "r"(p) : "memory"); 38 #endif 49 #endif 39 } 50 } 40 51 41 void mem_flush(unsigned char *buf, size_t buf_ !! 52 static void mem_flush(void *p, size_t s) 42 { 53 { 43 unsigned char *cp = buf; !! 54 char *cp = (char *)p; 44 size_t i = 0; 55 size_t i = 0; 45 56 46 buf_size = buf_size / CL_SIZE; /* mem !! 57 s = s / CL_SIZE; /* mem size in cache llines */ 47 58 48 for (i = 0; i < buf_size; i++) !! 59 for (i = 0; i < s; i++) 49 cl_flush(&cp[i * CL_SIZE]); 60 cl_flush(&cp[i * CL_SIZE]); 50 61 51 sb(); 62 sb(); 52 } 63 } 53 64 54 /* !! 65 static void *malloc_and_init_memory(size_t s) 55 * Buffer index step advance to workaround HW !! 66 { 56 * the measurements. !! 67 uint64_t *p64; 57 * !! 68 size_t s64; 58 * Must be a prime to step through all indexes !! 69 59 * !! 70 void *p = memalign(PAGE_SIZE, s); 60 * Some primes work better than others on some !! 71 if (!p) 61 * result stability point of view). !! 72 return NULL; 62 */ << 63 #define FILL_IDX_MULT 23 << 64 << 65 static int fill_one_span_read(unsigned char *b << 66 { << 67 unsigned int size = buf_size / (CL_SIZ << 68 unsigned int i, idx = 0; << 69 unsigned char sum = 0; << 70 73 71 /* !! 74 p64 = (uint64_t *)p; 72 * Read the buffer in an order that is !! 75 s64 = s / sizeof(uint64_t); 73 * optimizations to prevent them inter << 74 * << 75 * The read order is (in terms of halv << 76 * i * FILL_IDX_MULT % size << 77 * The formula is open-coded below to << 78 * as it improves MBA/MBM result stabi << 79 */ << 80 for (i = 0; i < size; i++) { << 81 sum += buf[idx * (CL_SIZE / 2) << 82 76 83 idx += FILL_IDX_MULT; !! 77 while (s64 > 0) { 84 while (idx >= size) !! 78 *p64 = (uint64_t)rand(); 85 idx -= size; !! 79 p64 += (CL_SIZE / sizeof(uint64_t)); >> 80 s64 -= (CL_SIZE / sizeof(uint64_t)); >> 81 } >> 82 >> 83 return p; >> 84 } >> 85 >> 86 static int fill_one_span_read(unsigned char *start_ptr, unsigned char *end_ptr) >> 87 { >> 88 unsigned char sum, *p; >> 89 >> 90 sum = 0; >> 91 p = start_ptr; >> 92 while (p < end_ptr) { >> 93 sum += *p; >> 94 p += (CL_SIZE / 2); 86 } 95 } 87 96 88 return sum; 97 return sum; 89 } 98 } 90 99 91 static void fill_one_span_write(unsigned char !! 100 static >> 101 void fill_one_span_write(unsigned char *start_ptr, unsigned char *end_ptr) 92 { 102 { 93 unsigned char *end_ptr = buf + buf_siz << 94 unsigned char *p; 103 unsigned char *p; 95 104 96 p = buf; !! 105 p = start_ptr; 97 while (p < end_ptr) { 106 while (p < end_ptr) { 98 *p = '1'; 107 *p = '1'; 99 p += (CL_SIZE / 2); 108 p += (CL_SIZE / 2); 100 } 109 } 101 } 110 } 102 111 103 void fill_cache_read(unsigned char *buf, size_ !! 112 static int fill_cache_read(unsigned char *start_ptr, unsigned char *end_ptr, >> 113 char *resctrl_val) 104 { 114 { 105 int ret = 0; 115 int ret = 0; >> 116 FILE *fp; 106 117 107 while (1) { 118 while (1) { 108 ret = fill_one_span_read(buf, !! 119 ret = fill_one_span_read(start_ptr, end_ptr); 109 if (once) !! 120 if (!strncmp(resctrl_val, CAT_STR, sizeof(CAT_STR))) 110 break; 121 break; 111 } 122 } 112 123 113 /* Consume read result so that reading 124 /* Consume read result so that reading memory is not optimized out. */ 114 *value_sink = ret; !! 125 fp = fopen("/dev/null", "w"); >> 126 if (!fp) { >> 127 perror("Unable to write to /dev/null"); >> 128 return -1; >> 129 } >> 130 fprintf(fp, "Sum: %d ", ret); >> 131 fclose(fp); >> 132 >> 133 return 0; 115 } 134 } 116 135 117 static void fill_cache_write(unsigned char *bu !! 136 static int fill_cache_write(unsigned char *start_ptr, unsigned char *end_ptr, >> 137 char *resctrl_val) 118 { 138 { 119 while (1) { 139 while (1) { 120 fill_one_span_write(buf, buf_s !! 140 fill_one_span_write(start_ptr, end_ptr); 121 if (once) !! 141 if (!strncmp(resctrl_val, CAT_STR, sizeof(CAT_STR))) 122 break; 142 break; 123 } 143 } >> 144 >> 145 return 0; 124 } 146 } 125 147 126 unsigned char *alloc_buffer(size_t buf_size, i !! 148 static int >> 149 fill_cache(unsigned long long buf_size, int malloc_and_init, int memflush, >> 150 int op, char *resctrl_val) 127 { 151 { 128 void *buf = NULL; !! 152 unsigned char *start_ptr, *end_ptr; 129 uint64_t *p64; !! 153 unsigned long long i; 130 size_t s64; << 131 int ret; 154 int ret; 132 155 133 ret = posix_memalign(&buf, PAGE_SIZE, !! 156 if (malloc_and_init) 134 if (ret < 0) !! 157 start_ptr = malloc_and_init_memory(buf_size); 135 return NULL; !! 158 else >> 159 start_ptr = malloc(buf_size); 136 160 137 /* Initialize the buffer */ !! 161 if (!start_ptr) 138 p64 = buf; !! 162 return -1; 139 s64 = buf_size / sizeof(uint64_t); << 140 163 141 while (s64 > 0) { !! 164 startptr = start_ptr; 142 *p64 = (uint64_t)rand(); !! 165 end_ptr = start_ptr + buf_size; 143 p64 += (CL_SIZE / sizeof(uint6 !! 166 144 s64 -= (CL_SIZE / sizeof(uint6 !! 167 /* >> 168 * It's better to touch the memory once to avoid any compiler >> 169 * optimizations >> 170 */ >> 171 if (!malloc_and_init) { >> 172 for (i = 0; i < buf_size; i++) >> 173 *start_ptr++ = (unsigned char)rand(); 145 } 174 } 146 175 >> 176 start_ptr = startptr; >> 177 147 /* Flush the memory before using to av 178 /* Flush the memory before using to avoid "cache hot pages" effect */ 148 if (memflush) 179 if (memflush) 149 mem_flush(buf, buf_size); !! 180 mem_flush(start_ptr, buf_size); 150 181 151 return buf; !! 182 if (op == 0) >> 183 ret = fill_cache_read(start_ptr, end_ptr, resctrl_val); >> 184 else >> 185 ret = fill_cache_write(start_ptr, end_ptr, resctrl_val); >> 186 >> 187 free(startptr); >> 188 >> 189 if (ret) { >> 190 printf("\n Error in fill cache read/write...\n"); >> 191 return -1; >> 192 } >> 193 >> 194 >> 195 return 0; 152 } 196 } 153 197 154 int run_fill_buf(size_t buf_size, int memflush !! 198 int run_fill_buf(unsigned long span, int malloc_and_init_memory, >> 199 int memflush, int op, char *resctrl_val) 155 { 200 { 156 unsigned char *buf; !! 201 unsigned long long cache_size = span; >> 202 int ret; 157 203 158 buf = alloc_buffer(buf_size, memflush) !! 204 /* set up ctrl-c handler */ 159 if (!buf) !! 205 if (signal(SIGINT, ctrl_handler) == SIG_ERR) >> 206 printf("Failed to catch SIGINT!\n"); >> 207 if (signal(SIGHUP, ctrl_handler) == SIG_ERR) >> 208 printf("Failed to catch SIGHUP!\n"); >> 209 >> 210 ret = fill_cache(cache_size, malloc_and_init_memory, memflush, op, >> 211 resctrl_val); >> 212 if (ret) { >> 213 printf("\n Error in fill cache\n"); 160 return -1; 214 return -1; 161 !! 215 } 162 if (op == 0) << 163 fill_cache_read(buf, buf_size, << 164 else << 165 fill_cache_write(buf, buf_size << 166 free(buf); << 167 216 168 return 0; 217 return 0; 169 } 218 } 170 219
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.