Add IRQ status handling in libkvm and use status for RTC interrupt re-injection
PATCH 1/1 Add IRQ status handling in libkvm and use status for RTC interrupt re-injection
Signed-off-by Gleb Natapov <[email protected]>
libkvm/kvm-common.h +2 -0
@@ -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
libkvm/libkvm.c +14 -3
@@ -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 ; }
libkvm/libkvm.h +1 -1
@@ -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,
qemu/hw/apic.c +5 -0
@@ -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);
qemu/hw/i8259.c +8 -3
@@ -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]) {
qemu/hw/pc.h +1 -0
@@ -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 */
qemu/qemu-kvm.c +2 -2
@@ -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
qemu/qemu-kvm.h +1 -1
@@ -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 );
--
Gleb.