commit 13ff10bd81a3a6d7e13c43596a2f0efb6be39088
parent 1ffb06efd201e4d754a6295f70aecbe59152f18a
Author: Louis Burda <quent.burda@gmail.com>
Date: Sat, 12 Nov 2022 01:59:45 +0100
Rename uspt to cachepc events
Diffstat:
6 files changed, 177 insertions(+), 189 deletions(-)
diff --git a/cachepc/events.c b/cachepc/events.c
@@ -0,0 +1,131 @@
+#include "events.h"
+#include "sevstep.h"
+#include "cachepc.h"
+#include "uapi.h"
+
+#include <linux/kvm.h>
+#include <linux/timekeeping.h>
+#include <linux/uaccess.h>
+#include <linux/types.h>
+#include <linux/vmalloc.h>
+#include <linux/printk.h>
+#include <linux/ratelimit.h>
+
+#define ARRLEN(x) (sizeof(x)/sizeof((x)[0]))
+
+void
+cachepc_events_reset(void)
+{
+ write_lock(&cachepc_event_lock);
+ cachepc_events_init = true;
+ cachepc_last_event_sent = 1;
+ cachepc_last_event_acked = 1;
+ cachepc_event_avail = false;
+ write_unlock(&cachepc_event_lock);
+}
+
+int
+cachepc_send_tracking_event(uint64_t inst_fault_gfn, uint32_t inst_fault_err,
+ uint64_t data_fault_gfn, uint32_t data_fault_err)
+{
+ struct cpc_track_event event;
+ ktime_t deadline;
+
+ read_lock(&cachepc_event_lock);
+ if (!cachepc_events_init) {
+ pr_warn("CachePC: events ctx not initialized!\n");
+ read_unlock(&cachepc_event_lock);
+ return 1;
+ }
+ read_unlock(&cachepc_event_lock);
+
+ write_lock(&cachepc_event_lock);
+ if (cachepc_last_event_sent != cachepc_last_event_acked) {
+ pr_warn("CachePC: event IDs out of sync\n");
+ write_unlock(&cachepc_event_lock);
+ return 1;
+ } else {
+ cachepc_last_event_sent++;
+ }
+ event.id = cachepc_last_event_sent;
+ event.inst_fault_gfn = inst_fault_gfn;
+ event.inst_fault_err = inst_fault_err;
+ event.data_fault_avail = (data_fault_err != 0);
+ event.data_fault_gfn = data_fault_gfn;
+ event.data_fault_err = data_fault_err;
+ event.timestamp_ns = ktime_get_real_ns();
+ event.retinst = cachepc_retinst;
+
+ cachepc_event_avail = true;
+ cachepc_event = event;
+ write_unlock(&cachepc_event_lock);
+
+ /* wait for ack with timeout */
+ deadline = ktime_get_ns() + 2000000000ULL; /* 2s in ns */
+ while (!cachepc_event_is_done(cachepc_event.id)) {
+ if (ktime_get_ns() > deadline) {
+ pr_warn("CachePC: Timeout waiting for ack of event %llu\n",
+ cachepc_event.id);
+ return 3;
+ }
+ }
+
+ return 0;
+}
+
+bool
+cachepc_event_is_done(uint64_t id)
+{
+ bool done;
+
+ read_lock(&cachepc_event_lock);
+ done = cachepc_last_event_acked >= id;
+ read_unlock(&cachepc_event_lock);
+
+ return done;
+}
+
+int
+cachepc_handle_poll_event_ioctl(struct cpc_track_event __user *event)
+{
+ int err;
+
+ read_lock(&cachepc_event_lock);
+ if (!cachepc_event_avail) {
+ read_unlock(&cachepc_event_lock);
+ return -EAGAIN;
+ }
+ read_unlock(&cachepc_event_lock);
+
+ write_lock(&cachepc_event_lock);
+ if (cachepc_event_avail) {
+ err = copy_to_user(event, &cachepc_event,
+ sizeof(struct cpc_track_event));
+ cachepc_event_avail = false;
+ } else {
+ err = -EAGAIN;
+ }
+ write_unlock(&cachepc_event_lock);
+
+ return err;
+}
+
+int
+cachepc_handle_ack_event_ioctl(uint64_t eventid)
+{
+ int err;
+
+ write_lock(&cachepc_event_lock);
+ if (eventid == cachepc_last_event_sent) {
+ err = 0;
+ cachepc_last_event_acked = cachepc_last_event_sent;
+ } else {
+ err = 1;
+ pr_warn("CachePC: Acked event does not match sent: %llu %llu\n",
+ cachepc_last_event_sent, eventid);
+ }
+ write_unlock(&cachepc_event_lock);
+
+ return err;
+}
+
diff --git a/cachepc/events.h b/cachepc/events.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "uapi.h"
+
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <linux/types.h>
+
+extern uint64_t cachepc_last_event_sent;
+extern uint64_t cachepc_last_event_acked;
+extern rwlock_t cachepc_event_lock;
+
+extern struct cpc_track_event cachepc_event;
+extern bool cachepc_event_avail;
+
+extern bool cachepc_events_init;
+
+void cachepc_events_reset(void);
+
+int cachepc_send_tracking_event(uint64_t inst_fault_gfn, uint32_t inst_fault_err,
+ uint64_t data_fault_gfn, uint32_t data_fault_err);
+bool cachepc_event_is_done(uint64_t id);
+
+int cachepc_handle_poll_event_ioctl(struct cpc_track_event *userpace_mem);
+int cachepc_handle_ack_event_ioctl(uint64_t eventid);
diff --git a/cachepc/kvm.c b/cachepc/kvm.c
@@ -1,5 +1,5 @@
#include "kvm.h"
-#include "uspt.h"
+#include "events.h"
#include "cachepc.h"
#include "sevstep.h"
#include "uapi.h"
@@ -59,20 +59,20 @@ uint64_t cachepc_regs_vm[16];
EXPORT_SYMBOL(cachepc_regs_tmp);
EXPORT_SYMBOL(cachepc_regs_vm);
-uint64_t last_sent_eventid;
-uint64_t last_acked_eventid;
-DEFINE_RWLOCK(event_lock);
-EXPORT_SYMBOL(last_sent_eventid);
-EXPORT_SYMBOL(last_acked_eventid);
-EXPORT_SYMBOL(event_lock);
+uint64_t cachepc_last_event_sent;
+uint64_t cachepc_last_event_acked;
+DEFINE_RWLOCK(cachepc_event_lock);
+EXPORT_SYMBOL(cachepc_last_event_sent);
+EXPORT_SYMBOL(cachepc_last_event_acked);
+EXPORT_SYMBOL(cachepc_event_lock);
-struct cpc_track_event sent_event;
-bool have_event;
-EXPORT_SYMBOL(sent_event);
-EXPORT_SYMBOL(have_event);
+struct cpc_track_event cachepc_event;
+bool cachepc_event_avail;
+EXPORT_SYMBOL(cachepc_event);
+EXPORT_SYMBOL(cachepc_event_avail);
-bool uspt_init;
-EXPORT_SYMBOL(uspt_init);
+bool cachepc_events_init;
+EXPORT_SYMBOL(cachepc_events_init);
static void cachepc_kvm_prime_probe_test(void *p);
static void cachepc_kvm_stream_hwpf_test(void *p);
@@ -588,7 +588,7 @@ cachepc_kvm_uspt_reset_ioctl(void __user *arg_user)
{
struct kvm_vcpu *vcpu;
- sevstep_uspt_clear();
+ cachepc_events_reset();
vcpu = xa_load(&main_vm->vcpu_array, 0);
sevstep_untrack_all(vcpu, KVM_PAGE_TRACK_EXEC);
sevstep_untrack_all(vcpu, KVM_PAGE_TRACK_ACCESS);
@@ -600,10 +600,10 @@ cachepc_kvm_uspt_reset_ioctl(void __user *arg_user)
int
cachepc_kvm_poll_event_ioctl(void __user *arg_user)
{
- if (!sevstep_uspt_is_initialized())
+ if (!cachepc_events_init)
return -EINVAL;
- return sevstep_uspt_handle_poll_event(arg_user);
+ return cachepc_handle_poll_event_ioctl(arg_user);
}
int
@@ -613,13 +613,13 @@ cachepc_kvm_uscpt_ack_event_ioctl(void __user *arg_user)
if (!arg_user) return -EINVAL;
- if (!sevstep_uspt_is_initialized())
+ if (!cachepc_events_init)
return -EINVAL;
if (copy_from_user(&eventid, arg_user, sizeof(eventid)))
return -EINVAL;
- return sevstep_uspt_handle_ack_event_ioctl(eventid);
+ return cachepc_handle_ack_event_ioctl(eventid);
}
long
diff --git a/cachepc/mmu.c b/cachepc/mmu.c
@@ -1,13 +1,11 @@
#include "../cachepc/sevstep.h"
#include "../cachepc/cachepc.h"
-#include "../cachepc/uspt.h"
+#include "../cachepc/events.h"
static void
sevstep_uspt_page_fault_handle(struct kvm_vcpu *vcpu,
struct kvm_page_fault *fault)
{
- int err;
-
if (!kvm_slot_page_track_is_active(vcpu->kvm,
fault->slot, fault->gfn, KVM_PAGE_TRACK_ACCESS))
return;
@@ -52,12 +50,10 @@ sevstep_uspt_page_fault_handle(struct kvm_vcpu *vcpu,
}
cachepc_inst_fault_gfn = fault->gfn;
cachepc_inst_fault_err = fault->error_code;
- if (sevstep_uspt_send_and_block(fault->gfn, fault->error_code, 0, 0))
- pr_warn("Sevstep: uspt_send_and_block failed (%d)\n", err);
+ cachepc_send_tracking_event(fault->gfn, fault->error_code, 0, 0);
} else if (cachepc_track_mode == CPC_TRACK_ACCESS) {
sevstep_track_single(vcpu, fault->gfn, KVM_PAGE_TRACK_ACCESS);
- if (sevstep_uspt_send_and_block(fault->gfn, fault->error_code, 0, 0))
- pr_warn("Sevstep: uspt_send_and_block failed (%d)\n", err);
+ cachepc_send_tracking_event(fault->gfn, fault->error_code, 0, 0);
}
}
diff --git a/cachepc/uspt.c b/cachepc/uspt.c
@@ -1,138 +0,0 @@
-#include "uspt.h"
-#include "sevstep.h"
-#include "cachepc.h"
-#include "uapi.h"
-
-#include <linux/kvm.h>
-#include <linux/timekeeping.h>
-#include <linux/uaccess.h>
-#include <linux/types.h>
-#include <linux/vmalloc.h>
-#include <linux/printk.h>
-#include <linux/ratelimit.h>
-
-#define ARRLEN(x) (sizeof(x)/sizeof((x)[0]))
-
-void
-sevstep_uspt_clear(void)
-{
- write_lock(&event_lock);
- uspt_init = true;
- last_sent_eventid = 1;
- last_acked_eventid = 1;
- have_event = false;
- write_unlock(&event_lock);
-}
-
-bool
-sevstep_uspt_is_initialized()
-{
- return uspt_init;
-}
-
-int
-sevstep_uspt_send_and_block(uint64_t inst_fault_gfn, uint32_t inst_fault_err,
- uint64_t data_fault_gfn, uint32_t data_fault_err)
-{
- struct cpc_track_event event;
- ktime_t deadline;
-
- read_lock(&event_lock);
- if (!sevstep_uspt_is_initialized()) {
- pr_warn("Sevstep: ctx not initialized!\n");
- read_unlock(&event_lock);
- return 1;
- }
- read_unlock(&event_lock);
-
- write_lock(&event_lock);
- if (last_sent_eventid != last_acked_eventid) {
- pr_warn("Sevstep: event id_s out of sync, aborting\n");
- write_unlock(&event_lock);
- return 1;
- } else {
- last_sent_eventid++;
- }
- event.id = last_sent_eventid;
- event.inst_fault_gfn = inst_fault_gfn;
- event.inst_fault_err = inst_fault_err;
- event.data_fault_avail = (data_fault_err != 0);
- event.data_fault_gfn = data_fault_gfn;
- event.data_fault_err = data_fault_err;
- event.timestamp_ns = ktime_get_real_ns();
- event.retinst = cachepc_retinst;
-
- have_event = true;
- sent_event = event;
- write_unlock(&event_lock);
-
- /* wait for ack with timeout */
- // pr_warn("Sevstep: uspt_send_and_block: Begin wait for event ack");
- deadline = ktime_get_ns() + 2000000000ULL; /* 1s in ns */
- while (!sevstep_uspt_is_event_done(sent_event.id)) {
- if (ktime_get_ns() > deadline) {
- pr_warn("Sevstep: Timeout waiting for ack of event %llu ",
- sent_event.id);
- return 3;
- }
- }
-
- return 0;
-}
-
-int
-sevstep_uspt_is_event_done(uint64_t id)
-{
- bool done;
-
- read_lock(&event_lock);
- done = last_acked_eventid >= id;
- read_unlock(&event_lock);
-
- return done;
-}
-
-int
-sevstep_uspt_handle_poll_event(struct cpc_track_event __user *event)
-{
- int err;
-
- read_lock(&event_lock);
- if (!have_event) {
- read_unlock(&event_lock);
- return -EAGAIN;
- }
- read_unlock(&event_lock);
-
- write_lock(&event_lock);
- if (have_event) {
- err = copy_to_user(event, &sent_event,
- sizeof(struct cpc_track_event));
- have_event = false;
- } else {
- err = -EAGAIN;
- }
- write_unlock(&event_lock);
-
- return err;
-}
-
-int
-sevstep_uspt_handle_ack_event_ioctl(uint64_t eventid)
-{
- int err;
-
- write_lock(&event_lock);
- if (eventid == last_sent_eventid) {
- err = 0;
- last_acked_eventid = last_sent_eventid;
- } else {
- err = 1;
- pr_warn("Sevstep: Ackd event does not match sent: %llu %llu\n",
- last_sent_eventid, eventid);
- }
- write_unlock(&event_lock);
-
- return err;
-}
-
diff --git a/cachepc/uspt.h b/cachepc/uspt.h
@@ -1,26 +0,0 @@
-#pragma once
-
-#include "uapi.h"
-
-#include <linux/kvm.h>
-#include <linux/kvm_host.h>
-#include <linux/types.h>
-
-extern uint64_t last_sent_eventid;
-extern uint64_t last_acked_eventid;
-extern rwlock_t event_lock;
-
-extern struct cpc_track_event sent_event;
-extern bool have_event;
-
-extern bool uspt_init;
-
-bool sevstep_uspt_is_initialized(void);
-void sevstep_uspt_clear(void);
-
-int sevstep_uspt_send_and_block(uint64_t inst_fault_gfn, uint32_t inst_fault_err,
- uint64_t data_fault_gfn, uint32_t data_fault_err);
-int sevstep_uspt_is_event_done(uint64_t id);
-
-int sevstep_uspt_handle_poll_event(struct cpc_track_event *userpace_mem);
-int sevstep_uspt_handle_ack_event_ioctl(uint64_t eventid);