| /* SPDX-License-Identifier: GPL-2.0-only */ |
| /* |
| * Library to decode addressing related exceptions |
| * |
| * Copyright 2021 IBM Corp. |
| * |
| * Authors: |
| * Janosch Frank <frankja@linux.ibm.com> |
| */ |
| #include <libcflat.h> |
| #include <bitops.h> |
| #include <asm/arch_def.h> |
| #include <asm/page.h> |
| #include <fault.h> |
| |
| |
| 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); |
| } |