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

Commit 7f22b45d authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

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

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

Features and fixes for 4.1 (kvm/next)

1. Assorted changes
1.1 allow more feature bits for the guest
1.2 Store breaking event address on program interrupts

2. Interrupt handling rework
2.1 Fix copy_to_user while holding a spinlock (cc stable)
2.2 Rework floating interrupts to follow the priorities
2.3 Allow to inject all local interrupts via new ioctl
2.4 allow to get/set the full local irq state, e.g. for migration
    and introspection
parents bf0fb67c 816c7667
Loading
Loading
Loading
Loading
+117 −0
Original line number Diff line number Diff line
@@ -2861,6 +2861,123 @@ single frame starting at start_gfn for count frames.
Note: If any architecturally invalid key value is found in the given data then
the ioctl will return -EINVAL.

4.92 KVM_S390_IRQ

Capability: KVM_CAP_S390_INJECT_IRQ
Architectures: s390
Type: vcpu ioctl
Parameters: struct kvm_s390_irq (in)
Returns: 0 on success, -1 on error
Errors:
  EINVAL: interrupt type is invalid
          type is KVM_S390_SIGP_STOP and flag parameter is invalid value
          type is KVM_S390_INT_EXTERNAL_CALL and code is bigger
            than the maximum of VCPUs
  EBUSY:  type is KVM_S390_SIGP_SET_PREFIX and vcpu is not stopped
          type is KVM_S390_SIGP_STOP and a stop irq is already pending
          type is KVM_S390_INT_EXTERNAL_CALL and an external call interrupt
            is already pending

Allows to inject an interrupt to the guest.

Using struct kvm_s390_irq as a parameter allows
to inject additional payload which is not
possible via KVM_S390_INTERRUPT.

Interrupt parameters are passed via kvm_s390_irq:

struct kvm_s390_irq {
	__u64 type;
	union {
		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_stop_info stop;
		struct kvm_s390_mchk_info mchk;
		char reserved[64];
	} u;
};

type can be one of the following:

KVM_S390_SIGP_STOP - sigp stop; parameter in .stop
KVM_S390_PROGRAM_INT - program check; parameters in .pgm
KVM_S390_SIGP_SET_PREFIX - sigp set prefix; parameters in .prefix
KVM_S390_RESTART - restart; no parameters
KVM_S390_INT_CLOCK_COMP - clock comparator interrupt; no parameters
KVM_S390_INT_CPU_TIMER - CPU timer interrupt; no parameters
KVM_S390_INT_EMERGENCY - sigp emergency; parameters in .emerg
KVM_S390_INT_EXTERNAL_CALL - sigp external call; parameters in .extcall
KVM_S390_MCHK - machine check interrupt; parameters in .mchk


Note that the vcpu ioctl is asynchronous to vcpu execution.

4.94 KVM_S390_GET_IRQ_STATE

Capability: KVM_CAP_S390_IRQ_STATE
Architectures: s390
Type: vcpu ioctl
Parameters: struct kvm_s390_irq_state (out)
Returns: >= number of bytes copied into buffer,
         -EINVAL if buffer size is 0,
         -ENOBUFS if buffer size is too small to fit all pending interrupts,
         -EFAULT if the buffer address was invalid

This ioctl allows userspace to retrieve the complete state of all currently
pending interrupts in a single buffer. Use cases include migration
and introspection. The parameter structure contains the address of a
userspace buffer and its length:

struct kvm_s390_irq_state {
	__u64 buf;
	__u32 flags;
	__u32 len;
	__u32 reserved[4];
};

Userspace passes in the above struct and for each pending interrupt a
struct kvm_s390_irq is copied to the provided buffer.

If -ENOBUFS is returned the buffer provided was too small and userspace
may retry with a bigger buffer.

4.95 KVM_S390_SET_IRQ_STATE

Capability: KVM_CAP_S390_IRQ_STATE
Architectures: s390
Type: vcpu ioctl
Parameters: struct kvm_s390_irq_state (in)
Returns: 0 on success,
         -EFAULT if the buffer address was invalid,
         -EINVAL for an invalid buffer length (see below),
         -EBUSY if there were already interrupts pending,
         errors occurring when actually injecting the
          interrupt. See KVM_S390_IRQ.

This ioctl allows userspace to set the complete state of all cpu-local
interrupts currently pending for the vcpu. It is intended for restoring
interrupt state after a migration. The input parameter is a userspace buffer
containing a struct kvm_s390_irq_state:

struct kvm_s390_irq_state {
	__u64 buf;
	__u32 len;
	__u32 pad;
};

The userspace memory referenced by buf contains a struct kvm_s390_irq
for each interrupt to be injected into the guest.
If one of the interrupts could not be injected for some reason the
ioctl aborts.

len must be a multiple of sizeof(struct kvm_s390_irq). It must be > 0
and it must not exceed (max_vcpus + 32) * sizeof(struct kvm_s390_irq),
which is the maximum number of possibly pending cpu-local interrupts.

5. The kvm_run structure
------------------------

+3 −0
Original line number Diff line number Diff line
@@ -27,6 +27,9 @@ Groups:
    Copies all floating interrupts into a buffer provided by userspace.
    When the buffer is too small it returns -ENOMEM, which is the indication
    for userspace to try again with a bigger buffer.
    -ENOBUFS is returned when the allocation of a kernelspace buffer has
    failed.
    -EFAULT is returned when copying data to userspace failed.
    All interrupts remain pending, i.e. are not deleted from the list of
    currently pending interrupts.
    attr->addr contains the userspace address of the buffer into which all
+27 −3
Original line number Diff line number Diff line
@@ -344,6 +344,11 @@ enum irq_types {
	IRQ_PEND_COUNT
};

