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

Commit be06b6be authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

Merge tag 'kvm-s390-next-20141128' of...

Merge tag 'kvm-s390-next-20141128' of git://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux into HEAD

KVM: s390: Several fixes,cleanups and reworks

Here is a bunch of fixes that deal mostly with architectural compliance:
- interrupt priorities
- interrupt handling
- intruction exit handling

We also provide a helper function for getting the guest visible storage key.
parents 2b4a273b fc2020cf
Loading
Loading
Loading
Loading
+87 −3
Original line number Diff line number Diff line
@@ -123,7 +123,7 @@ struct kvm_s390_sie_block {
#define ICPT_PARTEXEC	0x38
#define ICPT_IOINST	0x40
	__u8	icptcode;		/* 0x0050 */
	__u8	reserved51;		/* 0x0051 */
	__u8	icptstatus;		/* 0x0051 */
	__u16	ihcpu;			/* 0x0052 */
	__u8	reserved54[2];		/* 0x0054 */
	__u16	ipa;			/* 0x0056 */
@@ -295,6 +295,79 @@ struct kvm_vcpu_stat {
#define PGM_PER				0x80
#define PGM_CRYPTO_OPERATION		0x119

/* irq types in order of priority */
enum irq_types {
	IRQ_PEND_MCHK_EX = 0,
	IRQ_PEND_SVC,
	IRQ_PEND_PROG,
	IRQ_PEND_MCHK_REP,
	IRQ_PEND_EXT_IRQ_KEY,
	IRQ_PEND_EXT_MALFUNC,
	IRQ_PEND_EXT_EMERGENCY,
	IRQ_PEND_EXT_EXTERNAL,
	IRQ_PEND_EXT_CLOCK_COMP,
	IRQ_PEND_EXT_CPU_TIMER,
	IRQ_PEND_EXT_TIMING,
	IRQ_PEND_EXT_SERVICE,
	IRQ_PEND_EXT_HOST,
	IRQ_PEND_PFAULT_INIT,
	IRQ_PEND_PFAULT_DONE,
	IRQ_PEND_VIRTIO,
	IRQ_PEND_IO_ISC_0,
	IRQ_PEND_IO_ISC_1,
	IRQ_PEND_IO_ISC_2,
	IRQ_PEND_IO_ISC_3,
	IRQ_PEND_IO_ISC_4,
	IRQ_PEND_IO_ISC_5,
	IRQ_PEND_IO_ISC_6,
	IRQ_PEND_IO_ISC_7,
	IRQ_PEND_SIGP_STOP,
	IRQ_PEND_RESTART,
	IRQ_PEND_SET_PREFIX,
	IRQ_PEND_COUNT
};

/*
 * Repressible (non-floating) machine check interrupts
 * subclass bits in MCIC
 */
#define MCHK_EXTD_BIT 58
#define MCHK_DEGR_BIT 56
#define MCHK_WARN_BIT 55
#define MCHK_REP_MASK ((1UL << MCHK_DEGR_BIT) | \
		       (1UL << MCHK_EXTD_BIT) | \
		       (1UL << MCHK_WARN_BIT))

/* Exigent machine check interrupts subclass bits in MCIC */
#define MCHK_SD_BIT 63
#define MCHK_PD_BIT 62
#define MCHK_EX_MASK ((1UL << MCHK_SD_BIT) | (1UL << MCHK_PD_BIT))

#define IRQ_PEND_EXT_MASK ((1UL << IRQ_PEND_EXT_IRQ_KEY)    | \
			   (1UL << IRQ_PEND_EXT_CLOCK_COMP) | \
			   (1UL << IRQ_PEND_EXT_CPU_TIMER)  | \
			   (1UL << IRQ_PEND_EXT_MALFUNC)    | \
			   (1UL << IRQ_PEND_EXT_EMERGENCY)  | \
			   (1UL << IRQ_PEND_EXT_EXTERNAL)   | \
			   (1UL << IRQ_PEND_EXT_TIMING)     | \
			   (1UL << IRQ_PEND_EXT_HOST)       | \
			   (1UL << IRQ_PEND_EXT_SERVICE)    | \
			   (1UL << IRQ_PEND_VIRTIO)         | \
			   (1UL << IRQ_PEND_PFAULT_INIT)    | \
			   (1UL << IRQ_PEND_PFAULT_DONE))

#define IRQ_PEND_IO_MASK ((1UL << IRQ_PEND_IO_ISC_0) | \
			  (1UL << IRQ_PEND_IO_ISC_1) | \
			  (1UL << IRQ_PEND_IO_ISC_2) | \
			  (1UL << IRQ_PEND_IO_ISC_3) | \
			  (1UL << IRQ_PEND_IO_ISC_4) | \
			  (1UL << IRQ_PEND_IO_ISC_5) | \
			  (1UL << IRQ_PEND_IO_ISC_6) | \
			  (1UL << IRQ_PEND_IO_ISC_7))

#define IRQ_PEND_MCHK_MASK ((1UL << IRQ_PEND_MCHK_REP) | \
			    (1UL << IRQ_PEND_MCHK_EX))

