aboutsummaryrefslogtreecommitdiff
path: root/accel/kvm
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 /accel/kvm
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>
Diffstat (limited to 'accel/kvm')
-rw-r--r--accel/kvm/kvm-all.c102
1 files changed, 7 insertions, 95 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;