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:
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
# ---------------------------------