#include <stdio.h>
#include <stdlib.h>
#include <linux/bitmap.h>
#include <linux/bitops.h>
#include "test_util.h"
#include "kvm_util.h"
#include "memstress.h"
#include "processor.h"
#include "svm_util.h"
#include "vmx.h"
void memstress_l2_guest_code(uint64_t vcpu_id)
{
memstress_guest_code(vcpu_id);
vmcall();
}
extern char memstress_l2_guest_entry[];
__asm__(
"memstress_l2_guest_entry:"
" mov (%rsp), %rdi;"
" call memstress_l2_guest_code;"
" ud2;"
);
#define L2_GUEST_STACK_SIZE 64
static void l1_vmx_code(struct vmx_pages *vmx, uint64_t vcpu_id)
{
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, memstress_l2_guest_entry, rsp);
GUEST_ASSERT(!vmlaunch());
GUEST_ASSERT_EQ(vmreadz(VM_EXIT_REASON), EXIT_REASON_VMCALL);
GUEST_DONE();
}
static void l1_svm_code(struct svm_test_data *svm, uint64_t vcpu_id)
{
unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE];
unsigned long *rsp;
rsp = &l2_guest_stack[L2_GUEST_STACK_SIZE - 1];
*rsp = vcpu_id;
generic_svm_setup(svm, memstress_l2_guest_entry, rsp);
run_guest(svm->vmcb, svm->vmcb_gpa);
GUEST_ASSERT_EQ(svm->vmcb->control.exit_code, SVM_EXIT_VMMCALL);
GUEST_DONE();
}
static void memstress_l1_guest_code(void *data, uint64_t vcpu_id)
{
if (this_cpu_has(X86_FEATURE_VMX))
l1_vmx_code(data, vcpu_id);
else
l1_svm_code(data, vcpu_id);
}
uint64_t memstress_nested_pages(int nr_vcpus)
{
return 513 + 10 * nr_vcpus;
}
static void memstress_setup_ept_mappings(struct kvm_vm *vm)
{
uint64_t start, end;
tdp_identity_map_1g(vm, 0, 0x100000000ULL);
start = align_down(memstress_args.gpa, PG_SIZE_1G);
end = align_up(memstress_args.gpa + memstress_args.size, PG_SIZE_1G);
tdp_identity_map_1g(vm, start, end - start);
}
void memstress_setup_nested(struct kvm_vm *vm, int nr_vcpus, struct kvm_vcpu *vcpus[])
{
struct kvm_regs regs;
vm_vaddr_t nested_gva;
int vcpu_id;
TEST_REQUIRE(kvm_cpu_has_tdp());
vm_enable_tdp(vm);
memstress_setup_ept_mappings(vm);
for (vcpu_id = 0; vcpu_id < nr_vcpus; vcpu_id++) {
if (kvm_cpu_has(X86_FEATURE_VMX))
vcpu_alloc_vmx(vm, &nested_gva);
else
vcpu_alloc_svm(vm, &nested_gva);
vcpu_regs_get(vcpus[vcpu_id], ®s);
regs.rip = (unsigned long) memstress_l1_guest_code;
vcpu_regs_set(vcpus[vcpu_id], ®s);
vcpu_args_set(vcpus[vcpu_id], 2, nested_gva, vcpu_id);
}
}