1/* 2 * Copyright 2019, Data61, CSIRO (ABN 41 687 119 230) 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6#include <stdio.h> 7#include <assert.h> 8#include <utils/util.h> 9 10#include <sel4vm/sel4_arch/processor.h> 11 12#include "fault.h" 13 14seL4_Word *decode_rt(int reg, seL4_UserContext *c) 15{ 16 switch (reg) { 17 case 0: 18 return &c->r0; 19 case 1: 20 return &c->r1; 21 case 2: 22 return &c->r2; 23 case 3: 24 return &c->r3; 25 case 4: 26 return &c->r4; 27 case 5: 28 return &c->r5; 29 case 6: 30 return &c->r6; 31 case 7: 32 return &c->r7; 33 case 8: 34 return &c->r8; 35 case 9: 36 return &c->r9; 37 case 10: 38 return &c->r10; 39 case 11: 40 return &c->r11; 41 case 12: 42 return &c->r12; 43 case 13: 44 return &c->sp; 45 case 14: 46 return &c->r14; /* lr */ 47 case 15: 48 return &c->pc; 49 default: 50 assert(!"Invalid register"); 51 return NULL; 52 } 53}; 54 55#define PREG(regs, r) printf(#r ": 0x%x\n", regs->r) 56void print_ctx_regs(seL4_UserContext *regs) 57{ 58 PREG(regs, r0); 59 PREG(regs, r1); 60 PREG(regs, r2); 61 PREG(regs, r3); 62 PREG(regs, r4); 63 PREG(regs, r5); 64 PREG(regs, r6); 65 PREG(regs, r7); 66 PREG(regs, r8); 67 PREG(regs, r9); 68 PREG(regs, r10); 69 PREG(regs, r11); 70 PREG(regs, r12); 71 PREG(regs, pc); 72 PREG(regs, r14); 73 PREG(regs, sp); 74 PREG(regs, cpsr); 75} 76 77/** 78 * Returns a seL4_VCPUReg if the fault affects a banked register. Otherwise 79 * seL4_VCPUReg_Num is returned. It uses the fault to look up what mode the 80 * processor is in and based on rt returns a banked register. 81 */ 82int decode_vcpu_reg(int rt, fault_t *f) 83{ 84 assert(f->pmode != PMODE_HYPERVISOR); 85 if (f->pmode == PMODE_USER || f->pmode == PMODE_SYSTEM) { 86 return seL4_VCPUReg_Num; 87 } 88 89 int reg = seL4_VCPUReg_Num; 90 if (f->pmode == PMODE_FIQ) { 91 switch (rt) { 92 case 8: 93 reg = seL4_VCPUReg_R8fiq; 94 break; 95 case 9: 96 reg = seL4_VCPUReg_R9fiq; 97 break; 98 case 10: 99 reg = seL4_VCPUReg_R10fiq; 100 break; 101 case 11: 102 reg = seL4_VCPUReg_R11fiq; 103 break; 104 case 12: 105 reg = seL4_VCPUReg_R12fiq; 106 break; 107 case 13: 108 reg = seL4_VCPUReg_SPfiq; 109 break; 110 case 14: 111 reg = seL4_VCPUReg_LRfiq; 112 break; 113 default: 114 reg = seL4_VCPUReg_Num; 115 break; 116 } 117 118 } else if (rt == 13) { 119 switch (f->pmode) { 120 case PMODE_IRQ: 121 reg = seL4_VCPUReg_SPirq; 122 break; 123 case PMODE_SUPERVISOR: 124 reg = seL4_VCPUReg_SPsvc; 125 break; 126 case PMODE_ABORT: 127 reg = seL4_VCPUReg_SPabt; 128 break; 129 case PMODE_UNDEFINED: 130 reg = seL4_VCPUReg_SPund; 131 break; 132 default: 133 ZF_LOGF("Invalid processor mode"); 134 } 135 136 } else if (rt == 14) { 137 switch (f->pmode) { 138 case PMODE_IRQ: 139 reg = seL4_VCPUReg_LRirq; 140 break; 141 case PMODE_SUPERVISOR: 142 reg = seL4_VCPUReg_LRsvc; 143 break; 144 case PMODE_ABORT: 145 reg = seL4_VCPUReg_LRabt; 146 break; 147 case PMODE_UNDEFINED: 148 reg = seL4_VCPUReg_LRund; 149 break; 150 default: 151 ZF_LOGF("Invalid processor mode"); 152 } 153 154 } 155 156 return reg; 157} 158 159void fault_print_data(fault_t *fault) 160{ 161 seL4_Word data; 162 data = fault_get_data(fault) & fault_get_data_mask(fault); 163 switch (fault_get_width(fault)) { 164 case WIDTH_WORD: 165 printf("0x%8x", data); 166 break; 167 case WIDTH_HALFWORD: 168 printf("0x%4x", data); 169 break; 170 case WIDTH_BYTE: 171 printf("0x%02x", data); 172 break; 173 default: 174 printf("<Invalid width> 0x%x", data); 175 } 176} 177 178bool fault_is_thumb(fault_t *f) 179{ 180 return CPSR_IS_THUMB(fault_get_ctx(f)->cpsr); 181} 182