commit 4dd9fe04e1399e8629ab2a98b54db6a7dcdb0076
parent 0d4f62bcc065026390dd1f19b0bb462d07dcf9ff
Author: Louis Burda <quent.burda@gmail.com>
Date: Sun, 5 Feb 2023 16:02:54 -0600
Fix stepping inconsistency by moving oneshot after primee
Diffstat:
8 files changed, 41 insertions(+), 29 deletions(-)
diff --git a/cachepc/cachepc.c b/cachepc/cachepc.c
@@ -214,7 +214,10 @@ cpc_print_msrmts(struct cpc_cl *head)
void
cpc_apic_oneshot_run(uint32_t interval)
{
+ /* 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 */
native_apic_mem_write(APIC_LVTT, LOCAL_TIMER_VECTOR | APIC_LVT_TIMER_ONESHOT);
- native_apic_mem_write(APIC_TDCR, CPC_APIC_TIMER_TDCR);
- native_apic_mem_write(APIC_TMICT, interval / CPC_APIC_TIMER_SOFTDIV);
+ native_apic_mem_write(APIC_TDCR, APIC_TDR_DIV_1);
+ native_apic_mem_write(APIC_TMICT, interval / cpc_apic_timer_softdiv);
}
diff --git a/cachepc/cachepc.h b/cachepc/cachepc.h
@@ -108,9 +108,10 @@ 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 int32_t cpc_apic_timer_softdiv;
+extern int32_t cpc_apic_timer_min;
+extern int32_t cpc_apic_timer_dec_npf;
+extern int32_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
@@ -23,12 +23,6 @@
#define CPC_CL_PREV_OFFSET 8
#define CPC_CL_COUNT_OFFSET 16
-/* 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_EVENT_BATCH_MAX 10000
#define CPC_LOGLVL_INFO 1
diff --git a/cachepc/kvm.c b/cachepc/kvm.c
@@ -64,9 +64,11 @@ 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;
+int32_t cpc_apic_timer_softdiv = 1;
+int32_t cpc_apic_timer_min = 0;
+int32_t cpc_apic_timer_dec_npf = 0;
+int32_t cpc_apic_timer_dec_intr = 0;
+EXPORT_SYMBOL(cpc_apic_timer_softdiv);
EXPORT_SYMBOL(cpc_apic_timer_min);
EXPORT_SYMBOL(cpc_apic_timer_dec_npf);
EXPORT_SYMBOL(cpc_apic_timer_dec_intr);
@@ -481,6 +483,7 @@ cpc_track_mode_ioctl(void __user *arg_user)
cpc_singlestep_reset = false;
cpc_long_step = false;
+ cpc_apic_timer_softdiv = 3;
if (sev_es_guest(vcpu->kvm)) {
cpc_apic_timer_min = 200;
cpc_apic_timer_dec_npf = 25;
@@ -506,9 +509,6 @@ 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 = 50;
- cpc_apic_timer_dec_intr = 100;
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;
@@ -714,6 +714,7 @@ cpc_kvm_init(void)
cpc_apic_oneshot = false;
cpc_apic_timer = 0;
+ cpc_apic_timer_softdiv = 1;
cpc_apic_timer_min = 0;
cpc_apic_timer_dec_npf = 0;
cpc_apic_timer_dec_intr = 0;
diff --git a/test/kvm-step.c b/test/kvm-step.c
@@ -66,14 +66,17 @@ main(int argc, const char **argv)
struct cpc_track_cfg cfg;
uint64_t eventcnt;
uint32_t arg;
+ bool with_data;
int ret;
- vmtype = "kvm";
- if (argc > 1) vmtype = argv[1];
- if (strcmp(vmtype, "kvm") && strcmp(vmtype, "sev")
- && strcmp(vmtype, "sev-es")
- && strcmp(vmtype, "sev-snp"))
- errx(1, "invalid vm mode: %s", vmtype);
+ with_data = true;
+ if (argc > 1 && !strcmp(argv[1], "--exec-only")) {
+ with_data = false;
+ argc--;
+ argv++;
+ }
+
+ parse_vmtype(argc, argv);
setvbuf(stdout, NULL, _IONBF, 0);
@@ -122,7 +125,7 @@ main(int argc, const char **argv)
memset(&cfg, 0, sizeof(cfg));
cfg.mode = CPC_TRACK_STEPS;
- cfg.steps.with_data = true;
+ cfg.steps.with_data = with_data;
ret = ioctl(kvm_dev, KVM_CPC_TRACK_MODE, &cfg);
if (ret) err(1, "KVM_CPC_TRACK_MODE");
@@ -173,7 +176,7 @@ main(int argc, const char **argv)
if (ret) err(1, "KVM_CPC_ACK_EVENT");
eventcnt = 0;
- while (eventcnt < 50) {
+ while (eventcnt < 110) {
eventcnt += monitor(&kvm, false);
}
diff --git a/test/kvm-step_guest.S b/test/kvm-step_guest.S
@@ -7,6 +7,10 @@
.code16gcc
guest:
+.rept 100
+ nop
+.endr
+
mov $(L1_LINESIZE * (L1_SETS + 11)), %bx
movb (%bx), %bl
hlt
diff --git a/test/kvm-targetstep_guest b/test/kvm-targetstep_guest
@@ -1 +1 @@
-
-\ No newline at end of file
+
+\ No newline at end of file
diff --git a/test/kvm-targetstep_guest.S b/test/kvm-targetstep_guest.S
@@ -25,8 +25,14 @@ guest:
mov $(L1_LINESIZE * (L1_SETS + 15)), %bx
movb (%bx), %bl
- # this should only be partially single-stepped if
- # single-stepping is limited to the first page
+ jmp skip
+.rept L1_LINESIZE * L1_SETS
+ nop
+.endr
+skip:
+
+ # these nops should not be single-stepped
+ # since they are outside the target gfn
.rept L1_LINESIZE * L1_SETS * 2
nop
.endr