cachepc

Prime+Probe cache-based side-channel attack on AMD SEV-SNP protected virtual machines
git clone https://git.sinitax.com/sinitax/cachepc
Log | Files | Refs | Submodules | README | sfeed.txt

kvm-pagestep.c (2421B)


      1#include "test/kvm-eviction.h"
      2#include "test/kvm.h"
      3#include "test/util.h"
      4#include "cachepc/uapi.h"
      5
      6#include <sys/ioctl.h>
      7#include <sys/mman.h>
      8#include <signal.h>
      9#include <unistd.h>
     10#include <fcntl.h>
     11#include <errno.h>
     12#include <err.h>
     13#include <string.h>
     14#include <stdbool.h>
     15#include <stdio.h>
     16#include <stdlib.h>
     17
     18static int child;
     19
     20uint64_t
     21monitor(struct kvm *kvm, bool baseline)
     22{
     23	struct cpc_event event;
     24	int ret;
     25
     26	ret = ioctl(kvm_dev, KVM_CPC_POLL_EVENT, &event);
     27	if (ret && errno == EAGAIN) return 0;
     28	if (ret) err(1, "KVM_CPC_POLL_EVENT");
     29
     30	if (event.type != CPC_EVENT_TRACK_PAGE)
     31		errx(1, "unexpected event type %i", event.type);
     32
     33	printf("Event: rip:%08llx prev:%llu next:%llu ret:%llu\n",
     34		vm_get_rip(), event.page.inst_gfn_prev,
     35		event.page.inst_gfn, event.page.retinst);
     36	printf("\n");
     37
     38	ret = ioctl(kvm_dev, KVM_CPC_ACK_EVENT, &event.id);
     39	if (ret) err(1, "KVM_CPC_ACK_EVENT");
     40
     41	return 1;
     42}
     43
     44void
     45deinit(void)
     46{
     47	ioctl(kvm_dev, KVM_CPC_DEINIT);
     48
     49	kill(child, SIGKILL);
     50
     51	kvm_setup_deinit();
     52}
     53
     54int
     55main(int argc, const char **argv)
     56{
     57	struct ipc *ipc;
     58	struct guest guest;
     59	struct kvm kvm;
     60	struct cpc_track_cfg cfg;
     61	uint64_t eventcnt;
     62	int ret;
     63
     64	setvbuf(stdout, NULL, _IONBF, 0);
     65
     66	parse_vmtype(argc, argv);
     67
     68	kvm_setup_init();
     69
     70	ipc = ipc_alloc();
     71
     72	child = fork();
     73	if (child < 0) err(1, "fork");
     74
     75	if (child == 0) {
     76		pin_process(0, TARGET_CORE, true);
     77
     78		guest_init(&guest, "test/kvm-pagestep_guest");
     79		vm_init(&kvm, &guest);
     80		guest_deinit(&guest);
     81
     82		ret = ioctl(kvm_dev, KVM_CPC_RESET, NULL);
     83		if (ret < 0) err(1, "KVM_CPC_RESET");
     84
     85		ipc_signal_parent(ipc);
     86		ipc_wait_parent(ipc);
     87
     88		printf("VM start\n");
     89
     90		do {
     91			ret = ioctl(kvm.vcpufd, KVM_RUN, NULL);
     92			if (ret < 0) err(1, "KVM_RUN");
     93
     94			if (kvm.run->exit_reason == KVM_EXIT_HLT)
     95				printf("VM halt\n");
     96		} while (kvm.run->exit_reason == KVM_EXIT_HLT);
     97
     98		printf("VM exit\n");
     99
    100		vm_deinit(&kvm);
    101
    102		ipc_free(ipc);
    103
    104		kvm_setup_deinit();
    105	} else {
    106		pin_process(0, SECONDARY_CORE, true);
    107
    108		atexit(deinit);
    109
    110		ipc_wait_child(ipc);
    111
    112		printf("Monitor start\n");
    113
    114		memset(&cfg, 0, sizeof(cfg));
    115		cfg.mode = CPC_TRACK_PAGES;
    116		cfg.pages.singlestep_resolve = true;
    117		ret = ioctl(kvm_dev, KVM_CPC_TRACK_MODE, &cfg);
    118		if (ret) err(1, "KVM_CPC_TRACK_MODE");
    119
    120		ipc_signal_child(ipc);
    121
    122		eventcnt = 0;
    123		while (eventcnt < 50) {
    124			eventcnt += monitor(&kvm, true);
    125		}
    126
    127		printf("Monitor exit\n");
    128
    129		ipc_free(ipc);
    130	}
    131}
    132