aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Filippov <jcmvbkbc@gmail.com>2016-09-12 00:35:07 -0400
committerMax Filippov <jcmvbkbc@gmail.com>2016-09-12 02:53:23 -0400
commitbf15f86b343ed894e74fb9c6c944cea1f8f9b654 (patch)
tree4a8bcb53725a63e68531404ed6fe2540233a4675
parentea951c34ea957d509916f79502917b87cf111b37 (diff)
xtensa: initialize MMU before jumping to reset vector
When reset is simulated MMU need to be brought into its initial state, because that's what bootloaders/OS kernels assume. This is especially important for MMUv3 because TLB state when the kernel is running is significatly different from its reset state. With this change it is possible to boot linux and get back to U-Boot repeatedly. Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
-rw-r--r--arch/xtensa/kernel/setup.c108
1 files changed, 108 insertions, 0 deletions
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
index 65486b8dfa2b..7ed63688f93c 100644
--- a/arch/xtensa/kernel/setup.c
+++ b/arch/xtensa/kernel/setup.c
@@ -551,6 +551,114 @@ subsys_initcall(topology_init);
551 551
552void cpu_reset(void) 552void cpu_reset(void)
553{ 553{
554#if XCHAL_HAVE_PTP_MMU
555 local_irq_disable();
556 /*
557 * We have full MMU: all autoload ways, ways 7, 8 and 9 of DTLB must
558 * be flushed.
559 * Way 4 is not currently used by linux.
560 * Ways 5 and 6 shall not be touched on MMUv2 as they are hardwired.
561 * Way 5 shall be flushed and way 6 shall be set to identity mapping
562 * on MMUv3.
563 */
564 local_flush_tlb_all();
565 invalidate_page_directory();
566#if XCHAL_HAVE_SPANNING_WAY
567 /* MMU v3 */
568 {
569 unsigned long vaddr = (unsigned long)cpu_reset;
570 unsigned long paddr = __pa(vaddr);
571 unsigned long tmpaddr = vaddr + SZ_512M;
572 unsigned long tmp0, tmp1, tmp2, tmp3;
573
574 /*
575 * Find a place for the temporary mapping. It must not be
576 * in the same 512MB region with vaddr or paddr, otherwise
577 * there may be multihit exception either on entry to the
578 * temporary mapping, or on entry to the identity mapping.
579 * (512MB is the biggest page size supported by TLB.)
580 */
581 while (((tmpaddr ^ paddr) & -SZ_512M) == 0)
582 tmpaddr += SZ_512M;
583
584 /* Invalidate mapping in the selected temporary area */
585 if (itlb_probe(tmpaddr) & 0x8)
586 invalidate_itlb_entry(itlb_probe(tmpaddr));
587 if (itlb_probe(tmpaddr + PAGE_SIZE) & 0x8)
588 invalidate_itlb_entry(itlb_probe(tmpaddr + PAGE_SIZE));
589
590 /*
591 * Map two consecutive pages starting at the physical address
592 * of this function to the temporary mapping area.
593 */
594 write_itlb_entry(__pte((paddr & PAGE_MASK) |
595 _PAGE_HW_VALID |
596 _PAGE_HW_EXEC |
597 _PAGE_CA_BYPASS),
598 tmpaddr & PAGE_MASK);
599 write_itlb_entry(__pte(((paddr & PAGE_MASK) + PAGE_SIZE) |
600 _PAGE_HW_VALID |
601 _PAGE_HW_EXEC |
602 _PAGE_CA_BYPASS),
603 (tmpaddr & PAGE_MASK) + PAGE_SIZE);
604
605 /* Reinitialize TLB */
606 __asm__ __volatile__ ("movi %0, 1f\n\t"
607 "movi %3, 2f\n\t"
608 "add %0, %0, %4\n\t"
609 "add %3, %3, %5\n\t"
610 "jx %0\n"
611 /*
612 * No literal, data or stack access
613 * below this point
614 */
615 "1:\n\t"
616 /* Initialize *tlbcfg */
617 "movi %0, 0\n\t"
618 "wsr %0, itlbcfg\n\t"
619 "wsr %0, dtlbcfg\n\t"
620 /* Invalidate TLB way 5 */
621 "movi %0, 4\n\t"
622 "movi %1, 5\n"
623 "1:\n\t"
624 "iitlb %1\n\t"
625 "idtlb %1\n\t"
626 "add %1, %1, %6\n\t"
627 "addi %0, %0, -1\n\t"
628 "bnez %0, 1b\n\t"
629 /* Initialize TLB way 6 */
630 "movi %0, 7\n\t"
631 "addi %1, %9, 3\n\t"
632 "addi %2, %9, 6\n"
633 "1:\n\t"
634 "witlb %1, %2\n\t"
635 "wdtlb %1, %2\n\t"
636 "add %1, %1, %7\n\t"
637 "add %2, %2, %7\n\t"
638 "addi %0, %0, -1\n\t"
639 "bnez %0, 1b\n\t"
640 /* Jump to identity mapping */
641 "jx %3\n"
642 "2:\n\t"
643 /* Complete way 6 initialization */
644 "witlb %1, %2\n\t"
645 "wdtlb %1, %2\n\t"
646 /* Invalidate temporary mapping */
647 "sub %0, %9, %7\n\t"
648 "iitlb %0\n\t"
649 "add %0, %0, %8\n\t"
650 "iitlb %0"
651 : "=&a"(tmp0), "=&a"(tmp1), "=&a"(tmp2),
652 "=&a"(tmp3)
653 : "a"(tmpaddr - vaddr),
654 "a"(paddr - vaddr),
655 "a"(SZ_128M), "a"(SZ_512M),
656 "a"(PAGE_SIZE),
657 "a"((tmpaddr + SZ_512M) & PAGE_MASK)
658 : "memory");
659 }
660#endif
661#endif
554 __asm__ __volatile__ ("movi a2, 0\n\t" 662 __asm__ __volatile__ ("movi a2, 0\n\t"
555 "wsr a2, icountlevel\n\t" 663 "wsr a2, icountlevel\n\t"
556 "movi a2, 0\n\t" 664 "movi a2, 0\n\t"