mirror of
https://github.com/torvalds/linux
synced 2024-11-05 18:23:50 +00:00
KVM: s390: deliver floating interrupts in order of priority
This patch makes interrupt handling compliant to the z/Architecture Principles of Operation with regard to interrupt priorities. Add a bitmap for pending floating interrupts. Each bit relates to a interrupt type and its list. A turned on bit indicates that a list contains items (interrupts) which need to be delivered. When delivering interrupts on a cpu we can merge the existing bitmap for cpu-local interrupts and floating interrupts and have a single mechanism for delivery. Currently we have one list for all kinds of floating interrupts and a corresponding spin lock. This patch adds a separate list per interrupt type. An exception to this are service signal and machine check interrupts, as there can be only one pending interrupt at a time. Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com> Acked-by: Cornelia Huck <cornelia.huck@de.ibm.com>
This commit is contained in:
parent
94aa033efc
commit
6d3da24141
5 changed files with 509 additions and 366 deletions
|
@ -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"
|
||||
|
@ -1069,7 +1070,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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -294,10 +294,13 @@ static int handle_tpi(struct kvm_vcpu *vcpu)
|
|||
|
||||
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.
|
||||
|
|
Loading…
Reference in a new issue