xref: /kvm-unit-tests/lib/s390x/sie-icpt.c (revision 1f08a91a41402b0e032ecce8ed1b5952cbfca0ea)
1*dc142414SNina Schoetterl-Glausch /* SPDX-License-Identifier: GPL-2.0-only */
2*dc142414SNina Schoetterl-Glausch /*
3*dc142414SNina Schoetterl-Glausch  * Functionality for SIE interception handling.
4*dc142414SNina Schoetterl-Glausch  *
5*dc142414SNina Schoetterl-Glausch  * Copyright IBM Corp. 2024
6*dc142414SNina Schoetterl-Glausch  */
7*dc142414SNina Schoetterl-Glausch 
8*dc142414SNina Schoetterl-Glausch #include <sie-icpt.h>
9*dc142414SNina Schoetterl-Glausch 
sblk_ip_as_diag(struct kvm_s390_sie_block * sblk)10*dc142414SNina Schoetterl-Glausch struct diag_itext sblk_ip_as_diag(struct kvm_s390_sie_block *sblk)
11*dc142414SNina Schoetterl-Glausch {
12*dc142414SNina Schoetterl-Glausch 	union {
13*dc142414SNina Schoetterl-Glausch 		struct {
14*dc142414SNina Schoetterl-Glausch 			uint64_t ipa : 16;
15*dc142414SNina Schoetterl-Glausch 			uint64_t ipb : 32;
16*dc142414SNina Schoetterl-Glausch 			uint64_t     : 16;
17*dc142414SNina Schoetterl-Glausch 		};
18*dc142414SNina Schoetterl-Glausch 		struct diag_itext diag;
19*dc142414SNina Schoetterl-Glausch 	} instr = { .ipa = sblk->ipa, .ipb = sblk->ipb };
20*dc142414SNina Schoetterl-Glausch 
21*dc142414SNina Schoetterl-Glausch 	return instr.diag;
22*dc142414SNina Schoetterl-Glausch }
23*dc142414SNina Schoetterl-Glausch 
sie_is_diag_icpt(struct vm * vm,unsigned int diag)24*dc142414SNina Schoetterl-Glausch bool sie_is_diag_icpt(struct vm *vm, unsigned int diag)
25*dc142414SNina Schoetterl-Glausch {
26*dc142414SNina Schoetterl-Glausch 	struct diag_itext instr = sblk_ip_as_diag(vm->sblk);
27*dc142414SNina Schoetterl-Glausch 	uint8_t icptcode;
28*dc142414SNina Schoetterl-Glausch 	uint64_t code;
29*dc142414SNina Schoetterl-Glausch 
30*dc142414SNina Schoetterl-Glausch 	switch (diag) {
31*dc142414SNina Schoetterl-Glausch 	case 0x44:
32*dc142414SNina Schoetterl-Glausch 	case 0x9c:
33*dc142414SNina Schoetterl-Glausch 	case 0x288:
34*dc142414SNina Schoetterl-Glausch 	case 0x308:
35*dc142414SNina Schoetterl-Glausch 		icptcode = ICPT_PV_NOTIFY;
36*dc142414SNina Schoetterl-Glausch 		break;
37*dc142414SNina Schoetterl-Glausch 	case 0x500:
38*dc142414SNina Schoetterl-Glausch 		icptcode = ICPT_PV_INSTR;
39*dc142414SNina Schoetterl-Glausch 		break;
40*dc142414SNina Schoetterl-Glausch 	default:
41*dc142414SNina Schoetterl-Glausch 		/* If a new diag is introduced add it to the cases above! */
42*dc142414SNina Schoetterl-Glausch 		assert_msg(false, "unknown diag 0x%x", diag);
43*dc142414SNina Schoetterl-Glausch 	}
44*dc142414SNina Schoetterl-Glausch 
45*dc142414SNina Schoetterl-Glausch 	if (sie_is_pv(vm)) {
46*dc142414SNina Schoetterl-Glausch 		if (instr.r_1 != 0 || instr.r_2 != 2 || instr.r_base != 5)
47*dc142414SNina Schoetterl-Glausch 			return false;
48*dc142414SNina Schoetterl-Glausch 		if (instr.displace)
49*dc142414SNina Schoetterl-Glausch 			return false;
50*dc142414SNina Schoetterl-Glausch 	} else {
51*dc142414SNina Schoetterl-Glausch 		icptcode = ICPT_INST;
52*dc142414SNina Schoetterl-Glausch 	}
53*dc142414SNina Schoetterl-Glausch 	if (vm->sblk->icptcode != icptcode)
54*dc142414SNina Schoetterl-Glausch 		return false;
55*dc142414SNina Schoetterl-Glausch 	if (instr.opcode != 0x83 || instr.zero)
56*dc142414SNina Schoetterl-Glausch 		return false;
57*dc142414SNina Schoetterl-Glausch 	code = instr.r_base ? vm->save_area.guest.grs[instr.r_base] : 0;
58*dc142414SNina Schoetterl-Glausch 	code = (code + instr.displace) & 0xffff;
59*dc142414SNina Schoetterl-Glausch 	return code == diag;
60*dc142414SNina Schoetterl-Glausch }
61