@@ -158,6 +158,7 @@ extern bool kvm_readonly_mem_allowed;
struct kvm_run;
struct kvm_lapic_state;
+struct kvm_irq_routing_entry;
typedef struct KVMCapabilityInfo {
const char *name;
@@ -270,6 +271,9 @@ int kvm_arch_on_sigbus(int code, void *addr);
void kvm_arch_init_irq_routing(KVMState *s);
+int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
+ uint64_t address, uint32_t data);
+
int kvm_set_irq(KVMState *s, int irq, int level);
int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg);
@@ -1225,6 +1225,10 @@ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg)
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);
@@ -1250,6 +1254,9 @@ int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg)
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);
}
@@ -548,3 +548,9 @@ int kvm_arch_irqchip_create(KVMState *s)
return 0;
}
+
+int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
+ uint64_t address, uint32_t data)
+{
+ return 0;
+}
@@ -2733,3 +2733,9 @@ int kvm_device_msix_deassign(KVMState *s, uint32_t dev_id)
return kvm_deassign_irq_internal(s, dev_id, KVM_DEV_IRQ_GUEST_MSIX |
KVM_DEV_IRQ_HOST_MSIX);
}
+
+int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
+ uint64_t address, uint32_t data)
+{
+ return 0;
+}
@@ -688,3 +688,9 @@ int kvm_arch_get_registers(CPUState *cs)
return ret;
}
+
+int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
+ uint64_t address, uint32_t data)
+{
+ return 0;
+}
@@ -2388,3 +2388,9 @@ out_close:
error_out:
return;
}
+
+int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
+ uint64_t address, uint32_t data)
+{
+ return 0;
+}
@@ -41,6 +41,7 @@
#include "trace.h"
#include "qapi-event.h"
#include "hw/s390x/s390-pci-inst.h"
+#include "hw/s390x/s390-pci-bus.h"
/* #define DEBUG_KVM */
@@ -1514,3 +1515,28 @@ int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state)
return ret;
}
+
+int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
+ uint64_t address, uint32_t data)
+{
+ S390PCIBusDevice *pbdev;
+ uint32_t fid = data >> ZPCI_MSI_VEC_BITS;
+ uint32_t vec = data & ZPCI_MSI_VEC_MASK;
+
+ pbdev = s390_pci_find_dev_by_fid(fid);
+ if (!pbdev) {
+ DPRINTF("add_msi_route no dev\n");
+ return -ENODEV;
+ }
+
+ pbdev->routes.adapter.ind_offset = vec;
+
+ route->type = KVM_IRQ_ROUTING_S390_ADAPTER;
+ route->flags = 0;
+ route->u.adapter.summary_addr = pbdev->routes.adapter.summary_addr;
+ route->u.adapter.ind_addr = pbdev->routes.adapter.ind_addr;
+ route->u.adapter.summary_offset = pbdev->routes.adapter.summary_offset;
+ route->u.adapter.ind_offset = pbdev->routes.adapter.ind_offset;
+ route->u.adapter.adapter_id = pbdev->routes.adapter.adapter_id;
+ return 0;
+}