diff options
author | He, Qing <qing.he@intel.com> | 2007-07-26 08:05:18 (GMT) |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2007-10-13 08:18:25 (GMT) |
commit | 6ceb9d791eeeb0a5493958f5d6d4dc7d91e59cf7 (patch) | |
tree | 8cef21acf9346fdbea36075029dc007fe969b51e /drivers/kvm | |
parent | 9cf98828d12285d1fb43e774c8c100a55f8f34e1 (diff) | |
download | linux-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.c | 5 | ||||
-rw-r--r-- | drivers/kvm/irq.h | 1 | ||||
-rw-r--r-- | drivers/kvm/kvm_main.c | 82 |
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: ; } |