diff mbox series

[v2,03/12] KVM: s390: add the GIB and its related life-cyle functions

Message ID 20181119172536.52649-4-mimu@linux.ibm.com (mailing list archive)
State New, archived
Headers show
Series KVM: s390: make use of the GIB | expand

Commit Message

Michael Mueller Nov. 19, 2018, 5:25 p.m. UTC
The GIB (Guest Information Block) links the GISA of all guests
that have adapter interrupts pending. These interrupts cannot be
deliverd because no vcpu of these guests is currently running in
SIE context. Instead, a GIB alert is issued on the host to schedule
these guests to run.

This mechanism allows to process adapter interrupts for currently
not running guests.

The GIB is created during host initialization and associated with
the Adapter Interruption Facility in case an Adapter Interruption
Virtualization Facility is available.

Signed-off-by: Michael Mueller <mimu@linux.ibm.com>
Reviewed-by: Janosch Frank <frankja@linux.ibm.com>
Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>
---
 arch/s390/include/asm/kvm_host.h | 10 ++++++++++
 arch/s390/kvm/interrupt.c        | 37 +++++++++++++++++++++++++++++++++++++
 arch/s390/kvm/kvm-s390.c         |  1 +
 arch/s390/kvm/kvm-s390.h         |  2 ++
 4 files changed, 50 insertions(+)

Comments

Cornelia Huck Nov. 26, 2018, 4:32 p.m. UTC | #1
On Mon, 19 Nov 2018 18:25:27 +0100
Michael Mueller <mimu@linux.ibm.com> wrote:

> The GIB (Guest Information Block) links the GISA of all guests
> that have adapter interrupts pending. These interrupts cannot be
> deliverd because no vcpu of these guests is currently running in

s/deliverd/delivered/

