1/* 2 * linux/arch/arm/kernel/head-common.S 3 * 4 * Copyright (C) 1994-2002 Russell King 5 * Copyright (c) 2003 ARM Limited 6 * All Rights Reserved 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 * 12 */ 13#include <asm/assembler.h> 14 15#define ATAG_CORE 0x54410001 16#define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2) 17#define ATAG_CORE_SIZE_EMPTY ((2*4) >> 2) 18 19#ifdef CONFIG_CPU_BIG_ENDIAN 20#define OF_DT_MAGIC 0xd00dfeed 21#else 22#define OF_DT_MAGIC 0xedfe0dd0 /* 0xd00dfeed in big-endian */ 23#endif 24 25/* 26 * Exception handling. Something went wrong and we can't proceed. We 27 * ought to tell the user, but since we don't have any guarantee that 28 * we're even running on the right architecture, we do virtually nothing. 29 * 30 * If CONFIG_DEBUG_LL is set we try to print out something about the error 31 * and hope for the best (useful if bootloader fails to pass a proper 32 * machine ID for example). 33 */ 34 __HEAD 35 36/* Determine validity of the r2 atags pointer. The heuristic requires 37 * that the pointer be aligned, in the first 16k of physical RAM and 38 * that the ATAG_CORE marker is first and present. If CONFIG_OF_FLATTREE 39 * is selected, then it will also accept a dtb pointer. Future revisions 40 * of this function may be more lenient with the physical address and 41 * may also be able to move the ATAGS block if necessary. 42 * 43 * Returns: 44 * r2 either valid atags pointer, valid dtb pointer, or zero 45 * r5, r6 corrupted 46 */ 47__vet_atags: 48 tst r2, #0x3 @ aligned? 49 bne 1f 50 51 ldr r5, [r2, #0] 52#ifdef CONFIG_OF_FLATTREE 53 ldr r6, =OF_DT_MAGIC @ is it a DTB? 54 cmp r5, r6 55 beq 2f 56#endif 57 cmp r5, #ATAG_CORE_SIZE @ is first tag ATAG_CORE? 58 cmpne r5, #ATAG_CORE_SIZE_EMPTY 59 bne 1f 60 ldr r5, [r2, #4] 61 ldr r6, =ATAG_CORE 62 cmp r5, r6 63 bne 1f 64 652: ret lr @ atag/dtb pointer is ok 66 671: mov r2, #0 68 ret lr 69ENDPROC(__vet_atags) 70 71/* 72 * The following fragment of code is executed with the MMU on in MMU mode, 73 * and uses absolute addresses; this is not position independent. 74 * 75 * r0 = cp#15 control register 76 * r1 = machine ID 77 * r2 = atags/dtb pointer 78 * r9 = processor ID 79 */ 80 __INIT 81__mmap_switched: 82 83 mov r7, r1 84 mov r8, r2 85 mov r10, r0 86 87 adr r4, __mmap_switched_data 88 mov fp, #0 89 90#if defined(CONFIG_XIP_DEFLATED_DATA) 91 ARM( ldr sp, [r4], #4 ) 92 THUMB( ldr sp, [r4] ) 93 THUMB( add r4, #4 ) 94 bl __inflate_kernel_data @ decompress .data to RAM 95 teq r0, #0 96 bne __error 97#elif defined(CONFIG_XIP_KERNEL) 98 ARM( ldmia r4!, {r0, r1, r2, sp} ) 99 THUMB( ldmia r4!, {r0, r1, r2, r3} ) 100 THUMB( mov sp, r3 ) 101 sub r2, r2, r1 102 bl memcpy @ copy .data to RAM 103#endif 104 105 ARM( ldmia r4!, {r0, r1, sp} ) 106 THUMB( ldmia r4!, {r0, r1, r3} ) 107 THUMB( mov sp, r3 ) 108 sub r2, r1, r0 109 mov r1, #0 110 bl memset @ clear .bss 111 112 ldmia r4, {r0, r1, r2, r3} 113 str r9, [r0] @ Save processor ID 114 str r7, [r1] @ Save machine type 115 str r8, [r2] @ Save atags pointer 116 cmp r3, #0 117 strne r10, [r3] @ Save control register values 118 mov lr, #0 119 b start_kernel 120ENDPROC(__mmap_switched) 121 122 .align 2 123 .type __mmap_switched_data, %object 124__mmap_switched_data: 125#ifdef CONFIG_XIP_KERNEL 126#ifndef CONFIG_XIP_DEFLATED_DATA 127 .long _sdata @ r0 128 .long __data_loc @ r1 129 .long _edata_loc @ r2 130#endif 131 .long __bss_stop @ sp (temporary stack in .bss) 132#endif 133 134 .long __bss_start @ r0 135 .long __bss_stop @ r1 136 .long init_thread_union + THREAD_START_SP @ sp 137 138 .long processor_id @ r0 139 .long __machine_arch_type @ r1 140 .long __atags_pointer @ r2 141#ifdef CONFIG_CPU_CP15 142 .long cr_alignment @ r3 143#else 144 .long 0 @ r3 145#endif 146 .size __mmap_switched_data, . - __mmap_switched_data 147 148/* 149 * This provides a C-API version of __lookup_processor_type 150 */ 151ENTRY(lookup_processor_type) 152 stmfd sp!, {r4 - r6, r9, lr} 153 mov r9, r0 154 bl __lookup_processor_type 155 mov r0, r5 156 ldmfd sp!, {r4 - r6, r9, pc} 157ENDPROC(lookup_processor_type) 158 159 __FINIT 160 .text 161 162/* 163 * Read processor ID register (CP#15, CR0), and look up in the linker-built 164 * supported processor list. Note that we can't use the absolute addresses 165 * for the __proc_info lists since we aren't running with the MMU on 166 * (and therefore, we are not in the correct address space). We have to 167 * calculate the offset. 168 * 169 * r9 = cpuid 170 * Returns: 171 * r3, r4, r6 corrupted 172 * r5 = proc_info pointer in physical address space 173 * r9 = cpuid (preserved) 174 */ 175__lookup_processor_type: 176 adr r3, __lookup_processor_type_data 177 ldmia r3, {r4 - r6} 178 sub r3, r3, r4 @ get offset between virt&phys 179 add r5, r5, r3 @ convert virt addresses to 180 add r6, r6, r3 @ physical address space 1811: ldmia r5, {r3, r4} @ value, mask 182 and r4, r4, r9 @ mask wanted bits 183 teq r3, r4 184 beq 2f 185 add r5, r5, #PROC_INFO_SZ @ sizeof(proc_info_list) 186 cmp r5, r6 187 blo 1b 188 mov r5, #0 @ unknown processor 1892: ret lr 190ENDPROC(__lookup_processor_type) 191 192/* 193 * Look in <asm/procinfo.h> for information about the __proc_info structure. 194 */ 195 .align 2 196 .type __lookup_processor_type_data, %object 197__lookup_processor_type_data: 198 .long . 199 .long __proc_info_begin 200 .long __proc_info_end 201 .size __lookup_processor_type_data, . - __lookup_processor_type_data 202 203__error_lpae: 204#ifdef CONFIG_DEBUG_LL 205 adr r0, str_lpae 206 bl printascii 207 b __error 208str_lpae: .asciz "\nError: Kernel with LPAE support, but CPU does not support LPAE.\n" 209#else 210 b __error 211#endif 212 .align 213ENDPROC(__error_lpae) 214 215__error_p: 216#ifdef CONFIG_DEBUG_LL 217 adr r0, str_p1 218 bl printascii 219 mov r0, r9 220 bl printhex8 221 adr r0, str_p2 222 bl printascii 223 b __error 224str_p1: .asciz "\nError: unrecognized/unsupported processor variant (0x" 225str_p2: .asciz ").\n" 226 .align 227#endif 228ENDPROC(__error_p) 229 230__error: 231#ifdef CONFIG_ARCH_RPC 232/* 233 * Turn the screen red on a error - RiscPC only. 234 */ 235 mov r0, #0x02000000 236 mov r3, #0x11 237 orr r3, r3, r3, lsl #8 238 orr r3, r3, r3, lsl #16 239 str r3, [r0], #4 240 str r3, [r0], #4 241 str r3, [r0], #4 242 str r3, [r0], #4 243#endif 2441: mov r0, r0 245 b 1b 246ENDPROC(__error) 247