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

vm_util.c (2487B)


      1// SPDX-License-Identifier: GPL-2.0
      2#include <string.h>
      3#include <fcntl.h>
      4#include "../kselftest.h"
      5#include "vm_util.h"
      6
      7#define PMD_SIZE_FILE_PATH "/sys/kernel/mm/transparent_hugepage/hpage_pmd_size"
      8#define SMAP_FILE_PATH "/proc/self/smaps"
      9#define MAX_LINE_LENGTH 500
     10
     11uint64_t pagemap_get_entry(int fd, char *start)
     12{
     13	const unsigned long pfn = (unsigned long)start / getpagesize();
     14	uint64_t entry;
     15	int ret;
     16
     17	ret = pread(fd, &entry, sizeof(entry), pfn * sizeof(entry));
     18	if (ret != sizeof(entry))
     19		ksft_exit_fail_msg("reading pagemap failed\n");
     20	return entry;
     21}
     22
     23bool pagemap_is_softdirty(int fd, char *start)
     24{
     25	uint64_t entry = pagemap_get_entry(fd, start);
     26
     27	// Check if dirty bit (55th bit) is set
     28	return entry & 0x0080000000000000ull;
     29}
     30
     31void clear_softdirty(void)
     32{
     33	int ret;
     34	const char *ctrl = "4";
     35	int fd = open("/proc/self/clear_refs", O_WRONLY);
     36
     37	if (fd < 0)
     38		ksft_exit_fail_msg("opening clear_refs failed\n");
     39	ret = write(fd, ctrl, strlen(ctrl));
     40	close(fd);
     41	if (ret != strlen(ctrl))
     42		ksft_exit_fail_msg("writing clear_refs failed\n");
     43}
     44
     45static bool check_for_pattern(FILE *fp, const char *pattern, char *buf)
     46{
     47	while (fgets(buf, MAX_LINE_LENGTH, fp) != NULL) {
     48		if (!strncmp(buf, pattern, strlen(pattern)))
     49			return true;
     50	}
     51	return false;
     52}
     53
     54uint64_t read_pmd_pagesize(void)
     55{
     56	int fd;
     57	char buf[20];
     58	ssize_t num_read;
     59
     60	fd = open(PMD_SIZE_FILE_PATH, O_RDONLY);
     61	if (fd == -1)
     62		ksft_exit_fail_msg("Open hpage_pmd_size failed\n");
     63
     64	num_read = read(fd, buf, 19);
     65	if (num_read < 1) {
     66		close(fd);
     67		ksft_exit_fail_msg("Read hpage_pmd_size failed\n");
     68	}
     69	buf[num_read] = '\0';
     70	close(fd);
     71
     72	return strtoul(buf, NULL, 10);
     73}
     74
     75uint64_t check_huge(void *addr)
     76{
     77	uint64_t thp = 0;
     78	int ret;
     79	FILE *fp;
     80	char buffer[MAX_LINE_LENGTH];
     81	char addr_pattern[MAX_LINE_LENGTH];
     82
     83	ret = snprintf(addr_pattern, MAX_LINE_LENGTH, "%08lx-",
     84		       (unsigned long) addr);
     85	if (ret >= MAX_LINE_LENGTH)
     86		ksft_exit_fail_msg("%s: Pattern is too long\n", __func__);
     87
     88	fp = fopen(SMAP_FILE_PATH, "r");
     89	if (!fp)
     90		ksft_exit_fail_msg("%s: Failed to open file %s\n", __func__, SMAP_FILE_PATH);
     91
     92	if (!check_for_pattern(fp, addr_pattern, buffer))
     93		goto err_out;
     94
     95	/*
     96	 * Fetch the AnonHugePages: in the same block and check the number of
     97	 * hugepages.
     98	 */
     99	if (!check_for_pattern(fp, "AnonHugePages:", buffer))
    100		goto err_out;
    101
    102	if (sscanf(buffer, "AnonHugePages:%10ld kB", &thp) != 1)
    103		ksft_exit_fail_msg("Reading smap error\n");
    104
    105err_out:
    106	fclose(fp);
    107	return thp;
    108}