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