Skip to content

Commit 672eaa3

Browse files
sean-jcbonzini
authored andcommitted
KVM: selftests: Introduce VM "shape" to allow tests to specify the VM type
Add a "vm_shape" structure to encapsulate the selftests-defined "mode", along with the KVM-defined "type" for use when creating a new VM. "mode" tracks physical and virtual address properties, as well as the preferred backing memory type, while "type" corresponds to the VM type. Taking the VM type will allow adding tests for KVM_CREATE_GUEST_MEMFD without needing an entirely separate set of helpers. At this time, guest_memfd is effectively usable only by confidential VM types in the form of guest private memory, and it's expected that x86 will double down and require unique VM types for TDX and SNP guests. Signed-off-by: Sean Christopherson <seanjc@google.com> Message-Id: <20231027182217.3615211-30-seanjc@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent 01244fc commit 672eaa3

File tree

7 files changed

+73
-35
lines changed

7 files changed

+73
-35
lines changed

tools/testing/selftests/kvm/aarch64/page_fault_test.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -705,7 +705,7 @@ static void run_test(enum vm_guest_mode mode, void *arg)
705705

706706
print_test_banner(mode, p);
707707

708-
vm = ____vm_create(mode);
708+
vm = ____vm_create(VM_SHAPE(mode));
709709
setup_memslots(vm, p);
710710
kvm_vm_elf_load(vm, program_invocation_name);
711711
setup_ucall(vm);

