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

Attachment: live_k1.patch
Description: live_k1.patch

Attachment: 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

Reply via email to