struct kvm_s390_interrupt_info {
	struct list_head list;
	u64	type;
@@ -313,14 +386,25 @@ struct kvm_s390_interrupt_info {
#define ACTION_STORE_ON_STOP		(1<<0)
#define ACTION_STOP_ON_STOP		(1<<1)

struct kvm_s390_irq_payload {
	struct kvm_s390_io_info io;
	struct kvm_s390_ext_info ext;
	struct kvm_s390_pgm_info pgm;
	struct kvm_s390_emerg_info emerg;
	struct kvm_s390_extcall_info extcall;
	struct kvm_s390_prefix_info prefix;
	struct kvm_s390_mchk_info mchk;
};

struct kvm_s390_local_interrupt {
	spinlock_t lock;
	struct list_head list;
	atomic_t active;
	struct kvm_s390_float_interrupt *float_int;
	wait_queue_head_t *wq;
	atomic_t *cpuflags;
	unsigned int action_bits;
	DECLARE_BITMAP(sigp_emerg_pending, KVM_MAX_VCPUS);
	struct kvm_s390_irq_payload irq;
	unsigned long pending_irqs;
};

struct kvm_s390_float_interrupt {
+1 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ void page_table_reset_pgste(struct mm_struct *, unsigned long, unsigned long,
			    bool init_skey);
int set_guest_storage_key(struct mm_struct *mm, unsigned long addr,
			  unsigned long key, bool nq);
unsigned long get_guest_storage_key(struct mm_struct *mm, unsigned long addr);

static inline void clear_table(unsigned long *s, unsigned long val, size_t n)
{
+16 −4
Original line number Diff line number Diff line
@@ -38,6 +38,19 @@ static const intercept_handler_t instruction_handlers[256] = {
	[0xeb] = kvm_s390_handle_eb,
};

void kvm_s390_rewind_psw(struct kvm_vcpu *vcpu, int ilc)
{
	struct kvm_s390_sie_block *sie_block = vcpu->arch.sie_block;

	/* Use the length of the EXECUTE instruction if necessary */
	if (sie_block->icptstatus & 1) {
		ilc = (sie_block->icptstatus >> 4) & 0x6;
		if (!ilc)
			ilc = 4;
	}
	sie_block->gpsw.addr = __rewind_psw(sie_block->gpsw, ilc);
}

static int handle_noop(struct kvm_vcpu *vcpu)
{
	switch (vcpu->arch.sie_block->icptcode) {
@@ -244,7 +257,7 @@ static int handle_instruction_and_prog(struct kvm_vcpu *vcpu)
static int handle_external_interrupt(struct kvm_vcpu *vcpu)
{
	u16 eic = vcpu->arch.sie_block->eic;
	struct kvm_s390_interrupt irq;
	struct kvm_s390_irq irq;
	psw_t newpsw;
	int rc;

@@ -269,7 +282,7 @@ static int handle_external_interrupt(struct kvm_vcpu *vcpu)
		if (kvm_s390_si_ext_call_pending(vcpu))
			return 0;
		irq.type = KVM_S390_INT_EXTERNAL_CALL;
		irq.parm = vcpu->arch.sie_block->extcpuaddr;
		irq.u.extcall.code = vcpu->arch.sie_block->extcpuaddr;
		break;
	default:
		return -EOPNOTSUPP;
@@ -288,7 +301,6 @@ static int handle_external_interrupt(struct kvm_vcpu *vcpu)
 */
static int handle_mvpg_pei(struct kvm_vcpu *vcpu)
{
	psw_t *psw = &vcpu->arch.sie_block->gpsw;
	unsigned long srcaddr, dstaddr;
	int reg1, reg2, rc;

@@ -310,7 +322,7 @@ static int handle_mvpg_pei(struct kvm_vcpu *vcpu)
	if (rc != 0)
		return rc;

	psw->addr = __rewind_psw(*psw, 4);
	kvm_s390_rewind_psw(vcpu, 4);

	return 0;
}
+692 −345

File changed.

Preview size limit exceeded, changes collapsed.

+9 −5
Original line number Diff line number Diff line
@@ -719,7 +719,6 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
	}

	spin_lock_init(&vcpu->arch.local_int.lock);
	INIT_LIST_HEAD(&vcpu->arch.local_int.list);
	vcpu->arch.local_int.float_int = &kvm->arch.float_int;
	vcpu->arch.local_int.wq = &vcpu->wq;
	vcpu->arch.local_int.cpuflags = &vcpu->arch.sie_block->cpuflags;
@@ -1122,13 +1121,15 @@ static void __kvm_inject_pfault_token(struct kvm_vcpu *vcpu, bool start_token,
				      unsigned long token)
{
	struct kvm_s390_interrupt inti;
	inti.parm64 = token;
	struct kvm_s390_irq irq;

	if (start_token) {
		inti.type = KVM_S390_INT_PFAULT_INIT;
		WARN_ON_ONCE(kvm_s390_inject_vcpu(vcpu, &inti));
		irq.u.ext.ext_params2 = token;
		irq.type = KVM_S390_INT_PFAULT_INIT;
		WARN_ON_ONCE(kvm_s390_inject_vcpu(vcpu, &irq));
	} else {
		inti.type = KVM_S390_INT_PFAULT_DONE;
		inti.parm64 = token;
		WARN_ON_ONCE(kvm_s390_inject_vm(vcpu->kvm, &inti));
	}
}
@@ -1622,11 +1623,14 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
	switch (ioctl) {
	case KVM_S390_INTERRUPT: {
		struct kvm_s390_interrupt s390int;
		struct kvm_s390_irq s390irq;

		r = -EFAULT;
		if (copy_from_user(&s390int, argp, sizeof(s390int)))
			break;
		r = kvm_s390_inject_vcpu(vcpu, &s390int);
		if (s390int_to_s390irq(&s390int, &s390irq))
			return -EINVAL;
		r = kvm_s390_inject_vcpu(vcpu, &s390irq);
		break;
	}
	case KVM_S390_STORE_STATUS:
Loading