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 
41*205de6ddSIlpo 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 
91f4123975SIlpo Järvinen static void fill_one_span_write(unsigned char *buf, size_t buf_size)
92a2561b12SSai Praneeth Prakhya {
93f4123975SIlpo Järvinen 	unsigned char *end_ptr = buf + buf_size;
94a2561b12SSai Praneeth Prakhya 	unsigned char *p;
95a2561b12SSai Praneeth Prakhya 
96f4123975SIlpo Järvinen 	p = buf;
97a2561b12SSai Praneeth Prakhya 	while (p < end_ptr) {
98a2561b12SSai Praneeth Prakhya 		*p = '1';
99a2561b12SSai Praneeth Prakhya 		p += (CL_SIZE / 2);
100a2561b12SSai Praneeth Prakhya 	}
101a2561b12SSai Praneeth Prakhya }
102a2561b12SSai Praneeth Prakhya 
103*205de6ddSIlpo Järvinen void fill_cache_read(unsigned char *buf, size_t buf_size, bool once)
104a2561b12SSai Praneeth Prakhya {
105a2561b12SSai Praneeth Prakhya 	int ret = 0;
106a2561b12SSai Praneeth Prakhya 
107790bf585SFenghua Yu 	while (1) {
108f4123975SIlpo Järvinen 		ret = fill_one_span_read(buf, buf_size);
1097f3c980cSIlpo Järvinen 		if (once)
110790bf585SFenghua Yu 			break;
111790bf585SFenghua Yu 	}
112a2561b12SSai Praneeth Prakhya 
113a2561b12SSai Praneeth Prakhya 	/* Consume read result so that reading memory is not optimized out. */
11490a009dbSIlpo Järvinen 	*value_sink = ret;
115a2561b12SSai Praneeth Prakhya }
116a2561b12SSai Praneeth Prakhya 
11790a009dbSIlpo Järvinen static void fill_cache_write(unsigned char *buf, size_t buf_size, bool once)
118a2561b12SSai Praneeth Prakhya {
119790bf585SFenghua Yu 	while (1) {
120f4123975SIlpo Järvinen 		fill_one_span_write(buf, buf_size);
1217f3c980cSIlpo Järvinen 		if (once)
122790bf585SFenghua Yu 			break;
123790bf585SFenghua Yu 	}
124a2561b12SSai Praneeth Prakhya }
125a2561b12SSai Praneeth Prakhya 
126*205de6ddSIlpo Järvinen unsigned char *alloc_buffer(size_t buf_size, int memflush)
127a2561b12SSai Praneeth Prakhya {
12824be0559SIlpo Järvinen 	void *buf = NULL;
12924be0559SIlpo Järvinen 	uint64_t *p64;
13024be0559SIlpo Järvinen 	size_t s64;
13124be0559SIlpo Järvinen 	int ret;
132a2561b12SSai Praneeth Prakhya 
13324be0559SIlpo Järvinen 	ret = posix_memalign(&buf, PAGE_SIZE, buf_size);
13424be0559SIlpo Järvinen 	if (ret < 0)
135f8f66969SIlpo Järvinen 		return NULL;
136a2561b12SSai Praneeth Prakhya 
13724be0559SIlpo Järvinen 	/* Initialize the buffer */
13824be0559SIlpo Järvinen 	p64 = buf;
13924be0559SIlpo Järvinen 	s64 = buf_size / sizeof(uint64_t);
14024be0559SIlpo Järvinen 
14124be0559SIlpo Järvinen 	while (s64 > 0) {
14224be0559SIlpo Järvinen 		*p64 = (uint64_t)rand();
14324be0559SIlpo Järvinen 		p64 += (CL_SIZE / sizeof(uint64_t));
14424be0559SIlpo Järvinen 		s64 -= (CL_SIZE / sizeof(uint64_t));
14524be0559SIlpo Järvinen 	}
14624be0559SIlpo Järvinen 
147a2561b12SSai Praneeth Prakhya 	/* Flush the memory before using to avoid "cache hot pages" effect */
148a2561b12SSai Praneeth Prakhya 	if (memflush)
149f4123975SIlpo Järvinen 		mem_flush(buf, buf_size);
150a2561b12SSai Praneeth Prakhya 
151f8f66969SIlpo Järvinen 	return buf;
152f8f66969SIlpo Järvinen }
153f8f66969SIlpo Järvinen 
15424be0559SIlpo Järvinen int run_fill_buf(size_t buf_size, int memflush, int op, bool once)
155f8f66969SIlpo Järvinen {
156f8f66969SIlpo Järvinen 	unsigned char *buf;
157f8f66969SIlpo Järvinen 
158f8f66969SIlpo Järvinen 	buf = alloc_buffer(buf_size, memflush);
159f8f66969SIlpo Järvinen 	if (!buf)
160f8f66969SIlpo Järvinen 		return -1;
161f8f66969SIlpo Järvinen 
162a2561b12SSai Praneeth Prakhya 	if (op == 0)
16390a009dbSIlpo Järvinen 		fill_cache_read(buf, buf_size, once);
164a2561b12SSai Praneeth Prakhya 	else
16590a009dbSIlpo Järvinen 		fill_cache_write(buf, buf_size, once);
166f4123975SIlpo Järvinen 	free(buf);
167a2561b12SSai Praneeth Prakhya 
168a2561b12SSai Praneeth Prakhya 	return 0;
169a2561b12SSai Praneeth Prakhya }
170