Linux Audio

Check our new training course

Loading...
 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
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{
28	struct kvm_vcpu *vcpu;
29	struct kvm_vm *vm;
30	struct kvm_run *run;
31	uint64_t reg;
32	uint64_t diag318_info;
33
34	vm = vm_create_with_one_vcpu(&vcpu, guest_code);
35	vcpu_run(vcpu);
36	run = vcpu->run;
37
38	TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_S390_SIEIC);
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	 */
63	if (!kvm_has_cap(KVM_CAP_S390_DIAG318)) {
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}
1