Commit | Line | Data |
---|---|---|
efaa83a3 CW |
1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* | |
3 | * Test handler for the s390x DIAGNOSE 0x0318 instruction. | |
4 | * | |
5 | * Copyright (C) 2020, IBM | |
6 | */ | |
7 | ||
8 | #include "test_util.h" | |
9 | #include "kvm_util.h" | |
10 | ||
efaa83a3 CW |
11 | #define ICPT_INSTRUCTION 0x04 |
12 | #define IPA0_DIAG 0x8300 | |
13 | ||
14 | static void guest_code(void) | |
15 | { | |
16 | uint64_t diag318_info = 0x12345678; | |
17 | ||
18 | asm volatile ("diag %0,0,0x318\n" : : "d" (diag318_info)); | |
19 | } | |
20 | ||
21 | /* | |
22 | * The DIAGNOSE 0x0318 instruction call must be handled via userspace. As such, | |
23 | * we create an ad-hoc VM here to handle the instruction then extract the | |
24 | * necessary data. It is up to the caller to decide what to do with that data. | |
25 | */ | |
26 | static uint64_t diag318_handler(void) | |
27 | { | |
7cdcdfe5 | 28 | struct kvm_vcpu *vcpu; |
efaa83a3 CW |
29 | struct kvm_vm *vm; |
30 | struct kvm_run *run; | |
31 | uint64_t reg; | |
32 | uint64_t diag318_info; | |
33 | ||
7cdcdfe5 | 34 | vm = vm_create_with_one_vcpu(&vcpu, guest_code); |
768e9a61 | 35 | vcpu_run(vcpu); |
7cdcdfe5 | 36 | run = vcpu->run; |
efaa83a3 | 37 | |
c96f57b0 | 38 | TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_S390_SIEIC); |
efaa83a3 CW |
39 | TEST_ASSERT(run->s390_sieic.icptcode == ICPT_INSTRUCTION, |
40 | "Unexpected intercept code: 0x%x", run->s390_sieic.icptcode); | |
41 | TEST_ASSERT((run->s390_sieic.ipa & 0xff00) == IPA0_DIAG, | |
42 | "Unexpected IPA0 code: 0x%x", (run->s390_sieic.ipa & 0xff00)); | |
43 | ||
44 | reg = (run->s390_sieic.ipa & 0x00f0) >> 4; | |
45 | diag318_info = run->s.regs.gprs[reg]; | |
46 | ||
47 | TEST_ASSERT(diag318_info != 0, "DIAGNOSE 0x0318 info not set"); | |
48 | ||
49 | kvm_vm_free(vm); | |
50 | ||
51 | return diag318_info; | |
52 | } | |
53 | ||
54 | uint64_t get_diag318_info(void) | |
55 | { | |
56 | static uint64_t diag318_info; | |
57 | static bool printed_skip; | |
58 | ||
59 | /* | |
60 | * If KVM does not support diag318, then return 0 to | |
61 | * ensure tests do not break. | |
62 | */ | |
3ea9b809 | 63 | if (!kvm_has_cap(KVM_CAP_S390_DIAG318)) { |
efaa83a3 CW |
64 | if (!printed_skip) { |
65 | fprintf(stdout, "KVM_CAP_S390_DIAG318 not supported. " | |
66 | "Skipping diag318 test.\n"); | |
67 | printed_skip = true; | |
68 | } | |
69 | return 0; | |
70 | } | |
71 | ||
72 | /* | |
73 | * If a test has previously requested the diag318 info, | |
74 | * then don't bother spinning up a temporary VM again. | |
75 | */ | |
76 | if (!diag318_info) | |
77 | diag318_info = diag318_handler(); | |
78 | ||
79 | return diag318_info; | |
80 | } |