qemu-aes.c (5825B)
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 struct cpc_event event; 19static struct cpc_event_batch batch; 20static uint64_t target_inst_gfn = 0; 21 22int 23monitor(bool baseline) 24{ 25 uint8_t counts[L1_SETS]; 26 int ret; 27 28 ret = ioctl(kvm_dev, KVM_CPC_POLL_EVENT, &event); 29 if (ret && errno == EAGAIN) return 0; 30 if (ret) err(1, "KVM_CPC_POLL_EVENT"); 31 32 switch (event.type) { 33 case CPC_EVENT_GUEST: 34 printf("Guest %s\n", !event.guest.type ? "start" : "stop"); 35 if (event.guest.type == CPC_GUEST_STOP_TRACK) 36 return 2; 37 break; 38 case CPC_EVENT_TRACK_STEP: 39 ret = ioctl(kvm_dev, KVM_CPC_READ_COUNTS, counts); 40 if (ret) err(1, "KVM_CPC_READ_COUNTS"); 41 42 if (!target_inst_gfn && baseline) 43 target_inst_gfn = event.step.inst_gfn; 44 45 printf("Event: rip:%016llx cnt:%llu " 46 "inst:%08llx ret:%llu\n", 47 vm_get_rip(), event.step.fault_count, 48 event.step.inst_gfn, event.step.retinst); 49 print_counts(counts); 50 printf("\n"); 51 print_counts_raw(counts); 52 printf("\n"); 53 break; 54 default: 55 errx(1, "unexpected event type %i", event.type); 56 } 57 58 ret = ioctl(kvm_dev, KVM_CPC_ACK_EVENT, &event.id); 59 if (ret) err(1, "KVM_CPC_ACK_EVENT"); 60 61 return 1; 62} 63 64void 65read_batch(void) 66{ 67 uint32_t i; 68 int ret; 69 70 ret = ioctl(kvm_dev, KVM_CPC_READ_BATCH, &batch); 71 if (ret && errno == EAGAIN) return; 72 if (ret && errno != EAGAIN) err(1, "KVM_CPC_READ_BATCH"); 73 74 for (i = 0; i < batch.cnt; i++) { 75 if (batch.buf[i].type == CPC_EVENT_TRACK_PAGE) { 76 printf("GFN %08llx %04x %4llu %4llu\n", 77 batch.buf[i].page.inst_gfn, 78 batch.buf[i].page.fault_err, 79 batch.buf[i].page.retinst, 80 batch.buf[i].page.retinst_user); 81 target_inst_gfn = batch.buf[i].page.inst_gfn; 82 } else if (batch.buf[i].type == CPC_EVENT_TRACK_STEP) { 83 printf("INST %08llx %04u\n", 84 batch.buf[i].step.inst_gfn, 85 batch.buf[i].step.fault_count); 86 } 87 } 88} 89 90void 91reset(int sig) 92{ 93 int ret; 94 95 ret = ioctl(kvm_dev, KVM_CPC_RESET); 96 if (ret) err(1, "KVM_CPC_RESET"); 97 98 exit(1); 99} 100 101int 102main(int argc, const char **argv) 103{ 104 uint8_t baseline[L1_SETS]; 105 struct cpc_track_cfg cfg; 106 bool first_guest_event; 107 uint32_t eventcnt; 108 uint32_t arg; 109 int ret; 110 111 pin_process(0, SECONDARY_CORE, true); 112 113 setvbuf(stdout, NULL, _IONBF, 0); 114 115 kvm_setup_init(); 116 117 ret = ioctl(kvm_dev, KVM_CPC_RESET); 118 if (ret) err(1, "KVM_CPC_RESET"); 119 120 signal(SIGINT, reset); 121 122 arg = true; 123 ret = ioctl(kvm_dev, KVM_CPC_CALC_BASELINE, &arg); 124 if (ret) err(1, "KVM_CPC_CALC_BASELINE"); 125 126 memset(&cfg, 0, sizeof(cfg)); 127 cfg.mode = CPC_TRACK_STEPS; 128 cfg.steps.with_data = true; 129 cfg.steps.use_filter = true; 130 ret = ioctl(kvm_dev, KVM_CPC_TRACK_MODE, &cfg); 131 if (ret) err(1, "KVM_CPC_RESET"); 132 133 eventcnt = 0; 134 while (eventcnt < 50) { 135 eventcnt += monitor(true); 136 } 137 138 ret = ioctl(kvm_dev, KVM_CPC_VM_REQ_PAUSE); 139 if (ret) err(1, "KVM_CPC_VM_REQ_PAUSE"); 140 141 while (1) { 142 ret = ioctl(kvm_dev, KVM_CPC_POLL_EVENT, &event); 143 if (ret && errno == EAGAIN) continue; 144 if (ret) err(1, "KVM_CPC_POLL_EVENT"); 145 146 if (event.type == CPC_EVENT_PAUSE) break; 147 148 ret = ioctl(kvm_dev, KVM_CPC_ACK_EVENT, &event.id); 149 if (ret) err(1, "KVM_CPC_ACK_EVENT"); 150 } 151 152 arg = false; 153 ret = ioctl(kvm_dev, KVM_CPC_CALC_BASELINE, &arg); 154 if (ret) err(1, "KVM_CPC_CALC_BASELINE"); 155 156 arg = true; 157 ret = ioctl(kvm_dev, KVM_CPC_APPLY_BASELINE, &arg); 158 if (ret) err(1, "KVM_CPC_APPLY_BASELINE"); 159 160 ret = ioctl(kvm_dev, KVM_CPC_READ_BASELINE, baseline); 161 if (ret) err(1, "KVM_CPC_READ_BASELINE"); 162 163 printf("\nBaseline:\n"); 164 print_counts(baseline); 165 printf("\n"); 166 print_counts_raw(baseline); 167 printf("\n\n"); 168 169 memset(&cfg, 0, sizeof(&cfg)); 170 cfg.mode = CPC_TRACK_NONE; 171 ret = ioctl(kvm_dev, KVM_CPC_TRACK_MODE, &cfg); 172 if (ret) err(1, "KVM_CPC_TRACK_MODE"); 173 174 ret = ioctl(kvm_dev, KVM_CPC_ACK_EVENT, &event.id); 175 if (ret) err(1, "KVM_CPC_ACK_EVENT"); 176 177 /* wait until guest program is run */ 178 printf("Press enter to continue..\n"); 179 getchar(); 180 181 arg = true; 182 ret = ioctl(kvm_dev, KVM_CPC_BATCH_EVENTS, &arg); 183 if (ret) err(1, "KVM_CPC_BATCH_EVENTS"); 184 185 memset(&cfg, 0, sizeof(cfg)); 186 cfg.mode = CPC_TRACK_PAGES; 187 ret = ioctl(kvm_dev, KVM_CPC_TRACK_MODE, &cfg); 188 if (ret) err(1, "KVM_CPC_TRACK_MODE"); 189 190 batch.cnt = 0; 191 batch.maxcnt = CPC_EVENT_BATCH_MAX; 192 batch.buf = malloc(sizeof(struct cpc_event) * batch.maxcnt); 193 if (!batch.buf) err(1, "malloc"); 194 195 first_guest_event = true; 196 while (1) { 197 ret = ioctl(kvm_dev, KVM_CPC_POLL_EVENT, &event); 198 if (ret && errno == EAGAIN) continue; 199 if (ret) err(1, "KVM_CPC_POLL_EVENT"); 200 201 if (event.type == CPC_EVENT_GUEST) { 202 read_batch(); 203 printf("Guest %s\n", 204 !event.guest.type ? "start" : "stop"); 205 } 206 207 if (event.type == CPC_EVENT_GUEST 208 && event.guest.type == CPC_GUEST_START_TRACK) { 209 if (!first_guest_event) 210 break; 211 first_guest_event = false; 212 } 213 214 if (event.type == CPC_EVENT_BATCH) 215 read_batch(); 216 217 ret = ioctl(kvm_dev, KVM_CPC_ACK_EVENT, &event.id); 218 if (ret) err(1, "KVM_CPC_ACK_EVENT"); 219 } 220 221 read_batch(); 222 223 if (!batch.cnt) errx(1, "empty batch buffer"); 224 memset(&cfg, 0, sizeof(cfg)); 225 cfg.mode = CPC_TRACK_STEPS; 226 cfg.steps.target_gfn = target_inst_gfn; 227 cfg.steps.use_target = true; 228 //cfg.steps.use_filter = true; 229 //cfg.steps.with_data = true; 230 ret = ioctl(kvm_dev, KVM_CPC_TRACK_MODE, &cfg); 231 if (ret) err(1, "KVM_CPC_TRACK_MODE"); 232 233 ret = ioctl(kvm_dev, KVM_CPC_ACK_EVENT, &event.id); 234 if (ret) err(1, "KVM_CPC_ACK_EVENT"); 235 236 printf("Target GFN: %08llx\n", cfg.steps.target_gfn); 237 238 while (monitor(false) != 2); 239 read_batch(); 240 241 signal(SIGINT, NULL); 242 243 ret = ioctl(kvm_dev, KVM_CPC_RESET); 244 if (ret) err(1, "KVM_CPC_RESET"); 245 246 free(batch.buf); 247 248 kvm_setup_deinit(); 249} 250