AArch64 EL2 hypervisor for QEMU virt that boots at EL2
1

Configure Feed

Select the types of activity you want to include in your feed.

ariel / core / sysreg.c
3.6 kB 107 lines
1#include "hv/sysreg.h" 2#include "hv/string.h" 3 4uint64_t sysreg_key_make(uint32_t op0, uint32_t op1, uint32_t crn, uint32_t crm, uint32_t op2) 5{ 6 return ((uint64_t)(op0 & 0x3u) << 14u) | 7 ((uint64_t)(op1 & 0x7u) << 11u) | 8 ((uint64_t)(crn & 0xfu) << 7u) | 9 ((uint64_t)(crm & 0xfu) << 3u) | 10 (uint64_t)(op2 & 0x7u); 11} 12 13bool sysreg_decode_from_esr_iss(uint64_t iss, struct sysreg_access *out) 14{ 15 if (out == (struct sysreg_access *)0) { 16 return false; 17 } 18 out->op0 = (uint32_t)((iss >> 20u) & 0x3u); 19 out->op2 = (uint32_t)((iss >> 17u) & 0x7u); 20 out->op1 = (uint32_t)((iss >> 14u) & 0x7u); 21 out->crn = (uint32_t)((iss >> 10u) & 0xfu); 22 out->rt = (uint32_t)((iss >> 5u) & 0x1fu); 23 out->crm = (uint32_t)((iss >> 1u) & 0xfu); 24 out->is_read = ((iss & 1u) == ESR_SYSREG_DIR_READ); 25 out->key = sysreg_key_make(out->op0, out->op1, out->crn, out->crm, out->op2); 26 return true; 27} 28 29struct sysreg_name { 30 uint64_t key; 31 const char *name; 32}; 33 34#define KEY(op0, op1, crn, crm, op2) SYSREG_KEY_CONST((op0), (op1), (crn), (crm), (op2)) 35 36static const struct sysreg_name g_names[] = { 37 { KEY(3, 0, 0, 0, 0), "midr_el1" }, 38 { KEY(3, 0, 0, 0, 5), "mpidr_el1" }, 39 { KEY(3, 0, 0, 4, 0), "id_aa64pfr0_el1" }, 40 { KEY(3, 0, 0, 4, 1), "id_aa64pfr1_el1" }, 41 { KEY(3, 0, 0, 6, 0), "id_aa64isar0_el1" }, 42 { KEY(3, 0, 0, 6, 1), "id_aa64isar1_el1" }, 43 { KEY(3, 0, 0, 7, 0), "id_aa64mmfr0_el1" }, 44 { KEY(3, 0, 0, 7, 1), "id_aa64mmfr1_el1" }, 45 { KEY(3, 1, 0, 0, 1), "clidr_el1" }, 46 { KEY(3, 2, 0, 0, 0), "csselr_el1" }, 47 { KEY(3, 3, 0, 0, 1), "ctr_el0" }, 48 { KEY(3, 3, 0, 0, 7), "dczid_el0" }, 49 { KEY(3, 0, 1, 0, 0), "sctlr_el1" }, 50 { KEY(3, 0, 1, 0, 1), "actlr_el1" }, 51 { KEY(3, 0, 1, 0, 2), "cpacr_el1" }, 52 { KEY(3, 4, 1, 1, 0), "hcr_el2" }, 53 { KEY(3, 6, 1, 1, 0), "scr_el3" }, 54 { KEY(3, 0, 2, 0, 0), "ttbr0_el1" }, 55 { KEY(3, 0, 2, 0, 1), "ttbr1_el1" }, 56 { KEY(3, 0, 2, 0, 2), "tcr_el1" }, 57 { KEY(3, 4, 2, 1, 0), "vttbr_el2" }, 58 { KEY(3, 3, 9, 12, 0), "pmcr_el0" }, 59 { KEY(3, 0, 10, 2, 0), "mair_el1" }, 60 { KEY(3, 0, 12, 0, 0), "vbar_el1" }, 61 { KEY(3, 0, 12, 0, 1), "rvbar_el1" }, 62 { KEY(3, 0, 13, 0, 1), "contextidr_el1" }, 63 { KEY(3, 0, 13, 0, 4), "tpidr_el1" }, 64 { KEY(3, 3, 13, 0, 3), "tpidrro_el0" }, 65 { KEY(3, 0, 14, 1, 0), "cntkctl_el1" }, 66 { KEY(3, 3, 14, 3, 0), "cntv_tval_el0" }, 67 { KEY(3, 3, 14, 3, 1), "cntv_ctl_el0" }, 68 { KEY(3, 3, 14, 3, 2), "cntv_cval_el0" }, 69 { KEY(2, 0, 0, 2, 2), "mdscr_el1" }, 70}; 71 72const char *sysreg_key_name(uint64_t key) 73{ 74 for (uint32_t i = 0; i < HV_ARRAY_SIZE(g_names); i++) { 75 if (g_names[i].key == key) { 76 return g_names[i].name; 77 } 78 } 79 return "unknown"; 80} 81 82const char *esr_ec_name(uint32_t ec) 83{ 84 switch (ec) { 85 case ESR_EC_UNKNOWN: return "unknown"; 86 case ESR_EC_WFI_WFE: return "wfi-wfe"; 87 case ESR_EC_HVC64: return "hvc64"; 88 case ESR_EC_SMC64: return "smc64"; 89 case ESR_EC_SYSREG: return "sysreg"; 90 case ESR_EC_IABT_LOWER: return "iabt-lower"; 91 case ESR_EC_DABT_LOWER: return "dabt-lower"; 92 case ESR_EC_BRK64: return "brk64"; 93 default: return "reserved"; 94 } 95} 96 97bool sysreg_selftest(void) 98{ 99 struct sysreg_access a; 100 uint64_t iss = (3ull << 20u) | (0ull << 17u) | (0ull << 14u) | 101 (0ull << 10u) | (0ull << 5u) | (0ull << 1u) | 1ull; 102 if (!sysreg_decode_from_esr_iss(iss, &a)) { 103 return false; 104 } 105 return a.is_read && a.rt == 0u && a.key == KEY(3, 0, 0, 0, 0) && 106 hv_strcmp(esr_ec_name(ESR_EC_SYSREG), "sysreg") == 0; 107}