X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=kvm-all.c;h=9b433d31636067b83687c99102a4ff49446e0a70;hb=cecd77ae6df060bbe8f0eea6691112097e680a52;hp=46cf7e9ec4aa836bfdbb9a0564e90def44157dda;hpb=ad1ff3d99a55f559e00a11de14d91ca33a139252;p=qemu.git diff --git a/kvm-all.c b/kvm-all.c index 46cf7e9ec..9b433d316 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -21,18 +21,18 @@ #include #include "qemu-common.h" -#include "qemu-barrier.h" -#include "qemu-option.h" -#include "qemu-config.h" -#include "sysemu.h" +#include "qemu/atomic.h" +#include "qemu/option.h" +#include "qemu/config-file.h" +#include "sysemu/sysemu.h" #include "hw/hw.h" -#include "hw/msi.h" -#include "gdbstub.h" -#include "kvm.h" -#include "bswap.h" -#include "memory.h" -#include "exec-memory.h" -#include "event_notifier.h" +#include "hw/pci/msi.h" +#include "exec/gdbstub.h" +#include "sysemu/kvm.h" +#include "qemu/bswap.h" +#include "exec/memory.h" +#include "exec/address-spaces.h" +#include "qemu/event_notifier.h" /* This check must be after config-host.h is included */ #ifdef CONFIG_EVENTFD @@ -60,7 +60,7 @@ typedef struct KVMSlot { - target_phys_addr_t start_addr; + hwaddr start_addr; ram_addr_t memory_size; void *ram; int slot; @@ -131,8 +131,8 @@ static KVMSlot *kvm_alloc_slot(KVMState *s) } static KVMSlot *kvm_lookup_matching_slot(KVMState *s, - target_phys_addr_t start_addr, - target_phys_addr_t end_addr) + hwaddr start_addr, + hwaddr end_addr) { int i; @@ -152,8 +152,8 @@ static KVMSlot *kvm_lookup_matching_slot(KVMState *s, * Find overlapping slot with lowest start address */ static KVMSlot *kvm_lookup_overlapping_slot(KVMState *s, - target_phys_addr_t start_addr, - target_phys_addr_t end_addr) + hwaddr start_addr, + hwaddr end_addr) { KVMSlot *found = NULL; int i; @@ -176,7 +176,7 @@ static KVMSlot *kvm_lookup_overlapping_slot(KVMState *s, } int kvm_physical_memory_addr_from_host(KVMState *s, void *ram, - target_phys_addr_t *phys_addr) + hwaddr *phys_addr) { int i; @@ -209,12 +209,12 @@ static int kvm_set_user_memory_region(KVMState *s, KVMSlot *slot) static void kvm_reset_vcpu(void *opaque) { - CPUArchState *env = opaque; + CPUState *cpu = opaque; - kvm_arch_reset_vcpu(env); + kvm_arch_reset_vcpu(cpu); } -int kvm_init_vcpu(CPUArchState *env) +int kvm_init_vcpu(CPUState *cpu) { KVMState *s = kvm_state; long mmap_size; @@ -222,15 +222,15 @@ int kvm_init_vcpu(CPUArchState *env) DPRINTF("kvm_init_vcpu\n"); - ret = kvm_vm_ioctl(s, KVM_CREATE_VCPU, env->cpu_index); + ret = kvm_vm_ioctl(s, KVM_CREATE_VCPU, (void *)kvm_arch_vcpu_id(cpu)); if (ret < 0) { DPRINTF("kvm_create_vcpu failed\n"); goto err; } - env->kvm_fd = ret; - env->kvm_state = s; - env->kvm_vcpu_dirty = 1; + cpu->kvm_fd = ret; + cpu->kvm_state = s; + cpu->kvm_vcpu_dirty = true; mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0); if (mmap_size < 0) { @@ -239,9 +239,9 @@ int kvm_init_vcpu(CPUArchState *env) goto err; } - env->kvm_run = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, - env->kvm_fd, 0); - if (env->kvm_run == MAP_FAILED) { + cpu->kvm_run = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, + cpu->kvm_fd, 0); + if (cpu->kvm_run == MAP_FAILED) { ret = -errno; DPRINTF("mmap'ing vcpu state failed\n"); goto err; @@ -249,13 +249,13 @@ int kvm_init_vcpu(CPUArchState *env) if (s->coalesced_mmio && !s->coalesced_mmio_ring) { s->coalesced_mmio_ring = - (void *)env->kvm_run + s->coalesced_mmio * PAGE_SIZE; + (void *)cpu->kvm_run + s->coalesced_mmio * PAGE_SIZE; } - ret = kvm_arch_init_vcpu(env); + ret = kvm_arch_init_vcpu(cpu); if (ret == 0) { - qemu_register_reset(kvm_reset_vcpu, env); - kvm_arch_reset_vcpu(env); + qemu_register_reset(kvm_reset_vcpu, cpu); + kvm_arch_reset_vcpu(cpu); } err: return ret; @@ -293,7 +293,7 @@ static int kvm_slot_dirty_pages_log_change(KVMSlot *mem, bool log_dirty) return kvm_set_user_memory_region(s, mem); } -static int kvm_dirty_pages_log_change(target_phys_addr_t phys_addr, +static int kvm_dirty_pages_log_change(hwaddr phys_addr, ram_addr_t size, bool log_dirty) { KVMState *s = kvm_state; @@ -302,7 +302,7 @@ static int kvm_dirty_pages_log_change(target_phys_addr_t phys_addr, if (mem == NULL) { fprintf(stderr, "BUG: %s: invalid parameters " TARGET_FMT_plx "-" TARGET_FMT_plx "\n", __func__, phys_addr, - (target_phys_addr_t)(phys_addr + size - 1)); + (hwaddr)(phys_addr + size - 1)); return -EINVAL; } return kvm_slot_dirty_pages_log_change(mem, log_dirty); @@ -363,8 +363,8 @@ static int kvm_get_dirty_pages_log_range(MemoryRegionSection *section, { unsigned int i, j; unsigned long page_number, c; - target_phys_addr_t addr, addr1; - unsigned int len = ((section->size / TARGET_PAGE_SIZE) + HOST_LONG_BITS - 1) / HOST_LONG_BITS; + hwaddr addr, addr1; + unsigned int len = ((section->size / getpagesize()) + HOST_LONG_BITS - 1) / HOST_LONG_BITS; unsigned long hpratio = getpagesize() / TARGET_PAGE_SIZE; /* @@ -406,8 +406,8 @@ static int kvm_physical_sync_dirty_bitmap(MemoryRegionSection *section) KVMDirtyLog d; KVMSlot *mem; int ret = 0; - target_phys_addr_t start_addr = section->offset_within_address_space; - target_phys_addr_t end_addr = start_addr + section->size; + hwaddr start_addr = section->offset_within_address_space; + hwaddr end_addr = start_addr + section->size; d.dirty_bitmap = NULL; while (start_addr < end_addr) { @@ -454,9 +454,10 @@ static int kvm_physical_sync_dirty_bitmap(MemoryRegionSection *section) return ret; } -int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size) +static void kvm_coalesce_mmio_region(MemoryListener *listener, + MemoryRegionSection *secion, + hwaddr start, hwaddr size) { - int ret = -ENOSYS; KVMState *s = kvm_state; if (s->coalesced_mmio) { @@ -466,15 +467,14 @@ int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size) zone.size = size; zone.pad = 0; - ret = kvm_vm_ioctl(s, KVM_REGISTER_COALESCED_MMIO, &zone); + (void)kvm_vm_ioctl(s, KVM_REGISTER_COALESCED_MMIO, &zone); } - - return ret; } -int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size) +static void kvm_uncoalesce_mmio_region(MemoryListener *listener, + MemoryRegionSection *secion, + hwaddr start, hwaddr size) { - int ret = -ENOSYS; KVMState *s = kvm_state; if (s->coalesced_mmio) { @@ -484,10 +484,8 @@ int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size) zone.size = size; zone.pad = 0; - ret = kvm_vm_ioctl(s, KVM_UNREGISTER_COALESCED_MMIO, &zone); + (void)kvm_vm_ioctl(s, KVM_UNREGISTER_COALESCED_MMIO, &zone); } - - return ret; } int kvm_check_extension(KVMState *s, unsigned int extension) @@ -558,7 +556,7 @@ static void kvm_set_phys_mem(MemoryRegionSection *section, bool add) int err; MemoryRegion *mr = section->mr; bool log_dirty = memory_region_is_logging(mr); - target_phys_addr_t start_addr = section->offset_within_address_space; + hwaddr start_addr = section->offset_within_address_space; ram_addr_t size = section->size; void *ram = NULL; unsigned delta; @@ -817,6 +815,8 @@ static MemoryListener kvm_memory_listener = { .log_global_stop = kvm_log_global_stop, .eventfd_add = kvm_mem_ioeventfd_add, .eventfd_del = kvm_mem_ioeventfd_del, + .coalesced_mmio_add = kvm_coalesce_mmio_region, + .coalesced_mmio_del = kvm_uncoalesce_mmio_region, .priority = 10, }; @@ -826,12 +826,12 @@ static MemoryListener kvm_io_listener = { .priority = 10, }; -static void kvm_handle_interrupt(CPUArchState *env, int mask) +static void kvm_handle_interrupt(CPUState *cpu, int mask) { - env->interrupt_request |= mask; + cpu->interrupt_request |= mask; - if (!qemu_cpu_is_self(env)) { - qemu_cpu_kick(env); + if (!qemu_cpu_is_self(cpu)) { + qemu_cpu_kick(cpu); } } @@ -989,8 +989,6 @@ void kvm_irqchip_release_virq(KVMState *s, int virq) } } clear_gsi(s, virq); - - kvm_irqchip_commit_routes(s); } static unsigned int kvm_hash_msi(uint32_t data) @@ -1181,6 +1179,11 @@ static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int virq, bool assign) { abort(); } + +int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg) +{ + return -ENOSYS; +} #endif /* !KVM_CAP_IRQ_ROUTING */ int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n, int virq) @@ -1375,8 +1378,8 @@ int kvm_init(void) } kvm_state = s; - memory_listener_register(&kvm_memory_listener, get_system_memory()); - memory_listener_register(&kvm_io_listener, get_system_io()); + memory_listener_register(&kvm_memory_listener, &address_space_memory); + memory_listener_register(&kvm_io_listener, &address_space_io); s->many_ioeventfds = kvm_check_many_ioeventfds(); @@ -1435,6 +1438,8 @@ static void kvm_handle_io(uint16_t port, void *data, int direction, int size, static int kvm_handle_internal_error(CPUArchState *env, struct kvm_run *run) { + CPUState *cpu = ENV_GET_CPU(env); + fprintf(stderr, "KVM internal error."); if (kvm_check_extension(kvm_state, KVM_CAP_INTERNAL_ERROR_DATA)) { int i; @@ -1449,7 +1454,7 @@ static int kvm_handle_internal_error(CPUArchState *env, struct kvm_run *run) } if (run->internal.suberror == KVM_INTERNAL_ERROR_EMULATION) { fprintf(stderr, "emulation failure\n"); - if (!kvm_arch_stop_on_emulation_error(env)) { + if (!kvm_arch_stop_on_emulation_error(cpu)) { cpu_dump_state(env, stderr, fprintf, CPU_DUMP_CODE); return EXCP_INTERRUPT; } @@ -1486,55 +1491,62 @@ void kvm_flush_coalesced_mmio_buffer(void) s->coalesced_flush_in_progress = false; } -static void do_kvm_cpu_synchronize_state(void *_env) +static void do_kvm_cpu_synchronize_state(void *arg) { - CPUArchState *env = _env; + CPUState *cpu = arg; - if (!env->kvm_vcpu_dirty) { - kvm_arch_get_registers(env); - env->kvm_vcpu_dirty = 1; + if (!cpu->kvm_vcpu_dirty) { + kvm_arch_get_registers(cpu); + cpu->kvm_vcpu_dirty = true; } } void kvm_cpu_synchronize_state(CPUArchState *env) { - if (!env->kvm_vcpu_dirty) { - run_on_cpu(env, do_kvm_cpu_synchronize_state, env); + CPUState *cpu = ENV_GET_CPU(env); + + if (!cpu->kvm_vcpu_dirty) { + run_on_cpu(cpu, do_kvm_cpu_synchronize_state, cpu); } } void kvm_cpu_synchronize_post_reset(CPUArchState *env) { - kvm_arch_put_registers(env, KVM_PUT_RESET_STATE); - env->kvm_vcpu_dirty = 0; + CPUState *cpu = ENV_GET_CPU(env); + + kvm_arch_put_registers(cpu, KVM_PUT_RESET_STATE); + cpu->kvm_vcpu_dirty = false; } void kvm_cpu_synchronize_post_init(CPUArchState *env) { - kvm_arch_put_registers(env, KVM_PUT_FULL_STATE); - env->kvm_vcpu_dirty = 0; + CPUState *cpu = ENV_GET_CPU(env); + + kvm_arch_put_registers(cpu, KVM_PUT_FULL_STATE); + cpu->kvm_vcpu_dirty = false; } int kvm_cpu_exec(CPUArchState *env) { - struct kvm_run *run = env->kvm_run; + CPUState *cpu = ENV_GET_CPU(env); + struct kvm_run *run = cpu->kvm_run; int ret, run_ret; DPRINTF("kvm_cpu_exec()\n"); - if (kvm_arch_process_async_events(env)) { - env->exit_request = 0; + if (kvm_arch_process_async_events(cpu)) { + cpu->exit_request = 0; return EXCP_HLT; } do { - if (env->kvm_vcpu_dirty) { - kvm_arch_put_registers(env, KVM_PUT_RUNTIME_STATE); - env->kvm_vcpu_dirty = 0; + if (cpu->kvm_vcpu_dirty) { + kvm_arch_put_registers(cpu, KVM_PUT_RUNTIME_STATE); + cpu->kvm_vcpu_dirty = false; } - kvm_arch_pre_run(env, run); - if (env->exit_request) { + kvm_arch_pre_run(cpu, run); + if (cpu->exit_request) { DPRINTF("interrupt exit requested\n"); /* * KVM requires us to reenter the kernel after IO exits to complete @@ -1545,10 +1557,10 @@ int kvm_cpu_exec(CPUArchState *env) } qemu_mutex_unlock_iothread(); - run_ret = kvm_vcpu_ioctl(env, KVM_RUN, 0); + run_ret = kvm_vcpu_ioctl(cpu, KVM_RUN, 0); qemu_mutex_lock_iothread(); - kvm_arch_post_run(env, run); + kvm_arch_post_run(cpu, run); if (run_ret < 0) { if (run_ret == -EINTR || run_ret == -EAGAIN) { @@ -1598,7 +1610,7 @@ int kvm_cpu_exec(CPUArchState *env) break; default: DPRINTF("kvm_arch_handle_exit\n"); - ret = kvm_arch_handle_exit(env, run); + ret = kvm_arch_handle_exit(cpu, run); break; } } while (ret == 0); @@ -1608,7 +1620,7 @@ int kvm_cpu_exec(CPUArchState *env) vm_stop(RUN_STATE_INTERNAL_ERROR); } - env->exit_request = 0; + cpu->exit_request = 0; return ret; } @@ -1646,7 +1658,7 @@ int kvm_vm_ioctl(KVMState *s, int type, ...) return ret; } -int kvm_vcpu_ioctl(CPUArchState *env, int type, ...) +int kvm_vcpu_ioctl(CPUState *cpu, int type, ...) { int ret; void *arg; @@ -1656,7 +1668,7 @@ int kvm_vcpu_ioctl(CPUArchState *env, int type, ...) arg = va_arg(ap, void *); va_end(ap); - ret = ioctl(env->kvm_fd, type, arg); + ret = ioctl(cpu->kvm_fd, type, arg); if (ret == -1) { ret = -errno; } @@ -1751,12 +1763,12 @@ void kvm_setup_guest_memory(void *start, size_t size) } #ifdef KVM_CAP_SET_GUEST_DEBUG -struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUArchState *env, +struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *cpu, target_ulong pc) { struct kvm_sw_breakpoint *bp; - QTAILQ_FOREACH(bp, &env->kvm_state->kvm_sw_breakpoints, entry) { + QTAILQ_FOREACH(bp, &cpu->kvm_state->kvm_sw_breakpoints, entry) { if (bp->pc == pc) { return bp; } @@ -1764,27 +1776,28 @@ struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUArchState *env, return NULL; } -int kvm_sw_breakpoints_active(CPUArchState *env) +int kvm_sw_breakpoints_active(CPUState *cpu) { - return !QTAILQ_EMPTY(&env->kvm_state->kvm_sw_breakpoints); + return !QTAILQ_EMPTY(&cpu->kvm_state->kvm_sw_breakpoints); } struct kvm_set_guest_debug_data { struct kvm_guest_debug dbg; - CPUArchState *env; + CPUState *cpu; int err; }; static void kvm_invoke_set_guest_debug(void *data) { struct kvm_set_guest_debug_data *dbg_data = data; - CPUArchState *env = dbg_data->env; - dbg_data->err = kvm_vcpu_ioctl(env, KVM_SET_GUEST_DEBUG, &dbg_data->dbg); + dbg_data->err = kvm_vcpu_ioctl(dbg_data->cpu, KVM_SET_GUEST_DEBUG, + &dbg_data->dbg); } int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap) { + CPUState *cpu = ENV_GET_CPU(env); struct kvm_set_guest_debug_data data; data.dbg.control = reinject_trap; @@ -1792,22 +1805,23 @@ int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap) if (env->singlestep_enabled) { data.dbg.control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP; } - kvm_arch_update_guest_debug(env, &data.dbg); - data.env = env; + kvm_arch_update_guest_debug(cpu, &data.dbg); + data.cpu = cpu; - run_on_cpu(env, kvm_invoke_set_guest_debug, &data); + run_on_cpu(cpu, kvm_invoke_set_guest_debug, &data); return data.err; } int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr, target_ulong len, int type) { + CPUState *current_cpu = ENV_GET_CPU(current_env); struct kvm_sw_breakpoint *bp; CPUArchState *env; int err; if (type == GDB_BREAKPOINT_SW) { - bp = kvm_find_sw_breakpoint(current_env, addr); + bp = kvm_find_sw_breakpoint(current_cpu, addr); if (bp) { bp->use_count++; return 0; @@ -1820,13 +1834,13 @@ int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr, bp->pc = addr; bp->use_count = 1; - err = kvm_arch_insert_sw_breakpoint(current_env, bp); + err = kvm_arch_insert_sw_breakpoint(current_cpu, bp); if (err) { g_free(bp); return err; } - QTAILQ_INSERT_HEAD(¤t_env->kvm_state->kvm_sw_breakpoints, + QTAILQ_INSERT_HEAD(¤t_cpu->kvm_state->kvm_sw_breakpoints, bp, entry); } else { err = kvm_arch_insert_hw_breakpoint(addr, len, type); @@ -1847,12 +1861,13 @@ int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr, int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr, target_ulong len, int type) { + CPUState *current_cpu = ENV_GET_CPU(current_env); struct kvm_sw_breakpoint *bp; CPUArchState *env; int err; if (type == GDB_BREAKPOINT_SW) { - bp = kvm_find_sw_breakpoint(current_env, addr); + bp = kvm_find_sw_breakpoint(current_cpu, addr); if (!bp) { return -ENOENT; } @@ -1862,12 +1877,12 @@ int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr, return 0; } - err = kvm_arch_remove_sw_breakpoint(current_env, bp); + err = kvm_arch_remove_sw_breakpoint(current_cpu, bp); if (err) { return err; } - QTAILQ_REMOVE(¤t_env->kvm_state->kvm_sw_breakpoints, bp, entry); + QTAILQ_REMOVE(¤t_cpu->kvm_state->kvm_sw_breakpoints, bp, entry); g_free(bp); } else { err = kvm_arch_remove_hw_breakpoint(addr, len, type); @@ -1887,19 +1902,24 @@ int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr, void kvm_remove_all_breakpoints(CPUArchState *current_env) { + CPUState *current_cpu = ENV_GET_CPU(current_env); struct kvm_sw_breakpoint *bp, *next; - KVMState *s = current_env->kvm_state; + KVMState *s = current_cpu->kvm_state; CPUArchState *env; + CPUState *cpu; QTAILQ_FOREACH_SAFE(bp, &s->kvm_sw_breakpoints, entry, next) { - if (kvm_arch_remove_sw_breakpoint(current_env, bp) != 0) { + if (kvm_arch_remove_sw_breakpoint(current_cpu, bp) != 0) { /* Try harder to find a CPU that currently sees the breakpoint. */ for (env = first_cpu; env != NULL; env = env->next_cpu) { - if (kvm_arch_remove_sw_breakpoint(env, bp) == 0) { + cpu = ENV_GET_CPU(env); + if (kvm_arch_remove_sw_breakpoint(cpu, bp) == 0) { break; } } } + QTAILQ_REMOVE(&s->kvm_sw_breakpoints, bp, entry); + g_free(bp); } kvm_arch_remove_all_hw_breakpoints(); @@ -1934,18 +1954,19 @@ void kvm_remove_all_breakpoints(CPUArchState *current_env) int kvm_set_signal_mask(CPUArchState *env, const sigset_t *sigset) { + CPUState *cpu = ENV_GET_CPU(env); struct kvm_signal_mask *sigmask; int r; if (!sigset) { - return kvm_vcpu_ioctl(env, KVM_SET_SIGNAL_MASK, NULL); + return kvm_vcpu_ioctl(cpu, KVM_SET_SIGNAL_MASK, NULL); } sigmask = g_malloc(sizeof(*sigmask) + sizeof(*sigset)); sigmask->len = 8; memcpy(sigmask->sigset, sigset, sizeof(*sigset)); - r = kvm_vcpu_ioctl(env, KVM_SET_SIGNAL_MASK, sigmask); + r = kvm_vcpu_ioctl(cpu, KVM_SET_SIGNAL_MASK, sigmask); g_free(sigmask); return r; @@ -2003,9 +2024,9 @@ int kvm_set_ioeventfd_pio_word(int fd, uint16_t addr, uint16_t val, bool assign) return 0; } -int kvm_on_sigbus_vcpu(CPUArchState *env, int code, void *addr) +int kvm_on_sigbus_vcpu(CPUState *cpu, int code, void *addr) { - return kvm_arch_on_sigbus_vcpu(env, code, addr); + return kvm_arch_on_sigbus_vcpu(cpu, code, addr); } int kvm_on_sigbus(int code, void *addr)