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 ca3b348013267bf727ba52bb6fc97a7ab7d367dc
parent dbb1ac88094516d1165c9e43c4a79cbc3a18d7d1
Author: Louis Burda <quent.burda@gmail.com>
Date:   Thu,  2 Feb 2023 17:39:09 -0600

Debug single-stepping on page-boundaries in page_step

Diffstat:
MMakefile | 1+
Mcachepc/cachepc.h | 5+++--
Mcachepc/const.h | 7+++++--
Mcachepc/kvm.c | 5+++--
Mcachepc/macro.S | 6++----
Mcachepc/uapi.h | 3+++
Mtest/kvm-pagestep.c | 1+
Mtest/kvm-pagestep_guest.S | 2+-
8 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/Makefile b/Makefile @@ -60,6 +60,7 @@ load: prep: sudo sh -c "echo 0 > /proc/sys/kernel/watchdog" + sudo sh -c "echo performance > /sys/devices/system/cpu/cpu2/cpufreq/scaling_governor" sudo sh -c "echo 1500000 > /sys/devices/system/cpu/cpu2/cpufreq/scaling_min_freq" sudo sh -c "echo 1500000 > /sys/devices/system/cpu/cpu2/cpufreq/scaling_max_freq" sudo sh -c "echo 1500000 > /sys/devices/system/cpu/cpu2/cpufreq/scaling_min_freq" diff --git a/cachepc/cachepc.h b/cachepc/cachepc.h @@ -37,6 +37,7 @@ struct cpc_fault { }; struct cpc_track_pages { + bool singlestep_resolve; bool prev_avail; bool cur_avail; bool next_avail; @@ -99,8 +100,8 @@ extern bool cpc_singlestep; extern bool cpc_singlestep_reset; extern bool cpc_long_step; -extern volatile bool cpc_apic_oneshot; -extern uint32_t cpc_apic_timer; +extern bool cpc_apic_oneshot; +extern int32_t cpc_apic_timer; extern uint32_t cpc_track_mode; extern uint64_t cpc_track_start_gfn; diff --git a/cachepc/const.h b/cachepc/const.h @@ -20,8 +20,11 @@ #define CPC_CL_PREV_OFFSET 8 #define CPC_CL_COUNT_OFFSET 16 -#define CPC_APIC_TIMER_TDCR APIC_TDR_DIV_2 // APIC_TDR_DIV_1 +/* APIC divisor determines how much time is added per increment. + * A large divisor decreases the counter slower, which means more time + * is added for each increment, possiblpy skipping whole instructions */ +#define CPC_APIC_TIMER_TDCR APIC_TDR_DIV_1 #define CPC_APIC_TIMER_SOFTDIV 1 -#define CPC_APIC_TIMER_MIN (100 * CPC_APIC_TIMER_SOFTDIV) +#define CPC_APIC_TIMER_MIN (20 * CPC_APIC_TIMER_SOFTDIV) #define CPC_EVENT_BATCH_MAX 1000 diff --git a/cachepc/kvm.c b/cachepc/kvm.c @@ -59,8 +59,8 @@ EXPORT_SYMBOL(cpc_singlestep); EXPORT_SYMBOL(cpc_singlestep_reset); EXPORT_SYMBOL(cpc_long_step); -volatile bool cpc_apic_oneshot = false; -uint32_t cpc_apic_timer = 0; +bool cpc_apic_oneshot = false; +int32_t cpc_apic_timer = 0; EXPORT_SYMBOL(cpc_apic_oneshot); EXPORT_SYMBOL(cpc_apic_timer); @@ -485,6 +485,7 @@ cpc_track_mode_ioctl(void __user *arg_user) break; case CPC_TRACK_PAGES: memset(&cpc_track_pages, 0, sizeof(cpc_track_pages)); + cpc_track_pages.singlestep_resolve = cfg.pages.singlestep_resolve; cpc_track_all(vcpu, KVM_PAGE_TRACK_EXEC); break; case CPC_TRACK_STEPS: diff --git a/cachepc/macro.S b/cachepc/macro.S @@ -2,10 +2,8 @@ # clobbers rax, rbx, rcx, rdx .macro barrier - mfence # memory barrier - rdtsc # serializing - # mov $0x80000005, %rax - # cpuid # serializing (cpuid alone does not work) + mfence # finish load and stores + lfence # prevent reordering .endm # clobbers rax, rbx, rcx, rdx, (out) diff --git a/cachepc/uapi.h b/cachepc/uapi.h @@ -72,6 +72,9 @@ struct cpc_track_cfg { __u8 use_filter; __u8 with_data; } steps; + struct { + __u8 singlestep_resolve; + } pages; }; }; diff --git a/test/kvm-pagestep.c b/test/kvm-pagestep.c @@ -111,6 +111,7 @@ main(int argc, const char **argv) memset(&cfg, 0, sizeof(cfg)); cfg.mode = CPC_TRACK_PAGES; + cfg.pages.singlestep_resolve = true; ret = ioctl(kvm_dev, KVM_CPC_TRACK_MODE, &cfg); if (ret) err(1, "KVM_CPC_TRACK_MODE"); diff --git a/test/kvm-pagestep_guest.S b/test/kvm-pagestep_guest.S @@ -17,7 +17,7 @@ guest: .rept L1_LINESIZE * L1_SETS - 2 nop .endr - cpuid # two byte instruction + rdtsc # two byte instruction .endr # ---------------------------------