summaryrefslogtreecommitdiff
path: root/kvm-all.c
diff options
context:
space:
mode:
authorChanho Park <chanho61.park@samsung.com>2014-12-10 15:42:55 +0900
committerChanho Park <chanho61.park@samsung.com>2014-12-10 15:42:55 +0900
commit0d6a2f7e595218b5632ba7005128470e65138951 (patch)
tree596b09930ef1538e6606450e2d8b88ec2e296a9b /kvm-all.c
parent16b1353a36171ae06d63fd309f4772dbfb1da113 (diff)
downloadqemu-0d6a2f7e595218b5632ba7005128470e65138951.tar.gz
qemu-0d6a2f7e595218b5632ba7005128470e65138951.tar.bz2
qemu-0d6a2f7e595218b5632ba7005128470e65138951.zip
Imported Upstream version 2.2.0upstream/2.2.1upstream/2.2.0
Diffstat (limited to 'kvm-all.c')
-rw-r--r--kvm-all.c106
1 files changed, 90 insertions, 16 deletions
diff --git a/kvm-all.c b/kvm-all.c
index 1402f4f42..937bc9d90 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 <sys/eventfd.h>
#endif
-#ifdef CONFIG_VALGRIND_H
-#include <valgrind/memcheck.h>
-#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,6 +109,11 @@ 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;
@@ -128,7 +132,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 +142,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();
}
@@ -493,6 +513,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 +650,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;
}
@@ -1368,8 +1403,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 +1424,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
@@ -1577,7 +1613,6 @@ err:
close(s->fd);
}
g_free(s->slots);
- g_free(s);
return ret;
}
@@ -1669,18 +1704,37 @@ void kvm_cpu_synchronize_state(CPUState *cpu)
}
}
-void kvm_cpu_synchronize_post_reset(CPUState *cpu)
+static void do_kvm_cpu_synchronize_post_reset(void *arg)
{
+ CPUState *cpu = arg;
+
kvm_arch_put_registers(cpu, KVM_PUT_RESET_STATE);
cpu->kvm_vcpu_dirty = false;
}
-void kvm_cpu_synchronize_post_init(CPUState *cpu)
+void kvm_cpu_synchronize_post_reset(CPUState *cpu)
{
+ run_on_cpu(cpu, do_kvm_cpu_synchronize_post_reset, cpu);
+}
+
+static void do_kvm_cpu_synchronize_post_init(void *arg)
+{
+ CPUState *cpu = arg;
+
kvm_arch_put_registers(cpu, KVM_PUT_FULL_STATE);
cpu->kvm_vcpu_dirty = false;
}
+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;
@@ -1724,7 +1778,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);
@@ -1926,9 +1981,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);
@@ -2199,3 +2251,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);