From patchwork Fri Nov 6 18:26:30 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Glauber Costa X-Patchwork-Id: 37883 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 88374B7063 for ; Sat, 7 Nov 2009 05:45:41 +1100 (EST) Received: from localhost ([127.0.0.1]:44150 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1N6ToY-0005Z8-Ls for incoming@patchwork.ozlabs.org; Fri, 06 Nov 2009 13:45:38 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1N6TWQ-0000RJ-9H for qemu-devel@nongnu.org; Fri, 06 Nov 2009 13:26:54 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1N6TWH-0000CY-Am for qemu-devel@nongnu.org; Fri, 06 Nov 2009 13:26:50 -0500 Received: from [199.232.76.173] (port=44869 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1N6TWH-0000Bh-2n for qemu-devel@nongnu.org; Fri, 06 Nov 2009 13:26:45 -0500 Received: from mx1.redhat.com ([209.132.183.28]:10728) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1N6TWF-0001js-RP for qemu-devel@nongnu.org; Fri, 06 Nov 2009 13:26:44 -0500 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id nA6IQgGi010430; Fri, 6 Nov 2009 13:26:43 -0500 Received: from localhost.localdomain (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id nA6IQUhc029342; Fri, 6 Nov 2009 13:26:42 -0500 From: Glauber Costa To: qemu-devel@nongnu.org Date: Fri, 6 Nov 2009 16:26:30 -0200 Message-Id: <1257531990-19437-9-git-send-email-glommer@redhat.com> In-Reply-To: <1257531990-19437-8-git-send-email-glommer@redhat.com> References: <1257531990-19437-1-git-send-email-glommer@redhat.com> <1257531990-19437-2-git-send-email-glommer@redhat.com> <1257531990-19437-3-git-send-email-glommer@redhat.com> <1257531990-19437-4-git-send-email-glommer@redhat.com> <1257531990-19437-5-git-send-email-glommer@redhat.com> <1257531990-19437-6-git-send-email-glommer@redhat.com> <1257531990-19437-7-git-send-email-glommer@redhat.com> <1257531990-19437-8-git-send-email-glommer@redhat.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 X-detected-operating-system: by monty-python.gnu.org: Genre and OS details not recognized. Cc: aliguori@us.ibm.com Subject: [Qemu-devel] [PATCH 8/8] Do GSI routing X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org To follow correctly what our bios ACPI tables say, we have to be able to program our irqchips with GSI routing mappings. This support is already in qemu-kvm Signed-off-by: Glauber Costa --- kvm-all.c | 6 ++- kvm.h | 3 + target-i386/kvm.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+), 2 deletions(-) diff --git a/kvm-all.c b/kvm-all.c index 94b07bf..9a2667a 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -66,6 +66,8 @@ struct KVMState #endif int irqchip_in_kernel; int pit_in_kernel; + + KVMArchState *arch_state; }; static KVMState *kvm_state; @@ -559,12 +561,12 @@ int kvm_init(int smp_cpus) if (ret < 0) goto err; + kvm_state = s; + ret = kvm_arch_init(s, smp_cpus); if (ret < 0) goto err; - kvm_state = s; - return 0; err: diff --git a/kvm.h b/kvm.h index f0c9201..07e1b77 100644 --- a/kvm.h +++ b/kvm.h @@ -72,7 +72,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 842cd00..495a466 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -36,6 +36,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; @@ -266,10 +276,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