1ae1fae34SPekka Enberg #ifndef KVM__KVM_H
2ae1fae34SPekka Enberg #define KVM__KVM_H
3ae1fae34SPekka Enberg
48d987725SAlexandru Elisei #include "kvm/mutex.h"
5af7b0868SMatt Evans #include "kvm/kvm-arch.h"
647621338SSasha Levin #include "kvm/kvm-config.h"
749a8afd1SSasha Levin #include "kvm/util-init.h"
849a8afd1SSasha Levin #include "kvm/kvm.h"
9da8883c1SPekka Enberg
10ae1fae34SPekka Enberg #include <stdbool.h>
113fdf659dSSasha Levin #include <linux/types.h>
12db927775SAlexandru Elisei #include <linux/compiler.h>
13ce79f1caSPekka Enberg #include <time.h>
1482d2f21eSSasha Levin #include <signal.h>
15a4d8c55eSSasha Levin #include <sys/prctl.h>
164095fac8SAndre Przywara #include <limits.h>
17ae1fae34SPekka Enberg
18b1c2516bSSasha Levin #define SIGKVMEXIT (SIGRTMIN + 0)
194298ddadSSasha Levin #define SIGKVMPAUSE (SIGRTMIN + 1)
20e300a5eeSMichael Ellerman #define SIGKVMTASK (SIGRTMIN + 2)
2149e5227dSSasha Levin
22354b198bSAsias He #define KVM_PID_FILE_PATH "/.lkvm/"
2382d65b5eSSasha Levin #define HOME_DIR getenv("HOME")
24ee8b1456SWanlong Gao #define KVM_BINARY_NAME "lkvm"
2582d65b5eSSasha Levin
264095fac8SAndre Przywara #ifndef PAGE_SIZE
27af7b0868SMatt Evans #define PAGE_SIZE (sysconf(_SC_PAGE_SIZE))
284095fac8SAndre Przywara #endif
29ae1fae34SPekka Enberg
3096f0c86cSAndre Przywara /*
3196f0c86cSAndre Przywara * We are reusing the existing DEVICE_BUS_MMIO and DEVICE_BUS_IOPORT constants
3296f0c86cSAndre Przywara * from kvm/devices.h to differentiate between registering an I/O port and an
3396f0c86cSAndre Przywara * MMIO region.
3496f0c86cSAndre Przywara * To avoid collisions with future additions of more bus types, we reserve
3596f0c86cSAndre Przywara * a generous 4 bits for the bus mask here.
3696f0c86cSAndre Przywara */
3796f0c86cSAndre Przywara #define IOTRAP_BUS_MASK 0xf
3896f0c86cSAndre Przywara #define IOTRAP_COALESCE (1U << 4)
3996f0c86cSAndre Przywara
40af7b0868SMatt Evans #define DEFINE_KVM_EXT(ext) \
41af7b0868SMatt Evans .name = #ext, \
42af7b0868SMatt Evans .code = ext
430c7c14a7SCyrill Gorcunov
4496f0c86cSAndre Przywara struct kvm_cpu;
4596f0c86cSAndre Przywara typedef void (*mmio_handler_fn)(struct kvm_cpu *vcpu, u64 addr, u8 *data,
4696f0c86cSAndre Przywara u32 len, u8 is_write, void *ptr);
47a81be31eSAndre Przywara
487021c50bSAsias He enum {
497021c50bSAsias He KVM_VMSTATE_RUNNING,
507021c50bSAsias He KVM_VMSTATE_PAUSED,
517021c50bSAsias He };
527021c50bSAsias He
538f46c736SJean-Philippe Brucker enum kvm_mem_type {
548f46c736SJean-Philippe Brucker KVM_MEM_TYPE_RAM = 1 << 0,
558f46c736SJean-Philippe Brucker KVM_MEM_TYPE_DEVICE = 1 << 1,
56fa1076abSJean-Philippe Brucker KVM_MEM_TYPE_RESERVED = 1 << 2,
570480e04aSAndre Przywara KVM_MEM_TYPE_READONLY = 1 << 3,
588f46c736SJean-Philippe Brucker
598f46c736SJean-Philippe Brucker KVM_MEM_TYPE_ALL = KVM_MEM_TYPE_RAM
608f46c736SJean-Philippe Brucker | KVM_MEM_TYPE_DEVICE
61fa1076abSJean-Philippe Brucker | KVM_MEM_TYPE_RESERVED
620480e04aSAndre Przywara | KVM_MEM_TYPE_READONLY
638f46c736SJean-Philippe Brucker };
648f46c736SJean-Philippe Brucker
65af7b0868SMatt Evans struct kvm_ext {
665358b0e6SSasha Levin const char *name;
67af7b0868SMatt Evans int code;
68ae1fae34SPekka Enberg };
69ae1fae34SPekka Enberg
70d82350d3SWill Deacon struct kvm_mem_bank {
71d82350d3SWill Deacon struct list_head list;
72d82350d3SWill Deacon u64 guest_phys_addr;
73d82350d3SWill Deacon void *host_addr;
74d82350d3SWill Deacon u64 size;
758f46c736SJean-Philippe Brucker enum kvm_mem_type type;
768d987725SAlexandru Elisei u32 slot;
77d82350d3SWill Deacon };
78d82350d3SWill Deacon
7942ac24f9SSasha Levin struct kvm {
8042ac24f9SSasha Levin struct kvm_arch arch;
8147621338SSasha Levin struct kvm_config cfg;
8242ac24f9SSasha Levin int sys_fd; /* For system ioctls(), i.e. /dev/kvm */
8342ac24f9SSasha Levin int vm_fd; /* For VM ioctls() */
8442ac24f9SSasha Levin timer_t timerid; /* Posix timer for interrupts */
8542ac24f9SSasha Levin
8642ac24f9SSasha Levin int nrcpus; /* Number of cpus to run */
87df4239fbSSasha Levin struct kvm_cpu **cpus;
8842ac24f9SSasha Levin
8942ac24f9SSasha Levin u32 mem_slots; /* for KVM_SET_USER_MEMORY_REGION */
909d655190SAlexandru Elisei u64 ram_size; /* Guest memory size, in bytes */
9142ac24f9SSasha Levin void *ram_start;
9242ac24f9SSasha Levin u64 ram_pagesize;
938d987725SAlexandru Elisei struct mutex mem_banks_lock;
94d82350d3SWill Deacon struct list_head mem_banks;
9542ac24f9SSasha Levin
9642ac24f9SSasha Levin bool nmi_disabled;
97714ab9e6SAndre Przywara bool msix_needs_devid;
9842ac24f9SSasha Levin
9942ac24f9SSasha Levin const char *vmlinux;
10042ac24f9SSasha Levin struct disk_image **disks;
10142ac24f9SSasha Levin int nr_disks;
10242ac24f9SSasha Levin
10342ac24f9SSasha Levin int vm_state;
10420b65266SJulien Thierry
10520b65266SJulien Thierry #ifdef KVM_BRLOCK_DEBUG
10620b65266SJulien Thierry pthread_rwlock_t brlock_sem;
10720b65266SJulien Thierry #endif
10842ac24f9SSasha Levin };
10942ac24f9SSasha Levin
1109667701cSPekka Enberg void kvm__set_dir(const char *fmt, ...);
1119667701cSPekka Enberg const char *kvm__get_dir(void);
1129667701cSPekka Enberg
11347621338SSasha Levin int kvm__init(struct kvm *kvm);
11447621338SSasha Levin struct kvm *kvm__new(void);
1158259b8ccSSasha Levin int kvm__recommended_cpus(struct kvm *kvm);
11643835ac9SSasha Levin int kvm__max_cpus(struct kvm *kvm);
1174250819dSMarc Zyngier int kvm__get_vm_type(struct kvm *kvm);
11843835ac9SSasha Levin void kvm__init_ram(struct kvm *kvm);
119495fbd4eSSasha Levin int kvm__exit(struct kvm *kvm);
1205ad8db5eSPekka Enberg bool kvm__load_firmware(struct kvm *kvm, const char *firmware_filename);
1212065a6f7SCyrill Gorcunov bool kvm__load_kernel(struct kvm *kvm, const char *kernel_filename,
122ff7ba6faSWill Deacon const char *initrd_filename, const char *kernel_cmdline);
123b4532ca9SSasha Levin int kvm_timer__init(struct kvm *kvm);
124b4532ca9SSasha Levin int kvm_timer__exit(struct kvm *kvm);
12543835ac9SSasha Levin void kvm__irq_line(struct kvm *kvm, int irq, int level);
126bfaed61cSSasha Levin void kvm__irq_trigger(struct kvm *kvm, int irq);
1274123ca55SMarc Zyngier bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int direction, int size, u32 count);
1289b735910SMarc Zyngier bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data, u32 len, u8 is_write);
1298d987725SAlexandru Elisei int kvm__destroy_mem(struct kvm *kvm, u64 guest_phys, u64 size, void *userspace_addr);
1308f46c736SJean-Philippe Brucker int kvm__register_mem(struct kvm *kvm, u64 guest_phys, u64 size, void *userspace_addr,
1318f46c736SJean-Philippe Brucker enum kvm_mem_type type);
kvm__register_ram(struct kvm * kvm,u64 guest_phys,u64 size,void * userspace_addr)1328f46c736SJean-Philippe Brucker static inline int kvm__register_ram(struct kvm *kvm, u64 guest_phys, u64 size,
1338f46c736SJean-Philippe Brucker void *userspace_addr)
1348f46c736SJean-Philippe Brucker {
1358f46c736SJean-Philippe Brucker return kvm__register_mem(kvm, guest_phys, size, userspace_addr,
1368f46c736SJean-Philippe Brucker KVM_MEM_TYPE_RAM);
1378f46c736SJean-Philippe Brucker }
1388f46c736SJean-Philippe Brucker
kvm__register_dev_mem(struct kvm * kvm,u64 guest_phys,u64 size,void * userspace_addr)1398f46c736SJean-Philippe Brucker static inline int kvm__register_dev_mem(struct kvm *kvm, u64 guest_phys,
1408f46c736SJean-Philippe Brucker u64 size, void *userspace_addr)
1418f46c736SJean-Philippe Brucker {
1428f46c736SJean-Philippe Brucker return kvm__register_mem(kvm, guest_phys, size, userspace_addr,
1438f46c736SJean-Philippe Brucker KVM_MEM_TYPE_DEVICE);
1448f46c736SJean-Philippe Brucker }
1458f46c736SJean-Philippe Brucker
kvm__reserve_mem(struct kvm * kvm,u64 guest_phys,u64 size)146fa1076abSJean-Philippe Brucker static inline int kvm__reserve_mem(struct kvm *kvm, u64 guest_phys, u64 size)
147fa1076abSJean-Philippe Brucker {
148fa1076abSJean-Philippe Brucker return kvm__register_mem(kvm, guest_phys, size, NULL,
149fa1076abSJean-Philippe Brucker KVM_MEM_TYPE_RESERVED);
150fa1076abSJean-Philippe Brucker }
151fa1076abSJean-Philippe Brucker
15296f0c86cSAndre Przywara int __must_check kvm__register_iotrap(struct kvm *kvm, u64 phys_addr, u64 len,
15396f0c86cSAndre Przywara mmio_handler_fn mmio_fn, void *ptr,
15496f0c86cSAndre Przywara unsigned int flags);
15596f0c86cSAndre Przywara
15696f0c86cSAndre Przywara static inline
kvm__register_mmio(struct kvm * kvm,u64 phys_addr,u64 phys_addr_len,bool coalesce,mmio_handler_fn mmio_fn,void * ptr)15796f0c86cSAndre Przywara int __must_check kvm__register_mmio(struct kvm *kvm, u64 phys_addr,
15896f0c86cSAndre Przywara u64 phys_addr_len, bool coalesce,
15996f0c86cSAndre Przywara mmio_handler_fn mmio_fn, void *ptr)
16096f0c86cSAndre Przywara {
16196f0c86cSAndre Przywara return kvm__register_iotrap(kvm, phys_addr, phys_addr_len, mmio_fn, ptr,
16296f0c86cSAndre Przywara DEVICE_BUS_MMIO | (coalesce ? IOTRAP_COALESCE : 0));
16396f0c86cSAndre Przywara }
16496f0c86cSAndre Przywara static inline
kvm__register_pio(struct kvm * kvm,u16 port,u16 len,mmio_handler_fn mmio_fn,void * ptr)16596f0c86cSAndre Przywara int __must_check kvm__register_pio(struct kvm *kvm, u16 port, u16 len,
16696f0c86cSAndre Przywara mmio_handler_fn mmio_fn, void *ptr)
16796f0c86cSAndre Przywara {
16896f0c86cSAndre Przywara return kvm__register_iotrap(kvm, port, len, mmio_fn, ptr,
16996f0c86cSAndre Przywara DEVICE_BUS_IOPORT);
17096f0c86cSAndre Przywara }
17196f0c86cSAndre Przywara
17296f0c86cSAndre Przywara bool kvm__deregister_iotrap(struct kvm *kvm, u64 phys_addr, unsigned int flags);
kvm__deregister_mmio(struct kvm * kvm,u64 phys_addr)17396f0c86cSAndre Przywara static inline bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr)
17496f0c86cSAndre Przywara {
17596f0c86cSAndre Przywara return kvm__deregister_iotrap(kvm, phys_addr, DEVICE_BUS_MMIO);
17696f0c86cSAndre Przywara }
kvm__deregister_pio(struct kvm * kvm,u16 port)17796f0c86cSAndre Przywara static inline bool kvm__deregister_pio(struct kvm *kvm, u16 port)
17896f0c86cSAndre Przywara {
17996f0c86cSAndre Przywara return kvm__deregister_iotrap(kvm, port, DEVICE_BUS_IOPORT);
18096f0c86cSAndre Przywara }
18196f0c86cSAndre Przywara
1822aa76b26SWill Deacon void kvm__reboot(struct kvm *kvm);
1834346fd8fSSasha Levin void kvm__pause(struct kvm *kvm);
1844346fd8fSSasha Levin void kvm__continue(struct kvm *kvm);
1854298ddadSSasha Levin void kvm__notify_paused(void);
1864b1addaeSSasha Levin int kvm__get_sock_by_instance(const char *name);
187886af5f2SLiming Wang int kvm__enumerate_instances(int (*callback)(const char *name, int pid));
1884b1addaeSSasha Levin void kvm__remove_socket(const char *name);
189ae1fae34SPekka Enberg
190abe3f28aSAlexandru Elisei void kvm__arch_validate_cfg(struct kvm *kvm);
1918e704a7aSMatt Evans void kvm__arch_set_cmdline(char *cmdline, bool video);
1925e9c654eSJulien Grall void kvm__arch_init(struct kvm *kvm);
1933f7e48f6SAlexandru Elisei u64 kvm__arch_default_ram_address(void);
194e56e2de7SLai Jiangshan void kvm__arch_delete_ram(struct kvm *kvm);
195f7f9d02bSCyrill Gorcunov int kvm__arch_setup_firmware(struct kvm *kvm);
1961add9f73SSasha Levin int kvm__arch_free_firmware(struct kvm *kvm);
197af7b0868SMatt Evans bool kvm__arch_cpu_supports_vm(void);
19812c406a8SJonathan Austin void kvm__arch_read_term(struct kvm *kvm);
199af7b0868SMatt Evans
200*8b91a182SAlexandru Elisei #ifdef ARCH_HAS_CFG_RAM_ADDRESS
kvm__arch_has_cfg_ram_address(void)201*8b91a182SAlexandru Elisei static inline bool kvm__arch_has_cfg_ram_address(void)
202*8b91a182SAlexandru Elisei {
203*8b91a182SAlexandru Elisei return true;
204*8b91a182SAlexandru Elisei }
205*8b91a182SAlexandru Elisei #else
kvm__arch_has_cfg_ram_address(void)206*8b91a182SAlexandru Elisei static inline bool kvm__arch_has_cfg_ram_address(void)
207*8b91a182SAlexandru Elisei {
208*8b91a182SAlexandru Elisei return false;
209*8b91a182SAlexandru Elisei }
210*8b91a182SAlexandru Elisei #endif
211*8b91a182SAlexandru Elisei
212f412251fSWill Deacon void *guest_flat_to_host(struct kvm *kvm, u64 offset);
2130cb41990SWill Deacon u64 host_to_guest_flat(struct kvm *kvm, void *ptr);
214f412251fSWill Deacon
215004f7684SAndre Przywara bool kvm__arch_load_kernel_image(struct kvm *kvm, int fd_kernel, int fd_initrd,
216004f7684SAndre Przywara const char *kernel_cmdline);
217af7b0868SMatt Evans
2180480e04aSAndre Przywara #define add_read_only(type, str) \
2190480e04aSAndre Przywara (((type) & KVM_MEM_TYPE_READONLY) ? str " (read-only)" : str)
kvm_mem_type_to_string(enum kvm_mem_type type)2208f46c736SJean-Philippe Brucker static inline const char *kvm_mem_type_to_string(enum kvm_mem_type type)
2218f46c736SJean-Philippe Brucker {
2220480e04aSAndre Przywara switch (type & ~KVM_MEM_TYPE_READONLY) {
2238f46c736SJean-Philippe Brucker case KVM_MEM_TYPE_ALL:
2248f46c736SJean-Philippe Brucker return "(all)";
2258f46c736SJean-Philippe Brucker case KVM_MEM_TYPE_RAM:
2260480e04aSAndre Przywara return add_read_only(type, "RAM");
2278f46c736SJean-Philippe Brucker case KVM_MEM_TYPE_DEVICE:
2280480e04aSAndre Przywara return add_read_only(type, "device");
229fa1076abSJean-Philippe Brucker case KVM_MEM_TYPE_RESERVED:
2300480e04aSAndre Przywara return add_read_only(type, "reserved");
2318f46c736SJean-Philippe Brucker }
2328f46c736SJean-Philippe Brucker
2338f46c736SJean-Philippe Brucker return "???";
2348f46c736SJean-Philippe Brucker }
2358f46c736SJean-Philippe Brucker
2368f46c736SJean-Philippe Brucker int kvm__for_each_mem_bank(struct kvm *kvm, enum kvm_mem_type type,
2378f46c736SJean-Philippe Brucker int (*fun)(struct kvm *kvm, struct kvm_mem_bank *bank, void *data),
2388f46c736SJean-Philippe Brucker void *data);
2398f46c736SJean-Philippe Brucker
240ae1fae34SPekka Enberg /*
241ae1fae34SPekka Enberg * Debugging
242ae1fae34SPekka Enberg */
243b2cf1e9fSAsias He void kvm__dump_mem(struct kvm *kvm, unsigned long addr, unsigned long size, int debug_fd);
244ae1fae34SPekka Enberg
245ae1fae34SPekka Enberg extern const char *kvm_exit_reasons[];
246ae1fae34SPekka Enberg
host_ptr_in_ram(struct kvm * kvm,void * p)24743835ac9SSasha Levin static inline bool host_ptr_in_ram(struct kvm *kvm, void *p)
2489292f776SCyrill Gorcunov {
24943835ac9SSasha Levin return kvm->ram_start <= p && p < (kvm->ram_start + kvm->ram_size);
2509292f776SCyrill Gorcunov }
2519292f776SCyrill Gorcunov
2521d6fb3f2SSasha Levin bool kvm__supports_extension(struct kvm *kvm, unsigned int extension);
253663165a2SAndre Przywara bool kvm__supports_vm_extension(struct kvm *kvm, unsigned int extension);
2546930e42fSSasha Levin
kvm__set_thread_name(const char * name)255a4d8c55eSSasha Levin static inline void kvm__set_thread_name(const char *name)
256a4d8c55eSSasha Levin {
257a4d8c55eSSasha Levin prctl(PR_SET_NAME, name);
258a4d8c55eSSasha Levin }
259a4d8c55eSSasha Levin
260ae1fae34SPekka Enberg #endif /* KVM__KVM_H */
261