diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-07-23 20:46:46 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-07-23 20:46:46 -0400 |
commit | 29ae8a6a281445ae5fe69287cf1165326978b1c7 (patch) | |
tree | 87e660a367dbc2186e53006a2c78de71985c1c07 /arch | |
parent | 02ec47474604beb7191f6e4c1aef73561cf66d25 (diff) | |
parent | 4ed2ad38b3b4c45a5a5999454b02d3c21e75af5a (diff) |
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
Diffstat (limited to 'arch')
-rw-r--r-- | arch/xtensa/kernel/vectors.S | 158 | ||||
-rw-r--r-- | arch/xtensa/kernel/vmlinux.lds.S | 4 | ||||
-rw-r--r-- | arch/xtensa/mm/init.c | 2 |
3 files changed, 139 insertions, 25 deletions
diff --git a/arch/xtensa/kernel/vectors.S b/arch/xtensa/kernel/vectors.S index f9e1ec346e35..8453e6e39895 100644 --- a/arch/xtensa/kernel/vectors.S +++ b/arch/xtensa/kernel/vectors.S | |||
@@ -376,38 +376,42 @@ _DoubleExceptionVector_WindowOverflow: | |||
376 | beqz a2, 1f # if at start of vector, don't restore | 376 | beqz a2, 1f # if at start of vector, don't restore |
377 | 377 | ||
378 | addi a0, a0, -128 | 378 | addi a0, a0, -128 |
379 | bbsi a0, 8, 1f # don't restore except for overflow 8 and 12 | 379 | bbsi.l a0, 8, 1f # don't restore except for overflow 8 and 12 |
380 | bbsi a0, 7, 2f | 380 | |
381 | /* | ||
382 | * This fixup handler is for the extremely unlikely case where the | ||
383 | * overflow handler's reference thru a0 gets a hardware TLB refill | ||
384 | * that bumps out the (distinct, aliasing) TLB entry that mapped its | ||
385 | * prior references thru a9/a13, and where our reference now thru | ||
386 | * a9/a13 gets a 2nd-level miss exception (not hardware TLB refill). | ||
387 | */ | ||
388 | movi a2, window_overflow_restore_a0_fixup | ||
389 | s32i a2, a3, EXC_TABLE_FIXUP | ||
390 | l32i a2, a3, EXC_TABLE_DOUBLE_SAVE | ||
391 | xsr a3, excsave1 | ||
392 | |||
393 | bbsi.l a0, 7, 2f | ||
381 | 394 | ||
382 | /* | 395 | /* |
383 | * Restore a0 as saved by _WindowOverflow8(). | 396 | * 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 | */ | 397 | */ |
392 | 398 | ||
393 | l32e a2, a9, -16 | 399 | l32e a0, a9, -16 |
394 | wsr a2, depc # replace the saved a0 | 400 | wsr a0, depc # replace the saved a0 |
395 | j 1f | 401 | j 3f |
396 | 402 | ||
397 | 2: | 403 | 2: |
398 | /* | 404 | /* |
399 | * Restore a0 as saved by _WindowOverflow12(). | 405 | * 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 | */ | 406 | */ |
408 | 407 | ||
409 | l32e a2, a13, -16 | 408 | l32e a0, a13, -16 |
410 | wsr a2, depc # replace the saved a0 | 409 | wsr a0, depc # replace the saved a0 |
410 | 3: | ||
411 | xsr a3, excsave1 | ||
412 | movi a0, 0 | ||
413 | s32i a0, a3, EXC_TABLE_FIXUP | ||
414 | s32i a2, a3, EXC_TABLE_DOUBLE_SAVE | ||
411 | 1: | 415 | 1: |
412 | /* | 416 | /* |
413 | * Restore WindowBase while leaving all address registers restored. | 417 | * Restore WindowBase while leaving all address registers restored. |
@@ -449,6 +453,7 @@ _DoubleExceptionVector_WindowOverflow: | |||
449 | 453 | ||
450 | s32i a0, a2, PT_DEPC | 454 | s32i a0, a2, PT_DEPC |
451 | 455 | ||
456 | _DoubleExceptionVector_handle_exception: | ||
452 | addx4 a0, a0, a3 | 457 | addx4 a0, a0, a3 |
453 | l32i a0, a0, EXC_TABLE_FAST_USER | 458 | l32i a0, a0, EXC_TABLE_FAST_USER |
454 | xsr a3, excsave1 | 459 | xsr a3, excsave1 |
@@ -464,11 +469,120 @@ _DoubleExceptionVector_WindowOverflow: | |||
464 | rotw -3 | 469 | rotw -3 |
465 | j 1b | 470 | j 1b |
466 | 471 | ||
467 | .end literal_prefix | ||
468 | 472 | ||
469 | ENDPROC(_DoubleExceptionVector) | 473 | ENDPROC(_DoubleExceptionVector) |
470 | 474 | ||
471 | /* | 475 | /* |
476 | * Fixup handler for TLB miss in double exception handler for window owerflow. | ||
477 | * We get here with windowbase set to the window that was being spilled and | ||
478 | * a0 trashed. a0 bit 7 determines if this is a call8 (bit clear) or call12 | ||
479 | * (bit set) window. | ||
480 | * | ||
481 | * We do the following here: | ||
482 | * - go to the original window retaining a0 value; | ||
483 | * - set up exception stack to return back to appropriate a0 restore code | ||
484 | * (we'll need to rotate window back and there's no place to save this | ||
485 | * information, use different return address for that); | ||
486 | * - handle the exception; | ||
487 | * - go to the window that was being spilled; | ||
488 | * - set up window_overflow_restore_a0_fixup as a fixup routine; | ||
489 | * - reload a0; | ||
490 | * - restore the original window; | ||
491 | * - reset the default fixup routine; | ||
492 | * - return to user. By the time we get to this fixup handler all information | ||
493 | * about the conditions of the original double exception that happened in | ||
494 | * the window overflow handler is lost, so we just return to userspace to | ||
495 | * retry overflow from start. | ||
496 | * | ||
497 | * a0: value of depc, original value in depc | ||
498 | * a2: trashed, original value in EXC_TABLE_DOUBLE_SAVE | ||
499 | * a3: exctable, original value in excsave1 | ||
500 | */ | ||
501 | |||
502 | ENTRY(window_overflow_restore_a0_fixup) | ||
503 | |||
504 | rsr a0, ps | ||
505 | extui a0, a0, PS_OWB_SHIFT, PS_OWB_WIDTH | ||
506 | rsr a2, windowbase | ||
507 | sub a0, a2, a0 | ||
508 | extui a0, a0, 0, 3 | ||
509 | l32i a2, a3, EXC_TABLE_DOUBLE_SAVE | ||
510 | xsr a3, excsave1 | ||
511 | |||
512 | _beqi a0, 1, .Lhandle_1 | ||
513 | _beqi a0, 3, .Lhandle_3 | ||
514 | |||
515 | .macro overflow_fixup_handle_exception_pane n | ||
516 | |||
517 | rsr a0, depc | ||
518 | rotw -\n | ||
519 | |||
520 | xsr a3, excsave1 | ||
521 | wsr a2, depc | ||
522 | l32i a2, a3, EXC_TABLE_KSTK | ||
523 | s32i a0, a2, PT_AREG0 | ||
524 | |||
525 | movi a0, .Lrestore_\n | ||
526 | s32i a0, a2, PT_DEPC | ||
527 | rsr a0, exccause | ||
528 | j _DoubleExceptionVector_handle_exception | ||
529 | |||
530 | .endm | ||
531 | |||
532 | overflow_fixup_handle_exception_pane 2 | ||
533 | .Lhandle_1: | ||
534 | overflow_fixup_handle_exception_pane 1 | ||
535 | .Lhandle_3: | ||
536 | overflow_fixup_handle_exception_pane 3 | ||
537 | |||
538 | .macro overflow_fixup_restore_a0_pane n | ||
539 | |||
540 | rotw \n | ||
541 | /* Need to preserve a0 value here to be able to handle exception | ||
542 | * that may occur on a0 reload from stack. It may occur because | ||
543 | * TLB miss handler may not be atomic and pointer to page table | ||
544 | * may be lost before we get here. There are no free registers, | ||
545 | * so we need to use EXC_TABLE_DOUBLE_SAVE area. | ||
546 | */ | ||
547 | xsr a3, excsave1 | ||
548 | s32i a2, a3, EXC_TABLE_DOUBLE_SAVE | ||
549 | movi a2, window_overflow_restore_a0_fixup | ||
550 | s32i a2, a3, EXC_TABLE_FIXUP | ||
551 | l32i a2, a3, EXC_TABLE_DOUBLE_SAVE | ||
552 | xsr a3, excsave1 | ||
553 | bbsi.l a0, 7, 1f | ||
554 | l32e a0, a9, -16 | ||
555 | j 2f | ||
556 | 1: | ||
557 | l32e a0, a13, -16 | ||
558 | 2: | ||
559 | rotw -\n | ||
560 | |||
561 | .endm | ||
562 | |||
563 | .Lrestore_2: | ||
564 | overflow_fixup_restore_a0_pane 2 | ||
565 | |||
566 | .Lset_default_fixup: | ||
567 | xsr a3, excsave1 | ||
568 | s32i a2, a3, EXC_TABLE_DOUBLE_SAVE | ||
569 | movi a2, 0 | ||
570 | s32i a2, a3, EXC_TABLE_FIXUP | ||
571 | l32i a2, a3, EXC_TABLE_DOUBLE_SAVE | ||
572 | xsr a3, excsave1 | ||
573 | rfe | ||
574 | |||
575 | .Lrestore_1: | ||
576 | overflow_fixup_restore_a0_pane 1 | ||
577 | j .Lset_default_fixup | ||
578 | .Lrestore_3: | ||
579 | overflow_fixup_restore_a0_pane 3 | ||
580 | j .Lset_default_fixup | ||
581 | |||
582 | ENDPROC(window_overflow_restore_a0_fixup) | ||
583 | |||
584 | .end literal_prefix | ||
585 | /* | ||
472 | * Debug interrupt vector | 586 | * Debug interrupt vector |
473 | * | 587 | * |
474 | * There is not much space here, so simply jump to another handler. | 588 | * There is not much space here, so simply jump to another handler. |
diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S index ee32c0085dff..d16db6df86f8 100644 --- a/arch/xtensa/kernel/vmlinux.lds.S +++ b/arch/xtensa/kernel/vmlinux.lds.S | |||
@@ -269,13 +269,13 @@ SECTIONS | |||
269 | .UserExceptionVector.literal) | 269 | .UserExceptionVector.literal) |
270 | SECTION_VECTOR (_DoubleExceptionVector_literal, | 270 | SECTION_VECTOR (_DoubleExceptionVector_literal, |
271 | .DoubleExceptionVector.literal, | 271 | .DoubleExceptionVector.literal, |
272 | DOUBLEEXC_VECTOR_VADDR - 16, | 272 | DOUBLEEXC_VECTOR_VADDR - 40, |
273 | SIZEOF(.UserExceptionVector.text), | 273 | SIZEOF(.UserExceptionVector.text), |
274 | .UserExceptionVector.text) | 274 | .UserExceptionVector.text) |
275 | SECTION_VECTOR (_DoubleExceptionVector_text, | 275 | SECTION_VECTOR (_DoubleExceptionVector_text, |
276 | .DoubleExceptionVector.text, | 276 | .DoubleExceptionVector.text, |
277 | DOUBLEEXC_VECTOR_VADDR, | 277 | DOUBLEEXC_VECTOR_VADDR, |
278 | 32, | 278 | 40, |
279 | .DoubleExceptionVector.literal) | 279 | .DoubleExceptionVector.literal) |
280 | 280 | ||
281 | . = (LOADADDR( .DoubleExceptionVector.text ) + SIZEOF( .DoubleExceptionVector.text ) + 3) & ~ 3; | 281 | . = (LOADADDR( .DoubleExceptionVector.text ) + SIZEOF( .DoubleExceptionVector.text ) + 3) & ~ 3; |
diff --git a/arch/xtensa/mm/init.c b/arch/xtensa/mm/init.c index 4224256bb215..77ed20209ca5 100644 --- a/arch/xtensa/mm/init.c +++ b/arch/xtensa/mm/init.c | |||
@@ -191,7 +191,7 @@ int __init mem_reserve(unsigned long start, unsigned long end, int must_exist) | |||
191 | return -EINVAL; | 191 | return -EINVAL; |
192 | } | 192 | } |
193 | 193 | ||
194 | if (it && start - it->start < bank_sz) { | 194 | if (it && start - it->start <= bank_sz) { |
195 | if (start == it->start) { | 195 | if (start == it->start) { |
196 | if (end - it->start < bank_sz) { | 196 | if (end - it->start < bank_sz) { |
197 | it->start = end; | 197 | it->start = end; |