0001
0002
0003
0004
0005
0006
0007
0008 #include "test_util.h"
0009 #include "kvm_util.h"
0010
0011 #define ICPT_INSTRUCTION 0x04
0012 #define IPA0_DIAG 0x8300
0013
0014 static void guest_code(void)
0015 {
0016 uint64_t diag318_info = 0x12345678;
0017
0018 asm volatile ("diag %0,0,0x318\n" : : "d" (diag318_info));
0019 }
0020
0021
0022
0023
0024
0025
0026 static uint64_t diag318_handler(void)
0027 {
0028 struct kvm_vcpu *vcpu;
0029 struct kvm_vm *vm;
0030 struct kvm_run *run;
0031 uint64_t reg;
0032 uint64_t diag318_info;
0033
0034 vm = vm_create_with_one_vcpu(&vcpu, guest_code);
0035 vcpu_run(vcpu);
0036 run = vcpu->run;
0037
0038 TEST_ASSERT(run->exit_reason == KVM_EXIT_S390_SIEIC,
0039 "DIAGNOSE 0x0318 instruction was not intercepted");
0040 TEST_ASSERT(run->s390_sieic.icptcode == ICPT_INSTRUCTION,
0041 "Unexpected intercept code: 0x%x", run->s390_sieic.icptcode);
0042 TEST_ASSERT((run->s390_sieic.ipa & 0xff00) == IPA0_DIAG,
0043 "Unexpected IPA0 code: 0x%x", (run->s390_sieic.ipa & 0xff00));
0044
0045 reg = (run->s390_sieic.ipa & 0x00f0) >> 4;
0046 diag318_info = run->s.regs.gprs[reg];
0047
0048 TEST_ASSERT(diag318_info != 0, "DIAGNOSE 0x0318 info not set");
0049
0050 kvm_vm_free(vm);
0051
0052 return diag318_info;
0053 }
0054
0055 uint64_t get_diag318_info(void)
0056 {
0057 static uint64_t diag318_info;
0058 static bool printed_skip;
0059
0060
0061
0062
0063
0064 if (!kvm_has_cap(KVM_CAP_S390_DIAG318)) {
0065 if (!printed_skip) {
0066 fprintf(stdout, "KVM_CAP_S390_DIAG318 not supported. "
0067 "Skipping diag318 test.\n");
0068 printed_skip = true;
0069 }
0070 return 0;
0071 }
0072
0073
0074
0075
0076
0077 if (!diag318_info)
0078 diag318_info = diag318_handler();
0079
0080 return diag318_info;
0081 }