aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/common/timer-sp.c3
-rw-r--r--arch/arm/mach-mvebu/armada-370-xp.c4
-rw-r--r--arch/mips/dec/ioasic-irq.c8
-rw-r--r--arch/mips/dec/time.c22
-rw-r--r--arch/mips/include/asm/dec/ioasic.h4
-rw-r--r--arch/mips/kernel/csrc-ioasic.c8
-rw-r--r--arch/mips/kernel/smp-cmp.c13
-rw-r--r--arch/mips/kernel/vpe.c2
-rw-r--r--arch/xtensa/Makefile4
-rw-r--r--arch/xtensa/boot/Makefile2
-rw-r--r--arch/xtensa/include/asm/regs.h1
-rw-r--r--arch/xtensa/include/asm/timex.h6
-rw-r--r--arch/xtensa/kernel/align.S5
-rw-r--r--arch/xtensa/kernel/coprocessor.S9
-rw-r--r--arch/xtensa/kernel/entry.S387
-rw-r--r--arch/xtensa/kernel/setup.c4
-rw-r--r--arch/xtensa/kernel/time.c8
-rw-r--r--arch/xtensa/kernel/vectors.S250
-rw-r--r--arch/xtensa/kernel/xtensa_ksyms.c1
19 files changed, 377 insertions, 364 deletions
diff --git a/arch/arm/common/timer-sp.c b/arch/arm/common/timer-sp.c
index 023ee63827a2..e901d0f3e0bb 100644
--- a/arch/arm/common/timer-sp.c
+++ b/arch/arm/common/timer-sp.c
@@ -166,7 +166,8 @@ static int sp804_set_next_event(unsigned long next,
166} 166}
167 167
168static struct clock_event_device sp804_clockevent = { 168static struct clock_event_device sp804_clockevent = {
169 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, 169 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT |
170 CLOCK_EVT_FEAT_DYNIRQ,
170 .set_mode = sp804_set_mode, 171 .set_mode = sp804_set_mode,
171 .set_next_event = sp804_set_next_event, 172 .set_next_event = sp804_set_next_event,
172 .rating = 300, 173 .rating = 300,
diff --git a/arch/arm/mach-mvebu/armada-370-xp.c b/arch/arm/mach-mvebu/armada-370-xp.c
index 829b57306328..e2acff98e750 100644
--- a/arch/arm/mach-mvebu/armada-370-xp.c
+++ b/arch/arm/mach-mvebu/armada-370-xp.c
@@ -18,7 +18,7 @@
18#include <linux/of_address.h> 18#include <linux/of_address.h>
19#include <linux/of_platform.h> 19#include <linux/of_platform.h>
20#include <linux/io.h> 20#include <linux/io.h>
21#include <linux/time-armada-370-xp.h> 21#include <linux/clocksource.h>
22#include <linux/dma-mapping.h> 22#include <linux/dma-mapping.h>
23#include <linux/mbus.h> 23#include <linux/mbus.h>
24#include <asm/hardware/cache-l2x0.h> 24#include <asm/hardware/cache-l2x0.h>
@@ -37,7 +37,7 @@ static void __init armada_370_xp_map_io(void)
37static void __init armada_370_xp_timer_and_clk_init(void) 37static void __init armada_370_xp_timer_and_clk_init(void)
38{ 38{
39 of_clk_init(NULL); 39 of_clk_init(NULL);
40 armada_370_xp_timer_init(); 40 clocksource_of_init();
41 coherency_init(); 41 coherency_init();
42 BUG_ON(mvebu_mbus_dt_init()); 42 BUG_ON(mvebu_mbus_dt_init());
43#ifdef CONFIG_CACHE_L2X0 43#ifdef CONFIG_CACHE_L2X0
diff --git a/arch/mips/dec/ioasic-irq.c b/arch/mips/dec/ioasic-irq.c
index 824e08c73798..4b3e3a4375a6 100644
--- a/arch/mips/dec/ioasic-irq.c
+++ b/arch/mips/dec/ioasic-irq.c
@@ -51,6 +51,14 @@ static struct irq_chip ioasic_irq_type = {
51 .irq_unmask = unmask_ioasic_irq, 51 .irq_unmask = unmask_ioasic_irq,
52}; 52};
53 53
54void clear_ioasic_dma_irq(unsigned int irq)
55{
56 u32 sir;
57
58 sir = ~(1 << (irq - ioasic_irq_base));
59 ioasic_write(IO_REG_SIR, sir);
60}
61
54static struct irq_chip ioasic_dma_irq_type = { 62static struct irq_chip ioasic_dma_irq_type = {
55 .name = "IO-ASIC-DMA", 63 .name = "IO-ASIC-DMA",
56 .irq_ack = ack_ioasic_irq, 64 .irq_ack = ack_ioasic_irq,
diff --git a/arch/mips/dec/time.c b/arch/mips/dec/time.c
index 56ebc7f2bede..1914e56f0d96 100644
--- a/arch/mips/dec/time.c
+++ b/arch/mips/dec/time.c
@@ -125,12 +125,16 @@ int rtc_mips_set_mmss(unsigned long nowtime)
125 125
126void __init plat_time_init(void) 126void __init plat_time_init(void)
127{ 127{
128 int ioasic_clock = 0;
128 u32 start, end; 129 u32 start, end;
129 int i = HZ / 8; 130 int i = HZ / 8;
130 131
131 /* Set up the rate of periodic DS1287 interrupts. */ 132 /* Set up the rate of periodic DS1287 interrupts. */
132 ds1287_set_base_clock(HZ); 133 ds1287_set_base_clock(HZ);
133 134
135 /* On some I/O ASIC systems we have the I/O ASIC's counter. */
136 if (IOASIC)
137 ioasic_clock = dec_ioasic_clocksource_init() == 0;
134 if (cpu_has_counter) { 138 if (cpu_has_counter) {
135 ds1287_timer_state(); 139 ds1287_timer_state();
136 while (!ds1287_timer_state()) 140 while (!ds1287_timer_state())
@@ -147,9 +151,21 @@ void __init plat_time_init(void)
147 mips_hpt_frequency = (end - start) * 8; 151 mips_hpt_frequency = (end - start) * 8;
148 printk(KERN_INFO "MIPS counter frequency %dHz\n", 152 printk(KERN_INFO "MIPS counter frequency %dHz\n",
149 mips_hpt_frequency); 153 mips_hpt_frequency);
150 } else if (IOASIC) 154
151 /* For pre-R4k systems we use the I/O ASIC's counter. */ 155 /*
152 dec_ioasic_clocksource_init(); 156 * All R4k DECstations suffer from the CP0 Count erratum,
157 * so we can't use the timer as a clock source, and a clock
158 * event both at a time. An accurate wall clock is more
159 * important than a high-precision interval timer so only
160 * use the timer as a clock source, and not a clock event
161 * if there's no I/O ASIC counter available to serve as a
162 * clock source.
163 */
164 if (!ioasic_clock) {
165 init_r4k_clocksource();
166 mips_hpt_frequency = 0;
167 }
168 }
153 169
154 ds1287_clockevent_init(dec_interrupt[DEC_IRQ_RTC]); 170 ds1287_clockevent_init(dec_interrupt[DEC_IRQ_RTC]);
155} 171}
diff --git a/arch/mips/include/asm/dec/ioasic.h b/arch/mips/include/asm/dec/ioasic.h
index 98badd6bf22d..a6e505a0e44b 100644
--- a/arch/mips/include/asm/dec/ioasic.h
+++ b/arch/mips/include/asm/dec/ioasic.h
@@ -31,8 +31,10 @@ static inline u32 ioasic_read(unsigned int reg)
31 return ioasic_base[reg / 4]; 31 return ioasic_base[reg / 4];
32} 32}
33 33
34extern void clear_ioasic_dma_irq(unsigned int irq);
35
34extern void init_ioasic_irqs(int base); 36extern void init_ioasic_irqs(int base);
35 37
36extern void dec_ioasic_clocksource_init(void); 38extern int dec_ioasic_clocksource_init(void);
37 39
38#endif /* __ASM_DEC_IOASIC_H */ 40#endif /* __ASM_DEC_IOASIC_H */
diff --git a/arch/mips/kernel/csrc-ioasic.c b/arch/mips/kernel/csrc-ioasic.c
index 87e88feb4a25..6cbbf6e106b9 100644
--- a/arch/mips/kernel/csrc-ioasic.c
+++ b/arch/mips/kernel/csrc-ioasic.c
@@ -37,7 +37,7 @@ static struct clocksource clocksource_dec = {
37 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 37 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
38}; 38};
39 39
40void __init dec_ioasic_clocksource_init(void) 40int __init dec_ioasic_clocksource_init(void)
41{ 41{
42 unsigned int freq; 42 unsigned int freq;
43 u32 start, end; 43 u32 start, end;
@@ -56,8 +56,14 @@ void __init dec_ioasic_clocksource_init(void)
56 end = dec_ioasic_hpt_read(&clocksource_dec); 56 end = dec_ioasic_hpt_read(&clocksource_dec);
57 57
58 freq = (end - start) * 8; 58 freq = (end - start) * 8;
59
60 /* An early revision of the I/O ASIC didn't have the counter. */
61 if (!freq)
62 return -ENXIO;
63
59 printk(KERN_INFO "I/O ASIC clock frequency %dHz\n", freq); 64 printk(KERN_INFO "I/O ASIC clock frequency %dHz\n", freq);
60 65
61 clocksource_dec.rating = 200 + freq / 10000000; 66 clocksource_dec.rating = 200 + freq / 10000000;
62 clocksource_register_hz(&clocksource_dec, freq); 67 clocksource_register_hz(&clocksource_dec, freq);
68 return 0;
63} 69}
diff --git a/arch/mips/kernel/smp-cmp.c b/arch/mips/kernel/smp-cmp.c
index c2e5d74739b4..5969f1e9b62a 100644
--- a/arch/mips/kernel/smp-cmp.c
+++ b/arch/mips/kernel/smp-cmp.c
@@ -99,7 +99,9 @@ static void cmp_init_secondary(void)
99 99
100 c->core = (read_c0_ebase() >> 1) & 0x1ff; 100 c->core = (read_c0_ebase() >> 1) & 0x1ff;
101#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC) 101#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC)
102 c->vpe_id = (read_c0_tcbind() >> TCBIND_CURVPE_SHIFT) & TCBIND_CURVPE; 102 if (cpu_has_mipsmt)
103 c->vpe_id = (read_c0_tcbind() >> TCBIND_CURVPE_SHIFT) &
104 TCBIND_CURVPE;
103#endif 105#endif
104#ifdef CONFIG_MIPS_MT_SMTC 106#ifdef CONFIG_MIPS_MT_SMTC
105 c->tc_id = (read_c0_tcbind() & TCBIND_CURTC) >> TCBIND_CURTC_SHIFT; 107 c->tc_id = (read_c0_tcbind() & TCBIND_CURTC) >> TCBIND_CURTC_SHIFT;
@@ -177,9 +179,16 @@ void __init cmp_smp_setup(void)
177 } 179 }
178 180
179 if (cpu_has_mipsmt) { 181 if (cpu_has_mipsmt) {
180 unsigned int nvpe, mvpconf0 = read_c0_mvpconf0(); 182 unsigned int nvpe = 1;
183#ifdef CONFIG_MIPS_MT_SMP
184 unsigned int mvpconf0 = read_c0_mvpconf0();
185
186 nvpe = ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1;
187#elif defined(CONFIG_MIPS_MT_SMTC)
188 unsigned int mvpconf0 = read_c0_mvpconf0();
181 189
182 nvpe = ((mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1; 190 nvpe = ((mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1;
191#endif
183 smp_num_siblings = nvpe; 192 smp_num_siblings = nvpe;
184 } 193 }
185 pr_info("Detected %i available secondary CPU(s)\n", ncpu); 194 pr_info("Detected %i available secondary CPU(s)\n", ncpu);
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index faf84c5f2629..59b2b3cd7885 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -1368,7 +1368,7 @@ out_einval:
1368} 1368}
1369static DEVICE_ATTR_RW(ntcs); 1369static DEVICE_ATTR_RW(ntcs);
1370 1370
1371static struct attribute vpe_attrs[] = { 1371static struct attribute *vpe_attrs[] = {
1372 &dev_attr_kill.attr, 1372 &dev_attr_kill.attr,
1373 &dev_attr_ntcs.attr, 1373 &dev_attr_ntcs.attr,
1374 NULL, 1374 NULL,
diff --git a/arch/xtensa/Makefile b/arch/xtensa/Makefile
index 136224b74d4f..81250ece3062 100644
--- a/arch/xtensa/Makefile
+++ b/arch/xtensa/Makefile
@@ -55,10 +55,10 @@ ifneq ($(CONFIG_LD_NO_RELAX),)
55LDFLAGS := --no-relax 55LDFLAGS := --no-relax
56endif 56endif
57 57
58ifeq ($(shell echo -e __XTENSA_EB__ | $(CC) -E - | grep -v "\#"),1) 58ifeq ($(shell echo __XTENSA_EB__ | $(CC) -E - | grep -v "\#"),1)
59CHECKFLAGS += -D__XTENSA_EB__ 59CHECKFLAGS += -D__XTENSA_EB__
60endif 60endif
61ifeq ($(shell echo -e __XTENSA_EL__ | $(CC) -E - | grep -v "\#"),1) 61ifeq ($(shell echo __XTENSA_EL__ | $(CC) -E - | grep -v "\#"),1)
62CHECKFLAGS += -D__XTENSA_EL__ 62CHECKFLAGS += -D__XTENSA_EL__
63endif 63endif
64 64
diff --git a/arch/xtensa/boot/Makefile b/arch/xtensa/boot/Makefile
index 64ffc4b53df6..ca20a892021b 100644
--- a/arch/xtensa/boot/Makefile
+++ b/arch/xtensa/boot/Makefile
@@ -12,7 +12,7 @@
12KBUILD_CFLAGS += -fno-builtin -Iarch/$(ARCH)/boot/include 12KBUILD_CFLAGS += -fno-builtin -Iarch/$(ARCH)/boot/include
13HOSTFLAGS += -Iarch/$(ARCH)/boot/include 13HOSTFLAGS += -Iarch/$(ARCH)/boot/include
14 14
15BIG_ENDIAN := $(shell echo -e __XTENSA_EB__ | $(CC) -E - | grep -v "\#") 15BIG_ENDIAN := $(shell echo __XTENSA_EB__ | $(CC) -E - | grep -v "\#")
16 16
17export ccflags-y 17export ccflags-y
18export BIG_ENDIAN 18export BIG_ENDIAN
diff --git a/arch/xtensa/include/asm/regs.h b/arch/xtensa/include/asm/regs.h
index b24de6717020..4ba9f516b0e2 100644
--- a/arch/xtensa/include/asm/regs.h
+++ b/arch/xtensa/include/asm/regs.h
@@ -82,6 +82,7 @@
82#define PS_CALLINC_SHIFT 16 82#define PS_CALLINC_SHIFT 16
83#define PS_CALLINC_MASK 0x00030000 83#define PS_CALLINC_MASK 0x00030000
84#define PS_OWB_SHIFT 8 84#define PS_OWB_SHIFT 8
85#define PS_OWB_WIDTH 4
85#define PS_OWB_MASK 0x00000F00 86#define PS_OWB_MASK 0x00000F00
86#define PS_RING_SHIFT 6 87#define PS_RING_SHIFT 6
87#define PS_RING_MASK 0x000000C0 88#define PS_RING_MASK 0x000000C0
diff --git a/arch/xtensa/include/asm/timex.h b/arch/xtensa/include/asm/timex.h
index 69f901713fb6..27fa3c170662 100644
--- a/arch/xtensa/include/asm/timex.h
+++ b/arch/xtensa/include/asm/timex.h
@@ -35,13 +35,7 @@
35# error "Bad timer number for Linux configurations!" 35# error "Bad timer number for Linux configurations!"
36#endif 36#endif
37 37
38#ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT
39extern unsigned long ccount_freq; 38extern unsigned long ccount_freq;
40#define CCOUNT_PER_JIFFY (ccount_freq / HZ)
41#else
42#define CCOUNT_PER_JIFFY (CONFIG_XTENSA_CPU_CLOCK*(1000000UL/HZ))
43#endif
44
45 39
46typedef unsigned long long cycles_t; 40typedef unsigned long long cycles_t;
47 41
diff --git a/arch/xtensa/kernel/align.S b/arch/xtensa/kernel/align.S
index aa2e87b8566a..d4cef6039a5c 100644
--- a/arch/xtensa/kernel/align.S
+++ b/arch/xtensa/kernel/align.S
@@ -146,9 +146,9 @@
146 * a0: trashed, original value saved on stack (PT_AREG0) 146 * a0: trashed, original value saved on stack (PT_AREG0)
147 * a1: a1 147 * a1: a1
148 * a2: new stack pointer, original in DEPC 148 * a2: new stack pointer, original in DEPC
149 * a3: dispatch table 149 * a3: a3
150 * depc: a2, original value saved on stack (PT_DEPC) 150 * depc: a2, original value saved on stack (PT_DEPC)
151 * excsave_1: a3 151 * excsave_1: dispatch table
152 * 152 *
153 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC 153 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
154 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception 154 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
@@ -171,7 +171,6 @@ ENTRY(fast_unaligned)
171 s32i a8, a2, PT_AREG8 171 s32i a8, a2, PT_AREG8
172 172
173 rsr a0, depc 173 rsr a0, depc
174 xsr a3, excsave1
175 s32i a0, a2, PT_AREG2 174 s32i a0, a2, PT_AREG2
176 s32i a3, a2, PT_AREG3 175 s32i a3, a2, PT_AREG3
177 176
diff --git a/arch/xtensa/kernel/coprocessor.S b/arch/xtensa/kernel/coprocessor.S
index 647657484866..a482df5df2b2 100644
--- a/arch/xtensa/kernel/coprocessor.S
+++ b/arch/xtensa/kernel/coprocessor.S
@@ -32,9 +32,9 @@
32 * a0: trashed, original value saved on stack (PT_AREG0) 32 * a0: trashed, original value saved on stack (PT_AREG0)
33 * a1: a1 33 * a1: a1
34 * a2: new stack pointer, original in DEPC 34 * a2: new stack pointer, original in DEPC
35 * a3: dispatch table 35 * a3: a3
36 * depc: a2, original value saved on stack (PT_DEPC) 36 * depc: a2, original value saved on stack (PT_DEPC)
37 * excsave_1: a3 37 * excsave_1: dispatch table
38 * 38 *
39 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC 39 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
40 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception 40 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
@@ -225,9 +225,9 @@ ENDPROC(coprocessor_restore)
225 * a0: trashed, original value saved on stack (PT_AREG0) 225 * a0: trashed, original value saved on stack (PT_AREG0)
226 * a1: a1 226 * a1: a1
227 * a2: new stack pointer, original in DEPC 227 * a2: new stack pointer, original in DEPC
228 * a3: dispatch table 228 * a3: a3
229 * depc: a2, original value saved on stack (PT_DEPC) 229 * depc: a2, original value saved on stack (PT_DEPC)
230 * excsave_1: a3 230 * excsave_1: dispatch table
231 * 231 *
232 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC 232 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
233 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception 233 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
@@ -245,7 +245,6 @@ ENTRY(fast_coprocessor)
245 245
246 /* Save remaining registers a1-a3 and SAR */ 246 /* Save remaining registers a1-a3 and SAR */
247 247
248 xsr a3, excsave1
249 s32i a3, a2, PT_AREG3 248 s32i a3, a2, PT_AREG3
250 rsr a3, sar 249 rsr a3, sar
251 s32i a1, a2, PT_AREG1 250 s32i a1, a2, PT_AREG1
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index 9298742f0fd0..de1dfa18d0a1 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -31,8 +31,6 @@
31/* Unimplemented features. */ 31/* Unimplemented features. */
32 32
33#undef KERNEL_STACK_OVERFLOW_CHECK 33#undef KERNEL_STACK_OVERFLOW_CHECK
34#undef PREEMPTIBLE_KERNEL
35#undef ALLOCA_EXCEPTION_IN_IRAM
36 34
37/* Not well tested. 35/* Not well tested.
38 * 36 *
@@ -92,9 +90,9 @@
92 * a0: trashed, original value saved on stack (PT_AREG0) 90 * a0: trashed, original value saved on stack (PT_AREG0)
93 * a1: a1 91 * a1: a1
94 * a2: new stack pointer, original value in depc 92 * a2: new stack pointer, original value in depc
95 * a3: dispatch table 93 * a3: a3
96 * depc: a2, original value saved on stack (PT_DEPC) 94 * depc: a2, original value saved on stack (PT_DEPC)
97 * excsave1: a3 95 * excsave1: dispatch table
98 * 96 *
99 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC 97 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
100 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception 98 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
@@ -110,9 +108,8 @@
110 108
111ENTRY(user_exception) 109ENTRY(user_exception)
112 110
113 /* Save a2, a3, and depc, restore excsave_1 and set SP. */ 111 /* Save a1, a2, a3, and set SP. */
114 112
115 xsr a3, excsave1
116 rsr a0, depc 113 rsr a0, depc
117 s32i a1, a2, PT_AREG1 114 s32i a1, a2, PT_AREG1
118 s32i a0, a2, PT_AREG2 115 s32i a0, a2, PT_AREG2
@@ -238,9 +235,9 @@ ENDPROC(user_exception)
238 * a0: trashed, original value saved on stack (PT_AREG0) 235 * a0: trashed, original value saved on stack (PT_AREG0)
239 * a1: a1 236 * a1: a1
240 * a2: new stack pointer, original in DEPC 237 * a2: new stack pointer, original in DEPC
241 * a3: dispatch table 238 * a3: a3
242 * depc: a2, original value saved on stack (PT_DEPC) 239 * depc: a2, original value saved on stack (PT_DEPC)
243 * excsave_1: a3 240 * excsave_1: dispatch table
244 * 241 *
245 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC 242 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
246 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception 243 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
@@ -256,9 +253,8 @@ ENDPROC(user_exception)
256 253
257ENTRY(kernel_exception) 254ENTRY(kernel_exception)
258 255
259 /* Save a0, a2, a3, DEPC and set SP. */ 256 /* Save a1, a2, a3, and set SP. */
260 257
261 xsr a3, excsave1 # restore a3, excsave_1
262 rsr a0, depc # get a2 258 rsr a0, depc # get a2
263 s32i a1, a2, PT_AREG1 259 s32i a1, a2, PT_AREG1
264 s32i a0, a2, PT_AREG2 260 s32i a0, a2, PT_AREG2
@@ -409,7 +405,7 @@ common_exception:
409 * exception handler and call the exception handler. 405 * exception handler and call the exception handler.
410 */ 406 */
411 407
412 movi a4, exc_table 408 rsr a4, excsave1
413 mov a6, a1 # pass stack frame 409 mov a6, a1 # pass stack frame
414 mov a7, a0 # pass EXCCAUSE 410 mov a7, a0 # pass EXCCAUSE
415 addx4 a4, a0, a4 411 addx4 a4, a0, a4
@@ -423,28 +419,15 @@ common_exception:
423 .global common_exception_return 419 .global common_exception_return
424common_exception_return: 420common_exception_return:
425 421
426#ifdef CONFIG_TRACE_IRQFLAGS
427 l32i a4, a1, PT_DEPC
428 /* Double exception means we came here with an exception
429 * while PS.EXCM was set, i.e. interrupts disabled.
430 */
431 bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
432 l32i a4, a1, PT_EXCCAUSE
433 bnei a4, EXCCAUSE_LEVEL1_INTERRUPT, 1f
434 /* We came here with an interrupt means interrupts were enabled
435 * and we'll reenable them on return.
436 */
437 movi a4, trace_hardirqs_on
438 callx4 a4
4391: 4221:
440#endif 423 rsil a2, LOCKLEVEL
441 424
442 /* Jump if we are returning from kernel exceptions. */ 425 /* Jump if we are returning from kernel exceptions. */
443 426
4441: l32i a3, a1, PT_PS 427 l32i a3, a1, PT_PS
445 _bbci.l a3, PS_UM_BIT, 4f 428 GET_THREAD_INFO(a2, a1)
446 429 l32i a4, a2, TI_FLAGS
447 rsil a2, 0 430 _bbci.l a3, PS_UM_BIT, 6f
448 431
449 /* Specific to a user exception exit: 432 /* Specific to a user exception exit:
450 * We need to check some flags for signal handling and rescheduling, 433 * We need to check some flags for signal handling and rescheduling,
@@ -453,9 +436,6 @@ common_exception_return:
453 * Note that we don't disable interrupts here. 436 * Note that we don't disable interrupts here.
454 */ 437 */
455 438
456 GET_THREAD_INFO(a2,a1)
457 l32i a4, a2, TI_FLAGS
458
459 _bbsi.l a4, TIF_NEED_RESCHED, 3f 439 _bbsi.l a4, TIF_NEED_RESCHED, 3f
460 _bbsi.l a4, TIF_NOTIFY_RESUME, 2f 440 _bbsi.l a4, TIF_NOTIFY_RESUME, 2f
461 _bbci.l a4, TIF_SIGPENDING, 5f 441 _bbci.l a4, TIF_SIGPENDING, 5f
@@ -465,6 +445,7 @@ common_exception_return:
465 445
466 /* Call do_signal() */ 446 /* Call do_signal() */
467 447
448 rsil a2, 0
468 movi a4, do_notify_resume # int do_notify_resume(struct pt_regs*) 449 movi a4, do_notify_resume # int do_notify_resume(struct pt_regs*)
469 mov a6, a1 450 mov a6, a1
470 callx4 a4 451 callx4 a4
@@ -472,10 +453,24 @@ common_exception_return:
472 453
4733: /* Reschedule */ 4543: /* Reschedule */
474 455
456 rsil a2, 0
475 movi a4, schedule # void schedule (void) 457 movi a4, schedule # void schedule (void)
476 callx4 a4 458 callx4 a4
477 j 1b 459 j 1b
478 460
461#ifdef CONFIG_PREEMPT
4626:
463 _bbci.l a4, TIF_NEED_RESCHED, 4f
464
465 /* Check current_thread_info->preempt_count */
466
467 l32i a4, a2, TI_PRE_COUNT
468 bnez a4, 4f
469 movi a4, preempt_schedule_irq
470 callx4 a4
471 j 1b
472#endif
473
4795: 4745:
480#ifdef CONFIG_DEBUG_TLB_SANITY 475#ifdef CONFIG_DEBUG_TLB_SANITY
481 l32i a4, a1, PT_DEPC 476 l32i a4, a1, PT_DEPC
@@ -483,7 +478,24 @@ common_exception_return:
483 movi a4, check_tlb_sanity 478 movi a4, check_tlb_sanity
484 callx4 a4 479 callx4 a4
485#endif 480#endif
4864: /* Restore optional registers. */ 4816:
4824:
483#ifdef CONFIG_TRACE_IRQFLAGS
484 l32i a4, a1, PT_DEPC
485 /* Double exception means we came here with an exception
486 * while PS.EXCM was set, i.e. interrupts disabled.
487 */
488 bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
489 l32i a4, a1, PT_EXCCAUSE
490 bnei a4, EXCCAUSE_LEVEL1_INTERRUPT, 1f
491 /* We came here with an interrupt means interrupts were enabled
492 * and we'll reenable them on return.
493 */
494 movi a4, trace_hardirqs_on
495 callx4 a4
4961:
497#endif
498 /* Restore optional registers. */
487 499
488 load_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT 500 load_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT
489 501
@@ -570,29 +582,6 @@ user_exception_exit:
570 582
571kernel_exception_exit: 583kernel_exception_exit:
572 584
573#ifdef PREEMPTIBLE_KERNEL
574
575#ifdef CONFIG_PREEMPT
576
577 /*
578 * Note: We've just returned from a call4, so we have
579 * at least 4 addt'l regs.
580 */
581
582 /* Check current_thread_info->preempt_count */
583
584 GET_THREAD_INFO(a2)
585 l32i a3, a2, TI_PREEMPT
586 bnez a3, 1f
587
588 l32i a2, a2, TI_FLAGS
589
5901:
591
592#endif
593
594#endif
595
596 /* Check if we have to do a movsp. 585 /* Check if we have to do a movsp.
597 * 586 *
598 * We only have to do a movsp if the previous window-frame has 587 * We only have to do a movsp if the previous window-frame has
@@ -829,176 +818,63 @@ ENDPROC(unrecoverable_exception)
829 * 818 *
830 * The ALLOCA handler is entered when user code executes the MOVSP 819 * The ALLOCA handler is entered when user code executes the MOVSP
831 * instruction and the caller's frame is not in the register file. 820 * instruction and the caller's frame is not in the register file.
832 * In this case, the caller frame's a0..a3 are on the stack just
833 * below sp (a1), and this handler moves them.
834 * 821 *
835 * For "MOVSP <ar>,<as>" without destination register a1, this routine 822 * This algorithm was taken from the Ross Morley's RTOS Porting Layer:
836 * simply moves the value from <as> to <ar> without moving the save area. 823 *
824 * /home/ross/rtos/porting/XtensaRTOS-PortingLayer-20090507/xtensa_vectors.S
825 *
826 * It leverages the existing window spill/fill routines and their support for
827 * double exceptions. The 'movsp' instruction will only cause an exception if
828 * the next window needs to be loaded. In fact this ALLOCA exception may be
829 * replaced at some point by changing the hardware to do a underflow exception
830 * of the proper size instead.
831 *
832 * This algorithm simply backs out the register changes started by the user
833 * excpetion handler, makes it appear that we have started a window underflow
834 * by rotating the window back and then setting the old window base (OWB) in
835 * the 'ps' register with the rolled back window base. The 'movsp' instruction
836 * will be re-executed and this time since the next window frames is in the
837 * active AR registers it won't cause an exception.
838 *
839 * If the WindowUnderflow code gets a TLB miss the page will get mapped
840 * the the partial windeowUnderflow will be handeled in the double exception
841 * handler.
837 * 842 *
838 * Entry condition: 843 * Entry condition:
839 * 844 *
840 * a0: trashed, original value saved on stack (PT_AREG0) 845 * a0: trashed, original value saved on stack (PT_AREG0)
841 * a1: a1 846 * a1: a1
842 * a2: new stack pointer, original in DEPC 847 * a2: new stack pointer, original in DEPC
843 * a3: dispatch table 848 * a3: a3
844 * depc: a2, original value saved on stack (PT_DEPC) 849 * depc: a2, original value saved on stack (PT_DEPC)
845 * excsave_1: a3 850 * excsave_1: dispatch table
846 * 851 *
847 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC 852 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
848 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception 853 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
849 */ 854 */
850 855
851#if XCHAL_HAVE_BE
852#define _EXTUI_MOVSP_SRC(ar) extui ar, ar, 4, 4
853#define _EXTUI_MOVSP_DST(ar) extui ar, ar, 0, 4
854#else
855#define _EXTUI_MOVSP_SRC(ar) extui ar, ar, 0, 4
856#define _EXTUI_MOVSP_DST(ar) extui ar, ar, 4, 4
857#endif
858
859ENTRY(fast_alloca) 856ENTRY(fast_alloca)
857 rsr a0, windowbase
858 rotw -1
859 rsr a2, ps
860 extui a3, a2, PS_OWB_SHIFT, PS_OWB_WIDTH
861 xor a3, a3, a4
862 l32i a4, a6, PT_AREG0
863 l32i a1, a6, PT_DEPC
864 rsr a6, depc
865 wsr a1, depc
866 slli a3, a3, PS_OWB_SHIFT
867 xor a2, a2, a3
868 wsr a2, ps
869 rsync
860 870
861 /* We shouldn't be in a double exception. */ 871 _bbci.l a4, 31, 4f
862 872 rotw -1
863 l32i a0, a2, PT_DEPC 873 _bbci.l a8, 30, 8f
864 _bgeui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, .Lunhandled_double 874 rotw -1
865 875 j _WindowUnderflow12
866 rsr a0, depc # get a2 8768: j _WindowUnderflow8
867 s32i a4, a2, PT_AREG4 # save a4 and 8774: j _WindowUnderflow4
868 s32i a0, a2, PT_AREG2 # a2 to stack
869
870 /* Exit critical section. */
871
872 movi a0, 0
873 s32i a0, a3, EXC_TABLE_FIXUP
874
875 /* Restore a3, excsave_1 */
876
877 xsr a3, excsave1 # make sure excsave_1 is valid for dbl.
878 rsr a4, epc1 # get exception address
879 s32i a3, a2, PT_AREG3 # save a3 to stack
880
881#ifdef ALLOCA_EXCEPTION_IN_IRAM
882#error iram not supported
883#else
884 /* Note: l8ui not allowed in IRAM/IROM!! */
885 l8ui a0, a4, 1 # read as(src) from MOVSP instruction
886#endif
887 movi a3, .Lmovsp_src
888 _EXTUI_MOVSP_SRC(a0) # extract source register number
889 addx8 a3, a0, a3
890 jx a3
891
892.Lunhandled_double:
893 wsr a0, excsave1
894 movi a0, unrecoverable_exception
895 callx0 a0
896
897 .align 8
898.Lmovsp_src:
899 l32i a3, a2, PT_AREG0; _j 1f; .align 8
900 mov a3, a1; _j 1f; .align 8
901 l32i a3, a2, PT_AREG2; _j 1f; .align 8
902 l32i a3, a2, PT_AREG3; _j 1f; .align 8
903 l32i a3, a2, PT_AREG4; _j 1f; .align 8
904 mov a3, a5; _j 1f; .align 8
905 mov a3, a6; _j 1f; .align 8
906 mov a3, a7; _j 1f; .align 8
907 mov a3, a8; _j 1f; .align 8
908 mov a3, a9; _j 1f; .align 8
909 mov a3, a10; _j 1f; .align 8
910 mov a3, a11; _j 1f; .align 8
911 mov a3, a12; _j 1f; .align 8
912 mov a3, a13; _j 1f; .align 8
913 mov a3, a14; _j 1f; .align 8
914 mov a3, a15; _j 1f; .align 8
915
9161:
917
918#ifdef ALLOCA_EXCEPTION_IN_IRAM
919#error iram not supported
920#else
921 l8ui a0, a4, 0 # read ar(dst) from MOVSP instruction
922#endif
923 addi a4, a4, 3 # step over movsp
924 _EXTUI_MOVSP_DST(a0) # extract destination register
925 wsr a4, epc1 # save new epc_1
926
927 _bnei a0, 1, 1f # no 'movsp a1, ax': jump
928
929 /* Move the save area. This implies the use of the L32E
930 * and S32E instructions, because this move must be done with
931 * the user's PS.RING privilege levels, not with ring 0
932 * (kernel's) privileges currently active with PS.EXCM
933 * set. Note that we have stil registered a fixup routine with the
934 * double exception vector in case a double exception occurs.
935 */
936
937 /* a0,a4:avail a1:old user stack a2:exc. stack a3:new user stack. */
938
939 l32e a0, a1, -16
940 l32e a4, a1, -12
941 s32e a0, a3, -16
942 s32e a4, a3, -12
943 l32e a0, a1, -8
944 l32e a4, a1, -4
945 s32e a0, a3, -8
946 s32e a4, a3, -4
947
948 /* Restore stack-pointer and all the other saved registers. */
949
950 mov a1, a3
951
952 l32i a4, a2, PT_AREG4
953 l32i a3, a2, PT_AREG3
954 l32i a0, a2, PT_AREG0
955 l32i a2, a2, PT_AREG2
956 rfe
957
958 /* MOVSP <at>,<as> was invoked with <at> != a1.
959 * Because the stack pointer is not being modified,
960 * we should be able to just modify the pointer
961 * without moving any save area.
962 * The processor only traps these occurrences if the
963 * caller window isn't live, so unfortunately we can't
964 * use this as an alternate trap mechanism.
965 * So we just do the move. This requires that we
966 * resolve the destination register, not just the source,
967 * so there's some extra work.
968 * (PERHAPS NOT REALLY NEEDED, BUT CLEANER...)
969 */
970
971 /* a0 dst-reg, a1 user-stack, a2 stack, a3 value of src reg. */
972
9731: movi a4, .Lmovsp_dst
974 addx8 a4, a0, a4
975 jx a4
976
977 .align 8
978.Lmovsp_dst:
979 s32i a3, a2, PT_AREG0; _j 1f; .align 8
980 mov a1, a3; _j 1f; .align 8
981 s32i a3, a2, PT_AREG2; _j 1f; .align 8
982 s32i a3, a2, PT_AREG3; _j 1f; .align 8
983 s32i a3, a2, PT_AREG4; _j 1f; .align 8
984 mov a5, a3; _j 1f; .align 8
985 mov a6, a3; _j 1f; .align 8
986 mov a7, a3; _j 1f; .align 8
987 mov a8, a3; _j 1f; .align 8
988 mov a9, a3; _j 1f; .align 8
989 mov a10, a3; _j 1f; .align 8
990 mov a11, a3; _j 1f; .align 8
991 mov a12, a3; _j 1f; .align 8
992 mov a13, a3; _j 1f; .align 8
993 mov a14, a3; _j 1f; .align 8
994 mov a15, a3; _j 1f; .align 8
995
9961: l32i a4, a2, PT_AREG4
997 l32i a3, a2, PT_AREG3
998 l32i a0, a2, PT_AREG0
999 l32i a2, a2, PT_AREG2
1000 rfe
1001
1002ENDPROC(fast_alloca) 878ENDPROC(fast_alloca)
1003 879
1004/* 880/*
@@ -1015,9 +891,9 @@ ENDPROC(fast_alloca)
1015 * a0: trashed, original value saved on stack (PT_AREG0) 891 * a0: trashed, original value saved on stack (PT_AREG0)
1016 * a1: a1 892 * a1: a1
1017 * a2: new stack pointer, original in DEPC 893 * a2: new stack pointer, original in DEPC
1018 * a3: dispatch table 894 * a3: a3
1019 * depc: a2, original value saved on stack (PT_DEPC) 895 * depc: a2, original value saved on stack (PT_DEPC)
1020 * excsave_1: a3 896 * excsave_1: dispatch table
1021 */ 897 */
1022 898
1023ENTRY(fast_syscall_kernel) 899ENTRY(fast_syscall_kernel)
@@ -1064,7 +940,6 @@ ENTRY(fast_syscall_unrecoverable)
1064 940
1065 l32i a0, a2, PT_AREG0 # restore a0 941 l32i a0, a2, PT_AREG0 # restore a0
1066 xsr a2, depc # restore a2, depc 942 xsr a2, depc # restore a2, depc
1067 rsr a3, excsave1
1068 943
1069 wsr a0, excsave1 944 wsr a0, excsave1
1070 movi a0, unrecoverable_exception 945 movi a0, unrecoverable_exception
@@ -1086,10 +961,10 @@ ENDPROC(fast_syscall_unrecoverable)
1086 * a0: a2 (syscall-nr), original value saved on stack (PT_AREG0) 961 * a0: a2 (syscall-nr), original value saved on stack (PT_AREG0)
1087 * a1: a1 962 * a1: a1
1088 * a2: new stack pointer, original in a0 and DEPC 963 * a2: new stack pointer, original in a0 and DEPC
1089 * a3: dispatch table, original in excsave_1 964 * a3: a3
1090 * a4..a15: unchanged 965 * a4..a15: unchanged
1091 * depc: a2, original value saved on stack (PT_DEPC) 966 * depc: a2, original value saved on stack (PT_DEPC)
1092 * excsave_1: a3 967 * excsave_1: dispatch table
1093 * 968 *
1094 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC 969 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
1095 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception 970 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
@@ -1122,8 +997,6 @@ ENDPROC(fast_syscall_unrecoverable)
1122 997
1123ENTRY(fast_syscall_xtensa) 998ENTRY(fast_syscall_xtensa)
1124 999
1125 xsr a3, excsave1 # restore a3, excsave1
1126
1127 s32i a7, a2, PT_AREG7 # we need an additional register 1000 s32i a7, a2, PT_AREG7 # we need an additional register
1128 movi a7, 4 # sizeof(unsigned int) 1001 movi a7, 4 # sizeof(unsigned int)
1129 access_ok a3, a7, a0, a2, .Leac # a0: scratch reg, a2: sp 1002 access_ok a3, a7, a0, a2, .Leac # a0: scratch reg, a2: sp
@@ -1186,9 +1059,9 @@ ENDPROC(fast_syscall_xtensa)
1186 * a0: trashed, original value saved on stack (PT_AREG0) 1059 * a0: trashed, original value saved on stack (PT_AREG0)
1187 * a1: a1 1060 * a1: a1
1188 * a2: new stack pointer, original in DEPC 1061 * a2: new stack pointer, original in DEPC
1189 * a3: dispatch table 1062 * a3: a3
1190 * depc: a2, original value saved on stack (PT_DEPC) 1063 * depc: a2, original value saved on stack (PT_DEPC)
1191 * excsave_1: a3 1064 * excsave_1: dispatch table
1192 * 1065 *
1193 * Note: We assume the stack pointer is EXC_TABLE_KSTK in the fixup handler. 1066 * Note: We assume the stack pointer is EXC_TABLE_KSTK in the fixup handler.
1194 */ 1067 */
@@ -1197,15 +1070,16 @@ ENTRY(fast_syscall_spill_registers)
1197 1070
1198 /* Register a FIXUP handler (pass current wb as a parameter) */ 1071 /* Register a FIXUP handler (pass current wb as a parameter) */
1199 1072
1073 xsr a3, excsave1
1200 movi a0, fast_syscall_spill_registers_fixup 1074 movi a0, fast_syscall_spill_registers_fixup
1201 s32i a0, a3, EXC_TABLE_FIXUP 1075 s32i a0, a3, EXC_TABLE_FIXUP
1202 rsr a0, windowbase 1076 rsr a0, windowbase
1203 s32i a0, a3, EXC_TABLE_PARAM 1077 s32i a0, a3, EXC_TABLE_PARAM
1078 xsr a3, excsave1 # restore a3 and excsave_1
1204 1079
1205 /* Save a3 and SAR on stack. */ 1080 /* Save a3, a4 and SAR on stack. */
1206 1081
1207 rsr a0, sar 1082 rsr a0, sar
1208 xsr a3, excsave1 # restore a3 and excsave_1
1209 s32i a3, a2, PT_AREG3 1083 s32i a3, a2, PT_AREG3
1210 s32i a4, a2, PT_AREG4 1084 s32i a4, a2, PT_AREG4
1211 s32i a0, a2, PT_AREG5 # store SAR to PT_AREG5 1085 s32i a0, a2, PT_AREG5 # store SAR to PT_AREG5
@@ -1259,14 +1133,14 @@ fast_syscall_spill_registers_fixup:
1259 * in WS, so that the exception handlers save them to the task stack. 1133 * in WS, so that the exception handlers save them to the task stack.
1260 */ 1134 */
1261 1135
1262 rsr a3, excsave1 # get spill-mask 1136 xsr a3, excsave1 # get spill-mask
1263 slli a2, a3, 1 # shift left by one 1137 slli a2, a3, 1 # shift left by one
1264 1138
1265 slli a3, a2, 32-WSBITS 1139 slli a3, a2, 32-WSBITS
1266 src a2, a2, a3 # a1 = xxwww1yyxxxwww1yy...... 1140 src a2, a2, a3 # a1 = xxwww1yyxxxwww1yy......
1267 wsr a2, windowstart # set corrected windowstart 1141 wsr a2, windowstart # set corrected windowstart
1268 1142
1269 movi a3, exc_table 1143 rsr a3, excsave1
1270 l32i a2, a3, EXC_TABLE_DOUBLE_SAVE # restore a2 1144 l32i a2, a3, EXC_TABLE_DOUBLE_SAVE # restore a2
1271 l32i a3, a3, EXC_TABLE_PARAM # original WB (in user task) 1145 l32i a3, a3, EXC_TABLE_PARAM # original WB (in user task)
1272 1146
@@ -1303,7 +1177,7 @@ fast_syscall_spill_registers_fixup:
1303 1177
1304 /* Jump to the exception handler. */ 1178 /* Jump to the exception handler. */
1305 1179
1306 movi a3, exc_table 1180 rsr a3, excsave1
1307 rsr a0, exccause 1181 rsr a0, exccause
1308 addx4 a0, a0, a3 # find entry in table 1182 addx4 a0, a0, a3 # find entry in table
1309 l32i a0, a0, EXC_TABLE_FAST_USER # load handler 1183 l32i a0, a0, EXC_TABLE_FAST_USER # load handler
@@ -1320,6 +1194,7 @@ fast_syscall_spill_registers_fixup_return:
1320 xsr a3, excsave1 1194 xsr a3, excsave1
1321 movi a2, fast_syscall_spill_registers_fixup 1195 movi a2, fast_syscall_spill_registers_fixup
1322 s32i a2, a3, EXC_TABLE_FIXUP 1196 s32i a2, a3, EXC_TABLE_FIXUP
1197 s32i a0, a3, EXC_TABLE_DOUBLE_SAVE
1323 rsr a2, windowbase 1198 rsr a2, windowbase
1324 s32i a2, a3, EXC_TABLE_PARAM 1199 s32i a2, a3, EXC_TABLE_PARAM
1325 l32i a2, a3, EXC_TABLE_KSTK 1200 l32i a2, a3, EXC_TABLE_KSTK
@@ -1331,11 +1206,6 @@ fast_syscall_spill_registers_fixup_return:
1331 wsr a3, windowbase 1206 wsr a3, windowbase
1332 rsync 1207 rsync
1333 1208
1334 /* Restore a3 and return. */
1335
1336 movi a3, exc_table
1337 xsr a3, excsave1
1338
1339 rfde 1209 rfde
1340 1210
1341 1211
@@ -1522,9 +1392,8 @@ ENTRY(_spill_registers)
1522 1392
1523 movi a0, 0 1393 movi a0, 0
1524 1394
1525 movi a3, exc_table 1395 rsr a3, excsave1
1526 l32i a1, a3, EXC_TABLE_KSTK 1396 l32i a1, a3, EXC_TABLE_KSTK
1527 wsr a3, excsave1
1528 1397
1529 movi a4, (1 << PS_WOE_BIT) | LOCKLEVEL 1398 movi a4, (1 << PS_WOE_BIT) | LOCKLEVEL
1530 wsr a4, ps 1399 wsr a4, ps
@@ -1568,9 +1437,9 @@ ENDPROC(fast_second_level_miss_double_kernel)
1568 * a0: trashed, original value saved on stack (PT_AREG0) 1437 * a0: trashed, original value saved on stack (PT_AREG0)
1569 * a1: a1 1438 * a1: a1
1570 * a2: new stack pointer, original in DEPC 1439 * a2: new stack pointer, original in DEPC
1571 * a3: dispatch table 1440 * a3: a3
1572 * depc: a2, original value saved on stack (PT_DEPC) 1441 * depc: a2, original value saved on stack (PT_DEPC)
1573 * excsave_1: a3 1442 * excsave_1: dispatch table
1574 * 1443 *
1575 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC 1444 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
1576 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception 1445 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
@@ -1578,9 +1447,10 @@ ENDPROC(fast_second_level_miss_double_kernel)
1578 1447
1579ENTRY(fast_second_level_miss) 1448ENTRY(fast_second_level_miss)
1580 1449
1581 /* Save a1. Note: we don't expect a double exception. */ 1450 /* Save a1 and a3. Note: we don't expect a double exception. */
1582 1451
1583 s32i a1, a2, PT_AREG1 1452 s32i a1, a2, PT_AREG1
1453 s32i a3, a2, PT_AREG3
1584 1454
1585 /* We need to map the page of PTEs for the user task. Find 1455 /* We need to map the page of PTEs for the user task. Find
1586 * the pointer to that page. Also, it's possible for tsk->mm 1456 * the pointer to that page. Also, it's possible for tsk->mm
@@ -1602,9 +1472,6 @@ ENTRY(fast_second_level_miss)
1602 l32i a0, a1, TASK_MM # tsk->mm 1472 l32i a0, a1, TASK_MM # tsk->mm
1603 beqz a0, 9f 1473 beqz a0, 9f
1604 1474
1605
1606 /* We deliberately destroy a3 that holds the exception table. */
1607
16088: rsr a3, excvaddr # fault address 14758: rsr a3, excvaddr # fault address
1609 _PGD_OFFSET(a0, a3, a1) 1476 _PGD_OFFSET(a0, a3, a1)
1610 l32i a0, a0, 0 # read pmdval 1477 l32i a0, a0, 0 # read pmdval
@@ -1655,7 +1522,7 @@ ENTRY(fast_second_level_miss)
1655 1522
1656 /* Exit critical section. */ 1523 /* Exit critical section. */
1657 1524
16584: movi a3, exc_table # restore a3 15254: rsr a3, excsave1
1659 movi a0, 0 1526 movi a0, 0
1660 s32i a0, a3, EXC_TABLE_FIXUP 1527 s32i a0, a3, EXC_TABLE_FIXUP
1661 1528
@@ -1663,8 +1530,8 @@ ENTRY(fast_second_level_miss)
1663 1530
1664 l32i a0, a2, PT_AREG0 1531 l32i a0, a2, PT_AREG0
1665 l32i a1, a2, PT_AREG1 1532 l32i a1, a2, PT_AREG1
1533 l32i a3, a2, PT_AREG3
1666 l32i a2, a2, PT_DEPC 1534 l32i a2, a2, PT_DEPC
1667 xsr a3, excsave1
1668 1535
1669 bgeui a2, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f 1536 bgeui a2, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
1670 1537
@@ -1751,11 +1618,8 @@ ENTRY(fast_second_level_miss)
1751 1618
17522: /* Invalid PGD, default exception handling */ 16192: /* Invalid PGD, default exception handling */
1753 1620
1754 movi a3, exc_table
1755 rsr a1, depc 1621 rsr a1, depc
1756 xsr a3, excsave1
1757 s32i a1, a2, PT_AREG2 1622 s32i a1, a2, PT_AREG2
1758 s32i a3, a2, PT_AREG3
1759 mov a1, a2 1623 mov a1, a2
1760 1624
1761 rsr a2, ps 1625 rsr a2, ps
@@ -1775,9 +1639,9 @@ ENDPROC(fast_second_level_miss)
1775 * a0: trashed, original value saved on stack (PT_AREG0) 1639 * a0: trashed, original value saved on stack (PT_AREG0)
1776 * a1: a1 1640 * a1: a1
1777 * a2: new stack pointer, original in DEPC 1641 * a2: new stack pointer, original in DEPC
1778 * a3: dispatch table 1642 * a3: a3
1779 * depc: a2, original value saved on stack (PT_DEPC) 1643 * depc: a2, original value saved on stack (PT_DEPC)
1780 * excsave_1: a3 1644 * excsave_1: dispatch table
1781 * 1645 *
1782 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC 1646 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
1783 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception 1647 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
@@ -1785,17 +1649,17 @@ ENDPROC(fast_second_level_miss)
1785 1649
1786ENTRY(fast_store_prohibited) 1650ENTRY(fast_store_prohibited)
1787 1651
1788 /* Save a1 and a4. */ 1652 /* Save a1 and a3. */
1789 1653
1790 s32i a1, a2, PT_AREG1 1654 s32i a1, a2, PT_AREG1
1791 s32i a4, a2, PT_AREG4 1655 s32i a3, a2, PT_AREG3
1792 1656
1793 GET_CURRENT(a1,a2) 1657 GET_CURRENT(a1,a2)
1794 l32i a0, a1, TASK_MM # tsk->mm 1658 l32i a0, a1, TASK_MM # tsk->mm
1795 beqz a0, 9f 1659 beqz a0, 9f
1796 1660
17978: rsr a1, excvaddr # fault address 16618: rsr a1, excvaddr # fault address
1798 _PGD_OFFSET(a0, a1, a4) 1662 _PGD_OFFSET(a0, a1, a3)
1799 l32i a0, a0, 0 1663 l32i a0, a0, 0
1800 beqz a0, 2f 1664 beqz a0, 2f
1801 1665
@@ -1804,39 +1668,37 @@ ENTRY(fast_store_prohibited)
1804 * and is not PAGE_NONE. See pgtable.h for possible PTE layouts. 1668 * and is not PAGE_NONE. See pgtable.h for possible PTE layouts.
1805 */ 1669 */
1806 1670
1807 _PTE_OFFSET(a0, a1, a4) 1671 _PTE_OFFSET(a0, a1, a3)
1808 l32i a4, a0, 0 # read pteval 1672 l32i a3, a0, 0 # read pteval
1809 movi a1, _PAGE_CA_INVALID 1673 movi a1, _PAGE_CA_INVALID
1810 ball a4, a1, 2f 1674 ball a3, a1, 2f
1811 bbci.l a4, _PAGE_WRITABLE_BIT, 2f 1675 bbci.l a3, _PAGE_WRITABLE_BIT, 2f
1812 1676
1813 movi a1, _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_HW_WRITE 1677 movi a1, _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_HW_WRITE
1814 or a4, a4, a1 1678 or a3, a3, a1
1815 rsr a1, excvaddr 1679 rsr a1, excvaddr
1816 s32i a4, a0, 0 1680 s32i a3, a0, 0
1817 1681
1818 /* We need to flush the cache if we have page coloring. */ 1682 /* We need to flush the cache if we have page coloring. */
1819#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK 1683#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
1820 dhwb a0, 0 1684 dhwb a0, 0
1821#endif 1685#endif
1822 pdtlb a0, a1 1686 pdtlb a0, a1
1823 wdtlb a4, a0 1687 wdtlb a3, a0
1824 1688
1825 /* Exit critical section. */ 1689 /* Exit critical section. */
1826 1690
1827 movi a0, 0 1691 movi a0, 0
1692 rsr a3, excsave1
1828 s32i a0, a3, EXC_TABLE_FIXUP 1693 s32i a0, a3, EXC_TABLE_FIXUP
1829 1694
1830 /* Restore the working registers, and return. */ 1695 /* Restore the working registers, and return. */
1831 1696
1832 l32i a4, a2, PT_AREG4 1697 l32i a3, a2, PT_AREG3
1833 l32i a1, a2, PT_AREG1 1698 l32i a1, a2, PT_AREG1
1834 l32i a0, a2, PT_AREG0 1699 l32i a0, a2, PT_AREG0
1835 l32i a2, a2, PT_DEPC 1700 l32i a2, a2, PT_DEPC
1836 1701
1837 /* Restore excsave1 and a3. */
1838
1839 xsr a3, excsave1
1840 bgeui a2, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f 1702 bgeui a2, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
1841 1703
1842 rsr a2, depc 1704 rsr a2, depc
@@ -1853,11 +1715,8 @@ ENTRY(fast_store_prohibited)
1853 1715
18542: /* If there was a problem, handle fault in C */ 17162: /* If there was a problem, handle fault in C */
1855 1717
1856 rsr a4, depc # still holds a2 1718 rsr a3, depc # still holds a2
1857 xsr a3, excsave1 1719 s32i a3, a2, PT_AREG2
1858 s32i a4, a2, PT_AREG2
1859 s32i a3, a2, PT_AREG3
1860 l32i a4, a2, PT_AREG4
1861 mov a1, a2 1720 mov a1, a2
1862 1721
1863 rsr a2, ps 1722 rsr a2, ps
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
index 101012bc1ff6..946fb8d06c8b 100644
--- a/arch/xtensa/kernel/setup.c
+++ b/arch/xtensa/kernel/setup.c
@@ -584,8 +584,8 @@ c_show(struct seq_file *f, void *slot)
584 "bogomips\t: %lu.%02lu\n", 584 "bogomips\t: %lu.%02lu\n",
585 XCHAL_BUILD_UNIQUE_ID, 585 XCHAL_BUILD_UNIQUE_ID,
586 XCHAL_HAVE_BE ? "big" : "little", 586 XCHAL_HAVE_BE ? "big" : "little",
587 CCOUNT_PER_JIFFY/(1000000/HZ), 587 ccount_freq/1000000,
588 (CCOUNT_PER_JIFFY/(10000/HZ)) % 100, 588 (ccount_freq/10000) % 100,
589 loops_per_jiffy/(500000/HZ), 589 loops_per_jiffy/(500000/HZ),
590 (loops_per_jiffy/(5000/HZ)) % 100); 590 (loops_per_jiffy/(5000/HZ)) % 100);
591 591
diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c
index 24bb0c1776ba..9af3dd88ad7e 100644
--- a/arch/xtensa/kernel/time.c
+++ b/arch/xtensa/kernel/time.c
@@ -29,9 +29,7 @@
29#include <asm/timex.h> 29#include <asm/timex.h>
30#include <asm/platform.h> 30#include <asm/platform.h>
31 31
32#ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT
33unsigned long ccount_freq; /* ccount Hz */ 32unsigned long ccount_freq; /* ccount Hz */
34#endif
35 33
36static cycle_t ccount_read(struct clocksource *cs) 34static cycle_t ccount_read(struct clocksource *cs)
37{ 35{
@@ -129,8 +127,10 @@ void __init time_init(void)
129 platform_calibrate_ccount(); 127 platform_calibrate_ccount();
130 printk("%d.%02d MHz\n", (int)ccount_freq/1000000, 128 printk("%d.%02d MHz\n", (int)ccount_freq/1000000,
131 (int)(ccount_freq/10000)%100); 129 (int)(ccount_freq/10000)%100);
130#else
131 ccount_freq = CONFIG_XTENSA_CPU_CLOCK*1000000UL;
132#endif 132#endif
133 clocksource_register_hz(&ccount_clocksource, CCOUNT_PER_JIFFY * HZ); 133 clocksource_register_hz(&ccount_clocksource, ccount_freq);
134 134
135 ccount_timer.evt.cpumask = cpumask_of(0); 135 ccount_timer.evt.cpumask = cpumask_of(0);
136 ccount_timer.evt.irq = irq_create_mapping(NULL, LINUX_TIMER_INT); 136 ccount_timer.evt.irq = irq_create_mapping(NULL, LINUX_TIMER_INT);
@@ -164,7 +164,7 @@ irqreturn_t timer_interrupt (int irq, void *dev_id)
164#ifndef CONFIG_GENERIC_CALIBRATE_DELAY 164#ifndef CONFIG_GENERIC_CALIBRATE_DELAY
165void calibrate_delay(void) 165void calibrate_delay(void)
166{ 166{
167 loops_per_jiffy = CCOUNT_PER_JIFFY; 167 loops_per_jiffy = ccount_freq / HZ;
168 printk("Calibrating delay loop (skipped)... " 168 printk("Calibrating delay loop (skipped)... "
169 "%lu.%02lu BogoMIPS preset\n", 169 "%lu.%02lu BogoMIPS preset\n",
170 loops_per_jiffy/(1000000/HZ), 170 loops_per_jiffy/(1000000/HZ),
diff --git a/arch/xtensa/kernel/vectors.S b/arch/xtensa/kernel/vectors.S
index f9e175382aa9..cb8fd44caabc 100644
--- a/arch/xtensa/kernel/vectors.S
+++ b/arch/xtensa/kernel/vectors.S
@@ -78,6 +78,7 @@ ENTRY(_UserExceptionVector)
78 s32i a0, a2, PT_DEPC # mark it as a regular exception 78 s32i a0, a2, PT_DEPC # mark it as a regular exception
79 addx4 a0, a0, a3 # find entry in table 79 addx4 a0, a0, a3 # find entry in table
80 l32i a0, a0, EXC_TABLE_FAST_USER # load handler 80 l32i a0, a0, EXC_TABLE_FAST_USER # load handler
81 xsr a3, excsave1 # restore a3 and dispatch table
81 jx a0 82 jx a0
82 83
83ENDPROC(_UserExceptionVector) 84ENDPROC(_UserExceptionVector)
@@ -104,6 +105,7 @@ ENTRY(_KernelExceptionVector)
104 s32i a0, a2, PT_DEPC # mark it as a regular exception 105 s32i a0, a2, PT_DEPC # mark it as a regular exception
105 addx4 a0, a0, a3 # find entry in table 106 addx4 a0, a0, a3 # find entry in table
106 l32i a0, a0, EXC_TABLE_FAST_KERNEL # load handler address 107 l32i a0, a0, EXC_TABLE_FAST_KERNEL # load handler address
108 xsr a3, excsave1 # restore a3 and dispatch table
107 jx a0 109 jx a0
108 110
109ENDPROC(_KernelExceptionVector) 111ENDPROC(_KernelExceptionVector)
@@ -168,7 +170,7 @@ ENDPROC(_KernelExceptionVector)
168 * 170 *
169 * a0: DEPC 171 * a0: DEPC
170 * a1: a1 172 * a1: a1
171 * a2: trashed, original value in EXC_TABLE_DOUBLE_A2 173 * a2: trashed, original value in EXC_TABLE_DOUBLE_SAVE
172 * a3: exctable 174 * a3: exctable
173 * depc: a0 175 * depc: a0
174 * excsave_1: a3 176 * excsave_1: a3
@@ -204,47 +206,46 @@ ENDPROC(_KernelExceptionVector)
204 206
205 .section .DoubleExceptionVector.text, "ax" 207 .section .DoubleExceptionVector.text, "ax"
206 .begin literal_prefix .DoubleExceptionVector 208 .begin literal_prefix .DoubleExceptionVector
209 .globl _DoubleExceptionVector_WindowUnderflow
210 .globl _DoubleExceptionVector_WindowOverflow
207 211
208ENTRY(_DoubleExceptionVector) 212ENTRY(_DoubleExceptionVector)
209 213
210 /* Deliberately destroy excsave (don't assume it's value was valid). */ 214 xsr a3, excsave1
211 215 s32i a2, a3, EXC_TABLE_DOUBLE_SAVE
212 wsr a3, excsave1 # save a3
213 216
214 /* Check for kernel double exception (usually fatal). */ 217 /* Check for kernel double exception (usually fatal). */
215 218
216 rsr a3, ps 219 rsr a2, ps
217 _bbci.l a3, PS_UM_BIT, .Lksp 220 _bbci.l a2, PS_UM_BIT, .Lksp
218 221
219 /* Check if we are currently handling a window exception. */ 222 /* Check if we are currently handling a window exception. */
220 /* Note: We don't need to indicate that we enter a critical section. */ 223 /* Note: We don't need to indicate that we enter a critical section. */
221 224
222 xsr a0, depc # get DEPC, save a0 225 xsr a0, depc # get DEPC, save a0
223 226
224 movi a3, WINDOW_VECTORS_VADDR 227 movi a2, WINDOW_VECTORS_VADDR
225 _bltu a0, a3, .Lfixup 228 _bltu a0, a2, .Lfixup
226 addi a3, a3, WINDOW_VECTORS_SIZE 229 addi a2, a2, WINDOW_VECTORS_SIZE
227 _bgeu a0, a3, .Lfixup 230 _bgeu a0, a2, .Lfixup
228 231
229 /* Window overflow/underflow exception. Get stack pointer. */ 232 /* Window overflow/underflow exception. Get stack pointer. */
230 233
231 mov a3, a2 234 l32i a2, a3, EXC_TABLE_KSTK
232 /* This explicit literal and the following references to it are made
233 * in order to fit DoubleExceptionVector.literals into the available
234 * 16-byte gap before DoubleExceptionVector.text in the absence of
235 * link time relaxation. See kernel/vmlinux.lds.S
236 */
237 .literal .Lexc_table, exc_table
238 l32r a2, .Lexc_table
239 l32i a2, a2, EXC_TABLE_KSTK
240 235
241 /* Check for overflow/underflow exception, jump if overflow. */ 236 /* Check for overflow/underflow exception, jump if overflow. */
242 237
243 _bbci.l a0, 6, .Lovfl 238 _bbci.l a0, 6, _DoubleExceptionVector_WindowOverflow
244
245 /* a0: depc, a1: a1, a2: kstk, a3: a2, depc: a0, excsave: a3 */
246 239
247 /* Restart window underflow exception. 240 /*
241 * Restart window underflow exception.
242 * Currently:
243 * depc = orig a0,
244 * a0 = orig DEPC,
245 * a2 = new sp based on KSTK from exc_table
246 * a3 = excsave_1
247 * excsave_1 = orig a3
248 *
248 * We return to the instruction in user space that caused the window 249 * We return to the instruction in user space that caused the window
249 * underflow exception. Therefore, we change window base to the value 250 * underflow exception. Therefore, we change window base to the value
250 * before we entered the window underflow exception and prepare the 251 * before we entered the window underflow exception and prepare the
@@ -252,10 +253,11 @@ ENTRY(_DoubleExceptionVector)
252 * by changing depc (in a0). 253 * by changing depc (in a0).
253 * Note: We can trash the current window frame (a0...a3) and depc! 254 * Note: We can trash the current window frame (a0...a3) and depc!
254 */ 255 */
255 256_DoubleExceptionVector_WindowUnderflow:
257 xsr a3, excsave1
256 wsr a2, depc # save stack pointer temporarily 258 wsr a2, depc # save stack pointer temporarily
257 rsr a0, ps 259 rsr a0, ps
258 extui a0, a0, PS_OWB_SHIFT, 4 260 extui a0, a0, PS_OWB_SHIFT, PS_OWB_WIDTH
259 wsr a0, windowbase 261 wsr a0, windowbase
260 rsync 262 rsync
261 263
@@ -263,28 +265,57 @@ ENTRY(_DoubleExceptionVector)
263 265
264 xsr a2, depc # save a2 and get stack pointer 266 xsr a2, depc # save a2 and get stack pointer
265 s32i a0, a2, PT_AREG0 267 s32i a0, a2, PT_AREG0
266 268 xsr a3, excsave1
267 wsr a3, excsave1 # save a3
268 l32r a3, .Lexc_table
269
270 rsr a0, exccause 269 rsr a0, exccause
271 s32i a0, a2, PT_DEPC # mark it as a regular exception 270 s32i a0, a2, PT_DEPC # mark it as a regular exception
272 addx4 a0, a0, a3 271 addx4 a0, a0, a3
272 xsr a3, excsave1
273 l32i a0, a0, EXC_TABLE_FAST_USER 273 l32i a0, a0, EXC_TABLE_FAST_USER
274 jx a0 274 jx a0
275 275
276.Lfixup:/* Check for a fixup handler or if we were in a critical section. */ 276 /*
277 * We only allow the ITLB miss exception if we are in kernel space.
278 * All other exceptions are unexpected and thus unrecoverable!
279 */
280
281#ifdef CONFIG_MMU
282 .extern fast_second_level_miss_double_kernel
283
284.Lksp: /* a0: a0, a1: a1, a2: a2, a3: trashed, depc: depc, excsave: a3 */
285
286 rsr a3, exccause
287 beqi a3, EXCCAUSE_ITLB_MISS, 1f
288 addi a3, a3, -EXCCAUSE_DTLB_MISS
289 bnez a3, .Lunrecoverable
2901: movi a3, fast_second_level_miss_double_kernel
291 jx a3
292#else
293.equ .Lksp, .Lunrecoverable
294#endif
295
296 /* Critical! We can't handle this situation. PANIC! */
277 297
278 /* a0: depc, a1: a1, a2: a2, a3: trashed, depc: a0, excsave1: a3 */ 298 .extern unrecoverable_exception
279 299
280 l32r a3, .Lexc_table 300.Lunrecoverable_fixup:
281 s32i a2, a3, EXC_TABLE_DOUBLE_SAVE # temporary variable 301 l32i a2, a3, EXC_TABLE_DOUBLE_SAVE
302 xsr a0, depc
303
304.Lunrecoverable:
305 rsr a3, excsave1
306 wsr a0, excsave1
307 movi a0, unrecoverable_exception
308 callx0 a0
309
310.Lfixup:/* Check for a fixup handler or if we were in a critical section. */
311
312 /* a0: depc, a1: a1, a2: trash, a3: exctable, depc: a0, excsave1: a3 */
282 313
283 /* Enter critical section. */ 314 /* Enter critical section. */
284 315
285 l32i a2, a3, EXC_TABLE_FIXUP 316 l32i a2, a3, EXC_TABLE_FIXUP
286 s32i a3, a3, EXC_TABLE_FIXUP 317 s32i a3, a3, EXC_TABLE_FIXUP
287 beq a2, a3, .Lunrecoverable_fixup # critical! 318 beq a2, a3, .Lunrecoverable_fixup # critical section
288 beqz a2, .Ldflt # no handler was registered 319 beqz a2, .Ldflt # no handler was registered
289 320
290 /* a0: depc, a1: a1, a2: trash, a3: exctable, depc: a0, excsave: a3 */ 321 /* a0: depc, a1: a1, a2: trash, a3: exctable, depc: a0, excsave: a3 */
@@ -293,58 +324,145 @@ ENTRY(_DoubleExceptionVector)
293 324
294.Ldflt: /* Get stack pointer. */ 325.Ldflt: /* Get stack pointer. */
295 326
296 l32i a3, a3, EXC_TABLE_DOUBLE_SAVE 327 l32i a2, a3, EXC_TABLE_DOUBLE_SAVE
297 addi a2, a3, -PT_USER_SIZE 328 addi a2, a2, -PT_USER_SIZE
298
299.Lovfl: /* Jump to default handlers. */
300 329
301 /* a0: depc, a1: a1, a2: kstk, a3: a2, depc: a0, excsave: a3 */ 330 /* a0: depc, a1: a1, a2: kstk, a3: exctable, depc: a0, excsave: a3 */
302 331
303 xsr a3, depc
304 s32i a0, a2, PT_DEPC 332 s32i a0, a2, PT_DEPC
305 s32i a3, a2, PT_AREG0 333 l32i a0, a3, EXC_TABLE_DOUBLE_SAVE
334 xsr a0, depc
335 s32i a0, a2, PT_AREG0
306 336
307 /* a0: avail, a1: a1, a2: kstk, a3: avail, depc: a2, excsave: a3 */ 337 /* a0: avail, a1: a1, a2: kstk, a3: exctable, depc: a2, excsave: a3 */
308 338
309 l32r a3, .Lexc_table
310 rsr a0, exccause 339 rsr a0, exccause
311 addx4 a0, a0, a3 340 addx4 a0, a0, a3
341 xsr a3, excsave1
312 l32i a0, a0, EXC_TABLE_FAST_USER 342 l32i a0, a0, EXC_TABLE_FAST_USER
313 jx a0 343 jx a0
314 344
315 /* 345 /*
316 * We only allow the ITLB miss exception if we are in kernel space. 346 * Restart window OVERFLOW exception.
317 * All other exceptions are unexpected and thus unrecoverable! 347 * Currently:
348 * depc = orig a0,
349 * a0 = orig DEPC,
350 * a2 = new sp based on KSTK from exc_table
351 * a3 = EXCSAVE_1
352 * excsave_1 = orig a3
353 *
354 * We return to the instruction in user space that caused the window
355 * overflow exception. Therefore, we change window base to the value
356 * before we entered the window overflow exception and prepare the
357 * registers to return as if we were coming from a regular exception
358 * by changing DEPC (in a0).
359 *
360 * NOTE: We CANNOT trash the current window frame (a0...a3), but we
361 * can clobber depc.
362 *
363 * The tricky part here is that overflow8 and overflow12 handlers
364 * save a0, then clobber a0. To restart the handler, we have to restore
365 * a0 if the double exception was past the point where a0 was clobbered.
366 *
367 * To keep things simple, we take advantage of the fact all overflow
368 * handlers save a0 in their very first instruction. If DEPC was past
369 * that instruction, we can safely restore a0 from where it was saved
370 * on the stack.
371 *
372 * a0: depc, a1: a1, a2: kstk, a3: exc_table, depc: a0, excsave1: a3
318 */ 373 */
374_DoubleExceptionVector_WindowOverflow:
375 extui a2, a0, 0, 6 # get offset into 64-byte vector handler
376 beqz a2, 1f # if at start of vector, don't restore
319 377
320#ifdef CONFIG_MMU 378 addi a0, a0, -128
321 .extern fast_second_level_miss_double_kernel 379 bbsi a0, 8, 1f # don't restore except for overflow 8 and 12
380 bbsi a0, 7, 2f
322 381
323.Lksp: /* a0: a0, a1: a1, a2: a2, a3: trashed, depc: depc, excsave: a3 */ 382 /*
383 * Restore a0 as saved by _WindowOverflow8().
384 *
385 * FIXME: we really need a fixup handler for this L32E,
386 * for the extremely unlikely case where the overflow handler's
387 * reference thru a0 gets a hardware TLB refill that bumps out
388 * the (distinct, aliasing) TLB entry that mapped its prior
389 * references thru a9, and where our reference now thru a9
390 * gets a 2nd-level miss exception (not hardware TLB refill).
391 */
324 392
325 rsr a3, exccause 393 l32e a2, a9, -16
326 beqi a3, EXCCAUSE_ITLB_MISS, 1f 394 wsr a2, depc # replace the saved a0
327 addi a3, a3, -EXCCAUSE_DTLB_MISS 395 j 1f
328 bnez a3, .Lunrecoverable
3291: movi a3, fast_second_level_miss_double_kernel
330 jx a3
331#else
332.equ .Lksp, .Lunrecoverable
333#endif
334 396
335 /* Critical! We can't handle this situation. PANIC! */ 3972:
398 /*
399 * Restore a0 as saved by _WindowOverflow12().
400 *
401 * FIXME: we really need a fixup handler for this L32E,
402 * for the extremely unlikely case where the overflow handler's
403 * reference thru a0 gets a hardware TLB refill that bumps out
404 * the (distinct, aliasing) TLB entry that mapped its prior
405 * references thru a13, and where our reference now thru a13
406 * gets a 2nd-level miss exception (not hardware TLB refill).
407 */
336 408
337 .extern unrecoverable_exception 409 l32e a2, a13, -16
410 wsr a2, depc # replace the saved a0
4111:
412 /*
413 * Restore WindowBase while leaving all address registers restored.
414 * We have to use ROTW for this, because WSR.WINDOWBASE requires
415 * an address register (which would prevent restore).
416 *
417 * Window Base goes from 0 ... 7 (Module 8)
418 * Window Start is 8 bits; Ex: (0b1010 1010):0x55 from series of call4s
419 */
420
421 rsr a0, ps
422 extui a0, a0, PS_OWB_SHIFT, PS_OWB_WIDTH
423 rsr a2, windowbase
424 sub a0, a2, a0
425 extui a0, a0, 0, 3
338 426
339.Lunrecoverable_fixup:
340 l32i a2, a3, EXC_TABLE_DOUBLE_SAVE 427 l32i a2, a3, EXC_TABLE_DOUBLE_SAVE
341 xsr a0, depc 428 xsr a3, excsave1
429 beqi a0, 1, .L1pane
430 beqi a0, 3, .L3pane
342 431
343.Lunrecoverable: 432 rsr a0, depc
344 rsr a3, excsave1 433 rotw -2
345 wsr a0, excsave1 434
346 movi a0, unrecoverable_exception 435 /*
347 callx0 a0 436 * We are now in the user code's original window frame.
437 * Process the exception as a user exception as if it was
438 * taken by the user code.
439 *
440 * This is similar to the user exception vector,
441 * except that PT_DEPC isn't set to EXCCAUSE.
442 */
4431:
444 xsr a3, excsave1
445 wsr a2, depc
446 l32i a2, a3, EXC_TABLE_KSTK
447 s32i a0, a2, PT_AREG0
448 rsr a0, exccause
449
450 s32i a0, a2, PT_DEPC
451
452 addx4 a0, a0, a3
453 l32i a0, a0, EXC_TABLE_FAST_USER
454 xsr a3, excsave1
455 jx a0
456
457.L1pane:
458 rsr a0, depc
459 rotw -1
460 j 1b
461
462.L3pane:
463 rsr a0, depc
464 rotw -3
465 j 1b
348 466
349 .end literal_prefix 467 .end literal_prefix
350 468
diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c
index d8507f812f46..74a60c7e085e 100644
--- a/arch/xtensa/kernel/xtensa_ksyms.c
+++ b/arch/xtensa/kernel/xtensa_ksyms.c
@@ -25,6 +25,7 @@
25#include <asm/io.h> 25#include <asm/io.h>
26#include <asm/page.h> 26#include <asm/page.h>
27#include <asm/pgalloc.h> 27#include <asm/pgalloc.h>
28#include <asm/ftrace.h>
28#ifdef CONFIG_BLK_DEV_FD 29#ifdef CONFIG_BLK_DEV_FD
29#include <asm/floppy.h> 30#include <asm/floppy.h>
30#endif 31#endif