tools/testing/selftests/kvm/dirty_log_test.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,7 @@ static struct kvm_vm *create_vm(enum vm_guest_mode mode, struct kvm_vcpu **vcpu,
699699

700700
pr_info("Testing guest mode: %s\n", vm_guest_mode_string(mode));
701701

702-
vm = __vm_create(mode, 1, extra_mem_pages);
702+
vm = __vm_create(VM_SHAPE(mode), 1, extra_mem_pages);
703703

704704
log_mode_create_vm_done(vm);
705705
*vcpu = vm_vcpu_add(vm, 0, guest_code);

tools/testing/selftests/kvm/include/kvm_util_base.h

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,23 @@ enum vm_guest_mode {
188188
NUM_VM_MODES,
189189
};
190190

191+
struct vm_shape {
192+
enum vm_guest_mode mode;
193+
unsigned int type;
194+
};
195+
196+
#define VM_TYPE_DEFAULT 0
197+
198+
#define VM_SHAPE(__mode) \
199+
({ \
200+
struct vm_shape shape = { \
201+
.mode = (__mode), \
202+
.type = VM_TYPE_DEFAULT \
203+
}; \
204+
\
205+
shape; \
206+
})
207+
191208
#if defined(__aarch64__)
192209

193210
extern enum vm_guest_mode vm_mode_default;
@@ -220,6 +237,8 @@ extern enum vm_guest_mode vm_mode_default;
220237

221238
#endif
222239

240+
#define VM_SHAPE_DEFAULT VM_SHAPE(VM_MODE_DEFAULT)
241+
223242
#define MIN_PAGE_SIZE (1U << MIN_PAGE_SHIFT)
224243
#define PTES_PER_MIN_PAGE ptes_per_page(MIN_PAGE_SIZE)
225244

@@ -784,46 +803,63 @@ vm_paddr_t vm_alloc_page_table(struct kvm_vm *vm);
784803
* __vm_create() does NOT create vCPUs, @nr_runnable_vcpus is used purely to
785804
* calculate the amount of memory needed for per-vCPU data, e.g. stacks.
786805
*/
787-
struct kvm_vm *____vm_create(enum vm_guest_mode mode);
788-
struct kvm_vm *__vm_create(enum vm_guest_mode mode, uint32_t nr_runnable_vcpus,
806+
struct kvm_vm *____vm_create(struct vm_shape shape);
807+
struct kvm_vm *__vm_create(struct vm_shape shape, uint32_t nr_runnable_vcpus,
789808
uint64_t nr_extra_pages);
790809

791810
static inline struct kvm_vm *vm_create_barebones(void)
792811
{
793-
return ____vm_create(VM_MODE_DEFAULT);
812+
return ____vm_create(VM_SHAPE_DEFAULT);
794813
}
795814

796815
static inline struct kvm_vm *vm_create(uint32_t nr_runnable_vcpus)
797816
{
798-
return __vm_create(VM_MODE_DEFAULT, nr_runnable_vcpus, 0);
817+
return __vm_create(VM_SHAPE_DEFAULT, nr_runnable_vcpus, 0);
799818
}
800819

801-
struct kvm_vm *__vm_create_with_vcpus(enum vm_guest_mode mode, uint32_t nr_vcpus,
820+
struct kvm_vm *__vm_create_with_vcpus(struct vm_shape shape, uint32_t nr_vcpus,
802821
uint64_t extra_mem_pages,
803822
void *guest_code, struct kvm_vcpu *vcpus[]);
804823

805824
static inline struct kvm_vm *vm_create_with_vcpus(uint32_t nr_vcpus,
806825
void *guest_code,
807826
struct kvm_vcpu *vcpus[])
808827
{
809-
return __vm_create_with_vcpus(VM_MODE_DEFAULT, nr_vcpus, 0,
828+
return __vm_create_with_vcpus(VM_SHAPE_DEFAULT, nr_vcpus, 0,
810829
guest_code, vcpus);
811830
}
812831

832+
833+
struct kvm_vm *__vm_create_shape_with_one_vcpu(struct vm_shape shape,
834+
struct kvm_vcpu **vcpu,
835+
uint64_t extra_mem_pages,
836+
void *guest_code);
837+
813838
/*
814839
* Create a VM with a single vCPU with reasonable defaults and @extra_mem_pages
815840
* additional pages of guest memory. Returns the VM and vCPU (via out param).
816841
*/
817-
struct kvm_vm *__vm_create_with_one_vcpu(struct kvm_vcpu **vcpu,
818-
uint64_t extra_mem_pages,
819-
void *guest_code);
842+
static inline struct kvm_vm *__vm_create_with_one_vcpu(struct kvm_vcpu **vcpu,
843+
uint64_t extra_mem_pages,
844+
void *guest_code)
845+
{
846+
return __vm_create_shape_with_one_vcpu(VM_SHAPE_DEFAULT, vcpu,
847+
extra_mem_pages, guest_code);
848+
}
820849

821850
static inline struct kvm_vm *vm_create_with_one_vcpu(struct kvm_vcpu **vcpu,
822851
void *guest_code)
823852
{
824853
return __vm_create_with_one_vcpu(vcpu, 0, guest_code);
825854
}
826855

856+
static inline struct kvm_vm *vm_create_shape_with_one_vcpu(struct vm_shape shape,
857+
struct kvm_vcpu **vcpu,
858+
void *guest_code)
859+
{
860+
return __vm_create_shape_with_one_vcpu(shape, vcpu, 0, guest_code);
861+
}
862+
827863
struct kvm_vcpu *vm_recreate_with_one_vcpu(struct kvm_vm *vm);
828864

829865
void kvm_pin_this_task_to_pcpu(uint32_t pcpu);

tools/testing/selftests/kvm/kvm_page_table_test.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ static struct kvm_vm *pre_init_before_test(enum vm_guest_mode mode, void *arg)
254254

255255
/* Create a VM with enough guest pages */
256256
guest_num_pages = test_mem_size / guest_page_size;
257-
vm = __vm_create_with_vcpus(mode, nr_vcpus, guest_num_pages,
257+
vm = __vm_create_with_vcpus(VM_SHAPE(mode), nr_vcpus, guest_num_pages,
258258
guest_code, test_args.vcpus);
259259

260260
/* Align down GPA of the testing memslot */

tools/testing/selftests/kvm/lib/kvm_util.c

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ __weak void vm_vaddr_populate_bitmap(struct kvm_vm *vm)
209209
(1ULL << (vm->va_bits - 1)) >> vm->page_shift);
210210
}
211211

212-
struct kvm_vm *____vm_create(enum vm_guest_mode mode)
212+
struct kvm_vm *____vm_create(struct vm_shape shape)
213213
{
214214
struct kvm_vm *vm;
215215

@@ -221,13 +221,13 @@ struct kvm_vm *____vm_create(enum vm_guest_mode mode)
221221
vm->regions.hva_tree = RB_ROOT;
222222
hash_init(vm->regions.slot_hash);
223223

224-
vm->mode = mode;
225-
vm->type = 0;
224+
vm->mode = shape.mode;
225+
vm->type = shape.type;
226226

227-
vm->pa_bits = vm_guest_mode_params[mode].pa_bits;
228-
vm->va_bits = vm_guest_mode_params[mode].va_bits;
229-
vm->page_size = vm_guest_mode_params[mode].page_size;
230-
vm->page_shift = vm_guest_mode_params[mode].page_shift;
227+
vm->pa_bits = vm_guest_mode_params[vm->mode].pa_bits;
228+
vm->va_bits = vm_guest_mode_params[vm->mode].va_bits;
229+
vm->page_size = vm_guest_mode_params[vm->mode].page_size;
230+
vm->page_shift = vm_guest_mode_params[vm->mode].page_shift;
231231

232232
/* Setup mode specific traits. */
233233
switch (vm->mode) {
@@ -265,7 +265,7 @@ struct kvm_vm *____vm_create(enum vm_guest_mode mode)
265265
/*
266266
* Ignore KVM support for 5-level paging (vm->va_bits == 57),
267267
* it doesn't take effect unless a CR4.LA57 is set, which it
268-
* isn't for this VM_MODE.
268+
* isn't for this mode (48-bit virtual address space).
269269
*/
270270
TEST_ASSERT(vm->va_bits == 48 || vm->va_bits == 57,
271271
"Linear address width (%d bits) not supported",
@@ -285,10 +285,11 @@ struct kvm_vm *____vm_create(enum vm_guest_mode mode)
285285
vm->pgtable_levels = 5;
286286
break;
287287
default:
288-
TEST_FAIL("Unknown guest mode, mode: 0x%x", mode);
288+
TEST_FAIL("Unknown guest mode: 0x%x", vm->mode);
289289
}
290290

291291
#ifdef __aarch64__
292+
TEST_ASSERT(!vm->type, "ARM doesn't support test-provided types");
292293
if (vm->pa_bits != 40)
293294
vm->type = KVM_VM_TYPE_ARM_IPA_SIZE(vm->pa_bits);
294295
#endif
@@ -347,19 +348,19 @@ static uint64_t vm_nr_pages_required(enum vm_guest_mode mode,
347348
return vm_adjust_num_guest_pages(mode, nr_pages);
348349
}
349350

350-
struct kvm_vm *__vm_create(enum vm_guest_mode mode, uint32_t nr_runnable_vcpus,
351+
struct kvm_vm *__vm_create(struct vm_shape shape, uint32_t nr_runnable_vcpus,
351352
uint64_t nr_extra_pages)
352353
{
353-
uint64_t nr_pages = vm_nr_pages_required(mode, nr_runnable_vcpus,
354+
uint64_t nr_pages = vm_nr_pages_required(shape.mode, nr_runnable_vcpus,
354355
nr_extra_pages);
355356
struct userspace_mem_region *slot0;
356357
struct kvm_vm *vm;
357358
int i;
358359

359-
pr_debug("%s: mode='%s' pages='%ld'\n", __func__,
360-
vm_guest_mode_string(mode), nr_pages);
360+
pr_debug("%s: mode='%s' type='%d', pages='%ld'\n", __func__,
361+
vm_guest_mode_string(shape.mode), shape.type, nr_pages);
361362

362-
vm = ____vm_create(mode);
363+
vm = ____vm_create(shape);
363364

364365
vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, 0, 0, nr_pages, 0);
365366
for (i = 0; i < NR_MEM_REGIONS; i++)
@@ -400,7 +401,7 @@ struct kvm_vm *__vm_create(enum vm_guest_mode mode, uint32_t nr_runnable_vcpus,
400401
* extra_mem_pages is only used to calculate the maximum page table size,
401402
* no real memory allocation for non-slot0 memory in this function.
402403
*/
403-
struct kvm_vm *__vm_create_with_vcpus(enum vm_guest_mode mode, uint32_t nr_vcpus,
404+
struct kvm_vm *__vm_create_with_vcpus(struct vm_shape shape, uint32_t nr_vcpus,
404405
uint64_t extra_mem_pages,
405406
void *guest_code, struct kvm_vcpu *vcpus[])
406407
{
@@ -409,23 +410,23 @@ struct kvm_vm *__vm_create_with_vcpus(enum vm_guest_mode mode, uint32_t nr_vcpus
409410

410411
TEST_ASSERT(!nr_vcpus || vcpus, "Must provide vCPU array");
411412

412-
vm = __vm_create(mode, nr_vcpus, extra_mem_pages);
413+
vm = __vm_create(shape, nr_vcpus, extra_mem_pages);
413414

414415
for (i = 0; i < nr_vcpus; ++i)
415416
vcpus[i] = vm_vcpu_add(vm, i, guest_code);
416417

417418
return vm;
418419
}
419420

420-
struct kvm_vm *__vm_create_with_one_vcpu(struct kvm_vcpu **vcpu,
421-
uint64_t extra_mem_pages,
422-
void *guest_code)
421+
struct kvm_vm *__vm_create_shape_with_one_vcpu(struct vm_shape shape,
422+
struct kvm_vcpu **vcpu,
423+
uint64_t extra_mem_pages,
424+
void *guest_code)
423425
{
424426
struct kvm_vcpu *vcpus[1];
425427
struct kvm_vm *vm;
426428

427-
vm = __vm_create_with_vcpus(VM_MODE_DEFAULT, 1, extra_mem_pages,
428-
guest_code, vcpus);
429+
vm = __vm_create_with_vcpus(shape, 1, extra_mem_pages, guest_code, vcpus);
429430

430431
*vcpu = vcpus[0];
431432
return vm;

tools/testing/selftests/kvm/lib/memstress.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ struct kvm_vm *memstress_create_vm(enum vm_guest_mode mode, int nr_vcpus,
168168
* The memory is also added to memslot 0, but that's a benign side
169169
* effect as KVM allows aliasing HVAs in meslots.
170170
*/
171-
vm = __vm_create_with_vcpus(mode, nr_vcpus, slot0_pages + guest_num_pages,
171+
vm = __vm_create_with_vcpus(VM_SHAPE(mode), nr_vcpus,
172+
slot0_pages + guest_num_pages,
172173
memstress_guest_code, vcpus);
173174

174175
args->vm = vm;

tools/testing/selftests/kvm/x86_64/ucna_injection_test.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ int main(int argc, char *argv[])
271271

272272
kvm_check_cap(KVM_CAP_MCE);
273273

274-
vm = __vm_create(VM_MODE_DEFAULT, 3, 0);
274+
vm = __vm_create(VM_SHAPE_DEFAULT, 3, 0);
275275

276276
kvm_ioctl(vm->kvm_fd, KVM_X86_GET_MCE_CAP_SUPPORTED,
277277
&supported_mcg_caps);

0 commit comments

Comments
 (0)