/* SPDX-License-Identifier: GPL-2.0-only */ /* * Library to decode addressing related exceptions * * Copyright 2021 IBM Corp. * * Authors: * Janosch Frank */ #include #include #include #include #include static void print_decode_pgm_prot(union teid teid) { switch (get_supp_on_prot_facility()) { case SOP_NONE: case SOP_BASIC: printf("Type: ?\n"); /* modern/relevant machines have ESOP */ break; case SOP_ENHANCED_1: if (teid.sop_teid_predictable) {/* implies access list or DAT */ if (teid.sop_acc_list) printf("Type: ACC\n"); else printf("Type: DAT\n"); } else { printf("Type: KEY or LAP\n"); } break; case SOP_ENHANCED_2: { static const char * const prot_str[] = { "KEY or LAP", "DAT", "KEY", "ACC", "LAP", "IEP", }; _Static_assert(ARRAY_SIZE(prot_str) == PROT_NUM_CODES, "ESOP2 prot codes"); int prot_code = teid_esop2_prot_code(teid); printf("Type: %s\n", prot_str[prot_code]); } } } void print_decode_teid(uint64_t raw_teid) { union teid teid = { .val = raw_teid }; bool dat = lowcore.pgm_old_psw.mask & PSW_MASK_DAT; printf("Memory exception information:\n"); printf("DAT: %s\n", dat ? "on" : "off"); printf("AS: "); switch (teid.asce_id) { case AS_PRIM: printf("Primary\n"); break; case AS_ACCR: printf("Access Register\n"); break; case AS_SECN: printf("Secondary\n"); break; case AS_HOME: printf("Home\n"); break; } if (lowcore.pgm_int_code == PGM_INT_CODE_PROTECTION) print_decode_pgm_prot(teid); /* * If teid bit 61 is off for these two exception the reported * address is unpredictable. */ if ((lowcore.pgm_int_code == PGM_INT_CODE_SECURE_STOR_ACCESS || lowcore.pgm_int_code == PGM_INT_CODE_SECURE_STOR_VIOLATION) && !teid.sop_teid_predictable) { printf("Address: %lx, unpredictable\n ", raw_teid & PAGE_MASK); return; } printf("TEID: %lx\n", raw_teid); printf("Address: %lx\n\n", raw_teid & PAGE_MASK); }