1a2561b12SSai Praneeth Prakhya // SPDX-License-Identifier: GPL-2.0 2a2561b12SSai Praneeth Prakhya /* 3a2561b12SSai Praneeth Prakhya * fill_buf benchmark 4a2561b12SSai Praneeth Prakhya * 5a2561b12SSai Praneeth Prakhya * Copyright (C) 2018 Intel Corporation 6a2561b12SSai Praneeth Prakhya * 7a2561b12SSai Praneeth Prakhya * Authors: 8a2561b12SSai Praneeth Prakhya * Sai Praneeth Prakhya <[email protected]>, 9a2561b12SSai Praneeth Prakhya * Fenghua Yu <[email protected]> 10a2561b12SSai Praneeth Prakhya */ 11a2561b12SSai Praneeth Prakhya #include <stdio.h> 12a2561b12SSai Praneeth Prakhya #include <unistd.h> 13a2561b12SSai Praneeth Prakhya #include <stdlib.h> 14a2561b12SSai Praneeth Prakhya #include <sys/types.h> 15a2561b12SSai Praneeth Prakhya #include <sys/wait.h> 16a2561b12SSai Praneeth Prakhya #include <inttypes.h> 17a2561b12SSai Praneeth Prakhya #include <string.h> 18a2561b12SSai Praneeth Prakhya 19a2561b12SSai Praneeth Prakhya #include "resctrl.h" 20a2561b12SSai Praneeth Prakhya 21a2561b12SSai Praneeth Prakhya #define CL_SIZE (64) 22a2561b12SSai Praneeth Prakhya #define PAGE_SIZE (4 * 1024) 23a2561b12SSai Praneeth Prakhya #define MB (1024 * 1024) 24a2561b12SSai Praneeth Prakhya 25a2561b12SSai Praneeth Prakhya static void sb(void) 26a2561b12SSai Praneeth Prakhya { 27a2561b12SSai Praneeth Prakhya #if defined(__i386) || defined(__x86_64) 28a2561b12SSai Praneeth Prakhya asm volatile("sfence\n\t" 29a2561b12SSai Praneeth Prakhya : : : "memory"); 30a2561b12SSai Praneeth Prakhya #endif 31a2561b12SSai Praneeth Prakhya } 32a2561b12SSai Praneeth Prakhya 33a2561b12SSai Praneeth Prakhya static void cl_flush(void *p) 34a2561b12SSai Praneeth Prakhya { 35a2561b12SSai Praneeth Prakhya #if defined(__i386) || defined(__x86_64) 36a2561b12SSai Praneeth Prakhya asm volatile("clflush (%0)\n\t" 37a2561b12SSai Praneeth Prakhya : : "r"(p) : "memory"); 38a2561b12SSai Praneeth Prakhya #endif 39a2561b12SSai Praneeth Prakhya } 40a2561b12SSai Praneeth Prakhya 41205de6ddSIlpo Järvinen void mem_flush(unsigned char *buf, size_t buf_size) 42a2561b12SSai Praneeth Prakhya { 43f4123975SIlpo Järvinen unsigned char *cp = buf; 44a2561b12SSai Praneeth Prakhya size_t i = 0; 45a2561b12SSai Praneeth Prakhya 46f4123975SIlpo Järvinen buf_size = buf_size / CL_SIZE; /* mem size in cache lines */ 47a2561b12SSai Praneeth Prakhya 48f4123975SIlpo Järvinen for (i = 0; i < buf_size; i++) 49a2561b12SSai Praneeth Prakhya cl_flush(&cp[i * CL_SIZE]); 50a2561b12SSai Praneeth Prakhya 51a2561b12SSai Praneeth Prakhya sb(); 52a2561b12SSai Praneeth Prakhya } 53a2561b12SSai Praneeth Prakhya 54bcdb2e9dSIlpo Järvinen /* 55bcdb2e9dSIlpo Järvinen * Buffer index step advance to workaround HW prefetching interfering with 56bcdb2e9dSIlpo Järvinen * the measurements. 57bcdb2e9dSIlpo Järvinen * 58bcdb2e9dSIlpo Järvinen * Must be a prime to step through all indexes of the buffer. 59bcdb2e9dSIlpo Järvinen * 60bcdb2e9dSIlpo Järvinen * Some primes work better than others on some architectures (from MBA/MBM 61bcdb2e9dSIlpo Järvinen * result stability point of view). 62bcdb2e9dSIlpo Järvinen */ 63bcdb2e9dSIlpo Järvinen #define FILL_IDX_MULT 23 64bcdb2e9dSIlpo Järvinen 65f4123975SIlpo Järvinen static int fill_one_span_read(unsigned char *buf, size_t buf_size) 66a2561b12SSai Praneeth Prakhya { 67bcdb2e9dSIlpo Järvinen unsigned int size = buf_size / (CL_SIZE / 2); 68bcdb2e9dSIlpo Järvinen unsigned int i, idx = 0; 69bcdb2e9dSIlpo Järvinen unsigned char sum = 0; 70a2561b12SSai Praneeth Prakhya 71bcdb2e9dSIlpo Järvinen /* 72bcdb2e9dSIlpo Järvinen * Read the buffer in an order that is unexpected by HW prefetching 73bcdb2e9dSIlpo Järvinen * optimizations to prevent them interfering with the caching pattern. 74bcdb2e9dSIlpo Järvinen * 75bcdb2e9dSIlpo Järvinen * The read order is (in terms of halves of cachelines): 76bcdb2e9dSIlpo Järvinen * i * FILL_IDX_MULT % size 77bcdb2e9dSIlpo Järvinen * The formula is open-coded below to avoiding modulo inside the loop 78bcdb2e9dSIlpo Järvinen * as it improves MBA/MBM result stability on some architectures. 79bcdb2e9dSIlpo Järvinen */ 80bcdb2e9dSIlpo Järvinen for (i = 0; i < size; i++) { 81bcdb2e9dSIlpo Järvinen sum += buf[idx * (CL_SIZE / 2)]; 82bcdb2e9dSIlpo Järvinen 83bcdb2e9dSIlpo Järvinen idx += FILL_IDX_MULT; 84bcdb2e9dSIlpo Järvinen while (idx >= size) 85bcdb2e9dSIlpo Järvinen idx -= size; 86a2561b12SSai Praneeth Prakhya } 87a2561b12SSai Praneeth Prakhya 88a2561b12SSai Praneeth Prakhya return sum; 89a2561b12SSai Praneeth Prakhya } 90a2561b12SSai Praneeth Prakhya 91205de6ddSIlpo Järvinen void fill_cache_read(unsigned char *buf, size_t buf_size, bool once) 92a2561b12SSai Praneeth Prakhya { 93a2561b12SSai Praneeth Prakhya int ret = 0; 94a2561b12SSai Praneeth Prakhya 95790bf585SFenghua Yu while (1) { 96f4123975SIlpo Järvinen ret = fill_one_span_read(buf, buf_size); 977f3c980cSIlpo Järvinen if (once) 98790bf585SFenghua Yu break; 99790bf585SFenghua Yu } 100a2561b12SSai Praneeth Prakhya 101a2561b12SSai Praneeth Prakhya /* Consume read result so that reading memory is not optimized out. */ 10290a009dbSIlpo Järvinen *value_sink = ret; 103a2561b12SSai Praneeth Prakhya } 104a2561b12SSai Praneeth Prakhya 105*e958c21eSReinette Chatre unsigned char *alloc_buffer(size_t buf_size, bool memflush) 106a2561b12SSai Praneeth Prakhya { 10724be0559SIlpo Järvinen void *buf = NULL; 10824be0559SIlpo Järvinen uint64_t *p64; 109caf02626SReinette Chatre ssize_t s64; 11024be0559SIlpo Järvinen int ret; 111a2561b12SSai Praneeth Prakhya 11224be0559SIlpo Järvinen ret = posix_memalign(&buf, PAGE_SIZE, buf_size); 11324be0559SIlpo Järvinen if (ret < 0) 114f8f66969SIlpo Järvinen return NULL; 115a2561b12SSai Praneeth Prakhya 11624be0559SIlpo Järvinen /* Initialize the buffer */ 11724be0559SIlpo Järvinen p64 = buf; 11824be0559SIlpo Järvinen s64 = buf_size / sizeof(uint64_t); 11924be0559SIlpo Järvinen 12024be0559SIlpo Järvinen while (s64 > 0) { 12124be0559SIlpo Järvinen *p64 = (uint64_t)rand(); 12224be0559SIlpo Järvinen p64 += (CL_SIZE / sizeof(uint64_t)); 12324be0559SIlpo Järvinen s64 -= (CL_SIZE / sizeof(uint64_t)); 12424be0559SIlpo Järvinen } 12524be0559SIlpo Järvinen 126a2561b12SSai Praneeth Prakhya /* Flush the memory before using to avoid "cache hot pages" effect */ 127a2561b12SSai Praneeth Prakhya if (memflush) 128f4123975SIlpo Järvinen mem_flush(buf, buf_size); 129a2561b12SSai Praneeth Prakhya 130f8f66969SIlpo Järvinen return buf; 131f8f66969SIlpo Järvinen } 132f8f66969SIlpo Järvinen 133*e958c21eSReinette Chatre int run_fill_buf(size_t buf_size, bool memflush) 134f8f66969SIlpo Järvinen { 135f8f66969SIlpo Järvinen unsigned char *buf; 136f8f66969SIlpo Järvinen 137f8f66969SIlpo Järvinen buf = alloc_buffer(buf_size, memflush); 138f8f66969SIlpo Järvinen if (!buf) 139f8f66969SIlpo Järvinen return -1; 140f8f66969SIlpo Järvinen 141f3069136SReinette Chatre fill_cache_read(buf, buf_size, false); 142f3069136SReinette Chatre 143f4123975SIlpo Järvinen free(buf); 144a2561b12SSai Praneeth Prakhya 145a2561b12SSai Praneeth Prakhya return 0; 146a2561b12SSai Praneeth Prakhya } 147