1
2
3
4
5#include <inttypes.h>
6
7#include "kvm_util.h"
8#include "perf_test_util.h"
9#include "processor.h"
10
11struct perf_test_args perf_test_args;
12
13uint64_t guest_test_phys_mem;
14
15
16
17
18
19static uint64_t guest_test_virt_mem = DEFAULT_GUEST_TEST_MEM;
20
21
22
23
24
25static void guest_code(uint32_t vcpu_id)
26{
27 struct perf_test_vcpu_args *vcpu_args = &perf_test_args.vcpu_args[vcpu_id];
28 uint64_t gva;
29 uint64_t pages;
30 int i;
31
32
33 GUEST_ASSERT(vcpu_args->vcpu_id == vcpu_id);
34
35 gva = vcpu_args->gva;
36 pages = vcpu_args->pages;
37
38 while (true) {
39 for (i = 0; i < pages; i++) {
40 uint64_t addr = gva + (i * perf_test_args.guest_page_size);
41
42 if (i % perf_test_args.wr_fract == 0)
43 *(uint64_t *)addr = 0x0123456789ABCDEF;
44 else
45 READ_ONCE(*(uint64_t *)addr);
46 }
47
48 GUEST_SYNC(1);
49 }
50}
51
52struct kvm_vm *perf_test_create_vm(enum vm_guest_mode mode, int vcpus,
53 uint64_t vcpu_memory_bytes, int slots,
54 enum vm_mem_backing_src_type backing_src)
55{
56 struct kvm_vm *vm;
57 uint64_t guest_num_pages;
58 int i;
59
60 pr_info("Testing guest mode: %s\n", vm_guest_mode_string(mode));
61
62 perf_test_args.host_page_size = getpagesize();
63 perf_test_args.guest_page_size = vm_guest_mode_params[mode].page_size;
64
65 guest_num_pages = vm_adjust_num_guest_pages(mode,
66 (vcpus * vcpu_memory_bytes) / perf_test_args.guest_page_size);
67
68 TEST_ASSERT(vcpu_memory_bytes % perf_test_args.host_page_size == 0,
69 "Guest memory size is not host page size aligned.");
70 TEST_ASSERT(vcpu_memory_bytes % perf_test_args.guest_page_size == 0,
71 "Guest memory size is not guest page size aligned.");
72 TEST_ASSERT(guest_num_pages % slots == 0,
73 "Guest memory cannot be evenly divided into %d slots.",
74 slots);
75
76 vm = vm_create_with_vcpus(mode, vcpus, DEFAULT_GUEST_PHY_PAGES,
77 (vcpus * vcpu_memory_bytes) / perf_test_args.guest_page_size,
78 0, guest_code, NULL);
79
80 perf_test_args.vm = vm;
81
82
83
84
85
86 TEST_ASSERT(guest_num_pages < vm_get_max_gfn(vm),
87 "Requested more guest memory than address space allows.\n"
88 " guest pages: %" PRIx64 " max gfn: %" PRIx64
89 " vcpus: %d wss: %" PRIx64 "]\n",
90 guest_num_pages, vm_get_max_gfn(vm), vcpus,
91 vcpu_memory_bytes);
92
93 guest_test_phys_mem = (vm_get_max_gfn(vm) - guest_num_pages) *
94 perf_test_args.guest_page_size;
95 guest_test_phys_mem &= ~(perf_test_args.host_page_size - 1);
96#ifdef __s390x__
97
98 guest_test_phys_mem &= ~((1 << 20) - 1);
99#endif
100 pr_info("guest physical test memory offset: 0x%lx\n", guest_test_phys_mem);
101
102
103 for (i = 0; i < slots; i++) {
104 uint64_t region_pages = guest_num_pages / slots;
105 vm_paddr_t region_start = guest_test_phys_mem +
106 region_pages * perf_test_args.guest_page_size * i;
107
108 vm_userspace_mem_region_add(vm, backing_src, region_start,
109 PERF_TEST_MEM_SLOT_INDEX + i,
110 region_pages, 0);
111 }
112
113
114 virt_map(vm, guest_test_virt_mem, guest_test_phys_mem, guest_num_pages);
115
116 ucall_init(vm, NULL);
117
118 return vm;
119}
120
121void perf_test_destroy_vm(struct kvm_vm *vm)
122{
123 ucall_uninit(vm);
124 kvm_vm_free(vm);
125}
126
127void perf_test_setup_vcpus(struct kvm_vm *vm, int vcpus,
128 uint64_t vcpu_memory_bytes,
129 bool partition_vcpu_memory_access)
130{
131 vm_paddr_t vcpu_gpa;
132 struct perf_test_vcpu_args *vcpu_args;
133 int vcpu_id;
134
135 for (vcpu_id = 0; vcpu_id < vcpus; vcpu_id++) {
136 vcpu_args = &perf_test_args.vcpu_args[vcpu_id];
137
138 vcpu_args->vcpu_id = vcpu_id;
139 if (partition_vcpu_memory_access) {
140 vcpu_args->gva = guest_test_virt_mem +
141 (vcpu_id * vcpu_memory_bytes);
142 vcpu_args->pages = vcpu_memory_bytes /
143 perf_test_args.guest_page_size;
144 vcpu_gpa = guest_test_phys_mem +
145 (vcpu_id * vcpu_memory_bytes);
146 } else {
147 vcpu_args->gva = guest_test_virt_mem;
148 vcpu_args->pages = (vcpus * vcpu_memory_bytes) /
149 perf_test_args.guest_page_size;
150 vcpu_gpa = guest_test_phys_mem;
151 }
152
153 vcpu_args_set(vm, vcpu_id, 1, vcpu_id);
154
155 pr_debug("Added VCPU %d with test mem gpa [%lx, %lx)\n",
156 vcpu_id, vcpu_gpa, vcpu_gpa +
157 (vcpu_args->pages * perf_test_args.guest_page_size));
158 }
159}
160