commit 2558cb66b59aae1578fc46ff8edf5d7cf9383037
parent c80d9518901eac7547b462ec4e79125c6913b378
Author: Louis Burda <quent.burda@gmail.com>
Date: Mon, 25 Jul 2022 22:51:20 +0200
Added proc device for reading counts
Diffstat:
5 files changed, 93 insertions(+), 53 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -1,3 +1,4 @@
build.sh
+push.sh
*.o.cmd
*.o
diff --git a/Makefile b/Makefile
@@ -18,8 +18,7 @@ prepare: $(KERNEL_SOURCE)/arch/x86/kvm/svm/cachepc
git -C $(KERNEL_SOURCE) apply $(PWD)/patch.diff
build:
- # $(MAKE) -C $(KERNEL_SOURCE) arch/x86/kvm/kvm.ko arch/x86/kvm/kvm-amd.ko
- $(MAKE) -C $(KERNEL_SOURCE) -v modules -j6 SUBDIRS=arch/x86/kvm
+ #$(MAKE) -C $(KERNEL_SOURCE) arch/x86/kvm/kvm.ko arch/x86/kvm/kvm-amd.ko
$(MAKE) -C $(KERNEL_SOURCE) -j6 M=arch/x86/kvm
load:
diff --git a/patch.diff b/patch.diff
@@ -24,7 +24,7 @@ index b804444e16d4..c94f8c4460f1 100644
obj-$(CONFIG_KVM) += kvm.o
obj-$(CONFIG_KVM_INTEL) += kvm-intel.o
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
-index 7b3cfbe8f7e3..e9a2b1048e28 100644
+index 7b3cfbe8f7e3..71697d08e9e4 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -2,6 +2,8 @@
@@ -47,55 +47,54 @@ index 7b3cfbe8f7e3..e9a2b1048e28 100644
+ static int run_index = 0;
+ struct vcpu_svm *svm;
+
++ printk(KERN_WARNING "CachePC: svm_cpu_enter_exit()\n");
++
+ if (!ctx) ctx = cachepc_get_ctx(L1);
+ if (!ds) ds = cachepc_prepare_ds(ctx);
-+
-+ head = cachepc_prime(ds);
+ svm = to_svm(vcpu);
svm->vmcb->save.rax = vcpu->arch.regs[VCPU_REGS_RAX];
svm->vmcb->save.rsp = vcpu->arch.regs[VCPU_REGS_RSP];
svm->vmcb->save.rip = vcpu->arch.regs[VCPU_REGS_RIP];
-@@ -3912,6 +3925,11 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu)
- if (is_guest_mode(vcpu))
- return EXIT_FASTPATH_NONE;
+@@ -3835,8 +3847,14 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu)
+ */
+ x86_spec_ctrl_set_guest(svm->spec_ctrl, svm->virt_spec_ctrl);
+
++ head = cachepc_prime(ds);
++
+ svm_vcpu_enter_exit(vcpu, svm);
+ cachepc_probe(head);
-+ cachepc_print_msrmts(head);
++ //cachepc_print_msrmts(head);
++ cachepc_save_msrmts(head);
+
+ /*
+ * We do not use IBRS in the kernel. If this vCPU has used the
+ * SPEC_CTRL MSR it may have left it on; save the value and
+@@ -3912,6 +3930,8 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu)
+ if (is_guest_mode(vcpu))
+ return EXIT_FASTPATH_NONE;
+
+ run_index += 1;
+
return svm_exit_handlers_fastpath(vcpu);
}
-diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
-index 7f2e2a09ebbd..762eb35f19e5 100644
---- a/include/linux/kvm_host.h
-+++ b/include/linux/kvm_host.h
-@@ -35,6 +35,10 @@
-
- #include <asm/kvm_host.h>
-
-+extern struct proc_dir_entry *cachepc_msrmts_file;
-+extern uint8_t cachepc_msrmts[1 << 20];
-+extern uint64_t cachepc_msrmts_count;
-+
- #ifndef KVM_MAX_VCPU_ID
- #define KVM_MAX_VCPU_ID KVM_MAX_VCPUS
- #endif
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
-index 2541a17ff1c4..fd7511484011 100644
+index 2541a17ff1c4..c219a214d904 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
-@@ -51,6 +51,7 @@
+@@ -51,6 +51,9 @@
#include <linux/io.h>
#include <linux/lockdep.h>
#include <linux/kthread.h>
+#include <linux/proc_fs.h>
++#include <linux/init.h>
++#include <asm/uaccess.h>
#include <asm/processor.h>
#include <asm/ioctl.h>
-@@ -66,6 +67,8 @@
+@@ -66,6 +69,8 @@
/* Worst case buffer size needed for holding an integer. */
#define ITOA_MAX_LEN 12
@@ -104,68 +103,99 @@ index 2541a17ff1c4..fd7511484011 100644
MODULE_AUTHOR("Qumranet");
MODULE_LICENSE("GPL");
-@@ -143,6 +146,10 @@ static void hardware_disable_all(void);
+@@ -143,6 +148,13 @@ static void hardware_disable_all(void);
static void kvm_io_bus_destroy(struct kvm_io_bus *bus);
-+struct proc_dir_entry *cachepc_msrmts_file;
-+uint8_t cachepc_msrmts[1 << 20];
-+uint64_t cachepc_msrmts_count;
++uint8_t *cachepc_msrmts;
++size_t cachepc_msrmts_count;
++struct proc_ops cachepc_proc_ops;
++
++EXPORT_SYMBOL(cachepc_msrmts);
++EXPORT_SYMBOL(cachepc_msrmts_count);
+
__visible bool kvm_rebooting;
EXPORT_SYMBOL_GPL(kvm_rebooting);
-@@ -4765,10 +4772,29 @@ static void check_processor_compat(void *data)
+@@ -4765,6 +4777,50 @@ static void check_processor_compat(void *data)
*c->ret = kvm_arch_check_processor_compat(c->opaque);
}
++int
++kvm_cachepc_open(struct inode *inode, struct file *file)
++{
++ try_module_get(THIS_MODULE);
++
++ return 0;
++}
++
++int
++kvm_cachepc_close(struct inode *inode, struct file *file)
++{
++ module_put(THIS_MODULE);
++
++ return 0;
++}
++
+ssize_t
+kvm_cachepc_read(struct file *file, char *buf, size_t buflen, loff_t *off)
+{
-+ size_t len;
++ size_t len, left;
+
-+ printk(KERN_INFO "Reading cachepc proc file\n");
++ printk(KERN_WARNING "CacheSC: Reading entries (%lu:%lli)\n",
++ buflen, off ? *off : 0);
+
-+ if (*off >= cachepc_msrmts_count)
++ if (!off || *off >= cachepc_msrmts_count || *off < 0)
+ return 0;
+
+ len = cachepc_msrmts_count - *off;
+ if (len > buflen) len = buflen;
+
-+ memcpy(buf, cachepc_msrmts + *off, len);
++ left = copy_to_user(buf, cachepc_msrmts + *off, len);
++
++ len -= left;
++ *off += len;
+
+ return len;
+}
+
++ssize_t
++kvm_cachepc_write(struct file *file, const char *buf, size_t buflen, loff_t *off)
++{
++ return 0;
++}
++
int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align,
struct module *module)
{
- struct kvm_cpu_compat_check c;
-+ struct proc_ops proc_ops;
- int r;
- int cpu;
-
-@@ -4848,6 +4874,15 @@ int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align,
+@@ -4848,6 +4904,20 @@ int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align,
r = kvm_vfio_ops_init();
WARN_ON(r);
+ cachepc_init_counters();
-+ cachepc_msrmts_count = 0;
+
-+ //memset(&proc_ops, 0, sizeof(proc_ops));
-+ //proc_ops.proc_read = kvm_cachepc_read;
++ cachepc_msrmts_count = L1_SETS;
++ cachepc_msrmts = kzalloc(cachepc_msrmts_count, GFP_KERNEL);
++ BUG_ON(cachepc_msrmts == NULL);
++
++ memset(&cachepc_proc_ops, 0, sizeof(cachepc_proc_ops));
++ cachepc_proc_ops.proc_open = kvm_cachepc_open;
++ cachepc_proc_ops.proc_read = kvm_cachepc_read;
++ cachepc_proc_ops.proc_write = kvm_cachepc_write;
++ cachepc_proc_ops.proc_release = kvm_cachepc_close;
+
-+ //cachepc_msrmts_file = proc_create("cachepc", 0644, NULL, &proc_ops);
-+ //BUG_ON(cachepc_msrmts_file == NULL);
++ proc_create("cachepc", 0644, NULL, &cachepc_proc_ops);
+
return 0;
out_unreg:
-@@ -4872,6 +4907,7 @@ EXPORT_SYMBOL_GPL(kvm_init);
+@@ -4872,6 +4942,9 @@ EXPORT_SYMBOL_GPL(kvm_init);
void kvm_exit(void)
{
-+ //remove_proc_entry("cachepc", cachepc_msrmts_file);
++ remove_proc_entry("cachepc", NULL);
++ kfree(cachepc_msrmts);
++
debugfs_remove_recursive(kvm_debugfs_dir);
misc_deregister(&kvm_dev);
kmem_cache_destroy(kvm_vcpu_cache);
diff --git a/src/cachepc.c b/src/cachepc.c
@@ -95,12 +95,19 @@ cachepc_prepare_ds(cache_ctx *ctx)
}
void
-cachepc_save_msrmts(cacheline *head, const char *prefix, int index)
+cachepc_save_msrmts(cacheline *head)
{
- char filename[256];
+ cacheline *curr_cl;
- snprintf(filename, sizeof(filename), "%s.%i", prefix, index);
+ curr_cl = head;
+ do {
+ if (IS_FIRST(curr_cl->flags)) {
+ BUG_ON(curr_cl->cache_set >= cachepc_msrmts_count);
+ cachepc_msrmts[curr_cl->cache_set] = curr_cl->count;
+ }
+ curr_cl = curr_cl->prev;
+ } while (curr_cl != head);
}
void
diff --git a/src/cachepc.h b/src/cachepc.h
@@ -15,7 +15,7 @@ void cachepc_init_counters(void);
cache_ctx *cachepc_get_ctx(cache_level cl);
cacheline *cachepc_prepare_ds(cache_ctx *ctx);
-void cachepc_save_msrmts(cacheline *head, const char *prefix, int index);
+void cachepc_save_msrmts(cacheline *head);
void cachepc_print_msrmts(cacheline *head);
void cachepc_release_ds(cache_ctx *ctx, cacheline *ds);
void cachepc_release_ctx(cache_ctx *ctx);
@@ -32,6 +32,9 @@ static inline cacheline *cachepc_probe_set(cacheline *curr_cl);
__attribute__((always_inline))
static inline cacheline *cachepc_probe(cacheline *head);
+extern uint8_t *cachepc_msrmts;
+extern size_t cachepc_msrmts_count;
+
/*
* Prime phase: fill the target cache (encoded in the size of the data structure)
* with the prepared data structure, i.e. with attacker data.