aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Hildenbrand <dahi@linux.vnet.ibm.com>2014-03-03 04:55:13 -0500
committerChristian Borntraeger <borntraeger@de.ibm.com>2014-04-22 07:24:49 -0400
commit8712836b30cef5d49bc3bb8bc3da88a40e11e574 (patch)
tree592631e765885ec2c3a10bfdaa8aaf087b3297ac
parent439716a5cab30e930bd1ec0f8fd66cbbaa319250 (diff)
KVM: s390: deliver program irq parameters and use correct ilc
When a program interrupt was to be delivered until now, no program interrupt parameters were stored in the low-core of the target vcpu. This patch enables the delivery of those program interrupt parameters, takes care of concurrent PER events which can be injected in addition to any program interrupt and uses the correct instruction length code (depending on the interception code) for the injection of program interrupts. Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
-rw-r--r--arch/s390/include/asm/kvm_host.h6
-rw-r--r--arch/s390/kvm/interrupt.c110
2 files changed, 107 insertions, 9 deletions
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index b8c808192893..5e5a14db8c21 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -102,6 +102,12 @@ struct kvm_s390_sie_block {
102#define ICTL_RRBE 0x00001000 102#define ICTL_RRBE 0x00001000
103 __u32 ictl; /* 0x0048 */ 103 __u32 ictl; /* 0x0048 */
104 __u32 eca; /* 0x004c */ 104 __u32 eca; /* 0x004c */
105#define ICPT_INST 0x04
106#define ICPT_PROGI 0x08
107#define ICPT_INSTPROGI 0x0C
108#define ICPT_OPEREXC 0x2C
109#define ICPT_PARTEXEC 0x38
110#define ICPT_IOINST 0x40
105 __u8 icptcode; /* 0x0050 */ 111 __u8 icptcode; /* 0x0050 */
106 __u8 reserved51; /* 0x0051 */ 112 __u8 reserved51; /* 0x0051 */
107 __u16 ihcpu; /* 0x0052 */ 113 __u16 ihcpu; /* 0x0052 */
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 1c74bb92329b..c49b4d4d310a 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -174,6 +174,106 @@ static void __set_intercept_indicator(struct kvm_vcpu *vcpu,
174 } 174 }
175} 175}
176 176
177static int __deliver_prog_irq(struct kvm_vcpu *vcpu,
178 struct kvm_s390_pgm_info *pgm_info)
179{
180 const unsigned short table[] = { 2, 4, 4, 6 };
181 int rc = 0;
182
183 switch (pgm_info->code & ~PGM_PER) {
184 case PGM_AFX_TRANSLATION:
185 case PGM_ASX_TRANSLATION:
186 case PGM_EX_TRANSLATION:
187 case PGM_LFX_TRANSLATION:
188 case PGM_LSTE_SEQUENCE:
189 case PGM_LSX_TRANSLATION:
190 case PGM_LX_TRANSLATION:
191 case PGM_PRIMARY_AUTHORITY:
192 case PGM_SECONDARY_AUTHORITY:
193 case PGM_SPACE_SWITCH:
194 rc = put_guest_lc(vcpu, pgm_info->trans_exc_code,
195 (u64 *)__LC_TRANS_EXC_CODE);
196 break;
197 case PGM_ALEN_TRANSLATION:
198 case PGM_ALE_SEQUENCE:
199 case PGM_ASTE_INSTANCE:
200 case PGM_ASTE_SEQUENCE:
201 case PGM_ASTE_VALIDITY:
202 case PGM_EXTENDED_AUTHORITY:
203 rc = put_guest_lc(vcpu, pgm_info->exc_access_id,
204 (u8 *)__LC_EXC_ACCESS_ID);
205 break;
206 case PGM_ASCE_TYPE:
207 case PGM_PAGE_TRANSLATION:
208 case PGM_REGION_FIRST_TRANS:
209 case PGM_REGION_SECOND_TRANS:
210 case PGM_REGION_THIRD_TRANS:
211 case PGM_SEGMENT_TRANSLATION:
212 rc = put_guest_lc(vcpu, pgm_info->trans_exc_code,
213 (u64 *)__LC_TRANS_EXC_CODE);
214 rc |= put_guest_lc(vcpu, pgm_info->exc_access_id,
215 (u8 *)__LC_EXC_ACCESS_ID);
216 rc |= put_guest_lc(vcpu, pgm_info->op_access_id,
217 (u8 *)__LC_OP_ACCESS_ID);
218 break;
219 case PGM_MONITOR:
220 rc = put_guest_lc(vcpu, pgm_info->mon_class_nr,
221 (u64 *)__LC_MON_CLASS_NR);
222 rc |= put_guest_lc(vcpu, pgm_info->mon_code,
223 (u64 *)__LC_MON_CODE);
224 break;
225 case PGM_DATA:
226 rc = put_guest_lc(vcpu, pgm_info->data_exc_code,
227 (u32 *)__LC_DATA_EXC_CODE);
228 break;
229 case PGM_PROTECTION:
230 rc = put_guest_lc(vcpu, pgm_info->trans_exc_code,
231 (u64 *)__LC_TRANS_EXC_CODE);
232 rc |= put_guest_lc(vcpu, pgm_info->exc_access_id,
233 (u8 *)__LC_EXC_ACCESS_ID);
234 break;
235 }
236
237 if (pgm_info->code & PGM_PER) {
238 rc |= put_guest_lc(vcpu, pgm_info->per_code,
239 (u8 *) __LC_PER_CODE);
240 rc |= put_guest_lc(vcpu, pgm_info->per_atmid,
241 (u8 *)__LC_PER_ATMID);
242 rc |= put_guest_lc(vcpu, pgm_info->per_address,
243 (u64 *) __LC_PER_ADDRESS);
244 rc |= put_guest_lc(vcpu, pgm_info->per_access_id,
245 (u8 *) __LC_PER_ACCESS_ID);
246 }
247
248 switch (vcpu->arch.sie_block->icptcode) {
249 case ICPT_INST:
250 case ICPT_INSTPROGI:
251 case ICPT_OPEREXC:
252 case ICPT_PARTEXEC:
253 case ICPT_IOINST:
254 /* last instruction only stored for these icptcodes */
255 rc |= put_guest_lc(vcpu, table[vcpu->arch.sie_block->ipa >> 14],
256 (u16 *) __LC_PGM_ILC);
257 break;
258 case ICPT_PROGI:
259 rc |= put_guest_lc(vcpu, vcpu->arch.sie_block->pgmilc,
260 (u16 *) __LC_PGM_ILC);
261 break;
262 default:
263 rc |= put_guest_lc(vcpu, 0,
264 (u16 *) __LC_PGM_ILC);
265 }
266
267 rc |= put_guest_lc(vcpu, pgm_info->code,
268 (u16 *)__LC_PGM_INT_CODE);
269 rc |= write_guest_lc(vcpu, __LC_PGM_OLD_PSW,
270 &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
271 rc |= read_guest_lc(vcpu, __LC_PGM_NEW_PSW,
272 &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
273
274 return rc;
275}
276
177static void __do_deliver_interrupt(struct kvm_vcpu *vcpu, 277static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
178 struct kvm_s390_interrupt_info *inti) 278 struct kvm_s390_interrupt_info *inti)
179{ 279{
@@ -305,15 +405,7 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
305 vcpu->stat.deliver_program_int++; 405 vcpu->stat.deliver_program_int++;
306 trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, 406 trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
307 inti->pgm.code, 0); 407 inti->pgm.code, 0);
308 rc = put_guest_lc(vcpu, inti->pgm.code, 408 rc = __deliver_prog_irq(vcpu, &inti->pgm);
309 (u16 __user *)__LC_PGM_INT_CODE);
310 rc |= put_guest_lc(vcpu, table[vcpu->arch.sie_block->ipa >> 14],
311 (u16 __user *)__LC_PGM_ILC);
312 rc |= write_guest_lc(vcpu, __LC_PGM_OLD_PSW,
313 &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
314 rc |= read_guest_lc(vcpu, __LC_PGM_NEW_PSW,
315 &vcpu->arch.sie_block->gpsw,
316 sizeof(psw_t));
317 break; 409 break;
318 410
319 case KVM_S390_MCHK: 411 case KVM_S390_MCHK: