aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2023-10-17 13:24:33 +0200
committerPaolo Bonzini <pbonzini@redhat.com>2023-10-25 17:35:14 +0200
commitcc5e719e2c8086c61bdd9114f42095f8d5b1b0db (patch)
treeab24f672e3e2b5a763c210624419db5b8533decb
parentaacec9aee11660471ca56afaaafe3f1fdcf431ab (diff)
kvm: require KVM_CAP_SIGNAL_MSI
This was introduced in KVM in Linux 3.5, we can require it unconditionally in kvm_irqchip_send_msi(). However, not all architectures have to implement it so check it only in x86, the only architecture that ever had MSI injection but not KVM_CAP_SIGNAL_MSI. ARM uses it to detect the presence of the ITS emulation in the kernel, introduced in Linux 4.8. Assume that it's there and possibly fail when realizing the arm-its-kvm device. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--accel/kvm/kvm-all.c102
-rw-r--r--accel/stubs/kvm-stub.c1
-rw-r--r--hw/intc/arm_gicv3_its_common.c3
-rw-r--r--include/sysemu/kvm.h9
-rw-r--r--include/sysemu/kvm_int.h1
-rw-r--r--target/i386/kvm/kvm.c1
6 files changed, 9 insertions, 108 deletions
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index 8eee504225..0c7b0569da 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -99,7 +99,6 @@ bool kvm_gsi_direct_mapping;
bool kvm_allowed;
bool kvm_readonly_mem_allowed;
bool kvm_vm_attributes_allowed;
-bool kvm_direct_msi_allowed;
bool kvm_ioeventfd_any_length_allowed;
bool kvm_msi_use_devid;
bool kvm_has_guest_debug;
@@ -1848,7 +1847,7 @@ static void clear_gsi(KVMState *s, unsigned int gsi)
void kvm_init_irq_routing(KVMState *s)
{
- int gsi_count, i;
+ int gsi_count;
gsi_count = kvm_check_extension(s, KVM_CAP_IRQ_ROUTING) - 1;
if (gsi_count > 0) {
@@ -1860,12 +1859,6 @@ void kvm_init_irq_routing(KVMState *s)
s->irq_routes = g_malloc0(sizeof(*s->irq_routes));
s->nr_allocated_irq_routes = 0;
- if (!kvm_direct_msi_allowed) {
- for (i = 0; i < KVM_MSI_HASHTAB_SIZE; i++) {
- QTAILQ_INIT(&s->msi_hashtab[i]);
- }
- }
-
kvm_arch_init_irq_routing(s);
}
@@ -1985,41 +1978,10 @@ void kvm_irqchip_change_notify(void)
notifier_list_notify(&kvm_irqchip_change_notifiers, NULL);
}
-static unsigned int kvm_hash_msi(uint32_t data)
-{
- /* This is optimized for IA32 MSI layout. However, no other arch shall
- * repeat the mistake of not providing a direct MSI injection API. */
- return data & 0xff;
-}
-
-static void kvm_flush_dynamic_msi_routes(KVMState *s)
-{
- KVMMSIRoute *route, *next;
- unsigned int hash;
-
- for (hash = 0; hash < KVM_MSI_HASHTAB_SIZE; hash++) {
- QTAILQ_FOREACH_SAFE(route, &s->msi_hashtab[hash], entry, next) {
- kvm_irqchip_release_virq(s, route->kroute.gsi);
- QTAILQ_REMOVE(&s->msi_hashtab[hash], route, entry);
- g_free(route);
- }
- }
-}
-
static int kvm_irqchip_get_virq(KVMState *s)
{
int next_virq;
- /*
- * PIC and IOAPIC share the first 16 GSI numbers, thus the available
- * GSI numbers are more than the number of IRQ route. Allocating a GSI
- * number can succeed even though a new route entry cannot be added.
- * When this happens, flush dynamic MSI entries to free IRQ route entries.
- */
- if (!kvm_direct_msi_allowed && s->irq_routes->nr == s->gsi_count) {
- kvm_flush_dynamic_msi_routes(s);
- }
-
/* Return the lowest unused GSI in the bitmap */
next_virq = find_first_zero_bit(s->used_gsi_bitmap, s->gsi_count);
if (next_virq >= s->gsi_count) {
@@ -2029,63 +1991,17 @@ static int kvm_irqchip_get_virq(KVMState *s)
}
}
-static KVMMSIRoute *kvm_lookup_msi_route(KVMState *s, MSIMessage msg)
-{
- unsigned int hash = kvm_hash_msi(msg.data);
- KVMMSIRoute *route;
-
- QTAILQ_FOREACH(route, &s->msi_hashtab[hash], entry) {
- if (route->kroute.u.msi.address_lo == (uint32_t)msg.address &&
- route->kroute.u.msi.address_hi == (msg.address >> 32) &&
- route->kroute.u.msi.data == le32_to_cpu(msg.data)) {
- return route;
- }
- }
- return NULL;
-}
-
int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg)
{
struct kvm_msi msi;
- KVMMSIRoute *route;
-
- if (kvm_direct_msi_allowed) {
- msi.address_lo = (uint32_t)msg.address;
- msi.address_hi = msg.address >> 32;
- msi.data = le32_to_cpu(msg.data);
- msi.flags = 0;
- memset(msi.pad, 0, sizeof(msi.pad));
-
- return kvm_vm_ioctl(s, KVM_SIGNAL_MSI, &msi);
- }
-
- route = kvm_lookup_msi_route(s, msg);
- if (!route) {
- int virq;
- virq = kvm_irqchip_get_virq(s);
- if (virq < 0) {
- return virq;
- }
-
- route = g_new0(KVMMSIRoute, 1);
- route->kroute.gsi = virq;
- route->kroute.type = KVM_IRQ_ROUTING_MSI;
- route->kroute.flags = 0;
- route->kroute.u.msi.address_lo = (uint32_t)msg.address;
- route->kroute.u.msi.address_hi = msg.address >> 32;
- route->kroute.u.msi.data = le32_to_cpu(msg.data);
-
- kvm_add_routing_entry(s, &route->kroute);
- kvm_irqchip_commit_routes(s);
-
- QTAILQ_INSERT_TAIL(&s->msi_hashtab[kvm_hash_msi(msg.data)], route,
- entry);
- }
+ msi.address_lo = (uint32_t)msg.address;
+ msi.address_hi = msg.address >> 32;
+ msi.data = le32_to_cpu(msg.data);
+ msi.flags = 0;
+ memset(msi.pad, 0, sizeof(msi.pad));
- assert(route->kroute.type == KVM_IRQ_ROUTING_MSI);
-
- return kvm_set_irq(s, route->kroute.gsi, 1);
+ return kvm_vm_ioctl(s, KVM_SIGNAL_MSI, &msi);
}
int kvm_irqchip_add_msi_route(KVMRouteChange *c, int vector, PCIDevice *dev)
@@ -2660,10 +2576,6 @@ static int kvm_init(MachineState *ms)
s->max_nested_state_len = kvm_check_extension(s, KVM_CAP_NESTED_STATE);
-#ifdef KVM_CAP_IRQ_ROUTING
- kvm_direct_msi_allowed = (kvm_check_extension(s, KVM_CAP_SIGNAL_MSI) > 0);
-#endif
-
s->intx_set_mask = kvm_check_extension(s, KVM_CAP_PCI_2_3);
s->irq_set_ioctl = KVM_IRQ_LINE;
diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c
index a323252f8e..bce005adad 100644
--- a/accel/stubs/kvm-stub.c
+++ b/accel/stubs/kvm-stub.c
@@ -27,7 +27,6 @@ bool kvm_allowed;
bool kvm_readonly_mem_allowed;
bool kvm_ioeventfd_any_length_allowed;
bool kvm_msi_use_devid;
-bool kvm_direct_msi_allowed;
void kvm_flush_coalesced_mmio_buffer(void)
{
diff --git a/hw/intc/arm_gicv3_its_common.c b/hw/intc/arm_gicv3_its_common.c
index abaf77057e..fddd6d490c 100644
--- a/hw/intc/arm_gicv3_its_common.c
+++ b/hw/intc/arm_gicv3_its_common.c
@@ -163,8 +163,7 @@ type_init(gicv3_its_common_register_types)
const char *its_class_name(void)
{
if (kvm_irqchip_in_kernel()) {
- /* KVM implementation requires this capability */
- return kvm_direct_msi_enabled() ? "arm-its-kvm" : NULL;
+ return "arm-its-kvm";
} else {
/* Software emulation based model */
return "arm-gicv3-its";
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index 97a8a4f201..93dccf5dd9 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -43,7 +43,6 @@ extern bool kvm_msi_via_irqfd_allowed;
extern bool kvm_gsi_routing_allowed;
extern bool kvm_gsi_direct_mapping;
extern bool kvm_readonly_mem_allowed;
-extern bool kvm_direct_msi_allowed;
extern bool kvm_ioeventfd_any_length_allowed;
extern bool kvm_msi_use_devid;
@@ -148,13 +147,6 @@ extern bool kvm_msi_use_devid;
#define kvm_readonly_mem_enabled() (kvm_readonly_mem_allowed)
/**
- * kvm_direct_msi_enabled:
- *
- * Returns: true if KVM allows direct MSI injection.
- */
-#define kvm_direct_msi_enabled() (kvm_direct_msi_allowed)
-
-/**
* kvm_ioeventfd_any_length_enabled:
* Returns: true if KVM allows any length io eventfd.
*/
@@ -181,7 +173,6 @@ extern bool kvm_msi_use_devid;
#define kvm_gsi_routing_allowed() (false)
#define kvm_gsi_direct_mapping() (false)
#define kvm_readonly_mem_enabled() (false)
-#define kvm_direct_msi_enabled() (false)
#define kvm_ioeventfd_any_length_enabled() (false)
#define kvm_msi_devid_required() (false)
diff --git a/include/sysemu/kvm_int.h b/include/sysemu/kvm_int.h
index 075939a3c4..a7dacd12d6 100644
--- a/include/sysemu/kvm_int.h
+++ b/include/sysemu/kvm_int.h
@@ -103,7 +103,6 @@ struct KVMState
int nr_allocated_irq_routes;
unsigned long *used_gsi_bitmap;
unsigned int gsi_count;
- QTAILQ_HEAD(, KVMMSIRoute) msi_hashtab[KVM_MSI_HASHTAB_SIZE];
#endif
KVMMemoryListener memory_listener;
QLIST_HEAD(, KVMParkedVcpu) kvm_parked_vcpus;
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index e7c054cc16..fb6655254f 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -91,6 +91,7 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
KVM_CAP_INFO(SET_TSS_ADDR),
KVM_CAP_INFO(EXT_CPUID),
KVM_CAP_INFO(MP_STATE),
+ KVM_CAP_INFO(SIGNAL_MSI),
KVM_CAP_LAST_INFO
};