Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 29ae8a6a authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

Pull Xtensa fixes from Chris Zankel:
 - 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.

* tag 'xtensa-next-20140721' of git://github.com/czankel/xtensa-linux:
  xtensa: fix sysmem reservation at the end of existing block
  xtensa: add fixup for double exception raised in window overflow
parents 02ec4747 4ed2ad38
Loading
Loading
Loading
Loading
+136 −22
Original line number Diff line number Diff line
@@ -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.
@@ -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
@@ -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
 *
+2 −2
Original line number Diff line number Diff line
@@ -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;
+1 −1
Original line number Diff line number Diff line
@@ -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;