From patchwork Fri Feb 26 20:12:21 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Glauber Costa X-Patchwork-Id: 82446 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o1QKD36i019498 for ; Fri, 26 Feb 2010 20:13:05 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S966016Ab0BZUMm (ORCPT ); Fri, 26 Feb 2010 15:12:42 -0500 Received: from mx1.redhat.com ([209.132.183.28]:5580 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S965998Ab0BZUMj (ORCPT ); Fri, 26 Feb 2010 15:12:39 -0500 Received: from int-mx03.intmail.prod.int.phx2.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.16]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o1QKCcJp005998 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Fri, 26 Feb 2010 15:12:38 -0500 Received: from localhost.localdomain (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx03.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o1QKCMPT012766; Fri, 26 Feb 2010 15:12:37 -0500 From: Glauber Costa To: kvm@vger.kernel.org Cc: mtosatti@redhat.com Subject: [PATCH 10/10] Do GSI routing Date: Fri, 26 Feb 2010 17:12:21 -0300 Message-Id: <1267215141-13629-11-git-send-email-glommer@redhat.com> In-Reply-To: <1267215141-13629-10-git-send-email-glommer@redhat.com> References: <1267215141-13629-1-git-send-email-glommer@redhat.com> <1267215141-13629-2-git-send-email-glommer@redhat.com> <1267215141-13629-3-git-send-email-glommer@redhat.com> <1267215141-13629-4-git-send-email-glommer@redhat.com> <1267215141-13629-5-git-send-email-glommer@redhat.com> <1267215141-13629-6-git-send-email-glommer@redhat.com> <1267215141-13629-7-git-send-email-glommer@redhat.com> <1267215141-13629-8-git-send-email-glommer@redhat.com> <1267215141-13629-9-git-send-email-glommer@redhat.com> <1267215141-13629-10-git-send-email-glommer@redhat.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.16 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Fri, 26 Feb 2010 20:13:05 +0000 (UTC) diff --git a/kvm-all.c b/kvm-all.c index 3038465..5c4151f 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -71,6 +71,8 @@ struct KVMState #endif int irqchip_in_kernel; int pit_in_kernel; + + KVMArchState *arch_state; }; static KVMState *kvm_state; @@ -627,6 +629,7 @@ int kvm_init(int smp_cpus) s = qemu_mallocz(sizeof(KVMState)); + kvm_state = s; #ifdef KVM_CAP_SET_GUEST_DEBUG QTAILQ_INIT(&s->kvm_sw_breakpoints); #endif @@ -710,7 +713,6 @@ int kvm_init(int smp_cpus) if (ret < 0) goto err; - kvm_state = s; cpu_register_phys_memory_client(&kvm_cpu_phys_memory_client); return 0; diff --git a/kvm.h b/kvm.h index 480e651..14d6e91 100644 --- a/kvm.h +++ b/kvm.h @@ -70,7 +70,10 @@ int kvm_set_irq(int irq, int level, int *status); /* internal API */ struct KVMState; +struct KVMArchState; + typedef struct KVMState KVMState; +typedef struct KVMArchState KVMArchState; int kvm_ioctl(KVMState *s, int type, ...); diff --git a/target-i386/kvm.c b/target-i386/kvm.c index e9a7585..58b1551 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -45,6 +45,16 @@ #ifdef KVM_CAP_EXT_CPUID +struct KVMArchState +{ + struct kvm_irq_routing *irq_routes; + int nr_allocated_irq_routes; + void *used_gsi_bitmap; + int max_gsi; +}; + +static KVMArchState *kvm_arch_state; + static struct kvm_cpuid2 *try_get_cpuid(KVMState *s, int max) { struct kvm_cpuid2 *cpuid; @@ -340,10 +350,118 @@ static int kvm_has_msr_star(CPUState *env) return 0; } +/* + * Setup x86 specific IRQ routing + */ +static inline void set_gsi(KVMArchState *s, unsigned int gsi) +{ + uint32_t *bitmap = s->used_gsi_bitmap; + + if (gsi < s->max_gsi) + bitmap[gsi / 32] |= 1U << (gsi % 32); + else + fprintf(stderr, "Invalid GSI %d\n", gsi); +} + +static int kvm_add_routing_entry(KVMArchState *s, struct kvm_irq_routing_entry *entry) +{ + struct kvm_irq_routing *z; + struct kvm_irq_routing_entry *new; + int n, size; + + if (s->irq_routes->nr == s->nr_allocated_irq_routes) { + n = s->nr_allocated_irq_routes * 2; + if (n < 64) + n = 64; + size = sizeof(struct kvm_irq_routing); + size += n * sizeof(*new); + z = realloc(s->irq_routes, size); + if (!z) + return -ENOMEM; + s->nr_allocated_irq_routes = n; + s->irq_routes = z; + } + n = s->irq_routes->nr++; + new = &s->irq_routes->entries[n]; + memset(new, 0, sizeof(*new)); + new->gsi = entry->gsi; + new->type = entry->type; + new->flags = entry->flags; + new->u = entry->u; + + set_gsi(s, entry->gsi); + + return 0; +} + +static int kvm_add_irq_route(KVMArchState *s, int gsi, int irqchip, int pin) +{ + struct kvm_irq_routing_entry e; + + e.gsi = gsi; + e.type = KVM_IRQ_ROUTING_IRQCHIP; + e.flags = 0; + e.u.irqchip.irqchip = irqchip; + e.u.irqchip.pin = pin; + return kvm_add_routing_entry(s, &e); +} + +static int kvm_init_irq_routing(KVMState *s) +{ + int i, r; + int gsi_count, gsi_bits; + + gsi_count = kvm_check_extension(s, KVM_CAP_IRQ_ROUTING); + if (!kvm_irqchip_in_kernel() && (gsi_count > 0)) { + return 0; + } + + /* Round up so we can search ints using ffs */ + gsi_bits = ((gsi_count - 31) & ~31); + kvm_arch_state->used_gsi_bitmap = qemu_mallocz(gsi_bits / 8); + kvm_arch_state->max_gsi = gsi_bits; + + /* Mark any over-allocated bits as already in use */ + for (i = gsi_count; i < gsi_bits; i++) { + set_gsi(kvm_arch_state, i); + } + + kvm_arch_state->irq_routes->nr = 0; + + for (i = 0; i < 8; ++i) { + if (i == 2) + continue; + r = kvm_add_irq_route(kvm_arch_state, i, KVM_IRQCHIP_PIC_MASTER, i); + if (r < 0) + return r; + } + for (i = 8; i < 16; ++i) { + r = kvm_add_irq_route(kvm_arch_state, i, KVM_IRQCHIP_PIC_SLAVE, i - 8); + if (r < 0) + return r; + } + for (i = 0; i < 24; ++i) { + if (i == 0) { + r = kvm_add_irq_route(kvm_arch_state, i, KVM_IRQCHIP_IOAPIC, 2); + } else if (i != 2) { + r = kvm_add_irq_route(kvm_arch_state, i, KVM_IRQCHIP_IOAPIC, i); + } + if (r < 0) + return r; + } + + kvm_arch_state->irq_routes->flags = 0; + return kvm_vm_ioctl(s, KVM_SET_GSI_ROUTING, kvm_arch_state->irq_routes); +} int kvm_arch_init(KVMState *s, int smp_cpus) { int ret; + kvm_arch_state = qemu_mallocz(sizeof(*kvm_arch_state)); + kvm_arch_state->irq_routes = qemu_mallocz(sizeof(*kvm_arch_state->irq_routes)); + + kvm_init_irq_routing(s); + /* create vm86 tss. KVM uses vm86 mode to emulate 16-bit code * directly. In order to use vm86 mode, a TSS is needed. Since this * must be part of guest physical memory, we need to allocate it. Older