#endif
int irqchip_in_kernel;
int pit_in_kernel;
+ int xsave, xcrs;
};
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;
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;
}
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;
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;
+}
+
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
}
}
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