Merge tag 'lkmm.2023.04.07a' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck...
[linux-block.git] / tools / testing / selftests / kvm / lib / s390x / diag318_test_handler.c
CommitLineData
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
14static 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 */
26static 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
54uint64_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}