summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorLouis Burda <quent.burda@gmail.com>2022-11-22 15:03:02 +0100
committerLouis Burda <quent.burda@gmail.com>2022-11-22 15:03:02 +0100
commit82d56ef77c114ac0b375fef04cea3a50f10f1843 (patch)
tree397acfbcb5f1c2584a03f6201d95120d6f299361 /test
parentafe49b52f6b2ac52efe8e610e64ee07c7c2efef4 (diff)
downloadcachepc-82d56ef77c114ac0b375fef04cea3a50f10f1843.tar.gz
cachepc-82d56ef77c114ac0b375fef04cea3a50f10f1843.zip
Improved single stepping and added initial cpuid events
Diffstat (limited to 'test')
-rwxr-xr-xtest/.gitignore4
-rw-r--r--test/access-detect_guest.c26
-rw-r--r--test/access-detect_host.c288
-rwxr-xr-xtest/aes-detect_guestbin1007048 -> 826488 bytes
-rw-r--r--test/aes-detect_guest.c16
-rw-r--r--test/sevstep.c33
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
index de1ec2f..d482fd2 100755
--- a/test/aes-detect_guest
+++ b/test/aes-detect_guest
Binary files differ
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;
}