cachepc

Prime+Probe cache-based side-channel attack on AMD SEV-SNP protected virtual machines
git clone https://git.sinitax.com/sinitax/cachepc
Log | Files | Refs | Submodules | README | sfeed.txt

commit 0c825583fc20f1b91c56e1aaf450d6a753d24658
parent ca3b348013267bf727ba52bb6fc97a7ab7d367dc
Author: Louis Burda <quent.burda@gmail.com>
Date:   Thu,  2 Feb 2023 18:38:00 -0600

qemu-pagestep is quasi-realtime when suppresing slow kernel logging

Diffstat:
MMakefile | 2+-
Mcachepc/cachepc.h | 14+++++++++++---
Mcachepc/const.h | 3+++
Mcachepc/kvm.c | 44++++++++++++++++++++++++++++++++++----------
Mcachepc/uapi.h | 2+-
Mutil/.gitignore | 2+-
Dutil/debug.c | 25-------------------------
Autil/loglevel.c | 34++++++++++++++++++++++++++++++++++
8 files changed, 85 insertions(+), 41 deletions(-)

diff --git a/Makefile b/Makefile @@ -12,7 +12,7 @@ BINS += test/kvm-pagestep test/kvm-pagestep_guest BINS += test/qemu-pagestep BINS += test/qemu-eviction test/qemu-eviction_guest # BINS += test/qemu-aes_guest test/qemu-aes -BINS += util/debug util/reset util/mainpfn +BINS += util/loglevel util/reset util/mainpfn CFLAGS = -I . -I linux/usr/include CFLAGS += -g -Wunused-variable -Wunknown-pragmas -Wunused-function diff --git a/cachepc/cachepc.h b/cachepc/cachepc.h @@ -12,8 +12,13 @@ #define PMC_GUEST (1 << 0) #define CPC_DBG(...) do { \ - if (cpc_debug) pr_info("CachePC: " __VA_ARGS__); } while (0) -#define CPC_INFO(...) do { pr_info("CachePC: " __VA_ARGS__); } while (0) + if (cpc_loglevel >= CPC_LOGLVL_DBG) \ + pr_info("CachePC: " __VA_ARGS__); \ + } while (0) +#define CPC_INFO(...) do { \ + if (cpc_loglevel >= CPC_LOGLVL_INFO) \ + pr_info("CachePC: " __VA_ARGS__); \ + } while (0) #define CPC_WARN(...) do { pr_warn("CachePC: " __VA_ARGS__); } while (0) #define CPC_ERR(...) do { pr_err("CachePC: " __VA_ARGS__); } while (0) @@ -83,7 +88,7 @@ uint64_t cpc_read_pmc(uint64_t event); void cpc_apic_oneshot_run(uint32_t interval); -extern bool cpc_debug; +extern uint32_t cpc_loglevel; extern uint8_t *cpc_msrmts; extern uint8_t *cpc_baseline; @@ -102,6 +107,9 @@ extern bool cpc_long_step; extern bool cpc_apic_oneshot; extern int32_t cpc_apic_timer; +extern uint32_t cpc_apic_timer_min; +extern uint32_t cpc_apic_timer_dec_npf; +extern uint32_t cpc_apic_timer_dec_intr; extern uint32_t cpc_track_mode; extern uint64_t cpc_track_start_gfn; diff --git a/cachepc/const.h b/cachepc/const.h @@ -28,3 +28,6 @@ #define CPC_APIC_TIMER_MIN (20 * CPC_APIC_TIMER_SOFTDIV) #define CPC_EVENT_BATCH_MAX 1000 + +#define CPC_LOGLVL_INFO 1 +#define CPC_LOGLVL_DBG 2 diff --git a/cachepc/kvm.c b/cachepc/kvm.c @@ -18,8 +18,8 @@ #define TEST_REPEAT_MAX 1000 -bool cpc_debug = false; -EXPORT_SYMBOL(cpc_debug); +uint32_t cpc_loglevel = 0; +EXPORT_SYMBOL(cpc_loglevel); uint8_t *cpc_msrmts = NULL; EXPORT_SYMBOL(cpc_msrmts); @@ -64,6 +64,13 @@ int32_t cpc_apic_timer = 0; EXPORT_SYMBOL(cpc_apic_oneshot); EXPORT_SYMBOL(cpc_apic_timer); +uint32_t cpc_apic_timer_min = 0; +uint32_t cpc_apic_timer_dec_npf = 0; +uint32_t cpc_apic_timer_dec_intr = 0; +EXPORT_SYMBOL(cpc_apic_timer_min); +EXPORT_SYMBOL(cpc_apic_timer_dec_npf); +EXPORT_SYMBOL(cpc_apic_timer_dec_intr); + uint32_t cpc_track_mode = false; uint64_t cpc_track_start_gfn = 0; uint64_t cpc_track_end_gfn = 0; @@ -101,7 +108,7 @@ static void cpc_pmc_setup(void *p); static void cpc_system_setup(void); static int cpc_reset_ioctl(void __user *arg_user); -static int cpc_debug_ioctl(void __user *arg_user); +static int cpc_loglevel_ioctl(void __user *arg_user); static int cpc_memory_encrypt_op_ioctl(void __user *arg_user); @@ -298,16 +305,16 @@ cpc_reset_ioctl(void __user *arg_user) } int -cpc_debug_ioctl(void __user *arg_user) +cpc_loglevel_ioctl(void __user *arg_user) { - uint32_t debug; + uint32_t level; if (!arg_user) return -EINVAL; - if (copy_from_user(&debug, arg_user, sizeof(uint32_t))) + if (copy_from_user(&level, arg_user, sizeof(uint32_t))) return -EFAULT; - cpc_debug = debug; + cpc_loglevel = level; return 0; } @@ -474,6 +481,16 @@ cpc_track_mode_ioctl(void __user *arg_user) cpc_singlestep_reset = false; cpc_long_step = false; + if (sev_es_guest(vcpu->kvm)) { + cpc_apic_timer_min = 200; + cpc_apic_timer_dec_npf = 25; + cpc_apic_timer_dec_intr = 50; + } else { + cpc_apic_timer_min = 15; + cpc_apic_timer_dec_npf = 5; + cpc_apic_timer_dec_intr = 10; + } + switch (cfg.mode) { case CPC_TRACK_FAULT_NO_RUN: cpc_prime_probe = true; @@ -489,6 +506,9 @@ cpc_track_mode_ioctl(void __user *arg_user) cpc_track_all(vcpu, KVM_PAGE_TRACK_EXEC); break; case CPC_TRACK_STEPS: + cpc_apic_timer_min = 7000; + cpc_apic_timer_dec_npf = 25; + cpc_apic_timer_dec_intr = 50; cpc_track_steps.use_target = cfg.steps.use_target; cpc_track_steps.target_gfn = cfg.steps.target_gfn; cpc_track_steps.with_data = cfg.steps.with_data; @@ -599,8 +619,8 @@ cpc_kvm_ioctl(struct file *file, unsigned int ioctl, unsigned long arg) switch (ioctl) { case KVM_CPC_RESET: return cpc_reset_ioctl(arg_user); - case KVM_CPC_DEBUG: - return cpc_debug_ioctl(arg_user); + case KVM_CPC_LOGLEVEL: + return cpc_loglevel_ioctl(arg_user); case KVM_CPC_MEMORY_ENCRYPT_OP: return cpc_memory_encrypt_op_ioctl(arg_user); case KVM_CPC_TEST_EVICTION: @@ -678,7 +698,7 @@ cpc_kvm_init(void) { int ret; - cpc_debug = false; + cpc_loglevel = 1; cpc_ds = NULL; cpc_ds_ul = NULL; @@ -693,6 +713,10 @@ cpc_kvm_init(void) cpc_apic_oneshot = false; cpc_apic_timer = 0; + cpc_apic_timer_min = 0; + cpc_apic_timer_dec_npf = 0; + cpc_apic_timer_dec_intr = 0; + INIT_LIST_HEAD(&cpc_faults); cpc_msrmts = kzalloc(L1_SETS, GFP_KERNEL); diff --git a/cachepc/uapi.h b/cachepc/uapi.h @@ -10,7 +10,7 @@ asm volatile("vmmcall" : : "a" (action), "b"(type), "c" (val) : "rdx") #define KVM_CPC_RESET _IOWR(KVMIO, 0x20, __u32) -#define KVM_CPC_DEBUG _IOW(KVMIO, 0x21, __u32) +#define KVM_CPC_LOGLEVEL _IOW(KVMIO, 0x21, __u32) #define KVM_CPC_MEMORY_ENCRYPT_OP _IOWR(KVMIO, 0x22, struct kvm_sev_cmd) diff --git a/util/.gitignore b/util/.gitignore @@ -1,3 +1,3 @@ -debug +loglevel reset mainpfn diff --git a/util/debug.c b/util/debug.c @@ -1,25 +0,0 @@ -#include "cachepc/uapi.h" - -#include <sys/ioctl.h> -#include <fcntl.h> -#include <err.h> -#include <fcntl.h> -#include <unistd.h> -#include <stdint.h> -#include <stdlib.h> - -int -main(int argc, const char **argv) -{ - uint32_t arg; - int fd, ret; - - fd = open("/dev/kvm", O_RDONLY); - if (fd < 0) err(1, "open"); - - arg = argc > 1 ? atoi(argv[1]) : 1; - ret = ioctl(fd, KVM_CPC_DEBUG, &arg); - if (ret == -1) err(1, "ioctl KVM_CPC_DEBUG"); - - close(fd); -} diff --git a/util/loglevel.c b/util/loglevel.c @@ -0,0 +1,34 @@ +#include "cachepc/uapi.h" + +#include <sys/ioctl.h> +#include <fcntl.h> +#include <err.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> + +int +main(int argc, const char **argv) +{ + uint32_t arg; + int fd, ret; + + fd = open("/dev/kvm", O_RDONLY); + if (fd < 0) err(1, "open"); + + if (argc > 1 && !strcmp(argv[1], "debug")) + arg = CPC_LOGLVL_DBG; + else if (argc > 1 && !strcmp(argv[1], "info")) + arg = CPC_LOGLVL_INFO; + else + arg = 0; + + printf("loglevel: %i\n", arg); + ret = ioctl(fd, KVM_CPC_LOGLEVEL, &arg); + if (ret == -1) err(1, "ioctl KVM_CPC_LOGLEVEL"); + + close(fd); +}