bool kvm_gsi_direct_mapping;
bool kvm_allowed;
bool kvm_readonly_mem_allowed;
+bool kvm_vm_attributes_allowed;
static const KVMCapabilityInfo kvm_required_capabilites[] = {
KVM_CAP_INFO(USER_MEMORY),
}
}
-static int kvm_set_migration_log(int enable)
+static int kvm_set_migration_log(bool enable)
{
KVMState *s = kvm_state;
KVMSlot *mem;
{
KVMState *s = kvm_state;
unsigned long size, allocated_size = 0;
- KVMDirtyLog d;
+ KVMDirtyLog d = {};
KVMSlot *mem;
int ret = 0;
hwaddr start_addr = section->offset_within_address_space;
return ret;
}
+static uint32_t adjust_ioeventfd_endianness(uint32_t val, uint32_t size)
+{
+#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
+ /* The kernel expects ioeventfd values in HOST_WORDS_BIGENDIAN
+ * endianness, but the memory core hands them in target endianness.
+ * For example, PPC is always treated as big-endian even if running
+ * on KVM and on PPC64LE. Correct here.
+ */
+ switch (size) {
+ case 2:
+ val = bswap16(val);
+ break;
+ case 4:
+ val = bswap32(val);
+ break;
+ }
+#endif
+ return val;
+}
+
static int kvm_set_ioeventfd_mmio(int fd, hwaddr addr, uint32_t val,
bool assign, uint32_t size, bool datamatch)
{
int ret;
struct kvm_ioeventfd iofd;
- iofd.datamatch = datamatch ? val : 0;
+ iofd.datamatch = datamatch ? adjust_ioeventfd_endianness(val, size) : 0;
iofd.addr = addr;
iofd.len = size;
iofd.flags = 0;
bool assign, uint32_t size, bool datamatch)
{
struct kvm_ioeventfd kick = {
- .datamatch = datamatch ? val : 0,
+ .datamatch = datamatch ? adjust_ioeventfd_endianness(val, size) : 0,
.addr = addr,
.flags = KVM_IOEVENTFD_FLAG_PIO,
.len = size,
kroute.u.msi.address_lo = (uint32_t)msg.address;
kroute.u.msi.address_hi = msg.address >> 32;
kroute.u.msi.data = le32_to_cpu(msg.data);
+ if (kvm_arch_fixup_msi_route(&kroute, msg.address, msg.data)) {
+ kvm_irqchip_release_virq(s, virq);
+ return -EINVAL;
+ }
kvm_add_routing_entry(s, &kroute);
kvm_irqchip_commit_routes(s);
kroute.u.msi.address_lo = (uint32_t)msg.address;
kroute.u.msi.address_hi = msg.address >> 32;
kroute.u.msi.data = le32_to_cpu(msg.data);
+ if (kvm_arch_fixup_msi_route(&kroute, msg.address, msg.data)) {
+ return -EINVAL;
+ }
return kvm_update_routing_entry(s, &kroute);
}
int kvm_irqchip_add_adapter_route(KVMState *s, AdapterInfo *adapter)
{
- struct kvm_irq_routing_entry kroute;
+ struct kvm_irq_routing_entry kroute = {};
int virq;
if (!kvm_gsi_routing_enabled()) {
false);
}
-static int kvm_irqchip_create(KVMState *s)
+static int kvm_irqchip_create(MachineState *machine, KVMState *s)
{
int ret;
- if (!qemu_opt_get_bool(qemu_get_machine_opts(), "kernel_irqchip", true) ||
+ if (!machine_kernel_irqchip_allowed(machine) ||
(!kvm_check_extension(s, KVM_CAP_IRQCHIP) &&
(kvm_vm_enable_cap(s, KVM_CAP_S390_IRQCHIP, 0) < 0))) {
return 0;
kvm_resamplefds_allowed =
(kvm_check_extension(s, KVM_CAP_IRQFD_RESAMPLE) > 0);
- ret = kvm_arch_init(s);
+ kvm_vm_attributes_allowed =
+ (kvm_check_extension(s, KVM_CAP_VM_ATTRIBUTES) > 0);
+
+ ret = kvm_arch_init(ms, s);
if (ret < 0) {
goto err;
}
- ret = kvm_irqchip_create(s);
+ ret = kvm_irqchip_create(ms, s);
if (ret < 0) {
goto err;
}
return ret;
}
+int kvm_vm_check_attr(KVMState *s, uint32_t group, uint64_t attr)
+{
+ int ret;
+ struct kvm_device_attr attribute = {
+ .group = group,
+ .attr = attr,
+ };
+
+ if (!kvm_vm_attributes_allowed) {
+ return 0;
+ }
+
+ ret = kvm_vm_ioctl(s, KVM_HAS_DEVICE_ATTR, &attribute);
+ /* kvm returns 0 on success for HAS_DEVICE_ATTR */
+ return ret ? 0 : 1;
+}
+
int kvm_has_sync_mmu(void)
{
return kvm_check_extension(kvm_state, KVM_CAP_SYNC_MMU);
}
bp = g_malloc(sizeof(struct kvm_sw_breakpoint));
- if (!bp) {
- return -ENOMEM;
- }
-
bp->pc = addr;
bp->use_count = 1;
err = kvm_arch_insert_sw_breakpoint(cpu, bp);