diff options
author | Adrian Bunk <bunk@stusta.de> | 2006-04-02 04:37:38 -0400 |
---|---|---|
committer | Adrian Bunk <bunk@stusta.de> | 2006-04-02 04:37:38 -0400 |
commit | 733f896927c955a114bf265993c1535c4b057a0f (patch) | |
tree | 724f37e10d3bd10e8162228cee4f908b52b7108d /arch | |
parent | 409ca8c8ae3173026e7dfbdcdab669766e43fb60 (diff) | |
parent | 683aa4012f53b2ada0f430487e05d37b0d94e90a (diff) |
Merge with git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
Diffstat (limited to 'arch')
-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/entry-armv.S | 2 | ||||
-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 | ||||
-rw-r--r-- | arch/arm/mm/proc-xsc3.S | 1 | ||||
-rw-r--r-- | arch/ia64/kernel/palinfo.c | 8 | ||||
-rw-r--r-- | arch/ia64/kernel/time.c | 2 | ||||
-rw-r--r-- | arch/ia64/kernel/topology.c | 367 |
14 files changed, 846 insertions, 219 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index e91db542eb01..dc5a9332c915 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -77,6 +77,14 @@ config FIQ | |||
77 | config ARCH_MTD_XIP | 77 | config ARCH_MTD_XIP |
78 | bool | 78 | bool |
79 | 79 | ||
80 | config VECTORS_BASE | ||
81 | hex | ||
82 | default 0xffff0000 if MMU | ||
83 | default DRAM_BASE if REMAP_VECTORS_TO_RAM | ||
84 | default 0x00000000 | ||
85 | help | ||
86 | The base address of exception vectors. | ||
87 | |||
80 | source "init/Kconfig" | 88 | source "init/Kconfig" |
81 | 89 | ||
82 | menu "System Type" | 90 | 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/entry-armv.S b/arch/arm/kernel/entry-armv.S index 355914ffb192..ab8e600c18c8 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S | |||
@@ -666,7 +666,7 @@ __kuser_helper_start: | |||
666 | * | 666 | * |
667 | * #define __kernel_dmb() \ | 667 | * #define __kernel_dmb() \ |
668 | * asm volatile ( "mov r0, #0xffff0fff; mov lr, pc; sub pc, r0, #95" \ | 668 | * asm volatile ( "mov r0, #0xffff0fff; mov lr, pc; sub pc, r0, #95" \ |
669 | * : : : "lr","cc" ) | 669 | * : : : "r0", "lr","cc" ) |
670 | */ | 670 | */ |
671 | 671 | ||
672 | __kuser_memory_barrier: @ 0xffff0fa0 | 672 | __kuser_memory_barrier: @ 0xffff0fa0 |
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 | } |
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S index f90513e9af0c..b9dfce57c272 100644 --- a/arch/arm/mm/proc-xsc3.S +++ b/arch/arm/mm/proc-xsc3.S | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <asm/procinfo.h> | 30 | #include <asm/procinfo.h> |
31 | #include <asm/hardware.h> | 31 | #include <asm/hardware.h> |
32 | #include <asm/pgtable.h> | 32 | #include <asm/pgtable.h> |
33 | #include <asm/pgtable-hwdef.h> | ||
33 | #include <asm/page.h> | 34 | #include <asm/page.h> |
34 | #include <asm/ptrace.h> | 35 | #include <asm/ptrace.h> |
35 | #include "proc-macros.S" | 36 | #include "proc-macros.S" |
diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c index 89faa603c6be..6386f63c413e 100644 --- a/arch/ia64/kernel/palinfo.c +++ b/arch/ia64/kernel/palinfo.c | |||
@@ -240,7 +240,7 @@ cache_info(char *page) | |||
240 | } | 240 | } |
241 | p += sprintf(p, | 241 | p += sprintf(p, |
242 | "%s Cache level %lu:\n" | 242 | "%s Cache level %lu:\n" |
243 | "\tSize : %lu bytes\n" | 243 | "\tSize : %u bytes\n" |
244 | "\tAttributes : ", | 244 | "\tAttributes : ", |
245 | cache_types[j+cci.pcci_unified], i+1, | 245 | cache_types[j+cci.pcci_unified], i+1, |
246 | cci.pcci_cache_size); | 246 | cci.pcci_cache_size); |
@@ -648,9 +648,9 @@ frequency_info(char *page) | |||
648 | if (ia64_pal_freq_ratios(&proc, &bus, &itc) != 0) return 0; | 648 | if (ia64_pal_freq_ratios(&proc, &bus, &itc) != 0) return 0; |
649 | 649 | ||
650 | p += sprintf(p, | 650 | p += sprintf(p, |
651 | "Processor/Clock ratio : %ld/%ld\n" | 651 | "Processor/Clock ratio : %d/%d\n" |
652 | "Bus/Clock ratio : %ld/%ld\n" | 652 | "Bus/Clock ratio : %d/%d\n" |
653 | "ITC/Clock ratio : %ld/%ld\n", | 653 | "ITC/Clock ratio : %d/%d\n", |
654 | proc.num, proc.den, bus.num, bus.den, itc.num, itc.den); | 654 | proc.num, proc.den, bus.num, bus.den, itc.num, itc.den); |
655 | 655 | ||
656 | return p - page; | 656 | return p - page; |
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c index ac167436e936..49958904045b 100644 --- a/arch/ia64/kernel/time.c +++ b/arch/ia64/kernel/time.c | |||
@@ -188,7 +188,7 @@ ia64_init_itm (void) | |||
188 | itc_freq = (platform_base_freq*itc_ratio.num)/itc_ratio.den; | 188 | itc_freq = (platform_base_freq*itc_ratio.num)/itc_ratio.den; |
189 | 189 | ||
190 | local_cpu_data->itm_delta = (itc_freq + HZ/2) / HZ; | 190 | local_cpu_data->itm_delta = (itc_freq + HZ/2) / HZ; |
191 | printk(KERN_DEBUG "CPU %d: base freq=%lu.%03luMHz, ITC ratio=%lu/%lu, " | 191 | printk(KERN_DEBUG "CPU %d: base freq=%lu.%03luMHz, ITC ratio=%u/%u, " |
192 | "ITC freq=%lu.%03luMHz", smp_processor_id(), | 192 | "ITC freq=%lu.%03luMHz", smp_processor_id(), |
193 | platform_base_freq / 1000000, (platform_base_freq / 1000) % 1000, | 193 | platform_base_freq / 1000000, (platform_base_freq / 1000) % 1000, |
194 | itc_ratio.num, itc_ratio.den, itc_freq / 1000000, (itc_freq / 1000) % 1000); | 194 | itc_ratio.num, itc_ratio.den, itc_freq / 1000000, (itc_freq / 1000) % 1000); |
diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c index 3b6fd798c4d6..b47476d655f1 100644 --- a/arch/ia64/kernel/topology.c +++ b/arch/ia64/kernel/topology.c | |||
@@ -9,6 +9,8 @@ | |||
9 | * 2002/08/07 Erich Focht <efocht@ess.nec.de> | 9 | * 2002/08/07 Erich Focht <efocht@ess.nec.de> |
10 | * Populate cpu entries in sysfs for non-numa systems as well | 10 | * Populate cpu entries in sysfs for non-numa systems as well |
11 | * Intel Corporation - Ashok Raj | 11 | * Intel Corporation - Ashok Raj |
12 | * 02/27/2006 Zhang, Yanmin | ||
13 | * Populate cpu cache entries in sysfs for cpu cache info | ||
12 | */ | 14 | */ |
13 | 15 | ||
14 | #include <linux/config.h> | 16 | #include <linux/config.h> |
@@ -19,6 +21,7 @@ | |||
19 | #include <linux/init.h> | 21 | #include <linux/init.h> |
20 | #include <linux/bootmem.h> | 22 | #include <linux/bootmem.h> |
21 | #include <linux/nodemask.h> | 23 | #include <linux/nodemask.h> |
24 | #include <linux/notifier.h> | ||
22 | #include <asm/mmzone.h> | 25 | #include <asm/mmzone.h> |
23 | #include <asm/numa.h> | 26 | #include <asm/numa.h> |
24 | #include <asm/cpu.h> | 27 | #include <asm/cpu.h> |
@@ -101,3 +104,367 @@ out: | |||
101 | } | 104 | } |
102 | 105 | ||
103 | subsys_initcall(topology_init); | 106 | subsys_initcall(topology_init); |
107 | |||
108 | |||
109 | /* | ||
110 | * Export cpu cache information through sysfs | ||
111 | */ | ||
112 | |||
113 | /* | ||
114 | * A bunch of string array to get pretty printing | ||
115 | */ | ||
116 | static const char *cache_types[] = { | ||
117 | "", /* not used */ | ||
118 | "Instruction", | ||
119 | "Data", | ||
120 | "Unified" /* unified */ | ||
121 | }; | ||
122 | |||
123 | static const char *cache_mattrib[]={ | ||
124 | "WriteThrough", | ||
125 | "WriteBack", | ||
126 | "", /* reserved */ | ||
127 | "" /* reserved */ | ||
128 | }; | ||
129 | |||
130 | struct cache_info { | ||
131 | pal_cache_config_info_t cci; | ||
132 | cpumask_t shared_cpu_map; | ||
133 | int level; | ||
134 | int type; | ||
135 | struct kobject kobj; | ||
136 | }; | ||
137 | |||
138 | struct cpu_cache_info { | ||
139 | struct cache_info *cache_leaves; | ||
140 | int num_cache_leaves; | ||
141 | struct kobject kobj; | ||
142 | }; | ||
143 | |||
144 | static struct cpu_cache_info all_cpu_cache_info[NR_CPUS]; | ||
145 | #define LEAF_KOBJECT_PTR(x,y) (&all_cpu_cache_info[x].cache_leaves[y]) | ||
146 | |||
147 | #ifdef CONFIG_SMP | ||
148 | static void cache_shared_cpu_map_setup( unsigned int cpu, | ||
149 | struct cache_info * this_leaf) | ||
150 | { | ||
151 | pal_cache_shared_info_t csi; | ||
152 | int num_shared, i = 0; | ||
153 | unsigned int j; | ||
154 | |||
155 | if (cpu_data(cpu)->threads_per_core <= 1 && | ||
156 | cpu_data(cpu)->cores_per_socket <= 1) { | ||
157 | cpu_set(cpu, this_leaf->shared_cpu_map); | ||
158 | return; | ||
159 | } | ||
160 | |||
161 | if (ia64_pal_cache_shared_info(this_leaf->level, | ||
162 | this_leaf->type, | ||
163 | 0, | ||
164 | &csi) != PAL_STATUS_SUCCESS) | ||
165 | return; | ||
166 | |||
167 | num_shared = (int) csi.num_shared; | ||
168 | do { | ||
169 | for_each_cpu(j) | ||
170 | if (cpu_data(cpu)->socket_id == cpu_data(j)->socket_id | ||
171 | && cpu_data(j)->core_id == csi.log1_cid | ||
172 | && cpu_data(j)->thread_id == csi.log1_tid) | ||
173 | cpu_set(j, this_leaf->shared_cpu_map); | ||
174 | |||
175 | i++; | ||
176 | } while (i < num_shared && | ||
177 | ia64_pal_cache_shared_info(this_leaf->level, | ||
178 | this_leaf->type, | ||
179 | i, | ||
180 | &csi) == PAL_STATUS_SUCCESS); | ||
181 | } | ||
182 | #else | ||
183 | static void cache_shared_cpu_map_setup(unsigned int cpu, | ||
184 | struct cache_info * this_leaf) | ||
185 | { | ||
186 | cpu_set(cpu, this_leaf->shared_cpu_map); | ||
187 | return; | ||
188 | } | ||
189 | #endif | ||
190 | |||
191 | static ssize_t show_coherency_line_size(struct cache_info *this_leaf, | ||
192 | char *buf) | ||
193 | { | ||
194 | return sprintf(buf, "%u\n", 1 << this_leaf->cci.pcci_line_size); | ||
195 | } | ||
196 | |||
197 | static ssize_t show_ways_of_associativity(struct cache_info *this_leaf, | ||
198 | char *buf) | ||
199 | { | ||
200 | return sprintf(buf, "%u\n", this_leaf->cci.pcci_assoc); | ||
201 | } | ||
202 | |||
203 | static ssize_t show_attributes(struct cache_info *this_leaf, char *buf) | ||
204 | { | ||
205 | return sprintf(buf, | ||
206 | "%s\n", | ||
207 | cache_mattrib[this_leaf->cci.pcci_cache_attr]); | ||
208 | } | ||
209 | |||
210 | static ssize_t show_size(struct cache_info *this_leaf, char *buf) | ||
211 | { | ||
212 | return sprintf(buf, "%uK\n", this_leaf->cci.pcci_cache_size / 1024); | ||
213 | } | ||
214 | |||
215 | static ssize_t show_number_of_sets(struct cache_info *this_leaf, char *buf) | ||
216 | { | ||
217 | unsigned number_of_sets = this_leaf->cci.pcci_cache_size; | ||
218 | number_of_sets /= this_leaf->cci.pcci_assoc; | ||
219 | number_of_sets /= 1 << this_leaf->cci.pcci_line_size; | ||
220 | |||
221 | return sprintf(buf, "%u\n", number_of_sets); | ||
222 | } | ||
223 | |||
224 | static ssize_t show_shared_cpu_map(struct cache_info *this_leaf, char *buf) | ||
225 | { | ||
226 | ssize_t len; | ||
227 | cpumask_t shared_cpu_map; | ||
228 | |||
229 | cpus_and(shared_cpu_map, this_leaf->shared_cpu_map, cpu_online_map); | ||
230 | len = cpumask_scnprintf(buf, NR_CPUS+1, shared_cpu_map); | ||
231 | len += sprintf(buf+len, "\n"); | ||
232 | return len; | ||
233 | } | ||
234 | |||
235 | static ssize_t show_type(struct cache_info *this_leaf, char *buf) | ||
236 | { | ||
237 | int type = this_leaf->type + this_leaf->cci.pcci_unified; | ||
238 | return sprintf(buf, "%s\n", cache_types[type]); | ||
239 | } | ||
240 | |||
241 | static ssize_t show_level(struct cache_info *this_leaf, char *buf) | ||
242 | { | ||
243 | return sprintf(buf, "%u\n", this_leaf->level); | ||
244 | } | ||
245 | |||
246 | struct cache_attr { | ||
247 | struct attribute attr; | ||
248 | ssize_t (*show)(struct cache_info *, char *); | ||
249 | ssize_t (*store)(struct cache_info *, const char *, size_t count); | ||
250 | }; | ||
251 | |||
252 | #ifdef define_one_ro | ||
253 | #undef define_one_ro | ||
254 | #endif | ||
255 | #define define_one_ro(_name) \ | ||
256 | static struct cache_attr _name = \ | ||
257 | __ATTR(_name, 0444, show_##_name, NULL) | ||
258 | |||
259 | define_one_ro(level); | ||
260 | define_one_ro(type); | ||
261 | define_one_ro(coherency_line_size); | ||
262 | define_one_ro(ways_of_associativity); | ||
263 | define_one_ro(size); | ||
264 | define_one_ro(number_of_sets); | ||
265 | define_one_ro(shared_cpu_map); | ||
266 | define_one_ro(attributes); | ||
267 | |||
268 | static struct attribute * cache_default_attrs[] = { | ||
269 | &type.attr, | ||
270 | &level.attr, | ||
271 | &coherency_line_size.attr, | ||
272 | &ways_of_associativity.attr, | ||
273 | &attributes.attr, | ||
274 | &size.attr, | ||
275 | &number_of_sets.attr, | ||
276 | &shared_cpu_map.attr, | ||
277 | NULL | ||
278 | }; | ||
279 | |||
280 | #define to_object(k) container_of(k, struct cache_info, kobj) | ||
281 | #define to_attr(a) container_of(a, struct cache_attr, attr) | ||
282 | |||
283 | static ssize_t cache_show(struct kobject * kobj, struct attribute * attr, char * buf) | ||
284 | { | ||
285 | struct cache_attr *fattr = to_attr(attr); | ||
286 | struct cache_info *this_leaf = to_object(kobj); | ||
287 | ssize_t ret; | ||
288 | |||
289 | ret = fattr->show ? fattr->show(this_leaf, buf) : 0; | ||
290 | return ret; | ||
291 | } | ||
292 | |||
293 | static struct sysfs_ops cache_sysfs_ops = { | ||
294 | .show = cache_show | ||
295 | }; | ||
296 | |||
297 | static struct kobj_type cache_ktype = { | ||
298 | .sysfs_ops = &cache_sysfs_ops, | ||
299 | .default_attrs = cache_default_attrs, | ||
300 | }; | ||
301 | |||
302 | static struct kobj_type cache_ktype_percpu_entry = { | ||
303 | .sysfs_ops = &cache_sysfs_ops, | ||
304 | }; | ||
305 | |||
306 | static void __cpuinit cpu_cache_sysfs_exit(unsigned int cpu) | ||
307 | { | ||
308 | if (all_cpu_cache_info[cpu].cache_leaves) { | ||
309 | kfree(all_cpu_cache_info[cpu].cache_leaves); | ||
310 | all_cpu_cache_info[cpu].cache_leaves = NULL; | ||
311 | } | ||
312 | all_cpu_cache_info[cpu].num_cache_leaves = 0; | ||
313 | memset(&all_cpu_cache_info[cpu].kobj, 0, sizeof(struct kobject)); | ||
314 | |||
315 | return; | ||
316 | } | ||
317 | |||
318 | static int __cpuinit cpu_cache_sysfs_init(unsigned int cpu) | ||
319 | { | ||
320 | u64 i, levels, unique_caches; | ||
321 | pal_cache_config_info_t cci; | ||
322 | int j; | ||
323 | s64 status; | ||
324 | struct cache_info *this_cache; | ||
325 | int num_cache_leaves = 0; | ||
326 | |||
327 | if ((status = ia64_pal_cache_summary(&levels, &unique_caches)) != 0) { | ||
328 | printk(KERN_ERR "ia64_pal_cache_summary=%ld\n", status); | ||
329 | return -1; | ||
330 | } | ||
331 | |||
332 | this_cache=kzalloc(sizeof(struct cache_info)*unique_caches, | ||
333 | GFP_KERNEL); | ||
334 | if (this_cache == NULL) | ||
335 | return -ENOMEM; | ||
336 | |||
337 | for (i=0; i < levels; i++) { | ||
338 | for (j=2; j >0 ; j--) { | ||
339 | if ((status=ia64_pal_cache_config_info(i,j, &cci)) != | ||
340 | PAL_STATUS_SUCCESS) | ||
341 | continue; | ||
342 | |||
343 | this_cache[num_cache_leaves].cci = cci; | ||
344 | this_cache[num_cache_leaves].level = i + 1; | ||
345 | this_cache[num_cache_leaves].type = j; | ||
346 | |||
347 | cache_shared_cpu_map_setup(cpu, | ||
348 | &this_cache[num_cache_leaves]); | ||
349 | num_cache_leaves ++; | ||
350 | } | ||
351 | } | ||
352 | |||
353 | all_cpu_cache_info[cpu].cache_leaves = this_cache; | ||
354 | all_cpu_cache_info[cpu].num_cache_leaves = num_cache_leaves; | ||
355 | |||
356 | memset(&all_cpu_cache_info[cpu].kobj, 0, sizeof(struct kobject)); | ||
357 | |||
358 | return 0; | ||
359 | } | ||
360 | |||
361 | /* Add cache interface for CPU device */ | ||
362 | static int __cpuinit cache_add_dev(struct sys_device * sys_dev) | ||
363 | { | ||
364 | unsigned int cpu = sys_dev->id; | ||
365 | unsigned long i, j; | ||
366 | struct cache_info *this_object; | ||
367 | int retval = 0; | ||
368 | cpumask_t oldmask; | ||
369 | |||
370 | if (all_cpu_cache_info[cpu].kobj.parent) | ||
371 | return 0; | ||
372 | |||
373 | oldmask = current->cpus_allowed; | ||
374 | retval = set_cpus_allowed(current, cpumask_of_cpu(cpu)); | ||
375 | if (unlikely(retval)) | ||
376 | return retval; | ||
377 | |||
378 | retval = cpu_cache_sysfs_init(cpu); | ||
379 | set_cpus_allowed(current, oldmask); | ||
380 | if (unlikely(retval < 0)) | ||
381 | return retval; | ||
382 | |||
383 | all_cpu_cache_info[cpu].kobj.parent = &sys_dev->kobj; | ||
384 | kobject_set_name(&all_cpu_cache_info[cpu].kobj, "%s", "cache"); | ||
385 | all_cpu_cache_info[cpu].kobj.ktype = &cache_ktype_percpu_entry; | ||
386 | retval = kobject_register(&all_cpu_cache_info[cpu].kobj); | ||
387 | |||
388 | for (i = 0; i < all_cpu_cache_info[cpu].num_cache_leaves; i++) { | ||
389 | this_object = LEAF_KOBJECT_PTR(cpu,i); | ||
390 | this_object->kobj.parent = &all_cpu_cache_info[cpu].kobj; | ||
391 | kobject_set_name(&(this_object->kobj), "index%1lu", i); | ||
392 | this_object->kobj.ktype = &cache_ktype; | ||
393 | retval = kobject_register(&(this_object->kobj)); | ||
394 | if (unlikely(retval)) { | ||
395 | for (j = 0; j < i; j++) { | ||
396 | kobject_unregister( | ||
397 | &(LEAF_KOBJECT_PTR(cpu,j)->kobj)); | ||
398 | } | ||
399 | kobject_unregister(&all_cpu_cache_info[cpu].kobj); | ||
400 | cpu_cache_sysfs_exit(cpu); | ||
401 | break; | ||
402 | } | ||
403 | } | ||
404 | return retval; | ||
405 | } | ||
406 | |||
407 | /* Remove cache interface for CPU device */ | ||
408 | static int __cpuinit cache_remove_dev(struct sys_device * sys_dev) | ||
409 | { | ||
410 | unsigned int cpu = sys_dev->id; | ||
411 | unsigned long i; | ||
412 | |||
413 | for (i = 0; i < all_cpu_cache_info[cpu].num_cache_leaves; i++) | ||
414 | kobject_unregister(&(LEAF_KOBJECT_PTR(cpu,i)->kobj)); | ||
415 | |||
416 | if (all_cpu_cache_info[cpu].kobj.parent) { | ||
417 | kobject_unregister(&all_cpu_cache_info[cpu].kobj); | ||
418 | memset(&all_cpu_cache_info[cpu].kobj, | ||
419 | 0, | ||
420 | sizeof(struct kobject)); | ||
421 | } | ||
422 | |||
423 | cpu_cache_sysfs_exit(cpu); | ||
424 | |||
425 | return 0; | ||
426 | } | ||
427 | |||
428 | /* | ||
429 | * When a cpu is hot-plugged, do a check and initiate | ||
430 | * cache kobject if necessary | ||
431 | */ | ||
432 | static int __cpuinit cache_cpu_callback(struct notifier_block *nfb, | ||
433 | unsigned long action, void *hcpu) | ||
434 | { | ||
435 | unsigned int cpu = (unsigned long)hcpu; | ||
436 | struct sys_device *sys_dev; | ||
437 | |||
438 | sys_dev = get_cpu_sysdev(cpu); | ||
439 | switch (action) { | ||
440 | case CPU_ONLINE: | ||
441 | cache_add_dev(sys_dev); | ||
442 | break; | ||
443 | case CPU_DEAD: | ||
444 | cache_remove_dev(sys_dev); | ||
445 | break; | ||
446 | } | ||
447 | return NOTIFY_OK; | ||
448 | } | ||
449 | |||
450 | static struct notifier_block cache_cpu_notifier = | ||
451 | { | ||
452 | .notifier_call = cache_cpu_callback | ||
453 | }; | ||
454 | |||
455 | static int __cpuinit cache_sysfs_init(void) | ||
456 | { | ||
457 | int i; | ||
458 | |||
459 | for_each_online_cpu(i) { | ||
460 | cache_cpu_callback(&cache_cpu_notifier, CPU_ONLINE, | ||
461 | (void *)(long)i); | ||
462 | } | ||
463 | |||
464 | register_cpu_notifier(&cache_cpu_notifier); | ||
465 | |||
466 | return 0; | ||
467 | } | ||
468 | |||
469 | device_initcall(cache_sysfs_init); | ||
470 | |||