commit c80d9518901eac7547b462ec4e79125c6913b378
parent 7e2719c913c833bdd93b463f5a7dc878d5a22273
Author: Louis Burda <quent.burda@gmail.com>
Date: Mon, 25 Jul 2022 20:13:43 +0200
Working prime and probe - but inaccuarate
Diffstat:
6 files changed, 94 insertions(+), 57 deletions(-)
diff --git a/Makefile b/Makefile
@@ -3,15 +3,13 @@ PWD := $(shell pwd)
.PHONY: all reset clean prepare build
-all: reset prepare build
+all: reset clean prepare build
clean:
$(MAKE) -C $(KERNEL_SOURCE) SUBDIRS=arch/x86/kvm clean
reset:
git -C $(KERNEL_SOURCE) reset --hard
- #git -C $(KERNEL_SOURCE) clean -dfx
- #cp .config $(KERNEL_SOURCE)/.config
$(KERNEL_SOURCE)/arch/x86/kvm/svm/cachepc:
ln -s $(PWD)/src $@
diff --git a/patch.diff b/patch.diff
@@ -1,8 +1,19 @@
diff --git a/arch/x86/kvm/Makefile b/arch/x86/kvm/Makefile
-index b804444e16d4..1f7d3b15cf4a 100644
+index b804444e16d4..c94f8c4460f1 100644
--- a/arch/x86/kvm/Makefile
+++ b/arch/x86/kvm/Makefile
-@@ -20,7 +20,8 @@ kvm-y += x86.o emulate.o i8259.o irq.o lapic.o \
+@@ -10,7 +10,9 @@ endif
+ KVM := ../../../virt/kvm
+
+ kvm-y += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o \
+- $(KVM)/eventfd.o $(KVM)/irqchip.o $(KVM)/vfio.o
++ $(KVM)/eventfd.o $(KVM)/irqchip.o $(KVM)/vfio.o \
++ svm/cachepc/cachepc.o svm/cachepc/util.o
++
+ kvm-$(CONFIG_KVM_ASYNC_PF) += $(KVM)/async_pf.o
+
+ kvm-y += x86.o emulate.o i8259.o irq.o lapic.o \
+@@ -20,7 +22,8 @@ kvm-y += x86.o emulate.o i8259.o irq.o lapic.o \
kvm-intel-y += vmx/vmx.o vmx/vmenter.o vmx/pmu_intel.o vmx/vmcs12.o \
vmx/evmcs.o vmx/nested.o vmx/posted_intr.o
@@ -13,7 +24,7 @@ index b804444e16d4..1f7d3b15cf4a 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..4c6ebe040c30 100644
+index 7b3cfbe8f7e3..e9a2b1048e28 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -2,6 +2,8 @@
@@ -25,37 +36,38 @@ index 7b3cfbe8f7e3..4c6ebe040c30 100644
#include "irq.h"
#include "mmu.h"
#include "kvm_cache_regs.h"
-@@ -3728,6 +3730,16 @@ void __svm_vcpu_run(unsigned long vmcb_pa, unsigned long *regs);
- static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu,
- struct vcpu_svm *svm)
+@@ -3785,8 +3787,18 @@ static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu,
+
+ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu)
{
+- struct vcpu_svm *svm = to_svm(vcpu);
+ static struct cache_ctx *ctx = NULL;
-+ static struct cacheline *cache_ds = NULL;
-+ static struct cacheline *curr_head = NULL;
-+ static struct cacheline *next_head = NULL;
++ static struct cacheline *ds = NULL;
++ static struct cacheline *head = NULL;
+ static int run_index = 0;
++ struct vcpu_svm *svm;
+
+ if (!ctx) ctx = cachepc_get_ctx(L1);
-+ if (!cache_ds) cache_ds = cachepc_prepare_ds(ctx);
-+ if (!curr_head) curr_head = cache_ds;
-+
- /*
- * VMENTER enables interrupts (host state), but the kernel state is
- * interrupts disabled when this is invoked. Also tell RCU about
-@@ -3751,7 +3763,13 @@ static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu,
- if (sev_es_guest(svm->vcpu.kvm)) {
- __svm_sev_es_vcpu_run(svm->vmcb_pa);
- } else {
-+ curr_head = cachepc_prime(curr_head);
- __svm_vcpu_run(svm->vmcb_pa, (unsigned long *)&svm->vcpu.arch.regs);
-+ next_head = cachepc_probe(curr_head);
-+ //cachepc_save_msrmts(curr_head, "/tmp/msrmt", run_index);
-+ cachepc_print_msrmts(curr_head);
-+ curr_head = next_head;
-+ run_index += 1;
-
- #ifdef CONFIG_X86_64
- native_wrmsrl(MSR_GS_BASE, svm->host.gs_base);
++ 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;
+
++ cachepc_probe(head);
++ cachepc_print_msrmts(head);
++
++ 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
@@ -72,7 +84,7 @@ index 7f2e2a09ebbd..762eb35f19e5 100644
#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..f900cf449fb8 100644
+index 2541a17ff1c4..fd7511484011 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -51,6 +51,7 @@
@@ -133,7 +145,7 @@ index 2541a17ff1c4..f900cf449fb8 100644
int r;
int cpu;
-@@ -4848,6 +4874,16 @@ int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align,
+@@ -4848,6 +4874,15 @@ int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align,
r = kvm_vfio_ops_init();
WARN_ON(r);
@@ -145,12 +157,11 @@ index 2541a17ff1c4..f900cf449fb8 100644
+
+ //cachepc_msrmts_file = proc_create("cachepc", 0644, NULL, &proc_ops);
+ //BUG_ON(cachepc_msrmts_file == NULL);
-+
+
return 0;
out_unreg:
-@@ -4872,6 +4908,7 @@ EXPORT_SYMBOL_GPL(kvm_init);
+@@ -4872,6 +4907,7 @@ EXPORT_SYMBOL_GPL(kvm_init);
void kvm_exit(void)
{
diff --git a/src/cache_types.h b/src/cache_types.h
@@ -8,8 +8,8 @@
#define REMOVE_PAGE_OFFSET(ptr) ((void *) (((uintptr_t) ptr) & PAGE_MASK))
-#define GET_BIT(b, i) (((b & (1 << i)) >> i) & 1)
-#define SET_BIT(b, i) (b | (1 << i))
+#define GET_BIT(b, i) (((b) >> (i)) & 1)
+#define SET_BIT(b, i) ((b) | (1 << (i)))
/* Operate cacheline flags
* Used flags:
diff --git a/src/cachepc.c b/src/cachepc.c
@@ -26,16 +26,16 @@ cachepc_init_counters(void)
event = event_no | (event_mask << 8);
event |= (1<< 17); /* OsUserMode bit */
event |= (1 << 22); /* enable performance counter */
- printk(KERN_INFO "Writing to msr event %d", event);
+ printk(KERN_WARNING "CachePC: Initialized event %d\n", event);
asm volatile ("wrmsr" : : "c"(reg_addr), "a"(event), "d"(0x00));
reg_addr = 0xc0010202;
event_no = 0x64;
event_mask = 0xC8;
event = event_no | (event_mask << 8);
- event |= (1<< 17); /* OsUserMode bit */
+ event |= (1 << 17); /* OsUserMode bit */
event |= (1 << 22); /* enable performance counter */
- printk(KERN_INFO "Writing to msr event %d", event);
+ printk(KERN_WARNING "CachePC: Initialized event %d\n", event);
asm volatile ("wrmsr" : : "c"(reg_addr), "a"(event), "d"(0x00));
}
@@ -44,11 +44,12 @@ cachepc_get_ctx(cache_level cache_level)
{
cache_ctx *ctx;
- printk(KERN_INFO "CACHEPC_GET_CTX");
+ // printk(KERN_WARNING "CachePC: Getting ctx..\n");
ctx = kzalloc(sizeof(cache_ctx), GFP_KERNEL);
BUG_ON(ctx == NULL);
+ BUG_ON(cache_level != L1);
if (cache_level == L1) {
ctx->addressing = L1_ADDRESSING;
ctx->sets = L1_SETS;
@@ -68,6 +69,8 @@ cachepc_get_ctx(cache_level cache_level)
ctx->set_size = CACHELINE_SIZE * ctx->associativity;
ctx->cache_size = ctx->sets * ctx->set_size;
+ // printk(KERN_WARNING "CachePC: Getting ctx done\n");
+
return ctx;
}
@@ -80,12 +83,14 @@ cachepc_prepare_ds(cache_ctx *ctx)
cacheline **cacheline_ptr_arr;
cacheline *cache_ds;
- printk(KERN_INFO "CACHEPC_BUILD_CACHE_DS");
+ //printk(KERN_WARNING "CachePC: Preparing ds..\n");
cacheline_ptr_arr = allocate_cache_ds(ctx);
cache_ds = build_cache_ds(ctx, cacheline_ptr_arr);
kfree(cacheline_ptr_arr);
+ // printk(KERN_WARNING "CachePC: Preparing ds done\n");
+
return cache_ds;
}
@@ -106,7 +111,7 @@ cachepc_print_msrmts(cacheline *head)
curr_cl = head;
do {
if (IS_FIRST(curr_cl->flags)) {
- printk(KERN_WARNING "Count for cache set %i: %llu\n",
+ printk(KERN_WARNING "CachePC: Count for cache set %i: %llu\n",
curr_cl->cache_set, curr_cl->count);
}
@@ -114,6 +119,24 @@ cachepc_print_msrmts(cacheline *head)
} while (curr_cl != head);
}
+void *
+remove_cache_set(cache_ctx *ctx, void *ptr)
+{
+ return (void *) (((uintptr_t) ptr) & ~SET_MASK(ctx->sets));
+}
+
+void
+cachepc_release_ds(cache_ctx *ctx, cacheline *ds)
+{
+ kfree(remove_cache_set(ctx, ds));
+}
+
+void
+cachepc_release_ctx(cache_ctx *ctx)
+{
+ kfree(ctx);
+}
+
/*
* Create a randomized doubly linked list with the following structure:
* set A <--> set B <--> ... <--> set X <--> set A
@@ -136,13 +159,13 @@ cacheline *build_cache_ds(cache_ctx *ctx, cacheline **cl_ptr_arr) {
idx_per_set = kzalloc(ctx->sets * sizeof(uint32_t), GFP_KERNEL);
BUG_ON(idx_per_set == NULL);
- cl_ptr_arr_sorted = kmalloc(ctx->nr_of_cachelines * sizeof(cacheline *), GFP_KERNEL);
+ cl_ptr_arr_sorted = kzalloc(ctx->nr_of_cachelines * sizeof(cacheline *), GFP_KERNEL);
BUG_ON(cl_ptr_arr_sorted == NULL);
set_len = ctx->associativity;
for (i = 0; i < ctx->nr_of_cachelines; ++i) {
- set_offset = cl_ptr_arr[i]->cache_set * set_len;
- idx_curr_set = idx_per_set[cl_ptr_arr[i]->cache_set];
+ set_offset = cl_ptr_arr[i]->cache_set * set_len;
+ idx_curr_set = idx_per_set[cl_ptr_arr[i]->cache_set];
cl_ptr_arr_sorted[set_offset + idx_curr_set] = cl_ptr_arr[i];
idx_per_set[cl_ptr_arr[i]->cache_set] += 1;
@@ -198,8 +221,8 @@ void build_randomized_list_for_cache_set(cache_ctx *ctx, cacheline **cacheline_p
curr_cl->prev = cacheline_ptr_arr[idx_map[(len - 1 + i) % len]];
curr_cl->count = 0;
- if (curr_cl == cacheline_ptr_arr[0]) {
- curr_cl->flags = SET_FIRST(DEFAULT_FLAGS);
+ if (idx_map[i] == 0) {
+ curr_cl->flags = SET_FIRST(DEFAULT_FLAGS);
curr_cl->prev->flags = SET_LAST(DEFAULT_FLAGS);
} else {
curr_cl->flags = curr_cl->flags | DEFAULT_FLAGS;
@@ -219,13 +242,13 @@ allocate_cache_ds(cache_ctx *ctx)
cacheline **cl_ptr_arr, *cl_arr;
uint32_t i;
- cl_ptr_arr = (cacheline **) kzalloc(ctx->nr_of_cachelines * sizeof(cacheline *), GFP_KERNEL);
+ cl_ptr_arr = kzalloc(ctx->nr_of_cachelines * sizeof(cacheline *), GFP_KERNEL);
BUG_ON(cl_ptr_arr == NULL);
BUG_ON(ctx->addressing != VIRTUAL);
// For virtual addressing, allocating a consecutive chunk of memory is enough
- cl_arr = (cacheline *) aligned_alloc(PAGE_SIZE, ctx->cache_size);
+ cl_arr = aligned_alloc(PAGE_SIZE, ctx->cache_size);
BUG_ON(cl_arr == NULL);
for (i = 0; i < ctx->nr_of_cachelines; ++i) {
@@ -249,10 +272,9 @@ aligned_alloc(size_t alignment, size_t size)
if (size % alignment != 0)
size = size - (size % alignment) + alignment;
- p = kmalloc(size, GFP_KERNEL);
+ p = kzalloc(size, GFP_KERNEL);
BUG_ON(((uintptr_t) p) % alignment != 0);
return p;
}
-
diff --git a/src/cachepc.h b/src/cachepc.h
@@ -17,6 +17,8 @@ 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_print_msrmts(cacheline *head);
+void cachepc_release_ds(cache_ctx *ctx, cacheline *ds);
+void cachepc_release_ctx(cache_ctx *ctx);
__attribute__((always_inline))
static inline cacheline *cachepc_prime(cacheline *head);
@@ -39,7 +41,7 @@ cachepc_prime(cacheline *head)
{
cacheline *curr_cl;
- printk(KERN_WARNING "PROBE");
+ //printk(KERN_WARNING "CachePC: Priming..\n");
cachepc_cpuid();
curr_cl = head;
@@ -49,6 +51,8 @@ cachepc_prime(cacheline *head)
} while(curr_cl != head);
cachepc_cpuid();
+ //printk(KERN_WARNING "CachePC: Priming done\n");
+
return curr_cl->prev;
}
@@ -128,13 +132,15 @@ cachepc_probe(cacheline *head)
{
cacheline *curr_cs;
- printk(KERN_WARNING "PROBE");
+ //printk(KERN_WARNING "CachePC: Probing..");
curr_cs = head;
do {
curr_cs = cachepc_probe_set(curr_cs);
} while (__builtin_expect(curr_cs != head, 1));
+ //printk(KERN_WARNING "CachePC: Probing done");
+
return curr_cs->next;
}
diff --git a/src/util.c b/src/util.c
@@ -12,8 +12,8 @@ random_perm(uint32_t *arr, uint32_t arr_len)
idx = idx % i;
tmp = arr[idx];
- arr[i] = arr[idx];
- arr[idx] = tmp;
+ arr[idx] = arr[i];
+ arr[i] = tmp;
}
}