diff options
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/Makefile | 5 | ||||
-rw-r--r-- | arch/arm/kernel/atags.h | 14 | ||||
-rw-r--r-- | arch/arm/kernel/atags_compat.c (renamed from arch/arm/kernel/compat.c) | 4 | ||||
-rw-r--r-- | arch/arm/kernel/atags_parse.c | 238 | ||||
-rw-r--r-- | arch/arm/kernel/atags_proc.c (renamed from arch/arm/kernel/atags.c) | 0 | ||||
-rw-r--r-- | arch/arm/kernel/calls.S | 1 | ||||
-rw-r--r-- | arch/arm/kernel/compat.h | 11 | ||||
-rw-r--r-- | arch/arm/kernel/entry-common.S | 9 | ||||
-rw-r--r-- | arch/arm/kernel/hw_breakpoint.c | 62 | ||||
-rw-r--r-- | arch/arm/kernel/machine_kexec.c | 29 | ||||
-rw-r--r-- | arch/arm/kernel/ptrace.c | 19 | ||||
-rw-r--r-- | arch/arm/kernel/sched_clock.c | 32 | ||||
-rw-r--r-- | arch/arm/kernel/setup.c | 236 | ||||
-rw-r--r-- | arch/arm/kernel/smp.c | 13 | ||||
-rw-r--r-- | arch/arm/kernel/smp_twd.c | 48 | ||||
-rw-r--r-- | arch/arm/kernel/topology.c | 2 | ||||
-rw-r--r-- | arch/arm/kernel/traps.c | 11 |
17 files changed, 448 insertions, 286 deletions
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 7ad2d5cf7008..79e346a5d78b 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile | |||
@@ -19,7 +19,9 @@ obj-y := elf.o entry-armv.o entry-common.o irq.o opcodes.o \ | |||
19 | process.o ptrace.o return_address.o sched_clock.o \ | 19 | process.o ptrace.o return_address.o sched_clock.o \ |
20 | setup.o signal.o stacktrace.o sys_arm.o time.o traps.o | 20 | setup.o signal.o stacktrace.o sys_arm.o time.o traps.o |
21 | 21 | ||
22 | obj-$(CONFIG_DEPRECATED_PARAM_STRUCT) += compat.o | 22 | obj-$(CONFIG_ATAGS) += atags_parse.o |
23 | obj-$(CONFIG_ATAGS_PROC) += atags_proc.o | ||
24 | obj-$(CONFIG_DEPRECATED_PARAM_STRUCT) += atags_compat.o | ||
23 | 25 | ||
24 | obj-$(CONFIG_LEDS) += leds.o | 26 | obj-$(CONFIG_LEDS) += leds.o |
25 | obj-$(CONFIG_OC_ETM) += etm.o | 27 | obj-$(CONFIG_OC_ETM) += etm.o |
@@ -52,7 +54,6 @@ test-kprobes-objs += kprobes-test-thumb.o | |||
52 | else | 54 | else |
53 | test-kprobes-objs += kprobes-test-arm.o | 55 | test-kprobes-objs += kprobes-test-arm.o |
54 | endif | 56 | endif |
55 | obj-$(CONFIG_ATAGS_PROC) += atags.o | ||
56 | obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o | 57 | obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o |
57 | obj-$(CONFIG_ARM_THUMBEE) += thumbee.o | 58 | obj-$(CONFIG_ARM_THUMBEE) += thumbee.o |
58 | obj-$(CONFIG_KGDB) += kgdb.o | 59 | obj-$(CONFIG_KGDB) += kgdb.o |
diff --git a/arch/arm/kernel/atags.h b/arch/arm/kernel/atags.h index e5f028d214a1..9edc9692332d 100644 --- a/arch/arm/kernel/atags.h +++ b/arch/arm/kernel/atags.h | |||
@@ -3,3 +3,17 @@ extern void save_atags(struct tag *tags); | |||
3 | #else | 3 | #else |
4 | static inline void save_atags(struct tag *tags) { } | 4 | static inline void save_atags(struct tag *tags) { } |
5 | #endif | 5 | #endif |
6 | |||
7 | void convert_to_tag_list(struct tag *tags); | ||
8 | |||
9 | #ifdef CONFIG_ATAGS | ||
10 | struct machine_desc *setup_machine_tags(phys_addr_t __atags_pointer, unsigned int machine_nr); | ||
11 | #else | ||
12 | static inline struct machine_desc * | ||
13 | setup_machine_tags(phys_addr_t __atags_pointer, unsigned int machine_nr) | ||
14 | { | ||
15 | early_print("no ATAGS support: can't continue\n"); | ||
16 | while (true); | ||
17 | unreachable(); | ||
18 | } | ||
19 | #endif | ||
diff --git a/arch/arm/kernel/compat.c b/arch/arm/kernel/atags_compat.c index 925652318b8b..5236ad38f417 100644 --- a/arch/arm/kernel/compat.c +++ b/arch/arm/kernel/atags_compat.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/kernel/compat.c | 2 | * linux/arch/arm/kernel/atags_compat.c |
3 | * | 3 | * |
4 | * Copyright (C) 2001 Russell King | 4 | * Copyright (C) 2001 Russell King |
5 | * | 5 | * |
@@ -26,7 +26,7 @@ | |||
26 | 26 | ||
27 | #include <asm/mach/arch.h> | 27 | #include <asm/mach/arch.h> |
28 | 28 | ||
29 | #include "compat.h" | 29 | #include "atags.h" |
30 | 30 | ||
31 | /* | 31 | /* |
32 | * Usage: | 32 | * Usage: |
diff --git a/arch/arm/kernel/atags_parse.c b/arch/arm/kernel/atags_parse.c new file mode 100644 index 000000000000..14512e6931d8 --- /dev/null +++ b/arch/arm/kernel/atags_parse.c | |||
@@ -0,0 +1,238 @@ | |||
1 | /* | ||
2 | * Tag parsing. | ||
3 | * | ||
4 | * Copyright (C) 1995-2001 Russell King | ||
5 | * | ||
6 | * 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 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | /* | ||
12 | * This is the traditional way of passing data to the kernel at boot time. Rather | ||
13 | * than passing a fixed inflexible structure to the kernel, we pass a list | ||
14 | * of variable-sized tags to the kernel. The first tag must be a ATAG_CORE | ||
15 | * tag for the list to be recognised (to distinguish the tagged list from | ||
16 | * a param_struct). The list is terminated with a zero-length tag (this tag | ||
17 | * is not parsed in any way). | ||
18 | */ | ||
19 | |||
20 | #include <linux/init.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/fs.h> | ||
23 | #include <linux/root_dev.h> | ||
24 | #include <linux/screen_info.h> | ||
25 | |||
26 | #include <asm/setup.h> | ||
27 | #include <asm/system_info.h> | ||
28 | #include <asm/page.h> | ||
29 | #include <asm/mach/arch.h> | ||
30 | |||
31 | #include "atags.h" | ||
32 | |||
33 | static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; | ||
34 | |||
35 | #ifndef MEM_SIZE | ||
36 | #define MEM_SIZE (16*1024*1024) | ||
37 | #endif | ||
38 | |||
39 | static struct { | ||
40 | struct tag_header hdr1; | ||
41 | struct tag_core core; | ||
42 | struct tag_header hdr2; | ||
43 | struct tag_mem32 mem; | ||
44 | struct tag_header hdr3; | ||
45 | } default_tags __initdata = { | ||
46 | { tag_size(tag_core), ATAG_CORE }, | ||
47 | { 1, PAGE_SIZE, 0xff }, | ||
48 | { tag_size(tag_mem32), ATAG_MEM }, | ||
49 | { MEM_SIZE }, | ||
50 | { 0, ATAG_NONE } | ||
51 | }; | ||
52 | |||
53 | static int __init parse_tag_core(const struct tag *tag) | ||
54 | { | ||
55 | if (tag->hdr.size > 2) { | ||
56 | if ((tag->u.core.flags & 1) == 0) | ||
57 | root_mountflags &= ~MS_RDONLY; | ||
58 | ROOT_DEV = old_decode_dev(tag->u.core.rootdev); | ||
59 | } | ||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | __tagtable(ATAG_CORE, parse_tag_core); | ||
64 | |||
65 | static int __init parse_tag_mem32(const struct tag *tag) | ||
66 | { | ||
67 | return arm_add_memory(tag->u.mem.start, tag->u.mem.size); | ||
68 | } | ||
69 | |||
70 | __tagtable(ATAG_MEM, parse_tag_mem32); | ||
71 | |||
72 | #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE) | ||
73 | static int __init parse_tag_videotext(const struct tag *tag) | ||
74 | { | ||
75 | screen_info.orig_x = tag->u.videotext.x; | ||
76 | screen_info.orig_y = tag->u.videotext.y; | ||
77 | screen_info.orig_video_page = tag->u.videotext.video_page; | ||
78 | screen_info.orig_video_mode = tag->u.videotext.video_mode; | ||
79 | screen_info.orig_video_cols = tag->u.videotext.video_cols; | ||
80 | screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx; | ||
81 | screen_info.orig_video_lines = tag->u.videotext.video_lines; | ||
82 | screen_info.orig_video_isVGA = tag->u.videotext.video_isvga; | ||
83 | screen_info.orig_video_points = tag->u.videotext.video_points; | ||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | __tagtable(ATAG_VIDEOTEXT, parse_tag_videotext); | ||
88 | #endif | ||
89 | |||
90 | #ifdef CONFIG_BLK_DEV_RAM | ||
91 | static int __init parse_tag_ramdisk(const struct tag *tag) | ||
92 | { | ||
93 | extern int rd_size, rd_image_start, rd_prompt, rd_doload; | ||
94 | |||
95 | rd_image_start = tag->u.ramdisk.start; | ||
96 | rd_doload = (tag->u.ramdisk.flags & 1) == 0; | ||
97 | rd_prompt = (tag->u.ramdisk.flags & 2) == 0; | ||
98 | |||
99 | if (tag->u.ramdisk.size) | ||
100 | rd_size = tag->u.ramdisk.size; | ||
101 | |||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | __tagtable(ATAG_RAMDISK, parse_tag_ramdisk); | ||
106 | #endif | ||
107 | |||
108 | static int __init parse_tag_serialnr(const struct tag *tag) | ||
109 | { | ||
110 | system_serial_low = tag->u.serialnr.low; | ||
111 | system_serial_high = tag->u.serialnr.high; | ||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | __tagtable(ATAG_SERIAL, parse_tag_serialnr); | ||
116 | |||
117 | static int __init parse_tag_revision(const struct tag *tag) | ||
118 | { | ||
119 | system_rev = tag->u.revision.rev; | ||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | __tagtable(ATAG_REVISION, parse_tag_revision); | ||
124 | |||
125 | static int __init parse_tag_cmdline(const struct tag *tag) | ||
126 | { | ||
127 | #if defined(CONFIG_CMDLINE_EXTEND) | ||
128 | strlcat(default_command_line, " ", COMMAND_LINE_SIZE); | ||
129 | strlcat(default_command_line, tag->u.cmdline.cmdline, | ||
130 | COMMAND_LINE_SIZE); | ||
131 | #elif defined(CONFIG_CMDLINE_FORCE) | ||
132 | pr_warning("Ignoring tag cmdline (using the default kernel command line)\n"); | ||
133 | #else | ||
134 | strlcpy(default_command_line, tag->u.cmdline.cmdline, | ||
135 | COMMAND_LINE_SIZE); | ||
136 | #endif | ||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | __tagtable(ATAG_CMDLINE, parse_tag_cmdline); | ||
141 | |||
142 | /* | ||
143 | * Scan the tag table for this tag, and call its parse function. | ||
144 | * The tag table is built by the linker from all the __tagtable | ||
145 | * declarations. | ||
146 | */ | ||
147 | static int __init parse_tag(const struct tag *tag) | ||
148 | { | ||
149 | extern struct tagtable __tagtable_begin, __tagtable_end; | ||
150 | struct tagtable *t; | ||
151 | |||
152 | for (t = &__tagtable_begin; t < &__tagtable_end; t++) | ||
153 | if (tag->hdr.tag == t->tag) { | ||
154 | t->parse(tag); | ||
155 | break; | ||
156 | } | ||
157 | |||
158 | return t < &__tagtable_end; | ||
159 | } | ||
160 | |||
161 | /* | ||
162 | * Parse all tags in the list, checking both the global and architecture | ||
163 | * specific tag tables. | ||
164 | */ | ||
165 | static void __init parse_tags(const struct tag *t) | ||
166 | { | ||
167 | for (; t->hdr.size; t = tag_next(t)) | ||
168 | if (!parse_tag(t)) | ||
169 | printk(KERN_WARNING | ||
170 | "Ignoring unrecognised tag 0x%08x\n", | ||
171 | t->hdr.tag); | ||
172 | } | ||
173 | |||
174 | static void __init squash_mem_tags(struct tag *tag) | ||
175 | { | ||
176 | for (; tag->hdr.size; tag = tag_next(tag)) | ||
177 | if (tag->hdr.tag == ATAG_MEM) | ||
178 | tag->hdr.tag = ATAG_NONE; | ||
179 | } | ||
180 | |||
181 | struct machine_desc * __init setup_machine_tags(phys_addr_t __atags_pointer, | ||
182 | unsigned int machine_nr) | ||
183 | { | ||
184 | struct tag *tags = (struct tag *)&default_tags; | ||
185 | struct machine_desc *mdesc = NULL, *p; | ||
186 | char *from = default_command_line; | ||
187 | |||
188 | default_tags.mem.start = PHYS_OFFSET; | ||
189 | |||
190 | /* | ||
191 | * locate machine in the list of supported machines. | ||
192 | */ | ||
193 | for_each_machine_desc(p) | ||
194 | if (machine_nr == p->nr) { | ||
195 | printk("Machine: %s\n", p->name); | ||
196 | mdesc = p; | ||
197 | break; | ||
198 | } | ||
199 | |||
200 | if (!mdesc) { | ||
201 | early_print("\nError: unrecognized/unsupported machine ID" | ||
202 | " (r1 = 0x%08x).\n\n", machine_nr); | ||
203 | dump_machine_table(); /* does not return */ | ||
204 | } | ||
205 | |||
206 | if (__atags_pointer) | ||
207 | tags = phys_to_virt(__atags_pointer); | ||
208 | else if (mdesc->atag_offset) | ||
209 | tags = (void *)(PAGE_OFFSET + mdesc->atag_offset); | ||
210 | |||
211 | #if defined(CONFIG_DEPRECATED_PARAM_STRUCT) | ||
212 | /* | ||
213 | * If we have the old style parameters, convert them to | ||
214 | * a tag list. | ||
215 | */ | ||
216 | if (tags->hdr.tag != ATAG_CORE) | ||
217 | convert_to_tag_list(tags); | ||
218 | #endif | ||
219 | if (tags->hdr.tag != ATAG_CORE) { | ||
220 | early_print("Warning: Neither atags nor dtb found\n"); | ||
221 | tags = (struct tag *)&default_tags; | ||
222 | } | ||
223 | |||
224 | if (mdesc->fixup) | ||
225 | mdesc->fixup(tags, &from, &meminfo); | ||
226 | |||
227 | if (tags->hdr.tag == ATAG_CORE) { | ||
228 | if (meminfo.nr_banks != 0) | ||
229 | squash_mem_tags(tags); | ||
230 | save_atags(tags); | ||
231 | parse_tags(tags); | ||
232 | } | ||
233 | |||
234 | /* parse_early_param needs a boot_command_line */ | ||
235 | strlcpy(boot_command_line, from, COMMAND_LINE_SIZE); | ||
236 | |||
237 | return mdesc; | ||
238 | } | ||
diff --git a/arch/arm/kernel/atags.c b/arch/arm/kernel/atags_proc.c index 42a1a1415fa6..42a1a1415fa6 100644 --- a/arch/arm/kernel/atags.c +++ b/arch/arm/kernel/atags_proc.c | |||
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index 463ff4a0ec8a..e337879595e5 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S | |||
@@ -387,6 +387,7 @@ | |||
387 | /* 375 */ CALL(sys_setns) | 387 | /* 375 */ CALL(sys_setns) |
388 | CALL(sys_process_vm_readv) | 388 | CALL(sys_process_vm_readv) |
389 | CALL(sys_process_vm_writev) | 389 | CALL(sys_process_vm_writev) |
390 | CALL(sys_ni_syscall) /* reserved for sys_kcmp */ | ||
390 | #ifndef syscalls_counted | 391 | #ifndef syscalls_counted |
391 | .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls | 392 | .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls |
392 | #define syscalls_counted | 393 | #define syscalls_counted |
diff --git a/arch/arm/kernel/compat.h b/arch/arm/kernel/compat.h deleted file mode 100644 index 39264ab1b9c6..000000000000 --- a/arch/arm/kernel/compat.h +++ /dev/null | |||
@@ -1,11 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/kernel/compat.h | ||
3 | * | ||
4 | * Copyright (C) 2001 Russell King | ||
5 | * | ||
6 | * 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 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | extern void convert_to_tag_list(struct tag *tags); | ||
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 978eac57e04a..f45987037bf1 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S | |||
@@ -94,6 +94,15 @@ ENDPROC(ret_from_fork) | |||
94 | .equ NR_syscalls,0 | 94 | .equ NR_syscalls,0 |
95 | #define CALL(x) .equ NR_syscalls,NR_syscalls+1 | 95 | #define CALL(x) .equ NR_syscalls,NR_syscalls+1 |
96 | #include "calls.S" | 96 | #include "calls.S" |
97 | |||
98 | /* | ||
99 | * Ensure that the system call table is equal to __NR_syscalls, | ||
100 | * which is the value the rest of the system sees | ||
101 | */ | ||
102 | .ifne NR_syscalls - __NR_syscalls | ||
103 | .error "__NR_syscalls is not equal to the size of the syscall table" | ||
104 | .endif | ||
105 | |||
97 | #undef CALL | 106 | #undef CALL |
98 | #define CALL(x) .long x | 107 | #define CALL(x) .long x |
99 | 108 | ||
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index ba386bd94107..281bf3301241 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c | |||
@@ -159,6 +159,12 @@ static int debug_arch_supported(void) | |||
159 | arch >= ARM_DEBUG_ARCH_V7_1; | 159 | arch >= ARM_DEBUG_ARCH_V7_1; |
160 | } | 160 | } |
161 | 161 | ||
162 | /* Can we determine the watchpoint access type from the fsr? */ | ||
163 | static int debug_exception_updates_fsr(void) | ||
164 | { | ||
165 | return 0; | ||
166 | } | ||
167 | |||
162 | /* Determine number of WRP registers available. */ | 168 | /* Determine number of WRP registers available. */ |
163 | static int get_num_wrp_resources(void) | 169 | static int get_num_wrp_resources(void) |
164 | { | 170 | { |
@@ -604,13 +610,14 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp) | |||
604 | /* Aligned */ | 610 | /* Aligned */ |
605 | break; | 611 | break; |
606 | case 1: | 612 | case 1: |
607 | /* Allow single byte watchpoint. */ | ||
608 | if (info->ctrl.len == ARM_BREAKPOINT_LEN_1) | ||
609 | break; | ||
610 | case 2: | 613 | case 2: |
611 | /* Allow halfword watchpoints and breakpoints. */ | 614 | /* Allow halfword watchpoints and breakpoints. */ |
612 | if (info->ctrl.len == ARM_BREAKPOINT_LEN_2) | 615 | if (info->ctrl.len == ARM_BREAKPOINT_LEN_2) |
613 | break; | 616 | break; |
617 | case 3: | ||
618 | /* Allow single byte watchpoint. */ | ||
619 | if (info->ctrl.len == ARM_BREAKPOINT_LEN_1) | ||
620 | break; | ||
614 | default: | 621 | default: |
615 | ret = -EINVAL; | 622 | ret = -EINVAL; |
616 | goto out; | 623 | goto out; |
@@ -619,18 +626,35 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp) | |||
619 | info->address &= ~alignment_mask; | 626 | info->address &= ~alignment_mask; |
620 | info->ctrl.len <<= offset; | 627 | info->ctrl.len <<= offset; |
621 | 628 | ||
622 | /* | 629 | if (!bp->overflow_handler) { |
623 | * Currently we rely on an overflow handler to take | 630 | /* |
624 | * care of single-stepping the breakpoint when it fires. | 631 | * Mismatch breakpoints are required for single-stepping |
625 | * In the case of userspace breakpoints on a core with V7 debug, | 632 | * breakpoints. |
626 | * we can use the mismatch feature as a poor-man's hardware | 633 | */ |
627 | * single-step, but this only works for per-task breakpoints. | 634 | if (!core_has_mismatch_brps()) |
628 | */ | 635 | return -EINVAL; |
629 | if (!bp->overflow_handler && (arch_check_bp_in_kernelspace(bp) || | 636 | |
630 | !core_has_mismatch_brps() || !bp->hw.bp_target)) { | 637 | /* We don't allow mismatch breakpoints in kernel space. */ |
631 | pr_warning("overflow handler required but none found\n"); | 638 | if (arch_check_bp_in_kernelspace(bp)) |
632 | ret = -EINVAL; | 639 | return -EPERM; |
640 | |||
641 | /* | ||
642 | * Per-cpu breakpoints are not supported by our stepping | ||
643 | * mechanism. | ||
644 | */ | ||
645 | if (!bp->hw.bp_target) | ||
646 | return -EINVAL; | ||
647 | |||
648 | /* | ||
649 | * We only support specific access types if the fsr | ||
650 | * reports them. | ||
651 | */ | ||
652 | if (!debug_exception_updates_fsr() && | ||
653 | (info->ctrl.type == ARM_BREAKPOINT_LOAD || | ||
654 | info->ctrl.type == ARM_BREAKPOINT_STORE)) | ||
655 | return -EINVAL; | ||
633 | } | 656 | } |
657 | |||
634 | out: | 658 | out: |
635 | return ret; | 659 | return ret; |
636 | } | 660 | } |
@@ -706,10 +730,12 @@ static void watchpoint_handler(unsigned long addr, unsigned int fsr, | |||
706 | goto unlock; | 730 | goto unlock; |
707 | 731 | ||
708 | /* Check that the access type matches. */ | 732 | /* Check that the access type matches. */ |
709 | access = (fsr & ARM_FSR_ACCESS_MASK) ? HW_BREAKPOINT_W : | 733 | if (debug_exception_updates_fsr()) { |
710 | HW_BREAKPOINT_R; | 734 | access = (fsr & ARM_FSR_ACCESS_MASK) ? |
711 | if (!(access & hw_breakpoint_type(wp))) | 735 | HW_BREAKPOINT_W : HW_BREAKPOINT_R; |
712 | goto unlock; | 736 | if (!(access & hw_breakpoint_type(wp))) |
737 | goto unlock; | ||
738 | } | ||
713 | 739 | ||
714 | /* We have a winner. */ | 740 | /* We have a winner. */ |
715 | info->trigger = addr; | 741 | info->trigger = addr; |
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index dfcdb9f7c126..e29c3337ca81 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c | |||
@@ -8,7 +8,9 @@ | |||
8 | #include <linux/reboot.h> | 8 | #include <linux/reboot.h> |
9 | #include <linux/io.h> | 9 | #include <linux/io.h> |
10 | #include <linux/irq.h> | 10 | #include <linux/irq.h> |
11 | #include <linux/memblock.h> | ||
11 | #include <asm/pgtable.h> | 12 | #include <asm/pgtable.h> |
13 | #include <linux/of_fdt.h> | ||
12 | #include <asm/pgalloc.h> | 14 | #include <asm/pgalloc.h> |
13 | #include <asm/mmu_context.h> | 15 | #include <asm/mmu_context.h> |
14 | #include <asm/cacheflush.h> | 16 | #include <asm/cacheflush.h> |
@@ -32,6 +34,29 @@ static atomic_t waiting_for_crash_ipi; | |||
32 | 34 | ||
33 | int machine_kexec_prepare(struct kimage *image) | 35 | int machine_kexec_prepare(struct kimage *image) |
34 | { | 36 | { |
37 | struct kexec_segment *current_segment; | ||
38 | __be32 header; | ||
39 | int i, err; | ||
40 | |||
41 | /* | ||
42 | * No segment at default ATAGs address. try to locate | ||
43 | * a dtb using magic. | ||
44 | */ | ||
45 | for (i = 0; i < image->nr_segments; i++) { | ||
46 | current_segment = &image->segment[i]; | ||
47 | |||
48 | err = memblock_is_region_memory(current_segment->mem, | ||
49 | current_segment->memsz); | ||
50 | if (err) | ||
51 | return - EINVAL; | ||
52 | |||
53 | err = get_user(header, (__be32*)current_segment->buf); | ||
54 | if (err) | ||
55 | return err; | ||
56 | |||
57 | if (be32_to_cpu(header) == OF_DT_HEADER) | ||
58 | kexec_boot_atags = current_segment->mem; | ||
59 | } | ||
35 | return 0; | 60 | return 0; |
36 | } | 61 | } |
37 | 62 | ||
@@ -122,7 +147,9 @@ void machine_kexec(struct kimage *image) | |||
122 | kexec_start_address = image->start; | 147 | kexec_start_address = image->start; |
123 | kexec_indirection_page = page_list; | 148 | kexec_indirection_page = page_list; |
124 | kexec_mach_type = machine_arch_type; | 149 | kexec_mach_type = machine_arch_type; |
125 | kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET; | 150 | if (!kexec_boot_atags) |
151 | kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET; | ||
152 | |||
126 | 153 | ||
127 | /* copy our kernel relocation code to the control code page */ | 154 | /* copy our kernel relocation code to the control code page */ |
128 | memcpy(reboot_code_buffer, | 155 | memcpy(reboot_code_buffer, |
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 3e0fc5f7ed4b..739db3a1b2d2 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c | |||
@@ -30,6 +30,9 @@ | |||
30 | #include <asm/pgtable.h> | 30 | #include <asm/pgtable.h> |
31 | #include <asm/traps.h> | 31 | #include <asm/traps.h> |
32 | 32 | ||
33 | #define CREATE_TRACE_POINTS | ||
34 | #include <trace/events/syscalls.h> | ||
35 | |||
33 | #define REG_PC 15 | 36 | #define REG_PC 15 |
34 | #define REG_PSR 16 | 37 | #define REG_PSR 16 |
35 | /* | 38 | /* |
@@ -918,11 +921,11 @@ static int ptrace_syscall_trace(struct pt_regs *regs, int scno, | |||
918 | { | 921 | { |
919 | unsigned long ip; | 922 | unsigned long ip; |
920 | 923 | ||
924 | current_thread_info()->syscall = scno; | ||
925 | |||
921 | if (!test_thread_flag(TIF_SYSCALL_TRACE)) | 926 | if (!test_thread_flag(TIF_SYSCALL_TRACE)) |
922 | return scno; | 927 | return scno; |
923 | 928 | ||
924 | current_thread_info()->syscall = scno; | ||
925 | |||
926 | /* | 929 | /* |
927 | * IP is used to denote syscall entry/exit: | 930 | * IP is used to denote syscall entry/exit: |
928 | * IP = 0 -> entry, =1 -> exit | 931 | * IP = 0 -> entry, =1 -> exit |
@@ -941,15 +944,19 @@ static int ptrace_syscall_trace(struct pt_regs *regs, int scno, | |||
941 | 944 | ||
942 | asmlinkage int syscall_trace_enter(struct pt_regs *regs, int scno) | 945 | asmlinkage int syscall_trace_enter(struct pt_regs *regs, int scno) |
943 | { | 946 | { |
944 | int ret = ptrace_syscall_trace(regs, scno, PTRACE_SYSCALL_ENTER); | 947 | scno = ptrace_syscall_trace(regs, scno, PTRACE_SYSCALL_ENTER); |
948 | if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) | ||
949 | trace_sys_enter(regs, scno); | ||
945 | audit_syscall_entry(AUDIT_ARCH_ARM, scno, regs->ARM_r0, regs->ARM_r1, | 950 | audit_syscall_entry(AUDIT_ARCH_ARM, scno, regs->ARM_r0, regs->ARM_r1, |
946 | regs->ARM_r2, regs->ARM_r3); | 951 | regs->ARM_r2, regs->ARM_r3); |
947 | return ret; | 952 | return scno; |
948 | } | 953 | } |
949 | 954 | ||
950 | asmlinkage int syscall_trace_exit(struct pt_regs *regs, int scno) | 955 | asmlinkage int syscall_trace_exit(struct pt_regs *regs, int scno) |
951 | { | 956 | { |
952 | int ret = ptrace_syscall_trace(regs, scno, PTRACE_SYSCALL_EXIT); | 957 | scno = ptrace_syscall_trace(regs, scno, PTRACE_SYSCALL_EXIT); |
958 | if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) | ||
959 | trace_sys_exit(regs, scno); | ||
953 | audit_syscall_exit(regs); | 960 | audit_syscall_exit(regs); |
954 | return ret; | 961 | return scno; |
955 | } | 962 | } |
diff --git a/arch/arm/kernel/sched_clock.c b/arch/arm/kernel/sched_clock.c index 27d186abbc06..e21bac20d90d 100644 --- a/arch/arm/kernel/sched_clock.c +++ b/arch/arm/kernel/sched_clock.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/init.h> | 9 | #include <linux/init.h> |
10 | #include <linux/jiffies.h> | 10 | #include <linux/jiffies.h> |
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/moduleparam.h> | ||
12 | #include <linux/sched.h> | 13 | #include <linux/sched.h> |
13 | #include <linux/syscore_ops.h> | 14 | #include <linux/syscore_ops.h> |
14 | #include <linux/timer.h> | 15 | #include <linux/timer.h> |
@@ -21,10 +22,15 @@ struct clock_data { | |||
21 | u32 epoch_cyc_copy; | 22 | u32 epoch_cyc_copy; |
22 | u32 mult; | 23 | u32 mult; |
23 | u32 shift; | 24 | u32 shift; |
25 | bool suspended; | ||
26 | bool needs_suspend; | ||
24 | }; | 27 | }; |
25 | 28 | ||
26 | static void sched_clock_poll(unsigned long wrap_ticks); | 29 | static void sched_clock_poll(unsigned long wrap_ticks); |
27 | static DEFINE_TIMER(sched_clock_timer, sched_clock_poll, 0, 0); | 30 | static DEFINE_TIMER(sched_clock_timer, sched_clock_poll, 0, 0); |
31 | static int irqtime = -1; | ||
32 | |||
33 | core_param(irqtime, irqtime, int, 0400); | ||
28 | 34 | ||
29 | static struct clock_data cd = { | 35 | static struct clock_data cd = { |
30 | .mult = NSEC_PER_SEC / HZ, | 36 | .mult = NSEC_PER_SEC / HZ, |
@@ -49,6 +55,9 @@ static unsigned long long cyc_to_sched_clock(u32 cyc, u32 mask) | |||
49 | u64 epoch_ns; | 55 | u64 epoch_ns; |
50 | u32 epoch_cyc; | 56 | u32 epoch_cyc; |
51 | 57 | ||
58 | if (cd.suspended) | ||
59 | return cd.epoch_ns; | ||
60 | |||
52 | /* | 61 | /* |
53 | * Load the epoch_cyc and epoch_ns atomically. We do this by | 62 | * Load the epoch_cyc and epoch_ns atomically. We do this by |
54 | * ensuring that we always write epoch_cyc, epoch_ns and | 63 | * ensuring that we always write epoch_cyc, epoch_ns and |
@@ -98,6 +107,13 @@ static void sched_clock_poll(unsigned long wrap_ticks) | |||
98 | update_sched_clock(); | 107 | update_sched_clock(); |
99 | } | 108 | } |
100 | 109 | ||
110 | void __init setup_sched_clock_needs_suspend(u32 (*read)(void), int bits, | ||
111 | unsigned long rate) | ||
112 | { | ||
113 | setup_sched_clock(read, bits, rate); | ||
114 | cd.needs_suspend = true; | ||
115 | } | ||
116 | |||
101 | void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate) | 117 | void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate) |
102 | { | 118 | { |
103 | unsigned long r, w; | 119 | unsigned long r, w; |
@@ -145,6 +161,10 @@ void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate) | |||
145 | */ | 161 | */ |
146 | cd.epoch_ns = 0; | 162 | cd.epoch_ns = 0; |
147 | 163 | ||
164 | /* Enable IRQ time accounting if we have a fast enough sched_clock */ | ||
165 | if (irqtime > 0 || (irqtime == -1 && rate >= 1000000)) | ||
166 | enable_sched_clock_irqtime(); | ||
167 | |||
148 | pr_debug("Registered %pF as sched_clock source\n", read); | 168 | pr_debug("Registered %pF as sched_clock source\n", read); |
149 | } | 169 | } |
150 | 170 | ||
@@ -169,11 +189,23 @@ void __init sched_clock_postinit(void) | |||
169 | static int sched_clock_suspend(void) | 189 | static int sched_clock_suspend(void) |
170 | { | 190 | { |
171 | sched_clock_poll(sched_clock_timer.data); | 191 | sched_clock_poll(sched_clock_timer.data); |
192 | if (cd.needs_suspend) | ||
193 | cd.suspended = true; | ||
172 | return 0; | 194 | return 0; |
173 | } | 195 | } |
174 | 196 | ||
197 | static void sched_clock_resume(void) | ||
198 | { | ||
199 | if (cd.needs_suspend) { | ||
200 | cd.epoch_cyc = read_sched_clock(); | ||
201 | cd.epoch_cyc_copy = cd.epoch_cyc; | ||
202 | cd.suspended = false; | ||
203 | } | ||
204 | } | ||
205 | |||
175 | static struct syscore_ops sched_clock_ops = { | 206 | static struct syscore_ops sched_clock_ops = { |
176 | .suspend = sched_clock_suspend, | 207 | .suspend = sched_clock_suspend, |
208 | .resume = sched_clock_resume, | ||
177 | }; | 209 | }; |
178 | 210 | ||
179 | static int __init sched_clock_syscore_init(void) | 211 | static int __init sched_clock_syscore_init(void) |
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index a81dcecc7343..0785472460a8 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c | |||
@@ -21,11 +21,9 @@ | |||
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/kexec.h> | 22 | #include <linux/kexec.h> |
23 | #include <linux/of_fdt.h> | 23 | #include <linux/of_fdt.h> |
24 | #include <linux/root_dev.h> | ||
25 | #include <linux/cpu.h> | 24 | #include <linux/cpu.h> |
26 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
27 | #include <linux/smp.h> | 26 | #include <linux/smp.h> |
28 | #include <linux/fs.h> | ||
29 | #include <linux/proc_fs.h> | 27 | #include <linux/proc_fs.h> |
30 | #include <linux/memblock.h> | 28 | #include <linux/memblock.h> |
31 | #include <linux/bug.h> | 29 | #include <linux/bug.h> |
@@ -56,15 +54,9 @@ | |||
56 | #include <asm/unwind.h> | 54 | #include <asm/unwind.h> |
57 | #include <asm/memblock.h> | 55 | #include <asm/memblock.h> |
58 | 56 | ||
59 | #if defined(CONFIG_DEPRECATED_PARAM_STRUCT) | ||
60 | #include "compat.h" | ||
61 | #endif | ||
62 | #include "atags.h" | 57 | #include "atags.h" |
63 | #include "tcm.h" | 58 | #include "tcm.h" |
64 | 59 | ||
65 | #ifndef MEM_SIZE | ||
66 | #define MEM_SIZE (16*1024*1024) | ||
67 | #endif | ||
68 | 60 | ||
69 | #if defined(CONFIG_FPE_NWFPE) || defined(CONFIG_FPE_FASTFPE) | 61 | #if defined(CONFIG_FPE_NWFPE) || defined(CONFIG_FPE_FASTFPE) |
70 | char fpe_type[8]; | 62 | char fpe_type[8]; |
@@ -145,7 +137,6 @@ static const char *machine_name; | |||
145 | static char __initdata cmd_line[COMMAND_LINE_SIZE]; | 137 | static char __initdata cmd_line[COMMAND_LINE_SIZE]; |
146 | struct machine_desc *machine_desc __initdata; | 138 | struct machine_desc *machine_desc __initdata; |
147 | 139 | ||
148 | static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; | ||
149 | static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } }; | 140 | static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } }; |
150 | #define ENDIANNESS ((char)endian_test.l) | 141 | #define ENDIANNESS ((char)endian_test.l) |
151 | 142 | ||
@@ -583,21 +574,6 @@ static int __init early_mem(char *p) | |||
583 | } | 574 | } |
584 | early_param("mem", early_mem); | 575 | early_param("mem", early_mem); |
585 | 576 | ||
586 | static void __init | ||
587 | setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz) | ||
588 | { | ||
589 | #ifdef CONFIG_BLK_DEV_RAM | ||
590 | extern int rd_size, rd_image_start, rd_prompt, rd_doload; | ||
591 | |||
592 | rd_image_start = image_start; | ||
593 | rd_prompt = prompt; | ||
594 | rd_doload = doload; | ||
595 | |||
596 | if (rd_sz) | ||
597 | rd_size = rd_sz; | ||
598 | #endif | ||
599 | } | ||
600 | |||
601 | static void __init request_standard_resources(struct machine_desc *mdesc) | 577 | static void __init request_standard_resources(struct machine_desc *mdesc) |
602 | { | 578 | { |
603 | struct memblock_region *region; | 579 | struct memblock_region *region; |
@@ -643,35 +619,6 @@ static void __init request_standard_resources(struct machine_desc *mdesc) | |||
643 | request_resource(&ioport_resource, &lp2); | 619 | request_resource(&ioport_resource, &lp2); |
644 | } | 620 | } |
645 | 621 | ||
646 | /* | ||
647 | * Tag parsing. | ||
648 | * | ||
649 | * This is the new way of passing data to the kernel at boot time. Rather | ||
650 | * than passing a fixed inflexible structure to the kernel, we pass a list | ||
651 | * of variable-sized tags to the kernel. The first tag must be a ATAG_CORE | ||
652 | * tag for the list to be recognised (to distinguish the tagged list from | ||
653 | * a param_struct). The list is terminated with a zero-length tag (this tag | ||
654 | * is not parsed in any way). | ||
655 | */ | ||
656 | static int __init parse_tag_core(const struct tag *tag) | ||
657 | { | ||
658 | if (tag->hdr.size > 2) { | ||
659 | if ((tag->u.core.flags & 1) == 0) | ||
660 | root_mountflags &= ~MS_RDONLY; | ||
661 | ROOT_DEV = old_decode_dev(tag->u.core.rootdev); | ||
662 | } | ||
663 | return 0; | ||
664 | } | ||
665 | |||
666 | __tagtable(ATAG_CORE, parse_tag_core); | ||
667 | |||
668 | static int __init parse_tag_mem32(const struct tag *tag) | ||
669 | { | ||
670 | return arm_add_memory(tag->u.mem.start, tag->u.mem.size); | ||
671 | } | ||
672 | |||
673 | __tagtable(ATAG_MEM, parse_tag_mem32); | ||
674 | |||
675 | #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE) | 622 | #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE) |
676 | struct screen_info screen_info = { | 623 | struct screen_info screen_info = { |
677 | .orig_video_lines = 30, | 624 | .orig_video_lines = 30, |
@@ -681,117 +628,8 @@ struct screen_info screen_info = { | |||
681 | .orig_video_isVGA = 1, | 628 | .orig_video_isVGA = 1, |
682 | .orig_video_points = 8 | 629 | .orig_video_points = 8 |
683 | }; | 630 | }; |
684 | |||
685 | static int __init parse_tag_videotext(const struct tag *tag) | ||
686 | { | ||
687 | screen_info.orig_x = tag->u.videotext.x; | ||
688 | screen_info.orig_y = tag->u.videotext.y; | ||
689 | screen_info.orig_video_page = tag->u.videotext.video_page; | ||
690 | screen_info.orig_video_mode = tag->u.videotext.video_mode; | ||
691 | screen_info.orig_video_cols = tag->u.videotext.video_cols; | ||
692 | screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx; | ||
693 | screen_info.orig_video_lines = tag->u.videotext.video_lines; | ||
694 | screen_info.orig_video_isVGA = tag->u.videotext.video_isvga; | ||
695 | screen_info.orig_video_points = tag->u.videotext.video_points; | ||
696 | return 0; | ||
697 | } | ||
698 | |||
699 | __tagtable(ATAG_VIDEOTEXT, parse_tag_videotext); | ||
700 | #endif | 631 | #endif |
701 | 632 | ||
702 | static int __init parse_tag_ramdisk(const struct tag *tag) | ||
703 | { | ||
704 | setup_ramdisk((tag->u.ramdisk.flags & 1) == 0, | ||
705 | (tag->u.ramdisk.flags & 2) == 0, | ||
706 | tag->u.ramdisk.start, tag->u.ramdisk.size); | ||
707 | return 0; | ||
708 | } | ||
709 | |||
710 | __tagtable(ATAG_RAMDISK, parse_tag_ramdisk); | ||
711 | |||
712 | static int __init parse_tag_serialnr(const struct tag *tag) | ||
713 | { | ||
714 | system_serial_low = tag->u.serialnr.low; | ||
715 | system_serial_high = tag->u.serialnr.high; | ||
716 | return 0; | ||
717 | } | ||
718 | |||
719 | __tagtable(ATAG_SERIAL, parse_tag_serialnr); | ||
720 | |||
721 | static int __init parse_tag_revision(const struct tag *tag) | ||
722 | { | ||
723 | system_rev = tag->u.revision.rev; | ||
724 | return 0; | ||
725 | } | ||
726 | |||
727 | __tagtable(ATAG_REVISION, parse_tag_revision); | ||
728 | |||
729 | static int __init parse_tag_cmdline(const struct tag *tag) | ||
730 | { | ||
731 | #if defined(CONFIG_CMDLINE_EXTEND) | ||
732 | strlcat(default_command_line, " ", COMMAND_LINE_SIZE); | ||
733 | strlcat(default_command_line, tag->u.cmdline.cmdline, | ||
734 | COMMAND_LINE_SIZE); | ||
735 | #elif defined(CONFIG_CMDLINE_FORCE) | ||
736 | pr_warning("Ignoring tag cmdline (using the default kernel command line)\n"); | ||
737 | #else | ||
738 | strlcpy(default_command_line, tag->u.cmdline.cmdline, | ||
739 | COMMAND_LINE_SIZE); | ||
740 | #endif | ||
741 | return 0; | ||
742 | } | ||
743 | |||
744 | __tagtable(ATAG_CMDLINE, parse_tag_cmdline); | ||
745 | |||
746 | /* | ||
747 | * Scan the tag table for this tag, and call its parse function. | ||
748 | * The tag table is built by the linker from all the __tagtable | ||
749 | * declarations. | ||
750 | */ | ||
751 | static int __init parse_tag(const struct tag *tag) | ||
752 | { | ||
753 | extern struct tagtable __tagtable_begin, __tagtable_end; | ||
754 | struct tagtable *t; | ||
755 | |||
756 | for (t = &__tagtable_begin; t < &__tagtable_end; t++) | ||
757 | if (tag->hdr.tag == t->tag) { | ||
758 | t->parse(tag); | ||
759 | break; | ||
760 | } | ||
761 | |||
762 | return t < &__tagtable_end; | ||
763 | } | ||
764 | |||
765 | /* | ||
766 | * Parse all tags in the list, checking both the global and architecture | ||
767 | * specific tag tables. | ||
768 | */ | ||
769 | static void __init parse_tags(const struct tag *t) | ||
770 | { | ||
771 | for (; t->hdr.size; t = tag_next(t)) | ||
772 | if (!parse_tag(t)) | ||
773 | printk(KERN_WARNING | ||
774 | "Ignoring unrecognised tag 0x%08x\n", | ||
775 | t->hdr.tag); | ||
776 | } | ||
777 | |||
778 | /* | ||
779 | * This holds our defaults. | ||
780 | */ | ||
781 | static struct init_tags { | ||
782 | struct tag_header hdr1; | ||
783 | struct tag_core core; | ||
784 | struct tag_header hdr2; | ||
785 | struct tag_mem32 mem; | ||
786 | struct tag_header hdr3; | ||
787 | } init_tags __initdata = { | ||
788 | { tag_size(tag_core), ATAG_CORE }, | ||
789 | { 1, PAGE_SIZE, 0xff }, | ||
790 | { tag_size(tag_mem32), ATAG_MEM }, | ||
791 | { MEM_SIZE }, | ||
792 | { 0, ATAG_NONE } | ||
793 | }; | ||
794 | |||
795 | static int __init customize_machine(void) | 633 | static int __init customize_machine(void) |
796 | { | 634 | { |
797 | /* customizes platform devices, or adds new ones */ | 635 | /* customizes platform devices, or adds new ones */ |
@@ -858,78 +696,6 @@ static void __init reserve_crashkernel(void) | |||
858 | static inline void reserve_crashkernel(void) {} | 696 | static inline void reserve_crashkernel(void) {} |
859 | #endif /* CONFIG_KEXEC */ | 697 | #endif /* CONFIG_KEXEC */ |
860 | 698 | ||
861 | static void __init squash_mem_tags(struct tag *tag) | ||
862 | { | ||
863 | for (; tag->hdr.size; tag = tag_next(tag)) | ||
864 | if (tag->hdr.tag == ATAG_MEM) | ||
865 | tag->hdr.tag = ATAG_NONE; | ||
866 | } | ||
867 | |||
868 | static struct machine_desc * __init setup_machine_tags(unsigned int nr) | ||
869 | { | ||
870 | struct tag *tags = (struct tag *)&init_tags; | ||
871 | struct machine_desc *mdesc = NULL, *p; | ||
872 | char *from = default_command_line; | ||
873 | |||
874 | init_tags.mem.start = PHYS_OFFSET; | ||
875 | |||
876 | /* | ||
877 | * locate machine in the list of supported machines. | ||
878 | */ | ||
879 | for_each_machine_desc(p) | ||
880 | if (nr == p->nr) { | ||
881 | printk("Machine: %s\n", p->name); | ||
882 | mdesc = p; | ||
883 | break; | ||
884 | } | ||
885 | |||
886 | if (!mdesc) { | ||
887 | early_print("\nError: unrecognized/unsupported machine ID" | ||
888 | " (r1 = 0x%08x).\n\n", nr); | ||
889 | dump_machine_table(); /* does not return */ | ||
890 | } | ||
891 | |||
892 | if (__atags_pointer) | ||
893 | tags = phys_to_virt(__atags_pointer); | ||
894 | else if (mdesc->atag_offset) | ||
895 | tags = (void *)(PAGE_OFFSET + mdesc->atag_offset); | ||
896 | |||
897 | #if defined(CONFIG_DEPRECATED_PARAM_STRUCT) | ||
898 | /* | ||
899 | * If we have the old style parameters, convert them to | ||
900 | * a tag list. | ||
901 | */ | ||
902 | if (tags->hdr.tag != ATAG_CORE) | ||
903 | convert_to_tag_list(tags); | ||
904 | #endif | ||
905 | |||
906 | if (tags->hdr.tag != ATAG_CORE) { | ||
907 | #if defined(CONFIG_OF) | ||
908 | /* | ||
909 | * If CONFIG_OF is set, then assume this is a reasonably | ||
910 | * modern system that should pass boot parameters | ||
911 | */ | ||
912 | early_print("Warning: Neither atags nor dtb found\n"); | ||
913 | #endif | ||
914 | tags = (struct tag *)&init_tags; | ||
915 | } | ||
916 | |||
917 | if (mdesc->fixup) | ||
918 | mdesc->fixup(tags, &from, &meminfo); | ||
919 | |||
920 | if (tags->hdr.tag == ATAG_CORE) { | ||
921 | if (meminfo.nr_banks != 0) | ||
922 | squash_mem_tags(tags); | ||
923 | save_atags(tags); | ||
924 | parse_tags(tags); | ||
925 | } | ||
926 | |||
927 | /* parse_early_param needs a boot_command_line */ | ||
928 | strlcpy(boot_command_line, from, COMMAND_LINE_SIZE); | ||
929 | |||
930 | return mdesc; | ||
931 | } | ||
932 | |||
933 | static int __init meminfo_cmp(const void *_a, const void *_b) | 699 | static int __init meminfo_cmp(const void *_a, const void *_b) |
934 | { | 700 | { |
935 | const struct membank *a = _a, *b = _b; | 701 | const struct membank *a = _a, *b = _b; |
@@ -944,7 +710,7 @@ void __init setup_arch(char **cmdline_p) | |||
944 | setup_processor(); | 710 | setup_processor(); |
945 | mdesc = setup_machine_fdt(__atags_pointer); | 711 | mdesc = setup_machine_fdt(__atags_pointer); |
946 | if (!mdesc) | 712 | if (!mdesc) |
947 | mdesc = setup_machine_tags(machine_arch_type); | 713 | mdesc = setup_machine_tags(__atags_pointer, machine_arch_type); |
948 | machine_desc = mdesc; | 714 | machine_desc = mdesc; |
949 | machine_name = mdesc->name; | 715 | machine_name = mdesc->name; |
950 | 716 | ||
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index ebd8ad274d76..d98c37e97d9d 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c | |||
@@ -51,7 +51,8 @@ | |||
51 | struct secondary_data secondary_data; | 51 | struct secondary_data secondary_data; |
52 | 52 | ||
53 | enum ipi_msg_type { | 53 | enum ipi_msg_type { |
54 | IPI_TIMER = 2, | 54 | IPI_WAKEUP, |
55 | IPI_TIMER, | ||
55 | IPI_RESCHEDULE, | 56 | IPI_RESCHEDULE, |
56 | IPI_CALL_FUNC, | 57 | IPI_CALL_FUNC, |
57 | IPI_CALL_FUNC_SINGLE, | 58 | IPI_CALL_FUNC_SINGLE, |
@@ -347,7 +348,8 @@ void arch_send_call_function_single_ipi(int cpu) | |||
347 | } | 348 | } |
348 | 349 | ||
349 | static const char *ipi_types[NR_IPI] = { | 350 | static const char *ipi_types[NR_IPI] = { |
350 | #define S(x,s) [x - IPI_TIMER] = s | 351 | #define S(x,s) [x] = s |
352 | S(IPI_WAKEUP, "CPU wakeup interrupts"), | ||
351 | S(IPI_TIMER, "Timer broadcast interrupts"), | 353 | S(IPI_TIMER, "Timer broadcast interrupts"), |
352 | S(IPI_RESCHEDULE, "Rescheduling interrupts"), | 354 | S(IPI_RESCHEDULE, "Rescheduling interrupts"), |
353 | S(IPI_CALL_FUNC, "Function call interrupts"), | 355 | S(IPI_CALL_FUNC, "Function call interrupts"), |
@@ -500,10 +502,13 @@ void handle_IPI(int ipinr, struct pt_regs *regs) | |||
500 | unsigned int cpu = smp_processor_id(); | 502 | unsigned int cpu = smp_processor_id(); |
501 | struct pt_regs *old_regs = set_irq_regs(regs); | 503 | struct pt_regs *old_regs = set_irq_regs(regs); |
502 | 504 | ||
503 | if (ipinr >= IPI_TIMER && ipinr < IPI_TIMER + NR_IPI) | 505 | if (ipinr < NR_IPI) |
504 | __inc_irq_stat(cpu, ipi_irqs[ipinr - IPI_TIMER]); | 506 | __inc_irq_stat(cpu, ipi_irqs[ipinr]); |
505 | 507 | ||
506 | switch (ipinr) { | 508 | switch (ipinr) { |
509 | case IPI_WAKEUP: | ||
510 | break; | ||
511 | |||
507 | case IPI_TIMER: | 512 | case IPI_TIMER: |
508 | irq_enter(); | 513 | irq_enter(); |
509 | ipi_timer(); | 514 | ipi_timer(); |
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index fef42b21cecb..e1f906989bb8 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c | |||
@@ -11,7 +11,6 @@ | |||
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/clk.h> | 13 | #include <linux/clk.h> |
14 | #include <linux/cpufreq.h> | ||
15 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
16 | #include <linux/device.h> | 15 | #include <linux/device.h> |
17 | #include <linux/err.h> | 16 | #include <linux/err.h> |
@@ -96,7 +95,52 @@ static void twd_timer_stop(struct clock_event_device *clk) | |||
96 | disable_percpu_irq(clk->irq); | 95 | disable_percpu_irq(clk->irq); |
97 | } | 96 | } |
98 | 97 | ||
99 | #ifdef CONFIG_CPU_FREQ | 98 | #ifdef CONFIG_COMMON_CLK |
99 | |||
100 | /* | ||
101 | * Updates clockevent frequency when the cpu frequency changes. | ||
102 | * Called on the cpu that is changing frequency with interrupts disabled. | ||
103 | */ | ||
104 | static void twd_update_frequency(void *new_rate) | ||
105 | { | ||
106 | twd_timer_rate = *((unsigned long *) new_rate); | ||
107 | |||
108 | clockevents_update_freq(*__this_cpu_ptr(twd_evt), twd_timer_rate); | ||
109 | } | ||
110 | |||
111 | static int twd_rate_change(struct notifier_block *nb, | ||
112 | unsigned long flags, void *data) | ||
113 | { | ||
114 | struct clk_notifier_data *cnd = data; | ||
115 | |||
116 | /* | ||
117 | * The twd clock events must be reprogrammed to account for the new | ||
118 | * frequency. The timer is local to a cpu, so cross-call to the | ||
119 | * changing cpu. | ||
120 | */ | ||
121 | if (flags == POST_RATE_CHANGE) | ||
122 | smp_call_function(twd_update_frequency, | ||
123 | (void *)&cnd->new_rate, 1); | ||
124 | |||
125 | return NOTIFY_OK; | ||
126 | } | ||
127 | |||
128 | static struct notifier_block twd_clk_nb = { | ||
129 | .notifier_call = twd_rate_change, | ||
130 | }; | ||
131 | |||
132 | static int twd_clk_init(void) | ||
133 | { | ||
134 | if (twd_evt && *__this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk)) | ||
135 | return clk_notifier_register(twd_clk, &twd_clk_nb); | ||
136 | |||
137 | return 0; | ||
138 | } | ||
139 | core_initcall(twd_clk_init); | ||
140 | |||
141 | #elif defined (CONFIG_CPU_FREQ) | ||
142 | |||
143 | #include <linux/cpufreq.h> | ||
100 | 144 | ||
101 | /* | 145 | /* |
102 | * Updates clockevent frequency when the cpu frequency changes. | 146 | * Updates clockevent frequency when the cpu frequency changes. |
diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c index 198b08456e90..26c12c6440fc 100644 --- a/arch/arm/kernel/topology.c +++ b/arch/arm/kernel/topology.c | |||
@@ -321,7 +321,7 @@ void store_cpu_topology(unsigned int cpuid) | |||
321 | * init_cpu_topology is called at boot when only one cpu is running | 321 | * init_cpu_topology is called at boot when only one cpu is running |
322 | * which prevent simultaneous write access to cpu_topology array | 322 | * which prevent simultaneous write access to cpu_topology array |
323 | */ | 323 | */ |
324 | void init_cpu_topology(void) | 324 | void __init init_cpu_topology(void) |
325 | { | 325 | { |
326 | unsigned int cpu; | 326 | unsigned int cpu; |
327 | 327 | ||
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index f7945218b8c6..b0179b89a04c 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c | |||
@@ -420,20 +420,23 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs) | |||
420 | #endif | 420 | #endif |
421 | instr = *(u32 *) pc; | 421 | instr = *(u32 *) pc; |
422 | } else if (thumb_mode(regs)) { | 422 | } else if (thumb_mode(regs)) { |
423 | get_user(instr, (u16 __user *)pc); | 423 | if (get_user(instr, (u16 __user *)pc)) |
424 | goto die_sig; | ||
424 | if (is_wide_instruction(instr)) { | 425 | if (is_wide_instruction(instr)) { |
425 | unsigned int instr2; | 426 | unsigned int instr2; |
426 | get_user(instr2, (u16 __user *)pc+1); | 427 | if (get_user(instr2, (u16 __user *)pc+1)) |
428 | goto die_sig; | ||
427 | instr <<= 16; | 429 | instr <<= 16; |
428 | instr |= instr2; | 430 | instr |= instr2; |
429 | } | 431 | } |
430 | } else { | 432 | } else if (get_user(instr, (u32 __user *)pc)) { |
431 | get_user(instr, (u32 __user *)pc); | 433 | goto die_sig; |
432 | } | 434 | } |
433 | 435 | ||
434 | if (call_undef_hook(regs, instr) == 0) | 436 | if (call_undef_hook(regs, instr) == 0) |
435 | return; | 437 | return; |
436 | 438 | ||
439 | die_sig: | ||
437 | #ifdef CONFIG_DEBUG_USER | 440 | #ifdef CONFIG_DEBUG_USER |
438 | if (user_debug & UDBG_UNDEFINED) { | 441 | if (user_debug & UDBG_UNDEFINED) { |
439 | printk(KERN_INFO "%s (%d): undefined instruction: pc=%p\n", | 442 | printk(KERN_INFO "%s (%d): undefined instruction: pc=%p\n", |