|
|
@@ -109,8 +109,69 @@ static int handle_instruction(struct kvm_vcpu *vcpu)
|
|
|
return -EOPNOTSUPP;
|
|
|
}
|
|
|
|
|
|
+static void __extract_prog_irq(struct kvm_vcpu *vcpu,
|
|
|
+ struct kvm_s390_pgm_info *pgm_info)
|
|
|
+{
|
|
|
+ memset(pgm_info, 0, sizeof(struct kvm_s390_pgm_info));
|
|
|
+ pgm_info->code = vcpu->arch.sie_block->iprcc;
|
|
|
+
|
|
|
+ switch (vcpu->arch.sie_block->iprcc & ~PGM_PER) {
|
|
|
+ case PGM_AFX_TRANSLATION:
|
|
|
+ case PGM_ASX_TRANSLATION:
|
|
|
+ case PGM_EX_TRANSLATION:
|
|
|
+ case PGM_LFX_TRANSLATION:
|
|
|
+ case PGM_LSTE_SEQUENCE:
|
|
|
+ case PGM_LSX_TRANSLATION:
|
|
|
+ case PGM_LX_TRANSLATION:
|
|
|
+ case PGM_PRIMARY_AUTHORITY:
|
|
|
+ case PGM_SECONDARY_AUTHORITY:
|
|
|
+ case PGM_SPACE_SWITCH:
|
|
|
+ pgm_info->trans_exc_code = vcpu->arch.sie_block->tecmc;
|
|
|
+ break;
|
|
|
+ case PGM_ALEN_TRANSLATION:
|
|
|
+ case PGM_ALE_SEQUENCE:
|
|
|
+ case PGM_ASTE_INSTANCE:
|
|
|
+ case PGM_ASTE_SEQUENCE:
|
|
|
+ case PGM_ASTE_VALIDITY:
|
|
|
+ case PGM_EXTENDED_AUTHORITY:
|
|
|
+ pgm_info->exc_access_id = vcpu->arch.sie_block->eai;
|
|
|
+ break;
|
|
|
+ case PGM_ASCE_TYPE:
|
|
|
+ case PGM_PAGE_TRANSLATION:
|
|
|
+ case PGM_REGION_FIRST_TRANS:
|
|
|
+ case PGM_REGION_SECOND_TRANS:
|
|
|
+ case PGM_REGION_THIRD_TRANS:
|
|
|
+ case PGM_SEGMENT_TRANSLATION:
|
|
|
+ pgm_info->trans_exc_code = vcpu->arch.sie_block->tecmc;
|
|
|
+ pgm_info->exc_access_id = vcpu->arch.sie_block->eai;
|
|
|
+ pgm_info->op_access_id = vcpu->arch.sie_block->oai;
|
|
|
+ break;
|
|
|
+ case PGM_MONITOR:
|
|
|
+ pgm_info->mon_class_nr = vcpu->arch.sie_block->mcn;
|
|
|
+ pgm_info->mon_code = vcpu->arch.sie_block->tecmc;
|
|
|
+ break;
|
|
|
+ case PGM_DATA:
|
|
|
+ pgm_info->data_exc_code = vcpu->arch.sie_block->dxc;
|
|
|
+ break;
|
|
|
+ case PGM_PROTECTION:
|
|
|
+ pgm_info->trans_exc_code = vcpu->arch.sie_block->tecmc;
|
|
|
+ pgm_info->exc_access_id = vcpu->arch.sie_block->eai;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (vcpu->arch.sie_block->iprcc & PGM_PER) {
|
|
|
+ pgm_info->per_code = vcpu->arch.sie_block->perc;
|
|
|
+ pgm_info->per_atmid = vcpu->arch.sie_block->peratmid;
|
|
|
+ pgm_info->per_address = vcpu->arch.sie_block->peraddr;
|
|
|
+ pgm_info->per_access_id = vcpu->arch.sie_block->peraid;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static int handle_prog(struct kvm_vcpu *vcpu)
|
|
|
{
|
|
|
+ struct kvm_s390_pgm_info pgm_info;
|
|
|
struct kvm_s390_itdb *itdb;
|
|
|
int rc;
|
|
|
|
|
|
@@ -128,7 +189,9 @@ static int handle_prog(struct kvm_vcpu *vcpu)
|
|
|
memset(itdb, 0, sizeof(*itdb));
|
|
|
skip_itdb:
|
|
|
trace_kvm_s390_intercept_prog(vcpu, vcpu->arch.sie_block->iprcc);
|
|
|
- return kvm_s390_inject_program_int(vcpu, vcpu->arch.sie_block->iprcc);
|
|
|
+ __extract_prog_irq(vcpu, &pgm_info);
|
|
|
+
|
|
|
+ return kvm_s390_inject_prog_irq(vcpu, &pgm_info);
|
|
|
}
|
|
|
|
|
|
static int handle_instruction_and_prog(struct kvm_vcpu *vcpu)
|