summaryrefslogtreecommitdiff
path: root/drivers/kvm
diff options
context:
space:
mode:
authorHe, Qing <qing.he@intel.com>2007-07-26 08:05:18 (GMT)
committerAvi Kivity <avi@qumranet.com>2007-10-13 08:18:25 (GMT)
commit6ceb9d791eeeb0a5493958f5d6d4dc7d91e59cf7 (patch)
tree8cef21acf9346fdbea36075029dc007fe969b51e /drivers/kvm
parent9cf98828d12285d1fb43e774c8c100a55f8f34e1 (diff)
downloadlinux-6ceb9d791eeeb0a5493958f5d6d4dc7d91e59cf7.tar.xz
KVM: Add get/set irqchip ioctls for in-kernel PIC live migration support
This patch adds two new ioctls to dump and write kernel irqchips for save/restore and live migration. PIC s/r and l/m is implemented in this patch. Signed-off-by: Yaozu (Eddie) Dong <eddie.dong@intel.com> Signed-off-by: Qing He <qing.he@intel.com> Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm')
-rw-r--r--drivers/kvm/i8259.c5
-rw-r--r--drivers/kvm/irq.h1
-rw-r--r--drivers/kvm/kvm_main.c82
3 files changed, 88 insertions, 0 deletions
diff --git a/drivers/kvm/i8259.c b/drivers/kvm/i8259.c
index ee6030d..a679157 100644
--- a/drivers/kvm/i8259.c
+++ b/drivers/kvm/i8259.c
@@ -119,6 +119,11 @@ static void pic_update_irq(struct kvm_pic *s)
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)
{
struct kvm_pic *s = opaque;
diff --git a/drivers/kvm/irq.h b/drivers/kvm/irq.h
index 6ed856a..4034f65 100644
--- a/drivers/kvm/irq.h
+++ b/drivers/kvm/irq.h
@@ -59,6 +59,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 */
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index 5063b3a..6e2c5f3 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -897,6 +897,53 @@ 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],
+ sizeof(struct kvm_pic_state));
+ break;
+ case KVM_IRQCHIP_PIC_SLAVE:
+ memcpy (&chip->chip.pic,
+ &pic_irqchip(kvm)->pics[1],
+ sizeof(struct kvm_pic_state));
+ 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,
+ sizeof(struct kvm_pic_state));
+ break;
+ case KVM_IRQCHIP_PIC_SLAVE:
+ memcpy (&pic_irqchip(kvm)->pics[1],
+ &chip->chip.pic,
+ sizeof(struct kvm_pic_state));
+ 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;
@@ -2835,6 +2882,41 @@ 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 = -ENXIO;
+ if (!irqchip_in_kernel(kvm))
+ goto out;
+ r = kvm_vm_ioctl_get_irqchip(kvm, &chip);
+ if (r)
+ goto out;
+ r = -EFAULT;
+ if (copy_to_user(argp, &chip, sizeof chip))
+ 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 = -ENXIO;
+ if (!irqchip_in_kernel(kvm))
+ goto out;
+ r = kvm_vm_ioctl_set_irqchip(kvm, &chip);
+ if (r)
+ goto out;
+ r = 0;
+ break;
+ }
default:
;
}