KVM: s390: Add operation exception interception handler
authorJanosch Frank <frankja@linux.vnet.ibm.com>
Mon, 9 May 2016 12:14:01 +0000 (14:14 +0200)
committerChristian Borntraeger <borntraeger@de.ibm.com>
Fri, 10 Jun 2016 10:07:11 +0000 (12:07 +0200)
This commit introduces code that handles operation exception
interceptions. With this handler we can emulate instructions by using
illegal opcodes.

Signed-off-by: Janosch Frank <frankja@linux.vnet.ibm.com>
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
arch/s390/include/asm/kvm_host.h
arch/s390/kvm/intercept.c
arch/s390/kvm/kvm-s390.c
arch/s390/kvm/trace.h

index 37b9017c6a96b70d5a9460be9923a44663268ff8..093ea14109e2a1ca77c46d210d68a37a9c779e99 100644 (file)
@@ -255,6 +255,7 @@ struct kvm_vcpu_stat {
        u32 instruction_stctg;
        u32 exit_program_interruption;
        u32 exit_instr_and_program;
+       u32 exit_operation_exception;
        u32 deliver_external_call;
        u32 deliver_emergency_signal;
        u32 deliver_service_signal;
index 2e6b54e4d3f955d1c7971fce4ad02551eeac3846..09c13db1416fdc95358d8aff8ade678f94cb7b41 100644 (file)
@@ -349,6 +349,15 @@ static int handle_partial_execution(struct kvm_vcpu *vcpu)
        return -EOPNOTSUPP;
 }
 
+static int handle_operexc(struct kvm_vcpu *vcpu)
+{
+       vcpu->stat.exit_operation_exception++;
+       trace_kvm_s390_handle_operexc(vcpu, vcpu->arch.sie_block->ipa,
+                                     vcpu->arch.sie_block->ipb);
+
+       return kvm_s390_inject_program_int(vcpu, PGM_OPERATION);
+}
+
 int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu)
 {
        if (kvm_is_ucontrol(vcpu->kvm))
@@ -370,6 +379,8 @@ int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu)
                return handle_validity(vcpu);
        case 0x28:
                return handle_stop(vcpu);
+       case 0x2c:
+               return handle_operexc(vcpu);
        case 0x38:
                return handle_partial_execution(vcpu);
        default:
index 6d8ec3ac9dd8ec675d4d138a83888fa371138bcb..f0addece729e886a445d5378eb9b0b744dfc793c 100644 (file)
@@ -63,6 +63,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
        { "exit_instruction", VCPU_STAT(exit_instruction) },
        { "exit_program_interruption", VCPU_STAT(exit_program_interruption) },
        { "exit_instr_and_program_int", VCPU_STAT(exit_instr_and_program) },
+       { "exit_operation_exception", VCPU_STAT(exit_operation_exception) },
        { "halt_successful_poll", VCPU_STAT(halt_successful_poll) },
        { "halt_attempted_poll", VCPU_STAT(halt_attempted_poll) },
        { "halt_poll_invalid", VCPU_STAT(halt_poll_invalid) },
index 916834d7a73a760da5b7fd9beba5c267ad437240..90d26a6aa52c09e64ac9f6a6bdfad70033ca4536 100644 (file)
@@ -412,6 +412,27 @@ TRACE_EVENT(kvm_s390_handle_stsi,
                           __entry->addr)
        );
 
+TRACE_EVENT(kvm_s390_handle_operexc,
+           TP_PROTO(VCPU_PROTO_COMMON, __u16 ipa, __u32 ipb),
+           TP_ARGS(VCPU_ARGS_COMMON, ipa, ipb),
+
+           TP_STRUCT__entry(
+                   VCPU_FIELD_COMMON
+                   __field(__u64, instruction)
+                   ),
+
+           TP_fast_assign(
+                   VCPU_ASSIGN_COMMON
+                   __entry->instruction = ((__u64)ipa << 48) |
+                   ((__u64)ipb << 16);
+                   ),
+
+           VCPU_TP_PRINTK("operation exception on instruction %016llx (%s)",
+                          __entry->instruction,
+                          __print_symbolic(icpt_insn_decoder(__entry->instruction),
+                                           icpt_insn_codes))
+       );
+
 #endif /* _TRACE_KVM_H */
 
 /* This part must be outside protection */