Changeset 25eec4e in mainline for kernel/arch/arm32/src/mm/page_fault.c
- Timestamp:
- 2013-04-19T18:38:18Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 6d717a4
- Parents:
- a1e2df13 (diff), 289cb7dd (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
ra1e2df13 r25eec4e 34 34 */ 35 35 #include <panic.h> 36 #include <arch/cp15.h> 36 37 #include <arch/exception.h> 37 38 #include <arch/mm/page_fault.h> … … 42 43 #include <print.h> 43 44 44 /** Returns value stored in fault status register. 45 * 46 * @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; 51 52 /* fault status is stored in CP15 register 5 */ 53 asm volatile ( 54 "mrc p15, 0, %[dummy], c5, c0, 0" 55 : [dummy] "=r" (fsu.dummy) 56 ); 57 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 64 * fault) 65 */ 66 static inline uintptr_t read_fault_address_register(void) 67 { 68 uintptr_t ret; 69 70 /* fault adress is stored in CP15 register 6 */ 71 asm volatile ( 72 "mrc p15, 0, %[ret], c6, c0, 0" 73 : [ret] "=r" (ret) 74 ); 75 76 return ret; 77 } 78 45 46 /** 47 * FSR encoding ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition. 48 * 49 * B3.13.3 page B3-1406 (PDF page 1406) 50 */ 51 typedef enum { 52 DFSR_SOURCE_ALIGN = 0x0001, 53 DFSR_SOURCE_CACHE_MAINTENANCE = 0x0004, 54 DFSR_SOURCE_SYNC_EXTERNAL_TRANSLATION_L1 = 0x000c, 55 DFSR_SOURCE_SYNC_EXTERNAL_TRANSLATION_L2 = 0x000e, 56 DFSR_SOURCE_SYNC_PARITY_TRANSLATION_L1 = 0x040c, 57 DFSR_SOURCE_SYNC_PARITY_TRANSLATION_L2 = 0x040e, 58 DFSR_SOURCE_TRANSLATION_L1 = 0x0005, 59 DFSR_SOURCE_TRANSLATION_L2 = 0x0007, 60 DFSR_SOURCE_ACCESS_FLAG_L1 = 0x0003, /**< @note: This used to be alignment enc. */ 61 DFSR_SOURCE_ACCESS_FLAG_L2 = 0x0006, 62 DFSR_SOURCE_DOMAIN_L1 = 0x0009, 63 DFSR_SOURCE_DOMAIN_L2 = 0x000b, 64 DFSR_SOURCE_PERMISSION_L1 = 0x000d, 65 DFSR_SOURCE_PERMISSION_L2 = 0x000f, 66 DFSR_SOURCE_DEBUG = 0x0002, 67 DFSR_SOURCE_SYNC_EXTERNAL = 0x0008, 68 DFSR_SOURCE_TLB_CONFLICT = 0x0400, 69 DFSR_SOURCE_LOCKDOWN = 0x0404, /**< @note: Implementation defined */ 70 DFSR_SOURCE_COPROCESSOR = 0x040a, /**< @note Implementation defined */ 71 DFSR_SOURCE_SYNC_PARITY = 0x0409, 72 DFSR_SOURCE_ASYNC_EXTERNAL = 0x0406, 73 DFSR_SOURCE_ASYNC_PARITY = 0x0408, 74 DFSR_SOURCE_MASK = 0x0000040f, 75 } dfsr_source_t; 76 77 static inline const char * dfsr_source_to_str(dfsr_source_t source) 78 { 79 switch (source) { 80 case DFSR_SOURCE_TRANSLATION_L1: 81 return "Translation fault L1"; 82 case DFSR_SOURCE_TRANSLATION_L2: 83 return "Translation fault L2"; 84 case DFSR_SOURCE_PERMISSION_L1: 85 return "Permission fault L1"; 86 case DFSR_SOURCE_PERMISSION_L2: 87 return "Permission fault L2"; 88 case DFSR_SOURCE_ALIGN: 89 return "Alignment fault"; 90 case DFSR_SOURCE_CACHE_MAINTENANCE: 91 return "Instruction cache maintenance fault"; 92 case DFSR_SOURCE_SYNC_EXTERNAL_TRANSLATION_L1: 93 return "Synchronous external abort on translation table walk level 1"; 94 case DFSR_SOURCE_SYNC_EXTERNAL_TRANSLATION_L2: 95 return "Synchronous external abort on translation table walk level 2"; 96 case DFSR_SOURCE_SYNC_PARITY_TRANSLATION_L1: 97 return "Synchronous parity error on translation table walk level 1"; 98 case DFSR_SOURCE_SYNC_PARITY_TRANSLATION_L2: 99 return "Synchronous parity error on translation table walk level 2"; 100 case DFSR_SOURCE_ACCESS_FLAG_L1: 101 return "Access flag fault L1"; 102 case DFSR_SOURCE_ACCESS_FLAG_L2: 103 return "Access flag fault L2"; 104 case DFSR_SOURCE_DOMAIN_L1: 105 return "Domain fault L1"; 106 case DFSR_SOURCE_DOMAIN_L2: 107 return "Domain flault L2"; 108 case DFSR_SOURCE_DEBUG: 109 return "Debug event"; 110 case DFSR_SOURCE_SYNC_EXTERNAL: 111 return "Synchronous external abort"; 112 case DFSR_SOURCE_TLB_CONFLICT: 113 return "TLB conflict abort"; 114 case DFSR_SOURCE_LOCKDOWN: 115 return "Lockdown (Implementation defined)"; 116 case DFSR_SOURCE_COPROCESSOR: 117 return "Coprocessor abort (Implementation defined)"; 118 case DFSR_SOURCE_SYNC_PARITY: 119 return "Synchronous parity error on memory access"; 120 case DFSR_SOURCE_ASYNC_EXTERNAL: 121 return "Asynchronous external abort"; 122 case DFSR_SOURCE_ASYNC_PARITY: 123 return "Asynchronous parity error on memory access"; 124 case DFSR_SOURCE_MASK: 125 break; 126 } 127 return "Unknown data abort"; 128 } 129 130 #if defined(PROCESSOR_ARCH_armv4) | defined(PROCESSOR_ARCH_armv5) 79 131 /** Decides whether read or write into memory is requested. 80 132 * … … 97 149 panic("page_fault - instruction does not access memory " 98 150 "(instr_code: %#0" PRIx32 ", badvaddr:%p).", 99 instr_union.pc, (void *) badvaddr);151 *(uint32_t*)instr_union.instr, (void *) badvaddr); 100 152 return PF_ACCESS_EXEC; 101 153 } … … 136 188 inst, (void *) badvaddr); 137 189 } 190 #endif 138 191 139 192 /** Handles "data abort" exception (load or store at invalid address). … … 145 198 void data_abort(unsigned int exc_no, istate_t *istate) 146 199 { 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); 154 155 if (ret == AS_PF_FAULT) { 156 fault_if_from_uspace(istate, "Page fault: %#x.", badvaddr); 157 panic_memtrap(istate, access, badvaddr, NULL); 158 } 200 const uintptr_t badvaddr = DFAR_read(); 201 const fault_status_t fsr = { .raw = DFSR_read() }; 202 const dfsr_source_t source = fsr.raw & DFSR_SOURCE_MASK; 203 204 switch (source) { 205 case DFSR_SOURCE_TRANSLATION_L1: 206 case DFSR_SOURCE_TRANSLATION_L2: 207 case DFSR_SOURCE_PERMISSION_L1: 208 case DFSR_SOURCE_PERMISSION_L2: 209 /* Page fault is handled further down */ 210 break; 211 case DFSR_SOURCE_ALIGN: 212 case DFSR_SOURCE_CACHE_MAINTENANCE: 213 case DFSR_SOURCE_SYNC_EXTERNAL_TRANSLATION_L1: 214 case DFSR_SOURCE_SYNC_EXTERNAL_TRANSLATION_L2: 215 case DFSR_SOURCE_SYNC_PARITY_TRANSLATION_L1: 216 case DFSR_SOURCE_SYNC_PARITY_TRANSLATION_L2: 217 case DFSR_SOURCE_ACCESS_FLAG_L1: 218 case DFSR_SOURCE_ACCESS_FLAG_L2: 219 case DFSR_SOURCE_DOMAIN_L1: 220 case DFSR_SOURCE_DOMAIN_L2: 221 case DFSR_SOURCE_DEBUG: 222 case DFSR_SOURCE_SYNC_EXTERNAL: 223 case DFSR_SOURCE_TLB_CONFLICT: 224 case DFSR_SOURCE_LOCKDOWN: 225 case DFSR_SOURCE_COPROCESSOR: 226 case DFSR_SOURCE_SYNC_PARITY: 227 case DFSR_SOURCE_ASYNC_EXTERNAL: 228 case DFSR_SOURCE_ASYNC_PARITY: 229 case DFSR_SOURCE_MASK: 230 /* Weird abort stuff */ 231 fault_if_from_uspace(istate, "Unhandled abort %s at address: " 232 "%#x.", dfsr_source_to_str(source), badvaddr); 233 panic("Unhandled abort %s at address: %#x.", 234 dfsr_source_to_str(source), badvaddr); 235 } 236 237 #if defined(PROCESSOR_ARCH_armv6) | defined(PROCESSOR_ARCH_armv7_a) 238 const pf_access_t access = 239 fsr.data.wr ? PF_ACCESS_WRITE : PF_ACCESS_READ; 240 #elif defined(PROCESSOR_ARCH_armv4) | defined(PROCESSOR_ARCH_armv5) 241 const pf_access_t access = get_memory_access_type(istate->pc, badvaddr); 242 #else 243 #error "Unsupported architecture" 244 #endif 245 as_page_fault(badvaddr, access, istate); 159 246 } 160 247 … … 167 254 void prefetch_abort(unsigned int exc_no, istate_t *istate) 168 255 { 169 int ret = as_page_fault(istate->pc, PF_ACCESS_EXEC, istate); 170 171 if (ret == AS_PF_FAULT) { 172 fault_if_from_uspace(istate, 173 "Page fault - prefetch_abort: %#x.", istate->pc); 174 panic_memtrap(istate, PF_ACCESS_EXEC, istate->pc, NULL); 175 } 256 as_page_fault(istate->pc, PF_ACCESS_EXEC, istate); 176 257 } 177 258
Note:
See TracChangeset
for help on using the changeset viewer.