diff options
| author | Louis Burda <quent.burda@gmail.com> | 2022-11-22 15:03:02 +0100 |
|---|---|---|
| committer | Louis Burda <quent.burda@gmail.com> | 2022-11-22 15:03:02 +0100 |
| commit | 82d56ef77c114ac0b375fef04cea3a50f10f1843 (patch) | |
| tree | 397acfbcb5f1c2584a03f6201d95120d6f299361 /test | |
| parent | afe49b52f6b2ac52efe8e610e64ee07c7c2efef4 (diff) | |
| download | cachepc-82d56ef77c114ac0b375fef04cea3a50f10f1843.tar.gz cachepc-82d56ef77c114ac0b375fef04cea3a50f10f1843.zip | |
Improved single stepping and added initial cpuid events
Diffstat (limited to 'test')
| -rwxr-xr-x | test/.gitignore | 4 | ||||
| -rw-r--r-- | test/access-detect_guest.c | 26 | ||||
| -rw-r--r-- | test/access-detect_host.c | 288 | ||||
| -rwxr-xr-x | test/aes-detect_guest | bin | 1007048 -> 826488 bytes | |||
| -rw-r--r-- | test/aes-detect_guest.c | 16 | ||||
| -rw-r--r-- | test/sevstep.c | 33 |
6 files changed, 355 insertions, 12 deletions
diff --git a/test/.gitignore b/test/.gitignore index c2e8d30..f54caf0 100755 --- a/test/.gitignore +++ b/test/.gitignore @@ -5,3 +5,7 @@ sev sev-es sev-snp sevstep +aes-detect_guest +aes-detect_host +access-detect_guest +access-detect_host diff --git a/test/access-detect_guest.c b/test/access-detect_guest.c new file mode 100644 index 0000000..442c88c --- /dev/null +++ b/test/access-detect_guest.c @@ -0,0 +1,26 @@ +#include "cachepc/uapi.h" + +#include <err.h> +#include <unistd.h> +#include <stdint.h> +#include <string.h> +#include <stdlib.h> + +int +main(int argc, const char **argv) +{ + void *buf; + + buf = NULL; + if (posix_memalign(&buf, L1_LINESIZE * L1_SETS, L1_LINESIZE * L1_SETS)) + err(1, "memalign"); + memset(buf, 0, L1_LINESIZE * L1_SETS); + + while (1) { + CPC_CPUID_SIGNAL(CPC_CPUID_START_TRACK, 0); + + *(uint8_t *)(buf + L1_LINESIZE * 5) += 1; + + CPC_CPUID_SIGNAL(CPC_CPUID_START_TRACK, 0); + } +} diff --git a/test/access-detect_host.c b/test/access-detect_host.c new file mode 100644 index 0000000..9ede56f --- /dev/null +++ b/test/access-detect_host.c @@ -0,0 +1,288 @@ +#define _GNU_SOURCE + +#include "cachepc/uapi.h" + +#include <linux/psp-sev.h> +#include <linux/kvm.h> +#include <sys/syscall.h> +#include <sys/ioctl.h> +#include <sys/user.h> +#include <sys/wait.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> +#include <signal.h> +#include <dirent.h> +#include <assert.h> +#include <errno.h> +#include <err.h> +#include <fcntl.h> +#include <sched.h> +#include <string.h> +#include <stdbool.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdio.h> +#include <stdarg.h> + +#define ARRLEN(x) (sizeof(x) / sizeof((x)[0])) +#define MIN(a,b) ((a) > (b) ? (b) : (a)) + +#define TARGET_CORE 2 +#define SECONDARY_CORE 3 + +#define TARGET_SET 15 + +/* ioctl dev fds */ +static int kvm_dev; +static int faultcnt; + +void +hexdump(void *data, int len) +{ + int i; + + for (i = 0; i < len; i++) { + if (i % 16 == 0 && i) + printf("\n"); + printf("%02X ", *(uint8_t *)(data + i)); + } + printf("\n"); +} + +bool +pin_process(pid_t pid, int cpu, bool assert) +{ + cpu_set_t cpuset; + int ret; + + CPU_ZERO(&cpuset); + CPU_SET(cpu, &cpuset); + ret = sched_setaffinity(pid, sizeof(cpu_set_t), &cpuset); + if (ret < 0) { + if (assert) err(1, "sched_setaffinity"); + return false; + } + + return true; +} + +cpc_msrmt_t * +read_counts() +{ + cpc_msrmt_t *counts; + int i, ret; + + counts = malloc(L1_SETS * sizeof(cpc_msrmt_t)); + if (!counts) err(1, "malloc"); + + ret = ioctl(kvm_dev, KVM_CPC_READ_COUNTS, counts); + if (ret == -1) err(1, "ioctl READ_COUNTS"); + + for (i = 0; i < L1_SETS; i++) { + if (counts[i] > 8) + errx(1, "Invalid counts set %i", i); + } + + return counts; +} + +void +print_counts(cpc_msrmt_t *counts) +{ + int i; + + for (i = 0; i < 64; i++) { + if (i % 16 == 0 && i) + printf("\n"); + if (counts[i] == 1) + printf("\x1b[38;5;88m"); + else if (counts[i] > 1) + printf("\x1b[38;5;196m"); + printf("%2i ", i); + if (counts[i] > 0) + printf("\x1b[0m"); + } + printf("\n"); +} + +void +print_counts_raw(cpc_msrmt_t *counts) +{ + int i; + + for (i = 0; i < 64; i++) { + if (i % 16 == 0 && i) + printf("\n"); + if (counts[i] == 1) + printf("\x1b[38;5;88m"); + else if (counts[i] > 1) + printf("\x1b[38;5;196m"); + printf("%02X ", (uint8_t) counts[i]); + if (counts[i] > 0) + printf("\x1b[0m"); + } + printf("\n"); +} + +int +monitor(bool baseline) +{ + struct cpc_event event; + cpc_msrmt_t counts[64]; + uint64_t track_mode; + int ret, i; + + /* Get page fault info */ + ret = ioctl(kvm_dev, KVM_CPC_POLL_EVENT, &event); + if (!ret) { + if (event.type == CPC_EVENT_CPUID) { + printf("CPUID EVENT\n"); + if (event.cpuid.type == CPC_CPUID_START_TRACK) { + track_mode = KVM_PAGE_TRACK_ACCESS; + ret = ioctl(kvm_dev, KVM_CPC_TRACK_ALL, &track_mode); + if (ret) err(1, "ioctl TRACK_ALL"); + } else if (event.cpuid.type == CPC_CPUID_STOP_TRACK) { + track_mode = KVM_PAGE_TRACK_ACCESS; + ret = ioctl(kvm_dev, KVM_CPC_UNTRACK_ALL, &track_mode); + if (ret) err(1, "ioctl UNTRACK_ALL"); + } + return 0; + } else if (event.type != CPC_EVENT_TRACK) { + return 0; + } + + printf("EVENT\n"); + + ret = ioctl(kvm_dev, KVM_CPC_READ_COUNTS, counts); + if (ret == -1) err(1, "ioctl READ_COUNTS"); + + if (!baseline) { + printf("Event: inst:%llu data:%llu retired:%llu\n", + event.track.inst_fault_gfn, + event.track.data_fault_gfn, + event.track.retinst); + print_counts(counts); + printf("\n"); + } + + for (i = 0; i < 64; i++) { + if (counts[i] > 8) { + errx(1, "Invalid count for set %i (%llu)", + i, counts[i]); + } + } + + ret = ioctl(kvm_dev, KVM_CPC_ACK_EVENT, &event.track.id); + if (ret == -1) err(1, "ioctl ACK_EVENT"); + + faultcnt++; + } else if (errno != EAGAIN) { + perror("ioctl POLL_EVENT"); + return 1; + } + + return 0; +} + +int +main(int argc, const char **argv) +{ + pid_t pid; + uint32_t arg; + struct cpc_event event; + cpc_msrmt_t baseline[64]; + int ret, i; + + if (argc <= 1 || !atoi(argv[1])) { + printf("Specify qemu process to pin\n"); + return 0; + } + + kvm_dev = open("/dev/kvm", O_RDWR); + if (!kvm_dev) err(1, "open /dev/kvm"); + + setvbuf(stdout, NULL, _IONBF, 0); + + pid = atoi(argv[1]); + pin_process(pid, TARGET_CORE, true); + + pin_process(0, TARGET_CORE, true); + + /* Setup needed performance counters */ + ret = ioctl(kvm_dev, KVM_CPC_SETUP_PMC, NULL); + if (ret < 0) err(1, "ioctl SETUP_PMC"); + + /* Reset previous tracking */ + ret = ioctl(kvm_dev, KVM_CPC_RESET_TRACKING, NULL); + if (ret == -1) err(1, "ioctl RESET_TRACKING"); + + /* Do data access stepping */ + arg = CPC_TRACK_DATA_ACCESS; + ret = ioctl(kvm_dev, KVM_CPC_TRACK_MODE, &arg); + if (ret == -1) err(1, "ioctl TRACK_MODE"); + + pin_process(0, SECONDARY_CORE, true); + printf("PINNED\n"); + + arg = false; + ret = ioctl(kvm_dev, KVM_CPC_SUB_BASELINE, &arg); + if (ret == -1) err(1, "ioctl SUB_BASELINE"); + + arg = true; + ret = ioctl(kvm_dev, KVM_CPC_MEASURE_BASELINE, &arg); + if (ret == -1) err(1, "ioctl MEASURE_BASELINE"); + + arg = KVM_PAGE_TRACK_ACCESS; + ret = ioctl(kvm_dev, KVM_CPC_TRACK_ALL, &arg); + if (ret) err(1, "ioctl TRACK_ALL"); + + faultcnt = 0; + while (faultcnt < 100) { + if (monitor(true)) break; + } + + arg = KVM_PAGE_TRACK_ACCESS; + ret = ioctl(kvm_dev, KVM_CPC_UNTRACK_ALL, &arg); + if (ret) err(1, "ioctl TRACK_ALL"); + + do { + ret = ioctl(kvm_dev, KVM_CPC_POLL_EVENT, &event); + if (ret == -1 && errno != EAGAIN) + err(1, "ioctl POLL_EVENT"); + } while (ret == -1 && errno == EAGAIN); + + arg = false; + ret = ioctl(kvm_dev, KVM_CPC_MEASURE_BASELINE, &arg); + if (ret == -1) err(1, "ioctl MEASURE_BASELINE"); + + ret = ioctl(kvm_dev, KVM_CPC_READ_BASELINE, baseline); + if (ret == -1) err(1, "ioctl READ_BASELINE"); + + printf("\n>>> BASELINE:\n"); + print_counts(baseline); + printf("\n"); + print_counts_raw(baseline); + printf("\n"); + + /* Check baseline for saturated sets */ + for (i = 0; i < 64; i++) { + if (baseline[i] >= 8) + errx(1, "!!! Baseline set %i full\n", i); + } + + arg = true; + ret = ioctl(kvm_dev, KVM_CPC_SUB_BASELINE, &arg); + if (ret == -1) err(1, "ioctl SUB_BASELINE"); + + ret = ioctl(kvm_dev, KVM_CPC_ACK_EVENT, &event.track.id); + if (ret == -1) err(1, "ioctl ACK_EVENT"); + + faultcnt = 0; + while (faultcnt < 10) { + if (monitor(false)) break; + } +} + diff --git a/test/aes-detect_guest b/test/aes-detect_guest Binary files differindex de1ec2f..d482fd2 100755 --- a/test/aes-detect_guest +++ b/test/aes-detect_guest diff --git a/test/aes-detect_guest.c b/test/aes-detect_guest.c index 4012b74..80a6a64 100644 --- a/test/aes-detect_guest.c +++ b/test/aes-detect_guest.c @@ -30,8 +30,24 @@ main(int argc, const char **argv) { struct kcapi_handle *kcapi; uint8_t block[128]; + uint8_t *buf; size_t n; + buf = NULL; + if (posix_memalign((void *)&buf, L1_LINESIZE * L1_SETS, L1_LINESIZE * L1_SETS)) + err(1, "memalign"); + memset(buf, 0, L1_LINESIZE * L1_SETS); + + while (1) { + CPC_CPUID_SIGNAL(CPC_CPUID_START_TRACK, 0); + + buf[L1_LINESIZE * 5] += 1; + + CPC_CPUID_SIGNAL(CPC_CPUID_START_TRACK, 0); + } + + return 0; + kcapi = NULL; if (kcapi_cipher_init(&kcapi, "ecb(aes)", 0)) err(1, "kcapi init"); diff --git a/test/sevstep.c b/test/sevstep.c index 3307245..40130c5 100644 --- a/test/sevstep.c +++ b/test/sevstep.c @@ -481,7 +481,7 @@ int monitor(struct kvm *kvm, bool baseline) { static uint64_t rip_prev = 1; - struct cpc_track_event event; + struct cpc_event event; cpc_msrmt_t counts[64]; uint64_t rip; int ret, i; @@ -489,17 +489,24 @@ monitor(struct kvm *kvm, bool baseline) /* Get page fault info */ ret = ioctl(kvm_dev, KVM_CPC_POLL_EVENT, &event); if (!ret) { + if (event.type != CPC_EVENT_TRACK) + return 0; + ret = ioctl(kvm_dev, KVM_CPC_READ_COUNTS, counts); if (ret == -1) err(1, "ioctl READ_COUNTS"); rip = sev_dbg_rip(kvm->vmfd); if (!baseline && rip != rip_prev) { printf("Event: inst:%llu data:%llu retired:%llu rip:%lu\n", - event.inst_fault_gfn, event.data_fault_gfn, - event.retinst, rip); + event.track.inst_fault_gfn, + event.track.data_fault_gfn, + event.track.retinst, rip); print_counts(counts); printf("\n"); rip_prev = rip; + faultcnt++; + } else if (baseline) { + faultcnt++; } for (i = 0; i < 64; i++) { @@ -511,8 +518,6 @@ monitor(struct kvm *kvm, bool baseline) ret = ioctl(kvm_dev, KVM_CPC_ACK_EVENT, &event.id); if (ret == -1) err(1, "ioctl ACK_EVENT"); - - faultcnt++; } else if (errno != EAGAIN) { perror("ioctl POLL_EVENT"); return 1; @@ -528,7 +533,7 @@ main(int argc, const char **argv) uint64_t track_mode; pid_t ppid, pid; uint32_t arg; - struct cpc_track_event event; + struct cpc_event event; cpc_msrmt_t baseline[64]; int ret, i; @@ -571,6 +576,14 @@ main(int argc, const char **argv) ret = ioctl(kvm_dev, KVM_CPC_TRACK_ALL, &track_mode); if (ret == -1) err(1, "ioctl TRACK_ALL"); + arg = false; + ret = ioctl(kvm_dev, KVM_CPC_SUB_BASELINE, &arg); + if (ret == -1) err(1, "ioctl SUB_BASELINE"); + + arg = true; + ret = ioctl(kvm_dev, KVM_CPC_MEASURE_BASELINE, &arg); + if (ret == -1) err(1, "ioctl MEASURE_BASELINE"); + ppid = getpid(); if ((pid = fork())) { if (pid < 0) err(1, "fork"); @@ -584,12 +597,8 @@ main(int argc, const char **argv) pin_process(0, SECONDARY_CORE, true); printf("PINNED\n"); - arg = true; - ret = ioctl(kvm_dev, KVM_CPC_MEASURE_BASELINE, &arg); - if (ret == -1) err(1, "ioctl MEASURE_BASELINE"); - faultcnt = 0; - while (faultcnt < 50) { + while (faultcnt < 300) { if (monitor(&kvm_with_access, true)) break; } @@ -626,7 +635,7 @@ main(int argc, const char **argv) if (ret == -1) err(1, "ioctl ACK_EVENT"); faultcnt = 0; - while (faultcnt < 50) { + while (faultcnt < 20) { if (monitor(&kvm_with_access, false)) break; } |
