0001
0002
0003
0004
0005
0006
0007 #include <stdio.h>
0008 #include <stdlib.h>
0009 #include <linux/bitmap.h>
0010 #include <linux/bitops.h>
0011
0012 #include "test_util.h"
0013 #include "kvm_util.h"
0014 #include "perf_test_util.h"
0015 #include "processor.h"
0016 #include "vmx.h"
0017
0018 void perf_test_l2_guest_code(uint64_t vcpu_id)
0019 {
0020 perf_test_guest_code(vcpu_id);
0021 vmcall();
0022 }
0023
0024 extern char perf_test_l2_guest_entry[];
0025 __asm__(
0026 "perf_test_l2_guest_entry:"
0027 " mov (%rsp), %rdi;"
0028 " call perf_test_l2_guest_code;"
0029 " ud2;"
0030 );
0031
0032 static void perf_test_l1_guest_code(struct vmx_pages *vmx, uint64_t vcpu_id)
0033 {
0034 #define L2_GUEST_STACK_SIZE 64
0035 unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE];
0036 unsigned long *rsp;
0037
0038 GUEST_ASSERT(vmx->vmcs_gpa);
0039 GUEST_ASSERT(prepare_for_vmx_operation(vmx));
0040 GUEST_ASSERT(load_vmcs(vmx));
0041 GUEST_ASSERT(ept_1g_pages_supported());
0042
0043 rsp = &l2_guest_stack[L2_GUEST_STACK_SIZE - 1];
0044 *rsp = vcpu_id;
0045 prepare_vmcs(vmx, perf_test_l2_guest_entry, rsp);
0046
0047 GUEST_ASSERT(!vmlaunch());
0048 GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL);
0049 GUEST_DONE();
0050 }
0051
0052 uint64_t perf_test_nested_pages(int nr_vcpus)
0053 {
0054
0055
0056
0057
0058
0059 return 513 + 10 * nr_vcpus;
0060 }
0061
0062 void perf_test_setup_ept(struct vmx_pages *vmx, struct kvm_vm *vm)
0063 {
0064 uint64_t start, end;
0065
0066 prepare_eptp(vmx, vm, 0);
0067
0068
0069
0070
0071
0072
0073 nested_identity_map_1g(vmx, vm, 0, 0x100000000ULL);
0074
0075 start = align_down(perf_test_args.gpa, PG_SIZE_1G);
0076 end = align_up(perf_test_args.gpa + perf_test_args.size, PG_SIZE_1G);
0077 nested_identity_map_1g(vmx, vm, start, end - start);
0078 }
0079
0080 void perf_test_setup_nested(struct kvm_vm *vm, int nr_vcpus, struct kvm_vcpu *vcpus[])
0081 {
0082 struct vmx_pages *vmx, *vmx0 = NULL;
0083 struct kvm_regs regs;
0084 vm_vaddr_t vmx_gva;
0085 int vcpu_id;
0086
0087 TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX));
0088
0089 for (vcpu_id = 0; vcpu_id < nr_vcpus; vcpu_id++) {
0090 vmx = vcpu_alloc_vmx(vm, &vmx_gva);
0091
0092 if (vcpu_id == 0) {
0093 perf_test_setup_ept(vmx, vm);
0094 vmx0 = vmx;
0095 } else {
0096
0097 vmx->eptp = vmx0->eptp;
0098 vmx->eptp_hva = vmx0->eptp_hva;
0099 vmx->eptp_gpa = vmx0->eptp_gpa;
0100 }
0101
0102
0103
0104
0105
0106 vcpu_regs_get(vcpus[vcpu_id], ®s);
0107 regs.rip = (unsigned long) perf_test_l1_guest_code;
0108 vcpu_regs_set(vcpus[vcpu_id], ®s);
0109 vcpu_args_set(vcpus[vcpu_id], 2, vmx_gva, vcpu_id);
0110 }
0111 }