X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/38a01e55d268aeba68c84eea425252e7f810feaf..a678508e46ac806d81bd401a483aef1b98734ae4:/kvm-all.c diff --git a/kvm-all.c b/kvm-all.c index b240bf87a9..05a79c20e0 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -25,6 +25,7 @@ #include "qemu/option.h" #include "qemu/config-file.h" #include "sysemu/sysemu.h" +#include "sysemu/accel.h" #include "hw/hw.h" #include "hw/pci/msi.h" #include "hw/s390x/adapter.h" @@ -44,10 +45,6 @@ #include #endif -#ifdef CONFIG_VALGRIND_H -#include -#endif - /* KVM uses PAGE_SIZE in its definition of COALESCED_MMIO_MAX */ #define PAGE_SIZE TARGET_PAGE_SIZE @@ -76,6 +73,8 @@ typedef struct kvm_dirty_log KVMDirtyLog; struct KVMState { + AccelState parent_obj; + KVMSlot *slots; int nr_slots; int fd; @@ -110,12 +109,18 @@ struct KVMState #endif }; +#define TYPE_KVM_ACCEL ACCEL_CLASS_NAME("kvm") + +#define KVM_STATE(obj) \ + OBJECT_CHECK(KVMState, (obj), TYPE_KVM_ACCEL) + KVMState *kvm_state; bool kvm_kernel_irqchip; bool kvm_async_interrupts_allowed; bool kvm_halt_in_kernel_allowed; bool kvm_eventfds_allowed; bool kvm_irqfds_allowed; +bool kvm_resamplefds_allowed; bool kvm_msi_via_irqfd_allowed; bool kvm_gsi_routing_allowed; bool kvm_gsi_direct_mapping; @@ -128,7 +133,7 @@ static const KVMCapabilityInfo kvm_required_capabilites[] = { KVM_CAP_LAST_INFO }; -static KVMSlot *kvm_alloc_slot(KVMState *s) +static KVMSlot *kvm_get_free_slot(KVMState *s) { int i; @@ -138,6 +143,22 @@ static KVMSlot *kvm_alloc_slot(KVMState *s) } } + return NULL; +} + +bool kvm_has_free_slot(MachineState *ms) +{ + return kvm_get_free_slot(KVM_STATE(ms->accelerator)); +} + +static KVMSlot *kvm_alloc_slot(KVMState *s) +{ + KVMSlot *slot = kvm_get_free_slot(s); + + if (slot) { + return slot; + } + fprintf(stderr, "%s: no free slot available\n", __func__); abort(); } @@ -396,7 +417,7 @@ static int kvm_physical_sync_dirty_bitmap(MemoryRegionSection *section) { KVMState *s = kvm_state; unsigned long size, allocated_size = 0; - KVMDirtyLog d; + KVMDirtyLog d = {}; KVMSlot *mem; int ret = 0; hwaddr start_addr = section->offset_within_address_space; @@ -493,6 +514,19 @@ int kvm_check_extension(KVMState *s, unsigned int extension) return ret; } +int kvm_vm_check_extension(KVMState *s, unsigned int extension) +{ + int ret; + + ret = kvm_vm_ioctl(s, KVM_CHECK_EXTENSION, extension); + if (ret < 0) { + /* VM wide version not implemented, use global one instead */ + ret = kvm_check_extension(s, extension); + } + + return ret; +} + static int kvm_set_ioeventfd_mmio(int fd, hwaddr addr, uint32_t val, bool assign, uint32_t size, bool datamatch) { @@ -617,8 +651,10 @@ static void kvm_set_phys_mem(MemoryRegionSection *section, bool add) unsigned delta; /* kvm works in page size chunks, but the function may be called - with sub-page size and unaligned start address. */ - delta = TARGET_PAGE_ALIGN(size) - size; + with sub-page size and unaligned start address. Pad the start + address to next and truncate size to previous page boundary. */ + delta = (TARGET_PAGE_SIZE - (start_addr & ~TARGET_PAGE_MASK)); + delta &= ~TARGET_PAGE_MASK; if (delta > size) { return; } @@ -1189,6 +1225,10 @@ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg) kroute.u.msi.address_lo = (uint32_t)msg.address; kroute.u.msi.address_hi = msg.address >> 32; kroute.u.msi.data = le32_to_cpu(msg.data); + if (kvm_arch_fixup_msi_route(&kroute, msg.address, msg.data)) { + kvm_irqchip_release_virq(s, virq); + return -EINVAL; + } kvm_add_routing_entry(s, &kroute); kvm_irqchip_commit_routes(s); @@ -1214,6 +1254,9 @@ int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg) kroute.u.msi.address_lo = (uint32_t)msg.address; kroute.u.msi.address_hi = msg.address >> 32; kroute.u.msi.data = le32_to_cpu(msg.data); + if (kvm_arch_fixup_msi_route(&kroute, msg.address, msg.data)) { + return -EINVAL; + } return kvm_update_routing_entry(s, &kroute); } @@ -1241,7 +1284,7 @@ static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int rfd, int virq, int kvm_irqchip_add_adapter_route(KVMState *s, AdapterInfo *adapter) { - struct kvm_irq_routing_entry kroute; + struct kvm_irq_routing_entry kroute = {}; int virq; if (!kvm_gsi_routing_enabled()) { @@ -1368,8 +1411,9 @@ static int kvm_max_vcpus(KVMState *s) return (ret) ? ret : kvm_recommended_vcpus(s); } -int kvm_init(MachineClass *mc) +static int kvm_init(MachineState *ms) { + MachineClass *mc = MACHINE_GET_CLASS(ms); static const char upgrade_note[] = "Please upgrade to at least kernel 2.6.29 or recent kvm-kmod\n" "(see http://sourceforge.net/projects/kvm).\n"; @@ -1388,7 +1432,7 @@ int kvm_init(MachineClass *mc) int i, type = 0; const char *kvm_type; - s = g_malloc0(sizeof(KVMState)); + s = KVM_STATE(ms->accelerator); /* * On systems where the kernel can support different base page @@ -1548,6 +1592,12 @@ int kvm_init(MachineClass *mc) kvm_eventfds_allowed = (kvm_check_extension(s, KVM_CAP_IOEVENTFD) > 0); + kvm_irqfds_allowed = + (kvm_check_extension(s, KVM_CAP_IRQFD) > 0); + + kvm_resamplefds_allowed = + (kvm_check_extension(s, KVM_CAP_IRQFD_RESAMPLE) > 0); + ret = kvm_arch_init(s); if (ret < 0) { goto err; @@ -1577,7 +1627,6 @@ err: close(s->fd); } g_free(s->slots); - g_free(s); return ret; } @@ -1695,6 +1744,11 @@ void kvm_cpu_synchronize_post_init(CPUState *cpu) run_on_cpu(cpu, do_kvm_cpu_synchronize_post_init, cpu); } +void kvm_cpu_clean_state(CPUState *cpu) +{ + cpu->kvm_vcpu_dirty = false; +} + int kvm_cpu_exec(CPUState *cpu) { struct kvm_run *run = cpu->kvm_run; @@ -1738,7 +1792,8 @@ int kvm_cpu_exec(CPUState *cpu) } fprintf(stderr, "error: kvm run failed %s\n", strerror(-run_ret)); - abort(); + ret = -1; + break; } trace_kvm_run_exit(cpu->cpu_index, run->exit_reason); @@ -1940,9 +1995,6 @@ int kvm_has_intx_set_mask(void) void kvm_setup_guest_memory(void *start, size_t size) { -#ifdef CONFIG_VALGRIND_H - VALGRIND_MAKE_MEM_DEFINED(start, size); -#endif if (!kvm_has_sync_mmu()) { int ret = qemu_madvise(start, size, QEMU_MADV_DONTFORK); @@ -2018,10 +2070,6 @@ int kvm_insert_breakpoint(CPUState *cpu, target_ulong addr, } bp = g_malloc(sizeof(struct kvm_sw_breakpoint)); - if (!bp) { - return -ENOMEM; - } - bp->pc = addr; bp->use_count = 1; err = kvm_arch_insert_sw_breakpoint(cpu, bp); @@ -2213,3 +2261,25 @@ int kvm_get_one_reg(CPUState *cs, uint64_t id, void *target) } return r; } + +static void kvm_accel_class_init(ObjectClass *oc, void *data) +{ + AccelClass *ac = ACCEL_CLASS(oc); + ac->name = "KVM"; + ac->init_machine = kvm_init; + ac->allowed = &kvm_allowed; +} + +static const TypeInfo kvm_accel_type = { + .name = TYPE_KVM_ACCEL, + .parent = TYPE_ACCEL, + .class_init = kvm_accel_class_init, + .instance_size = sizeof(KVMState), +}; + +static void kvm_type_init(void) +{ + type_register_static(&kvm_accel_type); +} + +type_init(kvm_type_init);