aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kvm/interrupt.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kvm/interrupt.c')
-rw-r--r--arch/s390/kvm/interrupt.c25
1 files changed, 22 insertions, 3 deletions
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 040745b23224..9faaa8f96fc3 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -249,6 +249,25 @@ static inline int gisa_set_iam(struct kvm_s390_gisa *gisa, u8 iam)
249 return 0; 249 return 0;
250} 250}
251 251
252/**
253 * gisa_clear_ipm - clear the GISA interruption pending mask
254 *
255 * @gisa: gisa to operate on
256 *
257 * Clear the IPM atomically with the next alert address and the IAM
258 * of the GISA unconditionally. All three fields are located in the
259 * first long word of the GISA.
260 */
261static inline void gisa_clear_ipm(struct kvm_s390_gisa *gisa)
262{
263 u64 word, _word;
264
265 do {
266 word = READ_ONCE(gisa->u64.word[0]);
267 _word = word & ~(0xffUL << 24);
268 } while (cmpxchg(&gisa->u64.word[0], word, _word) != word);
269}
270
252static inline void gisa_set_ipm_gisc(struct kvm_s390_gisa *gisa, u32 gisc) 271static inline void gisa_set_ipm_gisc(struct kvm_s390_gisa *gisa, u32 gisc)
253{ 272{
254 set_bit_inv(IPM_BIT_OFFSET + gisc, (unsigned long *) gisa); 273 set_bit_inv(IPM_BIT_OFFSET + gisc, (unsigned long *) gisa);
@@ -2926,8 +2945,7 @@ void kvm_s390_gisa_clear(struct kvm *kvm)
2926 2945
2927 if (!gi->origin) 2946 if (!gi->origin)
2928 return; 2947 return;
2929 memset(gi->origin, 0, sizeof(struct kvm_s390_gisa)); 2948 gisa_clear_ipm(gi->origin);
2930 gi->origin->next_alert = (u32)(u64)gi->origin;
2931 VM_EVENT(kvm, 3, "gisa 0x%pK cleared", gi->origin); 2949 VM_EVENT(kvm, 3, "gisa 0x%pK cleared", gi->origin);
2932} 2950}
2933 2951
@@ -2940,7 +2958,8 @@ void kvm_s390_gisa_init(struct kvm *kvm)
2940 gi->origin = &kvm->arch.sie_page2->gisa; 2958 gi->origin = &kvm->arch.sie_page2->gisa;
2941 gi->alert.mask = 0; 2959 gi->alert.mask = 0;
2942 spin_lock_init(&gi->alert.ref_lock); 2960 spin_lock_init(&gi->alert.ref_lock);
2943 kvm_s390_gisa_clear(kvm); 2961 memset(gi->origin, 0, sizeof(struct kvm_s390_gisa));
2962 gi->origin->next_alert = (u32)(u64)gi->origin;
2944 VM_EVENT(kvm, 3, "gisa 0x%pK initialized", gi->origin); 2963 VM_EVENT(kvm, 3, "gisa 0x%pK initialized", gi->origin);
2945} 2964}
2946 2965