1f08c3bdfSopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (C) 2021 SUSE LLC <mdoucha@suse.cz> 4f08c3bdfSopenharmony_ci * 5f08c3bdfSopenharmony_ci * KVM host library for setting up and running virtual machine tests. Tests 6f08c3bdfSopenharmony_ci * can either use the default setup/run/host functions or use the advanced 7f08c3bdfSopenharmony_ci * API to create customized VMs. 8f08c3bdfSopenharmony_ci */ 9f08c3bdfSopenharmony_ci 10f08c3bdfSopenharmony_ci/* 11f08c3bdfSopenharmony_ci * Most basic usage: 12f08c3bdfSopenharmony_ci * 13f08c3bdfSopenharmony_ci * #include "kvm_test.h" 14f08c3bdfSopenharmony_ci * 15f08c3bdfSopenharmony_ci * #ifdef COMPILE_PAYLOAD 16f08c3bdfSopenharmony_ci * 17f08c3bdfSopenharmony_ci * void main(void) 18f08c3bdfSopenharmony_ci * { 19f08c3bdfSopenharmony_ci * [VM guest code goes here] 20f08c3bdfSopenharmony_ci * } 21f08c3bdfSopenharmony_ci * 22f08c3bdfSopenharmony_ci * #else 23f08c3bdfSopenharmony_ci * 24f08c3bdfSopenharmony_ci * [optional VM host setup/run/cleanup code goes here] 25f08c3bdfSopenharmony_ci * 26f08c3bdfSopenharmony_ci * static struct tst_test test = { 27f08c3bdfSopenharmony_ci * .test_all = tst_kvm_run, 28f08c3bdfSopenharmony_ci * .setup = tst_kvm_setup, 29f08c3bdfSopenharmony_ci * .cleanup = tst_kvm_cleanup, 30f08c3bdfSopenharmony_ci * }; 31f08c3bdfSopenharmony_ci * 32f08c3bdfSopenharmony_ci * #endif 33f08c3bdfSopenharmony_ci */ 34f08c3bdfSopenharmony_ci 35f08c3bdfSopenharmony_ci#ifndef KVM_HOST_H_ 36f08c3bdfSopenharmony_ci#define KVM_HOST_H_ 37f08c3bdfSopenharmony_ci 38f08c3bdfSopenharmony_ci#include <inttypes.h> 39f08c3bdfSopenharmony_ci#include <linux/kvm.h> 40f08c3bdfSopenharmony_ci#include "kvm_common.h" 41f08c3bdfSopenharmony_ci 42f08c3bdfSopenharmony_ci#define VM_KERNEL_BASEADDR 0x1000 43f08c3bdfSopenharmony_ci#define VM_RESET_BASEADDR 0xfffffff0 44f08c3bdfSopenharmony_ci#define VM_RESET_CODE_SIZE 8 45f08c3bdfSopenharmony_ci 46f08c3bdfSopenharmony_ci#define MIN_FREE_RAM (10 * 1024 * 1024) 47f08c3bdfSopenharmony_ci#define DEFAULT_RAM_SIZE (16 * 1024 * 1024) 48f08c3bdfSopenharmony_ci#define MAX_KVM_MEMSLOTS 8 49f08c3bdfSopenharmony_ci 50f08c3bdfSopenharmony_cistruct tst_kvm_instance { 51f08c3bdfSopenharmony_ci int vm_fd, vcpu_fd; 52f08c3bdfSopenharmony_ci struct kvm_run *vcpu_info; 53f08c3bdfSopenharmony_ci size_t vcpu_info_size; 54f08c3bdfSopenharmony_ci struct kvm_userspace_memory_region ram[MAX_KVM_MEMSLOTS]; 55f08c3bdfSopenharmony_ci struct tst_kvm_result *result; 56f08c3bdfSopenharmony_ci}; 57f08c3bdfSopenharmony_ci 58f08c3bdfSopenharmony_ci/* Test binary to be installed into the VM at VM_KERNEL_BASEADDR */ 59f08c3bdfSopenharmony_ciextern const char kvm_payload_start[], kvm_payload_end[]; 60f08c3bdfSopenharmony_ci 61f08c3bdfSopenharmony_ci/* CPU reset code to be installed into the VM at VM_RESET_BASEADDR */ 62f08c3bdfSopenharmony_ciextern const unsigned char tst_kvm_reset_code[VM_RESET_CODE_SIZE]; 63f08c3bdfSopenharmony_ci 64f08c3bdfSopenharmony_ci/* Default KVM test functions. */ 65f08c3bdfSopenharmony_civoid tst_kvm_setup(void); 66f08c3bdfSopenharmony_civoid tst_kvm_run(void); 67f08c3bdfSopenharmony_civoid tst_kvm_cleanup(void); 68f08c3bdfSopenharmony_ci 69f08c3bdfSopenharmony_ci/* 70f08c3bdfSopenharmony_ci * Validate KVM guest test result (usually passed via result->result) and 71f08c3bdfSopenharmony_ci * fail with TBROK if the value cannot be safely passed to tst_res() or 72f08c3bdfSopenharmony_ci * tst_brk(). 73f08c3bdfSopenharmony_ci */ 74f08c3bdfSopenharmony_civoid tst_kvm_validate_result(int value); 75f08c3bdfSopenharmony_ci 76f08c3bdfSopenharmony_ci/* 77f08c3bdfSopenharmony_ci * Allocate memory slot for the VM. The returned pointer is page-aligned 78f08c3bdfSopenharmony_ci * so the actual requested base address is at ret[baseaddr % pagesize]. 79f08c3bdfSopenharmony_ci * 80f08c3bdfSopenharmony_ci * The first argument is a VM file descriptor created by ioctl(KVM_CREATE_VM) 81f08c3bdfSopenharmony_ci * 82f08c3bdfSopenharmony_ci * The return value points to a guarded buffer and the user should not attempt 83f08c3bdfSopenharmony_ci * to free() it. Any extra space added at the beginning or end for page 84f08c3bdfSopenharmony_ci * alignment will be writable. 85f08c3bdfSopenharmony_ci */ 86f08c3bdfSopenharmony_civoid *tst_kvm_alloc_memory(struct tst_kvm_instance *inst, unsigned int slot, 87f08c3bdfSopenharmony_ci uint64_t baseaddr, size_t size, unsigned int flags); 88f08c3bdfSopenharmony_ci 89f08c3bdfSopenharmony_ci/* 90f08c3bdfSopenharmony_ci * Translate VM virtual memory address to the corresponding physical address. 91f08c3bdfSopenharmony_ci * Returns 0 if the virtual address is unmapped or otherwise invalid. 92f08c3bdfSopenharmony_ci */ 93f08c3bdfSopenharmony_ciuint64_t tst_kvm_get_phys_address(const struct tst_kvm_instance *inst, 94f08c3bdfSopenharmony_ci uint64_t addr); 95f08c3bdfSopenharmony_ci 96f08c3bdfSopenharmony_ci/* 97f08c3bdfSopenharmony_ci * Find the struct tst_kvm_instance memory slot ID for the give virtual 98f08c3bdfSopenharmony_ci * or physical VM memory address. Returns -1 if the address is not backed 99f08c3bdfSopenharmony_ci * by any memory buffer. 100f08c3bdfSopenharmony_ci */ 101f08c3bdfSopenharmony_ciint tst_kvm_find_phys_memslot(const struct tst_kvm_instance *inst, 102f08c3bdfSopenharmony_ci uint64_t paddr); 103f08c3bdfSopenharmony_ciint tst_kvm_find_memslot(const struct tst_kvm_instance *inst, uint64_t addr); 104f08c3bdfSopenharmony_ci 105f08c3bdfSopenharmony_ci/* 106f08c3bdfSopenharmony_ci * Convert VM virtual memory address to a directly usable pointer. 107f08c3bdfSopenharmony_ci */ 108f08c3bdfSopenharmony_civoid *tst_kvm_get_memptr(const struct tst_kvm_instance *inst, uint64_t addr); 109f08c3bdfSopenharmony_ci 110f08c3bdfSopenharmony_ci/* 111f08c3bdfSopenharmony_ci * Find CPUIDs supported by KVM. x86_64 tests must set non-default CPUID, 112f08c3bdfSopenharmony_ci * otherwise bootstrap will fail to initialize 64bit mode. 113f08c3bdfSopenharmony_ci * Returns NULL if ioctl(KVM_GET_SUPPORTED_CPUID) is not supported. 114f08c3bdfSopenharmony_ci * 115f08c3bdfSopenharmony_ci * The argument is a file descriptor created by open("/dev/kvm") 116f08c3bdfSopenharmony_ci */ 117f08c3bdfSopenharmony_cistruct kvm_cpuid2 *tst_kvm_get_cpuid(int sysfd); 118f08c3bdfSopenharmony_ci 119f08c3bdfSopenharmony_ci/* 120f08c3bdfSopenharmony_ci * Initialize the given KVM instance structure. Creates new KVM virtual machine 121f08c3bdfSopenharmony_ci * with 1 virtual CPU, allocates VM RAM (max. 4GB minus one page) and 122f08c3bdfSopenharmony_ci * shared result structure. KVM memory slots 0 and 1 will be set by this 123f08c3bdfSopenharmony_ci * function. 124f08c3bdfSopenharmony_ci */ 125f08c3bdfSopenharmony_civoid tst_kvm_create_instance(struct tst_kvm_instance *inst, size_t ram_size); 126f08c3bdfSopenharmony_ci 127f08c3bdfSopenharmony_ci/* 128f08c3bdfSopenharmony_ci * Execute the given KVM instance and print results. If ioctl(KVM_RUN) is 129f08c3bdfSopenharmony_ci * expected to fail, pass the expected error code in exp_errno, otherwise 130f08c3bdfSopenharmony_ci * set it to zero. Returns last value returned by ioctl(KVM_RUN). 131f08c3bdfSopenharmony_ci */ 132f08c3bdfSopenharmony_ciint tst_kvm_run_instance(struct tst_kvm_instance *inst, int exp_errno); 133f08c3bdfSopenharmony_ci 134f08c3bdfSopenharmony_ci/* 135f08c3bdfSopenharmony_ci * Close the given KVM instance. 136f08c3bdfSopenharmony_ci */ 137f08c3bdfSopenharmony_civoid tst_kvm_destroy_instance(struct tst_kvm_instance *inst); 138f08c3bdfSopenharmony_ci 139f08c3bdfSopenharmony_ci/* 140f08c3bdfSopenharmony_ci * Wait for given VM to call tst_signal_host() or tst_wait_host(). Timeout 141f08c3bdfSopenharmony_ci * value is in milliseconds. Zero means no wait, negative value means wait 142f08c3bdfSopenharmony_ci * forever. Returns 0 if signal was received, KVM_TEXIT if the VM exited 143f08c3bdfSopenharmony_ci * without sending a signal, or -1 if timeout was reached. 144f08c3bdfSopenharmony_ci */ 145f08c3bdfSopenharmony_ciint tst_kvm_wait_guest(struct tst_kvm_instance *inst, int timeout_ms); 146f08c3bdfSopenharmony_ci 147f08c3bdfSopenharmony_ci/* 148f08c3bdfSopenharmony_ci * Clear VM signal sent by tst_signal_host(). If the VM is waiting 149f08c3bdfSopenharmony_ci * in tst_wait_host(), this function will signal the VM to resume execution. 150f08c3bdfSopenharmony_ci */ 151f08c3bdfSopenharmony_civoid tst_kvm_clear_guest_signal(struct tst_kvm_instance *inst); 152f08c3bdfSopenharmony_ci 153f08c3bdfSopenharmony_ci#endif /* KVM_HOST_H_ */ 154