Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/arm/boot/compressed/head.S
10819 views
1
/*
2
* linux/arch/arm/boot/compressed/head.S
3
*
4
* Copyright (C) 1996-2002 Russell King
5
* Copyright (C) 2004 Hyok S. Choi (MPU support)
6
*
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License version 2 as
9
* published by the Free Software Foundation.
10
*/
11
#include <linux/linkage.h>
12
13
/*
14
* Debugging stuff
15
*
16
* Note that these macros must not contain any code which is not
17
* 100% relocatable. Any attempt to do so will result in a crash.
18
* Please select one of the following when turning on debugging.
19
*/
20
#ifdef DEBUG
21
22
#if defined(CONFIG_DEBUG_ICEDCC)
23
24
#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7)
25
.macro loadsp, rb, tmp
26
.endm
27
.macro writeb, ch, rb
28
mcr p14, 0, \ch, c0, c5, 0
29
.endm
30
#elif defined(CONFIG_CPU_XSCALE)
31
.macro loadsp, rb, tmp
32
.endm
33
.macro writeb, ch, rb
34
mcr p14, 0, \ch, c8, c0, 0
35
.endm
36
#else
37
.macro loadsp, rb, tmp
38
.endm
39
.macro writeb, ch, rb
40
mcr p14, 0, \ch, c1, c0, 0
41
.endm
42
#endif
43
44
#else
45
46
#include <mach/debug-macro.S>
47
48
.macro writeb, ch, rb
49
senduart \ch, \rb
50
.endm
51
52
#if defined(CONFIG_ARCH_SA1100)
53
.macro loadsp, rb, tmp
54
mov \rb, #0x80000000 @ physical base address
55
#ifdef CONFIG_DEBUG_LL_SER3
56
add \rb, \rb, #0x00050000 @ Ser3
57
#else
58
add \rb, \rb, #0x00010000 @ Ser1
59
#endif
60
.endm
61
#elif defined(CONFIG_ARCH_S3C2410)
62
.macro loadsp, rb, tmp
63
mov \rb, #0x50000000
64
add \rb, \rb, #0x4000 * CONFIG_S3C_LOWLEVEL_UART_PORT
65
.endm
66
#else
67
.macro loadsp, rb, tmp
68
addruart \rb, \tmp
69
.endm
70
#endif
71
#endif
72
#endif
73
74
.macro kputc,val
75
mov r0, \val
76
bl putc
77
.endm
78
79
.macro kphex,val,len
80
mov r0, \val
81
mov r1, #\len
82
bl phex
83
.endm
84
85
.macro debug_reloc_start
86
#ifdef DEBUG
87
kputc #'\n'
88
kphex r6, 8 /* processor id */
89
kputc #':'
90
kphex r7, 8 /* architecture id */
91
#ifdef CONFIG_CPU_CP15
92
kputc #':'
93
mrc p15, 0, r0, c1, c0
94
kphex r0, 8 /* control reg */
95
#endif
96
kputc #'\n'
97
kphex r5, 8 /* decompressed kernel start */
98
kputc #'-'
99
kphex r9, 8 /* decompressed kernel end */
100
kputc #'>'
101
kphex r4, 8 /* kernel execution address */
102
kputc #'\n'
103
#endif
104
.endm
105
106
.macro debug_reloc_end
107
#ifdef DEBUG
108
kphex r5, 8 /* end of kernel */
109
kputc #'\n'
110
mov r0, r4
111
bl memdump /* dump 256 bytes at start of kernel */
112
#endif
113
.endm
114
115
.section ".start", #alloc, #execinstr
116
/*
117
* sort out different calling conventions
118
*/
119
.align
120
.arm @ Always enter in ARM state
121
start:
122
.type start,#function
123
.rept 7
124
mov r0, r0
125
.endr
126
ARM( mov r0, r0 )
127
ARM( b 1f )
128
THUMB( adr r12, BSYM(1f) )
129
THUMB( bx r12 )
130
131
.word 0x016f2818 @ Magic numbers to help the loader
132
.word start @ absolute load/run zImage address
133
.word _edata @ zImage end address
134
THUMB( .thumb )
135
1: mov r7, r1 @ save architecture ID
136
mov r8, r2 @ save atags pointer
137
138
#ifndef __ARM_ARCH_2__
139
/*
140
* Booting from Angel - need to enter SVC mode and disable
141
* FIQs/IRQs (numeric definitions from angel arm.h source).
142
* We only do this if we were in user mode on entry.
143
*/
144
mrs r2, cpsr @ get current mode
145
tst r2, #3 @ not user?
146
bne not_angel
147
mov r0, #0x17 @ angel_SWIreason_EnterSVC
148
ARM( swi 0x123456 ) @ angel_SWI_ARM
149
THUMB( svc 0xab ) @ angel_SWI_THUMB
150
not_angel:
151
mrs r2, cpsr @ turn off interrupts to
152
orr r2, r2, #0xc0 @ prevent angel from running
153
msr cpsr_c, r2
154
#else
155
teqp pc, #0x0c000003 @ turn off interrupts
156
#endif
157
158
/*
159
* Note that some cache flushing and other stuff may
160
* be needed here - is there an Angel SWI call for this?
161
*/
162
163
/*
164
* some architecture specific code can be inserted
165
* by the linker here, but it should preserve r7, r8, and r9.
166
*/
167
168
.text
169
170
#ifdef CONFIG_AUTO_ZRELADDR
171
@ determine final kernel image address
172
mov r4, pc
173
and r4, r4, #0xf8000000
174
add r4, r4, #TEXT_OFFSET
175
#else
176
ldr r4, =zreladdr
177
#endif
178
179
bl cache_on
180
181
restart: adr r0, LC0
182
ldmia r0, {r1, r2, r3, r6, r10, r11, r12}
183
ldr sp, [r0, #28]
184
185
/*
186
* We might be running at a different address. We need
187
* to fix up various pointers.
188
*/
189
sub r0, r0, r1 @ calculate the delta offset
190
add r6, r6, r0 @ _edata
191
add r10, r10, r0 @ inflated kernel size location
192
193
/*
194
* The kernel build system appends the size of the
195
* decompressed kernel at the end of the compressed data
196
* in little-endian form.
197
*/
198
ldrb r9, [r10, #0]
199
ldrb lr, [r10, #1]
200
orr r9, r9, lr, lsl #8
201
ldrb lr, [r10, #2]
202
ldrb r10, [r10, #3]
203
orr r9, r9, lr, lsl #16
204
orr r9, r9, r10, lsl #24
205
206
#ifndef CONFIG_ZBOOT_ROM
207
/* malloc space is above the relocated stack (64k max) */
208
add sp, sp, r0
209
add r10, sp, #0x10000
210
#else
211
/*
212
* With ZBOOT_ROM the bss/stack is non relocatable,
213
* but someone could still run this code from RAM,
214
* in which case our reference is _edata.
215
*/
216
mov r10, r6
217
#endif
218
219
/*
220
* Check to see if we will overwrite ourselves.
221
* r4 = final kernel address
222
* r9 = size of decompressed image
223
* r10 = end of this image, including bss/stack/malloc space if non XIP
224
* We basically want:
225
* r4 - 16k page directory >= r10 -> OK
226
* r4 + image length <= current position (pc) -> OK
227
*/
228
add r10, r10, #16384
229
cmp r4, r10
230
bhs wont_overwrite
231
add r10, r4, r9
232
ARM( cmp r10, pc )
233
THUMB( mov lr, pc )
234
THUMB( cmp r10, lr )
235
bls wont_overwrite
236
237
/*
238
* Relocate ourselves past the end of the decompressed kernel.
239
* r6 = _edata
240
* r10 = end of the decompressed kernel
241
* Because we always copy ahead, we need to do it from the end and go
242
* backward in case the source and destination overlap.
243
*/
244
/*
245
* Bump to the next 256-byte boundary with the size of
246
* the relocation code added. This avoids overwriting
247
* ourself when the offset is small.
248
*/
249
add r10, r10, #((reloc_code_end - restart + 256) & ~255)
250
bic r10, r10, #255
251
252
/* Get start of code we want to copy and align it down. */
253
adr r5, restart
254
bic r5, r5, #31
255
256
sub r9, r6, r5 @ size to copy
257
add r9, r9, #31 @ rounded up to a multiple
258
bic r9, r9, #31 @ ... of 32 bytes
259
add r6, r9, r5
260
add r9, r9, r10
261
262
1: ldmdb r6!, {r0 - r3, r10 - r12, lr}
263
cmp r6, r5
264
stmdb r9!, {r0 - r3, r10 - r12, lr}
265
bhi 1b
266
267
/* Preserve offset to relocated code. */
268
sub r6, r9, r6
269
270
#ifndef CONFIG_ZBOOT_ROM
271
/* cache_clean_flush may use the stack, so relocate it */
272
add sp, sp, r6
273
#endif
274
275
bl cache_clean_flush
276
277
adr r0, BSYM(restart)
278
add r0, r0, r6
279
mov pc, r0
280
281
wont_overwrite:
282
/*
283
* If delta is zero, we are running at the address we were linked at.
284
* r0 = delta
285
* r2 = BSS start
286
* r3 = BSS end
287
* r4 = kernel execution address
288
* r7 = architecture ID
289
* r8 = atags pointer
290
* r11 = GOT start
291
* r12 = GOT end
292
* sp = stack pointer
293
*/
294
teq r0, #0
295
beq not_relocated
296
add r11, r11, r0
297
add r12, r12, r0
298
299
#ifndef CONFIG_ZBOOT_ROM
300
/*
301
* If we're running fully PIC === CONFIG_ZBOOT_ROM = n,
302
* we need to fix up pointers into the BSS region.
303
* Note that the stack pointer has already been fixed up.
304
*/
305
add r2, r2, r0
306
add r3, r3, r0
307
308
/*
309
* Relocate all entries in the GOT table.
310
*/
311
1: ldr r1, [r11, #0] @ relocate entries in the GOT
312
add r1, r1, r0 @ table. This fixes up the
313
str r1, [r11], #4 @ C references.
314
cmp r11, r12
315
blo 1b
316
#else
317
318
/*
319
* Relocate entries in the GOT table. We only relocate
320
* the entries that are outside the (relocated) BSS region.
321
*/
322
1: ldr r1, [r11, #0] @ relocate entries in the GOT
323
cmp r1, r2 @ entry < bss_start ||
324
cmphs r3, r1 @ _end < entry
325
addlo r1, r1, r0 @ table. This fixes up the
326
str r1, [r11], #4 @ C references.
327
cmp r11, r12
328
blo 1b
329
#endif
330
331
not_relocated: mov r0, #0
332
1: str r0, [r2], #4 @ clear bss
333
str r0, [r2], #4
334
str r0, [r2], #4
335
str r0, [r2], #4
336
cmp r2, r3
337
blo 1b
338
339
/*
340
* The C runtime environment should now be setup sufficiently.
341
* Set up some pointers, and start decompressing.
342
* r4 = kernel execution address
343
* r7 = architecture ID
344
* r8 = atags pointer
345
*/
346
mov r0, r4
347
mov r1, sp @ malloc space above stack
348
add r2, sp, #0x10000 @ 64k max
349
mov r3, r7
350
bl decompress_kernel
351
bl cache_clean_flush
352
bl cache_off
353
mov r0, #0 @ must be zero
354
mov r1, r7 @ restore architecture number
355
mov r2, r8 @ restore atags pointer
356
mov pc, r4 @ call kernel
357
358
.align 2
359
.type LC0, #object
360
LC0: .word LC0 @ r1
361
.word __bss_start @ r2
362
.word _end @ r3
363
.word _edata @ r6
364
.word input_data_end - 4 @ r10 (inflated size location)
365
.word _got_start @ r11
366
.word _got_end @ ip
367
.word .L_user_stack_end @ sp
368
.size LC0, . - LC0
369
370
#ifdef CONFIG_ARCH_RPC
371
.globl params
372
params: ldr r0, =0x10000100 @ params_phys for RPC
373
mov pc, lr
374
.ltorg
375
.align
376
#endif
377
378
/*
379
* Turn on the cache. We need to setup some page tables so that we
380
* can have both the I and D caches on.
381
*
382
* We place the page tables 16k down from the kernel execution address,
383
* and we hope that nothing else is using it. If we're using it, we
384
* will go pop!
385
*
386
* On entry,
387
* r4 = kernel execution address
388
* r7 = architecture number
389
* r8 = atags pointer
390
* On exit,
391
* r0, r1, r2, r3, r9, r10, r12 corrupted
392
* This routine must preserve:
393
* r4, r7, r8
394
*/
395
.align 5
396
cache_on: mov r3, #8 @ cache_on function
397
b call_cache_fn
398
399
/*
400
* Initialize the highest priority protection region, PR7
401
* to cover all 32bit address and cacheable and bufferable.
402
*/
403
__armv4_mpu_cache_on:
404
mov r0, #0x3f @ 4G, the whole
405
mcr p15, 0, r0, c6, c7, 0 @ PR7 Area Setting
406
mcr p15, 0, r0, c6, c7, 1
407
408
mov r0, #0x80 @ PR7
409
mcr p15, 0, r0, c2, c0, 0 @ D-cache on
410
mcr p15, 0, r0, c2, c0, 1 @ I-cache on
411
mcr p15, 0, r0, c3, c0, 0 @ write-buffer on
412
413
mov r0, #0xc000
414
mcr p15, 0, r0, c5, c0, 1 @ I-access permission
415
mcr p15, 0, r0, c5, c0, 0 @ D-access permission
416
417
mov r0, #0
418
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
419
mcr p15, 0, r0, c7, c5, 0 @ flush(inval) I-Cache
420
mcr p15, 0, r0, c7, c6, 0 @ flush(inval) D-Cache
421
mrc p15, 0, r0, c1, c0, 0 @ read control reg
422
@ ...I .... ..D. WC.M
423
orr r0, r0, #0x002d @ .... .... ..1. 11.1
424
orr r0, r0, #0x1000 @ ...1 .... .... ....
425
426
mcr p15, 0, r0, c1, c0, 0 @ write control reg
427
428
mov r0, #0
429
mcr p15, 0, r0, c7, c5, 0 @ flush(inval) I-Cache
430
mcr p15, 0, r0, c7, c6, 0 @ flush(inval) D-Cache
431
mov pc, lr
432
433
__armv3_mpu_cache_on:
434
mov r0, #0x3f @ 4G, the whole
435
mcr p15, 0, r0, c6, c7, 0 @ PR7 Area Setting
436
437
mov r0, #0x80 @ PR7
438
mcr p15, 0, r0, c2, c0, 0 @ cache on
439
mcr p15, 0, r0, c3, c0, 0 @ write-buffer on
440
441
mov r0, #0xc000
442
mcr p15, 0, r0, c5, c0, 0 @ access permission
443
444
mov r0, #0
445
mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3
446
/*
447
* ?? ARMv3 MMU does not allow reading the control register,
448
* does this really work on ARMv3 MPU?
449
*/
450
mrc p15, 0, r0, c1, c0, 0 @ read control reg
451
@ .... .... .... WC.M
452
orr r0, r0, #0x000d @ .... .... .... 11.1
453
/* ?? this overwrites the value constructed above? */
454
mov r0, #0
455
mcr p15, 0, r0, c1, c0, 0 @ write control reg
456
457
/* ?? invalidate for the second time? */
458
mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3
459
mov pc, lr
460
461
__setup_mmu: sub r3, r4, #16384 @ Page directory size
462
bic r3, r3, #0xff @ Align the pointer
463
bic r3, r3, #0x3f00
464
/*
465
* Initialise the page tables, turning on the cacheable and bufferable
466
* bits for the RAM area only.
467
*/
468
mov r0, r3
469
mov r9, r0, lsr #18
470
mov r9, r9, lsl #18 @ start of RAM
471
add r10, r9, #0x10000000 @ a reasonable RAM size
472
mov r1, #0x12
473
orr r1, r1, #3 << 10
474
add r2, r3, #16384
475
1: cmp r1, r9 @ if virt > start of RAM
476
#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
477
orrhs r1, r1, #0x08 @ set cacheable
478
#else
479
orrhs r1, r1, #0x0c @ set cacheable, bufferable
480
#endif
481
cmp r1, r10 @ if virt > end of RAM
482
bichs r1, r1, #0x0c @ clear cacheable, bufferable
483
str r1, [r0], #4 @ 1:1 mapping
484
add r1, r1, #1048576
485
teq r0, r2
486
bne 1b
487
/*
488
* If ever we are running from Flash, then we surely want the cache
489
* to be enabled also for our execution instance... We map 2MB of it
490
* so there is no map overlap problem for up to 1 MB compressed kernel.
491
* If the execution is in RAM then we would only be duplicating the above.
492
*/
493
mov r1, #0x1e
494
orr r1, r1, #3 << 10
495
mov r2, pc
496
mov r2, r2, lsr #20
497
orr r1, r1, r2, lsl #20
498
add r0, r3, r2, lsl #2
499
str r1, [r0], #4
500
add r1, r1, #1048576
501
str r1, [r0]
502
mov pc, lr
503
ENDPROC(__setup_mmu)
504
505
__arm926ejs_mmu_cache_on:
506
#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
507
mov r0, #4 @ put dcache in WT mode
508
mcr p15, 7, r0, c15, c0, 0
509
#endif
510
511
__armv4_mmu_cache_on:
512
mov r12, lr
513
#ifdef CONFIG_MMU
514
bl __setup_mmu
515
mov r0, #0
516
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
517
mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs
518
mrc p15, 0, r0, c1, c0, 0 @ read control reg
519
orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement
520
orr r0, r0, #0x0030
521
#ifdef CONFIG_CPU_ENDIAN_BE8
522
orr r0, r0, #1 << 25 @ big-endian page tables
523
#endif
524
bl __common_mmu_cache_on
525
mov r0, #0
526
mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs
527
#endif
528
mov pc, r12
529
530
__armv7_mmu_cache_on:
531
mov r12, lr
532
#ifdef CONFIG_MMU
533
mrc p15, 0, r11, c0, c1, 4 @ read ID_MMFR0
534
tst r11, #0xf @ VMSA
535
blne __setup_mmu
536
mov r0, #0
537
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
538
tst r11, #0xf @ VMSA
539
mcrne p15, 0, r0, c8, c7, 0 @ flush I,D TLBs
540
#endif
541
mrc p15, 0, r0, c1, c0, 0 @ read control reg
542
orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement
543
orr r0, r0, #0x003c @ write buffer
544
#ifdef CONFIG_MMU
545
#ifdef CONFIG_CPU_ENDIAN_BE8
546
orr r0, r0, #1 << 25 @ big-endian page tables
547
#endif
548
orrne r0, r0, #1 @ MMU enabled
549
movne r1, #-1
550
mcrne p15, 0, r3, c2, c0, 0 @ load page table pointer
551
mcrne p15, 0, r1, c3, c0, 0 @ load domain access control
552
#endif
553
mcr p15, 0, r0, c1, c0, 0 @ load control register
554
mrc p15, 0, r0, c1, c0, 0 @ and read it back
555
mov r0, #0
556
mcr p15, 0, r0, c7, c5, 4 @ ISB
557
mov pc, r12
558
559
__fa526_cache_on:
560
mov r12, lr
561
bl __setup_mmu
562
mov r0, #0
563
mcr p15, 0, r0, c7, c7, 0 @ Invalidate whole cache
564
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
565
mcr p15, 0, r0, c8, c7, 0 @ flush UTLB
566
mrc p15, 0, r0, c1, c0, 0 @ read control reg
567
orr r0, r0, #0x1000 @ I-cache enable
568
bl __common_mmu_cache_on
569
mov r0, #0
570
mcr p15, 0, r0, c8, c7, 0 @ flush UTLB
571
mov pc, r12
572
573
__arm6_mmu_cache_on:
574
mov r12, lr
575
bl __setup_mmu
576
mov r0, #0
577
mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3
578
mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3
579
mov r0, #0x30
580
bl __common_mmu_cache_on
581
mov r0, #0
582
mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3
583
mov pc, r12
584
585
__common_mmu_cache_on:
586
#ifndef CONFIG_THUMB2_KERNEL
587
#ifndef DEBUG
588
orr r0, r0, #0x000d @ Write buffer, mmu
589
#endif
590
mov r1, #-1
591
mcr p15, 0, r3, c2, c0, 0 @ load page table pointer
592
mcr p15, 0, r1, c3, c0, 0 @ load domain access control
593
b 1f
594
.align 5 @ cache line aligned
595
1: mcr p15, 0, r0, c1, c0, 0 @ load control register
596
mrc p15, 0, r0, c1, c0, 0 @ and read it back to
597
sub pc, lr, r0, lsr #32 @ properly flush pipeline
598
#endif
599
600
#define PROC_ENTRY_SIZE (4*5)
601
602
/*
603
* Here follow the relocatable cache support functions for the
604
* various processors. This is a generic hook for locating an
605
* entry and jumping to an instruction at the specified offset
606
* from the start of the block. Please note this is all position
607
* independent code.
608
*
609
* r1 = corrupted
610
* r2 = corrupted
611
* r3 = block offset
612
* r9 = corrupted
613
* r12 = corrupted
614
*/
615
616
call_cache_fn: adr r12, proc_types
617
#ifdef CONFIG_CPU_CP15
618
mrc p15, 0, r9, c0, c0 @ get processor ID
619
#else
620
ldr r9, =CONFIG_PROCESSOR_ID
621
#endif
622
1: ldr r1, [r12, #0] @ get value
623
ldr r2, [r12, #4] @ get mask
624
eor r1, r1, r9 @ (real ^ match)
625
tst r1, r2 @ & mask
626
ARM( addeq pc, r12, r3 ) @ call cache function
627
THUMB( addeq r12, r3 )
628
THUMB( moveq pc, r12 ) @ call cache function
629
add r12, r12, #PROC_ENTRY_SIZE
630
b 1b
631
632
/*
633
* Table for cache operations. This is basically:
634
* - CPU ID match
635
* - CPU ID mask
636
* - 'cache on' method instruction
637
* - 'cache off' method instruction
638
* - 'cache flush' method instruction
639
*
640
* We match an entry using: ((real_id ^ match) & mask) == 0
641
*
642
* Writethrough caches generally only need 'on' and 'off'
643
* methods. Writeback caches _must_ have the flush method
644
* defined.
645
*/
646
.align 2
647
.type proc_types,#object
648
proc_types:
649
.word 0x41560600 @ ARM6/610
650
.word 0xffffffe0
651
W(b) __arm6_mmu_cache_off @ works, but slow
652
W(b) __arm6_mmu_cache_off
653
mov pc, lr
654
THUMB( nop )
655
@ b __arm6_mmu_cache_on @ untested
656
@ b __arm6_mmu_cache_off
657
@ b __armv3_mmu_cache_flush
658
659
.word 0x00000000 @ old ARM ID
660
.word 0x0000f000
661
mov pc, lr
662
THUMB( nop )
663
mov pc, lr
664
THUMB( nop )
665
mov pc, lr
666
THUMB( nop )
667
668
.word 0x41007000 @ ARM7/710
669
.word 0xfff8fe00
670
W(b) __arm7_mmu_cache_off
671
W(b) __arm7_mmu_cache_off
672
mov pc, lr
673
THUMB( nop )
674
675
.word 0x41807200 @ ARM720T (writethrough)
676
.word 0xffffff00
677
W(b) __armv4_mmu_cache_on
678
W(b) __armv4_mmu_cache_off
679
mov pc, lr
680
THUMB( nop )
681
682
.word 0x41007400 @ ARM74x
683
.word 0xff00ff00
684
W(b) __armv3_mpu_cache_on
685
W(b) __armv3_mpu_cache_off
686
W(b) __armv3_mpu_cache_flush
687
688
.word 0x41009400 @ ARM94x
689
.word 0xff00ff00
690
W(b) __armv4_mpu_cache_on
691
W(b) __armv4_mpu_cache_off
692
W(b) __armv4_mpu_cache_flush
693
694
.word 0x41069260 @ ARM926EJ-S (v5TEJ)
695
.word 0xff0ffff0
696
W(b) __arm926ejs_mmu_cache_on
697
W(b) __armv4_mmu_cache_off
698
W(b) __armv5tej_mmu_cache_flush
699
700
.word 0x00007000 @ ARM7 IDs
701
.word 0x0000f000
702
mov pc, lr
703
THUMB( nop )
704
mov pc, lr
705
THUMB( nop )
706
mov pc, lr
707
THUMB( nop )
708
709
@ Everything from here on will be the new ID system.
710
711
.word 0x4401a100 @ sa110 / sa1100
712
.word 0xffffffe0
713
W(b) __armv4_mmu_cache_on
714
W(b) __armv4_mmu_cache_off
715
W(b) __armv4_mmu_cache_flush
716
717
.word 0x6901b110 @ sa1110
718
.word 0xfffffff0
719
W(b) __armv4_mmu_cache_on
720
W(b) __armv4_mmu_cache_off
721
W(b) __armv4_mmu_cache_flush
722
723
.word 0x56056900
724
.word 0xffffff00 @ PXA9xx
725
W(b) __armv4_mmu_cache_on
726
W(b) __armv4_mmu_cache_off
727
W(b) __armv4_mmu_cache_flush
728
729
.word 0x56158000 @ PXA168
730
.word 0xfffff000
731
W(b) __armv4_mmu_cache_on
732
W(b) __armv4_mmu_cache_off
733
W(b) __armv5tej_mmu_cache_flush
734
735
.word 0x56050000 @ Feroceon
736
.word 0xff0f0000
737
W(b) __armv4_mmu_cache_on
738
W(b) __armv4_mmu_cache_off
739
W(b) __armv5tej_mmu_cache_flush
740
741
#ifdef CONFIG_CPU_FEROCEON_OLD_ID
742
/* this conflicts with the standard ARMv5TE entry */
743
.long 0x41009260 @ Old Feroceon
744
.long 0xff00fff0
745
b __armv4_mmu_cache_on
746
b __armv4_mmu_cache_off
747
b __armv5tej_mmu_cache_flush
748
#endif
749
750
.word 0x66015261 @ FA526
751
.word 0xff01fff1
752
W(b) __fa526_cache_on
753
W(b) __armv4_mmu_cache_off
754
W(b) __fa526_cache_flush
755
756
@ These match on the architecture ID
757
758
.word 0x00020000 @ ARMv4T
759
.word 0x000f0000
760
W(b) __armv4_mmu_cache_on
761
W(b) __armv4_mmu_cache_off
762
W(b) __armv4_mmu_cache_flush
763
764
.word 0x00050000 @ ARMv5TE
765
.word 0x000f0000
766
W(b) __armv4_mmu_cache_on
767
W(b) __armv4_mmu_cache_off
768
W(b) __armv4_mmu_cache_flush
769
770
.word 0x00060000 @ ARMv5TEJ
771
.word 0x000f0000
772
W(b) __armv4_mmu_cache_on
773
W(b) __armv4_mmu_cache_off
774
W(b) __armv5tej_mmu_cache_flush
775
776
.word 0x0007b000 @ ARMv6
777
.word 0x000ff000
778
W(b) __armv4_mmu_cache_on
779
W(b) __armv4_mmu_cache_off
780
W(b) __armv6_mmu_cache_flush
781
782
.word 0x000f0000 @ new CPU Id
783
.word 0x000f0000
784
W(b) __armv7_mmu_cache_on
785
W(b) __armv7_mmu_cache_off
786
W(b) __armv7_mmu_cache_flush
787
788
.word 0 @ unrecognised type
789
.word 0
790
mov pc, lr
791
THUMB( nop )
792
mov pc, lr
793
THUMB( nop )
794
mov pc, lr
795
THUMB( nop )
796
797
.size proc_types, . - proc_types
798
799
/*
800
* If you get a "non-constant expression in ".if" statement"
801
* error from the assembler on this line, check that you have
802
* not accidentally written a "b" instruction where you should
803
* have written W(b).
804
*/
805
.if (. - proc_types) % PROC_ENTRY_SIZE != 0
806
.error "The size of one or more proc_types entries is wrong."
807
.endif
808
809
/*
810
* Turn off the Cache and MMU. ARMv3 does not support
811
* reading the control register, but ARMv4 does.
812
*
813
* On exit,
814
* r0, r1, r2, r3, r9, r12 corrupted
815
* This routine must preserve:
816
* r4, r7, r8
817
*/
818
.align 5
819
cache_off: mov r3, #12 @ cache_off function
820
b call_cache_fn
821
822
__armv4_mpu_cache_off:
823
mrc p15, 0, r0, c1, c0
824
bic r0, r0, #0x000d
825
mcr p15, 0, r0, c1, c0 @ turn MPU and cache off
826
mov r0, #0
827
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
828
mcr p15, 0, r0, c7, c6, 0 @ flush D-Cache
829
mcr p15, 0, r0, c7, c5, 0 @ flush I-Cache
830
mov pc, lr
831
832
__armv3_mpu_cache_off:
833
mrc p15, 0, r0, c1, c0
834
bic r0, r0, #0x000d
835
mcr p15, 0, r0, c1, c0, 0 @ turn MPU and cache off
836
mov r0, #0
837
mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3
838
mov pc, lr
839
840
__armv4_mmu_cache_off:
841
#ifdef CONFIG_MMU
842
mrc p15, 0, r0, c1, c0
843
bic r0, r0, #0x000d
844
mcr p15, 0, r0, c1, c0 @ turn MMU and cache off
845
mov r0, #0
846
mcr p15, 0, r0, c7, c7 @ invalidate whole cache v4
847
mcr p15, 0, r0, c8, c7 @ invalidate whole TLB v4
848
#endif
849
mov pc, lr
850
851
__armv7_mmu_cache_off:
852
mrc p15, 0, r0, c1, c0
853
#ifdef CONFIG_MMU
854
bic r0, r0, #0x000d
855
#else
856
bic r0, r0, #0x000c
857
#endif
858
mcr p15, 0, r0, c1, c0 @ turn MMU and cache off
859
mov r12, lr
860
bl __armv7_mmu_cache_flush
861
mov r0, #0
862
#ifdef CONFIG_MMU
863
mcr p15, 0, r0, c8, c7, 0 @ invalidate whole TLB
864
#endif
865
mcr p15, 0, r0, c7, c5, 6 @ invalidate BTC
866
mcr p15, 0, r0, c7, c10, 4 @ DSB
867
mcr p15, 0, r0, c7, c5, 4 @ ISB
868
mov pc, r12
869
870
__arm6_mmu_cache_off:
871
mov r0, #0x00000030 @ ARM6 control reg.
872
b __armv3_mmu_cache_off
873
874
__arm7_mmu_cache_off:
875
mov r0, #0x00000070 @ ARM7 control reg.
876
b __armv3_mmu_cache_off
877
878
__armv3_mmu_cache_off:
879
mcr p15, 0, r0, c1, c0, 0 @ turn MMU and cache off
880
mov r0, #0
881
mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3
882
mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3
883
mov pc, lr
884
885
/*
886
* Clean and flush the cache to maintain consistency.
887
*
888
* On exit,
889
* r1, r2, r3, r9, r10, r11, r12 corrupted
890
* This routine must preserve:
891
* r4, r6, r7, r8
892
*/
893
.align 5
894
cache_clean_flush:
895
mov r3, #16
896
b call_cache_fn
897
898
__armv4_mpu_cache_flush:
899
mov r2, #1
900
mov r3, #0
901
mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache
902
mov r1, #7 << 5 @ 8 segments
903
1: orr r3, r1, #63 << 26 @ 64 entries
904
2: mcr p15, 0, r3, c7, c14, 2 @ clean & invalidate D index
905
subs r3, r3, #1 << 26
906
bcs 2b @ entries 63 to 0
907
subs r1, r1, #1 << 5
908
bcs 1b @ segments 7 to 0
909
910
teq r2, #0
911
mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
912
mcr p15, 0, ip, c7, c10, 4 @ drain WB
913
mov pc, lr
914
915
__fa526_cache_flush:
916
mov r1, #0
917
mcr p15, 0, r1, c7, c14, 0 @ clean and invalidate D cache
918
mcr p15, 0, r1, c7, c5, 0 @ flush I cache
919
mcr p15, 0, r1, c7, c10, 4 @ drain WB
920
mov pc, lr
921
922
__armv6_mmu_cache_flush:
923
mov r1, #0
924
mcr p15, 0, r1, c7, c14, 0 @ clean+invalidate D
925
mcr p15, 0, r1, c7, c5, 0 @ invalidate I+BTB
926
mcr p15, 0, r1, c7, c15, 0 @ clean+invalidate unified
927
mcr p15, 0, r1, c7, c10, 4 @ drain WB
928
mov pc, lr
929
930
__armv7_mmu_cache_flush:
931
mrc p15, 0, r10, c0, c1, 5 @ read ID_MMFR1
932
tst r10, #0xf << 16 @ hierarchical cache (ARMv7)
933
mov r10, #0
934
beq hierarchical
935
mcr p15, 0, r10, c7, c14, 0 @ clean+invalidate D
936
b iflush
937
hierarchical:
938
mcr p15, 0, r10, c7, c10, 5 @ DMB
939
stmfd sp!, {r0-r7, r9-r11}
940
mrc p15, 1, r0, c0, c0, 1 @ read clidr
941
ands r3, r0, #0x7000000 @ extract loc from clidr
942
mov r3, r3, lsr #23 @ left align loc bit field
943
beq finished @ if loc is 0, then no need to clean
944
mov r10, #0 @ start clean at cache level 0
945
loop1:
946
add r2, r10, r10, lsr #1 @ work out 3x current cache level
947
mov r1, r0, lsr r2 @ extract cache type bits from clidr
948
and r1, r1, #7 @ mask of the bits for current cache only
949
cmp r1, #2 @ see what cache we have at this level
950
blt skip @ skip if no cache, or just i-cache
951
mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr
952
mcr p15, 0, r10, c7, c5, 4 @ isb to sych the new cssr&csidr
953
mrc p15, 1, r1, c0, c0, 0 @ read the new csidr
954
and r2, r1, #7 @ extract the length of the cache lines
955
add r2, r2, #4 @ add 4 (line length offset)
956
ldr r4, =0x3ff
957
ands r4, r4, r1, lsr #3 @ find maximum number on the way size
958
clz r5, r4 @ find bit position of way size increment
959
ldr r7, =0x7fff
960
ands r7, r7, r1, lsr #13 @ extract max number of the index size
961
loop2:
962
mov r9, r4 @ create working copy of max way size
963
loop3:
964
ARM( orr r11, r10, r9, lsl r5 ) @ factor way and cache number into r11
965
ARM( orr r11, r11, r7, lsl r2 ) @ factor index number into r11
966
THUMB( lsl r6, r9, r5 )
967
THUMB( orr r11, r10, r6 ) @ factor way and cache number into r11
968
THUMB( lsl r6, r7, r2 )
969
THUMB( orr r11, r11, r6 ) @ factor index number into r11
970
mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way
971
subs r9, r9, #1 @ decrement the way
972
bge loop3
973
subs r7, r7, #1 @ decrement the index
974
bge loop2
975
skip:
976
add r10, r10, #2 @ increment cache number
977
cmp r3, r10
978
bgt loop1
979
finished:
980
ldmfd sp!, {r0-r7, r9-r11}
981
mov r10, #0 @ swith back to cache level 0
982
mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr
983
iflush:
984
mcr p15, 0, r10, c7, c10, 4 @ DSB
985
mcr p15, 0, r10, c7, c5, 0 @ invalidate I+BTB
986
mcr p15, 0, r10, c7, c10, 4 @ DSB
987
mcr p15, 0, r10, c7, c5, 4 @ ISB
988
mov pc, lr
989
990
__armv5tej_mmu_cache_flush:
991
1: mrc p15, 0, r15, c7, c14, 3 @ test,clean,invalidate D cache
992
bne 1b
993
mcr p15, 0, r0, c7, c5, 0 @ flush I cache
994
mcr p15, 0, r0, c7, c10, 4 @ drain WB
995
mov pc, lr
996
997
__armv4_mmu_cache_flush:
998
mov r2, #64*1024 @ default: 32K dcache size (*2)
999
mov r11, #32 @ default: 32 byte line size
1000
mrc p15, 0, r3, c0, c0, 1 @ read cache type
1001
teq r3, r9 @ cache ID register present?
1002
beq no_cache_id
1003
mov r1, r3, lsr #18
1004
and r1, r1, #7
1005
mov r2, #1024
1006
mov r2, r2, lsl r1 @ base dcache size *2
1007
tst r3, #1 << 14 @ test M bit
1008
addne r2, r2, r2, lsr #1 @ +1/2 size if M == 1
1009
mov r3, r3, lsr #12
1010
and r3, r3, #3
1011
mov r11, #8
1012
mov r11, r11, lsl r3 @ cache line size in bytes
1013
no_cache_id:
1014
mov r1, pc
1015
bic r1, r1, #63 @ align to longest cache line
1016
add r2, r1, r2
1017
1:
1018
ARM( ldr r3, [r1], r11 ) @ s/w flush D cache
1019
THUMB( ldr r3, [r1] ) @ s/w flush D cache
1020
THUMB( add r1, r1, r11 )
1021
teq r1, r2
1022
bne 1b
1023
1024
mcr p15, 0, r1, c7, c5, 0 @ flush I cache
1025
mcr p15, 0, r1, c7, c6, 0 @ flush D cache
1026
mcr p15, 0, r1, c7, c10, 4 @ drain WB
1027
mov pc, lr
1028
1029
__armv3_mmu_cache_flush:
1030
__armv3_mpu_cache_flush:
1031
mov r1, #0
1032
mcr p15, 0, r1, c7, c0, 0 @ invalidate whole cache v3
1033
mov pc, lr
1034
1035
/*
1036
* Various debugging routines for printing hex characters and
1037
* memory, which again must be relocatable.
1038
*/
1039
#ifdef DEBUG
1040
.align 2
1041
.type phexbuf,#object
1042
phexbuf: .space 12
1043
.size phexbuf, . - phexbuf
1044
1045
@ phex corrupts {r0, r1, r2, r3}
1046
phex: adr r3, phexbuf
1047
mov r2, #0
1048
strb r2, [r3, r1]
1049
1: subs r1, r1, #1
1050
movmi r0, r3
1051
bmi puts
1052
and r2, r0, #15
1053
mov r0, r0, lsr #4
1054
cmp r2, #10
1055
addge r2, r2, #7
1056
add r2, r2, #'0'
1057
strb r2, [r3, r1]
1058
b 1b
1059
1060
@ puts corrupts {r0, r1, r2, r3}
1061
puts: loadsp r3, r1
1062
1: ldrb r2, [r0], #1
1063
teq r2, #0
1064
moveq pc, lr
1065
2: writeb r2, r3
1066
mov r1, #0x00020000
1067
3: subs r1, r1, #1
1068
bne 3b
1069
teq r2, #'\n'
1070
moveq r2, #'\r'
1071
beq 2b
1072
teq r0, #0
1073
bne 1b
1074
mov pc, lr
1075
@ putc corrupts {r0, r1, r2, r3}
1076
putc:
1077
mov r2, r0
1078
mov r0, #0
1079
loadsp r3, r1
1080
b 2b
1081
1082
@ memdump corrupts {r0, r1, r2, r3, r10, r11, r12, lr}
1083
memdump: mov r12, r0
1084
mov r10, lr
1085
mov r11, #0
1086
2: mov r0, r11, lsl #2
1087
add r0, r0, r12
1088
mov r1, #8
1089
bl phex
1090
mov r0, #':'
1091
bl putc
1092
1: mov r0, #' '
1093
bl putc
1094
ldr r0, [r12, r11, lsl #2]
1095
mov r1, #8
1096
bl phex
1097
and r0, r11, #7
1098
teq r0, #3
1099
moveq r0, #' '
1100
bleq putc
1101
and r0, r11, #7
1102
add r11, r11, #1
1103
teq r0, #7
1104
bne 1b
1105
mov r0, #'\n'
1106
bl putc
1107
cmp r11, #64
1108
blt 2b
1109
mov pc, r10
1110
#endif
1111
1112
.ltorg
1113
reloc_code_end:
1114
1115
.align
1116
.section ".stack", "aw", %nobits
1117
.L_user_stack: .space 4096
1118
.L_user_stack_end:
1119
1120