#include "kvm.h"
#include "bswap.h"
+/* This check must be after config-host.h is included */
+#ifdef CONFIG_EVENTFD
+#include <sys/eventfd.h>
+#endif
+
/* KVM uses PAGE_SIZE in it's definition of COALESCED_MMIO_MAX */
#define PAGE_SIZE TARGET_PAGE_SIZE
#endif
int irqchip_in_kernel;
int pit_in_kernel;
+ int xsave, xcrs;
+ int many_ioeventfds;
};
static KVMState *kvm_state;
return found;
}
+int kvm_physical_memory_addr_from_ram(KVMState *s, ram_addr_t ram_addr,
+ target_phys_addr_t *phys_addr)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(s->slots); i++) {
+ KVMSlot *mem = &s->slots[i];
+
+ if (ram_addr >= mem->phys_offset &&
+ ram_addr < mem->phys_offset + mem->memory_size) {
+ *phys_addr = mem->start_addr + (ram_addr - mem->phys_offset);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
static int kvm_set_user_memory_region(KVMState *s, KVMSlot *slot)
{
struct kvm_userspace_memory_region mem;
mem.slot = slot->slot;
mem.guest_phys_addr = slot->start_addr;
mem.memory_size = slot->memory_size;
- mem.userspace_addr = (unsigned long)qemu_get_ram_ptr(slot->phys_offset);
+ mem.userspace_addr = (unsigned long)qemu_safe_ram_ptr(slot->phys_offset);
mem.flags = slot->flags;
if (s->migration_log) {
mem.flags |= KVM_MEM_LOG_DIRTY_PAGES;
for (i = 0; i < ARRAY_SIZE(s->slots); i++) {
mem = &s->slots[i];
+ if (!mem->memory_size) {
+ continue;
+ }
if (!!(mem->flags & KVM_MEM_LOG_DIRTY_PAGES) == enable) {
continue;
}
return ret;
}
+static int kvm_check_many_ioeventfds(void)
+{
+ /* Older kernels have a 6 device limit on the KVM io bus. Find out so we
+ * can avoid creating too many ioeventfds.
+ */
+#ifdef CONFIG_EVENTFD
+ int ioeventfds[7];
+ int i, ret = 0;
+ for (i = 0; i < ARRAY_SIZE(ioeventfds); i++) {
+ ioeventfds[i] = eventfd(0, EFD_CLOEXEC);
+ if (ioeventfds[i] < 0) {
+ break;
+ }
+ ret = kvm_set_ioeventfd_pio_word(ioeventfds[i], 0, i, true);
+ if (ret < 0) {
+ close(ioeventfds[i]);
+ break;
+ }
+ }
+
+ /* Decide whether many devices are supported or not */
+ ret = i == ARRAY_SIZE(ioeventfds);
+
+ while (i-- > 0) {
+ kvm_set_ioeventfd_pio_word(ioeventfds[i], 0, i, false);
+ close(ioeventfds[i]);
+ }
+ return ret;
+#else
+ return 0;
+#endif
+}
+
static void kvm_set_phys_mem(target_phys_addr_t start_addr,
ram_addr_t size,
ram_addr_t phys_offset)
KVMSlot *mem, old;
int err;
- if (start_addr & ~TARGET_PAGE_MASK) {
- if (flags >= IO_MEM_UNASSIGNED) {
- if (!kvm_lookup_overlapping_slot(s, start_addr,
- start_addr + size)) {
- return;
- }
- fprintf(stderr, "Unaligned split of a KVM memory slot\n");
- } else {
- fprintf(stderr, "Only page-aligned memory slots supported\n");
- }
- abort();
- }
+ /* kvm works in page size chunks, but the function may be called
+ with sub-page size and unaligned start address. */
+ size = TARGET_PAGE_ALIGN(size);
+ start_addr = TARGET_PAGE_ALIGN(start_addr);
/* KVM does not support read-only slots */
phys_offset &= ~IO_MEM_ROM;
s->debugregs = kvm_check_extension(s, KVM_CAP_DEBUGREGS);
#endif
+ s->xsave = 0;
+#ifdef KVM_CAP_XSAVE
+ s->xsave = kvm_check_extension(s, KVM_CAP_XSAVE);
+#endif
+
+ s->xcrs = 0;
+#ifdef KVM_CAP_XCRS
+ s->xcrs = kvm_check_extension(s, KVM_CAP_XCRS);
+#endif
+
ret = kvm_arch_init(s, smp_cpus);
if (ret < 0)
goto err;
kvm_state = s;
cpu_register_phys_memory_client(&kvm_cpu_phys_memory_client);
+ s->many_ioeventfds = kvm_check_many_ioeventfds();
+
return 0;
err:
cpu_dump_state(env, stderr, fprintf, 0);
if (run->internal.suberror == KVM_INTERNAL_ERROR_EMULATION) {
fprintf(stderr, "emulation failure\n");
+ if (!kvm_arch_stop_on_emulation_error(env))
+ return;
}
/* FIXME: Should trigger a qmp message to let management know
* something went wrong.
DPRINTF("kvm_exit_debug\n");
#ifdef KVM_CAP_SET_GUEST_DEBUG
if (kvm_arch_debug(&run->debug.arch)) {
- gdb_set_stop_cpu(env);
- vm_stop(EXCP_DEBUG);
env->exception_index = EXCP_DEBUG;
return 0;
}
return kvm_state->debugregs;
}
+int kvm_has_xsave(void)
+{
+ return kvm_state->xsave;
+}
+
+int kvm_has_xcrs(void)
+{
+ return kvm_state->xcrs;
+}
+
+int kvm_has_many_ioeventfds(void)
+{
+ if (!kvm_enabled()) {
+ return 0;
+ }
+ return kvm_state->many_ioeventfds;
+}
+
void kvm_setup_guest_memory(void *start, size_t size)
{
if (!kvm_has_sync_mmu()) {
-#ifdef MADV_DONTFORK
- int ret = madvise(start, size, MADV_DONTFORK);
+ int ret = qemu_madvise(start, size, QEMU_MADV_DONTFORK);
if (ret) {
- perror("madvice");
+ perror("qemu_madvise");
+ fprintf(stderr,
+ "Need MADV_DONTFORK in absence of synchronous KVM MMU\n");
exit(1);
}
-#else
- fprintf(stderr,
- "Need MADV_DONTFORK in absence of synchronous KVM MMU\n");
- exit(1);
-#endif
}
}
#ifdef KVM_CAP_SET_GUEST_DEBUG
-static void on_vcpu(CPUState *env, void (*func)(void *data), void *data)
-{
-#ifdef CONFIG_IOTHREAD
- if (env != cpu_single_env) {
- abort();
- }
-#endif
- func(data);
-}
-
struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *env,
target_ulong pc)
{
kvm_arch_update_guest_debug(env, &data.dbg);
data.env = env;
- on_vcpu(env, kvm_invoke_set_guest_debug, &data);
+ run_on_cpu(env, kvm_invoke_set_guest_debug, &data);
return data.err;
}
return r;
}
+int kvm_set_ioeventfd_mmio_long(int fd, uint32_t addr, uint32_t val, bool assign)
+{
+#ifdef KVM_IOEVENTFD
+ int ret;
+ struct kvm_ioeventfd iofd;
+
+ iofd.datamatch = val;
+ iofd.addr = addr;
+ iofd.len = 4;
+ iofd.flags = KVM_IOEVENTFD_FLAG_DATAMATCH;
+ iofd.fd = fd;
+
+ if (!kvm_enabled()) {
+ return -ENOSYS;
+ }
+
+ if (!assign) {
+ iofd.flags |= KVM_IOEVENTFD_FLAG_DEASSIGN;
+ }
+
+ ret = kvm_vm_ioctl(kvm_state, KVM_IOEVENTFD, &iofd);
+
+ if (ret < 0) {
+ return -errno;
+ }
+
+ return 0;
+#else
+ return -ENOSYS;
+#endif
+}
+
int kvm_set_ioeventfd_pio_word(int fd, uint16_t addr, uint16_t val, bool assign)
{
#ifdef KVM_IOEVENTFD