From 5029615e25dc5040beb065f36743c127a8e51497 Mon Sep 17 00:00:00 2001
From: Max Filippov <jcmvbkbc@gmail.com>
Date: Thu, 24 Sep 2015 23:11:53 +0300
Subject: xtensa: fixes for configs without loop option

Build-time fixes:
- make lbeg/lend/lcount save/restore conditional on kernel entry;
- don't clear lcount in platform_restart functions unconditionally.

Run-time fixes:
- use correct end of range register in __endla paired with __loopt, not
  the unused temporary register. This fixes .bss zero-initialization.
  Update comments in asmmacro.h;
- don't clobber a10 in the usercopy that leads to access to unmapped
  memory.

Cc: <stable@vger.kernel.org>
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 arch/xtensa/kernel/entry.S | 8 ++++++--
 arch/xtensa/kernel/head.S  | 2 +-
 2 files changed, 7 insertions(+), 3 deletions(-)

(limited to 'arch/xtensa/kernel')

diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index 504130357597..db5c1765b413 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -367,8 +367,10 @@ common_exception:
 	s32i	a2, a1, PT_SYSCALL
 	movi	a2, 0
 	s32i	a3, a1, PT_EXCVADDR
+#if XCHAL_HAVE_LOOPS
 	xsr	a2, lcount
 	s32i	a2, a1, PT_LCOUNT
+#endif
 
 	/* It is now save to restore the EXC_TABLE_FIXUP variable. */
 
@@ -429,11 +431,12 @@ common_exception:
 	rsync				# PS.WOE => rsync => overflow
 
 	/* Save lbeg, lend */
-
+#if XCHAL_HAVE_LOOPS
 	rsr	a4, lbeg
 	rsr	a3, lend
 	s32i	a4, a1, PT_LBEG
 	s32i	a3, a1, PT_LEND
+#endif
 
 	/* Save SCOMPARE1 */
 
@@ -724,13 +727,14 @@ common_exception_exit:
 	wsr	a3, sar
 
 	/* Restore LBEG, LEND, LCOUNT */
-
+#if XCHAL_HAVE_LOOPS
 	l32i	a2, a1, PT_LBEG
 	l32i	a3, a1, PT_LEND
 	wsr	a2, lbeg
 	l32i	a2, a1, PT_LCOUNT
 	wsr	a3, lend
 	wsr	a2, lcount
+#endif
 
 	/* We control single stepping through the ICOUNTLEVEL register. */
 
diff --git a/arch/xtensa/kernel/head.S b/arch/xtensa/kernel/head.S
index 15a461e2a0ed..9ed55649ac8e 100644
--- a/arch/xtensa/kernel/head.S
+++ b/arch/xtensa/kernel/head.S
@@ -249,7 +249,7 @@ ENTRY(_startup)
 
 	__loopt	a2, a3, a4, 2
 	s32i	a0, a2, 0
-	__endla	a2, a4, 4
+	__endla	a2, a3, 4
 
 #if XCHAL_DCACHE_IS_WRITEBACK
 
-- 
cgit v1.2.3


From 260c64bbabdb8da7248c87e0cdd92023bd7b76c6 Mon Sep 17 00:00:00 2001
From: Max Filippov <jcmvbkbc@gmail.com>
Date: Thu, 24 Sep 2015 23:36:45 +0300
Subject: xtensa: nommu: provide correct KIO addresses

KIO region location is different for noMMU cores. Provide different
default physical address and make KIO virtual address equal to physical.

Move xtensa_get_kio_paddr function close to XCHAL_KIO_PADDR definition
and define it not only for MMUv3, but for all MMU options except MMUv2.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 arch/xtensa/kernel/setup.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'arch/xtensa/kernel')

diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
index 28fc57ef5b86..149d372a9350 100644
--- a/arch/xtensa/kernel/setup.c
+++ b/arch/xtensa/kernel/setup.c
@@ -190,7 +190,7 @@ static int __init parse_bootparam(const bp_tag_t* tag)
 #ifdef CONFIG_OF
 bool __initdata dt_memory_scan = false;
 
-#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY
+#if !XCHAL_HAVE_PTP_MMU || XCHAL_HAVE_SPANNING_WAY
 unsigned long xtensa_kio_paddr = XCHAL_KIO_DEFAULT_PADDR;
 EXPORT_SYMBOL(xtensa_kio_paddr);
 
-- 
cgit v1.2.3


