kvm-eviction.c (4002B)
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 <unistd.h> 9#include <fcntl.h> 10#include <err.h> 11#include <string.h> 12#include <stdbool.h> 13#include <stdio.h> 14#include <stdlib.h> 15 16#define SAMPLE_COUNT 64 17 18void 19collect(struct kvm *kvm, uint8_t *counts) 20{ 21 int ret; 22 23 ret = ioctl(kvm->vcpufd, KVM_RUN, NULL); 24 if (ret == -1) err(1, "KVM_RUN"); 25 26 if (kvm->run->exit_reason == KVM_EXIT_MMIO) { 27 errx(1, "KVM died from OOB access! rip:%lu addr:%lu", 28 vm_get_rip(), kvm->run->mmio.phys_addr); 29 } else if (kvm->run->exit_reason != KVM_EXIT_HLT) { 30 errx(1, "KVM died! rip:%lu code:%i", 31 vm_get_rip(), kvm->run->exit_reason); 32 } 33 34 ret = ioctl(kvm_dev, KVM_CPC_READ_COUNTS, counts); 35 if (ret == -1) err(1, "KVM_CPC_READ_COUNTS"); 36} 37 38int 39main(int argc, const char **argv) 40{ 41 struct kvm vms[2]; 42 struct guest guests[2]; 43 uint8_t counts[2][SAMPLE_COUNT][L1_SETS]; 44 uint8_t baseline[L1_SETS]; 45 struct cpc_track_cfg cfg; 46 int i, k, ret, exitcode; 47 48 setvbuf(stdout, NULL, _IONBF, 0); 49 50 parse_vmtype(argc, argv); 51 52 pin_process(0, TARGET_CORE, true); 53 54 kvm_setup_init(); 55 56 guest_init(&guests[WITH], "test/kvm-eviction-with_guest"); 57 vm_init(&vms[WITH], &guests[WITH]); 58 guest_deinit(&guests[WITH]); 59 60 guest_init(&guests[WITHOUT], "test/kvm-eviction-without_guest"); 61 vm_init(&vms[WITHOUT], &guests[WITHOUT]); 62 guest_deinit(&guests[WITHOUT]); 63 64 /* reset kernel module state */ 65 ret = ioctl(kvm_dev, KVM_CPC_RESET); 66 if (ret == -1) err(1, "KVM_CPC_RESET"); 67 68 memset(&cfg, 0, sizeof(cfg)); 69 cfg.mode = CPC_TRACK_EXIT_EVICTIONS; 70 ret = ioctl(kvm_dev, KVM_CPC_TRACK_MODE, &cfg); 71 if (ret == -1) err(1, "KVM_CPC_TRACK_MODE"); 72 73 /* resolve page faults in advance (code only covers 1 page).. 74 * we want the read counts to apply between KVM_RUN and KVM_EXIT_HLT, 75 * any exits through PFs inbetween will influence our measurement */ 76 collect(&vms[WITH], counts[WITH][0]); 77 collect(&vms[WITHOUT], counts[WITHOUT][0]); 78 79 /* collect samples */ 80 for (i = 0; i < SAMPLE_COUNT; i++) { 81 collect(&vms[WITH], counts[WITH][i]); 82 collect(&vms[WITHOUT], counts[WITHOUT][i]); 83 } 84 85 /* calculate measurement baseline */ 86 memset(baseline, 0xff, L1_SETS); 87 for (i = 0; i < SAMPLE_COUNT; i++) { 88 for (k = 0; k < L1_SETS; k++) { 89 if (counts[WITH][i][k] < baseline[k]) 90 baseline[k] = counts[WITH][i][k]; 91 if (counts[WITHOUT][i][k] < baseline[k]) 92 baseline[k] = counts[WITHOUT][i][k]; 93 } 94 } 95 96 printf("=== Baseline ===\n\n", i); 97 print_counts(baseline); 98 printf("\n"); 99 print_counts_raw(baseline); 100 printf("\n"); 101 102 /* apply baseline and output samples */ 103 for (i = 0; i < SAMPLE_COUNT; i++) { 104 for (k = 0; k < L1_SETS; k++) { 105 counts[WITH][i][k] -= baseline[k]; 106 counts[WITHOUT][i][k] -= baseline[k]; 107 } 108 109 printf("=== Sample %2i ===\n", i); 110 111 printf("\nWith eviction:\n\n"); 112 print_counts(counts[WITH][i]); 113 printf("\n"); 114 print_counts_raw(counts[WITH][i]); 115 116 printf("\nWithout eviction:\n\n"); 117 print_counts(counts[WITHOUT][i]); 118 printf("\n"); 119 print_counts_raw(counts[WITHOUT][i]); 120 printf("\n"); 121 } 122 123 /* check for measurment errors */ 124 exitcode = 0; 125 for (i = 0; i < SAMPLE_COUNT; i++) { 126 for (k = 0; k < L1_SETS; k++) { 127 if (counts[WITH][i][k] + baseline[k] > L1_ASSOC) { 128 warnx("sample %i: With count OOB for set %i (=%i)", 129 i, k, counts[WITH][i][k] + baseline[k]); 130 exitcode = 1; 131 } 132 133 if (counts[WITHOUT][i][k] + baseline[k] > L1_ASSOC) { 134 warnx("sample %i: Without count OOB for set %i (=%i)", 135 i, k, counts[WITHOUT][i][k] + baseline[k]); 136 exitcode = 1; 137 } 138 } 139 140 if (!counts[WITH][i][TARGET_SET]) { 141 warnx("sample %i: Missing eviction in target set %i (=%i,%i)", 142 i, TARGET_SET, counts[WITH][i][TARGET_SET], 143 counts[WITH][i][TARGET_SET] + baseline[TARGET_SET]); 144 exitcode = 1; 145 } 146 } 147 148 vm_deinit(&vms[WITH]); 149 vm_deinit(&vms[WITHOUT]); 150 151 ret = ioctl(kvm_dev, KVM_CPC_DEINIT); 152 if (ret == -1) err(1, "KVM_CPC_DEINIT"); 153 154 kvm_setup_deinit(); 155 156 return exitcode; 157} 158