提交 67002151 编写于 作者: L Linus Torvalds

Merge tag 'xtensa-next-20130912' of git://github.com/czankel/xtensa-linux

Pull Xtensa updates from Chris Zankel.

* tag 'xtensa-next-20130912' of git://github.com/czankel/xtensa-linux:
  xtensa: Fix broken allmodconfig build
  xtensa: remove CCOUNT_PER_JIFFY
  xtensa: fix !CONFIG_XTENSA_CALIBRATE_CCOUNT build failure
  xtensa: don't use echo -e needlessly
  xtensa: new fast_alloca handler
  xtensa: keep a3 and excsave1 on entry to exception handlers
  xtensa: enable kernel preemption
  xtensa: check thread flags atomically on return from user exception
...@@ -55,10 +55,10 @@ ifneq ($(CONFIG_LD_NO_RELAX),) ...@@ -55,10 +55,10 @@ ifneq ($(CONFIG_LD_NO_RELAX),)
LDFLAGS := --no-relax LDFLAGS := --no-relax
endif endif
ifeq ($(shell echo -e __XTENSA_EB__ | $(CC) -E - | grep -v "\#"),1) ifeq ($(shell echo __XTENSA_EB__ | $(CC) -E - | grep -v "\#"),1)
CHECKFLAGS += -D__XTENSA_EB__ CHECKFLAGS += -D__XTENSA_EB__
endif endif
ifeq ($(shell echo -e __XTENSA_EL__ | $(CC) -E - | grep -v "\#"),1) ifeq ($(shell echo __XTENSA_EL__ | $(CC) -E - | grep -v "\#"),1)
CHECKFLAGS += -D__XTENSA_EL__ CHECKFLAGS += -D__XTENSA_EL__
endif endif
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
KBUILD_CFLAGS += -fno-builtin -Iarch/$(ARCH)/boot/include KBUILD_CFLAGS += -fno-builtin -Iarch/$(ARCH)/boot/include
HOSTFLAGS += -Iarch/$(ARCH)/boot/include HOSTFLAGS += -Iarch/$(ARCH)/boot/include
BIG_ENDIAN := $(shell echo -e __XTENSA_EB__ | $(CC) -E - | grep -v "\#") BIG_ENDIAN := $(shell echo __XTENSA_EB__ | $(CC) -E - | grep -v "\#")
export ccflags-y export ccflags-y
export BIG_ENDIAN export BIG_ENDIAN
......
...@@ -82,6 +82,7 @@ ...@@ -82,6 +82,7 @@
#define PS_CALLINC_SHIFT 16 #define PS_CALLINC_SHIFT 16
#define PS_CALLINC_MASK 0x00030000 #define PS_CALLINC_MASK 0x00030000
#define PS_OWB_SHIFT 8 #define PS_OWB_SHIFT 8
#define PS_OWB_WIDTH 4
#define PS_OWB_MASK 0x00000F00 #define PS_OWB_MASK 0x00000F00
#define PS_RING_SHIFT 6 #define PS_RING_SHIFT 6
#define PS_RING_MASK 0x000000C0 #define PS_RING_MASK 0x000000C0
......
...@@ -35,13 +35,7 @@ ...@@ -35,13 +35,7 @@
# error "Bad timer number for Linux configurations!" # error "Bad timer number for Linux configurations!"
#endif #endif
#ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT
extern unsigned long ccount_freq; extern unsigned long ccount_freq;
#define CCOUNT_PER_JIFFY (ccount_freq / HZ)
#else
#define CCOUNT_PER_JIFFY (CONFIG_XTENSA_CPU_CLOCK*(1000000UL/HZ))
#endif
typedef unsigned long long cycles_t; typedef unsigned long long cycles_t;
......
...@@ -146,9 +146,9 @@ ...@@ -146,9 +146,9 @@
* a0: trashed, original value saved on stack (PT_AREG0) * a0: trashed, original value saved on stack (PT_AREG0)
* a1: a1 * a1: a1
* a2: new stack pointer, original in DEPC * a2: new stack pointer, original in DEPC
* a3: dispatch table * a3: a3
* depc: a2, original value saved on stack (PT_DEPC) * depc: a2, original value saved on stack (PT_DEPC)
* excsave_1: a3 * excsave_1: dispatch table
* *
* PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
* < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
...@@ -171,7 +171,6 @@ ENTRY(fast_unaligned) ...@@ -171,7 +171,6 @@ ENTRY(fast_unaligned)
s32i a8, a2, PT_AREG8 s32i a8, a2, PT_AREG8
rsr a0, depc rsr a0, depc
xsr a3, excsave1
s32i a0, a2, PT_AREG2 s32i a0, a2, PT_AREG2
s32i a3, a2, PT_AREG3 s32i a3, a2, PT_AREG3
......
...@@ -32,9 +32,9 @@ ...@@ -32,9 +32,9 @@
* a0: trashed, original value saved on stack (PT_AREG0) * a0: trashed, original value saved on stack (PT_AREG0)
* a1: a1 * a1: a1
* a2: new stack pointer, original in DEPC * a2: new stack pointer, original in DEPC
* a3: dispatch table * a3: a3
* depc: a2, original value saved on stack (PT_DEPC) * depc: a2, original value saved on stack (PT_DEPC)
* excsave_1: a3 * excsave_1: dispatch table
* *
* PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
* < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
...@@ -225,9 +225,9 @@ ENDPROC(coprocessor_restore) ...@@ -225,9 +225,9 @@ ENDPROC(coprocessor_restore)
* a0: trashed, original value saved on stack (PT_AREG0) * a0: trashed, original value saved on stack (PT_AREG0)
* a1: a1 * a1: a1
* a2: new stack pointer, original in DEPC * a2: new stack pointer, original in DEPC
* a3: dispatch table * a3: a3
* depc: a2, original value saved on stack (PT_DEPC) * depc: a2, original value saved on stack (PT_DEPC)
* excsave_1: a3 * excsave_1: dispatch table
* *
* PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
* < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
...@@ -245,7 +245,6 @@ ENTRY(fast_coprocessor) ...@@ -245,7 +245,6 @@ ENTRY(fast_coprocessor)
/* Save remaining registers a1-a3 and SAR */ /* Save remaining registers a1-a3 and SAR */
xsr a3, excsave1
s32i a3, a2, PT_AREG3 s32i a3, a2, PT_AREG3
rsr a3, sar rsr a3, sar
s32i a1, a2, PT_AREG1 s32i a1, a2, PT_AREG1
......
...@@ -31,8 +31,6 @@ ...@@ -31,8 +31,6 @@
/* Unimplemented features. */ /* Unimplemented features. */
#undef KERNEL_STACK_OVERFLOW_CHECK #undef KERNEL_STACK_OVERFLOW_CHECK
#undef PREEMPTIBLE_KERNEL
#undef ALLOCA_EXCEPTION_IN_IRAM
/* Not well tested. /* Not well tested.
* *
...@@ -92,9 +90,9 @@ ...@@ -92,9 +90,9 @@
* a0: trashed, original value saved on stack (PT_AREG0) * a0: trashed, original value saved on stack (PT_AREG0)
* a1: a1 * a1: a1
* a2: new stack pointer, original value in depc * a2: new stack pointer, original value in depc
* a3: dispatch table * a3: a3
* depc: a2, original value saved on stack (PT_DEPC) * depc: a2, original value saved on stack (PT_DEPC)
* excsave1: a3 * excsave1: dispatch table
* *
* PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
* < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
...@@ -110,9 +108,8 @@ ...@@ -110,9 +108,8 @@
ENTRY(user_exception) ENTRY(user_exception)
/* Save a2, a3, and depc, restore excsave_1 and set SP. */ /* Save a1, a2, a3, and set SP. */
xsr a3, excsave1
rsr a0, depc rsr a0, depc
s32i a1, a2, PT_AREG1 s32i a1, a2, PT_AREG1
s32i a0, a2, PT_AREG2 s32i a0, a2, PT_AREG2
...@@ -238,9 +235,9 @@ ENDPROC(user_exception) ...@@ -238,9 +235,9 @@ ENDPROC(user_exception)
* a0: trashed, original value saved on stack (PT_AREG0) * a0: trashed, original value saved on stack (PT_AREG0)
* a1: a1 * a1: a1
* a2: new stack pointer, original in DEPC * a2: new stack pointer, original in DEPC
* a3: dispatch table * a3: a3
* depc: a2, original value saved on stack (PT_DEPC) * depc: a2, original value saved on stack (PT_DEPC)
* excsave_1: a3 * excsave_1: dispatch table
* *
* PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
* < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
...@@ -256,9 +253,8 @@ ENDPROC(user_exception) ...@@ -256,9 +253,8 @@ ENDPROC(user_exception)
ENTRY(kernel_exception) ENTRY(kernel_exception)
/* Save a0, a2, a3, DEPC and set SP. */ /* Save a1, a2, a3, and set SP. */
xsr a3, excsave1 # restore a3, excsave_1
rsr a0, depc # get a2 rsr a0, depc # get a2
s32i a1, a2, PT_AREG1 s32i a1, a2, PT_AREG1
s32i a0, a2, PT_AREG2 s32i a0, a2, PT_AREG2
...@@ -409,7 +405,7 @@ common_exception: ...@@ -409,7 +405,7 @@ common_exception:
* exception handler and call the exception handler. * exception handler and call the exception handler.
*/ */
movi a4, exc_table rsr a4, excsave1
mov a6, a1 # pass stack frame mov a6, a1 # pass stack frame
mov a7, a0 # pass EXCCAUSE mov a7, a0 # pass EXCCAUSE
addx4 a4, a0, a4 addx4 a4, a0, a4
...@@ -423,28 +419,15 @@ common_exception: ...@@ -423,28 +419,15 @@ common_exception:
.global common_exception_return .global common_exception_return
common_exception_return: common_exception_return:
#ifdef CONFIG_TRACE_IRQFLAGS
l32i a4, a1, PT_DEPC
/* Double exception means we came here with an exception
* while PS.EXCM was set, i.e. interrupts disabled.
*/
bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
l32i a4, a1, PT_EXCCAUSE
bnei a4, EXCCAUSE_LEVEL1_INTERRUPT, 1f
/* We came here with an interrupt means interrupts were enabled
* and we'll reenable them on return.
*/
movi a4, trace_hardirqs_on
callx4 a4
1: 1:
#endif rsil a2, LOCKLEVEL
/* Jump if we are returning from kernel exceptions. */ /* Jump if we are returning from kernel exceptions. */
1: l32i a3, a1, PT_PS l32i a3, a1, PT_PS
_bbci.l a3, PS_UM_BIT, 4f GET_THREAD_INFO(a2, a1)
l32i a4, a2, TI_FLAGS
rsil a2, 0 _bbci.l a3, PS_UM_BIT, 6f
/* Specific to a user exception exit: /* Specific to a user exception exit:
* We need to check some flags for signal handling and rescheduling, * We need to check some flags for signal handling and rescheduling,
...@@ -453,9 +436,6 @@ common_exception_return: ...@@ -453,9 +436,6 @@ common_exception_return:
* Note that we don't disable interrupts here. * Note that we don't disable interrupts here.
*/ */
GET_THREAD_INFO(a2,a1)
l32i a4, a2, TI_FLAGS
_bbsi.l a4, TIF_NEED_RESCHED, 3f _bbsi.l a4, TIF_NEED_RESCHED, 3f
_bbsi.l a4, TIF_NOTIFY_RESUME, 2f _bbsi.l a4, TIF_NOTIFY_RESUME, 2f
_bbci.l a4, TIF_SIGPENDING, 5f _bbci.l a4, TIF_SIGPENDING, 5f
...@@ -465,6 +445,7 @@ common_exception_return: ...@@ -465,6 +445,7 @@ common_exception_return:
/* Call do_signal() */ /* Call do_signal() */
rsil a2, 0
movi a4, do_notify_resume # int do_notify_resume(struct pt_regs*) movi a4, do_notify_resume # int do_notify_resume(struct pt_regs*)
mov a6, a1 mov a6, a1
callx4 a4 callx4 a4
...@@ -472,10 +453,24 @@ common_exception_return: ...@@ -472,10 +453,24 @@ common_exception_return:
3: /* Reschedule */ 3: /* Reschedule */
rsil a2, 0
movi a4, schedule # void schedule (void) movi a4, schedule # void schedule (void)
callx4 a4 callx4 a4
j 1b j 1b
#ifdef CONFIG_PREEMPT
6:
_bbci.l a4, TIF_NEED_RESCHED, 4f
/* Check current_thread_info->preempt_count */
l32i a4, a2, TI_PRE_COUNT
bnez a4, 4f
movi a4, preempt_schedule_irq
callx4 a4
j 1b
#endif
5: 5:
#ifdef CONFIG_DEBUG_TLB_SANITY #ifdef CONFIG_DEBUG_TLB_SANITY
l32i a4, a1, PT_DEPC l32i a4, a1, PT_DEPC
...@@ -483,7 +478,24 @@ common_exception_return: ...@@ -483,7 +478,24 @@ common_exception_return:
movi a4, check_tlb_sanity movi a4, check_tlb_sanity
callx4 a4 callx4 a4
#endif #endif
4: /* Restore optional registers. */ 6:
4:
#ifdef CONFIG_TRACE_IRQFLAGS
l32i a4, a1, PT_DEPC
/* Double exception means we came here with an exception
* while PS.EXCM was set, i.e. interrupts disabled.
*/
bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
l32i a4, a1, PT_EXCCAUSE
bnei a4, EXCCAUSE_LEVEL1_INTERRUPT, 1f
/* We came here with an interrupt means interrupts were enabled
* and we'll reenable them on return.
*/
movi a4, trace_hardirqs_on
callx4 a4
1:
#endif
/* Restore optional registers. */
load_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT load_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT
...@@ -570,29 +582,6 @@ user_exception_exit: ...@@ -570,29 +582,6 @@ user_exception_exit:
kernel_exception_exit: kernel_exception_exit:
#ifdef PREEMPTIBLE_KERNEL
#ifdef CONFIG_PREEMPT
/*
* Note: We've just returned from a call4, so we have
* at least 4 addt'l regs.
*/
/* Check current_thread_info->preempt_count */
GET_THREAD_INFO(a2)
l32i a3, a2, TI_PREEMPT
bnez a3, 1f
l32i a2, a2, TI_FLAGS
1:
#endif
#endif
/* Check if we have to do a movsp. /* Check if we have to do a movsp.
* *
* We only have to do a movsp if the previous window-frame has * We only have to do a movsp if the previous window-frame has
...@@ -829,176 +818,63 @@ ENDPROC(unrecoverable_exception) ...@@ -829,176 +818,63 @@ ENDPROC(unrecoverable_exception)
* *
* The ALLOCA handler is entered when user code executes the MOVSP * The ALLOCA handler is entered when user code executes the MOVSP
* instruction and the caller's frame is not in the register file. * instruction and the caller's frame is not in the register file.
* In this case, the caller frame's a0..a3 are on the stack just
* below sp (a1), and this handler moves them.
* *
* For "MOVSP <ar>,<as>" without destination register a1, this routine * This algorithm was taken from the Ross Morley's RTOS Porting Layer:
* simply moves the value from <as> to <ar> without moving the save area. *
* /home/ross/rtos/porting/XtensaRTOS-PortingLayer-20090507/xtensa_vectors.S
*
* It leverages the existing window spill/fill routines and their support for
* double exceptions. The 'movsp' instruction will only cause an exception if
* the next window needs to be loaded. In fact this ALLOCA exception may be
* replaced at some point by changing the hardware to do a underflow exception
* of the proper size instead.
*
* This algorithm simply backs out the register changes started by the user
* excpetion handler, makes it appear that we have started a window underflow
* by rotating the window back and then setting the old window base (OWB) in
* the 'ps' register with the rolled back window base. The 'movsp' instruction
* will be re-executed and this time since the next window frames is in the
* active AR registers it won't cause an exception.
*
* If the WindowUnderflow code gets a TLB miss the page will get mapped
* the the partial windeowUnderflow will be handeled in the double exception
* handler.
* *
* Entry condition: * Entry condition:
* *
* a0: trashed, original value saved on stack (PT_AREG0) * a0: trashed, original value saved on stack (PT_AREG0)
* a1: a1 * a1: a1
* a2: new stack pointer, original in DEPC * a2: new stack pointer, original in DEPC
* a3: dispatch table * a3: a3
* depc: a2, original value saved on stack (PT_DEPC) * depc: a2, original value saved on stack (PT_DEPC)
* excsave_1: a3 * excsave_1: dispatch table
* *
* PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
* < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
*/ */
#if XCHAL_HAVE_BE
#define _EXTUI_MOVSP_SRC(ar) extui ar, ar, 4, 4
#define _EXTUI_MOVSP_DST(ar) extui ar, ar, 0, 4
#else
#define _EXTUI_MOVSP_SRC(ar) extui ar, ar, 0, 4
#define _EXTUI_MOVSP_DST(ar) extui ar, ar, 4, 4
#endif
ENTRY(fast_alloca) ENTRY(fast_alloca)
rsr a0, windowbase
rotw -1
rsr a2, ps
extui a3, a2, PS_OWB_SHIFT, PS_OWB_WIDTH
xor a3, a3, a4
l32i a4, a6, PT_AREG0
l32i a1, a6, PT_DEPC
rsr a6, depc
wsr a1, depc
slli a3, a3, PS_OWB_SHIFT
xor a2, a2, a3
wsr a2, ps
rsync
/* We shouldn't be in a double exception. */ _bbci.l a4, 31, 4f
rotw -1
l32i a0, a2, PT_DEPC _bbci.l a8, 30, 8f
_bgeui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, .Lunhandled_double rotw -1
j _WindowUnderflow12
rsr a0, depc # get a2 8: j _WindowUnderflow8
s32i a4, a2, PT_AREG4 # save a4 and 4: j _WindowUnderflow4
s32i a0, a2, PT_AREG2 # a2 to stack
/* Exit critical section. */
movi a0, 0
s32i a0, a3, EXC_TABLE_FIXUP
/* Restore a3, excsave_1 */
xsr a3, excsave1 # make sure excsave_1 is valid for dbl.
rsr a4, epc1 # get exception address
s32i a3, a2, PT_AREG3 # save a3 to stack
#ifdef ALLOCA_EXCEPTION_IN_IRAM
#error iram not supported
#else
/* Note: l8ui not allowed in IRAM/IROM!! */
l8ui a0, a4, 1 # read as(src) from MOVSP instruction
#endif
movi a3, .Lmovsp_src
_EXTUI_MOVSP_SRC(a0) # extract source register number
addx8 a3, a0, a3
jx a3
.Lunhandled_double:
wsr a0, excsave1
movi a0, unrecoverable_exception
callx0 a0
.align 8
.Lmovsp_src:
l32i a3, a2, PT_AREG0; _j 1f; .align 8
mov a3, a1; _j 1f; .align 8
l32i a3, a2, PT_AREG2; _j 1f; .align 8
l32i a3, a2, PT_AREG3; _j 1f; .align 8
l32i a3, a2, PT_AREG4; _j 1f; .align 8
mov a3, a5; _j 1f; .align 8
mov a3, a6; _j 1f; .align 8
mov a3, a7; _j 1f; .align 8
mov a3, a8; _j 1f; .align 8
mov a3, a9; _j 1f; .align 8
mov a3, a10; _j 1f; .align 8
mov a3, a11; _j 1f; .align 8
mov a3, a12; _j 1f; .align 8
mov a3, a13; _j 1f; .align 8
mov a3, a14; _j 1f; .align 8
mov a3, a15; _j 1f; .align 8
1:
#ifdef ALLOCA_EXCEPTION_IN_IRAM
#error iram not supported
#else
l8ui a0, a4, 0 # read ar(dst) from MOVSP instruction
#endif
addi a4, a4, 3 # step over movsp
_EXTUI_MOVSP_DST(a0) # extract destination register
wsr a4, epc1 # save new epc_1
_bnei a0, 1, 1f # no 'movsp a1, ax': jump
/* Move the save area. This implies the use of the L32E
* and S32E instructions, because this move must be done with
* the user's PS.RING privilege levels, not with ring 0
* (kernel's) privileges currently active with PS.EXCM
* set. Note that we have stil registered a fixup routine with the
* double exception vector in case a double exception occurs.
*/
/* a0,a4:avail a1:old user stack a2:exc. stack a3:new user stack. */
l32e a0, a1, -16
l32e a4, a1, -12
s32e a0, a3, -16
s32e a4, a3, -12
l32e a0, a1, -8
l32e a4, a1, -4
s32e a0, a3, -8
s32e a4, a3, -4
/* Restore stack-pointer and all the other saved registers. */
mov a1, a3
l32i a4, a2, PT_AREG4
l32i a3, a2, PT_AREG3
l32i a0, a2, PT_AREG0
l32i a2, a2, PT_AREG2
rfe
/* MOVSP <at>,<as> was invoked with <at> != a1.
* Because the stack pointer is not being modified,
* we should be able to just modify the pointer
* without moving any save area.
* The processor only traps these occurrences if the
* caller window isn't live, so unfortunately we can't
* use this as an alternate trap mechanism.
* So we just do the move. This requires that we
* resolve the destination register, not just the source,
* so there's some extra work.
* (PERHAPS NOT REALLY NEEDED, BUT CLEANER...)
*/
/* a0 dst-reg, a1 user-stack, a2 stack, a3 value of src reg. */
1: movi a4, .Lmovsp_dst
addx8 a4, a0, a4
jx a4
.align 8
.Lmovsp_dst:
s32i a3, a2, PT_AREG0; _j 1f; .align 8
mov a1, a3; _j 1f; .align 8
s32i a3, a2, PT_AREG2; _j 1f; .align 8
s32i a3, a2, PT_AREG3; _j 1f; .align 8
s32i a3, a2, PT_AREG4; _j 1f; .align 8
mov a5, a3; _j 1f; .align 8
mov a6, a3; _j 1f; .align 8
mov a7, a3; _j 1f; .align 8
mov a8, a3; _j 1f; .align 8
mov a9, a3; _j 1f; .align 8
mov a10, a3; _j 1f; .align 8
mov a11, a3; _j 1f; .align 8
mov a12, a3; _j 1f; .align 8
mov a13, a3; _j 1f; .align 8
mov a14, a3; _j 1f; .align 8
mov a15, a3; _j 1f; .align 8
1: l32i a4, a2, PT_AREG4
l32i a3, a2, PT_AREG3
l32i a0, a2, PT_AREG0
l32i a2, a2, PT_AREG2
rfe
ENDPROC(fast_alloca) ENDPROC(fast_alloca)
/* /*
...@@ -1015,9 +891,9 @@ ENDPROC(fast_alloca) ...@@ -1015,9 +891,9 @@ ENDPROC(fast_alloca)
* a0: trashed, original value saved on stack (PT_AREG0) * a0: trashed, original value saved on stack (PT_AREG0)
* a1: a1 * a1: a1
* a2: new stack pointer, original in DEPC * a2: new stack pointer, original in DEPC
* a3: dispatch table * a3: a3
* depc: a2, original value saved on stack (PT_DEPC) * depc: a2, original value saved on stack (PT_DEPC)
* excsave_1: a3 * excsave_1: dispatch table
*/ */
ENTRY(fast_syscall_kernel) ENTRY(fast_syscall_kernel)
...@@ -1064,7 +940,6 @@ ENTRY(fast_syscall_unrecoverable) ...@@ -1064,7 +940,6 @@ ENTRY(fast_syscall_unrecoverable)
l32i a0, a2, PT_AREG0 # restore a0 l32i a0, a2, PT_AREG0 # restore a0
xsr a2, depc # restore a2, depc xsr a2, depc # restore a2, depc
rsr a3, excsave1
wsr a0, excsave1 wsr a0, excsave1
movi a0, unrecoverable_exception movi a0, unrecoverable_exception
...@@ -1086,10 +961,10 @@ ENDPROC(fast_syscall_unrecoverable) ...@@ -1086,10 +961,10 @@ ENDPROC(fast_syscall_unrecoverable)
* a0: a2 (syscall-nr), original value saved on stack (PT_AREG0) * a0: a2 (syscall-nr), original value saved on stack (PT_AREG0)
* a1: a1 * a1: a1
* a2: new stack pointer, original in a0 and DEPC * a2: new stack pointer, original in a0 and DEPC
* a3: dispatch table, original in excsave_1 * a3: a3
* a4..a15: unchanged * a4..a15: unchanged
* depc: a2, original value saved on stack (PT_DEPC) * depc: a2, original value saved on stack (PT_DEPC)
* excsave_1: a3 * excsave_1: dispatch table
* *
* PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
* < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
...@@ -1122,8 +997,6 @@ ENDPROC(fast_syscall_unrecoverable) ...@@ -1122,8 +997,6 @@ ENDPROC(fast_syscall_unrecoverable)
ENTRY(fast_syscall_xtensa) ENTRY(fast_syscall_xtensa)
xsr a3, excsave1 # restore a3, excsave1
s32i a7, a2, PT_AREG7 # we need an additional register s32i a7, a2, PT_AREG7 # we need an additional register
movi a7, 4 # sizeof(unsigned int) movi a7, 4 # sizeof(unsigned int)
access_ok a3, a7, a0, a2, .Leac # a0: scratch reg, a2: sp access_ok a3, a7, a0, a2, .Leac # a0: scratch reg, a2: sp
...@@ -1186,9 +1059,9 @@ ENDPROC(fast_syscall_xtensa) ...@@ -1186,9 +1059,9 @@ ENDPROC(fast_syscall_xtensa)
* a0: trashed, original value saved on stack (PT_AREG0) * a0: trashed, original value saved on stack (PT_AREG0)
* a1: a1 * a1: a1
* a2: new stack pointer, original in DEPC * a2: new stack pointer, original in DEPC
* a3: dispatch table * a3: a3
* depc: a2, original value saved on stack (PT_DEPC) * depc: a2, original value saved on stack (PT_DEPC)
* excsave_1: a3 * excsave_1: dispatch table
* *
* Note: We assume the stack pointer is EXC_TABLE_KSTK in the fixup handler. * Note: We assume the stack pointer is EXC_TABLE_KSTK in the fixup handler.
*/ */
...@@ -1197,15 +1070,16 @@ ENTRY(fast_syscall_spill_registers) ...@@ -1197,15 +1070,16 @@ ENTRY(fast_syscall_spill_registers)
/* Register a FIXUP handler (pass current wb as a parameter) */ /* Register a FIXUP handler (pass current wb as a parameter) */
xsr a3, excsave1
movi a0, fast_syscall_spill_registers_fixup movi a0, fast_syscall_spill_registers_fixup
s32i a0, a3, EXC_TABLE_FIXUP s32i a0, a3, EXC_TABLE_FIXUP
rsr a0, windowbase rsr a0, windowbase
s32i a0, a3, EXC_TABLE_PARAM s32i a0, a3, EXC_TABLE_PARAM
xsr a3, excsave1 # restore a3 and excsave_1
/* Save a3 and SAR on stack. */ /* Save a3, a4 and SAR on stack. */
rsr a0, sar rsr a0, sar
xsr a3, excsave1 # restore a3 and excsave_1
s32i a3, a2, PT_AREG3 s32i a3, a2, PT_AREG3
s32i a4, a2, PT_AREG4 s32i a4, a2, PT_AREG4
s32i a0, a2, PT_AREG5 # store SAR to PT_AREG5 s32i a0, a2, PT_AREG5 # store SAR to PT_AREG5
...@@ -1259,14 +1133,14 @@ fast_syscall_spill_registers_fixup: ...@@ -1259,14 +1133,14 @@ fast_syscall_spill_registers_fixup:
* in WS, so that the exception handlers save them to the task stack. * in WS, so that the exception handlers save them to the task stack.
*/ */
rsr a3, excsave1 # get spill-mask xsr a3, excsave1 # get spill-mask
slli a2, a3, 1 # shift left by one slli a2, a3, 1 # shift left by one
slli a3, a2, 32-WSBITS slli a3, a2, 32-WSBITS
src a2, a2, a3 # a1 = xxwww1yyxxxwww1yy...... src a2, a2, a3 # a1 = xxwww1yyxxxwww1yy......
wsr a2, windowstart # set corrected windowstart wsr a2, windowstart # set corrected windowstart
movi a3, exc_table rsr a3, excsave1
l32i a2, a3, EXC_TABLE_DOUBLE_SAVE # restore a2 l32i a2, a3, EXC_TABLE_DOUBLE_SAVE # restore a2
l32i a3, a3, EXC_TABLE_PARAM # original WB (in user task) l32i a3, a3, EXC_TABLE_PARAM # original WB (in user task)
...@@ -1303,7 +1177,7 @@ fast_syscall_spill_registers_fixup: ...@@ -1303,7 +1177,7 @@ fast_syscall_spill_registers_fixup:
/* Jump to the exception handler. */ /* Jump to the exception handler. */
movi a3, exc_table rsr a3, excsave1
rsr a0, exccause rsr a0, exccause
addx4 a0, a0, a3 # find entry in table addx4 a0, a0, a3 # find entry in table
l32i a0, a0, EXC_TABLE_FAST_USER # load handler l32i a0, a0, EXC_TABLE_FAST_USER # load handler
...@@ -1320,6 +1194,7 @@ fast_syscall_spill_registers_fixup_return: ...@@ -1320,6 +1194,7 @@ fast_syscall_spill_registers_fixup_return:
xsr a3, excsave1 xsr a3, excsave1
movi a2, fast_syscall_spill_registers_fixup movi a2, fast_syscall_spill_registers_fixup
s32i a2, a3, EXC_TABLE_FIXUP s32i a2, a3, EXC_TABLE_FIXUP
s32i a0, a3, EXC_TABLE_DOUBLE_SAVE
rsr a2, windowbase rsr a2, windowbase
s32i a2, a3, EXC_TABLE_PARAM s32i a2, a3, EXC_TABLE_PARAM
l32i a2, a3, EXC_TABLE_KSTK l32i a2, a3, EXC_TABLE_KSTK
...@@ -1331,11 +1206,6 @@ fast_syscall_spill_registers_fixup_return: ...@@ -1331,11 +1206,6 @@ fast_syscall_spill_registers_fixup_return:
wsr a3, windowbase wsr a3, windowbase
rsync rsync
/* Restore a3 and return. */
movi a3, exc_table
xsr a3, excsave1
rfde rfde
...@@ -1522,9 +1392,8 @@ ENTRY(_spill_registers) ...@@ -1522,9 +1392,8 @@ ENTRY(_spill_registers)
movi a0, 0 movi a0, 0
movi a3, exc_table rsr a3, excsave1
l32i a1, a3, EXC_TABLE_KSTK l32i a1, a3, EXC_TABLE_KSTK
wsr a3, excsave1
movi a4, (1 << PS_WOE_BIT) | LOCKLEVEL movi a4, (1 << PS_WOE_BIT) | LOCKLEVEL
wsr a4, ps wsr a4, ps
...@@ -1568,9 +1437,9 @@ ENDPROC(fast_second_level_miss_double_kernel) ...@@ -1568,9 +1437,9 @@ ENDPROC(fast_second_level_miss_double_kernel)
* a0: trashed, original value saved on stack (PT_AREG0) * a0: trashed, original value saved on stack (PT_AREG0)
* a1: a1 * a1: a1
* a2: new stack pointer, original in DEPC * a2: new stack pointer, original in DEPC
* a3: dispatch table * a3: a3
* depc: a2, original value saved on stack (PT_DEPC) * depc: a2, original value saved on stack (PT_DEPC)
* excsave_1: a3 * excsave_1: dispatch table
* *
* PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
* < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
...@@ -1578,9 +1447,10 @@ ENDPROC(fast_second_level_miss_double_kernel) ...@@ -1578,9 +1447,10 @@ ENDPROC(fast_second_level_miss_double_kernel)
ENTRY(fast_second_level_miss) ENTRY(fast_second_level_miss)
/* Save a1. Note: we don't expect a double exception. */ /* Save a1 and a3. Note: we don't expect a double exception. */
s32i a1, a2, PT_AREG1 s32i a1, a2, PT_AREG1
s32i a3, a2, PT_AREG3
/* We need to map the page of PTEs for the user task. Find /* We need to map the page of PTEs for the user task. Find
* the pointer to that page. Also, it's possible for tsk->mm * the pointer to that page. Also, it's possible for tsk->mm
...@@ -1602,9 +1472,6 @@ ENTRY(fast_second_level_miss) ...@@ -1602,9 +1472,6 @@ ENTRY(fast_second_level_miss)
l32i a0, a1, TASK_MM # tsk->mm l32i a0, a1, TASK_MM # tsk->mm
beqz a0, 9f beqz a0, 9f
/* We deliberately destroy a3 that holds the exception table. */
8: rsr a3, excvaddr # fault address 8: rsr a3, excvaddr # fault address
_PGD_OFFSET(a0, a3, a1) _PGD_OFFSET(a0, a3, a1)
l32i a0, a0, 0 # read pmdval l32i a0, a0, 0 # read pmdval
...@@ -1655,7 +1522,7 @@ ENTRY(fast_second_level_miss) ...@@ -1655,7 +1522,7 @@ ENTRY(fast_second_level_miss)
/* Exit critical section. */ /* Exit critical section. */
4: movi a3, exc_table # restore a3 4: rsr a3, excsave1
movi a0, 0 movi a0, 0
s32i a0, a3, EXC_TABLE_FIXUP s32i a0, a3, EXC_TABLE_FIXUP
...@@ -1663,8 +1530,8 @@ ENTRY(fast_second_level_miss) ...@@ -1663,8 +1530,8 @@ ENTRY(fast_second_level_miss)
l32i a0, a2, PT_AREG0 l32i a0, a2, PT_AREG0
l32i a1, a2, PT_AREG1 l32i a1, a2, PT_AREG1
l32i a3, a2, PT_AREG3
l32i a2, a2, PT_DEPC l32i a2, a2, PT_DEPC
xsr a3, excsave1
bgeui a2, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f bgeui a2, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
...@@ -1751,11 +1618,8 @@ ENTRY(fast_second_level_miss) ...@@ -1751,11 +1618,8 @@ ENTRY(fast_second_level_miss)
2: /* Invalid PGD, default exception handling */ 2: /* Invalid PGD, default exception handling */
movi a3, exc_table
rsr a1, depc rsr a1, depc
xsr a3, excsave1
s32i a1, a2, PT_AREG2 s32i a1, a2, PT_AREG2
s32i a3, a2, PT_AREG3
mov a1, a2 mov a1, a2
rsr a2, ps rsr a2, ps
...@@ -1775,9 +1639,9 @@ ENDPROC(fast_second_level_miss) ...@@ -1775,9 +1639,9 @@ ENDPROC(fast_second_level_miss)
* a0: trashed, original value saved on stack (PT_AREG0) * a0: trashed, original value saved on stack (PT_AREG0)
* a1: a1 * a1: a1
* a2: new stack pointer, original in DEPC * a2: new stack pointer, original in DEPC
* a3: dispatch table * a3: a3
* depc: a2, original value saved on stack (PT_DEPC) * depc: a2, original value saved on stack (PT_DEPC)
* excsave_1: a3 * excsave_1: dispatch table
* *
* PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
* < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
...@@ -1785,17 +1649,17 @@ ENDPROC(fast_second_level_miss) ...@@ -1785,17 +1649,17 @@ ENDPROC(fast_second_level_miss)
ENTRY(fast_store_prohibited) ENTRY(fast_store_prohibited)
/* Save a1 and a4. */ /* Save a1 and a3. */
s32i a1, a2, PT_AREG1 s32i a1, a2, PT_AREG1
s32i a4, a2, PT_AREG4 s32i a3, a2, PT_AREG3
GET_CURRENT(a1,a2) GET_CURRENT(a1,a2)
l32i a0, a1, TASK_MM # tsk->mm l32i a0, a1, TASK_MM # tsk->mm
beqz a0, 9f beqz a0, 9f
8: rsr a1, excvaddr # fault address 8: rsr a1, excvaddr # fault address
_PGD_OFFSET(a0, a1, a4) _PGD_OFFSET(a0, a1, a3)
l32i a0, a0, 0 l32i a0, a0, 0
beqz a0, 2f beqz a0, 2f
...@@ -1804,39 +1668,37 @@ ENTRY(fast_store_prohibited) ...@@ -1804,39 +1668,37 @@ ENTRY(fast_store_prohibited)
* and is not PAGE_NONE. See pgtable.h for possible PTE layouts. * and is not PAGE_NONE. See pgtable.h for possible PTE layouts.
*/ */
_PTE_OFFSET(a0, a1, a4) _PTE_OFFSET(a0, a1, a3)
l32i a4, a0, 0 # read pteval l32i a3, a0, 0 # read pteval
movi a1, _PAGE_CA_INVALID movi a1, _PAGE_CA_INVALID
ball a4, a1, 2f ball a3, a1, 2f
bbci.l a4, _PAGE_WRITABLE_BIT, 2f bbci.l a3, _PAGE_WRITABLE_BIT, 2f
movi a1, _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_HW_WRITE movi a1, _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_HW_WRITE
or a4, a4, a1 or a3, a3, a1
rsr a1, excvaddr rsr a1, excvaddr
s32i a4, a0, 0 s32i a3, a0, 0
/* We need to flush the cache if we have page coloring. */ /* We need to flush the cache if we have page coloring. */
#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK #if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
dhwb a0, 0 dhwb a0, 0
#endif #endif
pdtlb a0, a1 pdtlb a0, a1
wdtlb a4, a0 wdtlb a3, a0
/* Exit critical section. */ /* Exit critical section. */
movi a0, 0 movi a0, 0
rsr a3, excsave1
s32i a0, a3, EXC_TABLE_FIXUP s32i a0, a3, EXC_TABLE_FIXUP
/* Restore the working registers, and return. */ /* Restore the working registers, and return. */
l32i a4, a2, PT_AREG4 l32i a3, a2, PT_AREG3
l32i a1, a2, PT_AREG1 l32i a1, a2, PT_AREG1
l32i a0, a2, PT_AREG0 l32i a0, a2, PT_AREG0
l32i a2, a2, PT_DEPC l32i a2, a2, PT_DEPC
/* Restore excsave1 and a3. */
xsr a3, excsave1
bgeui a2, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f bgeui a2, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
rsr a2, depc rsr a2, depc
...@@ -1853,11 +1715,8 @@ ENTRY(fast_store_prohibited) ...@@ -1853,11 +1715,8 @@ ENTRY(fast_store_prohibited)
2: /* If there was a problem, handle fault in C */ 2: /* If there was a problem, handle fault in C */
rsr a4, depc # still holds a2 rsr a3, depc # still holds a2
xsr a3, excsave1 s32i a3, a2, PT_AREG2
s32i a4, a2, PT_AREG2
s32i a3, a2, PT_AREG3
l32i a4, a2, PT_AREG4
mov a1, a2 mov a1, a2
rsr a2, ps rsr a2, ps
......
...@@ -584,8 +584,8 @@ c_show(struct seq_file *f, void *slot) ...@@ -584,8 +584,8 @@ c_show(struct seq_file *f, void *slot)
"bogomips\t: %lu.%02lu\n", "bogomips\t: %lu.%02lu\n",
XCHAL_BUILD_UNIQUE_ID, XCHAL_BUILD_UNIQUE_ID,
XCHAL_HAVE_BE ? "big" : "little", XCHAL_HAVE_BE ? "big" : "little",
CCOUNT_PER_JIFFY/(1000000/HZ), ccount_freq/1000000,
(CCOUNT_PER_JIFFY/(10000/HZ)) % 100, (ccount_freq/10000) % 100,
loops_per_jiffy/(500000/HZ), loops_per_jiffy/(500000/HZ),
(loops_per_jiffy/(5000/HZ)) % 100); (loops_per_jiffy/(5000/HZ)) % 100);
......
...@@ -29,9 +29,7 @@ ...@@ -29,9 +29,7 @@
#include <asm/timex.h> #include <asm/timex.h>
#include <asm/platform.h> #include <asm/platform.h>
#ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT
unsigned long ccount_freq; /* ccount Hz */ unsigned long ccount_freq; /* ccount Hz */
#endif
static cycle_t ccount_read(struct clocksource *cs) static cycle_t ccount_read(struct clocksource *cs)
{ {
...@@ -129,8 +127,10 @@ void __init time_init(void) ...@@ -129,8 +127,10 @@ void __init time_init(void)
platform_calibrate_ccount(); platform_calibrate_ccount();
printk("%d.%02d MHz\n", (int)ccount_freq/1000000, printk("%d.%02d MHz\n", (int)ccount_freq/1000000,
(int)(ccount_freq/10000)%100); (int)(ccount_freq/10000)%100);
#else
ccount_freq = CONFIG_XTENSA_CPU_CLOCK*1000000UL;
#endif #endif
clocksource_register_hz(&ccount_clocksource, CCOUNT_PER_JIFFY * HZ); clocksource_register_hz(&ccount_clocksource, ccount_freq);
ccount_timer.evt.cpumask = cpumask_of(0); ccount_timer.evt.cpumask = cpumask_of(0);
ccount_timer.evt.irq = irq_create_mapping(NULL, LINUX_TIMER_INT); 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,7 +164,7 @@ irqreturn_t timer_interrupt (int irq, void *dev_id)
#ifndef CONFIG_GENERIC_CALIBRATE_DELAY #ifndef CONFIG_GENERIC_CALIBRATE_DELAY
void calibrate_delay(void) void calibrate_delay(void)
{ {
loops_per_jiffy = CCOUNT_PER_JIFFY; loops_per_jiffy = ccount_freq / HZ;
printk("Calibrating delay loop (skipped)... " printk("Calibrating delay loop (skipped)... "
"%lu.%02lu BogoMIPS preset\n", "%lu.%02lu BogoMIPS preset\n",
loops_per_jiffy/(1000000/HZ), loops_per_jiffy/(1000000/HZ),
......
...@@ -78,6 +78,7 @@ ENTRY(_UserExceptionVector) ...@@ -78,6 +78,7 @@ ENTRY(_UserExceptionVector)
s32i a0, a2, PT_DEPC # mark it as a regular exception s32i a0, a2, PT_DEPC # mark it as a regular exception
addx4 a0, a0, a3 # find entry in table addx4 a0, a0, a3 # find entry in table
l32i a0, a0, EXC_TABLE_FAST_USER # load handler l32i a0, a0, EXC_TABLE_FAST_USER # load handler
xsr a3, excsave1 # restore a3 and dispatch table
jx a0 jx a0
ENDPROC(_UserExceptionVector) ENDPROC(_UserExceptionVector)
...@@ -104,6 +105,7 @@ ENTRY(_KernelExceptionVector) ...@@ -104,6 +105,7 @@ ENTRY(_KernelExceptionVector)
s32i a0, a2, PT_DEPC # mark it as a regular exception s32i a0, a2, PT_DEPC # mark it as a regular exception
addx4 a0, a0, a3 # find entry in table addx4 a0, a0, a3 # find entry in table
l32i a0, a0, EXC_TABLE_FAST_KERNEL # load handler address l32i a0, a0, EXC_TABLE_FAST_KERNEL # load handler address
xsr a3, excsave1 # restore a3 and dispatch table
jx a0 jx a0
ENDPROC(_KernelExceptionVector) ENDPROC(_KernelExceptionVector)
...@@ -168,7 +170,7 @@ ENDPROC(_KernelExceptionVector) ...@@ -168,7 +170,7 @@ ENDPROC(_KernelExceptionVector)
* *
* a0: DEPC * a0: DEPC
* a1: a1 * a1: a1
* a2: trashed, original value in EXC_TABLE_DOUBLE_A2 * a2: trashed, original value in EXC_TABLE_DOUBLE_SAVE
* a3: exctable * a3: exctable
* depc: a0 * depc: a0
* excsave_1: a3 * excsave_1: a3
...@@ -204,47 +206,46 @@ ENDPROC(_KernelExceptionVector) ...@@ -204,47 +206,46 @@ ENDPROC(_KernelExceptionVector)
.section .DoubleExceptionVector.text, "ax" .section .DoubleExceptionVector.text, "ax"
.begin literal_prefix .DoubleExceptionVector .begin literal_prefix .DoubleExceptionVector
.globl _DoubleExceptionVector_WindowUnderflow
.globl _DoubleExceptionVector_WindowOverflow
ENTRY(_DoubleExceptionVector) ENTRY(_DoubleExceptionVector)
/* Deliberately destroy excsave (don't assume it's value was valid). */ xsr a3, excsave1
s32i a2, a3, EXC_TABLE_DOUBLE_SAVE
wsr a3, excsave1 # save a3
/* Check for kernel double exception (usually fatal). */ /* Check for kernel double exception (usually fatal). */
rsr a3, ps rsr a2, ps
_bbci.l a3, PS_UM_BIT, .Lksp _bbci.l a2, PS_UM_BIT, .Lksp
/* Check if we are currently handling a window exception. */ /* Check if we are currently handling a window exception. */
/* Note: We don't need to indicate that we enter a critical section. */ /* Note: We don't need to indicate that we enter a critical section. */
xsr a0, depc # get DEPC, save a0 xsr a0, depc # get DEPC, save a0
movi a3, WINDOW_VECTORS_VADDR movi a2, WINDOW_VECTORS_VADDR
_bltu a0, a3, .Lfixup _bltu a0, a2, .Lfixup
addi a3, a3, WINDOW_VECTORS_SIZE addi a2, a2, WINDOW_VECTORS_SIZE
_bgeu a0, a3, .Lfixup _bgeu a0, a2, .Lfixup
/* Window overflow/underflow exception. Get stack pointer. */ /* Window overflow/underflow exception. Get stack pointer. */
mov a3, a2 l32i a2, a3, EXC_TABLE_KSTK
/* This explicit literal and the following references to it are made
* in order to fit DoubleExceptionVector.literals into the available
* 16-byte gap before DoubleExceptionVector.text in the absence of
* link time relaxation. See kernel/vmlinux.lds.S
*/
.literal .Lexc_table, exc_table
l32r a2, .Lexc_table
l32i a2, a2, EXC_TABLE_KSTK
/* Check for overflow/underflow exception, jump if overflow. */ /* Check for overflow/underflow exception, jump if overflow. */
_bbci.l a0, 6, .Lovfl _bbci.l a0, 6, _DoubleExceptionVector_WindowOverflow
/* a0: depc, a1: a1, a2: kstk, a3: a2, depc: a0, excsave: a3 */
/* Restart window underflow exception. /*
* Restart window underflow exception.
* Currently:
* depc = orig a0,
* a0 = orig DEPC,
* a2 = new sp based on KSTK from exc_table
* a3 = excsave_1
* excsave_1 = orig a3
*
* We return to the instruction in user space that caused the window * We return to the instruction in user space that caused the window
* underflow exception. Therefore, we change window base to the value * underflow exception. Therefore, we change window base to the value
* before we entered the window underflow exception and prepare the * before we entered the window underflow exception and prepare the
...@@ -252,10 +253,11 @@ ENTRY(_DoubleExceptionVector) ...@@ -252,10 +253,11 @@ ENTRY(_DoubleExceptionVector)
* by changing depc (in a0). * by changing depc (in a0).
* Note: We can trash the current window frame (a0...a3) and depc! * Note: We can trash the current window frame (a0...a3) and depc!
*/ */
_DoubleExceptionVector_WindowUnderflow:
xsr a3, excsave1
wsr a2, depc # save stack pointer temporarily wsr a2, depc # save stack pointer temporarily
rsr a0, ps rsr a0, ps
extui a0, a0, PS_OWB_SHIFT, 4 extui a0, a0, PS_OWB_SHIFT, PS_OWB_WIDTH
wsr a0, windowbase wsr a0, windowbase
rsync rsync
...@@ -263,28 +265,57 @@ ENTRY(_DoubleExceptionVector) ...@@ -263,28 +265,57 @@ ENTRY(_DoubleExceptionVector)
xsr a2, depc # save a2 and get stack pointer xsr a2, depc # save a2 and get stack pointer
s32i a0, a2, PT_AREG0 s32i a0, a2, PT_AREG0
xsr a3, excsave1
wsr a3, excsave1 # save a3
l32r a3, .Lexc_table
rsr a0, exccause rsr a0, exccause
s32i a0, a2, PT_DEPC # mark it as a regular exception s32i a0, a2, PT_DEPC # mark it as a regular exception
addx4 a0, a0, a3 addx4 a0, a0, a3
xsr a3, excsave1
l32i a0, a0, EXC_TABLE_FAST_USER l32i a0, a0, EXC_TABLE_FAST_USER
jx a0 jx a0
.Lfixup:/* Check for a fixup handler or if we were in a critical section. */ /*
* We only allow the ITLB miss exception if we are in kernel space.
* All other exceptions are unexpected and thus unrecoverable!
*/
#ifdef CONFIG_MMU
.extern fast_second_level_miss_double_kernel
.Lksp: /* a0: a0, a1: a1, a2: a2, a3: trashed, depc: depc, excsave: a3 */
rsr a3, exccause
beqi a3, EXCCAUSE_ITLB_MISS, 1f
addi a3, a3, -EXCCAUSE_DTLB_MISS
bnez a3, .Lunrecoverable
1: movi a3, fast_second_level_miss_double_kernel
jx a3
#else
.equ .Lksp, .Lunrecoverable
#endif
/* Critical! We can't handle this situation. PANIC! */
/* a0: depc, a1: a1, a2: a2, a3: trashed, depc: a0, excsave1: a3 */ .extern unrecoverable_exception
l32r a3, .Lexc_table .Lunrecoverable_fixup:
s32i a2, a3, EXC_TABLE_DOUBLE_SAVE # temporary variable l32i a2, a3, EXC_TABLE_DOUBLE_SAVE
xsr a0, depc
.Lunrecoverable:
rsr a3, excsave1
wsr a0, excsave1
movi a0, unrecoverable_exception
callx0 a0
.Lfixup:/* Check for a fixup handler or if we were in a critical section. */
/* a0: depc, a1: a1, a2: trash, a3: exctable, depc: a0, excsave1: a3 */
/* Enter critical section. */ /* Enter critical section. */
l32i a2, a3, EXC_TABLE_FIXUP l32i a2, a3, EXC_TABLE_FIXUP
s32i a3, a3, EXC_TABLE_FIXUP s32i a3, a3, EXC_TABLE_FIXUP
beq a2, a3, .Lunrecoverable_fixup # critical! beq a2, a3, .Lunrecoverable_fixup # critical section
beqz a2, .Ldflt # no handler was registered beqz a2, .Ldflt # no handler was registered
/* a0: depc, a1: a1, a2: trash, a3: exctable, depc: a0, excsave: a3 */ /* a0: depc, a1: a1, a2: trash, a3: exctable, depc: a0, excsave: a3 */
...@@ -293,58 +324,145 @@ ENTRY(_DoubleExceptionVector) ...@@ -293,58 +324,145 @@ ENTRY(_DoubleExceptionVector)
.Ldflt: /* Get stack pointer. */ .Ldflt: /* Get stack pointer. */
l32i a3, a3, EXC_TABLE_DOUBLE_SAVE l32i a2, a3, EXC_TABLE_DOUBLE_SAVE
addi a2, a3, -PT_USER_SIZE addi a2, a2, -PT_USER_SIZE
.Lovfl: /* Jump to default handlers. */
/* a0: depc, a1: a1, a2: kstk, a3: a2, depc: a0, excsave: a3 */ /* a0: depc, a1: a1, a2: kstk, a3: exctable, depc: a0, excsave: a3 */
xsr a3, depc
s32i a0, a2, PT_DEPC s32i a0, a2, PT_DEPC
s32i a3, a2, PT_AREG0 l32i a0, a3, EXC_TABLE_DOUBLE_SAVE
xsr a0, depc
s32i a0, a2, PT_AREG0
/* a0: avail, a1: a1, a2: kstk, a3: avail, depc: a2, excsave: a3 */ /* a0: avail, a1: a1, a2: kstk, a3: exctable, depc: a2, excsave: a3 */
l32r a3, .Lexc_table
rsr a0, exccause rsr a0, exccause
addx4 a0, a0, a3 addx4 a0, a0, a3
xsr a3, excsave1
l32i a0, a0, EXC_TABLE_FAST_USER l32i a0, a0, EXC_TABLE_FAST_USER
jx a0 jx a0
/* /*
* We only allow the ITLB miss exception if we are in kernel space. * Restart window OVERFLOW exception.
* All other exceptions are unexpected and thus unrecoverable! * Currently:
* depc = orig a0,
* a0 = orig DEPC,
* a2 = new sp based on KSTK from exc_table
* a3 = EXCSAVE_1
* excsave_1 = orig a3
*
* We return to the instruction in user space that caused the window
* overflow exception. Therefore, we change window base to the value
* before we entered the window overflow exception and prepare the
* registers to return as if we were coming from a regular exception
* by changing DEPC (in a0).
*
* NOTE: We CANNOT trash the current window frame (a0...a3), but we
* can clobber depc.
*
* The tricky part here is that overflow8 and overflow12 handlers
* save a0, then clobber a0. To restart the handler, we have to restore
* a0 if the double exception was past the point where a0 was clobbered.
*
* To keep things simple, we take advantage of the fact all overflow
* handlers save a0 in their very first instruction. If DEPC was past
* that instruction, we can safely restore a0 from where it was saved
* on the stack.
*
* a0: depc, a1: a1, a2: kstk, a3: exc_table, depc: a0, excsave1: a3
*/ */
_DoubleExceptionVector_WindowOverflow:
extui a2, a0, 0, 6 # get offset into 64-byte vector handler
beqz a2, 1f # if at start of vector, don't restore
#ifdef CONFIG_MMU addi a0, a0, -128
.extern fast_second_level_miss_double_kernel bbsi a0, 8, 1f # don't restore except for overflow 8 and 12
bbsi a0, 7, 2f
.Lksp: /* a0: a0, a1: a1, a2: a2, a3: trashed, depc: depc, excsave: a3 */ /*
* Restore a0 as saved by _WindowOverflow8().
*
* FIXME: we really need a fixup handler for this L32E,
* for the extremely unlikely case where the overflow handler's
* reference thru a0 gets a hardware TLB refill that bumps out
* the (distinct, aliasing) TLB entry that mapped its prior
* references thru a9, and where our reference now thru a9
* gets a 2nd-level miss exception (not hardware TLB refill).
*/
rsr a3, exccause l32e a2, a9, -16
beqi a3, EXCCAUSE_ITLB_MISS, 1f wsr a2, depc # replace the saved a0
addi a3, a3, -EXCCAUSE_DTLB_MISS j 1f
bnez a3, .Lunrecoverable
1: movi a3, fast_second_level_miss_double_kernel
jx a3
#else
.equ .Lksp, .Lunrecoverable
#endif
/* Critical! We can't handle this situation. PANIC! */ 2:
/*
* Restore a0 as saved by _WindowOverflow12().
*
* FIXME: we really need a fixup handler for this L32E,
* for the extremely unlikely case where the overflow handler's
* reference thru a0 gets a hardware TLB refill that bumps out
* the (distinct, aliasing) TLB entry that mapped its prior
* references thru a13, and where our reference now thru a13
* gets a 2nd-level miss exception (not hardware TLB refill).
*/
.extern unrecoverable_exception l32e a2, a13, -16
wsr a2, depc # replace the saved a0
1:
/*
* Restore WindowBase while leaving all address registers restored.
* We have to use ROTW for this, because WSR.WINDOWBASE requires
* an address register (which would prevent restore).
*
* Window Base goes from 0 ... 7 (Module 8)
* Window Start is 8 bits; Ex: (0b1010 1010):0x55 from series of call4s
*/
rsr a0, ps
extui a0, a0, PS_OWB_SHIFT, PS_OWB_WIDTH
rsr a2, windowbase
sub a0, a2, a0
extui a0, a0, 0, 3
.Lunrecoverable_fixup:
l32i a2, a3, EXC_TABLE_DOUBLE_SAVE l32i a2, a3, EXC_TABLE_DOUBLE_SAVE
xsr a0, depc xsr a3, excsave1
beqi a0, 1, .L1pane
beqi a0, 3, .L3pane
.Lunrecoverable: rsr a0, depc
rsr a3, excsave1 rotw -2
wsr a0, excsave1
movi a0, unrecoverable_exception /*
callx0 a0 * We are now in the user code's original window frame.
* Process the exception as a user exception as if it was
* taken by the user code.
*
* This is similar to the user exception vector,
* except that PT_DEPC isn't set to EXCCAUSE.
*/
1:
xsr a3, excsave1
wsr a2, depc
l32i a2, a3, EXC_TABLE_KSTK
s32i a0, a2, PT_AREG0
rsr a0, exccause
s32i a0, a2, PT_DEPC
addx4 a0, a0, a3
l32i a0, a0, EXC_TABLE_FAST_USER
xsr a3, excsave1
jx a0
.L1pane:
rsr a0, depc
rotw -1
j 1b
.L3pane:
rsr a0, depc
rotw -3
j 1b
.end literal_prefix .end literal_prefix
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
#include <asm/ftrace.h>
#ifdef CONFIG_BLK_DEV_FD #ifdef CONFIG_BLK_DEV_FD
#include <asm/floppy.h> #include <asm/floppy.h>
#endif #endif
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册