summaryrefslogtreecommitdiffstats
path: root/tools/testing/selftests/kvm/lib/x86_64/perf_test_util.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2022-07-28 12:36:35 +0200
committerThomas Gleixner <tglx@linutronix.de>2022-07-28 12:36:35 +0200
commit779fda86bdeb86bad6daa4f0ecf37788dfc26f6c (patch)
tree6445c0ba43c460765b27e62d9d3bec13c2cde674 /tools/testing/selftests/kvm/lib/x86_64/perf_test_util.c
parentac165aab469895de059a4a191a2e04ddb5421d0e (diff)
parent2bd1753e8c431fc7475c04ac8d14a4e9930f47f6 (diff)
downloadlinux-779fda86bdeb86bad6daa4f0ecf37788dfc26f6c.tar.bz2
Merge tag 'irqchip-5.20' of git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms into irq/core
Pull irqchip/genirq updates from Marc Zyngier: * Core code update: - Non-SMP IRQ affinity fixes, allowing UP kernel to behave similarly to SMP ones for the purpose of interrupt affinity - Let irq_set_chip_handler_name_locked() take a const struct irq_chip * - Tidy-up the NOMAP irqdomain API variant - Teach action_show() to use for_each_action_of_desc() - Make irq_chip_request_resources_parent() allow the parent callback to be optional - Remove dynamic allocations from populate_parent_alloc_arg() * New drivers: - Merge the long awaited IRQ support for the LoongArch architecture, with the provisional ACPICA update (to be reverted once the official support lands) - New Renesas RZ/G2L IRQC driver, equipped with its companion GPIO driver * Driver updates - Optimise the hot path operations for the SiFive PLIC, trading the locking for per-CPU priority masking masking operations which are apparently faster - Work around broken PLIC implementations that deal pretty badly with edge-triggered interrupts. Flag two implementations as affected. - Simplify the irq-stm32-exti driver, particularly the table that remaps the interrupts from exti to the GIC, reducing the memory usage - Convert the ocelot irq_chip to being immutable - Check ioremap() return value in the MIPS GIC driver - Move MMP driver init function declarations into the common .h - The obligatory typo fixes Link: https://lore.kernel.org/all/20220727192356.1860546-1-maz@kernel.org
Diffstat (limited to 'tools/testing/selftests/kvm/lib/x86_64/perf_test_util.c')
-rw-r--r--tools/testing/selftests/kvm/lib/x86_64/perf_test_util.c112
1 files changed, 112 insertions, 0 deletions
diff --git a/tools/testing/selftests/kvm/lib/x86_64/perf_test_util.c b/tools/testing/selftests/kvm/lib/x86_64/perf_test_util.c
new file mode 100644
index 000000000000..e258524435a0
--- /dev/null
+++ b/tools/testing/selftests/kvm/lib/x86_64/perf_test_util.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * x86_64-specific extensions to perf_test_util.c.
+ *
+ * Copyright (C) 2022, Google, Inc.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <linux/bitmap.h>
+#include <linux/bitops.h>
+
+#include "test_util.h"
+#include "kvm_util.h"
+#include "perf_test_util.h"
+#include "../kvm_util_internal.h"
+#include "processor.h"
+#include "vmx.h"
+
+void perf_test_l2_guest_code(uint64_t vcpu_id)
+{
+ perf_test_guest_code(vcpu_id);
+ vmcall();
+}
+
+extern char perf_test_l2_guest_entry[];
+__asm__(
+"perf_test_l2_guest_entry:"
+" mov (%rsp), %rdi;"
+" call perf_test_l2_guest_code;"
+" ud2;"
+);
+
+static void perf_test_l1_guest_code(struct vmx_pages *vmx, uint64_t vcpu_id)
+{
+#define L2_GUEST_STACK_SIZE 64
+ unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE];
+ unsigned long *rsp;
+
+ GUEST_ASSERT(vmx->vmcs_gpa);
+ GUEST_ASSERT(prepare_for_vmx_operation(vmx));
+ GUEST_ASSERT(load_vmcs(vmx));
+ GUEST_ASSERT(ept_1g_pages_supported());
+
+ rsp = &l2_guest_stack[L2_GUEST_STACK_SIZE - 1];
+ *rsp = vcpu_id;
+ prepare_vmcs(vmx, perf_test_l2_guest_entry, rsp);
+
+ GUEST_ASSERT(!vmlaunch());
+ GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL);
+ GUEST_DONE();
+}
+
+uint64_t perf_test_nested_pages(int nr_vcpus)
+{
+ /*
+ * 513 page tables is enough to identity-map 256 TiB of L2 with 1G
+ * pages and 4-level paging, plus a few pages per-vCPU for data
+ * structures such as the VMCS.
+ */
+ return 513 + 10 * nr_vcpus;
+}
+
+void perf_test_setup_ept(struct vmx_pages *vmx, struct kvm_vm *vm)
+{
+ uint64_t start, end;
+
+ prepare_eptp(vmx, vm, 0);
+
+ /*
+ * Identity map the first 4G and the test region with 1G pages so that
+ * KVM can shadow the EPT12 with the maximum huge page size supported
+ * by the backing source.
+ */
+ nested_identity_map_1g(vmx, vm, 0, 0x100000000ULL);
+
+ start = align_down(perf_test_args.gpa, PG_SIZE_1G);
+ end = align_up(perf_test_args.gpa + perf_test_args.size, PG_SIZE_1G);
+ nested_identity_map_1g(vmx, vm, start, end - start);
+}
+
+void perf_test_setup_nested(struct kvm_vm *vm, int nr_vcpus)
+{
+ struct vmx_pages *vmx, *vmx0 = NULL;
+ struct kvm_regs regs;
+ vm_vaddr_t vmx_gva;
+ int vcpu_id;
+
+ nested_vmx_check_supported();
+
+ for (vcpu_id = 0; vcpu_id < nr_vcpus; vcpu_id++) {
+ vmx = vcpu_alloc_vmx(vm, &vmx_gva);
+
+ if (vcpu_id == 0) {
+ perf_test_setup_ept(vmx, vm);
+ vmx0 = vmx;
+ } else {
+ /* Share the same EPT table across all vCPUs. */
+ vmx->eptp = vmx0->eptp;
+ vmx->eptp_hva = vmx0->eptp_hva;
+ vmx->eptp_gpa = vmx0->eptp_gpa;
+ }
+
+ /*
+ * Override the vCPU to run perf_test_l1_guest_code() which will
+ * bounce it into L2 before calling perf_test_guest_code().
+ */
+ vcpu_regs_get(vm, vcpu_id, &regs);
+ regs.rip = (unsigned long) perf_test_l1_guest_code;
+ vcpu_regs_set(vm, vcpu_id, &regs);
+ vcpu_args_set(vm, vcpu_id, 2, vmx_gva, vcpu_id);
+ }
+}