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