kvm-step.c (3985B)
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; 19static struct cpc_event event; 20 21uint64_t 22monitor(struct kvm *kvm, bool baseline) 23{ 24 uint8_t counts[L1_SETS]; 25 int ret; 26 27 ret = ioctl(kvm_dev, KVM_CPC_POLL_EVENT, &event); 28 if (ret && errno == EAGAIN) return 0; 29 if (ret) err(1, "KVM_CPC_POLL_EVENT"); 30 31 if (event.type != CPC_EVENT_TRACK_STEP) 32 errx(1, "unexpected event type %i", event.type); 33 34 ret = ioctl(kvm_dev, KVM_CPC_READ_COUNTS, counts); 35 if (ret) err(1, "KVM_CPC_READ_COUNTS"); 36 37 printf("Event: rip:%08llx cnt:%llu inst:%08llx data:%08llx ret:%llu misses:%u\n", 38 vm_get_rip(), event.step.fault_count, 39 event.step.fault_gfns[0], event.step.fault_gfns[1], 40 event.step.retinst, event.step.misses); 41 print_counts(counts); 42 printf("\n"); 43 print_counts_raw(counts); 44 printf("\n"); 45 46 ret = ioctl(kvm_dev, KVM_CPC_ACK_EVENT, &event.id); 47 if (ret) err(1, "KVM_CPC_ACK_EVENT"); 48 49 return 1; 50} 51 52void 53deinit(void) 54{ 55 ioctl(kvm_dev, KVM_CPC_DEINIT); 56 57 kill(child, SIGKILL); 58 59 kvm_setup_deinit(); 60} 61 62int 63main(int argc, const char **argv) 64{ 65 struct ipc *ipc; 66 struct guest guest; 67 struct kvm kvm; 68 uint8_t baseline[L1_SETS]; 69 struct cpc_track_cfg cfg; 70 uint64_t eventcnt; 71 uint32_t arg; 72 bool with_data; 73 int ret; 74 75 setvbuf(stdout, NULL, _IONBF, 0); 76 77 with_data = true; 78 if (argc > 1 && !strcmp(argv[1], "--exec-only")) { 79 with_data = false; 80 argc--; 81 argv++; 82 } 83 84 parse_vmtype(argc, argv); 85 86 kvm_setup_init(); 87 88 ipc = ipc_alloc(); 89 90 child = fork(); 91 if (child < 0) err(1, "fork"); 92 93 if (child == 0) { 94 pin_process(0, TARGET_CORE, true); 95 96 guest_init(&guest, "test/kvm-step_guest"); 97 vm_init(&kvm, &guest); 98 guest_deinit(&guest); 99 100 /* reset kernel module state */ 101 ret = ioctl(kvm_dev, KVM_CPC_RESET, NULL); 102 if (ret < 0) err(1, "KVM_CPC_RESET"); 103 104 ipc_signal_parent(ipc); 105 ipc_wait_parent(ipc); 106 107 printf("VM start\n"); 108 109 do { 110 ret = ioctl(kvm.vcpufd, KVM_RUN, NULL); 111 if (ret < 0) err(1, "KVM_RUN"); 112 } while (kvm.run->exit_reason == KVM_EXIT_HLT); 113 114 printf("VM exit\n"); 115 116 vm_deinit(&kvm); 117 118 ipc_free(ipc); 119 kvm_setup_deinit(); 120 } else { 121 pin_process(0, SECONDARY_CORE, true); 122 123 atexit(deinit); 124 125 ipc_wait_child(ipc); 126 127 printf("Monitor start\n"); 128 129 memset(&cfg, 0, sizeof(cfg)); 130 cfg.mode = CPC_TRACK_STEPS; 131 cfg.steps.with_data = with_data; 132 ret = ioctl(kvm_dev, KVM_CPC_TRACK_MODE, &cfg); 133 if (ret) err(1, "KVM_CPC_TRACK_MODE"); 134 135 arg = true; 136 ret = ioctl(kvm_dev, KVM_CPC_CALC_BASELINE, &arg); 137 if (ret) err(1, "KVM_CPC_CALC_BASELINE"); 138 139 ipc_signal_child(ipc); 140 141 /* run vm while baseline is calculated */ 142 eventcnt = 0; 143 while (eventcnt < 50) { 144 eventcnt += monitor(&kvm, true); 145 } 146 147 ret = ioctl(kvm_dev, KVM_CPC_VM_REQ_PAUSE); 148 if (ret) err(1, "KVM_CPC_VM_REQ_PAUSE"); 149 150 while (1) { 151 ret = ioctl(kvm_dev, KVM_CPC_POLL_EVENT, &event); 152 if (ret && errno == EAGAIN) continue; 153 if (ret) err(1, "KVM_CPC_POLL_EVENT"); 154 155 if (event.type == CPC_EVENT_PAUSE) break; 156 157 ret = ioctl(kvm_dev, KVM_CPC_ACK_EVENT, &event.id); 158 if (ret) err(1, "KVM_CPC_ACK_EVENT"); 159 } 160 161 arg = false; 162 ret = ioctl(kvm_dev, KVM_CPC_CALC_BASELINE, &arg); 163 if (ret) err(1, "KVM_CPC_CALC_BASELINE"); 164 165 ret = ioctl(kvm_dev, KVM_CPC_READ_BASELINE, baseline); 166 if (ret) err(1, "KVM_CPC_READ_BASELINE"); 167 168 printf("\nBaseline:\n"); 169 print_counts(baseline); 170 printf("\n"); 171 print_counts_raw(baseline); 172 printf("\n\n"); 173 174 arg = true; 175 ret = ioctl(kvm_dev, KVM_CPC_APPLY_BASELINE, &arg); 176 if (ret) err(1, "KMV_CPC_APPLY_BASELINE"); 177 178 ret = ioctl(kvm_dev, KVM_CPC_ACK_EVENT, &event.id); 179 if (ret) err(1, "KVM_CPC_ACK_EVENT"); 180 181 eventcnt = 0; 182 while (eventcnt < 57) { 183 eventcnt += monitor(&kvm, false); 184 } 185 186 printf("Monitor exit\n"); 187 188 ipc_free(ipc); 189 } 190} 191