#include "exec/memory.h"
#include "exec/address-spaces.h"
#include "qemu/event_notifier.h"
+#include "trace.h"
/* This check must be after config-host.h is included */
#ifdef CONFIG_EVENTFD
bool kvm_irqfds_allowed;
bool kvm_msi_via_irqfd_allowed;
bool kvm_gsi_routing_allowed;
+bool kvm_allowed;
+bool kvm_readonly_mem_allowed;
static const KVMCapabilityInfo kvm_required_capabilites[] = {
KVM_CAP_INFO(USER_MEMORY),
mem.slot = slot->slot;
mem.guest_phys_addr = slot->start_addr;
- mem.memory_size = slot->memory_size;
mem.userspace_addr = (unsigned long)slot->ram;
mem.flags = slot->flags;
if (s->migration_log) {
mem.flags |= KVM_MEM_LOG_DIRTY_PAGES;
}
+
+ if (slot->memory_size && mem.flags & KVM_MEM_READONLY) {
+ /* Set the slot size to 0 before setting the slot to the desired
+ * value. This is needed based on KVM commit 75d61fbc. */
+ mem.memory_size = 0;
+ kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem);
+ }
+ mem.memory_size = slot->memory_size;
return kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem);
}
* dirty pages logging control
*/
-static int kvm_mem_flags(KVMState *s, bool log_dirty)
+static int kvm_mem_flags(KVMState *s, bool log_dirty, bool readonly)
{
- return log_dirty ? KVM_MEM_LOG_DIRTY_PAGES : 0;
+ int flags = 0;
+ flags = log_dirty ? KVM_MEM_LOG_DIRTY_PAGES : 0;
+ if (readonly && kvm_readonly_mem_allowed) {
+ flags |= KVM_MEM_READONLY;
+ }
+ return flags;
}
static int kvm_slot_dirty_pages_log_change(KVMSlot *mem, bool log_dirty)
old_flags = mem->flags;
- flags = (mem->flags & ~mask) | kvm_mem_flags(s, log_dirty);
+ flags = (mem->flags & ~mask) | kvm_mem_flags(s, log_dirty, false);
mem->flags = flags;
/* If nothing changed effectively, no need to issue ioctl */
int r;
r = kvm_dirty_pages_log_change(section->offset_within_address_space,
- section->size, true);
+ int128_get64(section->size), true);
if (r < 0) {
abort();
}
int r;
r = kvm_dirty_pages_log_change(section->offset_within_address_space,
- section->size, false);
+ int128_get64(section->size), false);
if (r < 0) {
abort();
}
unsigned int i, j;
unsigned long page_number, c;
hwaddr addr, addr1;
- unsigned int len = ((section->size / getpagesize()) + HOST_LONG_BITS - 1) / HOST_LONG_BITS;
+ unsigned int pages = int128_get64(section->size) / getpagesize();
+ unsigned int len = (pages + HOST_LONG_BITS - 1) / HOST_LONG_BITS;
unsigned long hpratio = getpagesize() / TARGET_PAGE_SIZE;
/*
KVMSlot *mem;
int ret = 0;
hwaddr start_addr = section->offset_within_address_space;
- hwaddr end_addr = start_addr + section->size;
+ hwaddr end_addr = start_addr + int128_get64(section->size);
d.dirty_bitmap = NULL;
while (start_addr < end_addr) {
int err;
MemoryRegion *mr = section->mr;
bool log_dirty = memory_region_is_logging(mr);
+ bool writeable = !mr->readonly && !mr->rom_device;
+ bool readonly_flag = mr->readonly || memory_region_is_romd(mr);
hwaddr start_addr = section->offset_within_address_space;
- ram_addr_t size = section->size;
+ ram_addr_t size = int128_get64(section->size);
void *ram = NULL;
unsigned delta;
}
if (!memory_region_is_ram(mr)) {
- return;
+ if (writeable || !kvm_readonly_mem_allowed) {
+ return;
+ } else if (!mr->romd_mode) {
+ /* If the memory device is not in romd_mode, then we actually want
+ * to remove the kvm memory slot so all accesses will trap. */
+ add = false;
+ }
}
ram = memory_region_get_ram_ptr(mr) + section->offset_within_region + delta;
mem->memory_size = old.memory_size;
mem->start_addr = old.start_addr;
mem->ram = old.ram;
- mem->flags = kvm_mem_flags(s, log_dirty);
+ mem->flags = kvm_mem_flags(s, log_dirty, readonly_flag);
err = kvm_set_user_memory_region(s, mem);
if (err) {
mem->memory_size = start_addr - old.start_addr;
mem->start_addr = old.start_addr;
mem->ram = old.ram;
- mem->flags = kvm_mem_flags(s, log_dirty);
+ mem->flags = kvm_mem_flags(s, log_dirty, readonly_flag);
err = kvm_set_user_memory_region(s, mem);
if (err) {
size_delta = mem->start_addr - old.start_addr;
mem->memory_size = old.memory_size - size_delta;
mem->ram = old.ram + size_delta;
- mem->flags = kvm_mem_flags(s, log_dirty);
+ mem->flags = kvm_mem_flags(s, log_dirty, readonly_flag);
err = kvm_set_user_memory_region(s, mem);
if (err) {
mem->memory_size = size;
mem->start_addr = start_addr;
mem->ram = ram;
- mem->flags = kvm_mem_flags(s, log_dirty);
+ mem->flags = kvm_mem_flags(s, log_dirty, readonly_flag);
err = kvm_set_user_memory_region(s, mem);
if (err) {
int r;
r = kvm_set_ioeventfd_mmio(fd, section->offset_within_address_space,
- data, true, section->size, match_data);
+ data, true, int128_get64(section->size),
+ match_data);
if (r < 0) {
abort();
}
int r;
r = kvm_set_ioeventfd_mmio(fd, section->offset_within_address_space,
- data, false, section->size, match_data);
+ data, false, int128_get64(section->size),
+ match_data);
if (r < 0) {
abort();
}
int r;
r = kvm_set_ioeventfd_pio(fd, section->offset_within_address_space,
- data, true, section->size, match_data);
+ data, true, int128_get64(section->size),
+ match_data);
if (r < 0) {
abort();
}
int r;
r = kvm_set_ioeventfd_pio(fd, section->offset_within_address_space,
- data, false, section->size, match_data);
+ data, false, int128_get64(section->size),
+ match_data);
if (r < 0) {
abort();
}
s->irq_set_ioctl = KVM_IRQ_LINE_STATUS;
}
+#ifdef KVM_CAP_READONLY_MEM
+ kvm_readonly_mem_allowed =
+ (kvm_check_extension(s, KVM_CAP_READONLY_MEM) > 0);
+#endif
+
ret = kvm_arch_init(s);
if (ret < 0) {
goto err;
}
}
-void kvm_cpu_synchronize_post_reset(CPUArchState *env)
+void kvm_cpu_synchronize_post_reset(CPUState *cpu)
{
- 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)
+void kvm_cpu_synchronize_post_init(CPUState *cpu)
{
- CPUState *cpu = ENV_GET_CPU(env);
-
kvm_arch_put_registers(cpu, KVM_PUT_FULL_STATE);
cpu->kvm_vcpu_dirty = false;
}
abort();
}
+ trace_kvm_run_exit(cpu->cpu_index, run->exit_reason);
switch (run->exit_reason) {
case KVM_EXIT_IO:
DPRINTF("handle_io\n");
arg = va_arg(ap, void *);
va_end(ap);
+ trace_kvm_ioctl(type, arg);
ret = ioctl(s->fd, type, arg);
if (ret == -1) {
ret = -errno;
arg = va_arg(ap, void *);
va_end(ap);
+ trace_kvm_vm_ioctl(type, arg);
ret = ioctl(s->vmfd, type, arg);
if (ret == -1) {
ret = -errno;
arg = va_arg(ap, void *);
va_end(ap);
+ trace_kvm_vcpu_ioctl(cpu->cpu_index, type, arg);
ret = ioctl(cpu->kvm_fd, type, arg);
if (ret == -1) {
ret = -errno;
return kvm_state->intx_set_mask;
}
-void *kvm_vmalloc(ram_addr_t size)
+void *kvm_ram_alloc(ram_addr_t size)
{
#ifdef TARGET_S390X
void *mem;
- mem = kvm_arch_vmalloc(size);
+ mem = kvm_arch_ram_alloc(size);
if (mem) {
return mem;
}
#endif
- return qemu_vmalloc(size);
+ return qemu_anon_ram_alloc(size);
}
void kvm_setup_guest_memory(void *start, size_t size)