162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci#include <errno.h> 462306a36Sopenharmony_ci#include <stddef.h> 562306a36Sopenharmony_ci#include <stdio.h> 662306a36Sopenharmony_ci#include <string.h> 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include "dexcr.h" 962306a36Sopenharmony_ci#include "utils.h" 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_cistatic unsigned int dexcr; 1262306a36Sopenharmony_cistatic unsigned int hdexcr; 1362306a36Sopenharmony_cistatic unsigned int effective; 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_cistruct dexcr_aspect { 1662306a36Sopenharmony_ci const char *name; 1762306a36Sopenharmony_ci const char *desc; 1862306a36Sopenharmony_ci unsigned int index; 1962306a36Sopenharmony_ci}; 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_cistatic const struct dexcr_aspect aspects[] = { 2262306a36Sopenharmony_ci { 2362306a36Sopenharmony_ci .name = "SBHE", 2462306a36Sopenharmony_ci .desc = "Speculative branch hint enable", 2562306a36Sopenharmony_ci .index = 0, 2662306a36Sopenharmony_ci }, 2762306a36Sopenharmony_ci { 2862306a36Sopenharmony_ci .name = "IBRTPD", 2962306a36Sopenharmony_ci .desc = "Indirect branch recurrent target prediction disable", 3062306a36Sopenharmony_ci .index = 3, 3162306a36Sopenharmony_ci }, 3262306a36Sopenharmony_ci { 3362306a36Sopenharmony_ci .name = "SRAPD", 3462306a36Sopenharmony_ci .desc = "Subroutine return address prediction disable", 3562306a36Sopenharmony_ci .index = 4, 3662306a36Sopenharmony_ci }, 3762306a36Sopenharmony_ci { 3862306a36Sopenharmony_ci .name = "NPHIE", 3962306a36Sopenharmony_ci .desc = "Non-privileged hash instruction enable", 4062306a36Sopenharmony_ci .index = 5, 4162306a36Sopenharmony_ci }, 4262306a36Sopenharmony_ci { 4362306a36Sopenharmony_ci .name = "PHIE", 4462306a36Sopenharmony_ci .desc = "Privileged hash instruction enable", 4562306a36Sopenharmony_ci .index = 6, 4662306a36Sopenharmony_ci }, 4762306a36Sopenharmony_ci}; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_cistatic void print_list(const char *list[], size_t len) 5062306a36Sopenharmony_ci{ 5162306a36Sopenharmony_ci for (size_t i = 0; i < len; i++) { 5262306a36Sopenharmony_ci printf("%s", list[i]); 5362306a36Sopenharmony_ci if (i + 1 < len) 5462306a36Sopenharmony_ci printf(", "); 5562306a36Sopenharmony_ci } 5662306a36Sopenharmony_ci} 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_cistatic void print_dexcr(char *name, unsigned int bits) 5962306a36Sopenharmony_ci{ 6062306a36Sopenharmony_ci const char *enabled_aspects[ARRAY_SIZE(aspects) + 1] = {NULL}; 6162306a36Sopenharmony_ci size_t j = 0; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci printf("%s: %08x", name, bits); 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci if (bits == 0) { 6662306a36Sopenharmony_ci printf("\n"); 6762306a36Sopenharmony_ci return; 6862306a36Sopenharmony_ci } 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci for (size_t i = 0; i < ARRAY_SIZE(aspects); i++) { 7162306a36Sopenharmony_ci unsigned int mask = DEXCR_PR_BIT(aspects[i].index); 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci if (bits & mask) { 7462306a36Sopenharmony_ci enabled_aspects[j++] = aspects[i].name; 7562306a36Sopenharmony_ci bits &= ~mask; 7662306a36Sopenharmony_ci } 7762306a36Sopenharmony_ci } 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci if (bits) 8062306a36Sopenharmony_ci enabled_aspects[j++] = "unknown"; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci printf(" ("); 8362306a36Sopenharmony_ci print_list(enabled_aspects, j); 8462306a36Sopenharmony_ci printf(")\n"); 8562306a36Sopenharmony_ci} 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_cistatic void print_aspect(const struct dexcr_aspect *aspect) 8862306a36Sopenharmony_ci{ 8962306a36Sopenharmony_ci const char *attributes[8] = {NULL}; 9062306a36Sopenharmony_ci size_t j = 0; 9162306a36Sopenharmony_ci unsigned long mask; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci mask = DEXCR_PR_BIT(aspect->index); 9462306a36Sopenharmony_ci if (dexcr & mask) 9562306a36Sopenharmony_ci attributes[j++] = "set"; 9662306a36Sopenharmony_ci if (hdexcr & mask) 9762306a36Sopenharmony_ci attributes[j++] = "set (hypervisor)"; 9862306a36Sopenharmony_ci if (!(effective & mask)) 9962306a36Sopenharmony_ci attributes[j++] = "clear"; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci printf("%12s %c (%d): ", aspect->name, effective & mask ? '*' : ' ', aspect->index); 10262306a36Sopenharmony_ci print_list(attributes, j); 10362306a36Sopenharmony_ci printf(" \t(%s)\n", aspect->desc); 10462306a36Sopenharmony_ci} 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ciint main(int argc, char *argv[]) 10762306a36Sopenharmony_ci{ 10862306a36Sopenharmony_ci if (!dexcr_exists()) { 10962306a36Sopenharmony_ci printf("DEXCR not detected on this hardware\n"); 11062306a36Sopenharmony_ci return 1; 11162306a36Sopenharmony_ci } 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci dexcr = get_dexcr(DEXCR); 11462306a36Sopenharmony_ci hdexcr = get_dexcr(HDEXCR); 11562306a36Sopenharmony_ci effective = dexcr | hdexcr; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci print_dexcr(" DEXCR", dexcr); 11862306a36Sopenharmony_ci print_dexcr(" HDEXCR", hdexcr); 11962306a36Sopenharmony_ci print_dexcr("Effective", effective); 12062306a36Sopenharmony_ci printf("\n"); 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci for (size_t i = 0; i < ARRAY_SIZE(aspects); i++) 12362306a36Sopenharmony_ci print_aspect(&aspects[i]); 12462306a36Sopenharmony_ci printf("\n"); 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci if (effective & DEXCR_PR_NPHIE) { 12762306a36Sopenharmony_ci printf("DEXCR[NPHIE] enabled: hashst/hashchk "); 12862306a36Sopenharmony_ci if (hashchk_triggers()) 12962306a36Sopenharmony_ci printf("working\n"); 13062306a36Sopenharmony_ci else 13162306a36Sopenharmony_ci printf("failed to trigger\n"); 13262306a36Sopenharmony_ci } else { 13362306a36Sopenharmony_ci printf("DEXCR[NPHIE] disabled: hashst/hashchk "); 13462306a36Sopenharmony_ci if (hashchk_triggers()) 13562306a36Sopenharmony_ci printf("unexpectedly triggered\n"); 13662306a36Sopenharmony_ci else 13762306a36Sopenharmony_ci printf("ignored\n"); 13862306a36Sopenharmony_ci } 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci return 0; 14162306a36Sopenharmony_ci} 142