brintos

brintos / linux-shallow public Read only

0
0
Text · 2.8 KiB · d61e623 Raw
113 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * x86_64-specific extensions to memstress.c.4 *5 * Copyright (C) 2022, Google, Inc.6 */7#include <stdio.h>8#include <stdlib.h>9#include <linux/bitmap.h>10#include <linux/bitops.h>11 12#include "test_util.h"13#include "kvm_util.h"14#include "memstress.h"15#include "processor.h"16#include "vmx.h"17 18void memstress_l2_guest_code(uint64_t vcpu_id)19{20	memstress_guest_code(vcpu_id);21	vmcall();22}23 24extern char memstress_l2_guest_entry[];25__asm__(26"memstress_l2_guest_entry:"27"	mov (%rsp), %rdi;"28"	call memstress_l2_guest_code;"29"	ud2;"30);31 32static void memstress_l1_guest_code(struct vmx_pages *vmx, uint64_t vcpu_id)33{34#define L2_GUEST_STACK_SIZE 6435	unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE];36	unsigned long *rsp;37 38	GUEST_ASSERT(vmx->vmcs_gpa);39	GUEST_ASSERT(prepare_for_vmx_operation(vmx));40	GUEST_ASSERT(load_vmcs(vmx));41	GUEST_ASSERT(ept_1g_pages_supported());42 43	rsp = &l2_guest_stack[L2_GUEST_STACK_SIZE - 1];44	*rsp = vcpu_id;45	prepare_vmcs(vmx, memstress_l2_guest_entry, rsp);46 47	GUEST_ASSERT(!vmlaunch());48	GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL);49	GUEST_DONE();50}51 52uint64_t memstress_nested_pages(int nr_vcpus)53{54	/*55	 * 513 page tables is enough to identity-map 256 TiB of L2 with 1G56	 * pages and 4-level paging, plus a few pages per-vCPU for data57	 * structures such as the VMCS.58	 */59	return 513 + 10 * nr_vcpus;60}61 62void memstress_setup_ept(struct vmx_pages *vmx, struct kvm_vm *vm)63{64	uint64_t start, end;65 66	prepare_eptp(vmx, vm, 0);67 68	/*69	 * Identity map the first 4G and the test region with 1G pages so that70	 * KVM can shadow the EPT12 with the maximum huge page size supported71	 * by the backing source.72	 */73	nested_identity_map_1g(vmx, vm, 0, 0x100000000ULL);74 75	start = align_down(memstress_args.gpa, PG_SIZE_1G);76	end = align_up(memstress_args.gpa + memstress_args.size, PG_SIZE_1G);77	nested_identity_map_1g(vmx, vm, start, end - start);78}79 80void memstress_setup_nested(struct kvm_vm *vm, int nr_vcpus, struct kvm_vcpu *vcpus[])81{82	struct vmx_pages *vmx, *vmx0 = NULL;83	struct kvm_regs regs;84	vm_vaddr_t vmx_gva;85	int vcpu_id;86 87	TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX));88	TEST_REQUIRE(kvm_cpu_has_ept());89 90	for (vcpu_id = 0; vcpu_id < nr_vcpus; vcpu_id++) {91		vmx = vcpu_alloc_vmx(vm, &vmx_gva);92 93		if (vcpu_id == 0) {94			memstress_setup_ept(vmx, vm);95			vmx0 = vmx;96		} else {97			/* Share the same EPT table across all vCPUs. */98			vmx->eptp = vmx0->eptp;99			vmx->eptp_hva = vmx0->eptp_hva;100			vmx->eptp_gpa = vmx0->eptp_gpa;101		}102 103		/*104		 * Override the vCPU to run memstress_l1_guest_code() which will105		 * bounce it into L2 before calling memstress_guest_code().106		 */107		vcpu_regs_get(vcpus[vcpu_id], &regs);108		regs.rip = (unsigned long) memstress_l1_guest_code;109		vcpu_regs_set(vcpus[vcpu_id], &regs);110		vcpu_args_set(vcpus[vcpu_id], 2, vmx_gva, vcpu_id);111	}112}113