khypervisor
v1
|
00001 #include <arch_types.h> 00002 #include <armv7_p15.h> 00003 #include <vdev.h> 00004 #include <hvmm_trace.h> 00005 #include "context.h" 00006 #include "trap_dabort.h" 00007 00008 #define DEBUG 00009 #include <log/print.h> 00010 00011 /* 00012 * ISS encoding for Data Abort exceptions taken to Hyp mode as beloww 00013 * ISS[24] : instruction syndrome valid. 0 is invalid information in ISS. 1 is valid information in ISS 00014 * when ISS[24] is 0, we don't need to extract information from the rest of ISS field 00015 * when ISS[24] is 1, we need to extract information from ISS[26:13] 00016 * 00017 * ISS[26:13] is consist of 10 parts. Details as below 00018 * 00019 * - ISS[23:22] is an access size. 00020 * - e.g. byte, hardword, word 00021 * - ISS[21] is a sign extend 00022 * - e.g. 1 is not sign, 1 is sign 00023 * - ISS[20] is reserved 00024 * - ISS[19:16] is for register transfer ? 00025 * - ISS[15:10] is reserved 00026 * - ISS[9] is an external abort type. It is IMPLEMENTATION_DEFINED 00027 * - ISS[8] is a cache maintenance. For synchronous fault, it should need a cache maintenance. 00028 * - ISS[7] is a stage 2 fault for a stage 1 translation table walk 00029 * - ISS[6] is synchronous abort that was caused by a write or read operation 00030 * - ISS[5:0] is a data fault status code(DFSC) 00031 * Additional register we should reference a DFSR 00032 */ 00033 00034 #define ISS_VALID 0x01000000 00035 00036 #define ISS_FSR_MASK 0x0000003F 00037 #define ISS_TRANS_FAULT_MASK 0x07 00038 #define TRANS_FAULT_LEVEL1 0x05 00039 #define TRANS_FAULT_LEVEL2 0x06 00040 #define TRANS_FAULT_LEVEL3 0x07 00041 #define ACCESS_FAULT_LEVEL0 0x08 00042 #define ACCESS_FAULT_LEVEL1 0x09 00043 #define ACCESS_FAULT_LEVEL2 0x0A 00044 #define ACCESS_FAULT_LEVEL3 0x0B 00045 00046 #define ISS_WNR_SHIFT 6 00047 #define ISS_WNR (1 << ISS_WNR_SHIFT) 00048 00049 #define ISS_SAS_SHIFT 22 00050 #define ISS_SAS_MASK (0x3 << ISS_SAS_SHIFT) 00051 #define ISS_SAS_BYTE 0x0 00052 #define ISS_SAS_HWORD 0x1 00053 #define ISS_SAS_WORD 0x2 00054 #define ISS_SAS_RESERVED 0x3 00055 00056 #define ISS_SSE_SHIFT 21 00057 #define ISS_SSE_MASK (0x1 << ISS_SSE_SHIFT) 00058 00059 #define ISS_SRT_SHIFT 16 00060 #define ISS_SRT_MASK (0xf << ISS_SRT_SHIFT) 00061 00062 /* HPFAR */ 00063 #define HPFAR_INITVAL 0x00000000 00064 #define HPFAR_FIPA_MASK 0xFFFFFFF0 00065 #define HPFAR_FIPA_SHIFT 4 00066 #define HPFAR_FIPA_PAGE_MASK 0x00000FFF 00067 #define HPFAR_FIPA_PAGE_SHIFT 12 00068 00069 /* 00070 Handles data abort case trapped into hvc, not dabort 00071 */ 00072 hvmm_status_t trap_hvc_dabort(unsigned int iss, struct arch_regs *regs) 00073 { 00074 hvmm_status_t result = HVMM_STATUS_UNKNOWN_ERROR; 00075 //far, fipa, il 00076 uint32_t far = read_hdfar(); 00077 uint32_t fipa; 00078 uint32_t sas, srt, wnr; 00079 00080 HVMM_TRACE_ENTER(); 00081 00082 printh( "trap_hvc_dabort: hdfar:%x hpfar:%x\n", far, read_hpfar() ); 00083 fipa = (read_hpfar() & HPFAR_FIPA_MASK) >> HPFAR_FIPA_SHIFT; 00084 fipa = fipa << HPFAR_FIPA_PAGE_SHIFT; 00085 fipa = fipa | (far & HPFAR_FIPA_PAGE_MASK); 00086 sas = (iss & ISS_SAS_MASK) >> ISS_SAS_SHIFT; 00087 srt = (iss & ISS_SRT_MASK) >> ISS_SRT_SHIFT; 00088 wnr = (iss & ISS_WNR) ? 1 : 0; 00089 00090 if ( (iss & ISS_VALID) && ((iss & ISS_FSR_MASK) < 8) ) { 00091 /* 00092 vdev emulates read/write, update pc, update destination register 00093 */ 00094 result = vdev_emulate(fipa, wnr, (vdev_access_size_t) sas, srt, regs ); 00095 if ( result != HVMM_STATUS_SUCCESS ) { 00096 printh( "trap_dabort: emulation failed guest pc:%x\n", regs->pc ); 00097 00098 /* Let the guest continue by increasing pc */ 00099 regs->pc += 4; 00100 } 00101 } else { 00102 printh( "trap_dboart: fipa=0x%x\n", fipa ); 00103 result = HVMM_STATUS_BAD_ACCESS; 00104 } 00105 if ( result != HVMM_STATUS_SUCCESS ) { 00106 printh( "- INSTR: %s[%d] r%d [%x]\n", wnr ? "str" : "ldr", (sas + 1) * 8, srt, fipa ); 00107 } 00108 00109 switch (iss & ISS_FSR_MASK) { 00110 case TRANS_FAULT_LEVEL1: 00111 case TRANS_FAULT_LEVEL2: 00112 case TRANS_FAULT_LEVEL3: 00113 break; 00114 00115 case ACCESS_FAULT_LEVEL1: 00116 case ACCESS_FAULT_LEVEL2: 00117 case ACCESS_FAULT_LEVEL3: 00118 { 00119 printh("ACCESS fault %d\n", iss & ISS_FSR_MASK); 00120 } 00121 break; 00122 default: 00123 break; 00124 } 00125 HVMM_TRACE_EXIT(); 00126 00127 return result; 00128 }