Skip to content

Commit

Permalink
Merge tag 'xtensa-for-next-20140715' of git://github.com/jcmvbkbc/lin…
Browse files Browse the repository at this point in the history
…ux-xtensa into for_next

Xtensa fixes for 3.16:
- resolve FIXMEs in double exception handler for window overflow. This
  fix makes native building of linux on xtensa host possible;
- fix sysmem region removal issue introduced in 3.15.
  • Loading branch information
czankel committed Jul 16, 2014
2 parents 7171511 + be6ae38 commit 4ed2ad3
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 25 deletions.
158 changes: 136 additions & 22 deletions arch/xtensa/kernel/vectors.S
Original file line number Diff line number Diff line change
Expand Up @@ -376,38 +376,42 @@ _DoubleExceptionVector_WindowOverflow:
beqz a2, 1f # if at start of vector, don't restore

addi a0, a0, -128
bbsi a0, 8, 1f # don't restore except for overflow 8 and 12
bbsi a0, 7, 2f
bbsi.l a0, 8, 1f # don't restore except for overflow 8 and 12

/*
* This fixup handler is 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/a13, and where our reference now thru
* a9/a13 gets a 2nd-level miss exception (not hardware TLB refill).
*/
movi a2, window_overflow_restore_a0_fixup
s32i a2, a3, EXC_TABLE_FIXUP
l32i a2, a3, EXC_TABLE_DOUBLE_SAVE
xsr a3, excsave1

bbsi.l a0, 7, 2f

/*
* 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).
*/

l32e a2, a9, -16
wsr a2, depc # replace the saved a0
j 1f
l32e a0, a9, -16
wsr a0, depc # replace the saved a0
j 3f

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).
*/

l32e a2, a13, -16
wsr a2, depc # replace the saved a0
l32e a0, a13, -16
wsr a0, depc # replace the saved a0
3:
xsr a3, excsave1
movi a0, 0
s32i a0, a3, EXC_TABLE_FIXUP
s32i a2, a3, EXC_TABLE_DOUBLE_SAVE
1:
/*
* Restore WindowBase while leaving all address registers restored.
Expand Down Expand Up @@ -449,6 +453,7 @@ _DoubleExceptionVector_WindowOverflow:

s32i a0, a2, PT_DEPC

_DoubleExceptionVector_handle_exception:
addx4 a0, a0, a3
l32i a0, a0, EXC_TABLE_FAST_USER
xsr a3, excsave1
Expand All @@ -464,10 +469,119 @@ _DoubleExceptionVector_WindowOverflow:
rotw -3
j 1b

.end literal_prefix

ENDPROC(_DoubleExceptionVector)

/*
* Fixup handler for TLB miss in double exception handler for window owerflow.
* We get here with windowbase set to the window that was being spilled and
* a0 trashed. a0 bit 7 determines if this is a call8 (bit clear) or call12
* (bit set) window.
*
* We do the following here:
* - go to the original window retaining a0 value;
* - set up exception stack to return back to appropriate a0 restore code
* (we'll need to rotate window back and there's no place to save this
* information, use different return address for that);
* - handle the exception;
* - go to the window that was being spilled;
* - set up window_overflow_restore_a0_fixup as a fixup routine;
* - reload a0;
* - restore the original window;
* - reset the default fixup routine;
* - return to user. By the time we get to this fixup handler all information
* about the conditions of the original double exception that happened in
* the window overflow handler is lost, so we just return to userspace to
* retry overflow from start.
*
* a0: value of depc, original value in depc
* a2: trashed, original value in EXC_TABLE_DOUBLE_SAVE
* a3: exctable, original value in excsave1
*/

ENTRY(window_overflow_restore_a0_fixup)

rsr a0, ps
extui a0, a0, PS_OWB_SHIFT, PS_OWB_WIDTH
rsr a2, windowbase
sub a0, a2, a0
extui a0, a0, 0, 3
l32i a2, a3, EXC_TABLE_DOUBLE_SAVE
xsr a3, excsave1

_beqi a0, 1, .Lhandle_1
_beqi a0, 3, .Lhandle_3

.macro overflow_fixup_handle_exception_pane n

rsr a0, depc
rotw -\n

xsr a3, excsave1
wsr a2, depc
l32i a2, a3, EXC_TABLE_KSTK
s32i a0, a2, PT_AREG0

movi a0, .Lrestore_\n
s32i a0, a2, PT_DEPC
rsr a0, exccause
j _DoubleExceptionVector_handle_exception

.endm

overflow_fixup_handle_exception_pane 2
.Lhandle_1:
overflow_fixup_handle_exception_pane 1
.Lhandle_3:
overflow_fixup_handle_exception_pane 3

.macro overflow_fixup_restore_a0_pane n

rotw \n
/* Need to preserve a0 value here to be able to handle exception
* that may occur on a0 reload from stack. It may occur because
* TLB miss handler may not be atomic and pointer to page table
* may be lost before we get here. There are no free registers,
* so we need to use EXC_TABLE_DOUBLE_SAVE area.
*/
xsr a3, excsave1
s32i a2, a3, EXC_TABLE_DOUBLE_SAVE
movi a2, window_overflow_restore_a0_fixup
s32i a2, a3, EXC_TABLE_FIXUP
l32i a2, a3, EXC_TABLE_DOUBLE_SAVE
xsr a3, excsave1
bbsi.l a0, 7, 1f
l32e a0, a9, -16
j 2f
1:
l32e a0, a13, -16
2:
rotw -\n

.endm

.Lrestore_2:
overflow_fixup_restore_a0_pane 2

.Lset_default_fixup:
xsr a3, excsave1
s32i a2, a3, EXC_TABLE_DOUBLE_SAVE
movi a2, 0
s32i a2, a3, EXC_TABLE_FIXUP
l32i a2, a3, EXC_TABLE_DOUBLE_SAVE
xsr a3, excsave1
rfe

.Lrestore_1:
overflow_fixup_restore_a0_pane 1
j .Lset_default_fixup
.Lrestore_3:
overflow_fixup_restore_a0_pane 3
j .Lset_default_fixup

ENDPROC(window_overflow_restore_a0_fixup)

.end literal_prefix
/*
* Debug interrupt vector
*
Expand Down
4 changes: 2 additions & 2 deletions arch/xtensa/kernel/vmlinux.lds.S
Original file line number Diff line number Diff line change
Expand Up @@ -269,13 +269,13 @@ SECTIONS
.UserExceptionVector.literal)
SECTION_VECTOR (_DoubleExceptionVector_literal,
.DoubleExceptionVector.literal,
DOUBLEEXC_VECTOR_VADDR - 16,
DOUBLEEXC_VECTOR_VADDR - 40,
SIZEOF(.UserExceptionVector.text),
.UserExceptionVector.text)
SECTION_VECTOR (_DoubleExceptionVector_text,
.DoubleExceptionVector.text,
DOUBLEEXC_VECTOR_VADDR,
32,
40,
.DoubleExceptionVector.literal)

. = (LOADADDR( .DoubleExceptionVector.text ) + SIZEOF( .DoubleExceptionVector.text ) + 3) & ~ 3;
Expand Down
2 changes: 1 addition & 1 deletion arch/xtensa/mm/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ int __init mem_reserve(unsigned long start, unsigned long end, int must_exist)
return -EINVAL;
}

if (it && start - it->start < bank_sz) {
if (it && start - it->start <= bank_sz) {
if (start == it->start) {
if (end - it->start < bank_sz) {
it->start = end;
Expand Down

0 comments on commit 4ed2ad3

Please sign in to comment.