> SIE context. Instead, a GIB alert is issued on the host to schedule
> these guests to run.
> 
> This mechanism allows to process adapter interrupts for currently
> not running guests.
> 
> The GIB is created during host initialization and associated with
> the Adapter Interruption Facility in case an Adapter Interruption
> Virtualization Facility is available.
> 
> Signed-off-by: Michael Mueller <mimu@linux.ibm.com>
> Reviewed-by: Janosch Frank <frankja@linux.ibm.com>
> Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>
> ---
>  arch/s390/include/asm/kvm_host.h | 10 ++++++++++
>  arch/s390/kvm/interrupt.c        | 37 +++++++++++++++++++++++++++++++++++++
>  arch/s390/kvm/kvm-s390.c         |  1 +
>  arch/s390/kvm/kvm-s390.h         |  2 ++
>  4 files changed, 50 insertions(+)
> 
> diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
> index d5d24889c3bc..537e5e59f27e 100644
> --- a/arch/s390/include/asm/kvm_host.h
> +++ b/arch/s390/include/asm/kvm_host.h
> @@ -785,6 +785,15 @@ struct kvm_s390_gisa {
>  	};
>  };
>  
> +struct kvm_s390_gib {
> +	u32 alert_list_origin;
> +	u32 reserved01;
> +	u8:5;
> +	u8  nisc:3;
> +	u8  reserved03[3];
> +	u32 reserved04[5];
> +};
> +
>  /*
>   * sie_page2 has to be allocated as DMA because fac_list, crycb and
>   * gisa need 31bit addresses in the sie control block.
> @@ -838,6 +847,7 @@ struct kvm_arch{
>  	/* subset of available cpu features enabled by user space */
>  	DECLARE_BITMAP(cpu_feat, KVM_S390_VM_CPU_FEAT_NR_BITS);
>  	struct kvm_s390_gisa *gisa;
> +	int gib_in_use;
>  };
>  
>  #define KVM_HVA_ERR_BAD		(-1UL)
> diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
> index 1f4c0c7286f7..2149059e9e17 100644
> --- a/arch/s390/kvm/interrupt.c
> +++ b/arch/s390/kvm/interrupt.c
> @@ -31,6 +31,8 @@
>  #define PFAULT_DONE 0x0680
>  #define VIRTIO_PARAM 0x0d00
>  
> +static struct kvm_s390_gib *gib;
> +
>  /* handle external calls via sigp interpretation facility */
>  static int sca_ext_call_pending(struct kvm_vcpu *vcpu, int *src_id)
>  {
> @@ -2895,6 +2897,7 @@ void kvm_s390_gisa_init(struct kvm *kvm)
>  		kvm->arch.gisa = &kvm->arch.sie_page2->gisa;
>  		VM_EVENT(kvm, 3, "gisa 0x%pK initialized", kvm->arch.gisa);
>  		kvm_s390_gisa_clear(kvm);
> +		kvm->arch.gib_in_use = !!gib;

So, that's basically gib && aiv?

>  	}
>  }
>  
> @@ -2904,3 +2907,37 @@ void kvm_s390_gisa_destroy(struct kvm *kvm)
>  		return;
>  	kvm->arch.gisa = NULL;
>  }
> +
> +void kvm_s390_gib_destroy(void)
> +{
> +	if (!gib)
> +		return;
> +	chsc_sgib(0);
> +	free_page((unsigned long)gib);
> +	gib = NULL;
> +}
> +
> +int kvm_s390_gib_init(u8 nisc)
> +{
> +	if (!css_general_characteristics.aiv) {
> +		KVM_EVENT(3, "%s", "gib not initialized, no AIV facility");
> +		return 0;
> +	}
> +
> +	gib = (struct kvm_s390_gib *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
> +	if (!gib) {
> +		KVM_EVENT(3, "gib 0x%pK memory allocation failed", gib);
> +		return -ENOMEM;
> +	}
> +
> +	gib->nisc = nisc;
> +	if (chsc_sgib((u32)(u64)gib)) {
> +		KVM_EVENT(3, "gib 0x%pK AIV association failed", gib);
> +		free_page((unsigned long)gib);
> +		gib = NULL;
> +		return -EIO;
> +	}
> +
> +	KVM_EVENT(3, "gib 0x%pK (nisc=%d) initialized", gib, gib->nisc);
> +	return 0;
> +}

And given that you now fail initializing the vm if aiv is present but
you could not setup the gib (which makes sense), isn't it enough to
either check for aiv or gib, instead of adding gib_in_use? (There's
always a pointer to a valid gisa if aiv.) What am I missing?
Michael Mueller Nov. 27, 2018, 5:12 p.m. UTC | #2
On 26.11.18 17:32, Cornelia Huck wrote:
> On Mon, 19 Nov 2018 18:25:27 +0100
> Michael Mueller <mimu@linux.ibm.com> wrote:
> 
>> The GIB (Guest Information Block) links the GISA of all guests
>> that have adapter interrupts pending. These interrupts cannot be
>> deliverd because no vcpu of these guests is currently running in
> 
> s/deliverd/delivered/

tx

> 
>> SIE context. Instead, a GIB alert is issued on the host to schedule
>> these guests to run.
>>
>> This mechanism allows to process adapter interrupts for currently
>> not running guests.
>>
>> The GIB is created during host initialization and associated with
>> the Adapter Interruption Facility in case an Adapter Interruption
>> Virtualization Facility is available.
>>
>> Signed-off-by: Michael Mueller <mimu@linux.ibm.com>
>> Reviewed-by: Janosch Frank <frankja@linux.ibm.com>
>> Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>
>> ---
>>   arch/s390/include/asm/kvm_host.h | 10 ++++++++++
>>   arch/s390/kvm/interrupt.c        | 37 +++++++++++++++++++++++++++++++++++++
>>   arch/s390/kvm/kvm-s390.c         |  1 +
>>   arch/s390/kvm/kvm-s390.h         |  2 ++
>>   4 files changed, 50 insertions(+)
>>
>> diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
>> index d5d24889c3bc..537e5e59f27e 100644
>> --- a/arch/s390/include/asm/kvm_host.h
>> +++ b/arch/s390/include/asm/kvm_host.h
>> @@ -785,6 +785,15 @@ struct kvm_s390_gisa {
>>   	};
>>   };
>>   
>> +struct kvm_s390_gib {
>> +	u32 alert_list_origin;
>> +	u32 reserved01;
>> +	u8:5;
>> +	u8  nisc:3;
>> +	u8  reserved03[3];
>> +	u32 reserved04[5];
>> +};
>> +
>>   /*
>>    * sie_page2 has to be allocated as DMA because fac_list, crycb and
>>    * gisa need 31bit addresses in the sie control block.
>> @@ -838,6 +847,7 @@ struct kvm_arch{
>>   	/* subset of available cpu features enabled by user space */
>>   	DECLARE_BITMAP(cpu_feat, KVM_S390_VM_CPU_FEAT_NR_BITS);
>>   	struct kvm_s390_gisa *gisa;
>> +	int gib_in_use;
>>   };
>>   
>>   #define KVM_HVA_ERR_BAD		(-1UL)
>> diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
>> index 1f4c0c7286f7..2149059e9e17 100644
>> --- a/arch/s390/kvm/interrupt.c
>> +++ b/arch/s390/kvm/interrupt.c
>> @@ -31,6 +31,8 @@
>>   #define PFAULT_DONE 0x0680
>>   #define VIRTIO_PARAM 0x0d00
>>   
>> +static struct kvm_s390_gib *gib;
>> +
>>   /* handle external calls via sigp interpretation facility */
>>   static int sca_ext_call_pending(struct kvm_vcpu *vcpu, int *src_id)
>>   {
>> @@ -2895,6 +2897,7 @@ void kvm_s390_gisa_init(struct kvm *kvm)
>>   		kvm->arch.gisa = &kvm->arch.sie_page2->gisa;
>>   		VM_EVENT(kvm, 3, "gisa 0x%pK initialized", kvm->arch.gisa);
>>   		kvm_s390_gisa_clear(kvm);
>> +		kvm->arch.gib_in_use = !!gib;
> 
> So, that's basically gib && aiv?
> 
>>   	}
>>   }
>>   
>> @@ -2904,3 +2907,37 @@ void kvm_s390_gisa_destroy(struct kvm *kvm)
>>   		return;
>>   	kvm->arch.gisa = NULL;
>>   }
>> +
>> +void kvm_s390_gib_destroy(void)
>> +{
>> +	if (!gib)
>> +		return;
>> +	chsc_sgib(0);
>> +	free_page((unsigned long)gib);
>> +	gib = NULL;
>> +}
>> +
>> +int kvm_s390_gib_init(u8 nisc)
>> +{
>> +	if (!css_general_characteristics.aiv) {
>> +		KVM_EVENT(3, "%s", "gib not initialized, no AIV facility");
>> +		return 0;
>> +	}
>> +
>> +	gib = (struct kvm_s390_gib *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
>> +	if (!gib) {
>> +		KVM_EVENT(3, "gib 0x%pK memory allocation failed", gib);
>> +		return -ENOMEM;
>> +	}
>> +
>> +	gib->nisc = nisc;
>> +	if (chsc_sgib((u32)(u64)gib)) {
>> +		KVM_EVENT(3, "gib 0x%pK AIV association failed", gib);
>> +		free_page((unsigned long)gib);
>> +		gib = NULL;
>> +		return -EIO;
>> +	}
>> +
>> +	KVM_EVENT(3, "gib 0x%pK (nisc=%d) initialized", gib, gib->nisc);
>> +	return 0;
>> +}
> 
> And given that you now fail initializing the vm if aiv is present but
> you could not setup the gib (which makes sense), isn't it enough to
> either check for aiv or gib, instead of adding gib_in_use? (There's
> always a pointer to a valid gisa if aiv.) What am I missing?

In addition there is the vSIE case where I have no AIV and thus no GISA.

>
Cornelia Huck Nov. 27, 2018, 5:21 p.m. UTC | #3
On Tue, 27 Nov 2018 18:12:07 +0100
Michael Mueller <mimu@linux.ibm.com> wrote:

> On 26.11.18 17:32, Cornelia Huck wrote:
> > On Mon, 19 Nov 2018 18:25:27 +0100
> > Michael Mueller <mimu@linux.ibm.com> wrote:

> >> @@ -2895,6 +2897,7 @@ void kvm_s390_gisa_init(struct kvm *kvm)
> >>   		kvm->arch.gisa = &kvm->arch.sie_page2->gisa;
> >>   		VM_EVENT(kvm, 3, "gisa 0x%pK initialized", kvm->arch.gisa);
> >>   		kvm_s390_gisa_clear(kvm);
> >> +		kvm->arch.gib_in_use = !!gib;  
> > 
> > So, that's basically gib && aiv?
> >   
> >>   	}
> >>   }
> >>   
> >> @@ -2904,3 +2907,37 @@ void kvm_s390_gisa_destroy(struct kvm *kvm)
> >>   		return;
> >>   	kvm->arch.gisa = NULL;
> >>   }
> >> +
> >> +void kvm_s390_gib_destroy(void)
> >> +{
> >> +	if (!gib)
> >> +		return;
> >> +	chsc_sgib(0);
> >> +	free_page((unsigned long)gib);
> >> +	gib = NULL;
> >> +}
> >> +
> >> +int kvm_s390_gib_init(u8 nisc)
> >> +{
> >> +	if (!css_general_characteristics.aiv) {
> >> +		KVM_EVENT(3, "%s", "gib not initialized, no AIV facility");
> >> +		return 0;
> >> +	}
> >> +
> >> +	gib = (struct kvm_s390_gib *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
> >> +	if (!gib) {
> >> +		KVM_EVENT(3, "gib 0x%pK memory allocation failed", gib);
> >> +		return -ENOMEM;
> >> +	}
> >> +
> >> +	gib->nisc = nisc;
> >> +	if (chsc_sgib((u32)(u64)gib)) {
> >> +		KVM_EVENT(3, "gib 0x%pK AIV association failed", gib);
> >> +		free_page((unsigned long)gib);
> >> +		gib = NULL;
> >> +		return -EIO;
> >> +	}
> >> +
> >> +	KVM_EVENT(3, "gib 0x%pK (nisc=%d) initialized", gib, gib->nisc);
> >> +	return 0;
> >> +}  
> > 
> > And given that you now fail initializing the vm if aiv is present but
> > you could not setup the gib (which makes sense), isn't it enough to
> > either check for aiv or gib, instead of adding gib_in_use? (There's
> > always a pointer to a valid gisa if aiv.) What am I missing?  
> 
> In addition there is the vSIE case where I have no AIV and thus no GISA.

Yes, but that should be covered by a !aiv check, shouldn't it?
Michael Mueller Nov. 27, 2018, 6:05 p.m. UTC | #4
On 27.11.18 18:21, Cornelia Huck wrote:
> On Tue, 27 Nov 2018 18:12:07 +0100
> Michael Mueller <mimu@linux.ibm.com> wrote:
> 
>> On 26.11.18 17:32, Cornelia Huck wrote:
>>> On Mon, 19 Nov 2018 18:25:27 +0100
>>> Michael Mueller <mimu@linux.ibm.com> wrote:
> 
>>>> @@ -2895,6 +2897,7 @@ void kvm_s390_gisa_init(struct kvm *kvm)
>>>>    		kvm->arch.gisa = &kvm->arch.sie_page2->gisa;
>>>>    		VM_EVENT(kvm, 3, "gisa 0x%pK initialized", kvm->arch.gisa);
>>>>    		kvm_s390_gisa_clear(kvm);
>>>> +		kvm->arch.gib_in_use = !!gib;
>>>
>>> So, that's basically gib && aiv?
>>>    
>>>>    	}
>>>>    }
>>>>    
>>>> @@ -2904,3 +2907,37 @@ void kvm_s390_gisa_destroy(struct kvm *kvm)
>>>>    		return;
>>>>    	kvm->arch.gisa = NULL;
>>>>    }
>>>> +
>>>> +void kvm_s390_gib_destroy(void)
>>>> +{
>>>> +	if (!gib)
>>>> +		return;
>>>> +	chsc_sgib(0);
>>>> +	free_page((unsigned long)gib);
>>>> +	gib = NULL;
>>>> +}
>>>> +
>>>> +int kvm_s390_gib_init(u8 nisc)
>>>> +{
>>>> +	if (!css_general_characteristics.aiv) {
>>>> +		KVM_EVENT(3, "%s", "gib not initialized, no AIV facility");
>>>> +		return 0;
>>>> +	}
>>>> +
>>>> +	gib = (struct kvm_s390_gib *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
>>>> +	if (!gib) {
>>>> +		KVM_EVENT(3, "gib 0x%pK memory allocation failed", gib);
>>>> +		return -ENOMEM;
>>>> +	}
>>>> +
>>>> +	gib->nisc = nisc;
>>>> +	if (chsc_sgib((u32)(u64)gib)) {
>>>> +		KVM_EVENT(3, "gib 0x%pK AIV association failed", gib);
>>>> +		free_page((unsigned long)gib);
>>>> +		gib = NULL;
>>>> +		return -EIO;
>>>> +	}
>>>> +
>>>> +	KVM_EVENT(3, "gib 0x%pK (nisc=%d) initialized", gib, gib->nisc);
>>>> +	return 0;
>>>> +}
>>>
>>> And given that you now fail initializing the vm if aiv is present but
>>> you could not setup the gib (which makes sense), isn't it enough to
>>> either check for aiv or gib, instead of adding gib_in_use? (There's
>>> always a pointer to a valid gisa if aiv.) What am I missing?
>>
>> In addition there is the vSIE case where I have no AIV and thus no GISA.
> 
> Yes, but that should be covered by a !aiv check, shouldn't it?

Both checks are already there and the information is stored in:

kvm->arch.gisa != NULL

But it works only because a failing gib_init() drags everything down.

The functions where the test is used are semantically related to the
GIB, thus using (kvm->arch.gisa) as test might be confusing.

I will prepare and see how the codes reads...

Thanks a lot for your comments today!

Michael


>
Cornelia Huck Nov. 27, 2018, 7:06 p.m. UTC | #5
On Tue, 27 Nov 2018 19:05:44 +0100
Michael Mueller <mimu@linux.ibm.com> wrote:

> On 27.11.18 18:21, Cornelia Huck wrote:
> > On Tue, 27 Nov 2018 18:12:07 +0100
> > Michael Mueller <mimu@linux.ibm.com> wrote:
> >   
> >> On 26.11.18 17:32, Cornelia Huck wrote:  
> >>> On Mon, 19 Nov 2018 18:25:27 +0100
> >>> Michael Mueller <mimu@linux.ibm.com> wrote:  
> >   
> >>>> @@ -2895,6 +2897,7 @@ void kvm_s390_gisa_init(struct kvm *kvm)
> >>>>    		kvm->arch.gisa = &kvm->arch.sie_page2->gisa;
> >>>>    		VM_EVENT(kvm, 3, "gisa 0x%pK initialized", kvm->arch.gisa);
> >>>>    		kvm_s390_gisa_clear(kvm);
> >>>> +		kvm->arch.gib_in_use = !!gib;  
> >>>
> >>> So, that's basically gib && aiv?
> >>>      
> >>>>    	}
> >>>>    }
> >>>>    
> >>>> @@ -2904,3 +2907,37 @@ void kvm_s390_gisa_destroy(struct kvm *kvm)
> >>>>    		return;
> >>>>    	kvm->arch.gisa = NULL;
> >>>>    }
> >>>> +
> >>>> +void kvm_s390_gib_destroy(void)
> >>>> +{
> >>>> +	if (!gib)
> >>>> +		return;
> >>>> +	chsc_sgib(0);
> >>>> +	free_page((unsigned long)gib);
> >>>> +	gib = NULL;
> >>>> +}
> >>>> +
> >>>> +int kvm_s390_gib_init(u8 nisc)
> >>>> +{
> >>>> +	if (!css_general_characteristics.aiv) {
> >>>> +		KVM_EVENT(3, "%s", "gib not initialized, no AIV facility");
> >>>> +		return 0;
> >>>> +	}
> >>>> +
> >>>> +	gib = (struct kvm_s390_gib *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
> >>>> +	if (!gib) {
> >>>> +		KVM_EVENT(3, "gib 0x%pK memory allocation failed", gib);
> >>>> +		return -ENOMEM;
> >>>> +	}
> >>>> +
> >>>> +	gib->nisc = nisc;
> >>>> +	if (chsc_sgib((u32)(u64)gib)) {
> >>>> +		KVM_EVENT(3, "gib 0x%pK AIV association failed", gib);
> >>>> +		free_page((unsigned long)gib);
> >>>> +		gib = NULL;
> >>>> +		return -EIO;
> >>>> +	}
> >>>> +
> >>>> +	KVM_EVENT(3, "gib 0x%pK (nisc=%d) initialized", gib, gib->nisc);
> >>>> +	return 0;
> >>>> +}  
> >>>
> >>> And given that you now fail initializing the vm if aiv is present but
> >>> you could not setup the gib (which makes sense), isn't it enough to
> >>> either check for aiv or gib, instead of adding gib_in_use? (There's
> >>> always a pointer to a valid gisa if aiv.) What am I missing?  
> >>
> >> In addition there is the vSIE case where I have no AIV and thus no GISA.  
> > 
> > Yes, but that should be covered by a !aiv check, shouldn't it?  
> 
> Both checks are already there and the information is stored in:
> 
> kvm->arch.gisa != NULL
> 
> But it works only because a failing gib_init() drags everything down.
> 
> The functions where the test is used are semantically related to the
> GIB, thus using (kvm->arch.gisa) as test might be confusing.
> 
> I will prepare and see how the codes reads...

If it becomes too mushy, just leave it as it is now and I'll stop
complaining ;)

