Changeset 0ab362c in mainline for kernel/arch/arm32/src/mm/page_fault.c
- Timestamp:
- 2012-11-22T14:36:04Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- e32720ff
- Parents:
- 1f7753a (diff), 0f2c80a (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/arm32/src/mm/page_fault.c
r1f7753a r0ab362c 42 42 #include <print.h> 43 43 44 /** Returns value stored in fault status register. 44 45 /** 46 * FSR encoding ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition. 47 * 48 * B3.13.3 page B3-1406 (PDF page 1406) 49 */ 50 typedef enum { 51 DFSR_SOURCE_ALIGN = 0x0001, 52 DFSR_SOURCE_CACHE_MAINTENANCE = 0x0004, 53 DFSR_SOURCE_SYNC_EXTERNAL_TRANSLATION_L1 = 0x000c, 54 DFSR_SOURCE_SYNC_EXTERNAL_TRANSLATION_L2 = 0x000e, 55 DFSR_SOURCE_SYNC_PARITY_TRANSLATION_L1 = 0x040c, 56 DFSR_SOURCE_SYNC_PARITY_TRANSLATION_L2 = 0x040e, 57 DFSR_SOURCE_TRANSLATION_L1 = 0x0005, 58 DFSR_SOURCE_TRANSLATION_L2 = 0x0007, 59 DFSR_SOURCE_ACCESS_FLAG_L1 = 0x0003, /**< @note: This used to be alignment enc. */ 60 DFSR_SOURCE_ACCESS_FLAG_L2 = 0x0006, 61 DFSR_SOURCE_DOMAIN_L1 = 0x0009, 62 DFSR_SOURCE_DOMAIN_L2 = 0x000b, 63 DFSR_SOURCE_PERMISSION_L1 = 0x000d, 64 DFSR_SOURCE_PERMISSION_L2 = 0x000f, 65 DFSR_SOURCE_DEBUG = 0x0002, 66 DFSR_SOURCE_SYNC_EXTERNAL = 0x0008, 67 DFSR_SOURCE_TLB_CONFLICT = 0x0400, 68 DFSR_SOURCE_LOCKDOWN = 0x0404, /**< @note: Implementation defined */ 69 DFSR_SOURCE_COPROCESSOR = 0x040a, /**< @note Implementation defined */ 70 DFSR_SOURCE_SYNC_PARITY = 0x0409, 71 DFSR_SOURCE_ASYNC_EXTERNAL = 0x0406, 72 DFSR_SOURCE_ASYNC_PARITY = 0x0408, 73 DFSR_SOURCE_MASK = 0x0000040f, 74 } dfsr_source_t; 75 76 static inline const char * dfsr_source_to_str(dfsr_source_t source) 77 { 78 switch (source) { 79 case DFSR_SOURCE_TRANSLATION_L1: 80 return "Translation fault L1"; 81 case DFSR_SOURCE_TRANSLATION_L2: 82 return "Translation fault L2"; 83 case DFSR_SOURCE_PERMISSION_L1: 84 return "Permission fault L1"; 85 case DFSR_SOURCE_PERMISSION_L2: 86 return "Permission fault L2"; 87 case DFSR_SOURCE_ALIGN: 88 return "Alignment fault"; 89 case DFSR_SOURCE_CACHE_MAINTENANCE: 90 return "Instruction cache maintenance fault"; 91 case DFSR_SOURCE_SYNC_EXTERNAL_TRANSLATION_L1: 92 return "Synchronous external abort on translation table walk level 1"; 93 case DFSR_SOURCE_SYNC_EXTERNAL_TRANSLATION_L2: 94 return "Synchronous external abort on translation table walk level 2"; 95 case DFSR_SOURCE_SYNC_PARITY_TRANSLATION_L1: 96 return "Synchronous parity error on translation table walk level 1"; 97 case DFSR_SOURCE_SYNC_PARITY_TRANSLATION_L2: 98 return "Synchronous parity error on translation table walk level 2"; 99 case DFSR_SOURCE_ACCESS_FLAG_L1: 100 return "Access flag fault L1"; 101 case DFSR_SOURCE_ACCESS_FLAG_L2: 102 return "Access flag fault L2"; 103 case DFSR_SOURCE_DOMAIN_L1: 104 return "Domain fault L1"; 105 case DFSR_SOURCE_DOMAIN_L2: 106 return "Domain flault L2"; 107 case DFSR_SOURCE_DEBUG: 108 return "Debug event"; 109 case DFSR_SOURCE_SYNC_EXTERNAL: 110 return "Synchronous external abort"; 111 case DFSR_SOURCE_TLB_CONFLICT: 112 return "TLB conflict abort"; 113 case DFSR_SOURCE_LOCKDOWN: 114 return "Lockdown (Implementation defined)"; 115 case DFSR_SOURCE_COPROCESSOR: 116 return "Coprocessor abort (Implementation defined)"; 117 case DFSR_SOURCE_SYNC_PARITY: 118 return "Synchronous parity error on memory access"; 119 case DFSR_SOURCE_ASYNC_EXTERNAL: 120 return "Asynchronous external abort"; 121 case DFSR_SOURCE_ASYNC_PARITY: 122 return "Asynchronous parity error on memory access"; 123 case DFSR_SOURCE_MASK: 124 break; 125 } 126 return "Unknown data abort"; 127 } 128 129 130 /** Returns value stored in comnbined/data fault status register. 45 131 * 46 132 * @return Value stored in CP15 fault status register (FSR). 47 */ 48 static inline fault_status_t read_fault_status_register(void) 49 { 50 fault_status_union_t fsu; 133 * 134 * "VMSAv6 added a fifth fault status bit (bit[10]) to both the IFSR and DFSR. 135 * It is IMPLEMENTATION DEFINED how this bit is encoded in earlier versions of 136 * the architecture. A write flag (bit[11] of the DFSR) has also been 137 * introduced." 138 * ARM Architecture Reference Manual version i ch. B4.6 (PDF p. 719) 139 * 140 * See ch. B4.9.6 for location of data/instruction FSR. 141 * 142 */ 143 static inline fault_status_t read_data_fault_status_register(void) 144 { 145 fault_status_t fsu; 51 146 52 /* fault status is stored in CP15 register 5*/147 /* Combined/Data fault status is stored in CP15 register 5, c0. */ 53 148 asm volatile ( 54 149 "mrc p15, 0, %[dummy], c5, c0, 0" 55 : [dummy] "=r" (fsu. dummy)150 : [dummy] "=r" (fsu.raw) 56 151 ); 57 152 58 return fsu.fs; 59 } 60 61 /** Returns FAR (fault address register) content. 62 * 63 * @return FAR (fault address register) content (address that caused a page 153 return fsu; 154 } 155 156 /** Returns DFAR (fault address register) content. 157 * 158 * This register is equivalent to FAR on pre armv6 machines. 159 * 160 * @return DFAR (fault address register) content (address that caused a page 64 161 * fault) 65 162 */ 66 static inline uintptr_t read_ fault_address_register(void)163 static inline uintptr_t read_data_fault_address_register(void) 67 164 { 68 165 uintptr_t ret; … … 77 174 } 78 175 176 #if defined(PROCESSOR_armv4) | defined(PROCESSOR_armv5) 79 177 /** Decides whether read or write into memory is requested. 80 178 * … … 97 195 panic("page_fault - instruction does not access memory " 98 196 "(instr_code: %#0" PRIx32 ", badvaddr:%p).", 99 instr_union.pc, (void *) badvaddr);197 *(uint32_t*)instr_union.instr, (void *) badvaddr); 100 198 return PF_ACCESS_EXEC; 101 199 } … … 136 234 inst, (void *) badvaddr); 137 235 } 236 #endif 138 237 139 238 /** Handles "data abort" exception (load or store at invalid address). … … 145 244 void data_abort(unsigned int exc_no, istate_t *istate) 146 245 { 147 fault_status_t fsr __attribute__ ((unused)) = 148 read_fault_status_register(); 149 uintptr_t badvaddr = read_fault_address_register(); 150 151 pf_access_t access = get_memory_access_type(istate->pc, badvaddr); 152 153 int ret = as_page_fault(badvaddr, access, istate); 246 const uintptr_t badvaddr = read_data_fault_address_register(); 247 const fault_status_t fsr = read_data_fault_status_register(); 248 const dfsr_source_t source = fsr.raw & DFSR_SOURCE_MASK; 249 250 switch (source) { 251 case DFSR_SOURCE_TRANSLATION_L1: 252 case DFSR_SOURCE_TRANSLATION_L2: 253 case DFSR_SOURCE_PERMISSION_L1: 254 case DFSR_SOURCE_PERMISSION_L2: 255 /* Page fault is handled further down */ 256 break; 257 case DFSR_SOURCE_ALIGN: 258 case DFSR_SOURCE_CACHE_MAINTENANCE: 259 case DFSR_SOURCE_SYNC_EXTERNAL_TRANSLATION_L1: 260 case DFSR_SOURCE_SYNC_EXTERNAL_TRANSLATION_L2: 261 case DFSR_SOURCE_SYNC_PARITY_TRANSLATION_L1: 262 case DFSR_SOURCE_SYNC_PARITY_TRANSLATION_L2: 263 case DFSR_SOURCE_ACCESS_FLAG_L1: 264 case DFSR_SOURCE_ACCESS_FLAG_L2: 265 case DFSR_SOURCE_DOMAIN_L1: 266 case DFSR_SOURCE_DOMAIN_L2: 267 case DFSR_SOURCE_DEBUG: 268 case DFSR_SOURCE_SYNC_EXTERNAL: 269 case DFSR_SOURCE_TLB_CONFLICT: 270 case DFSR_SOURCE_LOCKDOWN: 271 case DFSR_SOURCE_COPROCESSOR: 272 case DFSR_SOURCE_SYNC_PARITY: 273 case DFSR_SOURCE_ASYNC_EXTERNAL: 274 case DFSR_SOURCE_ASYNC_PARITY: 275 case DFSR_SOURCE_MASK: 276 /* Weird abort stuff */ 277 fault_if_from_uspace(istate, "Unhandled abort %s at address: " 278 "%#x.", dfsr_source_to_str(source), badvaddr); 279 panic("Unhandled abort %s at address: %#x.", 280 dfsr_source_to_str(source), badvaddr); 281 } 282 283 #if defined(PROCESSOR_armv6) | defined(PROCESSOR_armv7_a) 284 const pf_access_t access = 285 fsr.data.wr ? PF_ACCESS_WRITE : PF_ACCESS_READ; 286 #elif defined(PROCESSOR_armv4) | defined(PROCESSOR_armv5) 287 const pf_access_t access = get_memory_access_type(istate->pc, badvaddr); 288 #else 289 #error "Unsupported architecture" 290 #endif 291 const int ret = as_page_fault(badvaddr, access, istate); 154 292 155 293 if (ret == AS_PF_FAULT) { … … 167 305 void prefetch_abort(unsigned int exc_no, istate_t *istate) 168 306 { 307 /* NOTE: We should use IFAR and IFSR here. */ 169 308 int ret = as_page_fault(istate->pc, PF_ACCESS_EXEC, istate); 170 309
Note:
See TracChangeset
for help on using the changeset viewer.