From patchwork Wed Jan 21 12:37:19 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gleb Natapov X-Patchwork-Id: 3444 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n0LCYaWv013828 for ; Wed, 21 Jan 2009 04:34:36 -0800 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758117AbZAUMjL (ORCPT ); Wed, 21 Jan 2009 07:39:11 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1758134AbZAUMjL (ORCPT ); Wed, 21 Jan 2009 07:39:11 -0500 Received: from mx2.redhat.com ([66.187.237.31]:48582 "EHLO mx2.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758117AbZAUMjK (ORCPT ); Wed, 21 Jan 2009 07:39:10 -0500 Received: from int-mx2.corp.redhat.com (int-mx2.corp.redhat.com [172.16.27.26]) by mx2.redhat.com (8.13.8/8.13.8) with ESMTP id n0LCd9Kl008119 for ; Wed, 21 Jan 2009 07:39:09 -0500 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx2.corp.redhat.com (8.13.1/8.13.1) with ESMTP id n0LCd90f030796; Wed, 21 Jan 2009 07:39:10 -0500 Received: from dhcp-1-237.tlv.redhat.com (dhcp-1-237.tlv.redhat.com [10.35.1.237]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id n0LCd7Ji015233; Wed, 21 Jan 2009 07:39:08 -0500 Received: by dhcp-1-237.tlv.redhat.com (Postfix, from userid 587) id B3A6018D43A; Wed, 21 Jan 2009 14:37:19 +0200 (IST) Date: Wed, 21 Jan 2009 14:37:19 +0200 From: Gleb Natapov To: Avi Kivity Cc: kvm@vger.kernel.org Subject: [PATCH] Add IRQ status handling in libkvm and use status for RTC interrupt re-injection Message-ID: <20090121123719.GJ27675@redhat.com> MIME-Version: 1.0 Content-Disposition: inline X-Scanned-By: MIMEDefang 2.58 on 172.16.27.26 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Signed-off-by: Gleb Natapov --- Gleb. -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/libkvm/kvm-common.h b/libkvm/kvm-common.h index d4fffbe..de1ada2 100644 --- a/libkvm/kvm-common.h +++ b/libkvm/kvm-common.h @@ -55,6 +55,8 @@ struct kvm_context { int no_irqchip_creation; /// in-kernel irqchip status int irqchip_in_kernel; + /// ioctl to use to inject interrupts + int irqchip_inject_ioctl; /// do not create in-kernel pit if set int no_pit_creation; /// in-kernel pit status diff --git a/libkvm/libkvm.c b/libkvm/libkvm.c index 80300c9..9f15f32 100644 --- a/libkvm/libkvm.c +++ b/libkvm/libkvm.c @@ -435,8 +435,16 @@ void kvm_create_irqchip(kvm_context_t kvm) r = ioctl(kvm->fd, KVM_CHECK_EXTENSION, KVM_CAP_IRQCHIP); if (r > 0) { /* kernel irqchip supported */ r = ioctl(kvm->vm_fd, KVM_CREATE_IRQCHIP); - if (r >= 0) + if (r >= 0) { + kvm->irqchip_inject_ioctl = KVM_IRQ_LINE; +#if defined(KVM_CAP_IRQ_INJECT_STATUS) && defined(KVM_IRQ_LINE_STATUS) + r = ioctl(kvm->fd, KVM_CHECK_EXTENSION, + KVM_CAP_IRQ_INJECT_STATUS); + if (r > 0) + kvm->irqchip_inject_ioctl = KVM_IRQ_LINE_STATUS; +#endif kvm->irqchip_in_kernel = 1; + } else fprintf(stderr, "Create kernel PIC irqchip failed\n"); } @@ -646,7 +654,7 @@ int kvm_get_dirty_pages_range(kvm_context_t kvm, unsigned long phys_addr, #ifdef KVM_CAP_IRQCHIP -int kvm_set_irq_level(kvm_context_t kvm, int irq, int level) +int kvm_set_irq_level(kvm_context_t kvm, int irq, int level, int *status) { struct kvm_irq_level event; int r; @@ -655,9 +663,12 @@ int kvm_set_irq_level(kvm_context_t kvm, int irq, int level) return 0; event.level = level; event.irq = irq; - r = ioctl(kvm->vm_fd, KVM_IRQ_LINE, &event); + r = ioctl(kvm->vm_fd, kvm->irqchip_inject_ioctl, &event); if (r == -1) perror("kvm_set_irq_level"); + + *status = (kvm->irqchip_inject_ioctl == KVM_IRQ_LINE) ? 1 : event.status; + return 1; } diff --git a/libkvm/libkvm.h b/libkvm/libkvm.h index e79e4fd..f047086 100644 --- a/libkvm/libkvm.h +++ b/libkvm/libkvm.h @@ -525,7 +525,7 @@ int kvm_get_mem_map_range(kvm_context_t kvm, unsigned long phys_addr, unsigned long len, void *buf, void *opaque, int (*cb)(unsigned long start,unsigned long len, void* bitmap, void* opaque)); -int kvm_set_irq_level(kvm_context_t kvm, int irq, int level); +int kvm_set_irq_level(kvm_context_t kvm, int irq, int level, int *status); int kvm_dirty_pages_log_enable_slot(kvm_context_t kvm, uint64_t phys_start, diff --git a/qemu/hw/apic.c b/qemu/hw/apic.c index 782b398..b5dd1d5 100644 --- a/qemu/hw/apic.c +++ b/qemu/hw/apic.c @@ -377,6 +377,11 @@ int apic_get_irq_delivered(void) return apic_irq_delivered; } +int apic_set_irq_delivered(void) +{ + apic_irq_delivered = 1; +} + static void apic_set_irq(APICState *s, int vector_num, int trigger_mode) { apic_irq_delivered += !get_bit(s->irr, vector_num); diff --git a/qemu/hw/i8259.c b/qemu/hw/i8259.c index 6d41a5e..9da4360 100644 --- a/qemu/hw/i8259.c +++ b/qemu/hw/i8259.c @@ -186,9 +186,14 @@ static void i8259_set_irq(void *opaque, int irq, int level) { PicState2 *s = opaque; #ifdef KVM_CAP_IRQCHIP - if (kvm_enabled()) - if (kvm_set_irq(irq, level)) - return; + if (kvm_enabled()) { + int pic_ret; + if (kvm_set_irq(irq, level, &pic_ret)) { + if (pic_ret != 0) + apic_set_irq_delivered(); + return; + } + } #endif #if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT) if (level != irq_level[irq]) { diff --git a/qemu/hw/pc.h b/qemu/hw/pc.h index 54f865d..e637390 100644 --- a/qemu/hw/pc.h +++ b/qemu/hw/pc.h @@ -48,6 +48,7 @@ IOAPICState *ioapic_init(void); void ioapic_set_irq(void *opaque, int vector, int level); void apic_reset_irq_delivered(void); int apic_get_irq_delivered(void); +int apic_set_irq_delivered(void); /* i8254.c */ diff --git a/qemu/qemu-kvm.c b/qemu/qemu-kvm.c index 5ff63ad..9b2d516 100644 --- a/qemu/qemu-kvm.c +++ b/qemu/qemu-kvm.c @@ -1266,9 +1266,9 @@ int kvm_get_phys_ram_page_bitmap(unsigned char *bitmap) #ifdef KVM_CAP_IRQCHIP -int kvm_set_irq(int irq, int level) +int kvm_set_irq(int irq, int level, int *status) { - return kvm_set_irq_level(kvm_context, irq, level); + return kvm_set_irq_level(kvm_context, irq, level, status); } #endif diff --git a/qemu/qemu-kvm.h b/qemu/qemu-kvm.h index 042dd93..755b351 100644 --- a/qemu/qemu-kvm.h +++ b/qemu/qemu-kvm.h @@ -31,7 +31,7 @@ int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap); int kvm_qemu_init_env(CPUState *env); int kvm_qemu_check_extension(int ext); void kvm_apic_init(CPUState *env); -int kvm_set_irq(int irq, int level); +int kvm_set_irq(int irq, int level, int *status); int kvm_physical_memory_set_dirty_tracking(int enable); int kvm_update_dirty_pages_log(void);