1
2
3
4
5
6
7
8#include "test_util.h"
9#include "kvm_util.h"
10
11#define VCPU_ID 6
12
13#define ICPT_INSTRUCTION 0x04
14#define IPA0_DIAG 0x8300
15
16static void guest_code(void)
17{
18 uint64_t diag318_info = 0x12345678;
19
20 asm volatile ("diag %0,0,0x318\n" : : "d" (diag318_info));
21}
22
23
24
25
26
27
28static uint64_t diag318_handler(void)
29{
30 struct kvm_vm *vm;
31 struct kvm_run *run;
32 uint64_t reg;
33 uint64_t diag318_info;
34
35 vm = vm_create_default(VCPU_ID, 0, guest_code);
36 vcpu_run(vm, VCPU_ID);
37 run = vcpu_state(vm, VCPU_ID);
38
39 TEST_ASSERT(run->exit_reason == KVM_EXIT_S390_SIEIC,
40 "DIAGNOSE 0x0318 instruction was not intercepted");
41 TEST_ASSERT(run->s390_sieic.icptcode == ICPT_INSTRUCTION,
42 "Unexpected intercept code: 0x%x", run->s390_sieic.icptcode);
43 TEST_ASSERT((run->s390_sieic.ipa & 0xff00) == IPA0_DIAG,
44 "Unexpected IPA0 code: 0x%x", (run->s390_sieic.ipa & 0xff00));
45
46 reg = (run->s390_sieic.ipa & 0x00f0) >> 4;
47 diag318_info = run->s.regs.gprs[reg];
48
49 TEST_ASSERT(diag318_info != 0, "DIAGNOSE 0x0318 info not set");
50
51 kvm_vm_free(vm);
52
53 return diag318_info;
54}
55
56uint64_t get_diag318_info(void)
57{
58 static uint64_t diag318_info;
59 static bool printed_skip;
60
61
62
63
64
65 if (!kvm_check_cap(KVM_CAP_S390_DIAG318)) {
66 if (!printed_skip) {
67 fprintf(stdout, "KVM_CAP_S390_DIAG318 not supported. "
68 "Skipping diag318 test.\n");
69 printed_skip = true;
70 }
71 return 0;
72 }
73
74
75
76
77
78 if (!diag318_info)
79 diag318_info = diag318_handler();
80
81 return diag318_info;
82}
83