/* We have 2M for virtio device descriptor pages. Smallest amount of
 * memory per page is 24 bytes (1 queue), so (2048*1024) / 24 = 87381
 */
#define KVM_S390_MAX_VIRTIO_IRQS 87381

/*
 * Repressible (non-floating) machine check interrupts
 * subclass bits in MCIC
@@ -421,13 +426,32 @@ struct kvm_s390_local_interrupt {
	unsigned long pending_irqs;
};

#define FIRQ_LIST_IO_ISC_0 0
#define FIRQ_LIST_IO_ISC_1 1
#define FIRQ_LIST_IO_ISC_2 2
#define FIRQ_LIST_IO_ISC_3 3
#define FIRQ_LIST_IO_ISC_4 4
#define FIRQ_LIST_IO_ISC_5 5
#define FIRQ_LIST_IO_ISC_6 6
#define FIRQ_LIST_IO_ISC_7 7
#define FIRQ_LIST_PFAULT   8
#define FIRQ_LIST_VIRTIO   9
#define FIRQ_LIST_COUNT   10
#define FIRQ_CNTR_IO       0
#define FIRQ_CNTR_SERVICE  1
#define FIRQ_CNTR_VIRTIO   2
#define FIRQ_CNTR_PFAULT   3
#define FIRQ_MAX_COUNT     4

struct kvm_s390_float_interrupt {
	unsigned long pending_irqs;
	spinlock_t lock;
	struct list_head list;
	atomic_t active;
	struct list_head lists[FIRQ_LIST_COUNT];
	int counters[FIRQ_MAX_COUNT];
	struct kvm_s390_mchk_info mchk;
	struct kvm_s390_ext_info srv_signal;
	int next_rr_cpu;
	unsigned long idle_mask[BITS_TO_LONGS(KVM_MAX_VCPUS)];
	unsigned int irq_count;
};

struct kvm_hw_wp_info_arch {
+682 −391

File changed.

Preview size limit exceeded, changes collapsed.

+51 −3
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@
#include <asm/pgtable.h>
#include <asm/nmi.h>
#include <asm/switch_to.h>
#include <asm/isc.h>
#include <asm/sclp.h>
#include "kvm-s390.h"
#include "gaccess.h"
@@ -40,6 +41,9 @@
#include "trace-s390.h"

#define MEM_OP_MAX_SIZE 65536	/* Maximum transfer size for KVM_S390_MEM_OP */
#define LOCAL_IRQS 32
#define VCPU_IRQS_MAX_BUF (sizeof(struct kvm_s390_irq) * \
			   (KVM_MAX_VCPUS + LOCAL_IRQS))

#define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU

@@ -105,8 +109,8 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {

/* upper facilities limit for kvm */
unsigned long kvm_s390_fac_list_mask[] = {
	0xff82fffbf4fc2000UL,
	0x005c000000000000UL,
	0xffe6fffbfcfdfc40UL,
	0x205c800000000000UL,
};

unsigned long kvm_s390_fac_list_mask_size(void)
@@ -176,9 +180,11 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
	case KVM_CAP_S390_IRQCHIP:
	case KVM_CAP_VM_ATTRIBUTES:
	case KVM_CAP_MP_STATE:
	case KVM_CAP_S390_INJECT_IRQ:
	case KVM_CAP_S390_USER_SIGP:
	case KVM_CAP_S390_USER_STSI:
	case KVM_CAP_S390_SKEYS:
	case KVM_CAP_S390_IRQ_STATE:
		r = 1;
		break;
	case KVM_CAP_S390_MEM_OP:
@@ -1069,7 +1075,8 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
		goto out_err;

	spin_lock_init(&kvm->arch.float_int.lock);
	INIT_LIST_HEAD(&kvm->arch.float_int.list);
	for (i = 0; i < FIRQ_LIST_COUNT; i++)
		INIT_LIST_HEAD(&kvm->arch.float_int.lists[i]);
	init_waitqueue_head(&kvm->arch.ipte_wq);
	mutex_init(&kvm->arch.ipte_mutex);

@@ -2389,6 +2396,15 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
	long r;

	switch (ioctl) {
	case KVM_S390_IRQ: {
		struct kvm_s390_irq s390irq;

		r = -EFAULT;
		if (copy_from_user(&s390irq, argp, sizeof(s390irq)))
			break;
		r = kvm_s390_inject_vcpu(vcpu, &s390irq);
		break;
	}
	case KVM_S390_INTERRUPT: {
		struct kvm_s390_interrupt s390int;
		struct kvm_s390_irq s390irq;
@@ -2488,6 +2504,38 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
			r = -EFAULT;
		break;
	}
	case KVM_S390_SET_IRQ_STATE: {
		struct kvm_s390_irq_state irq_state;

		r = -EFAULT;
		if (copy_from_user(&irq_state, argp, sizeof(irq_state)))
			break;
		if (irq_state.len > VCPU_IRQS_MAX_BUF ||
		    irq_state.len == 0 ||
		    irq_state.len % sizeof(struct kvm_s390_irq) > 0) {
			r = -EINVAL;
			break;
		}
		r = kvm_s390_set_irq_state(vcpu,
					   (void __user *) irq_state.buf,
					   irq_state.len);
		break;
	}
	case KVM_S390_GET_IRQ_STATE: {
		struct kvm_s390_irq_state irq_state;

		r = -EFAULT;
		if (copy_from_user(&irq_state, argp, sizeof(irq_state)))
			break;
		if (irq_state.len == 0) {
			r = -EINVAL;
			break;
		}
		r = kvm_s390_get_irq_state(vcpu,
					   (__u8 __user *)  irq_state.buf,
					   irq_state.len);
		break;
	}
	default:
		r = -ENOTTY;
	}
Loading