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