aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/kvm/i8259.c5
-rw-r--r--drivers/kvm/irq.h1
-rw-r--r--drivers/kvm/kvm_main.c82
-rw-r--r--include/linux/kvm.h36
4 files changed, 124 insertions, 0 deletions
diff --git a/drivers/kvm/i8259.c b/drivers/kvm/i8259.c
index ee6030dc5c04..a679157bc599 100644
--- a/drivers/kvm/i8259.c
+++ b/drivers/kvm/i8259.c
@@ -119,6 +119,11 @@ static void pic_update_irq(struct kvm_pic *s)
119 s->irq_request(s->irq_request_opaque, 0); 119 s->irq_request(s->irq_request_opaque, 0);
120} 120}
121 121
122void kvm_pic_update_irq(struct kvm_pic *s)
123{
124 pic_update_irq(s);
125}
126
122void kvm_pic_set_irq(void *opaque, int irq, int level) 127void kvm_pic_set_irq(void *opaque, int irq, int level)
123{ 128{
124 struct kvm_pic *s = opaque; 129 struct kvm_pic *s = opaque;
diff --git a/drivers/kvm/irq.h b/drivers/kvm/irq.h
index 6ed856a41e23..4034f6576cd9 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);
59int kvm_pic_read_irq(struct kvm_pic *s); 59int kvm_pic_read_irq(struct kvm_pic *s);
60int kvm_cpu_get_interrupt(struct kvm_vcpu *v); 60int kvm_cpu_get_interrupt(struct kvm_vcpu *v);
61int kvm_cpu_has_interrupt(struct kvm_vcpu *v); 61int kvm_cpu_has_interrupt(struct kvm_vcpu *v);
62void kvm_pic_update_irq(struct kvm_pic *s);
62 63
63#define IOAPIC_NUM_PINS 24 64#define IOAPIC_NUM_PINS 24
64#define IOAPIC_VERSION_ID 0x11 /* IOAPIC version */ 65#define IOAPIC_VERSION_ID 0x11 /* IOAPIC version */
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index 5063b3addbbf..6e2c5f3f33fb 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -897,6 +897,53 @@ out:
897 return r; 897 return r;
898} 898}
899 899
900static int kvm_vm_ioctl_get_irqchip(struct kvm *kvm, struct kvm_irqchip *chip)
901{
902 int r;
903
904 r = 0;
905 switch (chip->chip_id) {
906 case KVM_IRQCHIP_PIC_MASTER:
907 memcpy (&chip->chip.pic,
908 &pic_irqchip(kvm)->pics[0],
909 sizeof(struct kvm_pic_state));
910 break;
911 case KVM_IRQCHIP_PIC_SLAVE:
912 memcpy (&chip->chip.pic,
913 &pic_irqchip(kvm)->pics[1],
914 sizeof(struct kvm_pic_state));
915 break;
916 default:
917 r = -EINVAL;
918 break;
919 }
920 return r;
921}
922
923static int kvm_vm_ioctl_set_irqchip(struct kvm *kvm, struct kvm_irqchip *chip)
924{
925 int r;
926
927 r = 0;
928 switch (chip->chip_id) {
929 case KVM_IRQCHIP_PIC_MASTER:
930 memcpy (&pic_irqchip(kvm)->pics[0],
931 &chip->chip.pic,
932 sizeof(struct kvm_pic_state));
933 break;
934 case KVM_IRQCHIP_PIC_SLAVE:
935 memcpy (&pic_irqchip(kvm)->pics[1],
936 &chip->chip.pic,
937 sizeof(struct kvm_pic_state));
938 break;
939 default:
940 r = -EINVAL;
941 break;
942 }
943 kvm_pic_update_irq(pic_irqchip(kvm));
944 return r;
945}
946
900static gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn) 947static gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn)
901{ 948{
902 int i; 949 int i;
@@ -2835,6 +2882,41 @@ static long kvm_vm_ioctl(struct file *filp,
2835 } 2882 }
2836 break; 2883 break;
2837 } 2884 }
2885 case KVM_GET_IRQCHIP: {
2886 /* 0: PIC master, 1: PIC slave, 2: IOAPIC */
2887 struct kvm_irqchip chip;
2888
2889 r = -EFAULT;
2890 if (copy_from_user(&chip, argp, sizeof chip))
2891 goto out;
2892 r = -ENXIO;
2893 if (!irqchip_in_kernel(kvm))
2894 goto out;
2895 r = kvm_vm_ioctl_get_irqchip(kvm, &chip);
2896 if (r)
2897 goto out;
2898 r = -EFAULT;
2899 if (copy_to_user(argp, &chip, sizeof chip))
2900 goto out;
2901 r = 0;
2902 break;
2903 }
2904 case KVM_SET_IRQCHIP: {
2905 /* 0: PIC master, 1: PIC slave, 2: IOAPIC */
2906 struct kvm_irqchip chip;
2907
2908 r = -EFAULT;
2909 if (copy_from_user(&chip, argp, sizeof chip))
2910 goto out;
2911 r = -ENXIO;
2912 if (!irqchip_in_kernel(kvm))
2913 goto out;
2914 r = kvm_vm_ioctl_set_irqchip(kvm, &chip);
2915 if (r)
2916 goto out;
2917 r = 0;
2918 break;
2919 }
2838 default: 2920 default:
2839 ; 2921 ;
2840 } 2922 }
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index b0a13d1b34cc..6560f11870fd 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -45,6 +45,40 @@ struct kvm_irq_level {
45 __u32 level; 45 __u32 level;
46}; 46};
47 47
48/* for KVM_GET_IRQCHIP / KVM_SET_IRQCHIP */
49struct kvm_pic_state {
50 __u8 last_irr; /* edge detection */
51 __u8 irr; /* interrupt request register */
52 __u8 imr; /* interrupt mask register */
53 __u8 isr; /* interrupt service register */
54 __u8 priority_add; /* highest irq priority */
55 __u8 irq_base;
56 __u8 read_reg_select;
57 __u8 poll;
58 __u8 special_mask;
59 __u8 init_state;
60 __u8 auto_eoi;
61 __u8 rotate_on_auto_eoi;
62 __u8 special_fully_nested_mode;
63 __u8 init4; /* true if 4 byte init */
64 __u8 elcr; /* PIIX edge/trigger selection */
65 __u8 elcr_mask;
66};
67
68enum kvm_irqchip_id {
69 KVM_IRQCHIP_PIC_MASTER = 0,
70 KVM_IRQCHIP_PIC_SLAVE = 1,
71};
72
73struct kvm_irqchip {
74 __u32 chip_id;
75 __u32 pad;
76 union {
77 char dummy[512]; /* reserving space */
78 struct kvm_pic_state pic;
79 } chip;
80};
81
48enum kvm_exit_reason { 82enum kvm_exit_reason {
49 KVM_EXIT_UNKNOWN = 0, 83 KVM_EXIT_UNKNOWN = 0,
50 KVM_EXIT_EXCEPTION = 1, 84 KVM_EXIT_EXCEPTION = 1,
@@ -299,6 +333,8 @@ struct kvm_signal_mask {
299/* Device model IOC */ 333/* Device model IOC */
300#define KVM_CREATE_IRQCHIP _IO(KVMIO, 0x60) 334#define KVM_CREATE_IRQCHIP _IO(KVMIO, 0x60)
301#define KVM_IRQ_LINE _IOW(KVMIO, 0x61, struct kvm_irq_level) 335#define KVM_IRQ_LINE _IOW(KVMIO, 0x61, struct kvm_irq_level)
336#define KVM_GET_IRQCHIP _IOWR(KVMIO, 0x62, struct kvm_irqchip)
337#define KVM_SET_IRQCHIP _IOR(KVMIO, 0x63, struct kvm_irqchip)
302 338
303/* 339/*
304 * ioctls for vcpu fds 340 * ioctls for vcpu fds