All of lore.kernel.org
 help / color / mirror / Atom feed
From: frank.blaschka@de.ibm.com
To: qemu-devel@nongnu.org, linux-s390@vger.kernel.org, kvm@vger.kernel.org
Cc: aik@ozlabs.ru, pbonzini@redhat.com, agraf@suse.de
Subject: [RFC][patch 3/6] KVM: s390: Add GISA support
Date: Thu, 04 Sep 2014 12:52:26 +0200	[thread overview]
Message-ID: <20140904105337.081387456@de.ibm.com> (raw)
In-Reply-To: 20140904105223.336503578@de.ibm.com

[-- Attachment #1: 004-s390_kvm_gisa-3.16.patch --]
[-- Type: text/plain, Size: 10151 bytes --]

From: Frank Blaschka <frank.blaschka@de.ibm.com>

This patch adds GISA (Guest Interrupt State Area) support
to s390 kvm. GISA can be used for exitless interrupts. The
patch provides a set of functions for GISA related operations
like accessing GISA fields or registering ISCs for alert.
Exploiters of GISA will follow with additional patches.

Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com>
---
 arch/s390/include/asm/kvm_host.h |   72 ++++++++++++++++
 arch/s390/kvm/kvm-s390.c         |  167 +++++++++++++++++++++++++++++++++++++++
 arch/s390/kvm/kvm-s390.h         |   28 ++++++
 3 files changed, 265 insertions(+), 2 deletions(-)

--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -129,11 +129,12 @@ struct kvm_s390_sie_block {
 	__u8	reserved60;		/* 0x0060 */
 	__u8	ecb;			/* 0x0061 */
 	__u8    ecb2;                   /* 0x0062 */
-	__u8    reserved63[1];          /* 0x0063 */
+	__u8    ecb3;			/* 0x0063 */
 	__u32	scaol;			/* 0x0064 */
 	__u8	reserved68[4];		/* 0x0068 */
 	__u32	todpr;			/* 0x006c */
-	__u8	reserved70[32];		/* 0x0070 */
+	__u32   gd;                     /* 0x0070 */
+	__u8    reserved74[28];         /* 0x0074 */
 	psw_t	gpsw;			/* 0x0090 */
 	__u64	gg14;			/* 0x00a0 */
 	__u64	gg15;			/* 0x00a8 */
@@ -300,6 +301,70 @@ struct kvm_s390_interrupt_info {
 #define ACTION_STORE_ON_STOP		(1<<0)
 #define ACTION_STOP_ON_STOP		(1<<1)
 
+#define KVM_S390_GISA_FORMAT_0	0
+#define KVM_S390_GISA_FORMAT_1	1
+
+struct kvm_s390_gisa_f0 {
+	u32 next_alert;
+	u8 ipm;
+	u16 rsv0:14;
+	u16 g:1;
+	u16 c:1;
+	u8 iam;
+	u32 rsv1;
+	u32 count;
+} __packed;
+
+struct kvm_s390_gisa_f1 {
+	u32 next_alert;
+	u8 ipm;
+	u8 simm;
+	u8 nimm;
+	u8 iam;
+	u64 aisma;
+	u32 rsv0:6;
+	u32 g:1;
+	u32 c:1;
+	u32 rsv1:24;
+	u64 rsv2;
+	u32 count;
+} __packed;
+
+union kvm_s390_gisa {
+	struct kvm_s390_gisa_f0 f0;
+	struct kvm_s390_gisa_f1 f1;
+};
+
+struct kvm_s390_gait {
+	u32 gd;
+	u16      : 5;
+	u16 gisc : 3;
+	u16 rpu  : 8;
+	u16        : 10;
+	u16 gaisbo :  6;
+	u64 gaisba;
+} __packed;
+
+struct kvm_s390_aifte {
+	u64 faisba;
+	u64 gaita;
+	u16 simm : 8;
+	u16      : 5;
+	u16 afi  : 3;
+	u16 reserved1;
+	u16 reserved2;
+	u16 faal;
+} __packed;
+
+struct kvm_s390_gib {
+	u32 alo;
+	u32 reserved1;
+	u32      : 5;
+	u32 nisc : 3;
+	u32      : 24;
+	u8 reserverd2[20];
+} __packed;
+
 struct kvm_s390_local_interrupt {
 	spinlock_t lock;
 	struct list_head list;
@@ -420,6 +485,9 @@ struct kvm_arch{
 	struct s390_io_adapter *adapters[MAX_S390_IO_ADAPTERS];
 	wait_queue_head_t ipte_wq;
 	spinlock_t start_stop_lock;
+	union kvm_s390_gisa *gisa;
+	unsigned long iam;
+	atomic_t in_sie;
 };
 
 #define KVM_HVA_ERR_BAD		(-1UL)
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -404,6 +404,16 @@ long kvm_arch_vm_ioctl(struct file *filp
 	return r;
 }
 
+static u8 kvm_s390_gisa_get_alert_mask(struct kvm *kvm)
+{
+	return (u8)ACCESS_ONCE(kvm->arch.iam);
+}
+
+static void kvm_s390_gisa_set_alert_mask(struct kvm *kvm, u8 iam)
+{
+	xchg(&kvm->arch.iam, iam);
+}
+
 int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 {
 	int rc;
@@ -461,6 +471,14 @@ int kvm_arch_init_vm(struct kvm *kvm, un
 	kvm->arch.css_support = 0;
 	kvm->arch.use_irqchip = 0;
 
+	kvm->arch.gisa = (union kvm_s390_gisa *)get_zeroed_page(
+			GFP_KERNEL | GFP_DMA);
+	if (!kvm->arch.gisa)
+		goto out_nogmap;
+	kvm_s390_gisa_set_next_alert(kvm, (u32)(unsigned long)kvm->arch.gisa);
+	kvm_s390_gisa_set_alert_mask(kvm, 0);
+	atomic_set(&kvm->arch.in_sie, 0);
+
 	spin_lock_init(&kvm->arch.start_stop_lock);
 
 	return 0;
@@ -520,6 +538,7 @@ void kvm_arch_sync_events(struct kvm *kv
 
 void kvm_arch_destroy_vm(struct kvm *kvm)
 {
+	free_page((unsigned long)kvm->arch.gisa);
 	kvm_free_vcpus(kvm);
 	free_page((unsigned long)(kvm->arch.sca));
 	debug_unregister(kvm->arch.dbf);
@@ -656,6 +675,19 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu
 	return rc;
 }
 
+u32 kvm_s390_gisa_get_fmt(void)
+{
+	if (test_facility(70) || test_facility(72))
+		return KVM_S390_GISA_FORMAT_1;
+	else
+		return KVM_S390_GISA_FORMAT_0;
+}
+
+static u32 kvm_s390_build_gd(struct kvm *kvm)
+{
+	return (u32)(unsigned long)kvm->arch.gisa | kvm_s390_gisa_get_fmt();
+}
+
 struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
 				      unsigned int id)
 {
@@ -699,6 +731,7 @@ struct kvm_vcpu *kvm_arch_vcpu_create(st
 	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;
+	vcpu->arch.sie_block->gd = kvm_s390_build_gd(kvm);
 
 	rc = kvm_vcpu_init(vcpu, kvm, id);
 	if (rc)
@@ -749,6 +782,132 @@ void exit_sie_sync(struct kvm_vcpu *vcpu
 	exit_sie(vcpu);
 }
 
+void kvm_s390_gisa_register_alert(struct kvm *kvm, u32 gisc)
+{
+	int bito = BITS_PER_BYTE * 7 + gisc;
+
+	set_bit(bito ^ (BITS_PER_LONG - 1), &kvm->arch.iam);
+}
+
+void kvm_s390_gisa_unregister_alert(struct kvm *kvm, u32 gisc)
+{
+	int bito = BITS_PER_BYTE * 7 + gisc;
+
+	clear_bit(bito ^ (BITS_PER_LONG - 1), &kvm->arch.iam);
+}
+
+u32 __kvm_s390_gisa_get_next_alert(union kvm_s390_gisa *gisa)
+{
+	return ACCESS_ONCE(gisa->f0.next_alert);
+}
+
+u32 kvm_s390_gisa_get_next_alert(struct kvm *kvm)
+{
+	return __kvm_s390_gisa_get_next_alert(
+		(union kvm_s390_gisa *)kvm->arch.gisa);
+}
+
+void __kvm_s390_gisa_set_next_alert(union kvm_s390_gisa *gisa, u32 val)
+{
+	xchg(&gisa->f0.next_alert, val);
+}
+
+void kvm_s390_gisa_set_next_alert(struct kvm *kvm, u32 val)
+{
+	__kvm_s390_gisa_set_next_alert(kvm->arch.gisa, val);
+}
+
+u8 kvm_s390_gisa_get_iam(struct kvm *kvm)
+{
+	return ACCESS_ONCE(kvm->arch.gisa->f0.iam);
+}
+
+void kvm_s390_gisa_set_iam(struct kvm *kvm, u8 iam)
+{
+	xchg(&kvm->arch.gisa->f0.iam, iam);
+}
+
+int kvm_s390_gisa_test_iam_gisc(struct kvm *kvm, u32 gisc)
+{
+	int bito = BITS_PER_BYTE * 7 + gisc;
+	unsigned long *addr = (unsigned long *)kvm->arch.gisa;
+
+	return test_bit(bito ^ (BITS_PER_LONG - 1), addr);
+}
+
+u8 kvm_s390_gisa_get_ipm(struct kvm *kvm)
+{
+	return ACCESS_ONCE(kvm->arch.gisa->f0.ipm);
+}
+
+void kvm_s390_gisa_set_ipm(struct kvm *kvm, u8 ipm)
+{
+	xchg(&kvm->arch.gisa->f0.ipm, ipm);
+}
+
+int kvm_s390_gisa_test_ipm_gisc(struct kvm *kvm, u32 gisc)
+{
+	int bito = BITS_PER_BYTE * 4 + gisc;
+	unsigned long *addr = (unsigned long *)kvm->arch.gisa;
+
+	return test_bit(bito ^ (BITS_PER_LONG - 1), addr);
+}
+
+void kvm_s390_gisa_set_ipm_gisc(struct kvm *kvm, u32 gisc)
+{
+	int bito = gisc + 32;
+	unsigned long *addr = (unsigned long *)kvm->arch.gisa;
+
+	set_bit(bito ^ (BITS_PER_LONG - 1), addr);
+}
+
+u32 kvm_s390_gisa_get_g(struct kvm *kvm)
+{
+	u32 fmt, bito;
+	unsigned long *addr;
+
+	fmt = kvm_s390_gisa_get_fmt();
+	if (fmt == KVM_S390_GISA_FORMAT_0) {
+		addr = (unsigned long *)kvm->arch.gisa;
+		bito = BITS_PER_BYTE * 6 + 6;
+	} else {
+		addr = (unsigned long *)((u8 *)kvm->arch.gisa + 16);
+		bito = 6;
+	}
+
+	return test_bit(bito ^ (BITS_PER_LONG - 1), addr);
+}
+
+u32 kvm_s390_gisa_get_c(struct kvm *kvm)
+{
+	u32 fmt, bito;
+	unsigned long *addr;
+
+	fmt = kvm_s390_gisa_get_fmt();
+	if (fmt == KVM_S390_GISA_FORMAT_0) {
+		addr = (unsigned long *)kvm->arch.gisa;
+		bito = BITS_PER_BYTE * 6 + 7;
+	} else {
+		addr = (unsigned long *)((u8 *)kvm->arch.gisa + 16);
+		bito = 7;
+	}
+
+	return test_bit(bito ^ (BITS_PER_LONG - 1), addr);
+}
+
+u32 kvm_s390_gisa_get_count(struct kvm *kvm)
+{
+	u32 fmt, cnt;
+
+	fmt = kvm_s390_gisa_get_fmt();
+	if (fmt == KVM_S390_GISA_FORMAT_0)
+		cnt = ACCESS_ONCE(kvm->arch.gisa->f0.count);
+	else
+		cnt = ACCESS_ONCE(kvm->arch.gisa->f1.count);
+
+	return cnt;
+}
+
 static void kvm_gmap_notifier(struct gmap *gmap, unsigned long address)
 {
 	int i;
@@ -1284,8 +1443,16 @@ static int __vcpu_run(struct kvm_vcpu *v
 		preempt_disable();
 		kvm_guest_enter();
 		preempt_enable();
+
+		atomic_inc(&vcpu->kvm->arch.in_sie);
+		kvm_s390_gisa_set_iam(vcpu->kvm, 0);
+
 		exit_reason = sie64a(vcpu->arch.sie_block,
 				     vcpu->run->s.regs.gprs);
+		if (atomic_dec_and_test(&vcpu->kvm->arch.in_sie))
+			kvm_s390_gisa_set_iam(vcpu->kvm,
+				kvm_s390_gisa_get_alert_mask(vcpu->kvm));
+
 		kvm_guest_exit();
 		vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
 
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -122,6 +122,17 @@ static inline u64 kvm_s390_get_base_disp
 	return (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + disp2;
 }
 
+static inline u64 kvm_s390_get_base_disp_rxy(struct kvm_vcpu *vcpu)
+{
+	u32 x2 = (vcpu->arch.sie_block->ipa & 0x000f);
+	u32 base2 = vcpu->arch.sie_block->ipb >> 28;
+	u32 disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16) +
+		((vcpu->arch.sie_block->ipb & 0xff00) << 4);
+
+	return (base2 ? vcpu->run->s.regs.gprs[base2] : 0) +
+		(x2 ? vcpu->run->s.regs.gprs[x2] : 0) + (u64)disp2;
+}
+
 /* Set the condition code in the guest program status word */
 static inline void kvm_s390_set_psw_cc(struct kvm_vcpu *vcpu, unsigned long cc)
 {
@@ -180,6 +191,23 @@ void exit_sie(struct kvm_vcpu *vcpu);
 void exit_sie_sync(struct kvm_vcpu *vcpu);
 int kvm_s390_vcpu_setup_cmma(struct kvm_vcpu *vcpu);
 void kvm_s390_vcpu_unsetup_cmma(struct kvm_vcpu *vcpu);
+u32 kvm_s390_gisa_get_fmt(void);
+void kvm_s390_gisa_register_alert(struct kvm *kvm, u32 gisc);
+void kvm_s390_gisa_unregister_alert(struct kvm *kvm, u32 gisc);
+u32 __kvm_s390_gisa_get_next_alert(union kvm_s390_gisa *gisa);
+u32 kvm_s390_gisa_get_next_alert(struct kvm *kvm);
+void __kvm_s390_gisa_set_next_alert(union kvm_s390_gisa *gisa, u32 val);
+void kvm_s390_gisa_set_next_alert(struct kvm *kvm, u32 val);
+u8 kvm_s390_gisa_get_iam(struct kvm *kvm);
+void kvm_s390_gisa_set_iam(struct kvm *kvm, u8 value);
+int kvm_s390_gisa_test_iam_gisc(struct kvm *kvm, u32 gisc);
+u8 kvm_s390_gisa_get_ipm(struct kvm *kvm);
+void kvm_s390_gisa_set_ipm(struct kvm *kvm, u8 value);
+int kvm_s390_gisa_test_ipm_gisc(struct kvm *kvm, u32 gisc);
+void kvm_s390_gisa_set_ipm_gisc(struct kvm *kvm, u32 gisc);
+u32 kvm_s390_gisa_get_g(struct kvm *kvm);
+u32 kvm_s390_gisa_get_c(struct kvm *kvm);
+u32 kvm_s390_gisa_get_count(struct kvm *kvm);
 /* is cmma enabled */
 bool kvm_s390_cmma_enabled(struct kvm *kvm);
 int test_vfacility(unsigned long nr);

WARNING: multiple messages have this Message-ID (diff)
From: frank.blaschka@de.ibm.com
To: qemu-devel@nongnu.org, linux-s390@vger.kernel.org, kvm@vger.kernel.org
Cc: aik@ozlabs.ru, pbonzini@redhat.com, agraf@suse.de
Subject: [Qemu-devel] [RFC][patch 3/6] KVM: s390: Add GISA support
Date: Thu, 04 Sep 2014 12:52:26 +0200	[thread overview]
Message-ID: <20140904105337.081387456@de.ibm.com> (raw)
In-Reply-To: 20140904105223.336503578@de.ibm.com

[-- Attachment #1: 004-s390_kvm_gisa-3.16.patch --]
[-- Type: text/plain, Size: 10151 bytes --]

From: Frank Blaschka <frank.blaschka@de.ibm.com>

This patch adds GISA (Guest Interrupt State Area) support
to s390 kvm. GISA can be used for exitless interrupts. The
patch provides a set of functions for GISA related operations
like accessing GISA fields or registering ISCs for alert.
Exploiters of GISA will follow with additional patches.

Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com>
---
 arch/s390/include/asm/kvm_host.h |   72 ++++++++++++++++
 arch/s390/kvm/kvm-s390.c         |  167 +++++++++++++++++++++++++++++++++++++++
 arch/s390/kvm/kvm-s390.h         |   28 ++++++
 3 files changed, 265 insertions(+), 2 deletions(-)

--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -129,11 +129,12 @@ struct kvm_s390_sie_block {
 	__u8	reserved60;		/* 0x0060 */
 	__u8	ecb;			/* 0x0061 */
 	__u8    ecb2;                   /* 0x0062 */
-	__u8    reserved63[1];          /* 0x0063 */
+	__u8    ecb3;			/* 0x0063 */
 	__u32	scaol;			/* 0x0064 */
 	__u8	reserved68[4];		/* 0x0068 */
 	__u32	todpr;			/* 0x006c */
-	__u8	reserved70[32];		/* 0x0070 */
+	__u32   gd;                     /* 0x0070 */
+	__u8    reserved74[28];         /* 0x0074 */
 	psw_t	gpsw;			/* 0x0090 */
 	__u64	gg14;			/* 0x00a0 */
 	__u64	gg15;			/* 0x00a8 */
@@ -300,6 +301,70 @@ struct kvm_s390_interrupt_info {
 #define ACTION_STORE_ON_STOP		(1<<0)
 #define ACTION_STOP_ON_STOP		(1<<1)
 
+#define KVM_S390_GISA_FORMAT_0	0
+#define KVM_S390_GISA_FORMAT_1	1
+
+struct kvm_s390_gisa_f0 {
+	u32 next_alert;
+	u8 ipm;
+	u16 rsv0:14;
+	u16 g:1;
+	u16 c:1;
+	u8 iam;
+	u32 rsv1;
+	u32 count;
+} __packed;
+
+struct kvm_s390_gisa_f1 {
+	u32 next_alert;
+	u8 ipm;
+	u8 simm;
+	u8 nimm;
+	u8 iam;
+	u64 aisma;
+	u32 rsv0:6;
+	u32 g:1;
+	u32 c:1;
+	u32 rsv1:24;
+	u64 rsv2;
+	u32 count;
+} __packed;
+
+union kvm_s390_gisa {
+	struct kvm_s390_gisa_f0 f0;
+	struct kvm_s390_gisa_f1 f1;
+};
+
+struct kvm_s390_gait {
+	u32 gd;
+	u16      : 5;
+	u16 gisc : 3;
+	u16 rpu  : 8;
+	u16        : 10;
+	u16 gaisbo :  6;
+	u64 gaisba;
+} __packed;
+
+struct kvm_s390_aifte {
+	u64 faisba;
+	u64 gaita;
+	u16 simm : 8;
+	u16      : 5;
+	u16 afi  : 3;
+	u16 reserved1;
+	u16 reserved2;
+	u16 faal;
+} __packed;
+
+struct kvm_s390_gib {
+	u32 alo;
+	u32 reserved1;
+	u32      : 5;
+	u32 nisc : 3;
+	u32      : 24;
+	u8 reserverd2[20];
+} __packed;
+
 struct kvm_s390_local_interrupt {
 	spinlock_t lock;
 	struct list_head list;
@@ -420,6 +485,9 @@ struct kvm_arch{
 	struct s390_io_adapter *adapters[MAX_S390_IO_ADAPTERS];
 	wait_queue_head_t ipte_wq;
 	spinlock_t start_stop_lock;
+	union kvm_s390_gisa *gisa;
+	unsigned long iam;
+	atomic_t in_sie;
 };
 
 #define KVM_HVA_ERR_BAD		(-1UL)
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -404,6 +404,16 @@ long kvm_arch_vm_ioctl(struct file *filp
 	return r;
 }
 
+static u8 kvm_s390_gisa_get_alert_mask(struct kvm *kvm)
+{
+	return (u8)ACCESS_ONCE(kvm->arch.iam);
+}
+
+static void kvm_s390_gisa_set_alert_mask(struct kvm *kvm, u8 iam)
+{
+	xchg(&kvm->arch.iam, iam);
+}
+
 int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 {
 	int rc;
@@ -461,6 +471,14 @@ int kvm_arch_init_vm(struct kvm *kvm, un
 	kvm->arch.css_support = 0;
 	kvm->arch.use_irqchip = 0;
 
+	kvm->arch.gisa = (union kvm_s390_gisa *)get_zeroed_page(
+			GFP_KERNEL | GFP_DMA);
+	if (!kvm->arch.gisa)
+		goto out_nogmap;
+	kvm_s390_gisa_set_next_alert(kvm, (u32)(unsigned long)kvm->arch.gisa);
+	kvm_s390_gisa_set_alert_mask(kvm, 0);
+	atomic_set(&kvm->arch.in_sie, 0);
+
 	spin_lock_init(&kvm->arch.start_stop_lock);
 
 	return 0;
@@ -520,6 +538,7 @@ void kvm_arch_sync_events(struct kvm *kv
 
 void kvm_arch_destroy_vm(struct kvm *kvm)
 {
+	free_page((unsigned long)kvm->arch.gisa);
 	kvm_free_vcpus(kvm);
 	free_page((unsigned long)(kvm->arch.sca));
 	debug_unregister(kvm->arch.dbf);
@@ -656,6 +675,19 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu
 	return rc;
 }
 
+u32 kvm_s390_gisa_get_fmt(void)
+{
+	if (test_facility(70) || test_facility(72))
+		return KVM_S390_GISA_FORMAT_1;
+	else
+		return KVM_S390_GISA_FORMAT_0;
+}
+
+static u32 kvm_s390_build_gd(struct kvm *kvm)
+{
+	return (u32)(unsigned long)kvm->arch.gisa | kvm_s390_gisa_get_fmt();
+}
+
 struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
 				      unsigned int id)
 {
@@ -699,6 +731,7 @@ struct kvm_vcpu *kvm_arch_vcpu_create(st
 	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;
+	vcpu->arch.sie_block->gd = kvm_s390_build_gd(kvm);
 
 	rc = kvm_vcpu_init(vcpu, kvm, id);
 	if (rc)
@@ -749,6 +782,132 @@ void exit_sie_sync(struct kvm_vcpu *vcpu
 	exit_sie(vcpu);
 }
 
+void kvm_s390_gisa_register_alert(struct kvm *kvm, u32 gisc)
+{
+	int bito = BITS_PER_BYTE * 7 + gisc;
+
+	set_bit(bito ^ (BITS_PER_LONG - 1), &kvm->arch.iam);
+}
+
+void kvm_s390_gisa_unregister_alert(struct kvm *kvm, u32 gisc)
+{
+	int bito = BITS_PER_BYTE * 7 + gisc;
+
+	clear_bit(bito ^ (BITS_PER_LONG - 1), &kvm->arch.iam);
+}
+
+u32 __kvm_s390_gisa_get_next_alert(union kvm_s390_gisa *gisa)
+{
+	return ACCESS_ONCE(gisa->f0.next_alert);
+}
+
+u32 kvm_s390_gisa_get_next_alert(struct kvm *kvm)
+{
+	return __kvm_s390_gisa_get_next_alert(
+		(union kvm_s390_gisa *)kvm->arch.gisa);
+}
+
+void __kvm_s390_gisa_set_next_alert(union kvm_s390_gisa *gisa, u32 val)
+{
+	xchg(&gisa->f0.next_alert, val);
+}
+
+void kvm_s390_gisa_set_next_alert(struct kvm *kvm, u32 val)
+{
+	__kvm_s390_gisa_set_next_alert(kvm->arch.gisa, val);
+}
+
+u8 kvm_s390_gisa_get_iam(struct kvm *kvm)
+{
+	return ACCESS_ONCE(kvm->arch.gisa->f0.iam);
+}
+
+void kvm_s390_gisa_set_iam(struct kvm *kvm, u8 iam)
+{
+	xchg(&kvm->arch.gisa->f0.iam, iam);
+}
+
+int kvm_s390_gisa_test_iam_gisc(struct kvm *kvm, u32 gisc)
+{
+	int bito = BITS_PER_BYTE * 7 + gisc;
+	unsigned long *addr = (unsigned long *)kvm->arch.gisa;
+
+	return test_bit(bito ^ (BITS_PER_LONG - 1), addr);
+}
+
+u8 kvm_s390_gisa_get_ipm(struct kvm *kvm)
+{
+	return ACCESS_ONCE(kvm->arch.gisa->f0.ipm);
+}
+
+void kvm_s390_gisa_set_ipm(struct kvm *kvm, u8 ipm)
+{
+	xchg(&kvm->arch.gisa->f0.ipm, ipm);
+}
+
+int kvm_s390_gisa_test_ipm_gisc(struct kvm *kvm, u32 gisc)
+{
+	int bito = BITS_PER_BYTE * 4 + gisc;
+	unsigned long *addr = (unsigned long *)kvm->arch.gisa;
+
+	return test_bit(bito ^ (BITS_PER_LONG - 1), addr);
+}
+
+void kvm_s390_gisa_set_ipm_gisc(struct kvm *kvm, u32 gisc)
+{
+	int bito = gisc + 32;
+	unsigned long *addr = (unsigned long *)kvm->arch.gisa;
+
+	set_bit(bito ^ (BITS_PER_LONG - 1), addr);
+}
+
+u32 kvm_s390_gisa_get_g(struct kvm *kvm)
+{
+	u32 fmt, bito;
+	unsigned long *addr;
+
+	fmt = kvm_s390_gisa_get_fmt();
+	if (fmt == KVM_S390_GISA_FORMAT_0) {
+		addr = (unsigned long *)kvm->arch.gisa;
+		bito = BITS_PER_BYTE * 6 + 6;
+	} else {
+		addr = (unsigned long *)((u8 *)kvm->arch.gisa + 16);
+		bito = 6;
+	}
+
+	return test_bit(bito ^ (BITS_PER_LONG - 1), addr);
+}
+
+u32 kvm_s390_gisa_get_c(struct kvm *kvm)
+{
+	u32 fmt, bito;
+	unsigned long *addr;
+
+	fmt = kvm_s390_gisa_get_fmt();
+	if (fmt == KVM_S390_GISA_FORMAT_0) {
+		addr = (unsigned long *)kvm->arch.gisa;
+		bito = BITS_PER_BYTE * 6 + 7;
+	} else {
+		addr = (unsigned long *)((u8 *)kvm->arch.gisa + 16);
+		bito = 7;
+	}
+
+	return test_bit(bito ^ (BITS_PER_LONG - 1), addr);
+}
+
+u32 kvm_s390_gisa_get_count(struct kvm *kvm)
+{
+	u32 fmt, cnt;
+
+	fmt = kvm_s390_gisa_get_fmt();
+	if (fmt == KVM_S390_GISA_FORMAT_0)
+		cnt = ACCESS_ONCE(kvm->arch.gisa->f0.count);
+	else
+		cnt = ACCESS_ONCE(kvm->arch.gisa->f1.count);
+
+	return cnt;
+}
+
 static void kvm_gmap_notifier(struct gmap *gmap, unsigned long address)
 {
 	int i;
@@ -1284,8 +1443,16 @@ static int __vcpu_run(struct kvm_vcpu *v
 		preempt_disable();
 		kvm_guest_enter();
 		preempt_enable();
+
+		atomic_inc(&vcpu->kvm->arch.in_sie);
+		kvm_s390_gisa_set_iam(vcpu->kvm, 0);
+
 		exit_reason = sie64a(vcpu->arch.sie_block,
 				     vcpu->run->s.regs.gprs);
+		if (atomic_dec_and_test(&vcpu->kvm->arch.in_sie))
+			kvm_s390_gisa_set_iam(vcpu->kvm,
+				kvm_s390_gisa_get_alert_mask(vcpu->kvm));
+
 		kvm_guest_exit();
 		vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
 
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -122,6 +122,17 @@ static inline u64 kvm_s390_get_base_disp
 	return (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + disp2;
 }
 
+static inline u64 kvm_s390_get_base_disp_rxy(struct kvm_vcpu *vcpu)
+{
+	u32 x2 = (vcpu->arch.sie_block->ipa & 0x000f);
+	u32 base2 = vcpu->arch.sie_block->ipb >> 28;
+	u32 disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16) +
+		((vcpu->arch.sie_block->ipb & 0xff00) << 4);
+
+	return (base2 ? vcpu->run->s.regs.gprs[base2] : 0) +
+		(x2 ? vcpu->run->s.regs.gprs[x2] : 0) + (u64)disp2;
+}
+
 /* Set the condition code in the guest program status word */
 static inline void kvm_s390_set_psw_cc(struct kvm_vcpu *vcpu, unsigned long cc)
 {
@@ -180,6 +191,23 @@ void exit_sie(struct kvm_vcpu *vcpu);
 void exit_sie_sync(struct kvm_vcpu *vcpu);
 int kvm_s390_vcpu_setup_cmma(struct kvm_vcpu *vcpu);
 void kvm_s390_vcpu_unsetup_cmma(struct kvm_vcpu *vcpu);
+u32 kvm_s390_gisa_get_fmt(void);
+void kvm_s390_gisa_register_alert(struct kvm *kvm, u32 gisc);
+void kvm_s390_gisa_unregister_alert(struct kvm *kvm, u32 gisc);
+u32 __kvm_s390_gisa_get_next_alert(union kvm_s390_gisa *gisa);
+u32 kvm_s390_gisa_get_next_alert(struct kvm *kvm);
+void __kvm_s390_gisa_set_next_alert(union kvm_s390_gisa *gisa, u32 val);
+void kvm_s390_gisa_set_next_alert(struct kvm *kvm, u32 val);
+u8 kvm_s390_gisa_get_iam(struct kvm *kvm);
+void kvm_s390_gisa_set_iam(struct kvm *kvm, u8 value);
+int kvm_s390_gisa_test_iam_gisc(struct kvm *kvm, u32 gisc);
+u8 kvm_s390_gisa_get_ipm(struct kvm *kvm);
+void kvm_s390_gisa_set_ipm(struct kvm *kvm, u8 value);
+int kvm_s390_gisa_test_ipm_gisc(struct kvm *kvm, u32 gisc);
+void kvm_s390_gisa_set_ipm_gisc(struct kvm *kvm, u32 gisc);
+u32 kvm_s390_gisa_get_g(struct kvm *kvm);
+u32 kvm_s390_gisa_get_c(struct kvm *kvm);
+u32 kvm_s390_gisa_get_count(struct kvm *kvm);
 /* is cmma enabled */
 bool kvm_s390_cmma_enabled(struct kvm *kvm);
 int test_vfacility(unsigned long nr);

  parent reply	other threads:[~2014-09-04 10:52 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-09-04 10:52 [RFC][patch 0/6] pci pass-through support for qemu/KVM on s390 frank.blaschka
2014-09-04 10:52 ` [Qemu-devel] " frank.blaschka
2014-09-04 10:52 ` [RFC][patch 1/6] s390: cio: chsc function to register GIB frank.blaschka
2014-09-04 10:52   ` [Qemu-devel] " frank.blaschka
2014-09-04 10:52 ` [RFC][patch 2/6] s390: pci: export pci functions for pass-through usage frank.blaschka
2014-09-04 10:52   ` [Qemu-devel] " frank.blaschka
2014-09-04 10:52 ` frank.blaschka [this message]
2014-09-04 10:52   ` [Qemu-devel] [RFC][patch 3/6] KVM: s390: Add GISA support frank.blaschka
2014-09-04 14:19   ` Heiko Carstens
2014-09-04 14:19     ` [Qemu-devel] " Heiko Carstens
2014-09-05  8:29   ` Alexander Graf
2014-09-05  8:29     ` [Qemu-devel] " Alexander Graf
2014-09-05 10:52     ` Frank Blaschka
2014-09-05 10:52       ` [Qemu-devel] " Frank Blaschka
2014-09-04 10:52 ` [RFC][patch 4/6] KVM: s390: Add PCI pass-through support frank.blaschka
2014-09-04 10:52   ` [Qemu-devel] " frank.blaschka
2014-09-05  8:37   ` Alexander Graf
2014-09-05  8:37     ` [Qemu-devel] " Alexander Graf
2014-09-04 10:52 ` [RFC][patch 5/6] s390: Add PCI bus support frank.blaschka
2014-09-04 10:52   ` [Qemu-devel] " frank.blaschka
2014-09-04 10:52 ` [RFC][patch 6/6] s390: Add PCI pass-through device support frank.blaschka
2014-09-04 10:52   ` [Qemu-devel] " frank.blaschka
2014-09-04 13:16 ` [RFC][patch 0/6] pci pass-through support for qemu/KVM on s390 Alex Williamson
2014-09-04 13:16   ` [Qemu-devel] " Alex Williamson
2014-09-05  7:46   ` Frank Blaschka
2014-09-05  7:46     ` [Qemu-devel] " Frank Blaschka
2014-09-05  8:35     ` Alexander Graf
2014-09-05  8:35       ` [Qemu-devel] " Alexander Graf
2014-09-05 11:55       ` Frank Blaschka
2014-09-05 11:55         ` [Qemu-devel] " Frank Blaschka
2014-09-05 23:03         ` Alexander Graf
2014-09-05 23:03           ` [Qemu-devel] " Alexander Graf
2014-09-05  8:21 ` Alexander Graf
2014-09-05  8:21   ` [Qemu-devel] " Alexander Graf
2014-09-05 11:39   ` Frank Blaschka
2014-09-05 11:39     ` [Qemu-devel] " Frank Blaschka
2014-09-05 23:19     ` Alexander Graf
2014-09-05 23:19       ` [Qemu-devel] " Alexander Graf
2014-09-08  9:20       ` Paolo Bonzini
2014-09-08  9:20         ` [Qemu-devel] " Paolo Bonzini
2014-09-08 14:19         ` Alex Williamson
2014-09-08 14:19           ` [Qemu-devel] " Alex Williamson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20140904105337.081387456@de.ibm.com \
    --to=frank.blaschka@de.ibm.com \
    --cc=agraf@suse.de \
    --cc=aik@ozlabs.ru \
    --cc=kvm@vger.kernel.org \
    --cc=linux-s390@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.