> 
> Thanks a lot for your comments today!
> 
> Michael
> 
> 
> >   
>
diff mbox series

Patch

diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index d5d24889c3bc..537e5e59f27e 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -785,6 +785,15 @@  struct kvm_s390_gisa {
 	};
 };
 
+struct kvm_s390_gib {
+	u32 alert_list_origin;
+	u32 reserved01;
+	u8:5;
+	u8  nisc:3;
+	u8  reserved03[3];
+	u32 reserved04[5];
+};
+
 /*
  * sie_page2 has to be allocated as DMA because fac_list, crycb and
  * gisa need 31bit addresses in the sie control block.
@@ -838,6 +847,7 @@  struct kvm_arch{
 	/* subset of available cpu features enabled by user space */
 	DECLARE_BITMAP(cpu_feat, KVM_S390_VM_CPU_FEAT_NR_BITS);
 	struct kvm_s390_gisa *gisa;
+	int gib_in_use;
 };
 
 #define KVM_HVA_ERR_BAD		(-1UL)
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 1f4c0c7286f7..2149059e9e17 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -31,6 +31,8 @@ 
 #define PFAULT_DONE 0x0680
 #define VIRTIO_PARAM 0x0d00
 
+static struct kvm_s390_gib *gib;
+
 /* handle external calls via sigp interpretation facility */
 static int sca_ext_call_pending(struct kvm_vcpu *vcpu, int *src_id)
 {
@@ -2895,6 +2897,7 @@  void kvm_s390_gisa_init(struct kvm *kvm)
 		kvm->arch.gisa = &kvm->arch.sie_page2->gisa;
 		VM_EVENT(kvm, 3, "gisa 0x%pK initialized", kvm->arch.gisa);
 		kvm_s390_gisa_clear(kvm);
+		kvm->arch.gib_in_use = !!gib;
 	}
 }
 
