commit afe49b52f6b2ac52efe8e610e64ee07c7c2efef4
parent 10d3c8f52dc2c0f498e81946bef8292424fcd1ce
Author: Louis Burda <quent.burda@gmail.com>
Date: Wed, 16 Nov 2022 16:03:04 +0100
APIC single stepping working
Diffstat:
4 files changed, 26 insertions(+), 21 deletions(-)
diff --git a/cachepc/cachepc.h b/cachepc/cachepc.h
@@ -290,6 +290,6 @@ void
cachepc_apic_oneshot(uint32_t interval)
{
native_apic_mem_write(APIC_LVTT, LOCAL_TIMER_VECTOR | APIC_LVT_TIMER_ONESHOT);
- native_apic_mem_write(APIC_TDCR, APIC_TDR_DIV_128);
+ native_apic_mem_write(APIC_TDCR, APIC_TDR_DIV_2);
native_apic_mem_write(APIC_TMICT, interval);
}
diff --git a/cachepc/mmu.c b/cachepc/mmu.c
@@ -35,20 +35,22 @@ cachepc_page_fault_handle(struct kvm_vcpu *vcpu,
cachepc_data_fault_avail = false;
cachepc_single_step = true;
- cachepc_apic_timer = 10;
+ cachepc_apic_timer = 390;
cachepc_track_state_next = CPC_TRACK_AWAIT_DATA_FAULT;
} else if (cachepc_track_state == CPC_TRACK_AWAIT_DATA_FAULT) {
/* second fault from data access */
pr_warn("CachePC: Got data fault gfn:%llu err:%u\n",
fault->gfn, fault->error_code);
+ if (!cachepc_inst_fault_avail)
+ pr_err("CachePC: Waiting for data fault without inst\n");
cachepc_data_fault_gfn = fault->gfn;
cachepc_data_fault_err = fault->error_code;
cachepc_data_fault_avail = true;
cachepc_single_step = true;
- cachepc_apic_timer = 10;
+ cachepc_apic_timer = 390;
cachepc_track_state_next = CPC_TRACK_AWAIT_STEP_INTR;
} else if (cachepc_track_state == CPC_TRACK_AWAIT_STEP_INTR) {
@@ -80,7 +82,9 @@ cachepc_page_fault_handle(struct kvm_vcpu *vcpu,
cachepc_track_state_next = CPC_TRACK_AWAIT_INST_FAULT;
}
} else if (cachepc_track_mode == CPC_TRACK_EXEC_PAGES) {
- /* TODO: skip if not instruction decode fault */
+ /* untrack pages that are not code (could be a problem for WX */
+ if (!inst_fetch) return;
+
/* TODO: calculate retired instructions (save and subtract global counter) */
if (cachepc_inst_fault_avail) {
/* track previous faulted page, current stays untracked */
diff --git a/notes b/notes
@@ -6,9 +6,6 @@ Questions:
- test/sevstep: why does it seem to work with event race but not without?
=> it doesnt (anymore)
-Tried:
-- try invalidating tlbs (no effect, prob was already)
-
Next steps:
- enable single-steping with multiple page faults (only one ends up in
last_fault_gfn and others stay untracked)
@@ -17,11 +14,15 @@ Next steps:
such that we see the relevant page faults and the gfn increment
- test/sevstep: implement counter.. read program memory to see
how many instructions were executed on apic timer
-- add warning for high values in baseline
Meeting questions:
- Why is decrypted rip sometimes off-by-one?
=>
-- VM gets interrupted independent of our APIC (by the scheduler) is this a problem?
+- VM gets interrupted independent of our APIC (by the scheduler?) was this a problem for you?
+ =>
+- Is supplementing apic with waiting for next fault viable? (seems to work well actually)
+ =>
+- How does single stepping work with fixed cpu frequency when we always step less than one instruction?
=>
--
+
+
diff --git a/test/sevstep.c b/test/sevstep.c
@@ -480,6 +480,7 @@ runonce(struct kvm *kvm)
int
monitor(struct kvm *kvm, bool baseline)
{
+ static uint64_t rip_prev = 1;
struct cpc_track_event event;
cpc_msrmt_t counts[64];
uint64_t rip;
@@ -488,20 +489,17 @@ monitor(struct kvm *kvm, bool baseline)
/* Get page fault info */
ret = ioctl(kvm_dev, KVM_CPC_POLL_EVENT, &event);
if (!ret) {
- if (!baseline) {
- rip = sev_dbg_rip(kvm->vmfd);
- printf("Event: inst:%llu data:%llu retired:%llu rip:%lu\n",
- event.inst_fault_gfn, event.data_fault_gfn,
- event.retinst, rip);
- }
- faultcnt++;
-
ret = ioctl(kvm_dev, KVM_CPC_READ_COUNTS, counts);
if (ret == -1) err(1, "ioctl READ_COUNTS");
- if (!baseline) {
+ rip = sev_dbg_rip(kvm->vmfd);
+ if (!baseline && rip != rip_prev) {
+ printf("Event: inst:%llu data:%llu retired:%llu rip:%lu\n",
+ event.inst_fault_gfn, event.data_fault_gfn,
+ event.retinst, rip);
print_counts(counts);
printf("\n");
+ rip_prev = rip;
}
for (i = 0; i < 64; i++) {
@@ -513,6 +511,8 @@ monitor(struct kvm *kvm, bool baseline)
ret = ioctl(kvm_dev, KVM_CPC_ACK_EVENT, &event.id);
if (ret == -1) err(1, "ioctl ACK_EVENT");
+
+ faultcnt++;
} else if (errno != EAGAIN) {
perror("ioctl POLL_EVENT");
return 1;
@@ -589,7 +589,7 @@ main(int argc, const char **argv)
if (ret == -1) err(1, "ioctl MEASURE_BASELINE");
faultcnt = 0;
- while (faultcnt < 30) {
+ while (faultcnt < 50) {
if (monitor(&kvm_with_access, true)) break;
}
@@ -626,7 +626,7 @@ main(int argc, const char **argv)
if (ret == -1) err(1, "ioctl ACK_EVENT");
faultcnt = 0;
- while (faultcnt < 30) {
+ while (faultcnt < 50) {
if (monitor(&kvm_with_access, false)) break;
}