Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/arm/kernel/head-common.S
10817 views
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
14
#define ATAG_CORE 0x54410001
15
#define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2)
16
#define ATAG_CORE_SIZE_EMPTY ((2*4) >> 2)
17
18
#ifdef CONFIG_CPU_BIG_ENDIAN
19
#define OF_DT_MAGIC 0xd00dfeed
20
#else
21
#define OF_DT_MAGIC 0xedfe0dd0 /* 0xd00dfeed in big-endian */
22
#endif
23
24
/*
25
* Exception handling. Something went wrong and we can't proceed. We
26
* ought to tell the user, but since we don't have any guarantee that
27
* we're even running on the right architecture, we do virtually nothing.
28
*
29
* If CONFIG_DEBUG_LL is set we try to print out something about the error
30
* and hope for the best (useful if bootloader fails to pass a proper
31
* machine ID for example).
32
*/
33
__HEAD
34
35
/* Determine validity of the r2 atags pointer. The heuristic requires
36
* that the pointer be aligned, in the first 16k of physical RAM and
37
* that the ATAG_CORE marker is first and present. If CONFIG_OF_FLATTREE
38
* is selected, then it will also accept a dtb pointer. Future revisions
39
* of this function may be more lenient with the physical address and
40
* may also be able to move the ATAGS block if necessary.
41
*
42
* Returns:
43
* r2 either valid atags pointer, valid dtb pointer, or zero
44
* r5, r6 corrupted
45
*/
46
__vet_atags:
47
tst r2, #0x3 @ aligned?
48
bne 1f
49
50
ldr r5, [r2, #0]
51
#ifdef CONFIG_OF_FLATTREE
52
ldr r6, =OF_DT_MAGIC @ is it a DTB?
53
cmp r5, r6
54
beq 2f
55
#endif
56
cmp r5, #ATAG_CORE_SIZE @ is first tag ATAG_CORE?
57
cmpne r5, #ATAG_CORE_SIZE_EMPTY
58
bne 1f
59
ldr r5, [r2, #4]
60
ldr r6, =ATAG_CORE
61
cmp r5, r6
62
bne 1f
63
64
2: mov pc, lr @ atag/dtb pointer is ok
65
66
1: mov r2, #0
67
mov pc, lr
68
ENDPROC(__vet_atags)
69
70
/*
71
* The following fragment of code is executed with the MMU on in MMU mode,
72
* and uses absolute addresses; this is not position independent.
73
*
74
* r0 = cp#15 control register
75
* r1 = machine ID
76
* r2 = atags/dtb pointer
77
* r9 = processor ID
78
*/
79
__INIT
80
__mmap_switched:
81
adr r3, __mmap_switched_data
82
83
ldmia r3!, {r4, r5, r6, r7}
84
cmp r4, r5 @ Copy data segment if needed
85
1: cmpne r5, r6
86
ldrne fp, [r4], #4
87
strne fp, [r5], #4
88
bne 1b
89
90
mov fp, #0 @ Clear BSS (and zero fp)
91
1: cmp r6, r7
92
strcc fp, [r6],#4
93
bcc 1b
94
95
ARM( ldmia r3, {r4, r5, r6, r7, sp})
96
THUMB( ldmia r3, {r4, r5, r6, r7} )
97
THUMB( ldr sp, [r3, #16] )
98
str r9, [r4] @ Save processor ID
99
str r1, [r5] @ Save machine type
100
str r2, [r6] @ Save atags pointer
101
bic r4, r0, #CR_A @ Clear 'A' bit
102
stmia r7, {r0, r4} @ Save control register values
103
b start_kernel
104
ENDPROC(__mmap_switched)
105
106
.align 2
107
.type __mmap_switched_data, %object
108
__mmap_switched_data:
109
.long __data_loc @ r4
110
.long _sdata @ r5
111
.long __bss_start @ r6
112
.long _end @ r7
113
.long processor_id @ r4
114
.long __machine_arch_type @ r5
115
.long __atags_pointer @ r6
116
.long cr_alignment @ r7
117
.long init_thread_union + THREAD_START_SP @ sp
118
.size __mmap_switched_data, . - __mmap_switched_data
119
120
/*
121
* This provides a C-API version of __lookup_processor_type
122
*/
123
ENTRY(lookup_processor_type)
124
stmfd sp!, {r4 - r6, r9, lr}
125
mov r9, r0
126
bl __lookup_processor_type
127
mov r0, r5
128
ldmfd sp!, {r4 - r6, r9, pc}
129
ENDPROC(lookup_processor_type)
130
131
/*
132
* Read processor ID register (CP#15, CR0), and look up in the linker-built
133
* supported processor list. Note that we can't use the absolute addresses
134
* for the __proc_info lists since we aren't running with the MMU on
135
* (and therefore, we are not in the correct address space). We have to
136
* calculate the offset.
137
*
138
* r9 = cpuid
139
* Returns:
140
* r3, r4, r6 corrupted
141
* r5 = proc_info pointer in physical address space
142
* r9 = cpuid (preserved)
143
*/
144
__CPUINIT
145
__lookup_processor_type:
146
adr r3, __lookup_processor_type_data
147
ldmia r3, {r4 - r6}
148
sub r3, r3, r4 @ get offset between virt&phys
149
add r5, r5, r3 @ convert virt addresses to
150
add r6, r6, r3 @ physical address space
151
1: ldmia r5, {r3, r4} @ value, mask
152
and r4, r4, r9 @ mask wanted bits
153
teq r3, r4
154
beq 2f
155
add r5, r5, #PROC_INFO_SZ @ sizeof(proc_info_list)
156
cmp r5, r6
157
blo 1b
158
mov r5, #0 @ unknown processor
159
2: mov pc, lr
160
ENDPROC(__lookup_processor_type)
161
162
/*
163
* Look in <asm/procinfo.h> for information about the __proc_info structure.
164
*/
165
.align 2
166
.type __lookup_processor_type_data, %object
167
__lookup_processor_type_data:
168
.long .
169
.long __proc_info_begin
170
.long __proc_info_end
171
.size __lookup_processor_type_data, . - __lookup_processor_type_data
172
173
__error_p:
174
#ifdef CONFIG_DEBUG_LL
175
adr r0, str_p1
176
bl printascii
177
mov r0, r9
178
bl printhex8
179
adr r0, str_p2
180
bl printascii
181
b __error
182
str_p1: .asciz "\nError: unrecognized/unsupported processor variant (0x"
183
str_p2: .asciz ").\n"
184
.align
185
#endif
186
ENDPROC(__error_p)
187
188
__error:
189
#ifdef CONFIG_ARCH_RPC
190
/*
191
* Turn the screen red on a error - RiscPC only.
192
*/
193
mov r0, #0x02000000
194
mov r3, #0x11
195
orr r3, r3, r3, lsl #8
196
orr r3, r3, r3, lsl #16
197
str r3, [r0], #4
198
str r3, [r0], #4
199
str r3, [r0], #4
200
str r3, [r0], #4
201
#endif
202
1: mov r0, r0
203
b 1b
204
ENDPROC(__error)
205
206