From ab45fb145096799dabd18afc58bb5f97171017cd Mon Sep 17 00:00:00 2001
From: Max Filippov <jcmvbkbc@gmail.com>
Date: Fri, 16 Oct 2015 17:01:04 +0300
Subject: xtensa: fix secondary core boot in SMP

There are multiple factors adding to the issue in different
configurations:

- commit 17290231df16eeee ("xtensa: add fixup for double exception raised
  in window overflow") added function window_overflow_restore_a0_fixup to
  double exception vector overlapping reset vector location of secondary
  processor cores.
- on MMUv2 cores RESET_VECTOR1_VADDR may point to uncached kernel memory
  making code overlapping depend on cache type and size, so that without
  cache or with WT cache reset vector code overwrites double exception
  code, making issue even harder to detect.
- on MMUv3 cores RESET_VECTOR1_VADDR may point to unmapped area, as
  MMUv3 cores change virtual address map to match MMUv2 layout, but
  reset vector virtual address is given for the original MMUv3 mapping.
- physical memory region of the secondary reset vector is not reserved
  in the physical memory map, and thus may be allocated and overwritten
  at arbitrary moment.

Fix it as follows:

- move window_overflow_restore_a0_fixup code to .text section.
- define RESET_VECTOR1_VADDR so that it points to reset vector in the
  cacheable MMUv2 map for cores with MMU.
- reserve reset vector region in the physical memory map. Drop separate
  literal section and build mxhead.S with text section literals.

Cc: <stable@vger.kernel.org>
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 arch/xtensa/kernel/Makefile      |  1 +
 arch/xtensa/kernel/setup.c       |  9 ++++++++-
 arch/xtensa/kernel/vectors.S     |  4 +++-
 arch/xtensa/kernel/vmlinux.lds.S | 12 ++----------
 4 files changed, 14 insertions(+), 12 deletions(-)

(limited to 'arch/xtensa/kernel')

diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile
index 50137bc9e150..4db730290d2d 100644
--- a/arch/xtensa/kernel/Makefile
+++ b/arch/xtensa/kernel/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_SMP) += smp.o mxhead.o
 obj-$(CONFIG_XTENSA_VARIANT_HAVE_PERF_EVENTS) += perf_event.o
 
 AFLAGS_head.o += -mtext-section-literals
+AFLAGS_mxhead.o += -mtext-section-literals
 
 # In the Xtensa architecture, assembly generates literals which must always
 # precede the L32R instruction with a relative offset less than 256 kB.
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
index 149d372a9350..9735691f37f1 100644
--- a/arch/xtensa/kernel/setup.c
+++ b/arch/xtensa/kernel/setup.c
@@ -334,7 +334,10 @@ extern char _Level5InterruptVector_text_end;
 extern char _Level6InterruptVector_text_start;
 extern char _Level6InterruptVector_text_end;
 #endif
-
+#ifdef CONFIG_SMP
+extern char _SecondaryResetVector_text_start;
+extern char _SecondaryResetVector_text_end;
+#endif
 
 
 #ifdef CONFIG_S32C1I_SELFTEST
@@ -506,6 +509,10 @@ void __init setup_arch(char **cmdline_p)
 		    __pa(&_Level6InterruptVector_text_end), 0);
 #endif
 
+#ifdef CONFIG_SMP
+	mem_reserve(__pa(&_SecondaryResetVector_text_start),
+		    __pa(&_SecondaryResetVector_text_end), 0);
+#endif
 	parse_early_param();
 	bootmem_init();
 
diff --git a/arch/xtensa/kernel/vectors.S b/arch/xtensa/kernel/vectors.S
index abcdb527f18a..fc25318e75ad 100644
--- a/arch/xtensa/kernel/vectors.S
+++ b/arch/xtensa/kernel/vectors.S
@@ -478,6 +478,9 @@ _DoubleExceptionVector_handle_exception:
 
 ENDPROC(_DoubleExceptionVector)
 
