blob: a882d5d931da95b5bdb20705eedef0d56c5e8d72 [file] [log] [blame]
/* 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);
}