From patchwork Wed Dec 2 13:46:15 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Glauber Costa X-Patchwork-Id: 40068 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 B4E27B7BE3 for ; Thu, 3 Dec 2009 03:30:47 +1100 (EST) Received: from localhost ([127.0.0.1]:33632 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NFs6C-00062l-Ew for incoming@patchwork.ozlabs.org; Wed, 02 Dec 2009 11:30:40 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NFpXT-0004mO-Mu for qemu-devel@nongnu.org; Wed, 02 Dec 2009 08:46:39 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1NFpXN-0004ce-M8 for qemu-devel@nongnu.org; Wed, 02 Dec 2009 08:46:37 -0500 Received: from [199.232.76.173] (port=58102 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NFpXM-0004bU-P9 for qemu-devel@nongnu.org; Wed, 02 Dec 2009 08:46:32 -0500 Received: from mx1.redhat.com ([209.132.183.28]:62473) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1NFpXL-00042q-UG for qemu-devel@nongnu.org; Wed, 02 Dec 2009 08:46:32 -0500 Received: from int-mx05.intmail.prod.int.phx2.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.18]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id nB2DkU5Q006357 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 2 Dec 2009 08:46:31 -0500 Received: from localhost.localdomain (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx05.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id nB2DkGtc025779; Wed, 2 Dec 2009 08:46:29 -0500 From: Glauber Costa To: qemu-devel@nongnu.org Date: Wed, 2 Dec 2009 11:46:15 -0200 Message-Id: <1259761575-3953-10-git-send-email-glommer@redhat.com> In-Reply-To: <1259761575-3953-9-git-send-email-glommer@redhat.com> References: <1259761575-3953-1-git-send-email-glommer@redhat.com> <1259761575-3953-2-git-send-email-glommer@redhat.com> <1259761575-3953-3-git-send-email-glommer@redhat.com> <1259761575-3953-4-git-send-email-glommer@redhat.com> <1259761575-3953-5-git-send-email-glommer@redhat.com> <1259761575-3953-6-git-send-email-glommer@redhat.com> <1259761575-3953-7-git-send-email-glommer@redhat.com> <1259761575-3953-8-git-send-email-glommer@redhat.com> <1259761575-3953-9-git-send-email-glommer@redhat.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.18 X-detected-operating-system: by monty-python.gnu.org: Genre and OS details not recognized. Cc: aliguori@us.ibm.com, avi@redhat.com Subject: [Qemu-devel] [PATCH 9/9] 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 0c6aba7..a5739c4 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; @@ -522,12 +524,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 cb896e3..15fb34a 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 a908819..7e1ce15 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -37,6 +37,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; @@ -272,10 +282,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