+	.end literal_prefix
+
+	.text
 /*
  * 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
@@ -587,7 +590,6 @@ ENTRY(window_overflow_restore_a0_fixup)
 
 ENDPROC(window_overflow_restore_a0_fixup)
 
-	.end literal_prefix
 /*
  * Debug interrupt vector
  *
diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S
index fc1bc2ba8d5d..d66cd408be13 100644
--- a/arch/xtensa/kernel/vmlinux.lds.S
+++ b/arch/xtensa/kernel/vmlinux.lds.S
@@ -166,8 +166,6 @@ SECTIONS
     RELOCATE_ENTRY(_DebugInterruptVector_text,
 		   .DebugInterruptVector.text);
 #if defined(CONFIG_SMP)
-    RELOCATE_ENTRY(_SecondaryResetVector_literal,
-		   .SecondaryResetVector.literal);
     RELOCATE_ENTRY(_SecondaryResetVector_text,
 		   .SecondaryResetVector.text);
 #endif
@@ -282,17 +280,11 @@ SECTIONS
 
 #if defined(CONFIG_SMP)
 
-  SECTION_VECTOR (_SecondaryResetVector_literal,
-		  .SecondaryResetVector.literal,
-		  RESET_VECTOR1_VADDR - 4,
-		  SIZEOF(.DoubleExceptionVector.text),
-		  .DoubleExceptionVector.text)
-
   SECTION_VECTOR (_SecondaryResetVector_text,
 		  .SecondaryResetVector.text,
 		  RESET_VECTOR1_VADDR,
-		  4,
-		  .SecondaryResetVector.literal)
+		  SIZEOF(.DoubleExceptionVector.text),
+		  .DoubleExceptionVector.text)
 
   . = LOADADDR(.SecondaryResetVector.text)+SIZEOF(.SecondaryResetVector.text);
 
-- 
cgit v1.2.3


From 0d848afe117ac3e31b9d57b65553ff18ef9d288f Mon Sep 17 00:00:00 2001
From: Max Filippov <jcmvbkbc@gmail.com>
Date: Fri, 16 Oct 2015 18:30:37 +0300
Subject: xtensa: drop unused sections and remapped reset handlers

There are no .bootstrap or .ResetVector.text sections linked to the
vmlinux image, drop these sections from vmlinux.ld.S. Drop
RESET_VECTOR_VADDR definition only used for .ResetVector.text.

Drop remapped copies of primary and secondary reset vectors, as modern
gdb don't have problems stepping through instructions at arbitrary
locations. Drop corresponding sections from the corresponding linker
scripts.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 arch/xtensa/kernel/mxhead.S      | 23 -----------------------
 arch/xtensa/kernel/vmlinux.lds.S | 25 -------------------------
 2 files changed, 48 deletions(-)

(limited to 'arch/xtensa/kernel')

diff --git a/arch/xtensa/kernel/mxhead.S b/arch/xtensa/kernel/mxhead.S
index 77a161a112c5..9f3843742726 100644
--- a/arch/xtensa/kernel/mxhead.S
+++ b/arch/xtensa/kernel/mxhead.S
@@ -48,8 +48,6 @@ _SetupOCD:
 	rsync
 
 _SetupMMU:
-	Offset = _SetupMMU - _SecondaryResetVector
-
 #ifdef CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX
 	initialize_mmu
 #endif
@@ -62,24 +60,3 @@ _SetupMMU:
 	jx	a3
 
 	.end    no-absolute-literals
-
-
-	.section 	.SecondaryResetVector.remapped_text, "ax"
-	.global         _RemappedSecondaryResetVector
-
-	.org 0                                  # Need to do org before literals
-
-_RemappedSecondaryResetVector:
-	.begin  no-absolute-literals
-	.literal_position
-
-	_j      _RemappedSetupMMU
-	. = _RemappedSecondaryResetVector + Offset
-
-_RemappedSetupMMU:
-
-#ifdef CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX
-	initialize_mmu
-#endif
-
-	.end    no-absolute-literals
diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S
index d66cd408be13..c417cbe4ec87 100644
--- a/arch/xtensa/kernel/vmlinux.lds.S
+++ b/arch/xtensa/kernel/vmlinux.lds.S
@@ -298,31 +298,6 @@ SECTIONS
 
   _end = .;
 
-  /* only used by the boot loader  */
-
-  . = ALIGN(0x10);
-  .bootstrap : { *(.bootstrap.literal .bootstrap.text .bootstrap.data) }
-
-  .ResetVector.text RESET_VECTOR_VADDR :
-  {
-    *(.ResetVector.text)
-  }
-
-
-  /*
-   * This is a remapped copy of the Secondary Reset Vector Code.
-   * It keeps gdb in sync with the PC after switching
-   * to the temporary mapping used while setting up
-   * the V2 MMU mappings for Linux.
-   *
-   * Only debug information about this section is put in the kernel image.
-   */
-  .SecondaryResetVector.remapped_text 0x46000000 (INFO):
-  {
-	*(.SecondaryResetVector.remapped_text)
-  }
-
-
   .xt.lit : { *(.xt.lit) }
   .xt.prop : { *(.xt.prop) }
 
