This patch is only for idea collection so far. The dilemma is that how to export the pic/IOAPIC/apic state data structure to user and make sure it has same/similar structure in user level. Otherwise a convert is a must and we must maintain the converter.
With this, PIC only guest can do live migration successfully. We can extend APIC side seamlessly. BTW, there is potential issue in IDT_Vectoring. The fix IMO is to retry vm_stop at user level to make sure no pending IDT_vectoring. Pls comments. Also I will temply off this week, Qing He may continue. Thx,eddie diff --git a/drivers/kvm/i8259.c b/drivers/kvm/i8259.c index 4237e17..17b836d 100644 --- a/drivers/kvm/i8259.c +++ b/drivers/kvm/i8259.c @@ -115,6 +115,13 @@ static void pic_update_irq(struct kvm_pic *s) irq = pic_get_irq(&s->pics[0]); if (irq >= 0) s->irq_request(s->irq_request_opaque, 1); + else + s->irq_request(s->irq_request_opaque, 0); +} + +void kvm_pic_update_irq(struct kvm_pic *s) +{ + pic_update_irq(s); } void kvm_pic_set_irq(void *opaque, int irq, int level) diff --git a/drivers/kvm/irq.h b/drivers/kvm/irq.h index 6cfc19f..217e969 100644 --- a/drivers/kvm/irq.h +++ b/drivers/kvm/irq.h @@ -26,25 +26,6 @@ typedef void irq_request_func(void *opaque, int level); -struct kvm_pic_state { - u8 last_irr; /* edge detection */ - u8 irr; /* interrupt request register */ - u8 imr; /* interrupt mask register */ - u8 isr; /* interrupt service register */ - u8 priority_add; /* highest irq priority */ - u8 irq_base; - u8 read_reg_select; - u8 poll; - u8 special_mask; - u8 init_state; - u8 auto_eoi; - u8 rotate_on_auto_eoi; - u8 special_fully_nested_mode; - u8 init4; /* true if 4 byte init */ - u8 elcr; /* PIIX edge/trigger selection */ - u8 elcr_mask; - struct kvm_pic *pics_state; -}; struct kvm_pic { struct kvm_pic_state pics[2]; /* 0 is master pic, 1 is slave pic */ @@ -59,6 +40,7 @@ void kvm_pic_set_irq(void *opaque, int irq, int level); int kvm_pic_read_irq(struct kvm_pic *s); int kvm_cpu_get_interrupt(struct kvm_vcpu *v); int kvm_cpu_has_interrupt(struct kvm_vcpu *v); +void kvm_pic_update_irq(struct kvm_pic *s); #define IOAPIC_NUM_PINS 24 #define IOAPIC_VERSION_ID 0x11 /* IOAPIC version */ @@ -79,11 +61,8 @@ int kvm_cpu_has_interrupt(struct kvm_vcpu *v); #define IOAPIC_REG_ARB_ID 0x02 /* x86 IOAPIC only */ struct kvm_ioapic { - struct kvm_io_device dev; - unsigned long base_address; - struct kvm *kvm; - u32 ioregsel; u32 id; + u32 ioregsel; u32 irr; union ioapic_redir_entry { u64 bits; @@ -101,6 +80,9 @@ struct kvm_ioapic { u8 dest_id; } fields; } redirtbl[IOAPIC_NUM_PINS]; + struct kvm_io_device dev; + unsigned long base_address; + struct kvm *kvm; }; struct kvm_lapic { diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index 0c75fef..805ca47 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c @@ -935,6 +935,57 @@ out: return r; } +static int kvm_vm_ioctl_get_irqchip(struct kvm *kvm, struct kvm_irqchip *chip) +{ + int r; + + r = 0; + switch (chip->chip_id) { + case KVM_IRQCHIP_PIC_MASTER: + memcpy (&chip->chip.pic, + &pic_irqchip(kvm)->pics[0], + KVM_IRQCHIP_SAVE_LEN); + break; + case KVM_IRQCHIP_PIC_SLAVE: + memcpy (&chip->chip.pic, + &pic_irqchip(kvm)->pics[1], + KVM_IRQCHIP_SAVE_LEN); + break; + case KVM_IRQCHIP_IOAPIC: + break; + default: + r = -EINVAL; + break; + } + return r; +} + +static int kvm_vm_ioctl_set_irqchip(struct kvm *kvm, struct kvm_irqchip *chip) +{ + int r; + + r = 0; + switch (chip->chip_id) { + case KVM_IRQCHIP_PIC_MASTER: + memcpy (&pic_irqchip(kvm)->pics[0], + &chip->chip.pic, + KVM_IRQCHIP_SAVE_LEN); + break; + case KVM_IRQCHIP_PIC_SLAVE: + memcpy (&pic_irqchip(kvm)->pics[1], + &chip->chip.pic, + KVM_IRQCHIP_SAVE_LEN); + break; + case KVM_IRQCHIP_IOAPIC: + break; + default: + r = -EINVAL; + break; + } + kvm_pic_update_irq(pic_irqchip(kvm)); + return r; +} + static gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn) { int i; @@ -2896,6 +2947,35 @@ static long kvm_vm_ioctl(struct file *filp, } break; } + case KVM_GET_IRQCHIP: { + /* 0: PIC master, 1: PIC slave, 2: IOAPIC */ + struct kvm_irqchip chip; + + r = -EFAULT; + if (copy_from_user(&chip, argp, sizeof chip)) + goto out; + r = kvm_vm_ioctl_get_irqchip(kvm, &chip); + if (r) + goto out; + r = -EFAULT; + if (copy_to_user(argp, &chip, sizeof chip - sizeof(void *))) + goto out; + r = 0; + break; + } + case KVM_SET_IRQCHIP: { + /* 0: PIC master, 1: PIC slave, 2: IOAPIC */ + struct kvm_irqchip chip; + + r = -EFAULT; + if (copy_from_user(&chip, argp, sizeof chip)) + goto out; + r = kvm_vm_ioctl_set_irqchip(kvm, &chip); + if (r) + goto out; + r = 0; + break; + } default: ; } diff --git a/include/linux/kvm.h b/include/linux/kvm.h index 5307ba3..4eee80d 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h @@ -51,6 +51,44 @@ struct kvm_irq_level { __u32 level; }; +/* for KVM_GET_IRQCHIP / KVM_SET_IRQCHIP */ +struct kvm_pic_state { + __u8 last_irr; /* edge detection */ + __u8 irr; /* interrupt request register */ + __u8 imr; /* interrupt mask register */ + __u8 isr; /* interrupt service register */ + __u8 priority_add; /* highest irq priority */ + __u8 irq_base; + __u8 read_reg_select; + __u8 poll; + __u8 special_mask; + __u8 init_state; + __u8 auto_eoi; + __u8 rotate_on_auto_eoi; + __u8 special_fully_nested_mode; + __u8 init4; /* true if 4 byte init */ + __u8 elcr; /* PIIX edge/trigger selection */ + __u8 elcr_mask; + struct kvm_pic *pics_state; +}; +#define KVM_IRQCHIP_SAVE_LEN \ + (sizeof(struct kvm_pic_state) - sizeof(struct kvm_pic *)) + +struct kvm_irqchip { + __u8 chip_id; + __u8 pad1; + __u16 pad2; + union { + struct kvm_pic_state pic; + } chip; +}; + +enum kvm_irqchip_id { + KVM_IRQCHIP_PIC_MASTER = 0, + KVM_IRQCHIP_PIC_SLAVE = 1, + KVM_IRQCHIP_IOAPIC = 2, +}; + enum kvm_exit_reason { KVM_EXIT_UNKNOWN = 0, KVM_EXIT_EXCEPTION = 1, @@ -304,6 +342,8 @@ struct kvm_signal_mask { /* Device model IOC */ #define KVM_CREATE_PIC _IO(KVMIO, 0x60) #define KVM_IRQ_LINE _IOW(KVMIO, 0x61, struct kvm_irq_level) +#define KVM_GET_IRQCHIP _IOWR(KVMIO, 0x62, struct kvm_irqchip) +#define KVM_SET_IRQCHIP _IOR(KVMIO, 0x63, struct kvm_irqchip) /* * ioctls for vcpu fds @@ -322,5 +362,7 @@ struct kvm_signal_mask { #define KVM_SET_SIGNAL_MASK _IOW(KVMIO, 0x8b, struct kvm_signal_mask) #define KVM_GET_FPU _IOR(KVMIO, 0x8c, struct kvm_fpu) #define KVM_SET_FPU _IOW(KVMIO, 0x8d, struct kvm_fpu) +#define KVM_GET_LAPIC _IOW(KVMIO, 0x8e, struct kvm_lapic) +#define KVM_SET_LAPIC _IOW(KVMIO, 0x8f, struct kvm_lapic) #endif
live_k1.patch
Description: live_k1.patch
live_u1.patch
Description: live_u1.patch
------------------------------------------------------------------------- This SF.net email is sponsored by: Splunk Inc. Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________ kvm-devel mailing list kvm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/kvm-devel