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

mmio_warning_test.c (2676B)


      1/*
      2 * mmio_warning_test
      3 *
      4 * Copyright (C) 2019, Google LLC.
      5 *
      6 * This work is licensed under the terms of the GNU GPL, version 2.
      7 *
      8 * Test that we don't get a kernel warning when we call KVM_RUN after a
      9 * triple fault occurs.  To get the triple fault to occur we call KVM_RUN
     10 * on a VCPU that hasn't been properly setup.
     11 *
     12 */
     13
     14#define _GNU_SOURCE
     15#include <fcntl.h>
     16#include <kvm_util.h>
     17#include <linux/kvm.h>
     18#include <processor.h>
     19#include <pthread.h>
     20#include <stdio.h>
     21#include <stdlib.h>
     22#include <string.h>
     23#include <sys/ioctl.h>
     24#include <sys/mman.h>
     25#include <sys/stat.h>
     26#include <sys/types.h>
     27#include <sys/wait.h>
     28#include <test_util.h>
     29#include <unistd.h>
     30
     31#define NTHREAD 4
     32#define NPROCESS 5
     33
     34struct thread_context {
     35	int kvmcpu;
     36	struct kvm_run *run;
     37};
     38
     39void *thr(void *arg)
     40{
     41	struct thread_context *tc = (struct thread_context *)arg;
     42	int res;
     43	int kvmcpu = tc->kvmcpu;
     44	struct kvm_run *run = tc->run;
     45
     46	res = ioctl(kvmcpu, KVM_RUN, 0);
     47	pr_info("ret1=%d exit_reason=%d suberror=%d\n",
     48		res, run->exit_reason, run->internal.suberror);
     49
     50	return 0;
     51}
     52
     53void test(void)
     54{
     55	int i, kvm, kvmvm, kvmcpu;
     56	pthread_t th[NTHREAD];
     57	struct kvm_run *run;
     58	struct thread_context tc;
     59
     60	kvm = open("/dev/kvm", O_RDWR);
     61	TEST_ASSERT(kvm != -1, "failed to open /dev/kvm");
     62	kvmvm = ioctl(kvm, KVM_CREATE_VM, 0);
     63	TEST_ASSERT(kvmvm != -1, "KVM_CREATE_VM failed");
     64	kvmcpu = ioctl(kvmvm, KVM_CREATE_VCPU, 0);
     65	TEST_ASSERT(kvmcpu != -1, "KVM_CREATE_VCPU failed");
     66	run = (struct kvm_run *)mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_SHARED,
     67				    kvmcpu, 0);
     68	tc.kvmcpu = kvmcpu;
     69	tc.run = run;
     70	srand(getpid());
     71	for (i = 0; i < NTHREAD; i++) {
     72		pthread_create(&th[i], NULL, thr, (void *)(uintptr_t)&tc);
     73		usleep(rand() % 10000);
     74	}
     75	for (i = 0; i < NTHREAD; i++)
     76		pthread_join(th[i], NULL);
     77}
     78
     79int get_warnings_count(void)
     80{
     81	int warnings;
     82	FILE *f;
     83
     84	f = popen("dmesg | grep \"WARNING:\" | wc -l", "r");
     85	if (fscanf(f, "%d", &warnings) < 1)
     86		warnings = 0;
     87	pclose(f);
     88
     89	return warnings;
     90}
     91
     92int main(void)
     93{
     94	int warnings_before, warnings_after;
     95
     96	if (!is_intel_cpu()) {
     97		print_skip("Must be run on an Intel CPU");
     98		exit(KSFT_SKIP);
     99	}
    100
    101	if (vm_is_unrestricted_guest(NULL)) {
    102		print_skip("Unrestricted guest must be disabled");
    103		exit(KSFT_SKIP);
    104	}
    105
    106	warnings_before = get_warnings_count();
    107
    108	for (int i = 0; i < NPROCESS; ++i) {
    109		int status;
    110		int pid = fork();
    111
    112		if (pid < 0)
    113			exit(1);
    114		if (pid == 0) {
    115			test();
    116			exit(0);
    117		}
    118		while (waitpid(pid, &status, __WALL) != pid)
    119			;
    120	}
    121
    122	warnings_after = get_warnings_count();
    123	TEST_ASSERT(warnings_before == warnings_after,
    124		   "Warnings found in kernel.  Run 'dmesg' to inspect them.");
    125
    126	return 0;
    127}