diff options
| author | Louis Burda <quent.burda@gmail.com> | 2023-01-24 01:43:18 +0100 |
|---|---|---|
| committer | Louis Burda <quent.burda@gmail.com> | 2023-01-24 01:43:18 +0100 |
| commit | 501c6bcf4513d40a53022dc93d4156402d43670b (patch) | |
| tree | 51ca4bdd9bbc5d9db2b6aa1e84f10dd361fb9037 | |
| parent | 1fe8249bbc782d28185e0e893504e8ac3a1fcaec (diff) | |
| download | cachepc-501c6bcf4513d40a53022dc93d4156402d43670b.tar.gz cachepc-501c6bcf4513d40a53022dc93d4156402d43670b.zip | |
Page track support (without speculation)
| -rw-r--r-- | cachepc/cachepc.h | 10 | ||||
| -rw-r--r-- | cachepc/kvm.c | 28 | ||||
| m--------- | linux | 0 | ||||
| -rw-r--r-- | test/kvm-pagestep.c | 118 | ||||
| -rw-r--r-- | test/kvm.c | 3 |
5 files changed, 62 insertions, 97 deletions
diff --git a/cachepc/cachepc.h b/cachepc/cachepc.h index 9522716..42707cb 100644 --- a/cachepc/cachepc.h +++ b/cachepc/cachepc.h @@ -65,6 +65,12 @@ struct cpc_fault { struct list_head list; }; +struct cpc_track_exec { + bool cur_avail; + uint64_t cur_gfn; + uint64_t retinst; +}; + static_assert(sizeof(struct cacheline) == L1_LINESIZE, "Bad cacheline struct"); static_assert(CPC_CL_NEXT_OFFSET == offsetof(struct cacheline, next)); static_assert(CPC_CL_PREV_OFFSET == offsetof(struct cacheline, prev)); @@ -128,9 +134,7 @@ extern uint64_t cachepc_rip; extern uint64_t cachepc_rip_prev; extern bool cachepc_rip_prev_set; -extern uint64_t cachepc_inst_fault_gfn; -extern uint32_t cachepc_inst_fault_err; -extern uint64_t cachepc_inst_fault_retinst; +extern struct cpc_track_exec cachepc_track_exec; extern struct list_head cachepc_faults; diff --git a/cachepc/kvm.c b/cachepc/kvm.c index 083aafb..3809737 100644 --- a/cachepc/kvm.c +++ b/cachepc/kvm.c @@ -71,12 +71,8 @@ EXPORT_SYMBOL(cachepc_track_end_gfn); LIST_HEAD(cachepc_faults); EXPORT_SYMBOL(cachepc_faults); -uint64_t cachepc_inst_fault_gfn = 0; -uint32_t cachepc_inst_fault_err = 0; -uint64_t cachepc_inst_fault_retinst = 0; -EXPORT_SYMBOL(cachepc_inst_fault_gfn); -EXPORT_SYMBOL(cachepc_inst_fault_err); -EXPORT_SYMBOL(cachepc_inst_fault_retinst); +struct cpc_track_exec cachepc_track_exec; +EXPORT_SYMBOL(cachepc_track_exec); cache_ctx *cachepc_ctx = NULL; cacheline *cachepc_ds = NULL; @@ -290,6 +286,8 @@ cachepc_kvm_reset_ioctl(void __user *arg_user) put_cpu(); + cachepc_events_reset(); + cachepc_kvm_reset_tracking_ioctl(NULL); cachepc_kvm_reset_baseline_ioctl(NULL); @@ -477,12 +475,11 @@ cachepc_kvm_reset_tracking_ioctl(void __user *arg_user) cachepc_untrack_all(vcpu, KVM_PAGE_TRACK_ACCESS); cachepc_untrack_all(vcpu, KVM_PAGE_TRACK_WRITE); - cachepc_inst_fault_gfn = 0; - cachepc_inst_fault_err = 0; - cachepc_track_start_gfn = 0; cachepc_track_end_gfn = 0; + memset(&cachepc_track_exec, 0, sizeof(cachepc_track_exec)); + cachepc_singlestep = false; cachepc_singlestep_reset = false; @@ -526,22 +523,22 @@ cachepc_kvm_track_mode_ioctl(void __user *arg_user) case CPC_TRACK_FULL: cachepc_track_all(vcpu, KVM_PAGE_TRACK_ACCESS); cachepc_singlestep_reset = true; - cachepc_track_mode = CPC_TRACK_FULL; break; case CPC_TRACK_EXEC: cachepc_track_all(vcpu, KVM_PAGE_TRACK_EXEC); cachepc_singlestep_reset = true; - cachepc_track_mode = CPC_TRACK_EXEC; break; case CPC_TRACK_FAULT_NO_RUN: cachepc_track_all(vcpu, KVM_PAGE_TRACK_ACCESS); - cachepc_track_mode = CPC_TRACK_FAULT_NO_RUN; break; - default: - cachepc_track_mode = CPC_TRACK_NONE; + case CPC_TRACK_NONE: break; + default: + return -EINVAL; } + cachepc_track_mode = mode; + return 0; } @@ -740,8 +737,7 @@ cachepc_kvm_init(void) cachepc_apic_oneshot = false; cachepc_apic_timer = 0; - cachepc_inst_fault_gfn = 0; - cachepc_inst_fault_err = 0; + memset(&cachepc_track_exec, 0, sizeof(cachepc_track_exec)); INIT_LIST_HEAD(&cachepc_faults); diff --git a/linux b/linux -Subproject 7dff256416aa9eb34d6687106644c3343051738 +Subproject abccf24ec694dd3d9196b8c03b9c1f0b3f2575a diff --git a/test/kvm-pagestep.c b/test/kvm-pagestep.c index c306e17..e04429b 100644 --- a/test/kvm-pagestep.c +++ b/test/kvm-pagestep.c @@ -5,8 +5,8 @@ #include <sys/ioctl.h> #include <sys/mman.h> -#include <unistd.h> #include <signal.h> +#include <unistd.h> #include <fcntl.h> #include <errno.h> #include <err.h> @@ -21,11 +21,12 @@ extern uint8_t guest_start[]; extern uint8_t guest_stop[]; +static int child; + uint64_t monitor(struct kvm *kvm, bool baseline) { struct cpc_event event; - uint8_t counts[64]; int ret; /* Get page fault info */ @@ -33,17 +34,12 @@ monitor(struct kvm *kvm, bool baseline) if (ret && errno == EAGAIN) return 0; if (ret) err(1, "ioctl KVM_CPC_POLL_EVENT"); - if (event.type != CPC_EVENT_TRACK_STEP) + if (event.type != CPC_EVENT_TRACK_PAGE) errx(1, "unexpected event type %i", event.type); - ret = ioctl(kvm_dev, KVM_CPC_READ_COUNTS, counts); - if (ret) err(1, "ioctl KVM_CPC_READ_COUNTS"); - - printf("Event: rip:%llu cnt:%llu inst:%llu data:%llu ret:%llu\n", - vm_get_rip(kvm), event.step.fault_count, - event.step.fault_gfns[0], event.step.fault_gfns[1], - event.step.retinst); - print_counts(counts); + printf("Event: rip:%08llx prev:%llu next:%llu ret:%llu\n", + vm_get_rip(kvm), event.page.inst_gfn_prev, + event.page.inst_gfn, event.page.retinst); printf("\n"); ret = ioctl(kvm_dev, KVM_CPC_ACK_EVENT, &event.id); @@ -52,36 +48,48 @@ monitor(struct kvm *kvm, bool baseline) return 1; } +void +kill_child(void) +{ + kill(child, SIGKILL); +} + int main(int argc, const char **argv) { + struct ipc *ipc; struct kvm kvm; - uint8_t baseline[L1_SETS]; - struct cpc_event event; uint64_t eventcnt; - pid_t ppid, pid; uint32_t arg; int ret; - parse_vmtype(argc, argv); + vmtype = "kvm"; + if (argc > 1) vmtype = argv[1]; + if (strcmp(vmtype, "kvm") && strcmp(vmtype, "sev") + && strcmp(vmtype, "sev-es") + && strcmp(vmtype, "sev-snp")) + errx(1, "invalid vm mode: %s", vmtype); setvbuf(stdout, NULL, _IONBF, 0); - pin_process(0, TARGET_CORE, true); - kvm_setup_init(); - vm_init(&kvm, guest_start, guest_stop); + ipc = ipc_alloc(); + + child = fork(); + if (child < 0) err(1, "fork"); - /* reset kernel module state */ - ret = ioctl(kvm_dev, KVM_CPC_RESET, NULL); - if (ret < 0) err(1, "ioctl KVM_CPC_RESET"); + if (child == 0) { + pin_process(0, TARGET_CORE, true); - ppid = getpid(); - if ((pid = fork())) { - if (pid < 0) err(1, "fork"); + vm_init(&kvm, guest_start, guest_stop); - sleep(1); /* give time for child to pin other core */ + /* reset kernel module state */ + ret = ioctl(kvm_dev, KVM_CPC_RESET, NULL); + if (ret < 0) err(1, "ioctl KVM_CPC_RESET"); + + ipc_signal_parent(ipc); + ipc_wait_parent(ipc); printf("VM start\n"); @@ -94,72 +102,32 @@ main(int argc, const char **argv) } while (kvm.run->exit_reason == KVM_EXIT_HLT); printf("VM exit\n"); + + vm_deinit(&kvm); } else { pin_process(0, SECONDARY_CORE, true); - /* capture baseline by just letting it fault over and over */ - arg = CPC_TRACK_EXEC; - ret = ioctl(kvm_dev, KVM_CPC_TRACK_MODE, &arg); - if (ret) err(1, "ioctl KVM_CPC_TRACK_MODE"); - - printf("Monitor ready\n"); - - /* run vm while baseline is calculated */ - eventcnt = 0; - while (eventcnt < 50) { - eventcnt += monitor(&kvm, true); - } - - ret = ioctl(kvm_dev, KVM_CPC_VM_REQ_PAUSE); - if (ret) err(1, "ioctl KVM_CPC_VM_REQ_PAUSE"); + atexit(kill_child); - while (1) { - ret = ioctl(kvm_dev, KVM_CPC_POLL_EVENT, &event); - if (ret && errno == EAGAIN) continue; - if (ret) err(1, "ioctl KVM_CPC_POLL_EVENT"); + ipc_wait_child(ipc); - if (event.type == CPC_EVENT_PAUSE) break; + printf("Monitor start\n"); - printf("Skipping non-pause event..\n"); - ret = ioctl(kvm_dev, KVM_CPC_ACK_EVENT, &event.id); - if (ret) err(1, "ioctl KVM_CPC_ACK_EVENT"); - } - - arg = false; - ret = ioctl(kvm_dev, KVM_CPC_CALC_BASELINE, &arg); - if (ret) err(1, "ioctl KVM_CPC_CALC_BASELINE"); - - ret = ioctl(kvm_dev, KVM_CPC_READ_BASELINE, baseline); - if (ret) err(1, "ioctl KVM_CPC_READ_BASELINE"); - - printf("\nBaseline:\n"); - print_counts(baseline); - printf("\n"); - print_counts_raw(baseline); - printf("\n\n"); - - arg = true; - ret = ioctl(kvm_dev, KVM_CPC_APPLY_BASELINE, &arg); - if (ret) err(1, "ioctl KMV_CPC_APPLY_BASELINE"); - - /* single step and log all accessed pages */ - arg = CPC_TRACK_FULL; + arg = CPC_TRACK_EXEC; ret = ioctl(kvm_dev, KVM_CPC_TRACK_MODE, &arg); if (ret) err(1, "ioctl KVM_CPC_TRACK_MODE"); - ret = ioctl(kvm_dev, KVM_CPC_ACK_EVENT, &event.id); - if (ret) err(1, "ioctl KVM_CPC_ACK_EVENT"); + ipc_signal_child(ipc); eventcnt = 0; while (eventcnt < 50) { - eventcnt += monitor(&kvm, false); + eventcnt += monitor(&kvm, true); } - kill(ppid, SIGINT); - exit(0); + printf("Monitor exit\n"); } - vm_deinit(&kvm); + ipc_free(ipc); kvm_setup_deinit(); } @@ -226,9 +226,6 @@ kvm_init_memory(struct kvm *kvm, size_t ramsize, assert(code_stop - code_start <= kvm->memsize); memcpy(kvm->mem, code_start, code_stop - code_start); - printf("KVM Memory:\n"); - hexdump(code_start, code_stop - code_start); - memset(®ion, 0, sizeof(region)); region.slot = 0; region.memory_size = kvm->memsize; |
