diff options
| -rw-r--r-- | arch/s390/kvm/interrupt.c | 25 |
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 | */ | ||
| 261 | static 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 | |||
| 252 | static inline void gisa_set_ipm_gisc(struct kvm_s390_gisa *gisa, u32 gisc) | 271 | static 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 | ||
