Changeset 850235d in mainline for kernel/arch/arm32/src
- Timestamp:
- 2013-03-10T14:56:21Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 05bab88
- Parents:
- ea906c29 (diff), 2277e03 (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. - Location:
- kernel/arch/arm32/src
- Files:
-
- 4 added
- 1 deleted
- 9 edited
-
arm32.c (modified) (3 diffs)
-
cpu/cpu.c (modified) (2 diffs)
-
dummy.S (modified) (2 diffs)
-
exception.c (modified) (6 diffs)
-
fpu.s (added)
-
fpu_context.c (added)
-
mach/beagleboardxm/beagleboardxm.c (added)
-
mach/beaglebone/beaglebone.c (added)
-
mach/gta02/gta02.c (modified) (1 diff)
-
mach/testarm/testarm.c (deleted)
-
machine_func.c (modified) (3 diffs)
-
mm/page.c (modified) (1 diff)
-
mm/page_fault.c (modified) (6 diffs)
-
ras.c (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/arm32/src/arm32.c
rea906c29 r850235d 49 49 #include <str.h> 50 50 #include <arch/ras.h> 51 #include <sysinfo/sysinfo.h> 51 52 52 53 /** Performs arm32-specific initialization before main_bsp() is called. */ … … 116 117 { 117 118 machine_input_init(); 119 const char *platform = machine_get_platform_name(); 120 121 sysinfo_set_item_data("platform", NULL, (void *) platform, 122 str_size(platform)); 118 123 } 119 124 … … 133 138 uint8_t *stck; 134 139 135 stck = &THREAD->kstack[STACK_SIZE - SP_DELTA];140 stck = &THREAD->kstack[STACK_SIZE]; 136 141 supervisor_sp = (uintptr_t) stck; 137 142 } -
kernel/arch/arm32/src/cpu/cpu.c
rea906c29 r850235d 34 34 */ 35 35 36 #include <arch/cache.h> 36 37 #include <arch/cpu.h> 38 #include <arch/cp15.h> 37 39 #include <cpu.h> 38 40 #include <arch.h> 39 41 #include <print.h> 40 42 41 /** Number of indexes left out in the #imp_data array */ 42 #define IMP_DATA_START_OFFSET 0x40 43 44 /** Implementators (vendor) names */ 45 static const char *imp_data[] = { 46 "?", /* IMP_DATA_START_OFFSET */ 47 "ARM Ltd", /* 0x41 */ 48 "", /* 0x42 */ 49 "", /* 0x43 */ 50 "Digital Equipment Corporation", /* 0x44 */ 51 "", "", "", "", "", "", "", "", "", "", /* 0x45 - 0x4e */ 52 "", "", "", "", "", "", "", "", "", "", /* 0x4f - 0x58 */ 53 "", "", "", "", "", "", "", "", "", "", /* 0x59 - 0x62 */ 54 "", "", "", "", "", "", /* 0x63 - 0x68 */ 55 "Intel Corporation" /* 0x69 */ 56 }; 57 58 /** Length of the #imp_data array */ 59 static unsigned int imp_data_length = sizeof(imp_data) / sizeof(char *); 43 static inline unsigned log2(unsigned val) 44 { 45 unsigned log = 0; 46 --val; 47 while (val) { 48 ++log; 49 val >>= 1; 50 } 51 return log; 52 } 53 54 static unsigned dcache_ways(unsigned level); 55 static unsigned dcache_sets(unsigned level); 56 static unsigned dcache_linesize_log(unsigned level); 57 58 59 /** Implementers (vendor) names */ 60 static const char * implementer(unsigned id) 61 { 62 switch (id) 63 { 64 case 0x41: return "ARM Limited"; 65 case 0x44: return "Digital Equipment Corporation"; 66 case 0x4d: return "Motorola, Freescale Semiconductor Inc."; 67 case 0x51: return "Qualcomm Inc."; 68 case 0x56: return "Marvell Semiconductor Inc."; 69 case 0x69: return "Intel Corporation"; 70 } 71 return "Unknown implementer"; 72 } 60 73 61 74 /** Architecture names */ 62 static const char *arch_data[] = { 63 "?", /* 0x0 */ 64 "4", /* 0x1 */ 65 "4T", /* 0x2 */ 66 "5", /* 0x3 */ 67 "5T", /* 0x4 */ 68 "5TE", /* 0x5 */ 69 "5TEJ", /* 0x6 */ 70 "6" /* 0x7 */ 71 }; 72 73 /** Length of the #arch_data array */ 74 static unsigned int arch_data_length = sizeof(arch_data) / sizeof(char *); 75 static const char * architecture_string(cpu_arch_t *arch) 76 { 77 static const char *arch_data[] = { 78 "ARM", /* 0x0 */ 79 "ARMv4", /* 0x1 */ 80 "ARMv4T", /* 0x2 */ 81 "ARMv5", /* 0x3 */ 82 "ARMv5T", /* 0x4 */ 83 "ARMv5TE", /* 0x5 */ 84 "ARMv5TEJ", /* 0x6 */ 85 "ARMv6" /* 0x7 */ 86 }; 87 if (arch->arch_num < (sizeof(arch_data) / sizeof(arch_data[0]))) 88 return arch_data[arch->arch_num]; 89 else 90 return arch_data[0]; 91 } 75 92 76 93 77 94 /** Retrieves processor identification from CP15 register 0. 78 * 95 * 79 96 * @param cpu Structure for storing CPU identification. 97 * See page B4-1630 of ARM Architecture Reference Manual. 80 98 */ 81 99 static void arch_cpu_identify(cpu_arch_t *cpu) 82 100 { 83 uint32_t ident; 84 asm volatile ( 85 "mrc p15, 0, %[ident], c0, c0, 0\n" 86 : [ident] "=r" (ident) 87 ); 101 const uint32_t ident = MIDR_read(); 102 103 cpu->imp_num = (ident >> MIDR_IMPLEMENTER_SHIFT) & MIDR_IMPLEMENTER_MASK; 104 cpu->variant_num = (ident >> MIDR_VARIANT_SHIFT) & MIDR_VARIANT_MASK; 105 cpu->arch_num = (ident >> MIDR_ARCHITECTURE_SHIFT) & MIDR_ARCHITECTURE_MASK; 106 cpu->prim_part_num = (ident >> MIDR_PART_NUMBER_SHIFT) & MIDR_PART_NUMBER_MASK; 107 cpu->rev_num = (ident >> MIDR_REVISION_SHIFT) & MIDR_REVISION_MASK; 108 109 // TODO CPUs with arch_num == 0xf use CPUID scheme for identification 110 cpu->dcache_levels = dcache_levels(); 111 112 for (unsigned i = 0; i < cpu->dcache_levels; ++i) { 113 cpu->dcache[i].ways = dcache_ways(i); 114 cpu->dcache[i].sets = dcache_sets(i); 115 cpu->dcache[i].way_shift = 31 - log2(cpu->dcache[i].ways); 116 cpu->dcache[i].set_shift = dcache_linesize_log(i); 117 cpu->dcache[i].line_size = 1 << dcache_linesize_log(i); 118 printf("Found DCache L%u: %u-way, %u sets, %u byte lines " 119 "(shifts: w%u, s%u)\n", i + 1, cpu->dcache[i].ways, 120 cpu->dcache[i].sets, cpu->dcache[i].line_size, 121 cpu->dcache[i].way_shift, cpu->dcache[i].set_shift); 122 } 123 } 124 125 /** Enables unaligned access and caching for armv6+ */ 126 void cpu_arch_init(void) 127 { 128 uint32_t control_reg = SCTLR_read(); 88 129 89 cpu->imp_num = ident >> 24; 90 cpu->variant_num = (ident << 8) >> 28; 91 cpu->arch_num = (ident << 12) >> 28; 92 cpu->prim_part_num = (ident << 16) >> 20; 93 cpu->rev_num = (ident << 28) >> 28; 94 } 95 96 /** Does nothing on ARM. */ 97 void cpu_arch_init(void) 98 { 130 /* Turn off tex remap, RAZ/WI prior to armv7 */ 131 control_reg &= ~SCTLR_TEX_REMAP_EN_FLAG; 132 /* Turn off accessed flag, RAZ/WI prior to armv7 */ 133 control_reg &= ~(SCTLR_ACCESS_FLAG_EN_FLAG | SCTLR_HW_ACCESS_FLAG_EN_FLAG); 134 135 /* Unaligned access is supported on armv6+ */ 136 #if defined(PROCESSOR_ARCH_armv7_a) | defined(PROCESSOR_ARCH_armv6) 137 /* Enable unaligned access, RAZ/WI prior to armv6 138 * switchable on armv6, RAO/WI writes on armv7, 139 * see ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition 140 * L.3.1 (p. 2456) */ 141 control_reg |= SCTLR_UNALIGNED_EN_FLAG; 142 /* Disable alignment checks, this turns unaligned access to undefined, 143 * unless U bit is set. */ 144 control_reg &= ~SCTLR_ALIGN_CHECK_EN_FLAG; 145 /* Enable caching, On arm prior to armv7 there is only one level 146 * of caches. Data cache is coherent. 147 * "This means that the behavior of accesses from the same observer to 148 * different VAs, that are translated to the same PA 149 * with the same memory attributes, is fully coherent." 150 * ARM Architecture Reference Manual ARMv7-A and ARMv7-R Edition 151 * B3.11.1 (p. 1383) 152 * We are safe to turn this on. For arm v6 see ch L.6.2 (p. 2469) 153 * L2 Cache for armv7 is enabled by default (i.e. controlled by 154 * this flag). 155 */ 156 control_reg |= SCTLR_CACHE_EN_FLAG; 157 #endif 158 #ifdef PROCESSOR_ARCH_armv7_a 159 /* ICache coherency is elaborate on in barrier.h. 160 * VIPT and PIPT caches need maintenance only on code modify, 161 * so it should be safe for general use. 162 * Enable branch predictors too as they follow the same rules 163 * as ICache and they can be flushed together 164 */ 165 if ((CTR_read() & CTR_L1I_POLICY_MASK) != CTR_L1I_POLICY_AIVIVT) { 166 control_reg |= 167 SCTLR_INST_CACHE_EN_FLAG | SCTLR_BRANCH_PREDICT_EN_FLAG; 168 } 169 #endif 170 SCTLR_write(control_reg); 171 172 #ifdef CONFIG_FPU 173 fpu_setup(); 174 #endif 175 176 #ifdef PROCESSOR_ARCH_armv7_a 177 if ((ID_PFR1_read() & ID_PFR1_GEN_TIMER_EXT_MASK) != 178 ID_PFR1_GEN_TIMER_EXT) { 179 PMCR_write(PMCR_read() | PMCR_E_FLAG | PMCR_D_FLAG); 180 PMCNTENSET_write(PMCNTENSET_CYCLE_COUNTER_EN_FLAG); 181 } 182 #endif 99 183 } 100 184 101 185 /** Retrieves processor identification and stores it to #CPU.arch */ 102 void cpu_identify(void) 186 void cpu_identify(void) 103 187 { 104 188 arch_cpu_identify(&CPU->arch); … … 108 192 void cpu_print_report(cpu_t *m) 109 193 { 110 const char *vendor = imp_data[0]; 111 const char *architecture = arch_data[0]; 112 cpu_arch_t * cpu_arch = &m->arch; 113 114 if ((cpu_arch->imp_num) > 0 && 115 (cpu_arch->imp_num < (imp_data_length + IMP_DATA_START_OFFSET))) { 116 vendor = imp_data[cpu_arch->imp_num - IMP_DATA_START_OFFSET]; 117 } 118 119 if ((cpu_arch->arch_num) > 0 && 120 (cpu_arch->arch_num < arch_data_length)) { 121 architecture = arch_data[cpu_arch->arch_num]; 122 } 123 124 printf("cpu%d: vendor=%s, architecture=ARM%s, part number=%x, " 194 printf("cpu%d: vendor=%s, architecture=%s, part number=%x, " 125 195 "variant=%x, revision=%x\n", 126 m->id, vendor, architecture, cpu_arch->prim_part_num, 127 cpu_arch->variant_num, cpu_arch->rev_num); 196 m->id, implementer(m->arch.imp_num), 197 architecture_string(&m->arch), m->arch.prim_part_num, 198 m->arch.variant_num, m->arch.rev_num); 199 } 200 201 /** See chapter B4.1.19 of ARM Architecture Reference Manual */ 202 static unsigned dcache_linesize_log(unsigned level) 203 { 204 #ifdef PROCESSOR_ARCH_armv7_a 205 CSSELR_write((level & CCSELR_LEVEL_MASK) << CCSELR_LEVEL_SHIFT); 206 const unsigned ls_log = 2 + 207 ((CCSIDR_read() >> CCSIDR_LINESIZE_SHIFT) & CCSIDR_LINESIZE_MASK); 208 return ls_log + 2; //return log2(bytes) 209 #endif 210 return 0; 211 212 } 213 214 /** See chapter B4.1.19 of ARM Architecture Reference Manual */ 215 static unsigned dcache_ways(unsigned level) 216 { 217 #ifdef PROCESSOR_ARCH_armv7_a 218 CSSELR_write((level & CCSELR_LEVEL_MASK) << CCSELR_LEVEL_SHIFT); 219 const unsigned ways = 1 + 220 ((CCSIDR_read() >> CCSIDR_ASSOC_SHIFT) & CCSIDR_ASSOC_MASK); 221 return ways; 222 #endif 223 return 0; 224 } 225 226 /** See chapter B4.1.19 of ARM Architecture Reference Manual */ 227 static unsigned dcache_sets(unsigned level) 228 { 229 #ifdef PROCESSOR_ARCH_armv7_a 230 CSSELR_write((level & CCSELR_LEVEL_MASK) << CCSELR_LEVEL_SHIFT); 231 const unsigned sets = 1 + 232 ((CCSIDR_read() >> CCSIDR_NUMSETS_SHIFT) & CCSIDR_NUMSETS_MASK); 233 return sets; 234 #endif 235 return 0; 236 } 237 238 unsigned dcache_levels(void) 239 { 240 unsigned levels = 0; 241 #ifdef PROCESSOR_ARCH_armv7_a 242 const uint32_t val = CLIDR_read(); 243 for (unsigned i = 1; i <= 7; ++i) { 244 const unsigned ctype = CLIDR_CACHE(i, val); 245 switch (ctype) { 246 case CLIDR_DCACHE_ONLY: 247 case CLIDR_SEP_CACHE: 248 case CLIDR_UNI_CACHE: 249 ++levels; 250 default: 251 (void)0; 252 } 253 } 254 #endif 255 return levels; 256 } 257 258 static void dcache_clean_manual(unsigned level, bool invalidate, 259 unsigned ways, unsigned sets, unsigned way_shift, unsigned set_shift) 260 { 261 262 for (unsigned i = 0; i < ways; ++i) { 263 for (unsigned j = 0; j < sets; ++j) { 264 const uint32_t val = 265 ((level & 0x7) << 1) | 266 (j << set_shift) | (i << way_shift); 267 if (invalidate) 268 DCCISW_write(val); 269 else 270 DCCSW_write(val); 271 } 272 } 273 } 274 275 void dcache_flush(void) 276 { 277 /* See ARM Architecture Reference Manual ch. B4.2.1 p. B4-1724 */ 278 const unsigned levels = dcache_levels(); 279 for (unsigned i = 0; i < levels; ++i) { 280 const unsigned ways = dcache_ways(i); 281 const unsigned sets = dcache_sets(i); 282 const unsigned way_shift = 31 - log2(ways); 283 const unsigned set_shift = dcache_linesize_log(i); 284 dcache_clean_manual(i, false, ways, sets, way_shift, set_shift); 285 } 286 } 287 288 void dcache_flush_invalidate(void) 289 { 290 /* See ARM Architecture Reference Manual ch. B4.2.1 p. B4-1724 */ 291 const unsigned levels = dcache_levels(); 292 for (unsigned i = 0; i < levels; ++i) { 293 const unsigned ways = dcache_ways(i); 294 const unsigned sets = dcache_sets(i); 295 const unsigned way_shift = 31 - log2(ways); 296 const unsigned set_shift = dcache_linesize_log(i); 297 dcache_clean_manual(i, true, ways, sets, way_shift, set_shift); 298 } 299 } 300 301 302 void cpu_dcache_flush(void) 303 { 304 for (unsigned i = 0; i < CPU->arch.dcache_levels; ++i) 305 dcache_clean_manual(i, false, 306 CPU->arch.dcache[i].ways, CPU->arch.dcache[i].sets, 307 CPU->arch.dcache[i].way_shift, CPU->arch.dcache[i].set_shift); 308 } 309 310 void cpu_dcache_flush_invalidate(void) 311 { 312 const unsigned levels = dcache_levels(); 313 for (unsigned i = 0; i < levels; ++i) 314 dcache_clean_manual(i, true, 315 CPU->arch.dcache[i].ways, CPU->arch.dcache[i].sets, 316 CPU->arch.dcache[i].way_shift, CPU->arch.dcache[i].set_shift); 317 } 318 319 void icache_invalidate(void) 320 { 321 ICIALLU_write(0); 128 322 } 129 323 -
kernel/arch/arm32/src/dummy.S
rea906c29 r850235d 32 32 .global asm_delay_loop 33 33 34 .global fpu_context_restore35 .global fpu_context_save36 .global fpu_enable37 .global fpu_init38 39 34 .global sys_tls_set 40 35 .global dummy … … 46 41 mov pc, lr 47 42 48 fpu_context_restore:49 mov pc, lr50 51 fpu_context_save:52 mov pc, lr53 54 fpu_enable:55 mov pc, lr56 57 fpu_init:58 mov pc, lr59 60 43 # not used on ARM 61 44 sys_tls_set: -
kernel/arch/arm32/src/exception.c
rea906c29 r850235d 39 39 #include <interrupt.h> 40 40 #include <arch/mm/page_fault.h> 41 #include <arch/cp15.h> 41 42 #include <arch/barrier.h> 42 43 #include <print.h> … … 73 74 /* make it LDR instruction and store at exception vector */ 74 75 *vector = handler_address_ptr | LDR_OPCODE; 75 smc_coherence( *vector);76 smc_coherence(vector); 76 77 77 78 /* store handler's address */ … … 117 118 118 119 #ifdef HIGH_EXCEPTION_VECTORS 119 /** Activates use of high exception vectors addresses. */ 120 /** Activates use of high exception vectors addresses. 121 * 122 * "High vectors were introduced into some implementations of ARMv4 and are 123 * required in ARMv6 implementations. High vectors allow the exception vector 124 * locations to be moved from their normal address range 0x00000000-0x0000001C 125 * at the bottom of the 32-bit address space, to an alternative address range 126 * 0xFFFF0000-0xFFFF001C near the top of the address space. These alternative 127 * locations are known as the high vectors. 128 * 129 * Prior to ARMv6, it is IMPLEMENTATION DEFINED whether the high vectors are 130 * supported. When they are, a hardware configuration input selects whether 131 * the normal vectors or the high vectors are to be used from 132 * reset." ARM Architecture Reference Manual A2.6.11 (p. 64 in the PDF). 133 * 134 * ARM920T (gta02) TRM A2.3.5 (PDF p. 36) and ARM926EJ-S (icp) 2.3.2 (PDF p. 42) 135 * say that armv4 an armv5 chips that we support implement this. 136 */ 120 137 static void high_vectors(void) 121 138 { 122 uint32_t control_reg; 123 124 asm volatile ( 125 "mrc p15, 0, %[control_reg], c1, c0" 126 : [control_reg] "=r" (control_reg) 127 ); 139 uint32_t control_reg = SCTLR_read(); 128 140 129 141 /* switch on the high vectors bit */ 130 control_reg |= CP15_R1_HIGH_VECTORS_BIT; 131 132 asm volatile ( 133 "mcr p15, 0, %[control_reg], c1, c0" 134 :: [control_reg] "r" (control_reg) 135 ); 142 control_reg |= SCTLR_HIGH_VECTORS_EN_FLAG; 143 144 SCTLR_write(control_reg); 136 145 } 137 146 #endif … … 144 153 { 145 154 machine_irq_exception(exc_no, istate); 155 } 156 157 /** Undefined instruction exception handler. 158 * 159 * Calls scheduler_fpu_lazy_request 160 */ 161 static void undef_insn_exception(unsigned int exc_no, istate_t *istate) 162 { 163 #ifdef CONFIG_FPU 164 if (handle_if_fpu_exception()) { 165 /* 166 * Retry the failing instruction, 167 * ARM Architecture Reference Manual says on p.B1-1169 168 * that offset for undef instruction exception is 4 169 */ 170 istate->pc -= 4; 171 return; 172 } 173 #endif 174 fault_if_from_uspace(istate, "Undefined instruction."); 175 panic_badtrap(istate, exc_no, "Undefined instruction."); 146 176 } 147 177 … … 153 183 void exception_init(void) 154 184 { 185 // TODO check for availability of high vectors for <= armv5 155 186 #ifdef HIGH_EXCEPTION_VECTORS 156 187 high_vectors(); … … 158 189 install_exception_handlers(); 159 190 191 exc_register(EXC_UNDEF_INSTR, "undefined instruction", true, 192 (iroutine_t) undef_insn_exception); 160 193 exc_register(EXC_IRQ, "interrupt", true, 161 194 (iroutine_t) irq_exception); -
kernel/arch/arm32/src/mach/gta02/gta02.c
rea906c29 r850235d 27 27 */ 28 28 29 /** @addtogroup arm32g xemul29 /** @addtogroup arm32gta02 30 30 * @{ 31 31 */ -
kernel/arch/arm32/src/machine_func.c
rea906c29 r850235d 41 41 #include <arch/mach/gta02/gta02.h> 42 42 #include <arch/mach/integratorcp/integratorcp.h> 43 #include <arch/mach/testarm/testarm.h> 43 #include <arch/mach/beagleboardxm/beagleboardxm.h> 44 #include <arch/mach/beaglebone/beaglebone.h> 44 45 45 46 /** Pointer to machine_ops structure being used. */ … … 51 52 #if defined(MACHINE_gta02) 52 53 machine_ops = >a02_machine_ops; 53 #elif defined(MACHINE_testarm)54 machine_ops = &gxemul_machine_ops;55 54 #elif defined(MACHINE_integratorcp) 56 55 machine_ops = &icp_machine_ops; 56 #elif defined(MACHINE_beagleboardxm) 57 machine_ops = &bbxm_machine_ops; 58 #elif defined(MACHINE_beaglebone) 59 machine_ops = &bbone_machine_ops; 57 60 #else 58 61 #error Machine type not defined. … … 131 134 } 132 135 136 const char * machine_get_platform_name(void) 137 { 138 if (machine_ops->machine_get_platform_name) 139 return machine_ops->machine_get_platform_name(); 140 return NULL; 141 } 133 142 /** @} 134 143 */ -
kernel/arch/arm32/src/mm/page.c
rea906c29 r850235d 52 52 void page_arch_init(void) 53 53 { 54 int flags = PAGE_CACHEABLE ;54 int flags = PAGE_CACHEABLE | PAGE_EXEC; 55 55 page_mapping_operations = &pt_mapping_operations; 56 56 57 57 page_table_lock(AS_KERNEL, true); 58 58 59 uintptr_t cur;60 61 59 /* Kernel identity mapping */ 62 for (cur = PHYSMEM_START_ADDR; 63 cur < min(config.identity_size, config.physmem_end); 60 //FIXME: We need to consider the possibility that 61 //identity_base > identity_size and physmem_end. 62 //This might lead to overflow if identity_size is too big. 63 for (uintptr_t cur = PHYSMEM_START_ADDR; 64 cur < min(KA2PA(config.identity_base) + 65 config.identity_size, config.physmem_end); 64 66 cur += FRAME_SIZE) 65 67 page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, flags); -
kernel/arch/arm32/src/mm/page_fault.c
rea906c29 r850235d 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 -
kernel/arch/arm32/src/ras.c
rea906c29 r850235d 67 67 void ras_check(unsigned int n, istate_t *istate) 68 68 { 69 uintptr_t rewrite_pc = istate->pc; 69 bool restart_needed = false; 70 uintptr_t restart_pc = 0; 70 71 71 72 if (istate_from_uspace(istate)) { … … 73 74 if ((ras_page[RAS_START] < istate->pc) && 74 75 (ras_page[RAS_END] > istate->pc)) { 75 rewrite_pc = ras_page[RAS_START]; 76 restart_needed = true; 77 restart_pc = ras_page[RAS_START]; 76 78 } 77 79 ras_page[RAS_START] = 0; 78 80 ras_page[RAS_END] = 0xffffffff; 79 } 81 } 80 82 } 81 83 82 84 exc_dispatch(n, istate); 83 84 istate->pc = rewrite_pc;85 if (restart_needed) 86 istate->pc = restart_pc; 85 87 } 86 88
Note:
See TracChangeset
for help on using the changeset viewer.
