diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2006-03-28 16:05:10 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2006-03-28 16:05:10 -0500 |
commit | ae574a5d7aa1d80469dfcbaa757db2bea536ee66 (patch) | |
tree | 6cfa7750df998359295227b76256d488f6d39d19 | |
parent | c4713074375c61f939310b04e92090afe29810dc (diff) | |
parent | c760fc1997e8156ebc4134c42c18f68137c689f9 (diff) |
Merge nommu tree
-rw-r--r-- | arch/arm/Kconfig | 8 | ||||
-rw-r--r-- | arch/arm/Kconfig-nommu | 44 | ||||
-rw-r--r-- | arch/arm/Makefile | 9 | ||||
-rw-r--r-- | arch/arm/boot/compressed/head.S | 106 | ||||
-rw-r--r-- | arch/arm/kernel/head-common.S | 217 | ||||
-rw-r--r-- | arch/arm/kernel/head-nommu.S | 83 | ||||
-rw-r--r-- | arch/arm/kernel/head.S | 207 | ||||
-rw-r--r-- | arch/arm/kernel/signal.h | 2 | ||||
-rw-r--r-- | arch/arm/kernel/traps.c | 9 |
9 files changed, 472 insertions, 213 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 427c72140110..1077c671256f 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -72,6 +72,14 @@ config FIQ | |||
72 | config ARCH_MTD_XIP | 72 | config ARCH_MTD_XIP |
73 | bool | 73 | bool |
74 | 74 | ||
75 | config VECTORS_BASE | ||
76 | hex | ||
77 | default 0xffff0000 if MMU | ||
78 | default DRAM_BASE if REMAP_VECTORS_TO_RAM | ||
79 | default 0x00000000 | ||
80 | help | ||
81 | The base address of exception vectors. | ||
82 | |||
75 | source "init/Kconfig" | 83 | source "init/Kconfig" |
76 | 84 | ||
77 | menu "System Type" | 85 | menu "System Type" |
diff --git a/arch/arm/Kconfig-nommu b/arch/arm/Kconfig-nommu new file mode 100644 index 000000000000..e1574be2ded6 --- /dev/null +++ b/arch/arm/Kconfig-nommu | |||
@@ -0,0 +1,44 @@ | |||
1 | # | ||
2 | # Kconfig for uClinux(non-paged MM) depend configurations | ||
3 | # Hyok S. Choi <hyok.choi@samsung.com> | ||
4 | # | ||
5 | |||
6 | config SET_MEM_PARAM | ||
7 | bool "Set flash/sdram size and base addr" | ||
8 | help | ||
9 | Say Y to manually set the base addresses and sizes. | ||
10 | otherwise, the default values are assigned. | ||
11 | |||
12 | config DRAM_BASE | ||
13 | hex '(S)DRAM Base Address' if SET_MEM_PARAM | ||
14 | default 0x00800000 | ||
15 | |||
16 | config DRAM_SIZE | ||
17 | hex '(S)DRAM SIZE' if SET_MEM_PARAM | ||
18 | default 0x00800000 | ||
19 | |||
20 | config FLASH_MEM_BASE | ||
21 | hex 'FLASH Base Address' if SET_MEM_PARAM | ||
22 | default 0x00400000 | ||
23 | |||
24 | config FLASH_SIZE | ||
25 | hex 'FLASH Size' if SET_MEM_PARAM | ||
26 | default 0x00400000 | ||
27 | |||
28 | config REMAP_VECTORS_TO_RAM | ||
29 | bool 'Install vectors to the begining of RAM' if DRAM_BASE | ||
30 | depends on DRAM_BASE | ||
31 | help | ||
32 | The kernel needs to change the hardware exception vectors. | ||
33 | In nommu mode, the hardware exception vectors are normally | ||
34 | placed at address 0x00000000. However, this region may be | ||
35 | occupied by read-only memory depending on H/W design. | ||
36 | |||
37 | If the region contains read-write memory, say 'n' here. | ||
38 | |||
39 | If your CPU provides a remap facility which allows the exception | ||
40 | vectors to be mapped to writable memory, say 'n' here. | ||
41 | |||
42 | Otherwise, say 'y' here. In this case, the kernel will require | ||
43 | external support to redirect the hardware exception vectors to | ||
44 | the writable versions located at DRAM_BASE. | ||
diff --git a/arch/arm/Makefile b/arch/arm/Makefile index ce3e804ea0f3..95a96275f88a 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile | |||
@@ -20,6 +20,11 @@ GZFLAGS :=-9 | |||
20 | # Select a platform tht is kept up-to-date | 20 | # Select a platform tht is kept up-to-date |
21 | KBUILD_DEFCONFIG := versatile_defconfig | 21 | KBUILD_DEFCONFIG := versatile_defconfig |
22 | 22 | ||
23 | # defines filename extension depending memory manement type. | ||
24 | ifeq ($(CONFIG_MMU),) | ||
25 | MMUEXT := -nommu | ||
26 | endif | ||
27 | |||
23 | ifeq ($(CONFIG_FRAME_POINTER),y) | 28 | ifeq ($(CONFIG_FRAME_POINTER),y) |
24 | CFLAGS +=-fno-omit-frame-pointer -mapcs -mno-sched-prolog | 29 | CFLAGS +=-fno-omit-frame-pointer -mapcs -mno-sched-prolog |
25 | endif | 30 | endif |
@@ -73,7 +78,7 @@ AFLAGS +=$(CFLAGS_ABI) $(arch-y) $(tune-y) -msoft-float | |||
73 | CHECKFLAGS += -D__arm__ | 78 | CHECKFLAGS += -D__arm__ |
74 | 79 | ||
75 | #Default value | 80 | #Default value |
76 | head-y := arch/arm/kernel/head.o arch/arm/kernel/init_task.o | 81 | head-y := arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o |
77 | textofs-y := 0x00008000 | 82 | textofs-y := 0x00008000 |
78 | 83 | ||
79 | machine-$(CONFIG_ARCH_RPC) := rpc | 84 | machine-$(CONFIG_ARCH_RPC) := rpc |
@@ -133,7 +138,7 @@ else | |||
133 | MACHINE := | 138 | MACHINE := |
134 | endif | 139 | endif |
135 | 140 | ||
136 | export TEXT_OFFSET GZFLAGS | 141 | export TEXT_OFFSET GZFLAGS MMUEXT |
137 | 142 | ||
138 | # Do we have FASTFPE? | 143 | # Do we have FASTFPE? |
139 | FASTFPE :=arch/arm/fastfpe | 144 | FASTFPE :=arch/arm/fastfpe |
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index 491c7e4c9ac6..b56f5e691d65 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S | |||
@@ -2,6 +2,7 @@ | |||
2 | * linux/arch/arm/boot/compressed/head.S | 2 | * linux/arch/arm/boot/compressed/head.S |
3 | * | 3 | * |
4 | * Copyright (C) 1996-2002 Russell King | 4 | * Copyright (C) 1996-2002 Russell King |
5 | * Copyright (C) 2004 Hyok S. Choi (MPU support) | ||
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
@@ -320,6 +321,62 @@ params: ldr r0, =params_phys | |||
320 | cache_on: mov r3, #8 @ cache_on function | 321 | cache_on: mov r3, #8 @ cache_on function |
321 | b call_cache_fn | 322 | b call_cache_fn |
322 | 323 | ||
324 | /* | ||
325 | * Initialize the highest priority protection region, PR7 | ||
326 | * to cover all 32bit address and cacheable and bufferable. | ||
327 | */ | ||
328 | __armv4_mpu_cache_on: | ||
329 | mov r0, #0x3f @ 4G, the whole | ||
330 | mcr p15, 0, r0, c6, c7, 0 @ PR7 Area Setting | ||
331 | mcr p15, 0, r0, c6, c7, 1 | ||
332 | |||
333 | mov r0, #0x80 @ PR7 | ||
334 | mcr p15, 0, r0, c2, c0, 0 @ D-cache on | ||
335 | mcr p15, 0, r0, c2, c0, 1 @ I-cache on | ||
336 | mcr p15, 0, r0, c3, c0, 0 @ write-buffer on | ||
337 | |||
338 | mov r0, #0xc000 | ||
339 | mcr p15, 0, r0, c5, c0, 1 @ I-access permission | ||
340 | mcr p15, 0, r0, c5, c0, 0 @ D-access permission | ||
341 | |||
342 | mov r0, #0 | ||
343 | mcr p15, 0, r0, c7, c10, 4 @ drain write buffer | ||
344 | mcr p15, 0, r0, c7, c5, 0 @ flush(inval) I-Cache | ||
345 | mcr p15, 0, r0, c7, c6, 0 @ flush(inval) D-Cache | ||
346 | mrc p15, 0, r0, c1, c0, 0 @ read control reg | ||
347 | @ ...I .... ..D. WC.M | ||
348 | orr r0, r0, #0x002d @ .... .... ..1. 11.1 | ||
349 | orr r0, r0, #0x1000 @ ...1 .... .... .... | ||
350 | |||
351 | mcr p15, 0, r0, c1, c0, 0 @ write control reg | ||
352 | |||
353 | mov r0, #0 | ||
354 | mcr p15, 0, r0, c7, c5, 0 @ flush(inval) I-Cache | ||
355 | mcr p15, 0, r0, c7, c6, 0 @ flush(inval) D-Cache | ||
356 | mov pc, lr | ||
357 | |||
358 | __armv3_mpu_cache_on: | ||
359 | mov r0, #0x3f @ 4G, the whole | ||
360 | mcr p15, 0, r0, c6, c7, 0 @ PR7 Area Setting | ||
361 | |||
362 | mov r0, #0x80 @ PR7 | ||
363 | mcr p15, 0, r0, c2, c0, 0 @ cache on | ||
364 | mcr p15, 0, r0, c3, c0, 0 @ write-buffer on | ||
365 | |||
366 | mov r0, #0xc000 | ||
367 | mcr p15, 0, r0, c5, c0, 0 @ access permission | ||
368 | |||
369 | mov r0, #0 | ||
370 | mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3 | ||
371 | mrc p15, 0, r0, c1, c0, 0 @ read control reg | ||
372 | @ .... .... .... WC.M | ||
373 | orr r0, r0, #0x000d @ .... .... .... 11.1 | ||
374 | mov r0, #0 | ||
375 | mcr p15, 0, r0, c1, c0, 0 @ write control reg | ||
376 | |||
377 | mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3 | ||
378 | mov pc, lr | ||
379 | |||
323 | __setup_mmu: sub r3, r4, #16384 @ Page directory size | 380 | __setup_mmu: sub r3, r4, #16384 @ Page directory size |
324 | bic r3, r3, #0xff @ Align the pointer | 381 | bic r3, r3, #0xff @ Align the pointer |
325 | bic r3, r3, #0x3f00 | 382 | bic r3, r3, #0x3f00 |
@@ -496,6 +553,18 @@ proc_types: | |||
496 | b __armv4_mmu_cache_off | 553 | b __armv4_mmu_cache_off |
497 | mov pc, lr | 554 | mov pc, lr |
498 | 555 | ||
556 | .word 0x41007400 @ ARM74x | ||
557 | .word 0xff00ff00 | ||
558 | b __armv3_mpu_cache_on | ||
559 | b __armv3_mpu_cache_off | ||
560 | b __armv3_mpu_cache_flush | ||
561 | |||
562 | .word 0x41009400 @ ARM94x | ||
563 | .word 0xff00ff00 | ||
564 | b __armv4_mpu_cache_on | ||
565 | b __armv4_mpu_cache_off | ||
566 | b __armv4_mpu_cache_flush | ||
567 | |||
499 | .word 0x00007000 @ ARM7 IDs | 568 | .word 0x00007000 @ ARM7 IDs |
500 | .word 0x0000f000 | 569 | .word 0x0000f000 |
501 | mov pc, lr | 570 | mov pc, lr |
@@ -562,6 +631,24 @@ proc_types: | |||
562 | cache_off: mov r3, #12 @ cache_off function | 631 | cache_off: mov r3, #12 @ cache_off function |
563 | b call_cache_fn | 632 | b call_cache_fn |
564 | 633 | ||
634 | __armv4_mpu_cache_off: | ||
635 | mrc p15, 0, r0, c1, c0 | ||
636 | bic r0, r0, #0x000d | ||
637 | mcr p15, 0, r0, c1, c0 @ turn MPU and cache off | ||
638 | mov r0, #0 | ||
639 | mcr p15, 0, r0, c7, c10, 4 @ drain write buffer | ||
640 | mcr p15, 0, r0, c7, c6, 0 @ flush D-Cache | ||
641 | mcr p15, 0, r0, c7, c5, 0 @ flush I-Cache | ||
642 | mov pc, lr | ||
643 | |||
644 | __armv3_mpu_cache_off: | ||
645 | mrc p15, 0, r0, c1, c0 | ||
646 | bic r0, r0, #0x000d | ||
647 | mcr p15, 0, r0, c1, c0, 0 @ turn MPU and cache off | ||
648 | mov r0, #0 | ||
649 | mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3 | ||
650 | mov pc, lr | ||
651 | |||
565 | __armv4_mmu_cache_off: | 652 | __armv4_mmu_cache_off: |
566 | mrc p15, 0, r0, c1, c0 | 653 | mrc p15, 0, r0, c1, c0 |
567 | bic r0, r0, #0x000d | 654 | bic r0, r0, #0x000d |
@@ -601,6 +688,24 @@ cache_clean_flush: | |||
601 | mov r3, #16 | 688 | mov r3, #16 |
602 | b call_cache_fn | 689 | b call_cache_fn |
603 | 690 | ||
691 | __armv4_mpu_cache_flush: | ||
692 | mov r2, #1 | ||
693 | mov r3, #0 | ||
694 | mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache | ||
695 | mov r1, #7 << 5 @ 8 segments | ||
696 | 1: orr r3, r1, #63 << 26 @ 64 entries | ||
697 | 2: mcr p15, 0, r3, c7, c14, 2 @ clean & invalidate D index | ||
698 | subs r3, r3, #1 << 26 | ||
699 | bcs 2b @ entries 63 to 0 | ||
700 | subs r1, r1, #1 << 5 | ||
701 | bcs 1b @ segments 7 to 0 | ||
702 | |||
703 | teq r2, #0 | ||
704 | mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache | ||
705 | mcr p15, 0, ip, c7, c10, 4 @ drain WB | ||
706 | mov pc, lr | ||
707 | |||
708 | |||
604 | __armv6_mmu_cache_flush: | 709 | __armv6_mmu_cache_flush: |
605 | mov r1, #0 | 710 | mov r1, #0 |
606 | mcr p15, 0, r1, c7, c14, 0 @ clean+invalidate D | 711 | mcr p15, 0, r1, c7, c14, 0 @ clean+invalidate D |
@@ -638,6 +743,7 @@ no_cache_id: | |||
638 | mov pc, lr | 743 | mov pc, lr |
639 | 744 | ||
640 | __armv3_mmu_cache_flush: | 745 | __armv3_mmu_cache_flush: |
746 | __armv3_mpu_cache_flush: | ||
641 | mov r1, #0 | 747 | mov r1, #0 |
642 | mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3 | 748 | mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3 |
643 | mov pc, lr | 749 | mov pc, lr |
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S new file mode 100644 index 000000000000..a52da0ddb43d --- /dev/null +++ b/arch/arm/kernel/head-common.S | |||
@@ -0,0 +1,217 @@ | |||
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 | .type __switch_data, %object | ||
15 | __switch_data: | ||
16 | .long __mmap_switched | ||
17 | .long __data_loc @ r4 | ||
18 | .long __data_start @ r5 | ||
19 | .long __bss_start @ r6 | ||
20 | .long _end @ r7 | ||
21 | .long processor_id @ r4 | ||
22 | .long __machine_arch_type @ r5 | ||
23 | .long cr_alignment @ r6 | ||
24 | .long init_thread_union + THREAD_START_SP @ sp | ||
25 | |||
26 | /* | ||
27 | * The following fragment of code is executed with the MMU on in MMU mode, | ||
28 | * and uses absolute addresses; this is not position independent. | ||
29 | * | ||
30 | * r0 = cp#15 control register | ||
31 | * r1 = machine ID | ||
32 | * r9 = processor ID | ||
33 | */ | ||
34 | .type __mmap_switched, %function | ||
35 | __mmap_switched: | ||
36 | adr r3, __switch_data + 4 | ||
37 | |||
38 | ldmia r3!, {r4, r5, r6, r7} | ||
39 | cmp r4, r5 @ Copy data segment if needed | ||
40 | 1: cmpne r5, r6 | ||
41 | ldrne fp, [r4], #4 | ||
42 | strne fp, [r5], #4 | ||
43 | bne 1b | ||
44 | |||
45 | mov fp, #0 @ Clear BSS (and zero fp) | ||
46 | 1: cmp r6, r7 | ||
47 | strcc fp, [r6],#4 | ||
48 | bcc 1b | ||
49 | |||
50 | ldmia r3, {r4, r5, r6, sp} | ||
51 | str r9, [r4] @ Save processor ID | ||
52 | str r1, [r5] @ Save machine type | ||
53 | bic r4, r0, #CR_A @ Clear 'A' bit | ||
54 | stmia r6, {r0, r4} @ Save control register values | ||
55 | b start_kernel | ||
56 | |||
57 | /* | ||
58 | * Exception handling. Something went wrong and we can't proceed. We | ||
59 | * ought to tell the user, but since we don't have any guarantee that | ||
60 | * we're even running on the right architecture, we do virtually nothing. | ||
61 | * | ||
62 | * If CONFIG_DEBUG_LL is set we try to print out something about the error | ||
63 | * and hope for the best (useful if bootloader fails to pass a proper | ||
64 | * machine ID for example). | ||
65 | */ | ||
66 | |||
67 | .type __error_p, %function | ||
68 | __error_p: | ||
69 | #ifdef CONFIG_DEBUG_LL | ||
70 | adr r0, str_p1 | ||
71 | bl printascii | ||
72 | b __error | ||
73 | str_p1: .asciz "\nError: unrecognized/unsupported processor variant.\n" | ||
74 | .align | ||
75 | #endif | ||
76 | |||
77 | .type __error_a, %function | ||
78 | __error_a: | ||
79 | #ifdef CONFIG_DEBUG_LL | ||
80 | mov r4, r1 @ preserve machine ID | ||
81 | adr r0, str_a1 | ||
82 | bl printascii | ||
83 | mov r0, r4 | ||
84 | bl printhex8 | ||
85 | adr r0, str_a2 | ||
86 | bl printascii | ||
87 | adr r3, 3f | ||
88 | ldmia r3, {r4, r5, r6} @ get machine desc list | ||
89 | sub r4, r3, r4 @ get offset between virt&phys | ||
90 | add r5, r5, r4 @ convert virt addresses to | ||
91 | add r6, r6, r4 @ physical address space | ||
92 | 1: ldr r0, [r5, #MACHINFO_TYPE] @ get machine type | ||
93 | bl printhex8 | ||
94 | mov r0, #'\t' | ||
95 | bl printch | ||
96 | ldr r0, [r5, #MACHINFO_NAME] @ get machine name | ||
97 | add r0, r0, r4 | ||
98 | bl printascii | ||
99 | mov r0, #'\n' | ||
100 | bl printch | ||
101 | add r5, r5, #SIZEOF_MACHINE_DESC @ next machine_desc | ||
102 | cmp r5, r6 | ||
103 | blo 1b | ||
104 | adr r0, str_a3 | ||
105 | bl printascii | ||
106 | b __error | ||
107 | str_a1: .asciz "\nError: unrecognized/unsupported machine ID (r1 = 0x" | ||
108 | str_a2: .asciz ").\n\nAvailable machine support:\n\nID (hex)\tNAME\n" | ||
109 | str_a3: .asciz "\nPlease check your kernel config and/or bootloader.\n" | ||
110 | .align | ||
111 | #endif | ||
112 | |||
113 | .type __error, %function | ||
114 | __error: | ||
115 | #ifdef CONFIG_ARCH_RPC | ||
116 | /* | ||
117 | * Turn the screen red on a error - RiscPC only. | ||
118 | */ | ||
119 | mov r0, #0x02000000 | ||
120 | mov r3, #0x11 | ||
121 | orr r3, r3, r3, lsl #8 | ||
122 | orr r3, r3, r3, lsl #16 | ||
123 | str r3, [r0], #4 | ||
124 | str r3, [r0], #4 | ||
125 | str r3, [r0], #4 | ||
126 | str r3, [r0], #4 | ||
127 | #endif | ||
128 | 1: mov r0, r0 | ||
129 | b 1b | ||
130 | |||
131 | |||
132 | /* | ||
133 | * Read processor ID register (CP#15, CR0), and look up in the linker-built | ||
134 | * supported processor list. Note that we can't use the absolute addresses | ||
135 | * for the __proc_info lists since we aren't running with the MMU on | ||
136 | * (and therefore, we are not in the correct address space). We have to | ||
137 | * calculate the offset. | ||
138 | * | ||
139 | * r9 = cpuid | ||
140 | * Returns: | ||
141 | * r3, r4, r6 corrupted | ||
142 | * r5 = proc_info pointer in physical address space | ||
143 | * r9 = cpuid (preserved) | ||
144 | */ | ||
145 | .type __lookup_processor_type, %function | ||
146 | __lookup_processor_type: | ||
147 | adr r3, 3f | ||
148 | ldmda r3, {r5 - r7} | ||
149 | sub r3, r3, r7 @ get offset between virt&phys | ||
150 | add r5, r5, r3 @ convert virt addresses to | ||
151 | add r6, r6, r3 @ physical address space | ||
152 | 1: ldmia r5, {r3, r4} @ value, mask | ||
153 | and r4, r4, r9 @ mask wanted bits | ||
154 | teq r3, r4 | ||
155 | beq 2f | ||
156 | add r5, r5, #PROC_INFO_SZ @ sizeof(proc_info_list) | ||
157 | cmp r5, r6 | ||
158 | blo 1b | ||
159 | mov r5, #0 @ unknown processor | ||
160 | 2: mov pc, lr | ||
161 | |||
162 | /* | ||
163 | * This provides a C-API version of the above function. | ||
164 | */ | ||
165 | ENTRY(lookup_processor_type) | ||
166 | stmfd sp!, {r4 - r7, r9, lr} | ||
167 | mov r9, r0 | ||
168 | bl __lookup_processor_type | ||
169 | mov r0, r5 | ||
170 | ldmfd sp!, {r4 - r7, r9, pc} | ||
171 | |||
172 | /* | ||
173 | * Look in include/asm-arm/procinfo.h and arch/arm/kernel/arch.[ch] for | ||
174 | * more information about the __proc_info and __arch_info structures. | ||
175 | */ | ||
176 | .long __proc_info_begin | ||
177 | .long __proc_info_end | ||
178 | 3: .long . | ||
179 | .long __arch_info_begin | ||
180 | .long __arch_info_end | ||
181 | |||
182 | /* | ||
183 | * Lookup machine architecture in the linker-build list of architectures. | ||
184 | * Note that we can't use the absolute addresses for the __arch_info | ||
185 | * lists since we aren't running with the MMU on (and therefore, we are | ||
186 | * not in the correct address space). We have to calculate the offset. | ||
187 | * | ||
188 | * r1 = machine architecture number | ||
189 | * Returns: | ||
190 | * r3, r4, r6 corrupted | ||
191 | * r5 = mach_info pointer in physical address space | ||
192 | */ | ||
193 | .type __lookup_machine_type, %function | ||
194 | __lookup_machine_type: | ||
195 | adr r3, 3b | ||
196 | ldmia r3, {r4, r5, r6} | ||
197 | sub r3, r3, r4 @ get offset between virt&phys | ||
198 | add r5, r5, r3 @ convert virt addresses to | ||
199 | add r6, r6, r3 @ physical address space | ||
200 | 1: ldr r3, [r5, #MACHINFO_TYPE] @ get machine type | ||
201 | teq r3, r1 @ matches loader number? | ||
202 | beq 2f @ found | ||
203 | add r5, r5, #SIZEOF_MACHINE_DESC @ next machine_desc | ||
204 | cmp r5, r6 | ||
205 | blo 1b | ||
206 | mov r5, #0 @ unknown machine | ||
207 | 2: mov pc, lr | ||
208 | |||
209 | /* | ||
210 | * This provides a C-API version of the above function. | ||
211 | */ | ||
212 | ENTRY(lookup_machine_type) | ||
213 | stmfd sp!, {r4 - r6, lr} | ||
214 | mov r1, r0 | ||
215 | bl __lookup_machine_type | ||
216 | mov r0, r5 | ||
217 | ldmfd sp!, {r4 - r6, pc} | ||
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S new file mode 100644 index 000000000000..b093ab8738b5 --- /dev/null +++ b/arch/arm/kernel/head-nommu.S | |||
@@ -0,0 +1,83 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/kernel/head-nommu.S | ||
3 | * | ||
4 | * Copyright (C) 1994-2002 Russell King | ||
5 | * Copyright (C) 2003-2006 Hyok S. Choi | ||
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 | * Common kernel startup code (non-paged MM) | ||
12 | * for 32-bit CPUs which has a process ID register(CP15). | ||
13 | * | ||
14 | */ | ||
15 | #include <linux/config.h> | ||
16 | #include <linux/linkage.h> | ||
17 | #include <linux/init.h> | ||
18 | |||
19 | #include <asm/assembler.h> | ||
20 | #include <asm/mach-types.h> | ||
21 | #include <asm/procinfo.h> | ||
22 | #include <asm/ptrace.h> | ||
23 | #include <asm/constants.h> | ||
24 | #include <asm/system.h> | ||
25 | |||
26 | #define PROCINFO_INITFUNC 12 | ||
27 | |||
28 | /* | ||
29 | * Kernel startup entry point. | ||
30 | * --------------------------- | ||
31 | * | ||
32 | * This is normally called from the decompressor code. The requirements | ||
33 | * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0, | ||
34 | * r1 = machine nr. | ||
35 | * | ||
36 | * See linux/arch/arm/tools/mach-types for the complete list of machine | ||
37 | * numbers for r1. | ||
38 | * | ||
39 | */ | ||
40 | __INIT | ||
41 | .type stext, %function | ||
42 | ENTRY(stext) | ||
43 | msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | MODE_SVC @ ensure svc mode | ||
44 | @ and irqs disabled | ||
45 | mrc p15, 0, r9, c0, c0 @ get processor id | ||
46 | bl __lookup_processor_type @ r5=procinfo r9=cpuid | ||
47 | movs r10, r5 @ invalid processor (r5=0)? | ||
48 | beq __error_p @ yes, error 'p' | ||
49 | bl __lookup_machine_type @ r5=machinfo | ||
50 | movs r8, r5 @ invalid machine (r5=0)? | ||
51 | beq __error_a @ yes, error 'a' | ||
52 | |||
53 | ldr r13, __switch_data @ address to jump to after | ||
54 | @ the initialization is done | ||
55 | adr lr, __after_proc_init @ return (PIC) address | ||
56 | add pc, r10, #PROCINFO_INITFUNC | ||
57 | |||
58 | /* | ||
59 | * Set the Control Register and Read the process ID. | ||
60 | */ | ||
61 | .type __after_proc_init, %function | ||
62 | __after_proc_init: | ||
63 | mrc p15, 0, r0, c1, c0, 0 @ read control reg | ||
64 | #ifdef CONFIG_ALIGNMENT_TRAP | ||
65 | orr r0, r0, #CR_A | ||
66 | #else | ||
67 | bic r0, r0, #CR_A | ||
68 | #endif | ||
69 | #ifdef CONFIG_CPU_DCACHE_DISABLE | ||
70 | bic r0, r0, #CR_C | ||
71 | #endif | ||
72 | #ifdef CONFIG_CPU_BPREDICT_DISABLE | ||
73 | bic r0, r0, #CR_Z | ||
74 | #endif | ||
75 | #ifdef CONFIG_CPU_ICACHE_DISABLE | ||
76 | bic r0, r0, #CR_I | ||
77 | #endif | ||
78 | mcr p15, 0, r0, c1, c0, 0 @ write control reg | ||
79 | |||
80 | mov pc, r13 @ clear the BSS and jump | ||
81 | @ to start_kernel | ||
82 | |||
83 | #include "head-common.S" | ||
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 53b6901f70a6..04b66a9328ef 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S | |||
@@ -102,49 +102,6 @@ ENTRY(stext) | |||
102 | adr lr, __enable_mmu @ return (PIC) address | 102 | adr lr, __enable_mmu @ return (PIC) address |
103 | add pc, r10, #PROCINFO_INITFUNC | 103 | add pc, r10, #PROCINFO_INITFUNC |
104 | 104 | ||
105 | .type __switch_data, %object | ||
106 | __switch_data: | ||
107 | .long __mmap_switched | ||
108 | .long __data_loc @ r4 | ||
109 | .long __data_start @ r5 | ||
110 | .long __bss_start @ r6 | ||
111 | .long _end @ r7 | ||
112 | .long processor_id @ r4 | ||
113 | .long __machine_arch_type @ r5 | ||
114 | .long cr_alignment @ r6 | ||
115 | .long init_thread_union + THREAD_START_SP @ sp | ||
116 | |||
117 | /* | ||
118 | * The following fragment of code is executed with the MMU on, and uses | ||
119 | * absolute addresses; this is not position independent. | ||
120 | * | ||
121 | * r0 = cp#15 control register | ||
122 | * r1 = machine ID | ||
123 | * r9 = processor ID | ||
124 | */ | ||
125 | .type __mmap_switched, %function | ||
126 | __mmap_switched: | ||
127 | adr r3, __switch_data + 4 | ||
128 | |||
129 | ldmia r3!, {r4, r5, r6, r7} | ||
130 | cmp r4, r5 @ Copy data segment if needed | ||
131 | 1: cmpne r5, r6 | ||
132 | ldrne fp, [r4], #4 | ||
133 | strne fp, [r5], #4 | ||
134 | bne 1b | ||
135 | |||
136 | mov fp, #0 @ Clear BSS (and zero fp) | ||
137 | 1: cmp r6, r7 | ||
138 | strcc fp, [r6],#4 | ||
139 | bcc 1b | ||
140 | |||
141 | ldmia r3, {r4, r5, r6, sp} | ||
142 | str r9, [r4] @ Save processor ID | ||
143 | str r1, [r5] @ Save machine type | ||
144 | bic r4, r0, #CR_A @ Clear 'A' bit | ||
145 | stmia r6, {r0, r4} @ Save control register values | ||
146 | b start_kernel | ||
147 | |||
148 | #if defined(CONFIG_SMP) | 105 | #if defined(CONFIG_SMP) |
149 | .type secondary_startup, #function | 106 | .type secondary_startup, #function |
150 | ENTRY(secondary_startup) | 107 | ENTRY(secondary_startup) |
@@ -367,166 +324,4 @@ __create_page_tables: | |||
367 | mov pc, lr | 324 | mov pc, lr |
368 | .ltorg | 325 | .ltorg |
369 | 326 | ||
370 | 327 | #include "head-common.S" | |
371 | |||
372 | /* | ||
373 | * Exception handling. Something went wrong and we can't proceed. We | ||
374 | * ought to tell the user, but since we don't have any guarantee that | ||
375 | * we're even running on the right architecture, we do virtually nothing. | ||
376 | * | ||
377 | * If CONFIG_DEBUG_LL is set we try to print out something about the error | ||
378 | * and hope for the best (useful if bootloader fails to pass a proper | ||
379 | * machine ID for example). | ||
380 | */ | ||
381 | |||
382 | .type __error_p, %function | ||
383 | __error_p: | ||
384 | #ifdef CONFIG_DEBUG_LL | ||
385 | adr r0, str_p1 | ||
386 | bl printascii | ||
387 | b __error | ||
388 | str_p1: .asciz "\nError: unrecognized/unsupported processor variant.\n" | ||
389 | .align | ||
390 | #endif | ||
391 | |||
392 | .type __error_a, %function | ||
393 | __error_a: | ||
394 | #ifdef CONFIG_DEBUG_LL | ||
395 | mov r4, r1 @ preserve machine ID | ||
396 | adr r0, str_a1 | ||
397 | bl printascii | ||
398 | mov r0, r4 | ||
399 | bl printhex8 | ||
400 | adr r0, str_a2 | ||
401 | bl printascii | ||
402 | adr r3, 3f | ||
403 | ldmia r3, {r4, r5, r6} @ get machine desc list | ||
404 | sub r4, r3, r4 @ get offset between virt&phys | ||
405 | add r5, r5, r4 @ convert virt addresses to | ||
406 | add r6, r6, r4 @ physical address space | ||
407 | 1: ldr r0, [r5, #MACHINFO_TYPE] @ get machine type | ||
408 | bl printhex8 | ||
409 | mov r0, #'\t' | ||
410 | bl printch | ||
411 | ldr r0, [r5, #MACHINFO_NAME] @ get machine name | ||
412 | add r0, r0, r4 | ||
413 | bl printascii | ||
414 | mov r0, #'\n' | ||
415 | bl printch | ||
416 | add r5, r5, #SIZEOF_MACHINE_DESC @ next machine_desc | ||
417 | cmp r5, r6 | ||
418 | blo 1b | ||
419 | adr r0, str_a3 | ||
420 | bl printascii | ||
421 | b __error | ||
422 | str_a1: .asciz "\nError: unrecognized/unsupported machine ID (r1 = 0x" | ||
423 | str_a2: .asciz ").\n\nAvailable machine support:\n\nID (hex)\tNAME\n" | ||
424 | str_a3: .asciz "\nPlease check your kernel config and/or bootloader.\n" | ||
425 | .align | ||
426 | #endif | ||
427 | |||
428 | .type __error, %function | ||
429 | __error: | ||
430 | #ifdef CONFIG_ARCH_RPC | ||
431 | /* | ||
432 | * Turn the screen red on a error - RiscPC only. | ||
433 | */ | ||
434 | mov r0, #0x02000000 | ||
435 | mov r3, #0x11 | ||
436 | orr r3, r3, r3, lsl #8 | ||
437 | orr r3, r3, r3, lsl #16 | ||
438 | str r3, [r0], #4 | ||
439 | str r3, [r0], #4 | ||
440 | str r3, [r0], #4 | ||
441 | str r3, [r0], #4 | ||
442 | #endif | ||
443 | 1: mov r0, r0 | ||
444 | b 1b | ||
445 | |||
446 | |||
447 | /* | ||
448 | * Read processor ID register (CP#15, CR0), and look up in the linker-built | ||
449 | * supported processor list. Note that we can't use the absolute addresses | ||
450 | * for the __proc_info lists since we aren't running with the MMU on | ||
451 | * (and therefore, we are not in the correct address space). We have to | ||
452 | * calculate the offset. | ||
453 | * | ||
454 | * r9 = cpuid | ||
455 | * Returns: | ||
456 | * r3, r4, r6 corrupted | ||
457 | * r5 = proc_info pointer in physical address space | ||
458 | * r9 = cpuid (preserved) | ||
459 | */ | ||
460 | .type __lookup_processor_type, %function | ||
461 | __lookup_processor_type: | ||
462 | adr r3, 3f | ||
463 | ldmda r3, {r5 - r7} | ||
464 | sub r3, r3, r7 @ get offset between virt&phys | ||
465 | add r5, r5, r3 @ convert virt addresses to | ||
466 | add r6, r6, r3 @ physical address space | ||
467 | 1: ldmia r5, {r3, r4} @ value, mask | ||
468 | and r4, r4, r9 @ mask wanted bits | ||
469 | teq r3, r4 | ||
470 | beq 2f | ||
471 | add r5, r5, #PROC_INFO_SZ @ sizeof(proc_info_list) | ||
472 | cmp r5, r6 | ||
473 | blo 1b | ||
474 | mov r5, #0 @ unknown processor | ||
475 | 2: mov pc, lr | ||
476 | |||
477 | /* | ||
478 | * This provides a C-API version of the above function. | ||
479 | */ | ||
480 | ENTRY(lookup_processor_type) | ||
481 | stmfd sp!, {r4 - r7, r9, lr} | ||
482 | mov r9, r0 | ||
483 | bl __lookup_processor_type | ||
484 | mov r0, r5 | ||
485 | ldmfd sp!, {r4 - r7, r9, pc} | ||
486 | |||
487 | /* | ||
488 | * Look in include/asm-arm/procinfo.h and arch/arm/kernel/arch.[ch] for | ||
489 | * more information about the __proc_info and __arch_info structures. | ||
490 | */ | ||
491 | .long __proc_info_begin | ||
492 | .long __proc_info_end | ||
493 | 3: .long . | ||
494 | .long __arch_info_begin | ||
495 | .long __arch_info_end | ||
496 | |||
497 | /* | ||
498 | * Lookup machine architecture in the linker-build list of architectures. | ||
499 | * Note that we can't use the absolute addresses for the __arch_info | ||
500 | * lists since we aren't running with the MMU on (and therefore, we are | ||
501 | * not in the correct address space). We have to calculate the offset. | ||
502 | * | ||
503 | * r1 = machine architecture number | ||
504 | * Returns: | ||
505 | * r3, r4, r6 corrupted | ||
506 | * r5 = mach_info pointer in physical address space | ||
507 | */ | ||
508 | .type __lookup_machine_type, %function | ||
509 | __lookup_machine_type: | ||
510 | adr r3, 3b | ||
511 | ldmia r3, {r4, r5, r6} | ||
512 | sub r3, r3, r4 @ get offset between virt&phys | ||
513 | add r5, r5, r3 @ convert virt addresses to | ||
514 | add r6, r6, r3 @ physical address space | ||
515 | 1: ldr r3, [r5, #MACHINFO_TYPE] @ get machine type | ||
516 | teq r3, r1 @ matches loader number? | ||
517 | beq 2f @ found | ||
518 | add r5, r5, #SIZEOF_MACHINE_DESC @ next machine_desc | ||
519 | cmp r5, r6 | ||
520 | blo 1b | ||
521 | mov r5, #0 @ unknown machine | ||
522 | 2: mov pc, lr | ||
523 | |||
524 | /* | ||
525 | * This provides a C-API version of the above function. | ||
526 | */ | ||
527 | ENTRY(lookup_machine_type) | ||
528 | stmfd sp!, {r4 - r6, lr} | ||
529 | mov r1, r0 | ||
530 | bl __lookup_machine_type | ||
531 | mov r0, r5 | ||
532 | ldmfd sp!, {r4 - r6, pc} | ||
diff --git a/arch/arm/kernel/signal.h b/arch/arm/kernel/signal.h index 9991049c522d..27beece15502 100644 --- a/arch/arm/kernel/signal.h +++ b/arch/arm/kernel/signal.h | |||
@@ -7,6 +7,6 @@ | |||
7 | * it under the terms of the GNU General Public License version 2 as | 7 | * it under the terms of the GNU General Public License version 2 as |
8 | * published by the Free Software Foundation. | 8 | * published by the Free Software Foundation. |
9 | */ | 9 | */ |
10 | #define KERN_SIGRETURN_CODE 0xffff0500 | 10 | #define KERN_SIGRETURN_CODE (CONFIG_VECTORS_BASE + 0x00000500) |
11 | 11 | ||
12 | extern const unsigned long sigreturn_codes[7]; | 12 | extern const unsigned long sigreturn_codes[7]; |
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index d566d5f4574d..35230a060108 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c | |||
@@ -688,6 +688,7 @@ EXPORT_SYMBOL(abort); | |||
688 | 688 | ||
689 | void __init trap_init(void) | 689 | void __init trap_init(void) |
690 | { | 690 | { |
691 | unsigned long vectors = CONFIG_VECTORS_BASE; | ||
691 | extern char __stubs_start[], __stubs_end[]; | 692 | extern char __stubs_start[], __stubs_end[]; |
692 | extern char __vectors_start[], __vectors_end[]; | 693 | extern char __vectors_start[], __vectors_end[]; |
693 | extern char __kuser_helper_start[], __kuser_helper_end[]; | 694 | extern char __kuser_helper_start[], __kuser_helper_end[]; |
@@ -698,9 +699,9 @@ void __init trap_init(void) | |||
698 | * into the vector page, mapped at 0xffff0000, and ensure these | 699 | * into the vector page, mapped at 0xffff0000, and ensure these |
699 | * are visible to the instruction stream. | 700 | * are visible to the instruction stream. |
700 | */ | 701 | */ |
701 | memcpy((void *)0xffff0000, __vectors_start, __vectors_end - __vectors_start); | 702 | memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start); |
702 | memcpy((void *)0xffff0200, __stubs_start, __stubs_end - __stubs_start); | 703 | memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start); |
703 | memcpy((void *)0xffff1000 - kuser_sz, __kuser_helper_start, kuser_sz); | 704 | memcpy((void *)vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz); |
704 | 705 | ||
705 | /* | 706 | /* |
706 | * Copy signal return handlers into the vector page, and | 707 | * Copy signal return handlers into the vector page, and |
@@ -709,6 +710,6 @@ void __init trap_init(void) | |||
709 | memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes, | 710 | memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes, |
710 | sizeof(sigreturn_codes)); | 711 | sizeof(sigreturn_codes)); |
711 | 712 | ||
712 | flush_icache_range(0xffff0000, 0xffff0000 + PAGE_SIZE); | 713 | flush_icache_range(vectors, vectors + PAGE_SIZE); |
713 | modify_domain(DOMAIN_USER, DOMAIN_CLIENT); | 714 | modify_domain(DOMAIN_USER, DOMAIN_CLIENT); |
714 | } | 715 | } |