mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-28 14:44:10 +08:00
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 -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.14 (GNU/Linux) iQIcBAABAgAGBQJVGvEUAAoJEBF7vIC1phx82tEP/3KrwsDRs+buiBqyv9k+qCFV v+R94gReBB5ggfbGfUYgBJMR2/4XQ+0jcZ55jfBCC4osOq6Juw/8HIj2nSgbQHmz F9Go0n8IqJ3DnqPTc0KYdFZ7kqDvMV5ME3XJrFiAHv1TUL9H/KpZArkcVIwD2NOo w01AVrCDY4bTajYqKShzGFymQl1K5vTGGvgxhh4kAHct4Nt5N5HFmyROm0RrsFZx Sycx4t177O7zhCN2tv5Zy8iWaEvzHAESoXkhZ2cJ6t+FXii2Eov5IgyyfYRXBfbm YACyvlFD087UdFGTt85ggPVS/S/5hn9xXmVHuIimHeyZU7CXCN5vYPcn+ZyksYr5 uA8+/2OPAgcaeDa2f7nCjl8jmcLR3hkQ0n/urA+pPYAZANJoFDfiGOr/kVk6aKff JTGSFUjNK891/IGEsdrSk2p64U5xMd8LFa3Il++kZT91gc2nrZOHNz5FGlXlkLdJ sADeNFWhoprEt/2P4aX6W2j26L8G874XkldDSjrS41U8L55+IiEm09r8oAWgfc5A pryeDaN4nSjFC+HOtlPkcVkAcsswiI6nHIm3+/XFetCq+v4pnVKFMHWsTeEjiQgQ H5aV9mfEKTJaCPrAJMsj8ZsKq0usG+BeRNqpIvxPAQB8fyl3jw9iu+RHeY1xWsTg BRHB/+CGYIxDu4XdRexv =Rrx5 -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
7f22b45d66
@ -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
|
||||
------------------------
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
||||
|
@ -178,7 +178,7 @@ int __must_check kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
|
||||
struct kvm_s390_irq *irq);
|
||||
int __must_check kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code);
|
||||
struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm,
|
||||
u64 cr6, u64 schid);
|
||||
u64 isc_mask, u32 schid);
|
||||
int kvm_s390_reinject_io_int(struct kvm *kvm,
|
||||
struct kvm_s390_interrupt_info *inti);
|
||||
int kvm_s390_mask_adapter(struct kvm *kvm, unsigned int id, bool masked);
|
||||
@ -272,6 +272,10 @@ int kvm_s390_ext_call_pending(struct kvm_vcpu *vcpu);
|
||||
extern struct kvm_device_ops kvm_flic_ops;
|
||||
int kvm_s390_is_stop_irq_pending(struct kvm_vcpu *vcpu);
|
||||
void kvm_s390_clear_stop_irq(struct kvm_vcpu *vcpu);
|
||||
int kvm_s390_set_irq_state(struct kvm_vcpu *vcpu,
|
||||
void __user *buf, int len);
|
||||
int kvm_s390_get_irq_state(struct kvm_vcpu *vcpu,
|
||||
__u8 __user *buf, int len);
|
||||
|
||||
/* implemented in guestdbg.c */
|
||||
void kvm_s390_backup_guest_per_regs(struct kvm_vcpu *vcpu);
|
||||
|
@ -294,10 +294,13 @@ reinject_interrupt:
|
||||
|
||||
static int handle_tsch(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_s390_interrupt_info *inti;
|
||||
struct kvm_s390_interrupt_info *inti = NULL;
|
||||
const u64 isc_mask = 0xffUL << 24; /* all iscs set */
|
||||
|
||||
inti = kvm_s390_get_io_int(vcpu->kvm, 0,
|
||||
vcpu->run->s.regs.gprs[1]);
|
||||
/* a valid schid has at least one bit set */
|
||||
if (vcpu->run->s.regs.gprs[1])
|
||||
inti = kvm_s390_get_io_int(vcpu->kvm, isc_mask,
|
||||
vcpu->run->s.regs.gprs[1]);
|
||||
|
||||
/*
|
||||
* Prepare exit to userspace.
|
||||
|
@ -558,6 +558,13 @@ struct kvm_s390_irq {
|
||||
} u;
|
||||
};
|
||||
|
||||
struct kvm_s390_irq_state {
|
||||
__u64 buf;
|
||||
__u32 flags;
|
||||
__u32 len;
|
||||
__u32 reserved[4];
|
||||
};
|
||||
|
||||
/* for KVM_SET_GUEST_DEBUG */
|
||||
|
||||
#define KVM_GUESTDBG_ENABLE 0x00000001
|
||||
@ -804,6 +811,8 @@ struct kvm_ppc_smmu_info {
|
||||
#define KVM_CAP_S390_SKEYS 110
|
||||
#define KVM_CAP_MIPS_FPU 111
|
||||
#define KVM_CAP_MIPS_MSA 112
|
||||
#define KVM_CAP_S390_INJECT_IRQ 113
|
||||
#define KVM_CAP_S390_IRQ_STATE 114
|
||||
|
||||
#ifdef KVM_CAP_IRQ_ROUTING
|
||||
|
||||
@ -1184,6 +1193,11 @@ struct kvm_s390_ucas_mapping {
|
||||
/* Available with KVM_CAP_S390_SKEYS */
|
||||
#define KVM_S390_GET_SKEYS _IOW(KVMIO, 0xb2, struct kvm_s390_skeys)
|
||||
#define KVM_S390_SET_SKEYS _IOW(KVMIO, 0xb3, struct kvm_s390_skeys)
|
||||
/* Available with KVM_CAP_S390_INJECT_IRQ */
|
||||
#define KVM_S390_IRQ _IOW(KVMIO, 0xb4, struct kvm_s390_irq)
|
||||
/* Available with KVM_CAP_S390_IRQ_STATE */
|
||||
#define KVM_S390_SET_IRQ_STATE _IOW(KVMIO, 0xb5, struct kvm_s390_irq_state)
|
||||
#define KVM_S390_GET_IRQ_STATE _IOW(KVMIO, 0xb6, struct kvm_s390_irq_state)
|
||||
|
||||
#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)
|
||||
#define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1)
|
||||
|
@ -2113,7 +2113,7 @@ static long kvm_vcpu_ioctl(struct file *filp,
|
||||
* Special cases: vcpu ioctls that are asynchronous to vcpu execution,
|
||||
* so vcpu_load() would break it.
|
||||
*/
|
||||
if (ioctl == KVM_S390_INTERRUPT || ioctl == KVM_INTERRUPT)
|
||||
if (ioctl == KVM_S390_INTERRUPT || ioctl == KVM_S390_IRQ || ioctl == KVM_INTERRUPT)
|
||||
return kvm_arch_vcpu_ioctl(filp, ioctl, arg);
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user