aboutsummaryrefslogtreecommitdiffstats
path: root/arch/avr32/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/avr32/kernel')
-rw-r--r--arch/avr32/kernel/cpu.c38
-rw-r--r--arch/avr32/kernel/entry-avr32b.S88
-rw-r--r--arch/avr32/kernel/signal.c3
-rw-r--r--arch/avr32/kernel/stacktrace.c1
-rw-r--r--arch/avr32/kernel/time.c14
-rw-r--r--arch/avr32/kernel/vmlinux.lds.S14
6 files changed, 89 insertions, 69 deletions
diff --git a/arch/avr32/kernel/cpu.c b/arch/avr32/kernel/cpu.c
index b8409caeb23d..e84faffbbeca 100644
--- a/arch/avr32/kernel/cpu.c
+++ b/arch/avr32/kernel/cpu.c
@@ -26,14 +26,16 @@ static DEFINE_PER_CPU(struct cpu, cpu_devices);
26 * XXX: If/when a SMP-capable implementation of AVR32 will ever be 26 * XXX: If/when a SMP-capable implementation of AVR32 will ever be
27 * made, we must make sure that the code executes on the correct CPU. 27 * made, we must make sure that the code executes on the correct CPU.
28 */ 28 */
29static ssize_t show_pc0event(struct sys_device *dev, char *buf) 29static ssize_t show_pc0event(struct sys_device *dev,
30 struct sysdev_attribute *attr, char *buf)
30{ 31{
31 unsigned long pccr; 32 unsigned long pccr;
32 33
33 pccr = sysreg_read(PCCR); 34 pccr = sysreg_read(PCCR);
34 return sprintf(buf, "0x%lx\n", (pccr >> 12) & 0x3f); 35 return sprintf(buf, "0x%lx\n", (pccr >> 12) & 0x3f);
35} 36}
36static ssize_t store_pc0event(struct sys_device *dev, const char *buf, 37static ssize_t store_pc0event(struct sys_device *dev,
38 struct sysdev_attribute *attr, const char *buf,
37 size_t count) 39 size_t count)
38{ 40{
39 unsigned long val; 41 unsigned long val;
@@ -46,15 +48,17 @@ static ssize_t store_pc0event(struct sys_device *dev, const char *buf,
46 sysreg_write(PCCR, val); 48 sysreg_write(PCCR, val);
47 return count; 49 return count;
48} 50}
49static ssize_t show_pc0count(struct sys_device *dev, char *buf) 51static ssize_t show_pc0count(struct sys_device *dev,
52 struct sysdev_attribute *attr, char *buf)
50{ 53{
51 unsigned long pcnt0; 54 unsigned long pcnt0;
52 55
53 pcnt0 = sysreg_read(PCNT0); 56 pcnt0 = sysreg_read(PCNT0);
54 return sprintf(buf, "%lu\n", pcnt0); 57 return sprintf(buf, "%lu\n", pcnt0);
55} 58}
56static ssize_t store_pc0count(struct sys_device *dev, const char *buf, 59static ssize_t store_pc0count(struct sys_device *dev,
57 size_t count) 60 struct sysdev_attribute *attr,
61 const char *buf, size_t count)
58{ 62{
59 unsigned long val; 63 unsigned long val;
60 char *endp; 64 char *endp;
@@ -67,14 +71,16 @@ static ssize_t store_pc0count(struct sys_device *dev, const char *buf,
67 return count; 71 return count;
68} 72}
69 73
70static ssize_t show_pc1event(struct sys_device *dev, char *buf) 74static ssize_t show_pc1event(struct sys_device *dev,
75 struct sysdev_attribute *attr, char *buf)
71{ 76{
72 unsigned long pccr; 77 unsigned long pccr;
73 78
74 pccr = sysreg_read(PCCR); 79 pccr = sysreg_read(PCCR);
75 return sprintf(buf, "0x%lx\n", (pccr >> 18) & 0x3f); 80 return sprintf(buf, "0x%lx\n", (pccr >> 18) & 0x3f);
76} 81}
77static ssize_t store_pc1event(struct sys_device *dev, const char *buf, 82static ssize_t store_pc1event(struct sys_device *dev,
83 struct sysdev_attribute *attr, const char *buf,
78 size_t count) 84 size_t count)
79{ 85{
80 unsigned long val; 86 unsigned long val;
@@ -87,14 +93,16 @@ static ssize_t store_pc1event(struct sys_device *dev, const char *buf,
87 sysreg_write(PCCR, val); 93 sysreg_write(PCCR, val);
88 return count; 94 return count;
89} 95}
90static ssize_t show_pc1count(struct sys_device *dev, char *buf) 96static ssize_t show_pc1count(struct sys_device *dev,
97 struct sysdev_attribute *attr, char *buf)
91{ 98{
92 unsigned long pcnt1; 99 unsigned long pcnt1;
93 100
94 pcnt1 = sysreg_read(PCNT1); 101 pcnt1 = sysreg_read(PCNT1);
95 return sprintf(buf, "%lu\n", pcnt1); 102 return sprintf(buf, "%lu\n", pcnt1);
96} 103}
97static ssize_t store_pc1count(struct sys_device *dev, const char *buf, 104static ssize_t store_pc1count(struct sys_device *dev,
105 struct sysdev_attribute *attr, const char *buf,
98 size_t count) 106 size_t count)
99{ 107{
100 unsigned long val; 108 unsigned long val;
@@ -108,14 +116,16 @@ static ssize_t store_pc1count(struct sys_device *dev, const char *buf,
108 return count; 116 return count;
109} 117}
110 118
111static ssize_t show_pccycles(struct sys_device *dev, char *buf) 119static ssize_t show_pccycles(struct sys_device *dev,
120 struct sysdev_attribute *attr, char *buf)
112{ 121{
113 unsigned long pccnt; 122 unsigned long pccnt;
114 123
115 pccnt = sysreg_read(PCCNT); 124 pccnt = sysreg_read(PCCNT);
116 return sprintf(buf, "%lu\n", pccnt); 125 return sprintf(buf, "%lu\n", pccnt);
117} 126}
118static ssize_t store_pccycles(struct sys_device *dev, const char *buf, 127static ssize_t store_pccycles(struct sys_device *dev,
128 struct sysdev_attribute *attr, const char *buf,
119 size_t count) 129 size_t count)
120{ 130{
121 unsigned long val; 131 unsigned long val;
@@ -129,14 +139,16 @@ static ssize_t store_pccycles(struct sys_device *dev, const char *buf,
129 return count; 139 return count;
130} 140}
131 141
132static ssize_t show_pcenable(struct sys_device *dev, char *buf) 142static ssize_t show_pcenable(struct sys_device *dev,
143 struct sysdev_attribute *attr, char *buf)
133{ 144{
134 unsigned long pccr; 145 unsigned long pccr;
135 146
136 pccr = sysreg_read(PCCR); 147 pccr = sysreg_read(PCCR);
137 return sprintf(buf, "%c\n", (pccr & 1)?'1':'0'); 148 return sprintf(buf, "%c\n", (pccr & 1)?'1':'0');
138} 149}
139static ssize_t store_pcenable(struct sys_device *dev, const char *buf, 150static ssize_t store_pcenable(struct sys_device *dev,
151 struct sysdev_attribute *attr, const char *buf,
140 size_t count) 152 size_t count)
141{ 153{
142 unsigned long pccr, val; 154 unsigned long pccr, val;
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S
index 5f31702d6b1c..2b398cae110c 100644
--- a/arch/avr32/kernel/entry-avr32b.S
+++ b/arch/avr32/kernel/entry-avr32b.S
@@ -74,50 +74,41 @@ exception_vectors:
74 .align 2 74 .align 2
75 bral do_dtlb_modified 75 bral do_dtlb_modified
76 76
77 /*
78 * r0 : PGD/PT/PTE
79 * r1 : Offending address
80 * r2 : Scratch register
81 * r3 : Cause (5, 12 or 13)
82 */
83#define tlbmiss_save pushm r0-r3 77#define tlbmiss_save pushm r0-r3
84#define tlbmiss_restore popm r0-r3 78#define tlbmiss_restore popm r0-r3
85 79
86 .section .tlbx.ex.text,"ax",@progbits 80 .org 0x50
87 .global itlb_miss 81 .global itlb_miss
88itlb_miss: 82itlb_miss:
89 tlbmiss_save 83 tlbmiss_save
90 rjmp tlb_miss_common 84 rjmp tlb_miss_common
91 85
92 .section .tlbr.ex.text,"ax",@progbits 86 .org 0x60
93dtlb_miss_read: 87dtlb_miss_read:
94 tlbmiss_save 88 tlbmiss_save
95 rjmp tlb_miss_common 89 rjmp tlb_miss_common
96 90
97 .section .tlbw.ex.text,"ax",@progbits 91 .org 0x70
98dtlb_miss_write: 92dtlb_miss_write:
99 tlbmiss_save 93 tlbmiss_save
100 94
101 .global tlb_miss_common 95 .global tlb_miss_common
96 .align 2
102tlb_miss_common: 97tlb_miss_common:
103 mfsr r0, SYSREG_TLBEAR 98 mfsr r0, SYSREG_TLBEAR
104 mfsr r1, SYSREG_PTBR 99 mfsr r1, SYSREG_PTBR
105 100
106 /* Is it the vmalloc space? */ 101 /*
107 bld r0, 31 102 * First level lookup: The PGD contains virtual pointers to
108 brcs handle_vmalloc_miss 103 * the second-level page tables, but they may be NULL if not
109 104 * present.
110 /* First level lookup */ 105 */
111pgtbl_lookup: 106pgtbl_lookup:
112 lsr r2, r0, PGDIR_SHIFT 107 lsr r2, r0, PGDIR_SHIFT
113 ld.w r3, r1[r2 << 2] 108 ld.w r3, r1[r2 << 2]
114 bfextu r1, r0, PAGE_SHIFT, PGDIR_SHIFT - PAGE_SHIFT 109 bfextu r1, r0, PAGE_SHIFT, PGDIR_SHIFT - PAGE_SHIFT
115 bld r3, _PAGE_BIT_PRESENT 110 cp.w r3, 0
116 brcc page_table_not_present 111 breq page_table_not_present
117
118 /* Translate to virtual address in P1. */
119 andl r3, 0xf000
120 sbr r3, 31
121 112
122 /* Second level lookup */ 113 /* Second level lookup */
123 ld.w r2, r3[r1 << 2] 114 ld.w r2, r3[r1 << 2]
@@ -148,16 +139,55 @@ pgtbl_lookup:
148 tlbmiss_restore 139 tlbmiss_restore
149 rete 140 rete
150 141
151handle_vmalloc_miss: 142 /* The slow path of the TLB miss handler */
152 /* Simply do the lookup in init's page table */ 143 .align 2
144page_table_not_present:
145 /* Do we need to synchronize with swapper_pg_dir? */
146 bld r0, 31
147 brcs sync_with_swapper_pg_dir
148
149page_not_present:
150 tlbmiss_restore
151 sub sp, 4
152 stmts --sp, r0-lr
153 rcall save_full_context_ex
154 mfsr r12, SYSREG_ECR
155 mov r11, sp
156 rcall do_page_fault
157 rjmp ret_from_exception
158
159 .align 2
160sync_with_swapper_pg_dir:
161 /*
162 * If swapper_pg_dir contains a non-NULL second-level page
163 * table pointer, copy it into the current PGD. If not, we
164 * must handle it as a full-blown page fault.
165 *
166 * Jumping back to pgtbl_lookup causes an unnecessary lookup,
167 * but it is guaranteed to be a cache hit, it won't happen
168 * very often, and we absolutely do not want to sacrifice any
169 * performance in the fast path in order to improve this.
170 */
153 mov r1, lo(swapper_pg_dir) 171 mov r1, lo(swapper_pg_dir)
154 orh r1, hi(swapper_pg_dir) 172 orh r1, hi(swapper_pg_dir)
173 ld.w r3, r1[r2 << 2]
174 cp.w r3, 0
175 breq page_not_present
176 mfsr r1, SYSREG_PTBR
177 st.w r1[r2 << 2], r3
155 rjmp pgtbl_lookup 178 rjmp pgtbl_lookup
156 179
180 /*
181 * We currently have two bytes left at this point until we
182 * crash into the system call handler...
183 *
184 * Don't worry, the assembler will let us know.
185 */
186
157 187
158 /* --- System Call --- */ 188 /* --- System Call --- */
159 189
160 .section .scall.text,"ax",@progbits 190 .org 0x100
161system_call: 191system_call:
162#ifdef CONFIG_PREEMPT 192#ifdef CONFIG_PREEMPT
163 mask_interrupts 193 mask_interrupts
@@ -266,18 +296,6 @@ syscall_exit_work:
266 brcc syscall_exit_cont 296 brcc syscall_exit_cont
267 rjmp enter_monitor_mode 297 rjmp enter_monitor_mode
268 298
269 /* The slow path of the TLB miss handler */
270page_table_not_present:
271page_not_present:
272 tlbmiss_restore
273 sub sp, 4
274 stmts --sp, r0-lr
275 rcall save_full_context_ex
276 mfsr r12, SYSREG_ECR
277 mov r11, sp
278 rcall do_page_fault
279 rjmp ret_from_exception
280
281 /* This function expects to find offending PC in SYSREG_RAR_EX */ 299 /* This function expects to find offending PC in SYSREG_RAR_EX */
282 .type save_full_context_ex, @function 300 .type save_full_context_ex, @function
283 .align 2 301 .align 2
diff --git a/arch/avr32/kernel/signal.c b/arch/avr32/kernel/signal.c
index 5616a00c10ba..c5b11f9067f1 100644
--- a/arch/avr32/kernel/signal.c
+++ b/arch/avr32/kernel/signal.c
@@ -93,6 +93,9 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
93 if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) 93 if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
94 goto badframe; 94 goto badframe;
95 95
96 if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT)
97 goto badframe;
98
96 pr_debug("Context restored: pc = %08lx, lr = %08lx, sp = %08lx\n", 99 pr_debug("Context restored: pc = %08lx, lr = %08lx, sp = %08lx\n",
97 regs->pc, regs->lr, regs->sp); 100 regs->pc, regs->lr, regs->sp);
98 101
diff --git a/arch/avr32/kernel/stacktrace.c b/arch/avr32/kernel/stacktrace.c
index 9a68190bbffd..f4bdb448049c 100644
--- a/arch/avr32/kernel/stacktrace.c
+++ b/arch/avr32/kernel/stacktrace.c
@@ -51,3 +51,4 @@ void save_stack_trace(struct stack_trace *trace)
51 fp = frame->fp; 51 fp = frame->fp;
52 } 52 }
53} 53}
54EXPORT_SYMBOL_GPL(save_stack_trace);
diff --git a/arch/avr32/kernel/time.c b/arch/avr32/kernel/time.c
index 00a9862380ff..abd954fb7ba0 100644
--- a/arch/avr32/kernel/time.c
+++ b/arch/avr32/kernel/time.c
@@ -7,21 +7,13 @@
7 */ 7 */
8#include <linux/clk.h> 8#include <linux/clk.h>
9#include <linux/clockchips.h> 9#include <linux/clockchips.h>
10#include <linux/time.h> 10#include <linux/init.h>
11#include <linux/module.h>
12#include <linux/interrupt.h> 11#include <linux/interrupt.h>
13#include <linux/irq.h> 12#include <linux/irq.h>
14#include <linux/kernel_stat.h> 13#include <linux/kernel.h>
15#include <linux/errno.h> 14#include <linux/time.h>
16#include <linux/init.h>
17#include <linux/profile.h>
18#include <linux/sysdev.h>
19#include <linux/err.h>
20 15
21#include <asm/div64.h>
22#include <asm/sysreg.h> 16#include <asm/sysreg.h>
23#include <asm/io.h>
24#include <asm/sections.h>
25 17
26#include <asm/arch/pm.h> 18#include <asm/arch/pm.h>
27 19
diff --git a/arch/avr32/kernel/vmlinux.lds.S b/arch/avr32/kernel/vmlinux.lds.S
index 481cfd40c053..7910d41eb886 100644
--- a/arch/avr32/kernel/vmlinux.lds.S
+++ b/arch/avr32/kernel/vmlinux.lds.S
@@ -68,14 +68,6 @@ SECTIONS
68 _evba = .; 68 _evba = .;
69 _text = .; 69 _text = .;
70 *(.ex.text) 70 *(.ex.text)
71 . = 0x50;
72 *(.tlbx.ex.text)
73 . = 0x60;
74 *(.tlbr.ex.text)
75 . = 0x70;
76 *(.tlbw.ex.text)
77 . = 0x100;
78 *(.scall.text)
79 *(.irq.text) 71 *(.irq.text)
80 KPROBES_TEXT 72 KPROBES_TEXT
81 TEXT_TEXT 73 TEXT_TEXT
@@ -93,8 +85,6 @@ SECTIONS
93 __stop___ex_table = .; 85 __stop___ex_table = .;
94 } 86 }
95 87
96 BUG_TABLE
97
98 RODATA 88 RODATA
99 89
100 . = ALIGN(THREAD_SIZE); 90 . = ALIGN(THREAD_SIZE);
@@ -107,6 +97,10 @@ SECTIONS
107 */ 97 */
108 *(.data.init_task) 98 *(.data.init_task)
109 99
100 /* Then, the page-aligned data */
101 . = ALIGN(PAGE_SIZE);
102 *(.data.page_aligned)
103
110 /* Then, the cacheline aligned data */ 104 /* Then, the cacheline aligned data */
111 . = ALIGN(L1_CACHE_BYTES); 105 . = ALIGN(L1_CACHE_BYTES);
112 *(.data.cacheline_aligned) 106 *(.data.cacheline_aligned)