-- 
cgit v1.2.3


From c7ca9fe17b84719ef2edbe854e1b0cac04a91e2f Mon Sep 17 00:00:00 2001
From: Max Filippov <jcmvbkbc@gmail.com>
Date: Fri, 9 Oct 2015 02:44:23 +0300
Subject: xtensa: support DMA to high memory

- don't bugcheck if high memory page is passed to xtensa_map_page;
- turn empty dcache flush macros into functions so that they could be
  passed as function parameters;
- use kmap_atomic to map high memory pages for cache invalidation/
  flushing performed by xtensa_sync_single_for_{cpu,device}.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 arch/xtensa/kernel/pci-dma.c | 45 ++++++++++++++++++++++++++++++--------------
 1 file changed, 31 insertions(+), 14 deletions(-)

(limited to 'arch/xtensa/kernel')

diff --git a/arch/xtensa/kernel/pci-dma.c b/arch/xtensa/kernel/pci-dma.c
index fb75ebf1463a..cd66698348ca 100644
--- a/arch/xtensa/kernel/pci-dma.c
+++ b/arch/xtensa/kernel/pci-dma.c
@@ -15,14 +15,15 @@
  * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
  */
 
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/pci.h>
 #include <linux/gfp.h>
+#include <linux/highmem.h>
+#include <linux/mm.h>
 #include <linux/module.h>
-#include <asm/io.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/types.h>
 #include <asm/cacheflush.h>
+#include <asm/io.h>
 
 void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
 		    enum dma_data_direction dir)
@@ -47,17 +48,36 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
 }
 EXPORT_SYMBOL(dma_cache_sync);
 
+static void do_cache_op(dma_addr_t dma_handle, size_t size,
+			void (*fn)(unsigned long, unsigned long))
+{
+	unsigned long off = dma_handle & (PAGE_SIZE - 1);
+	unsigned long pfn = PFN_DOWN(dma_handle);
+	struct page *page = pfn_to_page(pfn);
+
+	if (!PageHighMem(page))
+		fn((unsigned long)bus_to_virt(dma_handle), size);
+	else
+		while (size > 0) {
+			size_t sz = min_t(size_t, size, PAGE_SIZE - off);
+			void *vaddr = kmap_atomic(page);
+
+			fn((unsigned long)vaddr + off, sz);
+			kunmap_atomic(vaddr);
+			off = 0;
+			++page;
+			size -= sz;
+		}
+}
+
 static void xtensa_sync_single_for_cpu(struct device *dev,
 				       dma_addr_t dma_handle, size_t size,
 				       enum dma_data_direction dir)
 {
-	void *vaddr;
-
 	switch (dir) {
 	case DMA_BIDIRECTIONAL:
 	case DMA_FROM_DEVICE:
-		vaddr = bus_to_virt(dma_handle);
-		__invalidate_dcache_range((unsigned long)vaddr, size);
+		do_cache_op(dma_handle, size, __invalidate_dcache_range);
 		break;
 
 	case DMA_NONE:
@@ -73,13 +93,11 @@ static void xtensa_sync_single_for_device(struct device *dev,
 					  dma_addr_t dma_handle, size_t size,
 					  enum dma_data_direction dir)
 {
-	void *vaddr;
-
 	switch (dir) {
 	case DMA_BIDIRECTIONAL:
 	case DMA_TO_DEVICE:
-		vaddr = bus_to_virt(dma_handle);
-		__flush_dcache_range((unsigned long)vaddr, size);
+		if (XCHAL_DCACHE_IS_WRITEBACK)
+			do_cache_op(dma_handle, size, __flush_dcache_range);
 		break;
 
 	case DMA_NONE:
@@ -171,7 +189,6 @@ static dma_addr_t xtensa_map_page(struct device *dev, struct page *page,
 {
 	dma_addr_t dma_handle = page_to_phys(page) + offset;
 
-	BUG_ON(PageHighMem(page));
 	xtensa_sync_single_for_device(dev, dma_handle, size, dir);
 	return dma_handle;
 }
-- 
cgit v1.2.3