xref: /kvm-unit-tests/lib/s390x/fault.c (revision a63889fe244838b7c13051227d5ea5f7cc325ed0)
11921c4c6SJanosch Frank /* SPDX-License-Identifier: GPL-2.0-only */
21921c4c6SJanosch Frank /*
31921c4c6SJanosch Frank  * Library to decode addressing related exceptions
41921c4c6SJanosch Frank  *
51921c4c6SJanosch Frank  * Copyright 2021 IBM Corp.
61921c4c6SJanosch Frank  *
71921c4c6SJanosch Frank  * Authors:
81921c4c6SJanosch Frank  *    Janosch Frank <frankja@linux.ibm.com>
91921c4c6SJanosch Frank  */
101921c4c6SJanosch Frank #include <libcflat.h>
111921c4c6SJanosch Frank #include <bitops.h>
121921c4c6SJanosch Frank #include <asm/arch_def.h>
131921c4c6SJanosch Frank #include <asm/page.h>
141921c4c6SJanosch Frank #include <fault.h>
151921c4c6SJanosch Frank 
16c2c1663aSJanis Schoetterl-Glausch 
print_decode_pgm_prot(union teid teid)17c2c1663aSJanis Schoetterl-Glausch static void print_decode_pgm_prot(union teid teid)
181921c4c6SJanosch Frank {
19c2c1663aSJanis Schoetterl-Glausch 	switch (get_supp_on_prot_facility()) {
20c2c1663aSJanis Schoetterl-Glausch 	case SOP_NONE:
21c2c1663aSJanis Schoetterl-Glausch 	case SOP_BASIC:
22c2c1663aSJanis Schoetterl-Glausch 		printf("Type: ?\n"); /* modern/relevant machines have ESOP */
23c2c1663aSJanis Schoetterl-Glausch 		break;
24c2c1663aSJanis Schoetterl-Glausch 	case SOP_ENHANCED_1:
25c2c1663aSJanis Schoetterl-Glausch 		if (teid.sop_teid_predictable) {/* implies access list or DAT */
26c2c1663aSJanis Schoetterl-Glausch 			if (teid.sop_acc_list)
27c2c1663aSJanis Schoetterl-Glausch 				printf("Type: ACC\n");
28c2c1663aSJanis Schoetterl-Glausch 			else
291921c4c6SJanosch Frank 				printf("Type: DAT\n");
30c2c1663aSJanis Schoetterl-Glausch 		} else {
31c2c1663aSJanis Schoetterl-Glausch 			printf("Type: KEY or LAP\n");
32c2c1663aSJanis Schoetterl-Glausch 		}
33c2c1663aSJanis Schoetterl-Glausch 		break;
34c2c1663aSJanis Schoetterl-Glausch 	case SOP_ENHANCED_2: {
35c2c1663aSJanis Schoetterl-Glausch 		static const char * const prot_str[] = {
36c2c1663aSJanis Schoetterl-Glausch 			"KEY or LAP",
37c2c1663aSJanis Schoetterl-Glausch 			"DAT",
38c2c1663aSJanis Schoetterl-Glausch 			"KEY",
39c2c1663aSJanis Schoetterl-Glausch 			"ACC",
40c2c1663aSJanis Schoetterl-Glausch 			"LAP",
41c2c1663aSJanis Schoetterl-Glausch 			"IEP",
42c2c1663aSJanis Schoetterl-Glausch 		};
43*a63889feSPaolo Bonzini 		_Static_assert(ARRAY_SIZE(prot_str) == PROT_NUM_CODES, "ESOP2 prot codes");
44c2c1663aSJanis Schoetterl-Glausch 		int prot_code = teid_esop2_prot_code(teid);
45c2c1663aSJanis Schoetterl-Glausch 
46c2c1663aSJanis Schoetterl-Glausch 		printf("Type: %s\n", prot_str[prot_code]);
47c2c1663aSJanis Schoetterl-Glausch 		}
481921c4c6SJanosch Frank 	}
491921c4c6SJanosch Frank }
501921c4c6SJanosch Frank 
print_decode_teid(uint64_t raw_teid)51c2c1663aSJanis Schoetterl-Glausch void print_decode_teid(uint64_t raw_teid)
521921c4c6SJanosch Frank {
53c2c1663aSJanis Schoetterl-Glausch 	union teid teid = { .val = raw_teid };
54cd719531SJanis Schoetterl-Glausch 	bool dat = lowcore.pgm_old_psw.mask & PSW_MASK_DAT;
551921c4c6SJanosch Frank 
561921c4c6SJanosch Frank 	printf("Memory exception information:\n");
571921c4c6SJanosch Frank 	printf("DAT: %s\n", dat ? "on" : "off");
581921c4c6SJanosch Frank 
591921c4c6SJanosch Frank 	printf("AS: ");
60c2c1663aSJanis Schoetterl-Glausch 	switch (teid.asce_id) {
611921c4c6SJanosch Frank 	case AS_PRIM:
621921c4c6SJanosch Frank 		printf("Primary\n");
631921c4c6SJanosch Frank 		break;
641921c4c6SJanosch Frank 	case AS_ACCR:
651921c4c6SJanosch Frank 		printf("Access Register\n");
661921c4c6SJanosch Frank 		break;
671921c4c6SJanosch Frank 	case AS_SECN:
681921c4c6SJanosch Frank 		printf("Secondary\n");
691921c4c6SJanosch Frank 		break;
701921c4c6SJanosch Frank 	case AS_HOME:
711921c4c6SJanosch Frank 		printf("Home\n");
721921c4c6SJanosch Frank 		break;
731921c4c6SJanosch Frank 	}
741921c4c6SJanosch Frank 
75cd719531SJanis Schoetterl-Glausch 	if (lowcore.pgm_int_code == PGM_INT_CODE_PROTECTION)
761921c4c6SJanosch Frank 		print_decode_pgm_prot(teid);
771921c4c6SJanosch Frank 
781921c4c6SJanosch Frank 	/*
791921c4c6SJanosch Frank 	 * If teid bit 61 is off for these two exception the reported
801921c4c6SJanosch Frank 	 * address is unpredictable.
811921c4c6SJanosch Frank 	 */
82cd719531SJanis Schoetterl-Glausch 	if ((lowcore.pgm_int_code == PGM_INT_CODE_SECURE_STOR_ACCESS ||
83cd719531SJanis Schoetterl-Glausch 	     lowcore.pgm_int_code == PGM_INT_CODE_SECURE_STOR_VIOLATION) &&
84c2c1663aSJanis Schoetterl-Glausch 	    !teid.sop_teid_predictable) {
85c2c1663aSJanis Schoetterl-Glausch 		printf("Address: %lx, unpredictable\n ", raw_teid & PAGE_MASK);
861921c4c6SJanosch Frank 		return;
871921c4c6SJanosch Frank 	}
88c2c1663aSJanis Schoetterl-Glausch 	printf("TEID: %lx\n", raw_teid);
89c2c1663aSJanis Schoetterl-Glausch 	printf("Address: %lx\n\n", raw_teid & PAGE_MASK);
901921c4c6SJanosch Frank }
91