Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6ceb9d79 authored by He, Qing's avatar He, Qing Committed by Avi Kivity
Browse files

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: default avatarYaozu (Eddie) Dong <eddie.dong@intel.com>
Signed-off-by: default avatarQing He <qing.he@intel.com>
Signed-off-by: default avatarAvi Kivity <avi@qumranet.com>
parent 9cf98828
Loading
Loading
Loading
Loading
+5 −0
Original line number Original line Diff line number Diff line
@@ -119,6 +119,11 @@ static void pic_update_irq(struct kvm_pic *s)
		s->irq_request(s->irq_request_opaque, 0);
		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)
void kvm_pic_set_irq(void *opaque, int irq, int level)
{
{
	struct kvm_pic *s = opaque;
	struct kvm_pic *s = opaque;
+1 −0
Original line number Original line Diff line number Diff line
@@ -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_pic_read_irq(struct kvm_pic *s);
int kvm_cpu_get_interrupt(struct kvm_vcpu *v);
int kvm_cpu_get_interrupt(struct kvm_vcpu *v);
int kvm_cpu_has_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_NUM_PINS  24
#define IOAPIC_VERSION_ID 0x11	/* IOAPIC version */
#define IOAPIC_VERSION_ID 0x11	/* IOAPIC version */
+82 −0
Original line number Original line Diff line number Diff line
@@ -897,6 +897,53 @@ static int kvm_vm_ioctl_set_memory_alias(struct kvm *kvm,
	return r;
	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)
static gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn)
{
{
	int i;
	int i;
@@ -2835,6 +2882,41 @@ static long kvm_vm_ioctl(struct file *filp,
		}
		}
		break;
		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:
	default:
		;
		;
	}
	}
+36 −0
Original line number Original line Diff line number Diff line
@@ -45,6 +45,40 @@ struct kvm_irq_level {
	__u32 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;
};

enum kvm_irqchip_id {
	KVM_IRQCHIP_PIC_MASTER	 = 0,
	KVM_IRQCHIP_PIC_SLAVE	 = 1,
};

struct kvm_irqchip {
	__u32 chip_id;
	__u32 pad;
        union {
		char dummy[512];  /* reserving space */
		struct kvm_pic_state pic;
	} chip;
};

enum kvm_exit_reason {
enum kvm_exit_reason {
	KVM_EXIT_UNKNOWN          = 0,
	KVM_EXIT_UNKNOWN          = 0,
	KVM_EXIT_EXCEPTION        = 1,
	KVM_EXIT_EXCEPTION        = 1,
@@ -299,6 +333,8 @@ struct kvm_signal_mask {
/* Device model IOC */
/* Device model IOC */
#define KVM_CREATE_IRQCHIP	  _IO(KVMIO,  0x60)
#define KVM_CREATE_IRQCHIP	  _IO(KVMIO,  0x60)
#define KVM_IRQ_LINE		  _IOW(KVMIO, 0x61, struct kvm_irq_level)
#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
 * ioctls for vcpu fds