diff options
Diffstat (limited to 'arch/blackfin/kernel')
25 files changed, 868 insertions, 331 deletions
diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile index fd4d4328a0f2..3731088e181b 100644 --- a/arch/blackfin/kernel/Makefile +++ b/arch/blackfin/kernel/Makefile | |||
@@ -15,6 +15,10 @@ else | |||
15 | obj-y += time.o | 15 | obj-y += time.o |
16 | endif | 16 | endif |
17 | 17 | ||
18 | obj-$(CONFIG_FUNCTION_TRACER) += ftrace-entry.o | ||
19 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o | ||
20 | CFLAGS_REMOVE_ftrace.o = -pg | ||
21 | |||
18 | obj-$(CONFIG_IPIPE) += ipipe.o | 22 | obj-$(CONFIG_IPIPE) += ipipe.o |
19 | obj-$(CONFIG_IPIPE_TRACE_MCOUNT) += mcount.o | 23 | obj-$(CONFIG_IPIPE_TRACE_MCOUNT) += mcount.o |
20 | obj-$(CONFIG_BFIN_GPTIMERS) += gptimers.o | 24 | obj-$(CONFIG_BFIN_GPTIMERS) += gptimers.o |
@@ -23,6 +27,7 @@ obj-$(CONFIG_MODULES) += module.o | |||
23 | obj-$(CONFIG_KGDB) += kgdb.o | 27 | obj-$(CONFIG_KGDB) += kgdb.o |
24 | obj-$(CONFIG_KGDB_TESTS) += kgdb_test.o | 28 | obj-$(CONFIG_KGDB_TESTS) += kgdb_test.o |
25 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | 29 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o |
30 | obj-$(CONFIG_STACKTRACE) += stacktrace.o | ||
26 | 31 | ||
27 | # the kgdb test puts code into L2 and without linker | 32 | # the kgdb test puts code into L2 and without linker |
28 | # relaxation, we need to force long calls to/from it | 33 | # relaxation, we need to force long calls to/from it |
diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c index 8531693fb48d..e0bf8cc06907 100644 --- a/arch/blackfin/kernel/bfin_dma_5xx.c +++ b/arch/blackfin/kernel/bfin_dma_5xx.c | |||
@@ -20,6 +20,11 @@ | |||
20 | #include <asm/dma.h> | 20 | #include <asm/dma.h> |
21 | #include <asm/uaccess.h> | 21 | #include <asm/uaccess.h> |
22 | 22 | ||
23 | /* | ||
24 | * To make sure we work around 05000119 - we always check DMA_DONE bit, | ||
25 | * never the DMA_RUN bit | ||
26 | */ | ||
27 | |||
23 | struct dma_channel dma_ch[MAX_DMA_CHANNELS]; | 28 | struct dma_channel dma_ch[MAX_DMA_CHANNELS]; |
24 | EXPORT_SYMBOL(dma_ch); | 29 | EXPORT_SYMBOL(dma_ch); |
25 | 30 | ||
@@ -232,6 +237,87 @@ void blackfin_dma_resume(void) | |||
232 | void __init blackfin_dma_early_init(void) | 237 | void __init blackfin_dma_early_init(void) |
233 | { | 238 | { |
234 | bfin_write_MDMA_S0_CONFIG(0); | 239 | bfin_write_MDMA_S0_CONFIG(0); |
240 | bfin_write_MDMA_S1_CONFIG(0); | ||
241 | } | ||
242 | |||
243 | void __init early_dma_memcpy(void *pdst, const void *psrc, size_t size) | ||
244 | { | ||
245 | unsigned long dst = (unsigned long)pdst; | ||
246 | unsigned long src = (unsigned long)psrc; | ||
247 | struct dma_register *dst_ch, *src_ch; | ||
248 | |||
249 | /* We assume that everything is 4 byte aligned, so include | ||
250 | * a basic sanity check | ||
251 | */ | ||
252 | BUG_ON(dst % 4); | ||
253 | BUG_ON(src % 4); | ||
254 | BUG_ON(size % 4); | ||
255 | |||
256 | /* Force a sync in case a previous config reset on this channel | ||
257 | * occurred. This is needed so subsequent writes to DMA registers | ||
258 | * are not spuriously lost/corrupted. | ||
259 | */ | ||
260 | __builtin_bfin_ssync(); | ||
261 | |||
262 | src_ch = 0; | ||
263 | /* Find an avalible memDMA channel */ | ||
264 | while (1) { | ||
265 | if (!src_ch || src_ch == (struct dma_register *)MDMA_S1_NEXT_DESC_PTR) { | ||
266 | dst_ch = (struct dma_register *)MDMA_D0_NEXT_DESC_PTR; | ||
267 | src_ch = (struct dma_register *)MDMA_S0_NEXT_DESC_PTR; | ||
268 | } else { | ||
269 | dst_ch = (struct dma_register *)MDMA_D1_NEXT_DESC_PTR; | ||
270 | src_ch = (struct dma_register *)MDMA_S1_NEXT_DESC_PTR; | ||
271 | } | ||
272 | |||
273 | if (!bfin_read16(&src_ch->cfg)) { | ||
274 | break; | ||
275 | } else { | ||
276 | if (bfin_read16(&src_ch->irq_status) & DMA_DONE) | ||
277 | bfin_write16(&src_ch->cfg, 0); | ||
278 | } | ||
279 | |||
280 | } | ||
281 | |||
282 | /* Destination */ | ||
283 | bfin_write32(&dst_ch->start_addr, dst); | ||
284 | bfin_write16(&dst_ch->x_count, size >> 2); | ||
285 | bfin_write16(&dst_ch->x_modify, 1 << 2); | ||
286 | bfin_write16(&dst_ch->irq_status, DMA_DONE | DMA_ERR); | ||
287 | |||
288 | /* Source */ | ||
289 | bfin_write32(&src_ch->start_addr, src); | ||
290 | bfin_write16(&src_ch->x_count, size >> 2); | ||
291 | bfin_write16(&src_ch->x_modify, 1 << 2); | ||
292 | bfin_write16(&src_ch->irq_status, DMA_DONE | DMA_ERR); | ||
293 | |||
294 | /* Enable */ | ||
295 | bfin_write16(&src_ch->cfg, DMAEN | WDSIZE_32); | ||
296 | bfin_write16(&dst_ch->cfg, WNR | DI_EN | DMAEN | WDSIZE_32); | ||
297 | |||
298 | /* Since we are atomic now, don't use the workaround ssync */ | ||
299 | __builtin_bfin_ssync(); | ||
300 | } | ||
301 | |||
302 | void __init early_dma_memcpy_done(void) | ||
303 | { | ||
304 | while ((bfin_read_MDMA_S0_CONFIG() && !(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)) || | ||
305 | (bfin_read_MDMA_S1_CONFIG() && !(bfin_read_MDMA_D1_IRQ_STATUS() & DMA_DONE))) | ||
306 | continue; | ||
307 | |||
308 | bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR); | ||
309 | bfin_write_MDMA_D1_IRQ_STATUS(DMA_DONE | DMA_ERR); | ||
310 | /* | ||
311 | * Now that DMA is done, we would normally flush cache, but | ||
312 | * i/d cache isn't running this early, so we don't bother, | ||
313 | * and just clear out the DMA channel for next time | ||
314 | */ | ||
315 | bfin_write_MDMA_S0_CONFIG(0); | ||
316 | bfin_write_MDMA_S1_CONFIG(0); | ||
317 | bfin_write_MDMA_D0_CONFIG(0); | ||
318 | bfin_write_MDMA_D1_CONFIG(0); | ||
319 | |||
320 | __builtin_bfin_ssync(); | ||
235 | } | 321 | } |
236 | 322 | ||
237 | /** | 323 | /** |
@@ -367,10 +453,10 @@ void *dma_memcpy(void *pdst, const void *psrc, size_t size) | |||
367 | unsigned long src = (unsigned long)psrc; | 453 | unsigned long src = (unsigned long)psrc; |
368 | size_t bulk, rest; | 454 | size_t bulk, rest; |
369 | 455 | ||
370 | if (bfin_addr_dcachable(src)) | 456 | if (bfin_addr_dcacheable(src)) |
371 | blackfin_dcache_flush_range(src, src + size); | 457 | blackfin_dcache_flush_range(src, src + size); |
372 | 458 | ||
373 | if (bfin_addr_dcachable(dst)) | 459 | if (bfin_addr_dcacheable(dst)) |
374 | blackfin_dcache_invalidate_range(dst, dst + size); | 460 | blackfin_dcache_invalidate_range(dst, dst + size); |
375 | 461 | ||
376 | bulk = size & ~0xffff; | 462 | bulk = size & ~0xffff; |
diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index a0678da40532..beffa00a93c3 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c | |||
@@ -313,15 +313,6 @@ inline void portmux_setup(unsigned short per) | |||
313 | # define portmux_setup(...) do { } while (0) | 313 | # define portmux_setup(...) do { } while (0) |
314 | #endif | 314 | #endif |
315 | 315 | ||
316 | static int __init bfin_gpio_init(void) | ||
317 | { | ||
318 | printk(KERN_INFO "Blackfin GPIO Controller\n"); | ||
319 | |||
320 | return 0; | ||
321 | } | ||
322 | arch_initcall(bfin_gpio_init); | ||
323 | |||
324 | |||
325 | #ifndef CONFIG_BF54x | 316 | #ifndef CONFIG_BF54x |
326 | /*********************************************************** | 317 | /*********************************************************** |
327 | * | 318 | * |
@@ -1021,15 +1012,6 @@ int bfin_gpio_irq_request(unsigned gpio, const char *label) | |||
1021 | 1012 | ||
1022 | local_irq_save_hw(flags); | 1013 | local_irq_save_hw(flags); |
1023 | 1014 | ||
1024 | if (unlikely(reserved_gpio_irq_map[gpio_bank(gpio)] & gpio_bit(gpio))) { | ||
1025 | if (system_state == SYSTEM_BOOTING) | ||
1026 | dump_stack(); | ||
1027 | printk(KERN_ERR | ||
1028 | "bfin-gpio: GPIO %d is already reserved as gpio-irq !\n", | ||
1029 | gpio); | ||
1030 | local_irq_restore_hw(flags); | ||
1031 | return -EBUSY; | ||
1032 | } | ||
1033 | if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) { | 1015 | if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) { |
1034 | if (system_state == SYSTEM_BOOTING) | 1016 | if (system_state == SYSTEM_BOOTING) |
1035 | dump_stack(); | 1017 | dump_stack(); |
diff --git a/arch/blackfin/kernel/bfin_ksyms.c b/arch/blackfin/kernel/bfin_ksyms.c index 01f917d58b59..aa05e638fb7c 100644 --- a/arch/blackfin/kernel/bfin_ksyms.c +++ b/arch/blackfin/kernel/bfin_ksyms.c | |||
@@ -16,7 +16,6 @@ EXPORT_SYMBOL(bfin_return_from_exception); | |||
16 | 16 | ||
17 | /* All the Blackfin cache functions: mach-common/cache.S */ | 17 | /* All the Blackfin cache functions: mach-common/cache.S */ |
18 | EXPORT_SYMBOL(blackfin_dcache_invalidate_range); | 18 | EXPORT_SYMBOL(blackfin_dcache_invalidate_range); |
19 | EXPORT_SYMBOL(blackfin_icache_dcache_flush_range); | ||
20 | EXPORT_SYMBOL(blackfin_icache_flush_range); | 19 | EXPORT_SYMBOL(blackfin_icache_flush_range); |
21 | EXPORT_SYMBOL(blackfin_dcache_flush_range); | 20 | EXPORT_SYMBOL(blackfin_dcache_flush_range); |
22 | EXPORT_SYMBOL(blackfin_dflush_page); | 21 | EXPORT_SYMBOL(blackfin_dflush_page); |
@@ -104,3 +103,8 @@ EXPORT_SYMBOL(__raw_smp_mark_barrier_asm); | |||
104 | EXPORT_SYMBOL(__raw_smp_check_barrier_asm); | 103 | EXPORT_SYMBOL(__raw_smp_check_barrier_asm); |
105 | #endif | 104 | #endif |
106 | #endif | 105 | #endif |
106 | |||
107 | #ifdef CONFIG_FUNCTION_TRACER | ||
108 | extern void _mcount(void); | ||
109 | EXPORT_SYMBOL(_mcount); | ||
110 | #endif | ||
diff --git a/arch/blackfin/kernel/cplb-mpu/cacheinit.c b/arch/blackfin/kernel/cplb-mpu/cacheinit.c index c6ff947f9d37..d5a86c3017f7 100644 --- a/arch/blackfin/kernel/cplb-mpu/cacheinit.c +++ b/arch/blackfin/kernel/cplb-mpu/cacheinit.c | |||
@@ -55,7 +55,14 @@ void __cpuinit bfin_dcache_init(struct cplb_entry *dcplb_tbl) | |||
55 | } | 55 | } |
56 | 56 | ||
57 | ctrl = bfin_read_DMEM_CONTROL(); | 57 | ctrl = bfin_read_DMEM_CONTROL(); |
58 | ctrl |= DMEM_CNTR; | 58 | |
59 | /* | ||
60 | * Anomaly notes: | ||
61 | * 05000287 - We implement workaround #2 - Change the DMEM_CONTROL | ||
62 | * register, so that the port preferences for DAG0 and DAG1 are set | ||
63 | * to port B | ||
64 | */ | ||
65 | ctrl |= DMEM_CNTR | PORT_PREF0 | (ANOMALY_05000287 ? PORT_PREF1 : 0); | ||
59 | bfin_write_DMEM_CONTROL(ctrl); | 66 | bfin_write_DMEM_CONTROL(ctrl); |
60 | SSYNC(); | 67 | SSYNC(); |
61 | } | 68 | } |
diff --git a/arch/blackfin/kernel/cplb-mpu/cplbinit.c b/arch/blackfin/kernel/cplb-mpu/cplbinit.c index 3e329a6ce041..c006a44527bf 100644 --- a/arch/blackfin/kernel/cplb-mpu/cplbinit.c +++ b/arch/blackfin/kernel/cplb-mpu/cplbinit.c | |||
@@ -64,7 +64,7 @@ void __init generate_cplb_tables_cpu(unsigned int cpu) | |||
64 | dcplb_tbl[cpu][i_d++].data = SDRAM_OOPS | PAGE_SIZE_1KB; | 64 | dcplb_tbl[cpu][i_d++].data = SDRAM_OOPS | PAGE_SIZE_1KB; |
65 | 65 | ||
66 | icplb_tbl[cpu][i_i].addr = 0; | 66 | icplb_tbl[cpu][i_i].addr = 0; |
67 | icplb_tbl[cpu][i_i++].data = i_cache | CPLB_USER_RD | PAGE_SIZE_1KB; | 67 | icplb_tbl[cpu][i_i++].data = CPLB_VALID | i_cache | CPLB_USER_RD | PAGE_SIZE_1KB; |
68 | 68 | ||
69 | /* Cover kernel memory with 4M pages. */ | 69 | /* Cover kernel memory with 4M pages. */ |
70 | addr = 0; | 70 | addr = 0; |
diff --git a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c index 87463ce87f5a..784923e52a9a 100644 --- a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c +++ b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c | |||
@@ -151,7 +151,7 @@ static noinline int dcplb_miss(unsigned int cpu) | |||
151 | 151 | ||
152 | d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB; | 152 | d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB; |
153 | #ifdef CONFIG_BFIN_DCACHE | 153 | #ifdef CONFIG_BFIN_DCACHE |
154 | if (bfin_addr_dcachable(addr)) { | 154 | if (bfin_addr_dcacheable(addr)) { |
155 | d_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND; | 155 | d_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND; |
156 | #ifdef CONFIG_BFIN_WT | 156 | #ifdef CONFIG_BFIN_WT |
157 | d_data |= CPLB_L1_AOW | CPLB_WT; | 157 | d_data |= CPLB_L1_AOW | CPLB_WT; |
diff --git a/arch/blackfin/kernel/cplb-nompu/cacheinit.c b/arch/blackfin/kernel/cplb-nompu/cacheinit.c index c6ff947f9d37..d5a86c3017f7 100644 --- a/arch/blackfin/kernel/cplb-nompu/cacheinit.c +++ b/arch/blackfin/kernel/cplb-nompu/cacheinit.c | |||
@@ -55,7 +55,14 @@ void __cpuinit bfin_dcache_init(struct cplb_entry *dcplb_tbl) | |||
55 | } | 55 | } |
56 | 56 | ||
57 | ctrl = bfin_read_DMEM_CONTROL(); | 57 | ctrl = bfin_read_DMEM_CONTROL(); |
58 | ctrl |= DMEM_CNTR; | 58 | |
59 | /* | ||
60 | * Anomaly notes: | ||
61 | * 05000287 - We implement workaround #2 - Change the DMEM_CONTROL | ||
62 | * register, so that the port preferences for DAG0 and DAG1 are set | ||
63 | * to port B | ||
64 | */ | ||
65 | ctrl |= DMEM_CNTR | PORT_PREF0 | (ANOMALY_05000287 ? PORT_PREF1 : 0); | ||
59 | bfin_write_DMEM_CONTROL(ctrl); | 66 | bfin_write_DMEM_CONTROL(ctrl); |
60 | SSYNC(); | 67 | SSYNC(); |
61 | } | 68 | } |
diff --git a/arch/blackfin/kernel/cplb-nompu/cplbmgr.c b/arch/blackfin/kernel/cplb-nompu/cplbmgr.c index 8cbb47c7b663..12b030842fdb 100644 --- a/arch/blackfin/kernel/cplb-nompu/cplbmgr.c +++ b/arch/blackfin/kernel/cplb-nompu/cplbmgr.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <asm/cplbinit.h> | 28 | #include <asm/cplbinit.h> |
29 | #include <asm/cplb.h> | 29 | #include <asm/cplb.h> |
30 | #include <asm/mmu_context.h> | 30 | #include <asm/mmu_context.h> |
31 | #include <asm/traps.h> | ||
31 | 32 | ||
32 | /* | 33 | /* |
33 | * WARNING | 34 | * WARNING |
@@ -100,28 +101,6 @@ static inline void write_icplb_data(int cpu, int idx, unsigned long data, | |||
100 | #endif | 101 | #endif |
101 | } | 102 | } |
102 | 103 | ||
103 | /* | ||
104 | * Given the contents of the status register, return the index of the | ||
105 | * CPLB that caused the fault. | ||
106 | */ | ||
107 | static inline int faulting_cplb_index(int status) | ||
108 | { | ||
109 | int signbits = __builtin_bfin_norm_fr1x32(status & 0xFFFF); | ||
110 | return 30 - signbits; | ||
111 | } | ||
112 | |||
113 | /* | ||
114 | * Given the contents of the status register and the DCPLB_DATA contents, | ||
115 | * return true if a write access should be permitted. | ||
116 | */ | ||
117 | static inline int write_permitted(int status, unsigned long data) | ||
118 | { | ||
119 | if (status & FAULT_USERSUPV) | ||
120 | return !!(data & CPLB_SUPV_WR); | ||
121 | else | ||
122 | return !!(data & CPLB_USER_WR); | ||
123 | } | ||
124 | |||
125 | /* Counters to implement round-robin replacement. */ | 104 | /* Counters to implement round-robin replacement. */ |
126 | static int icplb_rr_index[NR_CPUS] PDT_ATTR; | 105 | static int icplb_rr_index[NR_CPUS] PDT_ATTR; |
127 | static int dcplb_rr_index[NR_CPUS] PDT_ATTR; | 106 | static int dcplb_rr_index[NR_CPUS] PDT_ATTR; |
@@ -245,43 +224,16 @@ MGR_ATTR static int dcplb_miss(int cpu) | |||
245 | return CPLB_RELOADED; | 224 | return CPLB_RELOADED; |
246 | } | 225 | } |
247 | 226 | ||
248 | MGR_ATTR static noinline int dcplb_protection_fault(int cpu) | ||
249 | { | ||
250 | int status = bfin_read_DCPLB_STATUS(); | ||
251 | |||
252 | nr_dcplb_prot[cpu]++; | ||
253 | |||
254 | if (likely(status & FAULT_RW)) { | ||
255 | int idx = faulting_cplb_index(status); | ||
256 | unsigned long regaddr = DCPLB_DATA0 + idx * 4; | ||
257 | unsigned long data = bfin_read32(regaddr); | ||
258 | |||
259 | /* Check if fault is to dirty a clean page */ | ||
260 | if (!(data & CPLB_WT) && !(data & CPLB_DIRTY) && | ||
261 | write_permitted(status, data)) { | ||
262 | |||
263 | dcplb_tbl[cpu][idx].data = data; | ||
264 | bfin_write32(regaddr, data); | ||
265 | return CPLB_RELOADED; | ||
266 | } | ||
267 | } | ||
268 | |||
269 | return CPLB_PROT_VIOL; | ||
270 | } | ||
271 | |||
272 | MGR_ATTR int cplb_hdr(int seqstat, struct pt_regs *regs) | 227 | MGR_ATTR int cplb_hdr(int seqstat, struct pt_regs *regs) |
273 | { | 228 | { |
274 | int cause = seqstat & 0x3f; | 229 | int cause = seqstat & 0x3f; |
275 | unsigned int cpu = smp_processor_id(); | 230 | unsigned int cpu = smp_processor_id(); |
276 | switch (cause) { | 231 | switch (cause) { |
277 | case 0x2C: | 232 | case VEC_CPLB_I_M: |
278 | return icplb_miss(cpu); | 233 | return icplb_miss(cpu); |
279 | case 0x26: | 234 | case VEC_CPLB_M: |
280 | return dcplb_miss(cpu); | 235 | return dcplb_miss(cpu); |
281 | default: | 236 | default: |
282 | if (unlikely(cause == 0x23)) | ||
283 | return dcplb_protection_fault(cpu); | ||
284 | |||
285 | return CPLB_UNKNOWN_ERR; | 237 | return CPLB_UNKNOWN_ERR; |
286 | } | 238 | } |
287 | } | 239 | } |
diff --git a/arch/blackfin/kernel/early_printk.c b/arch/blackfin/kernel/early_printk.c index c8ad051742e2..2ab56811841c 100644 --- a/arch/blackfin/kernel/early_printk.c +++ b/arch/blackfin/kernel/early_printk.c | |||
@@ -178,25 +178,15 @@ int __init setup_early_printk(char *buf) | |||
178 | 178 | ||
179 | asmlinkage void __init init_early_exception_vectors(void) | 179 | asmlinkage void __init init_early_exception_vectors(void) |
180 | { | 180 | { |
181 | u32 evt; | ||
181 | SSYNC(); | 182 | SSYNC(); |
182 | 183 | ||
183 | /* cannot program in software: | 184 | /* cannot program in software: |
184 | * evt0 - emulation (jtag) | 185 | * evt0 - emulation (jtag) |
185 | * evt1 - reset | 186 | * evt1 - reset |
186 | */ | 187 | */ |
187 | bfin_write_EVT2(early_trap); | 188 | for (evt = EVT2; evt <= EVT15; evt += 4) |
188 | bfin_write_EVT3(early_trap); | 189 | bfin_write32(evt, early_trap); |
189 | bfin_write_EVT5(early_trap); | ||
190 | bfin_write_EVT6(early_trap); | ||
191 | bfin_write_EVT7(early_trap); | ||
192 | bfin_write_EVT8(early_trap); | ||
193 | bfin_write_EVT9(early_trap); | ||
194 | bfin_write_EVT10(early_trap); | ||
195 | bfin_write_EVT11(early_trap); | ||
196 | bfin_write_EVT12(early_trap); | ||
197 | bfin_write_EVT13(early_trap); | ||
198 | bfin_write_EVT14(early_trap); | ||
199 | bfin_write_EVT15(early_trap); | ||
200 | CSYNC(); | 190 | CSYNC(); |
201 | 191 | ||
202 | /* Set all the return from interrupt, exception, NMI to a known place | 192 | /* Set all the return from interrupt, exception, NMI to a known place |
@@ -212,11 +202,15 @@ asmlinkage void __init init_early_exception_vectors(void) | |||
212 | asmlinkage void __init early_trap_c(struct pt_regs *fp, void *retaddr) | 202 | asmlinkage void __init early_trap_c(struct pt_regs *fp, void *retaddr) |
213 | { | 203 | { |
214 | /* This can happen before the uart is initialized, so initialize | 204 | /* This can happen before the uart is initialized, so initialize |
215 | * the UART now | 205 | * the UART now (but only if we are running on the processor we think |
206 | * we are compiled for - otherwise we write to MMRs that don't exist, | ||
207 | * and cause other problems. Nothing comes out the UART, but it does | ||
208 | * end up in the __buf_log. | ||
216 | */ | 209 | */ |
217 | if (likely(early_console == NULL)) | 210 | if (likely(early_console == NULL) && CPUID == bfin_cpuid()) |
218 | setup_early_printk(DEFAULT_EARLY_PORT); | 211 | setup_early_printk(DEFAULT_EARLY_PORT); |
219 | 212 | ||
213 | printk(KERN_EMERG "Early panic\n"); | ||
220 | dump_bfin_mem(fp); | 214 | dump_bfin_mem(fp); |
221 | show_regs(fp); | 215 | show_regs(fp); |
222 | dump_bfin_trace_buffer(); | 216 | dump_bfin_trace_buffer(); |
diff --git a/arch/blackfin/kernel/ftrace-entry.S b/arch/blackfin/kernel/ftrace-entry.S new file mode 100644 index 000000000000..6980b7a0615d --- /dev/null +++ b/arch/blackfin/kernel/ftrace-entry.S | |||
@@ -0,0 +1,140 @@ | |||
1 | /* | ||
2 | * mcount and friends -- ftrace stuff | ||
3 | * | ||
4 | * Copyright (C) 2009 Analog Devices Inc. | ||
5 | * Licensed under the GPL-2 or later. | ||
6 | */ | ||
7 | |||
8 | #include <linux/linkage.h> | ||
9 | #include <asm/ftrace.h> | ||
10 | |||
11 | .text | ||
12 | |||
13 | /* GCC will have called us before setting up the function prologue, so we | ||
14 | * can clobber the normal scratch registers, but we need to make sure to | ||
15 | * save/restore the registers used for argument passing (R0-R2) in case | ||
16 | * the profiled function is using them. With data registers, R3 is the | ||
17 | * only one we can blow away. With pointer registers, we have P0-P2. | ||
18 | * | ||
19 | * Upon entry, the RETS will point to the top of the current profiled | ||
20 | * function. And since GCC setup the frame for us, the previous function | ||
21 | * will be waiting there. mmmm pie. | ||
22 | */ | ||
23 | ENTRY(__mcount) | ||
24 | /* save third function arg early so we can do testing below */ | ||
25 | [--sp] = r2; | ||
26 | |||
27 | /* load the function pointer to the tracer */ | ||
28 | p0.l = _ftrace_trace_function; | ||
29 | p0.h = _ftrace_trace_function; | ||
30 | r3 = [p0]; | ||
31 | |||
32 | /* optional micro optimization: don't call the stub tracer */ | ||
33 | r2.l = _ftrace_stub; | ||
34 | r2.h = _ftrace_stub; | ||
35 | cc = r2 == r3; | ||
36 | if ! cc jump .Ldo_trace; | ||
37 | |||
38 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
39 | /* if the ftrace_graph_return function pointer is not set to | ||
40 | * the ftrace_stub entry, call prepare_ftrace_return(). | ||
41 | */ | ||
42 | p0.l = _ftrace_graph_return; | ||
43 | p0.h = _ftrace_graph_return; | ||
44 | r3 = [p0]; | ||
45 | cc = r2 == r3; | ||
46 | if ! cc jump _ftrace_graph_caller; | ||
47 | |||
48 | /* similarly, if the ftrace_graph_entry function pointer is not | ||
49 | * set to the ftrace_graph_entry_stub entry, ... | ||
50 | */ | ||
51 | p0.l = _ftrace_graph_entry; | ||
52 | p0.h = _ftrace_graph_entry; | ||
53 | r2.l = _ftrace_graph_entry_stub; | ||
54 | r2.h = _ftrace_graph_entry_stub; | ||
55 | r3 = [p0]; | ||
56 | cc = r2 == r3; | ||
57 | if ! cc jump _ftrace_graph_caller; | ||
58 | #endif | ||
59 | |||
60 | r2 = [sp++]; | ||
61 | rts; | ||
62 | |||
63 | .Ldo_trace: | ||
64 | |||
65 | /* save first/second function arg and the return register */ | ||
66 | [--sp] = r0; | ||
67 | [--sp] = r1; | ||
68 | [--sp] = rets; | ||
69 | |||
70 | /* setup the tracer function */ | ||
71 | p0 = r3; | ||
72 | |||
73 | /* tracer(ulong frompc, ulong selfpc): | ||
74 | * frompc: the pc that did the call to ... | ||
75 | * selfpc: ... this location | ||
76 | * the selfpc itself will need adjusting for the mcount call | ||
77 | */ | ||
78 | r1 = rets; | ||
79 | r0 = [fp + 4]; | ||
80 | r1 += -MCOUNT_INSN_SIZE; | ||
81 | |||
82 | /* call the tracer */ | ||
83 | call (p0); | ||
84 | |||
85 | /* restore state and get out of dodge */ | ||
86 | .Lfinish_trace: | ||
87 | rets = [sp++]; | ||
88 | r1 = [sp++]; | ||
89 | r0 = [sp++]; | ||
90 | r2 = [sp++]; | ||
91 | |||
92 | .globl _ftrace_stub | ||
93 | _ftrace_stub: | ||
94 | rts; | ||
95 | ENDPROC(__mcount) | ||
96 | |||
97 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
98 | /* The prepare_ftrace_return() function is similar to the trace function | ||
99 | * except it takes a pointer to the location of the frompc. This is so | ||
100 | * the prepare_ftrace_return() can hijack it temporarily for probing | ||
101 | * purposes. | ||
102 | */ | ||
103 | ENTRY(_ftrace_graph_caller) | ||
104 | /* save first/second function arg and the return register */ | ||
105 | [--sp] = r0; | ||
106 | [--sp] = r1; | ||
107 | [--sp] = rets; | ||
108 | |||
109 | r0 = fp; | ||
110 | r1 = rets; | ||
111 | r0 += 4; | ||
112 | r1 += -MCOUNT_INSN_SIZE; | ||
113 | call _prepare_ftrace_return; | ||
114 | |||
115 | jump .Lfinish_trace; | ||
116 | ENDPROC(_ftrace_graph_caller) | ||
117 | |||
118 | /* Undo the rewrite caused by ftrace_graph_caller(). The common function | ||
119 | * ftrace_return_to_handler() will return the original rets so we can | ||
120 | * restore it and be on our way. | ||
121 | */ | ||
122 | ENTRY(_return_to_handler) | ||
123 | /* make sure original return values are saved */ | ||
124 | [--sp] = p0; | ||
125 | [--sp] = r0; | ||
126 | [--sp] = r1; | ||
127 | |||
128 | /* get original return address */ | ||
129 | call _ftrace_return_to_handler; | ||
130 | rets = r0; | ||
131 | |||
132 | /* anomaly 05000371 - make sure we have at least three instructions | ||
133 | * between rets setting and the return | ||
134 | */ | ||
135 | r1 = [sp++]; | ||
136 | r0 = [sp++]; | ||
137 | p0 = [sp++]; | ||
138 | rts; | ||
139 | ENDPROC(_return_to_handler) | ||
140 | #endif | ||
diff --git a/arch/blackfin/kernel/ftrace.c b/arch/blackfin/kernel/ftrace.c new file mode 100644 index 000000000000..905bfc40a00b --- /dev/null +++ b/arch/blackfin/kernel/ftrace.c | |||
@@ -0,0 +1,42 @@ | |||
1 | /* | ||
2 | * ftrace graph code | ||
3 | * | ||
4 | * Copyright (C) 2009 Analog Devices Inc. | ||
5 | * Licensed under the GPL-2 or later. | ||
6 | */ | ||
7 | |||
8 | #include <linux/ftrace.h> | ||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/sched.h> | ||
11 | #include <asm/atomic.h> | ||
12 | |||
13 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
14 | |||
15 | /* | ||
16 | * Hook the return address and push it in the stack of return addrs | ||
17 | * in current thread info. | ||
18 | */ | ||
19 | void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) | ||
20 | { | ||
21 | struct ftrace_graph_ent trace; | ||
22 | unsigned long return_hooker = (unsigned long)&return_to_handler; | ||
23 | |||
24 | if (unlikely(atomic_read(¤t->tracing_graph_pause))) | ||
25 | return; | ||
26 | |||
27 | if (ftrace_push_return_trace(*parent, self_addr, &trace.depth) == -EBUSY) | ||
28 | return; | ||
29 | |||
30 | trace.func = self_addr; | ||
31 | |||
32 | /* Only trace if the calling function expects to */ | ||
33 | if (!ftrace_graph_entry(&trace)) { | ||
34 | current->curr_ret_stack--; | ||
35 | return; | ||
36 | } | ||
37 | |||
38 | /* all is well in the world ! hijack RETS ... */ | ||
39 | *parent = return_hooker; | ||
40 | } | ||
41 | |||
42 | #endif | ||
diff --git a/arch/blackfin/kernel/gptimers.c b/arch/blackfin/kernel/gptimers.c index 3a3e9615b002..7281a91d26b5 100644 --- a/arch/blackfin/kernel/gptimers.c +++ b/arch/blackfin/kernel/gptimers.c | |||
@@ -189,10 +189,10 @@ void set_gptimer_status(int group, uint32_t value) | |||
189 | } | 189 | } |
190 | EXPORT_SYMBOL(set_gptimer_status); | 190 | EXPORT_SYMBOL(set_gptimer_status); |
191 | 191 | ||
192 | uint16_t get_gptimer_intr(int timer_id) | 192 | int get_gptimer_intr(int timer_id) |
193 | { | 193 | { |
194 | tassert(timer_id < MAX_BLACKFIN_GPTIMERS); | 194 | tassert(timer_id < MAX_BLACKFIN_GPTIMERS); |
195 | return (group_regs[BFIN_TIMER_OCTET(timer_id)]->status & timil_mask[timer_id]) ? 1 : 0; | 195 | return !!(group_regs[BFIN_TIMER_OCTET(timer_id)]->status & timil_mask[timer_id]); |
196 | } | 196 | } |
197 | EXPORT_SYMBOL(get_gptimer_intr); | 197 | EXPORT_SYMBOL(get_gptimer_intr); |
198 | 198 | ||
@@ -203,10 +203,10 @@ void clear_gptimer_intr(int timer_id) | |||
203 | } | 203 | } |
204 | EXPORT_SYMBOL(clear_gptimer_intr); | 204 | EXPORT_SYMBOL(clear_gptimer_intr); |
205 | 205 | ||
206 | uint16_t get_gptimer_over(int timer_id) | 206 | int get_gptimer_over(int timer_id) |
207 | { | 207 | { |
208 | tassert(timer_id < MAX_BLACKFIN_GPTIMERS); | 208 | tassert(timer_id < MAX_BLACKFIN_GPTIMERS); |
209 | return (group_regs[BFIN_TIMER_OCTET(timer_id)]->status & tovf_mask[timer_id]) ? 1 : 0; | 209 | return !!(group_regs[BFIN_TIMER_OCTET(timer_id)]->status & tovf_mask[timer_id]); |
210 | } | 210 | } |
211 | EXPORT_SYMBOL(get_gptimer_over); | 211 | EXPORT_SYMBOL(get_gptimer_over); |
212 | 212 | ||
@@ -217,6 +217,13 @@ void clear_gptimer_over(int timer_id) | |||
217 | } | 217 | } |
218 | EXPORT_SYMBOL(clear_gptimer_over); | 218 | EXPORT_SYMBOL(clear_gptimer_over); |
219 | 219 | ||
220 | int get_gptimer_run(int timer_id) | ||
221 | { | ||
222 | tassert(timer_id < MAX_BLACKFIN_GPTIMERS); | ||
223 | return !!(group_regs[BFIN_TIMER_OCTET(timer_id)]->status & trun_mask[timer_id]); | ||
224 | } | ||
225 | EXPORT_SYMBOL(get_gptimer_run); | ||
226 | |||
220 | void set_gptimer_config(int timer_id, uint16_t config) | 227 | void set_gptimer_config(int timer_id, uint16_t config) |
221 | { | 228 | { |
222 | tassert(timer_id < MAX_BLACKFIN_GPTIMERS); | 229 | tassert(timer_id < MAX_BLACKFIN_GPTIMERS); |
@@ -244,7 +251,7 @@ void enable_gptimers(uint16_t mask) | |||
244 | } | 251 | } |
245 | EXPORT_SYMBOL(enable_gptimers); | 252 | EXPORT_SYMBOL(enable_gptimers); |
246 | 253 | ||
247 | void disable_gptimers(uint16_t mask) | 254 | static void _disable_gptimers(uint16_t mask) |
248 | { | 255 | { |
249 | int i; | 256 | int i; |
250 | uint16_t m = mask; | 257 | uint16_t m = mask; |
@@ -253,6 +260,12 @@ void disable_gptimers(uint16_t mask) | |||
253 | group_regs[i]->disable = m & 0xFF; | 260 | group_regs[i]->disable = m & 0xFF; |
254 | m >>= 8; | 261 | m >>= 8; |
255 | } | 262 | } |
263 | } | ||
264 | |||
265 | void disable_gptimers(uint16_t mask) | ||
266 | { | ||
267 | int i; | ||
268 | _disable_gptimers(mask); | ||
256 | for (i = 0; i < MAX_BLACKFIN_GPTIMERS; ++i) | 269 | for (i = 0; i < MAX_BLACKFIN_GPTIMERS; ++i) |
257 | if (mask & (1 << i)) | 270 | if (mask & (1 << i)) |
258 | group_regs[BFIN_TIMER_OCTET(i)]->status |= trun_mask[i]; | 271 | group_regs[BFIN_TIMER_OCTET(i)]->status |= trun_mask[i]; |
@@ -260,6 +273,13 @@ void disable_gptimers(uint16_t mask) | |||
260 | } | 273 | } |
261 | EXPORT_SYMBOL(disable_gptimers); | 274 | EXPORT_SYMBOL(disable_gptimers); |
262 | 275 | ||
276 | void disable_gptimers_sync(uint16_t mask) | ||
277 | { | ||
278 | _disable_gptimers(mask); | ||
279 | SSYNC(); | ||
280 | } | ||
281 | EXPORT_SYMBOL(disable_gptimers_sync); | ||
282 | |||
263 | void set_gptimer_pulse_hi(int timer_id) | 283 | void set_gptimer_pulse_hi(int timer_id) |
264 | { | 284 | { |
265 | tassert(timer_id < MAX_BLACKFIN_GPTIMERS); | 285 | tassert(timer_id < MAX_BLACKFIN_GPTIMERS); |
diff --git a/arch/blackfin/kernel/ipipe.c b/arch/blackfin/kernel/ipipe.c index a5de8d45424c..d8cde1fc5cb9 100644 --- a/arch/blackfin/kernel/ipipe.c +++ b/arch/blackfin/kernel/ipipe.c | |||
@@ -99,7 +99,7 @@ void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs) | |||
99 | * interrupt. | 99 | * interrupt. |
100 | */ | 100 | */ |
101 | m_ack = (regs == NULL || irq == IRQ_SYSTMR || irq == IRQ_CORETMR); | 101 | m_ack = (regs == NULL || irq == IRQ_SYSTMR || irq == IRQ_CORETMR); |
102 | this_domain = ipipe_current_domain; | 102 | this_domain = __ipipe_current_domain; |
103 | 103 | ||
104 | if (unlikely(test_bit(IPIPE_STICKY_FLAG, &this_domain->irqs[irq].control))) | 104 | if (unlikely(test_bit(IPIPE_STICKY_FLAG, &this_domain->irqs[irq].control))) |
105 | head = &this_domain->p_link; | 105 | head = &this_domain->p_link; |
@@ -167,7 +167,7 @@ int __ipipe_check_root(void) | |||
167 | void __ipipe_enable_irqdesc(struct ipipe_domain *ipd, unsigned irq) | 167 | void __ipipe_enable_irqdesc(struct ipipe_domain *ipd, unsigned irq) |
168 | { | 168 | { |
169 | struct irq_desc *desc = irq_to_desc(irq); | 169 | struct irq_desc *desc = irq_to_desc(irq); |
170 | int prio = desc->ic_prio; | 170 | int prio = __ipipe_get_irq_priority(irq); |
171 | 171 | ||
172 | desc->depth = 0; | 172 | desc->depth = 0; |
173 | if (ipd != &ipipe_root && | 173 | if (ipd != &ipipe_root && |
@@ -178,8 +178,7 @@ EXPORT_SYMBOL(__ipipe_enable_irqdesc); | |||
178 | 178 | ||
179 | void __ipipe_disable_irqdesc(struct ipipe_domain *ipd, unsigned irq) | 179 | void __ipipe_disable_irqdesc(struct ipipe_domain *ipd, unsigned irq) |
180 | { | 180 | { |
181 | struct irq_desc *desc = irq_to_desc(irq); | 181 | int prio = __ipipe_get_irq_priority(irq); |
182 | int prio = desc->ic_prio; | ||
183 | 182 | ||
184 | if (ipd != &ipipe_root && | 183 | if (ipd != &ipipe_root && |
185 | atomic_dec_and_test(&__ipipe_irq_lvdepth[prio])) | 184 | atomic_dec_and_test(&__ipipe_irq_lvdepth[prio])) |
@@ -213,7 +212,9 @@ void __ipipe_unstall_root_raw(void) | |||
213 | 212 | ||
214 | int __ipipe_syscall_root(struct pt_regs *regs) | 213 | int __ipipe_syscall_root(struct pt_regs *regs) |
215 | { | 214 | { |
215 | struct ipipe_percpu_domain_data *p; | ||
216 | unsigned long flags; | 216 | unsigned long flags; |
217 | int ret; | ||
217 | 218 | ||
218 | /* | 219 | /* |
219 | * We need to run the IRQ tail hook whenever we don't | 220 | * We need to run the IRQ tail hook whenever we don't |
@@ -232,29 +233,31 @@ int __ipipe_syscall_root(struct pt_regs *regs) | |||
232 | /* | 233 | /* |
233 | * This routine either returns: | 234 | * This routine either returns: |
234 | * 0 -- if the syscall is to be passed to Linux; | 235 | * 0 -- if the syscall is to be passed to Linux; |
235 | * 1 -- if the syscall should not be passed to Linux, and no | 236 | * >0 -- if the syscall should not be passed to Linux, and no |
236 | * tail work should be performed; | 237 | * tail work should be performed; |
237 | * -1 -- if the syscall should not be passed to Linux but the | 238 | * <0 -- if the syscall should not be passed to Linux but the |
238 | * tail work has to be performed (for handling signals etc). | 239 | * tail work has to be performed (for handling signals etc). |
239 | */ | 240 | */ |
240 | 241 | ||
241 | if (__ipipe_event_monitored_p(IPIPE_EVENT_SYSCALL) && | 242 | if (!__ipipe_event_monitored_p(IPIPE_EVENT_SYSCALL)) |
242 | __ipipe_dispatch_event(IPIPE_EVENT_SYSCALL, regs) > 0) { | 243 | return 0; |
243 | if (ipipe_root_domain_p && !in_atomic()) { | 244 | |
244 | /* | 245 | ret = __ipipe_dispatch_event(IPIPE_EVENT_SYSCALL, regs); |
245 | * Sync pending VIRQs before _TIF_NEED_RESCHED | 246 | |
246 | * is tested. | 247 | local_irq_save_hw(flags); |
247 | */ | 248 | |
248 | local_irq_save_hw(flags); | 249 | if (!__ipipe_root_domain_p) { |
249 | if ((ipipe_root_cpudom_var(irqpend_himask) & IPIPE_IRQMASK_VIRT) != 0) | 250 | local_irq_restore_hw(flags); |
250 | __ipipe_sync_pipeline(IPIPE_IRQMASK_VIRT); | ||
251 | local_irq_restore_hw(flags); | ||
252 | return -1; | ||
253 | } | ||
254 | return 1; | 251 | return 1; |
255 | } | 252 | } |
256 | 253 | ||
257 | return 0; | 254 | p = ipipe_root_cpudom_ptr(); |
255 | if ((p->irqpend_himask & IPIPE_IRQMASK_VIRT) != 0) | ||
256 | __ipipe_sync_pipeline(IPIPE_IRQMASK_VIRT); | ||
257 | |||
258 | local_irq_restore_hw(flags); | ||
259 | |||
260 | return -ret; | ||
258 | } | 261 | } |
259 | 262 | ||
260 | unsigned long ipipe_critical_enter(void (*syncfn) (void)) | 263 | unsigned long ipipe_critical_enter(void (*syncfn) (void)) |
@@ -310,12 +313,16 @@ int ipipe_trigger_irq(unsigned irq) | |||
310 | 313 | ||
311 | asmlinkage void __ipipe_sync_root(void) | 314 | asmlinkage void __ipipe_sync_root(void) |
312 | { | 315 | { |
316 | void (*irq_tail_hook)(void) = (void (*)(void))__ipipe_irq_tail_hook; | ||
313 | unsigned long flags; | 317 | unsigned long flags; |
314 | 318 | ||
315 | BUG_ON(irqs_disabled()); | 319 | BUG_ON(irqs_disabled()); |
316 | 320 | ||
317 | local_irq_save_hw(flags); | 321 | local_irq_save_hw(flags); |
318 | 322 | ||
323 | if (irq_tail_hook) | ||
324 | irq_tail_hook(); | ||
325 | |||
319 | clear_thread_flag(TIF_IRQ_SYNC); | 326 | clear_thread_flag(TIF_IRQ_SYNC); |
320 | 327 | ||
321 | if (ipipe_root_cpudom_var(irqpend_himask) != 0) | 328 | if (ipipe_root_cpudom_var(irqpend_himask) != 0) |
@@ -326,9 +333,7 @@ asmlinkage void __ipipe_sync_root(void) | |||
326 | 333 | ||
327 | void ___ipipe_sync_pipeline(unsigned long syncmask) | 334 | void ___ipipe_sync_pipeline(unsigned long syncmask) |
328 | { | 335 | { |
329 | struct ipipe_domain *ipd = ipipe_current_domain; | 336 | if (__ipipe_root_domain_p) { |
330 | |||
331 | if (ipd == ipipe_root_domain) { | ||
332 | if (test_bit(IPIPE_SYNCDEFER_FLAG, &ipipe_root_cpudom_var(status))) | 337 | if (test_bit(IPIPE_SYNCDEFER_FLAG, &ipipe_root_cpudom_var(status))) |
333 | return; | 338 | return; |
334 | } | 339 | } |
diff --git a/arch/blackfin/kernel/irqchip.c b/arch/blackfin/kernel/irqchip.c index 401bd32aa499..6e31e935bb31 100644 --- a/arch/blackfin/kernel/irqchip.c +++ b/arch/blackfin/kernel/irqchip.c | |||
@@ -59,12 +59,14 @@ static struct irq_chip bad_chip = { | |||
59 | .unmask = dummy_mask_unmask_irq, | 59 | .unmask = dummy_mask_unmask_irq, |
60 | }; | 60 | }; |
61 | 61 | ||
62 | static int bad_stats; | ||
62 | static struct irq_desc bad_irq_desc = { | 63 | static struct irq_desc bad_irq_desc = { |
63 | .status = IRQ_DISABLED, | 64 | .status = IRQ_DISABLED, |
64 | .chip = &bad_chip, | 65 | .chip = &bad_chip, |
65 | .handle_irq = handle_bad_irq, | 66 | .handle_irq = handle_bad_irq, |
66 | .depth = 1, | 67 | .depth = 1, |
67 | .lock = __SPIN_LOCK_UNLOCKED(irq_desc->lock), | 68 | .lock = __SPIN_LOCK_UNLOCKED(irq_desc->lock), |
69 | .kstat_irqs = &bad_stats, | ||
68 | #ifdef CONFIG_SMP | 70 | #ifdef CONFIG_SMP |
69 | .affinity = CPU_MASK_ALL | 71 | .affinity = CPU_MASK_ALL |
70 | #endif | 72 | #endif |
diff --git a/arch/blackfin/kernel/kgdb.c b/arch/blackfin/kernel/kgdb.c index b163f6d3330d..da28f796ad78 100644 --- a/arch/blackfin/kernel/kgdb.c +++ b/arch/blackfin/kernel/kgdb.c | |||
@@ -466,7 +466,7 @@ static int validate_memory_access_address(unsigned long addr, int size) | |||
466 | int cpu = raw_smp_processor_id(); | 466 | int cpu = raw_smp_processor_id(); |
467 | 467 | ||
468 | if (size < 0) | 468 | if (size < 0) |
469 | return EFAULT; | 469 | return -EFAULT; |
470 | if (addr >= 0x1000 && (addr + size) <= physical_mem_end) | 470 | if (addr >= 0x1000 && (addr + size) <= physical_mem_end) |
471 | return 0; | 471 | return 0; |
472 | if (addr >= SYSMMR_BASE) | 472 | if (addr >= SYSMMR_BASE) |
@@ -498,7 +498,7 @@ static int validate_memory_access_address(unsigned long addr, int size) | |||
498 | if (IN_MEM(addr, size, L2_START, L2_LENGTH)) | 498 | if (IN_MEM(addr, size, L2_START, L2_LENGTH)) |
499 | return 0; | 499 | return 0; |
500 | 500 | ||
501 | return EFAULT; | 501 | return -EFAULT; |
502 | } | 502 | } |
503 | 503 | ||
504 | /* | 504 | /* |
@@ -508,14 +508,15 @@ static int validate_memory_access_address(unsigned long addr, int size) | |||
508 | int kgdb_mem2hex(char *mem, char *buf, int count) | 508 | int kgdb_mem2hex(char *mem, char *buf, int count) |
509 | { | 509 | { |
510 | char *tmp; | 510 | char *tmp; |
511 | int err = 0; | 511 | int err; |
512 | unsigned char *pch; | 512 | unsigned char *pch; |
513 | unsigned short mmr16; | 513 | unsigned short mmr16; |
514 | unsigned long mmr32; | 514 | unsigned long mmr32; |
515 | int cpu = raw_smp_processor_id(); | 515 | int cpu = raw_smp_processor_id(); |
516 | 516 | ||
517 | if (validate_memory_access_address((unsigned long)mem, count)) | 517 | err = validate_memory_access_address((unsigned long)mem, count); |
518 | return EFAULT; | 518 | if (err) |
519 | return err; | ||
519 | 520 | ||
520 | /* | 521 | /* |
521 | * We use the upper half of buf as an intermediate buffer for the | 522 | * We use the upper half of buf as an intermediate buffer for the |
@@ -533,7 +534,7 @@ int kgdb_mem2hex(char *mem, char *buf, int count) | |||
533 | *tmp++ = *pch++; | 534 | *tmp++ = *pch++; |
534 | tmp -= 2; | 535 | tmp -= 2; |
535 | } else | 536 | } else |
536 | err = EFAULT; | 537 | err = -EFAULT; |
537 | break; | 538 | break; |
538 | case 4: | 539 | case 4: |
539 | if ((unsigned int)mem % 4 == 0) { | 540 | if ((unsigned int)mem % 4 == 0) { |
@@ -545,10 +546,10 @@ int kgdb_mem2hex(char *mem, char *buf, int count) | |||
545 | *tmp++ = *pch++; | 546 | *tmp++ = *pch++; |
546 | tmp -= 4; | 547 | tmp -= 4; |
547 | } else | 548 | } else |
548 | err = EFAULT; | 549 | err = -EFAULT; |
549 | break; | 550 | break; |
550 | default: | 551 | default: |
551 | err = EFAULT; | 552 | err = -EFAULT; |
552 | } | 553 | } |
553 | } else if ((cpu == 0 && IN_MEM(mem, count, L1_CODE_START, L1_CODE_LENGTH)) | 554 | } else if ((cpu == 0 && IN_MEM(mem, count, L1_CODE_START, L1_CODE_LENGTH)) |
554 | #ifdef CONFIG_SMP | 555 | #ifdef CONFIG_SMP |
@@ -557,7 +558,7 @@ int kgdb_mem2hex(char *mem, char *buf, int count) | |||
557 | ) { | 558 | ) { |
558 | /* access L1 instruction SRAM*/ | 559 | /* access L1 instruction SRAM*/ |
559 | if (dma_memcpy(tmp, mem, count) == NULL) | 560 | if (dma_memcpy(tmp, mem, count) == NULL) |
560 | err = EFAULT; | 561 | err = -EFAULT; |
561 | } else | 562 | } else |
562 | err = probe_kernel_read(tmp, mem, count); | 563 | err = probe_kernel_read(tmp, mem, count); |
563 | 564 | ||
@@ -585,24 +586,24 @@ int kgdb_ebin2mem(char *buf, char *mem, int count) | |||
585 | char *tmp_new; | 586 | char *tmp_new; |
586 | unsigned short *mmr16; | 587 | unsigned short *mmr16; |
587 | unsigned long *mmr32; | 588 | unsigned long *mmr32; |
588 | int err = 0; | 589 | int err; |
589 | int size = 0; | 590 | int size; |
590 | int cpu = raw_smp_processor_id(); | 591 | int cpu = raw_smp_processor_id(); |
591 | 592 | ||
592 | tmp_old = tmp_new = buf; | 593 | tmp_old = tmp_new = buf; |
593 | 594 | ||
594 | while (count-- > 0) { | 595 | for (size = 0; size < count; ++size) { |
595 | if (*tmp_old == 0x7d) | 596 | if (*tmp_old == 0x7d) |
596 | *tmp_new = *(++tmp_old) ^ 0x20; | 597 | *tmp_new = *(++tmp_old) ^ 0x20; |
597 | else | 598 | else |
598 | *tmp_new = *tmp_old; | 599 | *tmp_new = *tmp_old; |
599 | tmp_new++; | 600 | tmp_new++; |
600 | tmp_old++; | 601 | tmp_old++; |
601 | size++; | ||
602 | } | 602 | } |
603 | 603 | ||
604 | if (validate_memory_access_address((unsigned long)mem, size)) | 604 | err = validate_memory_access_address((unsigned long)mem, size); |
605 | return EFAULT; | 605 | if (err) |
606 | return err; | ||
606 | 607 | ||
607 | if ((unsigned int)mem >= SYSMMR_BASE) { /*access MMR registers*/ | 608 | if ((unsigned int)mem >= SYSMMR_BASE) { /*access MMR registers*/ |
608 | switch (size) { | 609 | switch (size) { |
@@ -611,17 +612,17 @@ int kgdb_ebin2mem(char *buf, char *mem, int count) | |||
611 | mmr16 = (unsigned short *)buf; | 612 | mmr16 = (unsigned short *)buf; |
612 | *(unsigned short *)mem = *mmr16; | 613 | *(unsigned short *)mem = *mmr16; |
613 | } else | 614 | } else |
614 | return EFAULT; | 615 | err = -EFAULT; |
615 | break; | 616 | break; |
616 | case 4: | 617 | case 4: |
617 | if ((unsigned int)mem % 4 == 0) { | 618 | if ((unsigned int)mem % 4 == 0) { |
618 | mmr32 = (unsigned long *)buf; | 619 | mmr32 = (unsigned long *)buf; |
619 | *(unsigned long *)mem = *mmr32; | 620 | *(unsigned long *)mem = *mmr32; |
620 | } else | 621 | } else |
621 | return EFAULT; | 622 | err = -EFAULT; |
622 | break; | 623 | break; |
623 | default: | 624 | default: |
624 | return EFAULT; | 625 | err = -EFAULT; |
625 | } | 626 | } |
626 | } else if ((cpu == 0 && IN_MEM(mem, count, L1_CODE_START, L1_CODE_LENGTH)) | 627 | } else if ((cpu == 0 && IN_MEM(mem, count, L1_CODE_START, L1_CODE_LENGTH)) |
627 | #ifdef CONFIG_SMP | 628 | #ifdef CONFIG_SMP |
@@ -630,7 +631,7 @@ int kgdb_ebin2mem(char *buf, char *mem, int count) | |||
630 | ) { | 631 | ) { |
631 | /* access L1 instruction SRAM */ | 632 | /* access L1 instruction SRAM */ |
632 | if (dma_memcpy(mem, buf, size) == NULL) | 633 | if (dma_memcpy(mem, buf, size) == NULL) |
633 | err = EFAULT; | 634 | err = -EFAULT; |
634 | } else | 635 | } else |
635 | err = probe_kernel_write(mem, buf, size); | 636 | err = probe_kernel_write(mem, buf, size); |
636 | 637 | ||
@@ -648,10 +649,12 @@ int kgdb_hex2mem(char *buf, char *mem, int count) | |||
648 | char *tmp_hex; | 649 | char *tmp_hex; |
649 | unsigned short *mmr16; | 650 | unsigned short *mmr16; |
650 | unsigned long *mmr32; | 651 | unsigned long *mmr32; |
652 | int err; | ||
651 | int cpu = raw_smp_processor_id(); | 653 | int cpu = raw_smp_processor_id(); |
652 | 654 | ||
653 | if (validate_memory_access_address((unsigned long)mem, count)) | 655 | err = validate_memory_access_address((unsigned long)mem, count); |
654 | return EFAULT; | 656 | if (err) |
657 | return err; | ||
655 | 658 | ||
656 | /* | 659 | /* |
657 | * We use the upper half of buf as an intermediate buffer for the | 660 | * We use the upper half of buf as an intermediate buffer for the |
@@ -673,17 +676,17 @@ int kgdb_hex2mem(char *buf, char *mem, int count) | |||
673 | mmr16 = (unsigned short *)tmp_raw; | 676 | mmr16 = (unsigned short *)tmp_raw; |
674 | *(unsigned short *)mem = *mmr16; | 677 | *(unsigned short *)mem = *mmr16; |
675 | } else | 678 | } else |
676 | return EFAULT; | 679 | err = -EFAULT; |
677 | break; | 680 | break; |
678 | case 4: | 681 | case 4: |
679 | if ((unsigned int)mem % 4 == 0) { | 682 | if ((unsigned int)mem % 4 == 0) { |
680 | mmr32 = (unsigned long *)tmp_raw; | 683 | mmr32 = (unsigned long *)tmp_raw; |
681 | *(unsigned long *)mem = *mmr32; | 684 | *(unsigned long *)mem = *mmr32; |
682 | } else | 685 | } else |
683 | return EFAULT; | 686 | err = -EFAULT; |
684 | break; | 687 | break; |
685 | default: | 688 | default: |
686 | return EFAULT; | 689 | err = -EFAULT; |
687 | } | 690 | } |
688 | } else if ((cpu == 0 && IN_MEM(mem, count, L1_CODE_START, L1_CODE_LENGTH)) | 691 | } else if ((cpu == 0 && IN_MEM(mem, count, L1_CODE_START, L1_CODE_LENGTH)) |
689 | #ifdef CONFIG_SMP | 692 | #ifdef CONFIG_SMP |
@@ -692,10 +695,11 @@ int kgdb_hex2mem(char *buf, char *mem, int count) | |||
692 | ) { | 695 | ) { |
693 | /* access L1 instruction SRAM */ | 696 | /* access L1 instruction SRAM */ |
694 | if (dma_memcpy(mem, tmp_raw, count) == NULL) | 697 | if (dma_memcpy(mem, tmp_raw, count) == NULL) |
695 | return EFAULT; | 698 | err = -EFAULT; |
696 | } else | 699 | } else |
697 | return probe_kernel_write(mem, tmp_raw, count); | 700 | err = probe_kernel_write(mem, tmp_raw, count); |
698 | return 0; | 701 | |
702 | return err; | ||
699 | } | 703 | } |
700 | 704 | ||
701 | int kgdb_validate_break_address(unsigned long addr) | 705 | int kgdb_validate_break_address(unsigned long addr) |
@@ -715,7 +719,7 @@ int kgdb_validate_break_address(unsigned long addr) | |||
715 | if (IN_MEM(addr, BREAK_INSTR_SIZE, L2_START, L2_LENGTH)) | 719 | if (IN_MEM(addr, BREAK_INSTR_SIZE, L2_START, L2_LENGTH)) |
716 | return 0; | 720 | return 0; |
717 | 721 | ||
718 | return EFAULT; | 722 | return -EFAULT; |
719 | } | 723 | } |
720 | 724 | ||
721 | int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr) | 725 | int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr) |
diff --git a/arch/blackfin/kernel/module.c b/arch/blackfin/kernel/module.c index 1bd7f2d018a8..d5aee3626688 100644 --- a/arch/blackfin/kernel/module.c +++ b/arch/blackfin/kernel/module.c | |||
@@ -201,8 +201,8 @@ apply_relocate(Elf_Shdr * sechdrs, const char *strtab, | |||
201 | /* Arithmetic relocations are handled. */ | 201 | /* Arithmetic relocations are handled. */ |
202 | /* We do not expect LSETUP to be split and hence is not */ | 202 | /* We do not expect LSETUP to be split and hence is not */ |
203 | /* handled. */ | 203 | /* handled. */ |
204 | /* R_byte and R_byte2 are also not handled as the gas */ | 204 | /* R_BFIN_BYTE and R_BFIN_BYTE2 are also not handled as the */ |
205 | /* does not generate it. */ | 205 | /* gas does not generate it. */ |
206 | /*************************************************************************/ | 206 | /*************************************************************************/ |
207 | int | 207 | int |
208 | apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab, | 208 | apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab, |
@@ -243,8 +243,8 @@ apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab, | |||
243 | #endif | 243 | #endif |
244 | switch (ELF32_R_TYPE(rel[i].r_info)) { | 244 | switch (ELF32_R_TYPE(rel[i].r_info)) { |
245 | 245 | ||
246 | case R_pcrel24: | 246 | case R_BFIN_PCREL24: |
247 | case R_pcrel24_jump_l: | 247 | case R_BFIN_PCREL24_JUMP_L: |
248 | /* Add the value, subtract its postition */ | 248 | /* Add the value, subtract its postition */ |
249 | location16 = | 249 | location16 = |
250 | (uint16_t *) (sechdrs[sechdrs[relsec].sh_info]. | 250 | (uint16_t *) (sechdrs[sechdrs[relsec].sh_info]. |
@@ -266,18 +266,18 @@ apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab, | |||
266 | (*location16 & 0xff00) | (value >> 16 & 0x00ff); | 266 | (*location16 & 0xff00) | (value >> 16 & 0x00ff); |
267 | *(location16 + 1) = value & 0xffff; | 267 | *(location16 + 1) = value & 0xffff; |
268 | break; | 268 | break; |
269 | case R_pcrel12_jump: | 269 | case R_BFIN_PCREL12_JUMP: |
270 | case R_pcrel12_jump_s: | 270 | case R_BFIN_PCREL12_JUMP_S: |
271 | value -= (uint32_t) location32; | 271 | value -= (uint32_t) location32; |
272 | value >>= 1; | 272 | value >>= 1; |
273 | *location16 = (value & 0xfff); | 273 | *location16 = (value & 0xfff); |
274 | break; | 274 | break; |
275 | case R_pcrel10: | 275 | case R_BFIN_PCREL10: |
276 | value -= (uint32_t) location32; | 276 | value -= (uint32_t) location32; |
277 | value >>= 1; | 277 | value >>= 1; |
278 | *location16 = (value & 0x3ff); | 278 | *location16 = (value & 0x3ff); |
279 | break; | 279 | break; |
280 | case R_luimm16: | 280 | case R_BFIN_LUIMM16: |
281 | pr_debug("before %x after %x\n", *location16, | 281 | pr_debug("before %x after %x\n", *location16, |
282 | (value & 0xffff)); | 282 | (value & 0xffff)); |
283 | tmp = (value & 0xffff); | 283 | tmp = (value & 0xffff); |
@@ -286,7 +286,7 @@ apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab, | |||
286 | } else | 286 | } else |
287 | *location16 = tmp; | 287 | *location16 = tmp; |
288 | break; | 288 | break; |
289 | case R_huimm16: | 289 | case R_BFIN_HUIMM16: |
290 | pr_debug("before %x after %x\n", *location16, | 290 | pr_debug("before %x after %x\n", *location16, |
291 | ((value >> 16) & 0xffff)); | 291 | ((value >> 16) & 0xffff)); |
292 | tmp = ((value >> 16) & 0xffff); | 292 | tmp = ((value >> 16) & 0xffff); |
@@ -295,10 +295,10 @@ apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab, | |||
295 | } else | 295 | } else |
296 | *location16 = tmp; | 296 | *location16 = tmp; |
297 | break; | 297 | break; |
298 | case R_rimm16: | 298 | case R_BFIN_RIMM16: |
299 | *location16 = (value & 0xffff); | 299 | *location16 = (value & 0xffff); |
300 | break; | 300 | break; |
301 | case R_byte4_data: | 301 | case R_BFIN_BYTE4_DATA: |
302 | pr_debug("before %x after %x\n", *location32, value); | 302 | pr_debug("before %x after %x\n", *location32, value); |
303 | *location32 = value; | 303 | *location32 = value; |
304 | break; | 304 | break; |
diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c index e040e03335ea..30d0843ed701 100644 --- a/arch/blackfin/kernel/process.c +++ b/arch/blackfin/kernel/process.c | |||
@@ -322,6 +322,9 @@ void finish_atomic_sections (struct pt_regs *regs) | |||
322 | } | 322 | } |
323 | 323 | ||
324 | #if defined(CONFIG_ACCESS_CHECK) | 324 | #if defined(CONFIG_ACCESS_CHECK) |
325 | #ifdef CONFIG_ACCESS_OK_L1 | ||
326 | __attribute__((l1_text)) | ||
327 | #endif | ||
325 | /* Return 1 if access to memory range is OK, 0 otherwise */ | 328 | /* Return 1 if access to memory range is OK, 0 otherwise */ |
326 | int _access_ok(unsigned long addr, unsigned long size) | 329 | int _access_ok(unsigned long addr, unsigned long size) |
327 | { | 330 | { |
diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index a58687bdee6a..6454babdfaff 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c | |||
@@ -18,9 +18,12 @@ | |||
18 | #include <linux/tty.h> | 18 | #include <linux/tty.h> |
19 | #include <linux/pfn.h> | 19 | #include <linux/pfn.h> |
20 | 20 | ||
21 | #ifdef CONFIG_MTD_UCLINUX | ||
22 | #include <linux/mtd/map.h> | ||
21 | #include <linux/ext2_fs.h> | 23 | #include <linux/ext2_fs.h> |
22 | #include <linux/cramfs_fs.h> | 24 | #include <linux/cramfs_fs.h> |
23 | #include <linux/romfs_fs.h> | 25 | #include <linux/romfs_fs.h> |
26 | #endif | ||
24 | 27 | ||
25 | #include <asm/cplb.h> | 28 | #include <asm/cplb.h> |
26 | #include <asm/cacheflush.h> | 29 | #include <asm/cacheflush.h> |
@@ -45,6 +48,7 @@ EXPORT_SYMBOL(_ramend); | |||
45 | EXPORT_SYMBOL(reserved_mem_dcache_on); | 48 | EXPORT_SYMBOL(reserved_mem_dcache_on); |
46 | 49 | ||
47 | #ifdef CONFIG_MTD_UCLINUX | 50 | #ifdef CONFIG_MTD_UCLINUX |
51 | extern struct map_info uclinux_ram_map; | ||
48 | unsigned long memory_mtd_end, memory_mtd_start, mtd_size; | 52 | unsigned long memory_mtd_end, memory_mtd_start, mtd_size; |
49 | unsigned long _ebss; | 53 | unsigned long _ebss; |
50 | EXPORT_SYMBOL(memory_mtd_end); | 54 | EXPORT_SYMBOL(memory_mtd_end); |
@@ -150,40 +154,45 @@ void __init bfin_relocate_l1_mem(void) | |||
150 | unsigned long l1_data_b_length; | 154 | unsigned long l1_data_b_length; |
151 | unsigned long l2_length; | 155 | unsigned long l2_length; |
152 | 156 | ||
157 | /* | ||
158 | * due to the ALIGN(4) in the arch/blackfin/kernel/vmlinux.lds.S | ||
159 | * we know that everything about l1 text/data is nice and aligned, | ||
160 | * so copy by 4 byte chunks, and don't worry about overlapping | ||
161 | * src/dest. | ||
162 | * | ||
163 | * We can't use the dma_memcpy functions, since they can call | ||
164 | * scheduler functions which might be in L1 :( and core writes | ||
165 | * into L1 instruction cause bad access errors, so we are stuck, | ||
166 | * we are required to use DMA, but can't use the common dma | ||
167 | * functions. We can't use memcpy either - since that might be | ||
168 | * going to be in the relocated L1 | ||
169 | */ | ||
170 | |||
153 | blackfin_dma_early_init(); | 171 | blackfin_dma_early_init(); |
154 | 172 | ||
173 | /* if necessary, copy _stext_l1 to _etext_l1 to L1 instruction SRAM */ | ||
155 | l1_code_length = _etext_l1 - _stext_l1; | 174 | l1_code_length = _etext_l1 - _stext_l1; |
156 | if (l1_code_length > L1_CODE_LENGTH) | 175 | if (l1_code_length) |
157 | panic("L1 Instruction SRAM Overflow\n"); | 176 | early_dma_memcpy(_stext_l1, _l1_lma_start, l1_code_length); |
158 | /* cannot complain as printk is not available as yet. | ||
159 | * But we can continue booting and complain later! | ||
160 | */ | ||
161 | |||
162 | /* Copy _stext_l1 to _etext_l1 to L1 instruction SRAM */ | ||
163 | dma_memcpy(_stext_l1, _l1_lma_start, l1_code_length); | ||
164 | 177 | ||
178 | /* if necessary, copy _sdata_l1 to _sbss_l1 to L1 data bank A SRAM */ | ||
165 | l1_data_a_length = _sbss_l1 - _sdata_l1; | 179 | l1_data_a_length = _sbss_l1 - _sdata_l1; |
166 | if (l1_data_a_length > L1_DATA_A_LENGTH) | 180 | if (l1_data_a_length) |
167 | panic("L1 Data SRAM Bank A Overflow\n"); | 181 | early_dma_memcpy(_sdata_l1, _l1_lma_start + l1_code_length, l1_data_a_length); |
168 | |||
169 | /* Copy _sdata_l1 to _sbss_l1 to L1 data bank A SRAM */ | ||
170 | dma_memcpy(_sdata_l1, _l1_lma_start + l1_code_length, l1_data_a_length); | ||
171 | 182 | ||
183 | /* if necessary, copy _sdata_b_l1 to _sbss_b_l1 to L1 data bank B SRAM */ | ||
172 | l1_data_b_length = _sbss_b_l1 - _sdata_b_l1; | 184 | l1_data_b_length = _sbss_b_l1 - _sdata_b_l1; |
173 | if (l1_data_b_length > L1_DATA_B_LENGTH) | 185 | if (l1_data_b_length) |
174 | panic("L1 Data SRAM Bank B Overflow\n"); | 186 | early_dma_memcpy(_sdata_b_l1, _l1_lma_start + l1_code_length + |
175 | |||
176 | /* Copy _sdata_b_l1 to _sbss_b_l1 to L1 data bank B SRAM */ | ||
177 | dma_memcpy(_sdata_b_l1, _l1_lma_start + l1_code_length + | ||
178 | l1_data_a_length, l1_data_b_length); | 187 | l1_data_a_length, l1_data_b_length); |
179 | 188 | ||
189 | early_dma_memcpy_done(); | ||
190 | |||
191 | /* if necessary, copy _stext_l2 to _edata_l2 to L2 SRAM */ | ||
180 | if (L2_LENGTH != 0) { | 192 | if (L2_LENGTH != 0) { |
181 | l2_length = _sbss_l2 - _stext_l2; | 193 | l2_length = _sbss_l2 - _stext_l2; |
182 | if (l2_length > L2_LENGTH) | 194 | if (l2_length) |
183 | panic("L2 SRAM Overflow\n"); | 195 | memcpy(_stext_l2, _l2_lma_start, l2_length); |
184 | |||
185 | /* Copy _stext_l2 to _edata_l2 to L2 SRAM */ | ||
186 | dma_memcpy(_stext_l2, _l2_lma_start, l2_length); | ||
187 | } | 196 | } |
188 | } | 197 | } |
189 | 198 | ||
@@ -472,7 +481,7 @@ static __init void memory_setup(void) | |||
472 | 481 | ||
473 | if (DMA_UNCACHED_REGION > (_ramend - _ramstart)) { | 482 | if (DMA_UNCACHED_REGION > (_ramend - _ramstart)) { |
474 | console_init(); | 483 | console_init(); |
475 | panic("DMA region exceeds memory limit: %lu.\n", | 484 | panic("DMA region exceeds memory limit: %lu.", |
476 | _ramend - _ramstart); | 485 | _ramend - _ramstart); |
477 | } | 486 | } |
478 | memory_end = _ramend - DMA_UNCACHED_REGION; | 487 | memory_end = _ramend - DMA_UNCACHED_REGION; |
@@ -526,14 +535,13 @@ static __init void memory_setup(void) | |||
526 | 535 | ||
527 | if (mtd_size == 0) { | 536 | if (mtd_size == 0) { |
528 | console_init(); | 537 | console_init(); |
529 | panic("Don't boot kernel without rootfs attached.\n"); | 538 | panic("Don't boot kernel without rootfs attached."); |
530 | } | 539 | } |
531 | 540 | ||
532 | /* Relocate MTD image to the top of memory after the uncached memory area */ | 541 | /* Relocate MTD image to the top of memory after the uncached memory area */ |
533 | dma_memcpy((char *)memory_end, _end, mtd_size); | 542 | uclinux_ram_map.phys = memory_mtd_start = memory_end; |
534 | 543 | uclinux_ram_map.size = mtd_size; | |
535 | memory_mtd_start = memory_end; | 544 | dma_memcpy((void *)uclinux_ram_map.phys, _end, uclinux_ram_map.size); |
536 | _ebss = memory_mtd_start; /* define _ebss for compatible */ | ||
537 | #endif /* CONFIG_MTD_UCLINUX */ | 545 | #endif /* CONFIG_MTD_UCLINUX */ |
538 | 546 | ||
539 | #if (defined(CONFIG_BFIN_ICACHE) && ANOMALY_05000263) | 547 | #if (defined(CONFIG_BFIN_ICACHE) && ANOMALY_05000263) |
@@ -796,10 +804,8 @@ void __init setup_arch(char **cmdline_p) | |||
796 | cclk = get_cclk(); | 804 | cclk = get_cclk(); |
797 | sclk = get_sclk(); | 805 | sclk = get_sclk(); |
798 | 806 | ||
799 | #if !defined(CONFIG_BFIN_KERNEL_CLOCK) | 807 | if ((ANOMALY_05000273 || ANOMALY_05000274) && (cclk >> 1) < sclk) |
800 | if (ANOMALY_05000273 && cclk == sclk) | 808 | panic("ANOMALY 05000273 or 05000274: CCLK must be >= 2*SCLK"); |
801 | panic("ANOMALY 05000273, SCLK can not be same as CCLK"); | ||
802 | #endif | ||
803 | 809 | ||
804 | #ifdef BF561_FAMILY | 810 | #ifdef BF561_FAMILY |
805 | if (ANOMALY_05000266) { | 811 | if (ANOMALY_05000266) { |
@@ -881,7 +887,7 @@ void __init setup_arch(char **cmdline_p) | |||
881 | printk(KERN_ERR "Warning: Compiled for Rev %d, but running on Rev %d\n", | 887 | printk(KERN_ERR "Warning: Compiled for Rev %d, but running on Rev %d\n", |
882 | bfin_compiled_revid(), bfin_revid()); | 888 | bfin_compiled_revid(), bfin_revid()); |
883 | if (bfin_compiled_revid() > bfin_revid()) | 889 | if (bfin_compiled_revid() > bfin_revid()) |
884 | panic("Error: you are missing anomaly workarounds for this rev\n"); | 890 | panic("Error: you are missing anomaly workarounds for this rev"); |
885 | } | 891 | } |
886 | } | 892 | } |
887 | if (bfin_revid() < CONFIG_BF_REV_MIN || bfin_revid() > CONFIG_BF_REV_MAX) | 893 | if (bfin_revid() < CONFIG_BF_REV_MIN || bfin_revid() > CONFIG_BF_REV_MAX) |
@@ -891,16 +897,13 @@ void __init setup_arch(char **cmdline_p) | |||
891 | 897 | ||
892 | /* We can't run on BF548-0.1 due to ANOMALY 05000448 */ | 898 | /* We can't run on BF548-0.1 due to ANOMALY 05000448 */ |
893 | if (bfin_cpuid() == 0x27de && bfin_revid() == 1) | 899 | if (bfin_cpuid() == 0x27de && bfin_revid() == 1) |
894 | panic("You can't run on this processor due to 05000448\n"); | 900 | panic("You can't run on this processor due to 05000448"); |
895 | 901 | ||
896 | printk(KERN_INFO "Blackfin Linux support by http://blackfin.uclinux.org/\n"); | 902 | printk(KERN_INFO "Blackfin Linux support by http://blackfin.uclinux.org/\n"); |
897 | 903 | ||
898 | printk(KERN_INFO "Processor Speed: %lu MHz core clock and %lu MHz System Clock\n", | 904 | printk(KERN_INFO "Processor Speed: %lu MHz core clock and %lu MHz System Clock\n", |
899 | cclk / 1000000, sclk / 1000000); | 905 | cclk / 1000000, sclk / 1000000); |
900 | 906 | ||
901 | if (ANOMALY_05000273 && (cclk >> 1) <= sclk) | ||
902 | printk("\n\n\nANOMALY_05000273: CCLK must be >= 2*SCLK !!!\n\n\n"); | ||
903 | |||
904 | setup_bootmem_allocator(); | 907 | setup_bootmem_allocator(); |
905 | 908 | ||
906 | paging_init(); | 909 | paging_init(); |
@@ -1095,7 +1098,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
1095 | CPUID, bfin_cpuid()); | 1098 | CPUID, bfin_cpuid()); |
1096 | 1099 | ||
1097 | seq_printf(m, "model name\t: ADSP-%s %lu(MHz CCLK) %lu(MHz SCLK) (%s)\n" | 1100 | seq_printf(m, "model name\t: ADSP-%s %lu(MHz CCLK) %lu(MHz SCLK) (%s)\n" |
1098 | "stepping\t: %d\n", | 1101 | "stepping\t: %d ", |
1099 | cpu, cclk/1000000, sclk/1000000, | 1102 | cpu, cclk/1000000, sclk/1000000, |
1100 | #ifdef CONFIG_MPU | 1103 | #ifdef CONFIG_MPU |
1101 | "mpu on", | 1104 | "mpu on", |
@@ -1104,7 +1107,16 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
1104 | #endif | 1107 | #endif |
1105 | revid); | 1108 | revid); |
1106 | 1109 | ||
1107 | seq_printf(m, "cpu MHz\t\t: %lu.%03lu/%lu.%03lu\n", | 1110 | if (bfin_revid() != bfin_compiled_revid()) { |
1111 | if (bfin_compiled_revid() == -1) | ||
1112 | seq_printf(m, "(Compiled for Rev none)"); | ||
1113 | else if (bfin_compiled_revid() == 0xffff) | ||
1114 | seq_printf(m, "(Compiled for Rev any)"); | ||
1115 | else | ||
1116 | seq_printf(m, "(Compiled for Rev %d)", bfin_compiled_revid()); | ||
1117 | } | ||
1118 | |||
1119 | seq_printf(m, "\ncpu MHz\t\t: %lu.%03lu/%lu.%03lu\n", | ||
1108 | cclk/1000000, cclk%1000000, | 1120 | cclk/1000000, cclk%1000000, |
1109 | sclk/1000000, sclk%1000000); | 1121 | sclk/1000000, sclk%1000000); |
1110 | seq_printf(m, "bogomips\t: %lu.%02lu\n" | 1122 | seq_printf(m, "bogomips\t: %lu.%02lu\n" |
@@ -1169,6 +1181,9 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
1169 | #ifdef __ARCH_SYNC_CORE_DCACHE | 1181 | #ifdef __ARCH_SYNC_CORE_DCACHE |
1170 | seq_printf(m, "SMP Dcache Flushes\t: %lu\n\n", cpudata->dcache_invld_count); | 1182 | seq_printf(m, "SMP Dcache Flushes\t: %lu\n\n", cpudata->dcache_invld_count); |
1171 | #endif | 1183 | #endif |
1184 | #ifdef __ARCH_SYNC_CORE_ICACHE | ||
1185 | seq_printf(m, "SMP Icache Flushes\t: %lu\n\n", cpudata->icache_invld_count); | ||
1186 | #endif | ||
1172 | #ifdef CONFIG_BFIN_ICACHE_LOCK | 1187 | #ifdef CONFIG_BFIN_ICACHE_LOCK |
1173 | switch ((cpudata->imemctl >> 3) & WAYALL_L) { | 1188 | switch ((cpudata->imemctl >> 3) & WAYALL_L) { |
1174 | case WAY0_L: | 1189 | case WAY0_L: |
diff --git a/arch/blackfin/kernel/stacktrace.c b/arch/blackfin/kernel/stacktrace.c new file mode 100644 index 000000000000..30301e1eace5 --- /dev/null +++ b/arch/blackfin/kernel/stacktrace.c | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * Blackfin stacktrace code (mostly copied from avr32) | ||
3 | * | ||
4 | * Copyright 2009 Analog Devices Inc. | ||
5 | * Licensed under the GPL-2 or later. | ||
6 | */ | ||
7 | |||
8 | #include <linux/sched.h> | ||
9 | #include <linux/stacktrace.h> | ||
10 | #include <linux/thread_info.h> | ||
11 | #include <linux/module.h> | ||
12 | |||
13 | register unsigned long current_frame_pointer asm("FP"); | ||
14 | |||
15 | struct stackframe { | ||
16 | unsigned long fp; | ||
17 | unsigned long rets; | ||
18 | }; | ||
19 | |||
20 | /* | ||
21 | * Save stack-backtrace addresses into a stack_trace buffer. | ||
22 | */ | ||
23 | void save_stack_trace(struct stack_trace *trace) | ||
24 | { | ||
25 | unsigned long low, high; | ||
26 | unsigned long fp; | ||
27 | struct stackframe *frame; | ||
28 | int skip = trace->skip; | ||
29 | |||
30 | low = (unsigned long)task_stack_page(current); | ||
31 | high = low + THREAD_SIZE; | ||
32 | fp = current_frame_pointer; | ||
33 | |||
34 | while (fp >= low && fp <= (high - sizeof(*frame))) { | ||
35 | frame = (struct stackframe *)fp; | ||
36 | |||
37 | if (skip) { | ||
38 | skip--; | ||
39 | } else { | ||
40 | trace->entries[trace->nr_entries++] = frame->rets; | ||
41 | if (trace->nr_entries >= trace->max_entries) | ||
42 | break; | ||
43 | } | ||
44 | |||
45 | /* | ||
46 | * The next frame must be at a higher address than the | ||
47 | * current frame. | ||
48 | */ | ||
49 | low = fp + sizeof(*frame); | ||
50 | fp = frame->fp; | ||
51 | } | ||
52 | } | ||
53 | EXPORT_SYMBOL_GPL(save_stack_trace); | ||
diff --git a/arch/blackfin/kernel/sys_bfin.c b/arch/blackfin/kernel/sys_bfin.c index fce49d7cf001..a8f1329c15a4 100644 --- a/arch/blackfin/kernel/sys_bfin.c +++ b/arch/blackfin/kernel/sys_bfin.c | |||
@@ -78,11 +78,6 @@ asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, | |||
78 | return do_mmap2(addr, len, prot, flags, fd, pgoff); | 78 | return do_mmap2(addr, len, prot, flags, fd, pgoff); |
79 | } | 79 | } |
80 | 80 | ||
81 | asmlinkage int sys_getpagesize(void) | ||
82 | { | ||
83 | return PAGE_SIZE; | ||
84 | } | ||
85 | |||
86 | asmlinkage void *sys_sram_alloc(size_t size, unsigned long flags) | 81 | asmlinkage void *sys_sram_alloc(size_t size, unsigned long flags) |
87 | { | 82 | { |
88 | return sram_alloc_with_lsl(size, flags); | 83 | return sram_alloc_with_lsl(size, flags); |
diff --git a/arch/blackfin/kernel/time-ts.c b/arch/blackfin/kernel/time-ts.c index 27646121280a..0791eba40d9f 100644 --- a/arch/blackfin/kernel/time-ts.c +++ b/arch/blackfin/kernel/time-ts.c | |||
@@ -20,8 +20,9 @@ | |||
20 | 20 | ||
21 | #include <asm/blackfin.h> | 21 | #include <asm/blackfin.h> |
22 | #include <asm/time.h> | 22 | #include <asm/time.h> |
23 | #include <asm/gptimers.h> | ||
23 | 24 | ||
24 | #ifdef CONFIG_CYCLES_CLOCKSOURCE | 25 | #if defined(CONFIG_CYCLES_CLOCKSOURCE) |
25 | 26 | ||
26 | /* Accelerators for sched_clock() | 27 | /* Accelerators for sched_clock() |
27 | * convert from cycles(64bits) => nanoseconds (64bits) | 28 | * convert from cycles(64bits) => nanoseconds (64bits) |
@@ -58,15 +59,15 @@ static inline unsigned long long cycles_2_ns(cycle_t cyc) | |||
58 | return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR; | 59 | return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR; |
59 | } | 60 | } |
60 | 61 | ||
61 | static cycle_t read_cycles(struct clocksource *cs) | 62 | static cycle_t bfin_read_cycles(struct clocksource *cs) |
62 | { | 63 | { |
63 | return __bfin_cycles_off + (get_cycles() << __bfin_cycles_mod); | 64 | return __bfin_cycles_off + (get_cycles() << __bfin_cycles_mod); |
64 | } | 65 | } |
65 | 66 | ||
66 | static struct clocksource clocksource_bfin = { | 67 | static struct clocksource bfin_cs_cycles = { |
67 | .name = "bfin_cycles", | 68 | .name = "bfin_cs_cycles", |
68 | .rating = 350, | 69 | .rating = 350, |
69 | .read = read_cycles, | 70 | .read = bfin_read_cycles, |
70 | .mask = CLOCKSOURCE_MASK(64), | 71 | .mask = CLOCKSOURCE_MASK(64), |
71 | .shift = 22, | 72 | .shift = 22, |
72 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 73 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
@@ -74,53 +75,198 @@ static struct clocksource clocksource_bfin = { | |||
74 | 75 | ||
75 | unsigned long long sched_clock(void) | 76 | unsigned long long sched_clock(void) |
76 | { | 77 | { |
77 | return cycles_2_ns(read_cycles(&clocksource_bfin)); | 78 | return cycles_2_ns(bfin_read_cycles(&bfin_cs_cycles)); |
78 | } | 79 | } |
79 | 80 | ||
80 | static int __init bfin_clocksource_init(void) | 81 | static int __init bfin_cs_cycles_init(void) |
81 | { | 82 | { |
82 | set_cyc2ns_scale(get_cclk() / 1000); | 83 | set_cyc2ns_scale(get_cclk() / 1000); |
83 | 84 | ||
84 | clocksource_bfin.mult = clocksource_hz2mult(get_cclk(), clocksource_bfin.shift); | 85 | bfin_cs_cycles.mult = \ |
86 | clocksource_hz2mult(get_cclk(), bfin_cs_cycles.shift); | ||
85 | 87 | ||
86 | if (clocksource_register(&clocksource_bfin)) | 88 | if (clocksource_register(&bfin_cs_cycles)) |
87 | panic("failed to register clocksource"); | 89 | panic("failed to register clocksource"); |
88 | 90 | ||
89 | return 0; | 91 | return 0; |
90 | } | 92 | } |
93 | #else | ||
94 | # define bfin_cs_cycles_init() | ||
95 | #endif | ||
96 | |||
97 | #ifdef CONFIG_GPTMR0_CLOCKSOURCE | ||
98 | |||
99 | void __init setup_gptimer0(void) | ||
100 | { | ||
101 | disable_gptimers(TIMER0bit); | ||
102 | |||
103 | set_gptimer_config(TIMER0_id, \ | ||
104 | TIMER_OUT_DIS | TIMER_PERIOD_CNT | TIMER_MODE_PWM); | ||
105 | set_gptimer_period(TIMER0_id, -1); | ||
106 | set_gptimer_pwidth(TIMER0_id, -2); | ||
107 | SSYNC(); | ||
108 | enable_gptimers(TIMER0bit); | ||
109 | } | ||
110 | |||
111 | static cycle_t bfin_read_gptimer0(void) | ||
112 | { | ||
113 | return bfin_read_TIMER0_COUNTER(); | ||
114 | } | ||
115 | |||
116 | static struct clocksource bfin_cs_gptimer0 = { | ||
117 | .name = "bfin_cs_gptimer0", | ||
118 | .rating = 400, | ||
119 | .read = bfin_read_gptimer0, | ||
120 | .mask = CLOCKSOURCE_MASK(32), | ||
121 | .shift = 22, | ||
122 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
123 | }; | ||
124 | |||
125 | static int __init bfin_cs_gptimer0_init(void) | ||
126 | { | ||
127 | setup_gptimer0(); | ||
91 | 128 | ||
129 | bfin_cs_gptimer0.mult = \ | ||
130 | clocksource_hz2mult(get_sclk(), bfin_cs_gptimer0.shift); | ||
131 | |||
132 | if (clocksource_register(&bfin_cs_gptimer0)) | ||
133 | panic("failed to register clocksource"); | ||
134 | |||
135 | return 0; | ||
136 | } | ||
92 | #else | 137 | #else |
93 | # define bfin_clocksource_init() | 138 | # define bfin_cs_gptimer0_init() |
94 | #endif | 139 | #endif |
95 | 140 | ||
141 | #ifdef CONFIG_CORE_TIMER_IRQ_L1 | ||
142 | __attribute__((l1_text)) | ||
143 | #endif | ||
144 | irqreturn_t timer_interrupt(int irq, void *dev_id); | ||
145 | |||
146 | static int bfin_timer_set_next_event(unsigned long, \ | ||
147 | struct clock_event_device *); | ||
148 | |||
149 | static void bfin_timer_set_mode(enum clock_event_mode, \ | ||
150 | struct clock_event_device *); | ||
151 | |||
152 | static struct clock_event_device clockevent_bfin = { | ||
153 | #if defined(CONFIG_TICKSOURCE_GPTMR0) | ||
154 | .name = "bfin_gptimer0", | ||
155 | .rating = 300, | ||
156 | .irq = IRQ_TIMER0, | ||
157 | #else | ||
158 | .name = "bfin_core_timer", | ||
159 | .rating = 350, | ||
160 | .irq = IRQ_CORETMR, | ||
161 | #endif | ||
162 | .shift = 32, | ||
163 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | ||
164 | .set_next_event = bfin_timer_set_next_event, | ||
165 | .set_mode = bfin_timer_set_mode, | ||
166 | }; | ||
167 | |||
168 | static struct irqaction bfin_timer_irq = { | ||
169 | #if defined(CONFIG_TICKSOURCE_GPTMR0) | ||
170 | .name = "Blackfin GPTimer0", | ||
171 | #else | ||
172 | .name = "Blackfin CoreTimer", | ||
173 | #endif | ||
174 | .flags = IRQF_DISABLED | IRQF_TIMER | \ | ||
175 | IRQF_IRQPOLL | IRQF_PERCPU, | ||
176 | .handler = timer_interrupt, | ||
177 | .dev_id = &clockevent_bfin, | ||
178 | }; | ||
179 | |||
180 | #if defined(CONFIG_TICKSOURCE_GPTMR0) | ||
96 | static int bfin_timer_set_next_event(unsigned long cycles, | 181 | static int bfin_timer_set_next_event(unsigned long cycles, |
97 | struct clock_event_device *evt) | 182 | struct clock_event_device *evt) |
98 | { | 183 | { |
184 | disable_gptimers(TIMER0bit); | ||
185 | |||
186 | /* it starts counting three SCLK cycles after the TIMENx bit is set */ | ||
187 | set_gptimer_pwidth(TIMER0_id, cycles - 3); | ||
188 | enable_gptimers(TIMER0bit); | ||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static void bfin_timer_set_mode(enum clock_event_mode mode, | ||
193 | struct clock_event_device *evt) | ||
194 | { | ||
195 | switch (mode) { | ||
196 | case CLOCK_EVT_MODE_PERIODIC: { | ||
197 | set_gptimer_config(TIMER0_id, \ | ||
198 | TIMER_OUT_DIS | TIMER_IRQ_ENA | \ | ||
199 | TIMER_PERIOD_CNT | TIMER_MODE_PWM); | ||
200 | set_gptimer_period(TIMER0_id, get_sclk() / HZ); | ||
201 | set_gptimer_pwidth(TIMER0_id, get_sclk() / HZ - 1); | ||
202 | enable_gptimers(TIMER0bit); | ||
203 | break; | ||
204 | } | ||
205 | case CLOCK_EVT_MODE_ONESHOT: | ||
206 | disable_gptimers(TIMER0bit); | ||
207 | set_gptimer_config(TIMER0_id, \ | ||
208 | TIMER_OUT_DIS | TIMER_IRQ_ENA | TIMER_MODE_PWM); | ||
209 | set_gptimer_period(TIMER0_id, 0); | ||
210 | break; | ||
211 | case CLOCK_EVT_MODE_UNUSED: | ||
212 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
213 | disable_gptimers(TIMER0bit); | ||
214 | break; | ||
215 | case CLOCK_EVT_MODE_RESUME: | ||
216 | break; | ||
217 | } | ||
218 | } | ||
219 | |||
220 | static void bfin_timer_ack(void) | ||
221 | { | ||
222 | set_gptimer_status(TIMER_GROUP1, TIMER_STATUS_TIMIL0); | ||
223 | } | ||
224 | |||
225 | static void __init bfin_timer_init(void) | ||
226 | { | ||
227 | disable_gptimers(TIMER0bit); | ||
228 | } | ||
229 | |||
230 | static unsigned long __init bfin_clockevent_check(void) | ||
231 | { | ||
232 | setup_irq(IRQ_TIMER0, &bfin_timer_irq); | ||
233 | return get_sclk(); | ||
234 | } | ||
235 | |||
236 | #else /* CONFIG_TICKSOURCE_CORETMR */ | ||
237 | |||
238 | static int bfin_timer_set_next_event(unsigned long cycles, | ||
239 | struct clock_event_device *evt) | ||
240 | { | ||
241 | bfin_write_TCNTL(TMPWR); | ||
242 | CSYNC(); | ||
99 | bfin_write_TCOUNT(cycles); | 243 | bfin_write_TCOUNT(cycles); |
100 | CSYNC(); | 244 | CSYNC(); |
245 | bfin_write_TCNTL(TMPWR | TMREN); | ||
101 | return 0; | 246 | return 0; |
102 | } | 247 | } |
103 | 248 | ||
104 | static void bfin_timer_set_mode(enum clock_event_mode mode, | 249 | static void bfin_timer_set_mode(enum clock_event_mode mode, |
105 | struct clock_event_device *evt) | 250 | struct clock_event_device *evt) |
106 | { | 251 | { |
107 | switch (mode) { | 252 | switch (mode) { |
108 | case CLOCK_EVT_MODE_PERIODIC: { | 253 | case CLOCK_EVT_MODE_PERIODIC: { |
109 | unsigned long tcount = ((get_cclk() / (HZ * TIME_SCALE)) - 1); | 254 | unsigned long tcount = ((get_cclk() / (HZ * TIME_SCALE)) - 1); |
110 | bfin_write_TCNTL(TMPWR); | 255 | bfin_write_TCNTL(TMPWR); |
111 | bfin_write_TSCALE(TIME_SCALE - 1); | ||
112 | CSYNC(); | 256 | CSYNC(); |
257 | bfin_write_TSCALE(TIME_SCALE - 1); | ||
113 | bfin_write_TPERIOD(tcount); | 258 | bfin_write_TPERIOD(tcount); |
114 | bfin_write_TCOUNT(tcount); | 259 | bfin_write_TCOUNT(tcount); |
115 | bfin_write_TCNTL(TMPWR | TMREN | TAUTORLD); | ||
116 | CSYNC(); | 260 | CSYNC(); |
261 | bfin_write_TCNTL(TMPWR | TMREN | TAUTORLD); | ||
117 | break; | 262 | break; |
118 | } | 263 | } |
119 | case CLOCK_EVT_MODE_ONESHOT: | 264 | case CLOCK_EVT_MODE_ONESHOT: |
265 | bfin_write_TCNTL(TMPWR); | ||
266 | CSYNC(); | ||
120 | bfin_write_TSCALE(TIME_SCALE - 1); | 267 | bfin_write_TSCALE(TIME_SCALE - 1); |
268 | bfin_write_TPERIOD(0); | ||
121 | bfin_write_TCOUNT(0); | 269 | bfin_write_TCOUNT(0); |
122 | bfin_write_TCNTL(TMPWR | TMREN); | ||
123 | CSYNC(); | ||
124 | break; | 270 | break; |
125 | case CLOCK_EVT_MODE_UNUSED: | 271 | case CLOCK_EVT_MODE_UNUSED: |
126 | case CLOCK_EVT_MODE_SHUTDOWN: | 272 | case CLOCK_EVT_MODE_SHUTDOWN: |
@@ -132,6 +278,10 @@ static void bfin_timer_set_mode(enum clock_event_mode mode, | |||
132 | } | 278 | } |
133 | } | 279 | } |
134 | 280 | ||
281 | static void bfin_timer_ack(void) | ||
282 | { | ||
283 | } | ||
284 | |||
135 | static void __init bfin_timer_init(void) | 285 | static void __init bfin_timer_init(void) |
136 | { | 286 | { |
137 | /* power up the timer, but don't enable it just yet */ | 287 | /* power up the timer, but don't enable it just yet */ |
@@ -145,38 +295,32 @@ static void __init bfin_timer_init(void) | |||
145 | bfin_write_TPERIOD(0); | 295 | bfin_write_TPERIOD(0); |
146 | bfin_write_TCOUNT(0); | 296 | bfin_write_TCOUNT(0); |
147 | 297 | ||
148 | /* now enable the timer */ | ||
149 | CSYNC(); | 298 | CSYNC(); |
150 | } | 299 | } |
151 | 300 | ||
301 | static unsigned long __init bfin_clockevent_check(void) | ||
302 | { | ||
303 | setup_irq(IRQ_CORETMR, &bfin_timer_irq); | ||
304 | return get_cclk() / TIME_SCALE; | ||
305 | } | ||
306 | |||
307 | void __init setup_core_timer(void) | ||
308 | { | ||
309 | bfin_timer_init(); | ||
310 | bfin_timer_set_mode(CLOCK_EVT_MODE_PERIODIC, NULL); | ||
311 | } | ||
312 | #endif /* CONFIG_TICKSOURCE_GPTMR0 */ | ||
313 | |||
152 | /* | 314 | /* |
153 | * timer_interrupt() needs to keep up the real-time clock, | 315 | * timer_interrupt() needs to keep up the real-time clock, |
154 | * as well as call the "do_timer()" routine every clocktick | 316 | * as well as call the "do_timer()" routine every clocktick |
155 | */ | 317 | */ |
156 | #ifdef CONFIG_CORE_TIMER_IRQ_L1 | ||
157 | __attribute__((l1_text)) | ||
158 | #endif | ||
159 | irqreturn_t timer_interrupt(int irq, void *dev_id); | ||
160 | |||
161 | static struct clock_event_device clockevent_bfin = { | ||
162 | .name = "bfin_core_timer", | ||
163 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | ||
164 | .shift = 32, | ||
165 | .set_next_event = bfin_timer_set_next_event, | ||
166 | .set_mode = bfin_timer_set_mode, | ||
167 | }; | ||
168 | |||
169 | static struct irqaction bfin_timer_irq = { | ||
170 | .name = "Blackfin Core Timer", | ||
171 | .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, | ||
172 | .handler = timer_interrupt, | ||
173 | .dev_id = &clockevent_bfin, | ||
174 | }; | ||
175 | |||
176 | irqreturn_t timer_interrupt(int irq, void *dev_id) | 318 | irqreturn_t timer_interrupt(int irq, void *dev_id) |
177 | { | 319 | { |
178 | struct clock_event_device *evt = dev_id; | 320 | struct clock_event_device *evt = dev_id; |
321 | smp_mb(); | ||
179 | evt->event_handler(evt); | 322 | evt->event_handler(evt); |
323 | bfin_timer_ack(); | ||
180 | return IRQ_HANDLED; | 324 | return IRQ_HANDLED; |
181 | } | 325 | } |
182 | 326 | ||
@@ -184,9 +328,8 @@ static int __init bfin_clockevent_init(void) | |||
184 | { | 328 | { |
185 | unsigned long timer_clk; | 329 | unsigned long timer_clk; |
186 | 330 | ||
187 | timer_clk = get_cclk() / TIME_SCALE; | 331 | timer_clk = bfin_clockevent_check(); |
188 | 332 | ||
189 | setup_irq(IRQ_CORETMR, &bfin_timer_irq); | ||
190 | bfin_timer_init(); | 333 | bfin_timer_init(); |
191 | 334 | ||
192 | clockevent_bfin.mult = div_sc(timer_clk, NSEC_PER_SEC, clockevent_bfin.shift); | 335 | clockevent_bfin.mult = div_sc(timer_clk, NSEC_PER_SEC, clockevent_bfin.shift); |
@@ -218,6 +361,7 @@ void __init time_init(void) | |||
218 | xtime.tv_nsec = 0; | 361 | xtime.tv_nsec = 0; |
219 | set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec); | 362 | set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec); |
220 | 363 | ||
221 | bfin_clocksource_init(); | 364 | bfin_cs_cycles_init(); |
365 | bfin_cs_gptimer0_init(); | ||
222 | bfin_clockevent_init(); | 366 | bfin_clockevent_init(); |
223 | } | 367 | } |
diff --git a/arch/blackfin/kernel/time.c b/arch/blackfin/kernel/time.c index 1bbacfbd4c5d..adb54aa7d7c8 100644 --- a/arch/blackfin/kernel/time.c +++ b/arch/blackfin/kernel/time.c | |||
@@ -24,14 +24,10 @@ | |||
24 | 24 | ||
25 | static struct irqaction bfin_timer_irq = { | 25 | static struct irqaction bfin_timer_irq = { |
26 | .name = "Blackfin Timer Tick", | 26 | .name = "Blackfin Timer Tick", |
27 | #ifdef CONFIG_IRQ_PER_CPU | ||
28 | .flags = IRQF_DISABLED | IRQF_PERCPU, | ||
29 | #else | ||
30 | .flags = IRQF_DISABLED | 27 | .flags = IRQF_DISABLED |
31 | #endif | ||
32 | }; | 28 | }; |
33 | 29 | ||
34 | #if defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE) | 30 | #if defined(CONFIG_IPIPE) |
35 | void __init setup_system_timer0(void) | 31 | void __init setup_system_timer0(void) |
36 | { | 32 | { |
37 | /* Power down the core timer, just to play safe. */ | 33 | /* Power down the core timer, just to play safe. */ |
@@ -74,7 +70,7 @@ void __init setup_core_timer(void) | |||
74 | static void __init | 70 | static void __init |
75 | time_sched_init(irqreturn_t(*timer_routine) (int, void *)) | 71 | time_sched_init(irqreturn_t(*timer_routine) (int, void *)) |
76 | { | 72 | { |
77 | #if defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE) | 73 | #if defined(CONFIG_IPIPE) |
78 | setup_system_timer0(); | 74 | setup_system_timer0(); |
79 | bfin_timer_irq.handler = timer_routine; | 75 | bfin_timer_irq.handler = timer_routine; |
80 | setup_irq(IRQ_TIMER0, &bfin_timer_irq); | 76 | setup_irq(IRQ_TIMER0, &bfin_timer_irq); |
@@ -94,7 +90,7 @@ static unsigned long gettimeoffset(void) | |||
94 | unsigned long offset; | 90 | unsigned long offset; |
95 | unsigned long clocks_per_jiffy; | 91 | unsigned long clocks_per_jiffy; |
96 | 92 | ||
97 | #if defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE) | 93 | #if defined(CONFIG_IPIPE) |
98 | clocks_per_jiffy = bfin_read_TIMER0_PERIOD(); | 94 | clocks_per_jiffy = bfin_read_TIMER0_PERIOD(); |
99 | offset = bfin_read_TIMER0_COUNTER() / \ | 95 | offset = bfin_read_TIMER0_COUNTER() / \ |
100 | (((clocks_per_jiffy + 1) * HZ) / USEC_PER_SEC); | 96 | (((clocks_per_jiffy + 1) * HZ) / USEC_PER_SEC); |
@@ -133,36 +129,25 @@ irqreturn_t timer_interrupt(int irq, void *dummy) | |||
133 | static long last_rtc_update; | 129 | static long last_rtc_update; |
134 | 130 | ||
135 | write_seqlock(&xtime_lock); | 131 | write_seqlock(&xtime_lock); |
136 | #if defined(CONFIG_TICK_SOURCE_SYSTMR0) && !defined(CONFIG_IPIPE) | 132 | do_timer(1); |
133 | |||
137 | /* | 134 | /* |
138 | * TIMIL0 is latched in __ipipe_grab_irq() when the I-Pipe is | 135 | * If we have an externally synchronized Linux clock, then update |
139 | * enabled. | 136 | * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be |
137 | * called as close as possible to 500 ms before the new second starts. | ||
140 | */ | 138 | */ |
141 | if (get_gptimer_status(0) & TIMER_STATUS_TIMIL0) { | 139 | if (ntp_synced() && |
142 | #endif | 140 | xtime.tv_sec > last_rtc_update + 660 && |
143 | do_timer(1); | 141 | (xtime.tv_nsec / NSEC_PER_USEC) >= |
144 | 142 | 500000 - ((unsigned)TICK_SIZE) / 2 | |
145 | /* | 143 | && (xtime.tv_nsec / NSEC_PER_USEC) <= |
146 | * If we have an externally synchronized Linux clock, then update | 144 | 500000 + ((unsigned)TICK_SIZE) / 2) { |
147 | * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be | 145 | if (set_rtc_mmss(xtime.tv_sec) == 0) |
148 | * called as close as possible to 500 ms before the new second starts. | 146 | last_rtc_update = xtime.tv_sec; |
149 | */ | 147 | else |
150 | if (ntp_synced() && | 148 | /* Do it again in 60s. */ |
151 | xtime.tv_sec > last_rtc_update + 660 && | 149 | last_rtc_update = xtime.tv_sec - 600; |
152 | (xtime.tv_nsec / NSEC_PER_USEC) >= | ||
153 | 500000 - ((unsigned)TICK_SIZE) / 2 | ||
154 | && (xtime.tv_nsec / NSEC_PER_USEC) <= | ||
155 | 500000 + ((unsigned)TICK_SIZE) / 2) { | ||
156 | if (set_rtc_mmss(xtime.tv_sec) == 0) | ||
157 | last_rtc_update = xtime.tv_sec; | ||
158 | else | ||
159 | /* Do it again in 60s. */ | ||
160 | last_rtc_update = xtime.tv_sec - 600; | ||
161 | } | ||
162 | #if defined(CONFIG_TICK_SOURCE_SYSTMR0) && !defined(CONFIG_IPIPE) | ||
163 | set_gptimer_status(0, TIMER_STATUS_TIMIL0); | ||
164 | } | 150 | } |
165 | #endif | ||
166 | write_sequnlock(&xtime_lock); | 151 | write_sequnlock(&xtime_lock); |
167 | 152 | ||
168 | #ifdef CONFIG_IPIPE | 153 | #ifdef CONFIG_IPIPE |
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index ffe7fb53eccb..d279552fe9b0 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c | |||
@@ -27,6 +27,7 @@ | |||
27 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 27 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include <linux/bug.h> | ||
30 | #include <linux/uaccess.h> | 31 | #include <linux/uaccess.h> |
31 | #include <linux/interrupt.h> | 32 | #include <linux/interrupt.h> |
32 | #include <linux/module.h> | 33 | #include <linux/module.h> |
@@ -68,6 +69,13 @@ | |||
68 | ({ if (0) printk(fmt, ##arg); 0; }) | 69 | ({ if (0) printk(fmt, ##arg); 0; }) |
69 | #endif | 70 | #endif |
70 | 71 | ||
72 | #if defined(CONFIG_DEBUG_MMRS) || defined(CONFIG_DEBUG_MMRS_MODULE) | ||
73 | u32 last_seqstat; | ||
74 | #ifdef CONFIG_DEBUG_MMRS_MODULE | ||
75 | EXPORT_SYMBOL(last_seqstat); | ||
76 | #endif | ||
77 | #endif | ||
78 | |||
71 | /* Initiate the event table handler */ | 79 | /* Initiate the event table handler */ |
72 | void __init trap_init(void) | 80 | void __init trap_init(void) |
73 | { | 81 | { |
@@ -79,7 +87,6 @@ void __init trap_init(void) | |||
79 | static void decode_address(char *buf, unsigned long address) | 87 | static void decode_address(char *buf, unsigned long address) |
80 | { | 88 | { |
81 | #ifdef CONFIG_DEBUG_VERBOSE | 89 | #ifdef CONFIG_DEBUG_VERBOSE |
82 | struct vm_list_struct *vml; | ||
83 | struct task_struct *p; | 90 | struct task_struct *p; |
84 | struct mm_struct *mm; | 91 | struct mm_struct *mm; |
85 | unsigned long flags, offset; | 92 | unsigned long flags, offset; |
@@ -196,6 +203,11 @@ done: | |||
196 | 203 | ||
197 | asmlinkage void double_fault_c(struct pt_regs *fp) | 204 | asmlinkage void double_fault_c(struct pt_regs *fp) |
198 | { | 205 | { |
206 | #ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON | ||
207 | int j; | ||
208 | trace_buffer_save(j); | ||
209 | #endif | ||
210 | |||
199 | console_verbose(); | 211 | console_verbose(); |
200 | oops_in_progress = 1; | 212 | oops_in_progress = 1; |
201 | #ifdef CONFIG_DEBUG_VERBOSE | 213 | #ifdef CONFIG_DEBUG_VERBOSE |
@@ -220,10 +232,16 @@ asmlinkage void double_fault_c(struct pt_regs *fp) | |||
220 | dump_bfin_process(fp); | 232 | dump_bfin_process(fp); |
221 | dump_bfin_mem(fp); | 233 | dump_bfin_mem(fp); |
222 | show_regs(fp); | 234 | show_regs(fp); |
235 | dump_bfin_trace_buffer(); | ||
223 | } | 236 | } |
224 | #endif | 237 | #endif |
225 | panic("Double Fault - unrecoverable event\n"); | 238 | panic("Double Fault - unrecoverable event"); |
239 | |||
240 | } | ||
226 | 241 | ||
242 | static int kernel_mode_regs(struct pt_regs *regs) | ||
243 | { | ||
244 | return regs->ipend & 0xffc0; | ||
227 | } | 245 | } |
228 | 246 | ||
229 | asmlinkage void trap_c(struct pt_regs *fp) | 247 | asmlinkage void trap_c(struct pt_regs *fp) |
@@ -234,37 +252,24 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
234 | #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO | 252 | #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO |
235 | unsigned int cpu = smp_processor_id(); | 253 | unsigned int cpu = smp_processor_id(); |
236 | #endif | 254 | #endif |
255 | const char *strerror = NULL; | ||
237 | int sig = 0; | 256 | int sig = 0; |
238 | siginfo_t info; | 257 | siginfo_t info; |
239 | unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE; | 258 | unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE; |
240 | 259 | ||
241 | trace_buffer_save(j); | 260 | trace_buffer_save(j); |
261 | #if defined(CONFIG_DEBUG_MMRS) || defined(CONFIG_DEBUG_MMRS_MODULE) | ||
262 | last_seqstat = (u32)fp->seqstat; | ||
263 | #endif | ||
242 | 264 | ||
243 | /* Important - be very careful dereferncing pointers - will lead to | 265 | /* Important - be very careful dereferncing pointers - will lead to |
244 | * double faults if the stack has become corrupt | 266 | * double faults if the stack has become corrupt |
245 | */ | 267 | */ |
246 | 268 | ||
247 | /* If the fault was caused by a kernel thread, or interrupt handler | 269 | #ifndef CONFIG_KGDB |
248 | * we will kernel panic, so the system reboots. | 270 | /* IPEND is skipped if KGDB isn't enabled (see entry code) */ |
249 | * If KGDB is enabled, don't set this for kernel breakpoints | 271 | fp->ipend = bfin_read_IPEND(); |
250 | */ | ||
251 | |||
252 | /* TODO: check to see if we are in some sort of deferred HWERR | ||
253 | * that we should be able to recover from, not kernel panic | ||
254 | */ | ||
255 | if ((bfin_read_IPEND() & 0xFFC0) && (trapnr != VEC_STEP) | ||
256 | #ifdef CONFIG_KGDB | ||
257 | && (trapnr != VEC_EXCPT02) | ||
258 | #endif | 272 | #endif |
259 | ){ | ||
260 | console_verbose(); | ||
261 | oops_in_progress = 1; | ||
262 | } else if (current) { | ||
263 | if (current->mm == NULL) { | ||
264 | console_verbose(); | ||
265 | oops_in_progress = 1; | ||
266 | } | ||
267 | } | ||
268 | 273 | ||
269 | /* trap_c() will be called for exceptions. During exceptions | 274 | /* trap_c() will be called for exceptions. During exceptions |
270 | * processing, the pc value should be set with retx value. | 275 | * processing, the pc value should be set with retx value. |
@@ -292,15 +297,15 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
292 | sig = SIGTRAP; | 297 | sig = SIGTRAP; |
293 | CHK_DEBUGGER_TRAP_MAYBE(); | 298 | CHK_DEBUGGER_TRAP_MAYBE(); |
294 | /* Check if this is a breakpoint in kernel space */ | 299 | /* Check if this is a breakpoint in kernel space */ |
295 | if (fp->ipend & 0xffc0) | 300 | if (kernel_mode_regs(fp)) |
296 | return; | 301 | goto traps_done; |
297 | else | 302 | else |
298 | break; | 303 | break; |
299 | /* 0x03 - User Defined, userspace stack overflow */ | 304 | /* 0x03 - User Defined, userspace stack overflow */ |
300 | case VEC_EXCPT03: | 305 | case VEC_EXCPT03: |
301 | info.si_code = SEGV_STACKFLOW; | 306 | info.si_code = SEGV_STACKFLOW; |
302 | sig = SIGSEGV; | 307 | sig = SIGSEGV; |
303 | verbose_printk(KERN_NOTICE EXC_0x03(KERN_NOTICE)); | 308 | strerror = KERN_NOTICE EXC_0x03(KERN_NOTICE); |
304 | CHK_DEBUGGER_TRAP_MAYBE(); | 309 | CHK_DEBUGGER_TRAP_MAYBE(); |
305 | break; | 310 | break; |
306 | /* 0x02 - KGDB initial connection and break signal trap */ | 311 | /* 0x02 - KGDB initial connection and break signal trap */ |
@@ -309,7 +314,7 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
309 | info.si_code = TRAP_ILLTRAP; | 314 | info.si_code = TRAP_ILLTRAP; |
310 | sig = SIGTRAP; | 315 | sig = SIGTRAP; |
311 | CHK_DEBUGGER_TRAP(); | 316 | CHK_DEBUGGER_TRAP(); |
312 | return; | 317 | goto traps_done; |
313 | #endif | 318 | #endif |
314 | /* 0x04 - User Defined */ | 319 | /* 0x04 - User Defined */ |
315 | /* 0x05 - User Defined */ | 320 | /* 0x05 - User Defined */ |
@@ -329,7 +334,7 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
329 | case VEC_EXCPT04 ... VEC_EXCPT15: | 334 | case VEC_EXCPT04 ... VEC_EXCPT15: |
330 | info.si_code = ILL_ILLPARAOP; | 335 | info.si_code = ILL_ILLPARAOP; |
331 | sig = SIGILL; | 336 | sig = SIGILL; |
332 | verbose_printk(KERN_NOTICE EXC_0x04(KERN_NOTICE)); | 337 | strerror = KERN_NOTICE EXC_0x04(KERN_NOTICE); |
333 | CHK_DEBUGGER_TRAP_MAYBE(); | 338 | CHK_DEBUGGER_TRAP_MAYBE(); |
334 | break; | 339 | break; |
335 | /* 0x10 HW Single step, handled here */ | 340 | /* 0x10 HW Single step, handled here */ |
@@ -338,15 +343,15 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
338 | sig = SIGTRAP; | 343 | sig = SIGTRAP; |
339 | CHK_DEBUGGER_TRAP_MAYBE(); | 344 | CHK_DEBUGGER_TRAP_MAYBE(); |
340 | /* Check if this is a single step in kernel space */ | 345 | /* Check if this is a single step in kernel space */ |
341 | if (fp->ipend & 0xffc0) | 346 | if (kernel_mode_regs(fp)) |
342 | return; | 347 | goto traps_done; |
343 | else | 348 | else |
344 | break; | 349 | break; |
345 | /* 0x11 - Trace Buffer Full, handled here */ | 350 | /* 0x11 - Trace Buffer Full, handled here */ |
346 | case VEC_OVFLOW: | 351 | case VEC_OVFLOW: |
347 | info.si_code = TRAP_TRACEFLOW; | 352 | info.si_code = TRAP_TRACEFLOW; |
348 | sig = SIGTRAP; | 353 | sig = SIGTRAP; |
349 | verbose_printk(KERN_NOTICE EXC_0x11(KERN_NOTICE)); | 354 | strerror = KERN_NOTICE EXC_0x11(KERN_NOTICE); |
350 | CHK_DEBUGGER_TRAP_MAYBE(); | 355 | CHK_DEBUGGER_TRAP_MAYBE(); |
351 | break; | 356 | break; |
352 | /* 0x12 - Reserved, Caught by default */ | 357 | /* 0x12 - Reserved, Caught by default */ |
@@ -366,37 +371,54 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
366 | /* 0x20 - Reserved, Caught by default */ | 371 | /* 0x20 - Reserved, Caught by default */ |
367 | /* 0x21 - Undefined Instruction, handled here */ | 372 | /* 0x21 - Undefined Instruction, handled here */ |
368 | case VEC_UNDEF_I: | 373 | case VEC_UNDEF_I: |
374 | #ifdef CONFIG_BUG | ||
375 | if (kernel_mode_regs(fp)) { | ||
376 | switch (report_bug(fp->pc, fp)) { | ||
377 | case BUG_TRAP_TYPE_NONE: | ||
378 | break; | ||
379 | case BUG_TRAP_TYPE_WARN: | ||
380 | dump_bfin_trace_buffer(); | ||
381 | fp->pc += 2; | ||
382 | goto traps_done; | ||
383 | case BUG_TRAP_TYPE_BUG: | ||
384 | /* call to panic() will dump trace, and it is | ||
385 | * off at this point, so it won't be clobbered | ||
386 | */ | ||
387 | panic("BUG()"); | ||
388 | } | ||
389 | } | ||
390 | #endif | ||
369 | info.si_code = ILL_ILLOPC; | 391 | info.si_code = ILL_ILLOPC; |
370 | sig = SIGILL; | 392 | sig = SIGILL; |
371 | verbose_printk(KERN_NOTICE EXC_0x21(KERN_NOTICE)); | 393 | strerror = KERN_NOTICE EXC_0x21(KERN_NOTICE); |
372 | CHK_DEBUGGER_TRAP_MAYBE(); | 394 | CHK_DEBUGGER_TRAP_MAYBE(); |
373 | break; | 395 | break; |
374 | /* 0x22 - Illegal Instruction Combination, handled here */ | 396 | /* 0x22 - Illegal Instruction Combination, handled here */ |
375 | case VEC_ILGAL_I: | 397 | case VEC_ILGAL_I: |
376 | info.si_code = ILL_ILLPARAOP; | 398 | info.si_code = ILL_ILLPARAOP; |
377 | sig = SIGILL; | 399 | sig = SIGILL; |
378 | verbose_printk(KERN_NOTICE EXC_0x22(KERN_NOTICE)); | 400 | strerror = KERN_NOTICE EXC_0x22(KERN_NOTICE); |
379 | CHK_DEBUGGER_TRAP_MAYBE(); | 401 | CHK_DEBUGGER_TRAP_MAYBE(); |
380 | break; | 402 | break; |
381 | /* 0x23 - Data CPLB protection violation, handled here */ | 403 | /* 0x23 - Data CPLB protection violation, handled here */ |
382 | case VEC_CPLB_VL: | 404 | case VEC_CPLB_VL: |
383 | info.si_code = ILL_CPLB_VI; | 405 | info.si_code = ILL_CPLB_VI; |
384 | sig = SIGBUS; | 406 | sig = SIGBUS; |
385 | verbose_printk(KERN_NOTICE EXC_0x23(KERN_NOTICE)); | 407 | strerror = KERN_NOTICE EXC_0x23(KERN_NOTICE); |
386 | CHK_DEBUGGER_TRAP_MAYBE(); | 408 | CHK_DEBUGGER_TRAP_MAYBE(); |
387 | break; | 409 | break; |
388 | /* 0x24 - Data access misaligned, handled here */ | 410 | /* 0x24 - Data access misaligned, handled here */ |
389 | case VEC_MISALI_D: | 411 | case VEC_MISALI_D: |
390 | info.si_code = BUS_ADRALN; | 412 | info.si_code = BUS_ADRALN; |
391 | sig = SIGBUS; | 413 | sig = SIGBUS; |
392 | verbose_printk(KERN_NOTICE EXC_0x24(KERN_NOTICE)); | 414 | strerror = KERN_NOTICE EXC_0x24(KERN_NOTICE); |
393 | CHK_DEBUGGER_TRAP_MAYBE(); | 415 | CHK_DEBUGGER_TRAP_MAYBE(); |
394 | break; | 416 | break; |
395 | /* 0x25 - Unrecoverable Event, handled here */ | 417 | /* 0x25 - Unrecoverable Event, handled here */ |
396 | case VEC_UNCOV: | 418 | case VEC_UNCOV: |
397 | info.si_code = ILL_ILLEXCPT; | 419 | info.si_code = ILL_ILLEXCPT; |
398 | sig = SIGILL; | 420 | sig = SIGILL; |
399 | verbose_printk(KERN_NOTICE EXC_0x25(KERN_NOTICE)); | 421 | strerror = KERN_NOTICE EXC_0x25(KERN_NOTICE); |
400 | CHK_DEBUGGER_TRAP_MAYBE(); | 422 | CHK_DEBUGGER_TRAP_MAYBE(); |
401 | break; | 423 | break; |
402 | /* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr, | 424 | /* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr, |
@@ -404,7 +426,7 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
404 | case VEC_CPLB_M: | 426 | case VEC_CPLB_M: |
405 | info.si_code = BUS_ADRALN; | 427 | info.si_code = BUS_ADRALN; |
406 | sig = SIGBUS; | 428 | sig = SIGBUS; |
407 | verbose_printk(KERN_NOTICE EXC_0x26(KERN_NOTICE)); | 429 | strerror = KERN_NOTICE EXC_0x26(KERN_NOTICE); |
408 | break; | 430 | break; |
409 | /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */ | 431 | /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */ |
410 | case VEC_CPLB_MHIT: | 432 | case VEC_CPLB_MHIT: |
@@ -412,10 +434,10 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
412 | sig = SIGSEGV; | 434 | sig = SIGSEGV; |
413 | #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO | 435 | #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO |
414 | if (cpu_pda[cpu].dcplb_fault_addr < FIXED_CODE_START) | 436 | if (cpu_pda[cpu].dcplb_fault_addr < FIXED_CODE_START) |
415 | verbose_printk(KERN_NOTICE "NULL pointer access\n"); | 437 | strerror = KERN_NOTICE "NULL pointer access\n"; |
416 | else | 438 | else |
417 | #endif | 439 | #endif |
418 | verbose_printk(KERN_NOTICE EXC_0x27(KERN_NOTICE)); | 440 | strerror = KERN_NOTICE EXC_0x27(KERN_NOTICE); |
419 | CHK_DEBUGGER_TRAP_MAYBE(); | 441 | CHK_DEBUGGER_TRAP_MAYBE(); |
420 | break; | 442 | break; |
421 | /* 0x28 - Emulation Watchpoint, handled here */ | 443 | /* 0x28 - Emulation Watchpoint, handled here */ |
@@ -425,8 +447,8 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
425 | pr_debug(EXC_0x28(KERN_DEBUG)); | 447 | pr_debug(EXC_0x28(KERN_DEBUG)); |
426 | CHK_DEBUGGER_TRAP_MAYBE(); | 448 | CHK_DEBUGGER_TRAP_MAYBE(); |
427 | /* Check if this is a watchpoint in kernel space */ | 449 | /* Check if this is a watchpoint in kernel space */ |
428 | if (fp->ipend & 0xffc0) | 450 | if (kernel_mode_regs(fp)) |
429 | return; | 451 | goto traps_done; |
430 | else | 452 | else |
431 | break; | 453 | break; |
432 | #ifdef CONFIG_BF535 | 454 | #ifdef CONFIG_BF535 |
@@ -434,7 +456,7 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
434 | case VEC_ISTRU_VL: /* ADSP-BF535 only (MH) */ | 456 | case VEC_ISTRU_VL: /* ADSP-BF535 only (MH) */ |
435 | info.si_code = BUS_OPFETCH; | 457 | info.si_code = BUS_OPFETCH; |
436 | sig = SIGBUS; | 458 | sig = SIGBUS; |
437 | verbose_printk(KERN_NOTICE "BF535: VEC_ISTRU_VL\n"); | 459 | strerror = KERN_NOTICE "BF535: VEC_ISTRU_VL\n"; |
438 | CHK_DEBUGGER_TRAP_MAYBE(); | 460 | CHK_DEBUGGER_TRAP_MAYBE(); |
439 | break; | 461 | break; |
440 | #else | 462 | #else |
@@ -444,21 +466,21 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
444 | case VEC_MISALI_I: | 466 | case VEC_MISALI_I: |
445 | info.si_code = BUS_ADRALN; | 467 | info.si_code = BUS_ADRALN; |
446 | sig = SIGBUS; | 468 | sig = SIGBUS; |
447 | verbose_printk(KERN_NOTICE EXC_0x2A(KERN_NOTICE)); | 469 | strerror = KERN_NOTICE EXC_0x2A(KERN_NOTICE); |
448 | CHK_DEBUGGER_TRAP_MAYBE(); | 470 | CHK_DEBUGGER_TRAP_MAYBE(); |
449 | break; | 471 | break; |
450 | /* 0x2B - Instruction CPLB protection violation, handled here */ | 472 | /* 0x2B - Instruction CPLB protection violation, handled here */ |
451 | case VEC_CPLB_I_VL: | 473 | case VEC_CPLB_I_VL: |
452 | info.si_code = ILL_CPLB_VI; | 474 | info.si_code = ILL_CPLB_VI; |
453 | sig = SIGBUS; | 475 | sig = SIGBUS; |
454 | verbose_printk(KERN_NOTICE EXC_0x2B(KERN_NOTICE)); | 476 | strerror = KERN_NOTICE EXC_0x2B(KERN_NOTICE); |
455 | CHK_DEBUGGER_TRAP_MAYBE(); | 477 | CHK_DEBUGGER_TRAP_MAYBE(); |
456 | break; | 478 | break; |
457 | /* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */ | 479 | /* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */ |
458 | case VEC_CPLB_I_M: | 480 | case VEC_CPLB_I_M: |
459 | info.si_code = ILL_CPLB_MISS; | 481 | info.si_code = ILL_CPLB_MISS; |
460 | sig = SIGBUS; | 482 | sig = SIGBUS; |
461 | verbose_printk(KERN_NOTICE EXC_0x2C(KERN_NOTICE)); | 483 | strerror = KERN_NOTICE EXC_0x2C(KERN_NOTICE); |
462 | break; | 484 | break; |
463 | /* 0x2D - Instruction CPLB Multiple Hits, handled here */ | 485 | /* 0x2D - Instruction CPLB Multiple Hits, handled here */ |
464 | case VEC_CPLB_I_MHIT: | 486 | case VEC_CPLB_I_MHIT: |
@@ -466,17 +488,17 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
466 | sig = SIGSEGV; | 488 | sig = SIGSEGV; |
467 | #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO | 489 | #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO |
468 | if (cpu_pda[cpu].icplb_fault_addr < FIXED_CODE_START) | 490 | if (cpu_pda[cpu].icplb_fault_addr < FIXED_CODE_START) |
469 | verbose_printk(KERN_NOTICE "Jump to NULL address\n"); | 491 | strerror = KERN_NOTICE "Jump to NULL address\n"; |
470 | else | 492 | else |
471 | #endif | 493 | #endif |
472 | verbose_printk(KERN_NOTICE EXC_0x2D(KERN_NOTICE)); | 494 | strerror = KERN_NOTICE EXC_0x2D(KERN_NOTICE); |
473 | CHK_DEBUGGER_TRAP_MAYBE(); | 495 | CHK_DEBUGGER_TRAP_MAYBE(); |
474 | break; | 496 | break; |
475 | /* 0x2E - Illegal use of Supervisor Resource, handled here */ | 497 | /* 0x2E - Illegal use of Supervisor Resource, handled here */ |
476 | case VEC_ILL_RES: | 498 | case VEC_ILL_RES: |
477 | info.si_code = ILL_PRVOPC; | 499 | info.si_code = ILL_PRVOPC; |
478 | sig = SIGILL; | 500 | sig = SIGILL; |
479 | verbose_printk(KERN_NOTICE EXC_0x2E(KERN_NOTICE)); | 501 | strerror = KERN_NOTICE EXC_0x2E(KERN_NOTICE); |
480 | CHK_DEBUGGER_TRAP_MAYBE(); | 502 | CHK_DEBUGGER_TRAP_MAYBE(); |
481 | break; | 503 | break; |
482 | /* 0x2F - Reserved, Caught by default */ | 504 | /* 0x2F - Reserved, Caught by default */ |
@@ -504,17 +526,17 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
504 | case (SEQSTAT_HWERRCAUSE_SYSTEM_MMR): | 526 | case (SEQSTAT_HWERRCAUSE_SYSTEM_MMR): |
505 | info.si_code = BUS_ADRALN; | 527 | info.si_code = BUS_ADRALN; |
506 | sig = SIGBUS; | 528 | sig = SIGBUS; |
507 | verbose_printk(KERN_NOTICE HWC_x2(KERN_NOTICE)); | 529 | strerror = KERN_NOTICE HWC_x2(KERN_NOTICE); |
508 | break; | 530 | break; |
509 | /* External Memory Addressing Error */ | 531 | /* External Memory Addressing Error */ |
510 | case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR): | 532 | case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR): |
511 | info.si_code = BUS_ADRERR; | 533 | info.si_code = BUS_ADRERR; |
512 | sig = SIGBUS; | 534 | sig = SIGBUS; |
513 | verbose_printk(KERN_NOTICE HWC_x3(KERN_NOTICE)); | 535 | strerror = KERN_NOTICE HWC_x3(KERN_NOTICE); |
514 | break; | 536 | break; |
515 | /* Performance Monitor Overflow */ | 537 | /* Performance Monitor Overflow */ |
516 | case (SEQSTAT_HWERRCAUSE_PERF_FLOW): | 538 | case (SEQSTAT_HWERRCAUSE_PERF_FLOW): |
517 | verbose_printk(KERN_NOTICE HWC_x12(KERN_NOTICE)); | 539 | strerror = KERN_NOTICE HWC_x12(KERN_NOTICE); |
518 | break; | 540 | break; |
519 | /* RAISE 5 instruction */ | 541 | /* RAISE 5 instruction */ |
520 | case (SEQSTAT_HWERRCAUSE_RAISE_5): | 542 | case (SEQSTAT_HWERRCAUSE_RAISE_5): |
@@ -531,7 +553,6 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
531 | * if we get here we hit a reserved one, so panic | 553 | * if we get here we hit a reserved one, so panic |
532 | */ | 554 | */ |
533 | default: | 555 | default: |
534 | oops_in_progress = 1; | ||
535 | info.si_code = ILL_ILLPARAOP; | 556 | info.si_code = ILL_ILLPARAOP; |
536 | sig = SIGILL; | 557 | sig = SIGILL; |
537 | verbose_printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n", | 558 | verbose_printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n", |
@@ -542,6 +563,16 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
542 | 563 | ||
543 | BUG_ON(sig == 0); | 564 | BUG_ON(sig == 0); |
544 | 565 | ||
566 | /* If the fault was caused by a kernel thread, or interrupt handler | ||
567 | * we will kernel panic, so the system reboots. | ||
568 | */ | ||
569 | if (kernel_mode_regs(fp) || (current && !current->mm)) { | ||
570 | console_verbose(); | ||
571 | oops_in_progress = 1; | ||
572 | if (strerror) | ||
573 | verbose_printk(strerror); | ||
574 | } | ||
575 | |||
545 | if (sig != SIGTRAP) { | 576 | if (sig != SIGTRAP) { |
546 | dump_bfin_process(fp); | 577 | dump_bfin_process(fp); |
547 | dump_bfin_mem(fp); | 578 | dump_bfin_mem(fp); |
@@ -588,8 +619,11 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
588 | force_sig_info(sig, &info, current); | 619 | force_sig_info(sig, &info, current); |
589 | } | 620 | } |
590 | 621 | ||
622 | if (ANOMALY_05000461 && trapnr == VEC_HWERR && !access_ok(VERIFY_READ, fp->pc, 8)) | ||
623 | fp->pc = SAFE_USER_INSTRUCTION; | ||
624 | |||
625 | traps_done: | ||
591 | trace_buffer_restore(j); | 626 | trace_buffer_restore(j); |
592 | return; | ||
593 | } | 627 | } |
594 | 628 | ||
595 | /* Typical exception handling routines */ | 629 | /* Typical exception handling routines */ |
@@ -774,6 +808,18 @@ void dump_bfin_trace_buffer(void) | |||
774 | } | 808 | } |
775 | EXPORT_SYMBOL(dump_bfin_trace_buffer); | 809 | EXPORT_SYMBOL(dump_bfin_trace_buffer); |
776 | 810 | ||
811 | #ifdef CONFIG_BUG | ||
812 | int is_valid_bugaddr(unsigned long addr) | ||
813 | { | ||
814 | unsigned short opcode; | ||
815 | |||
816 | if (!get_instruction(&opcode, (unsigned short *)addr)) | ||
817 | return 0; | ||
818 | |||
819 | return opcode == BFIN_BUG_OPCODE; | ||
820 | } | ||
821 | #endif | ||
822 | |||
777 | /* | 823 | /* |
778 | * Checks to see if the address pointed to is either a | 824 | * Checks to see if the address pointed to is either a |
779 | * 16-bit CALL instruction, or a 32-bit CALL instruction | 825 | * 16-bit CALL instruction, or a 32-bit CALL instruction |
@@ -832,6 +878,11 @@ void show_stack(struct task_struct *task, unsigned long *stack) | |||
832 | decode_address(buf, (unsigned int)stack); | 878 | decode_address(buf, (unsigned int)stack); |
833 | printk(KERN_NOTICE " SP: [0x%p] %s\n", stack, buf); | 879 | printk(KERN_NOTICE " SP: [0x%p] %s\n", stack, buf); |
834 | 880 | ||
881 | if (!access_ok(VERIFY_READ, stack, (unsigned int)endstack - (unsigned int)stack)) { | ||
882 | printk(KERN_NOTICE "Invalid stack pointer\n"); | ||
883 | return; | ||
884 | } | ||
885 | |||
835 | /* First thing is to look for a frame pointer */ | 886 | /* First thing is to look for a frame pointer */ |
836 | for (addr = (unsigned int *)((unsigned int)stack & ~0xF); addr < endstack; addr++) { | 887 | for (addr = (unsigned int *)((unsigned int)stack & ~0xF); addr < endstack; addr++) { |
837 | if (*addr & 0x1) | 888 | if (*addr & 0x1) |
@@ -1066,6 +1117,29 @@ void show_regs(struct pt_regs *fp) | |||
1066 | unsigned int cpu = smp_processor_id(); | 1117 | unsigned int cpu = smp_processor_id(); |
1067 | unsigned char in_atomic = (bfin_read_IPEND() & 0x10) || in_atomic(); | 1118 | unsigned char in_atomic = (bfin_read_IPEND() & 0x10) || in_atomic(); |
1068 | 1119 | ||
1120 | verbose_printk(KERN_NOTICE "\n"); | ||
1121 | if (CPUID != bfin_cpuid()) | ||
1122 | verbose_printk(KERN_NOTICE "Compiled for cpu family 0x%04x (Rev %d), " | ||
1123 | "but running on:0x%04x (Rev %d)\n", | ||
1124 | CPUID, bfin_compiled_revid(), bfin_cpuid(), bfin_revid()); | ||
1125 | |||
1126 | verbose_printk(KERN_NOTICE "ADSP-%s-0.%d", | ||
1127 | CPU, bfin_compiled_revid()); | ||
1128 | |||
1129 | if (bfin_compiled_revid() != bfin_revid()) | ||
1130 | verbose_printk("(Detected 0.%d)", bfin_revid()); | ||
1131 | |||
1132 | verbose_printk(" %lu(MHz CCLK) %lu(MHz SCLK) (%s)\n", | ||
1133 | get_cclk()/1000000, get_sclk()/1000000, | ||
1134 | #ifdef CONFIG_MPU | ||
1135 | "mpu on" | ||
1136 | #else | ||
1137 | "mpu off" | ||
1138 | #endif | ||
1139 | ); | ||
1140 | |||
1141 | verbose_printk(KERN_NOTICE "%s", linux_banner); | ||
1142 | |||
1069 | verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted()); | 1143 | verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted()); |
1070 | verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", | 1144 | verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", |
1071 | (long)fp->seqstat, fp->ipend, fp->syscfg); | 1145 | (long)fp->seqstat, fp->ipend, fp->syscfg); |
@@ -1246,5 +1320,5 @@ void panic_cplb_error(int cplb_panic, struct pt_regs *fp) | |||
1246 | dump_bfin_mem(fp); | 1320 | dump_bfin_mem(fp); |
1247 | show_regs(fp); | 1321 | show_regs(fp); |
1248 | dump_stack(); | 1322 | dump_stack(); |
1249 | panic("Unrecoverable event\n"); | 1323 | panic("Unrecoverable event"); |
1250 | } | 1324 | } |
diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S index 27952ae047d8..6ac307ca0d80 100644 --- a/arch/blackfin/kernel/vmlinux.lds.S +++ b/arch/blackfin/kernel/vmlinux.lds.S | |||
@@ -50,8 +50,11 @@ SECTIONS | |||
50 | _text = .; | 50 | _text = .; |
51 | __stext = .; | 51 | __stext = .; |
52 | TEXT_TEXT | 52 | TEXT_TEXT |
53 | #ifndef CONFIG_SCHEDULE_L1 | ||
53 | SCHED_TEXT | 54 | SCHED_TEXT |
55 | #endif | ||
54 | LOCK_TEXT | 56 | LOCK_TEXT |
57 | IRQENTRY_TEXT | ||
55 | KPROBES_TEXT | 58 | KPROBES_TEXT |
56 | *(.text.*) | 59 | *(.text.*) |
57 | *(.fixup) | 60 | *(.fixup) |
@@ -164,6 +167,20 @@ SECTIONS | |||
164 | } | 167 | } |
165 | PERCPU(4) | 168 | PERCPU(4) |
166 | SECURITY_INIT | 169 | SECURITY_INIT |
170 | |||
171 | /* we have to discard exit text and such at runtime, not link time, to | ||
172 | * handle embedded cross-section references (alt instructions, bug | ||
173 | * table, eh_frame, etc...) | ||
174 | */ | ||
175 | .exit.text : | ||
176 | { | ||
177 | EXIT_TEXT | ||
178 | } | ||
179 | .exit.data : | ||
180 | { | ||
181 | EXIT_DATA | ||
182 | } | ||
183 | |||
167 | .init.ramfs : | 184 | .init.ramfs : |
168 | { | 185 | { |
169 | . = ALIGN(4); | 186 | . = ALIGN(4); |
@@ -180,6 +197,9 @@ SECTIONS | |||
180 | . = ALIGN(4); | 197 | . = ALIGN(4); |
181 | __stext_l1 = .; | 198 | __stext_l1 = .; |
182 | *(.l1.text) | 199 | *(.l1.text) |
200 | #ifdef CONFIG_SCHEDULE_L1 | ||
201 | SCHED_TEXT | ||
202 | #endif | ||
183 | . = ALIGN(4); | 203 | . = ALIGN(4); |
184 | __etext_l1 = .; | 204 | __etext_l1 = .; |
185 | } | 205 | } |
@@ -259,8 +279,6 @@ SECTIONS | |||
259 | 279 | ||
260 | /DISCARD/ : | 280 | /DISCARD/ : |
261 | { | 281 | { |
262 | EXIT_TEXT | ||
263 | EXIT_DATA | ||
264 | *(.exitcall.exit) | 282 | *(.exitcall.exit) |
265 | } | 283 | } |
266 | } | 284 | } |