@@ -2904,3 +2907,37 @@  void kvm_s390_gisa_destroy(struct kvm *kvm)
 		return;
 	kvm->arch.gisa = NULL;
 }
+
+void kvm_s390_gib_destroy(void)
+{
+	if (!gib)
+		return;
+	chsc_sgib(0);
+	free_page((unsigned long)gib);
+	gib = NULL;
+}
+
+int kvm_s390_gib_init(u8 nisc)
+{
+	if (!css_general_characteristics.aiv) {
+		KVM_EVENT(3, "%s", "gib not initialized, no AIV facility");
+		return 0;
+	}
+
+	gib = (struct kvm_s390_gib *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+	if (!gib) {
+		KVM_EVENT(3, "gib 0x%pK memory allocation failed", gib);
+		return -ENOMEM;
+	}
+
+	gib->nisc = nisc;
+	if (chsc_sgib((u32)(u64)gib)) {
+		KVM_EVENT(3, "gib 0x%pK AIV association failed", gib);
+		free_page((unsigned long)gib);
+		gib = NULL;
+		return -EIO;
+	}
+
+	KVM_EVENT(3, "gib 0x%pK (nisc=%d) initialized", gib, gib->nisc);
+	return 0;
+}
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index fe24150ff666..a4ba9fa582fe 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -434,6 +434,7 @@  int kvm_arch_init(void *opaque)
 
 void kvm_arch_exit(void)
 {
+	kvm_s390_gib_destroy();
 	debug_unregister(kvm_s390_dbf);
 }
 
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index 1f6e36cdce0d..1a79105b0e9f 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -381,6 +381,8 @@  int kvm_s390_get_irq_state(struct kvm_vcpu *vcpu,
 void kvm_s390_gisa_init(struct kvm *kvm);
 void kvm_s390_gisa_clear(struct kvm *kvm);
 void kvm_s390_gisa_destroy(struct kvm *kvm);
+int kvm_s390_gib_init(u8 nisc);
+void kvm_s390_gib_destroy(void);
 
 /* implemented in guestdbg.c */
 void kvm_s390_backup_guest_per_regs(struct kvm_vcpu *vcpu);