cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

fill_buf.c (4048B)


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