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 c1f2064fda3711db4878376884c36979c7b470cc
parent 32331c7f421411bccb87ea818a2a0198b8cf88aa
Author: Louis Burda <quent.burda@gmail.com>
Date:   Tue,  7 Feb 2023 08:26:00 -0600

Add counter for L1 misses in guest

Diffstat:
Mcachepc/cachepc.h | 3+++
Mcachepc/const.h | 1+
Mcachepc/event.c | 7+++++--
Mcachepc/event.h | 5+++--
Mcachepc/kvm.c | 16+++++++++++++---
Mcachepc/uapi.h | 1+
Mtest/kvm-step.c | 4++--
Mutil/disasm | 7++++---
8 files changed, 32 insertions(+), 12 deletions(-)

diff --git a/cachepc/cachepc.h b/cachepc/cachepc.h @@ -104,6 +104,9 @@ extern uint8_t *cpc_baseline; extern bool cpc_baseline_measure; extern bool cpc_baseline_active; +extern uint32_t cpc_guest_misses; +extern uint32_t cpc_baseline_guest_misses; + extern uint32_t cpc_svm_exitcode; extern bool cpc_pause_vm; diff --git a/cachepc/const.h b/cachepc/const.h @@ -11,6 +11,7 @@ #define CPC_L1MISS_PMC 0 #define CPC_RETINST_PMC 1 #define CPC_RETINST_USER_PMC 2 +#define CPC_L1MISS_GUEST_PMC 3 #define CPC_VMSA_MAGIC_ADDR ((void *) 0xC0FFEE) diff --git a/cachepc/event.c b/cachepc/event.c @@ -155,7 +155,7 @@ cpc_send_pause_event(void) } int -cpc_send_track_step_event(struct list_head *list) +cpc_send_track_step_event(struct list_head *list, uint32_t guest_misses) { struct cpc_event event = { 0 }; struct cpc_fault *fault; @@ -174,6 +174,7 @@ cpc_send_track_step_event(struct list_head *list) } event.step.fault_count = count; event.step.retinst = cpc_retinst; + event.step.misses = guest_misses; return cpc_send_event(event); } @@ -195,7 +196,8 @@ cpc_send_track_page_event(uint64_t gfn_prev, uint64_t gfn, uint16_t err, } int -cpc_send_track_step_event_single(uint64_t gfn, uint32_t err, uint64_t retinst) +cpc_send_track_step_event_single(uint64_t gfn, uint32_t err, + uint64_t retinst, uint32_t guest_misses) { struct cpc_event event = { 0 }; @@ -205,6 +207,7 @@ cpc_send_track_step_event_single(uint64_t gfn, uint32_t err, uint64_t retinst) event.step.fault_errs[0] = err; event.step.inst_gfn = gfn; event.step.retinst = retinst; + event.step.misses = guest_misses; return cpc_send_event(event); } diff --git a/cachepc/event.h b/cachepc/event.h @@ -18,8 +18,9 @@ void cpc_events_skip(void); int cpc_send_guest_event(uint64_t type, uint64_t val); int cpc_send_pause_event(void); -int cpc_send_track_step_event(struct list_head *list); -int cpc_send_track_step_event_single(uint64_t gfn, uint32_t err, uint64_t retinst); +int cpc_send_track_step_event(struct list_head *list, uint32_t guest_misses); +int cpc_send_track_step_event_single(uint64_t gfn, uint32_t err, + uint64_t retinst, uint32_t guest_misses); int cpc_send_track_page_event(uint64_t gfn_prev, uint64_t gfn, uint16_t err, uint64_t retinst, uint64_t retinst_user); diff --git a/cachepc/kvm.c b/cachepc/kvm.c @@ -22,15 +22,19 @@ uint32_t cpc_loglevel = 0; EXPORT_SYMBOL(cpc_loglevel); uint8_t *cpc_msrmts = NULL; -EXPORT_SYMBOL(cpc_msrmts); - uint8_t *cpc_baseline = NULL; bool cpc_baseline_measure = false; bool cpc_baseline_active = false; +EXPORT_SYMBOL(cpc_msrmts); EXPORT_SYMBOL(cpc_baseline); EXPORT_SYMBOL(cpc_baseline_measure); EXPORT_SYMBOL(cpc_baseline_active); +uint32_t cpc_guest_misses = 0; +uint32_t cpc_baseline_guest_misses = 0; +EXPORT_SYMBOL(cpc_guest_misses); +EXPORT_SYMBOL(cpc_baseline_guest_misses); + uint32_t cpc_svm_exitcode = false; EXPORT_SYMBOL(cpc_svm_exitcode); @@ -240,11 +244,16 @@ cpc_pmc_setup(void *p) /* retired instructions in guest */ cpc_init_pmc(CPC_RETINST_PMC, 0xC0, 0x00, - PMC_GUEST, PMC_KERNEL | PMC_USER); + PMC_GUEST, PMC_USER | PMC_KERNEL); /* retired instructions in guest userspace */ cpc_init_pmc(CPC_RETINST_USER_PMC, 0xC0, 0x00, PMC_GUEST, PMC_USER); + + /* L1 misses in guest */ + cpc_init_pmc(CPC_L1MISS_GUEST_PMC, 0x64, 0xD8, + PMC_GUEST, PMC_USER | PMC_KERNEL); + } void @@ -377,6 +386,7 @@ cpc_reset_baseline_ioctl(void __user *arg_user) cpc_baseline_active = false; cpc_baseline_measure = false; memset(cpc_baseline, 0xff, L1_SETS); + cpc_baseline_guest_misses = 0xffffffff; return 0; } diff --git a/cachepc/uapi.h b/cachepc/uapi.h @@ -82,6 +82,7 @@ struct cpc_track_step_event { __u64 fault_count; __u64 inst_gfn; __u64 retinst; + __u32 misses; }; struct cpc_track_page_event { diff --git a/test/kvm-step.c b/test/kvm-step.c @@ -34,10 +34,10 @@ monitor(struct kvm *kvm, bool baseline) ret = ioctl(kvm_dev, KVM_CPC_READ_COUNTS, counts); if (ret) err(1, "KVM_CPC_READ_COUNTS"); - printf("Event: rip:%08llx cnt:%llu inst:%08llx data:%08llx ret:%llu\n", + printf("Event: rip:%08llx cnt:%llu inst:%08llx data:%08llx ret:%llu misses:%u\n", vm_get_rip(), event.step.fault_count, event.step.fault_gfns[0], event.step.fault_gfns[1], - event.step.retinst); + event.step.retinst, event.step.misses); print_counts(counts); printf("\n"); print_counts_raw(counts); diff --git a/util/disasm b/util/disasm @@ -5,9 +5,10 @@ if [ $# -lt 2 ]; then exit 1 fi -ARCH="i386" if [ "$2" = "guest" ]; then - ARCH="i8086" + objdump -D -b binary -m i8086 $1 +else + objdump -b binary -m i8086 --disassemble="$2" $1 fi -gdb --batch -ex "set architecture $ARCH" -ex "disassemble $2" $1 +