summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/sh/include/asm/page.h19
-rw-r--r--arch/sh/include/asm/ptrace.h11
-rw-r--r--arch/sh/kernel/head_32.S8
-rw-r--r--arch/sh/mm/Makefile1
-rw-r--r--arch/sh/mm/init.c21
-rw-r--r--arch/sh/mm/uncached.c28
6 files changed, 58 insertions, 30 deletions
diff --git a/arch/sh/include/asm/page.h b/arch/sh/include/asm/page.h
index 3accdc5ab122..8237d9f53e56 100644
--- a/arch/sh/include/asm/page.h
+++ b/arch/sh/include/asm/page.h
@@ -50,13 +50,22 @@ extern unsigned long shm_align_mask;
extern unsigned long max_low_pfn, min_low_pfn;
extern unsigned long memory_start, memory_end;
+#ifdef CONFIG_UNCACHED_MAPPING
+extern unsigned long uncached_start, uncached_end;
+
+extern int virt_addr_uncached(unsigned long kaddr);
+extern void uncached_init(void);
+#else
+#define virt_addr_uncached(kaddr) (0)
+#define uncached_init() do { } while (0)
+#endif
+
static inline unsigned long
pages_do_alias(unsigned long addr1, unsigned long addr2)
{
return (addr1 ^ addr2) & shm_align_mask;
}
-
#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
extern void copy_page(void *to, void *from);
@@ -135,6 +144,14 @@ typedef struct page *pgtable_t;
#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))
#endif
+#ifdef CONFIG_UNCACHED_MAPPING
+#define UNCAC_ADDR(addr) ((addr) - PAGE_OFFSET + uncached_start)
+#define CAC_ADDR(addr) ((addr) - uncached_start + PAGE_OFFSET)
+#else
+#define UNCAC_ADDR(addr) ((addr))
+#define CAC_ADDR(addr) ((addr))
+#endif
+
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
diff --git a/arch/sh/include/asm/ptrace.h b/arch/sh/include/asm/ptrace.h
index e879dffa324b..e11b14ea2c43 100644
--- a/arch/sh/include/asm/ptrace.h
+++ b/arch/sh/include/asm/ptrace.h
@@ -139,15 +139,8 @@ static inline unsigned long profile_pc(struct pt_regs *regs)
{
unsigned long pc = instruction_pointer(regs);
-#ifdef CONFIG_UNCACHED_MAPPING
- /*
- * If PC points in to the uncached mapping, fix it up and hand
- * back the cached equivalent.
- */
- if ((pc >= (memory_start + cached_to_uncached)) &&
- (pc < (memory_start + cached_to_uncached + uncached_size)))
- pc -= cached_to_uncached;
-#endif
+ if (virt_addr_uncached(pc))
+ return CAC_ADDR(pc);
return pc;
}
diff --git a/arch/sh/kernel/head_32.S b/arch/sh/kernel/head_32.S
index 91ae76277d8f..79ff39517f8e 100644
--- a/arch/sh/kernel/head_32.S
+++ b/arch/sh/kernel/head_32.S
@@ -152,6 +152,7 @@ ENTRY(_stext)
mov #0, r10
+#ifdef CONFIG_UNCACHED_MAPPING
/*
* Uncached mapping
*/
@@ -171,6 +172,7 @@ ENTRY(_stext)
add r4, r1
add r4, r3
add #1, r10
+#endif
/*
* Iterate over all of the available sizes from largest to
@@ -216,6 +218,7 @@ ENTRY(_stext)
__PMB_ITER_BY_SIZE(64)
__PMB_ITER_BY_SIZE(16)
+#ifdef CONFIG_UNCACHED_MAPPING
/*
* Now that we can access it, update cached_to_uncached and
* uncached_size.
@@ -228,6 +231,7 @@ ENTRY(_stext)
shll16 r7
shll8 r7
mov.l r7, @r0
+#endif
/*
* Clear the remaining PMB entries.
@@ -306,7 +310,9 @@ ENTRY(stack_start)
.LFIRST_ADDR_ENTRY: .long PAGE_OFFSET | PMB_V
.LFIRST_DATA_ENTRY: .long __MEMORY_START | PMB_V
.LMMUCR: .long MMUCR
+.LMEMORY_SIZE: .long __MEMORY_SIZE
+#ifdef CONFIG_UNCACHED_MAPPING
.Lcached_to_uncached: .long cached_to_uncached
.Luncached_size: .long uncached_size
-.LMEMORY_SIZE: .long __MEMORY_SIZE
+#endif
#endif
diff --git a/arch/sh/mm/Makefile b/arch/sh/mm/Makefile
index de714cbd961a..3dc8a8a63822 100644
--- a/arch/sh/mm/Makefile
+++ b/arch/sh/mm/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
obj-$(CONFIG_PMB) += pmb.o
obj-$(CONFIG_NUMA) += numa.o
obj-$(CONFIG_IOREMAP_FIXED) += ioremap_fixed.o
+obj-$(CONFIG_UNCACHED_MAPPING) += uncached.o
# Special flags for fault_64.o. This puts restrictions on the number of
# caller-save registers that the compiler can target when building this file.
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index 58012b6bbe76..08e280d7cc7e 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -26,21 +26,6 @@
DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
pgd_t swapper_pg_dir[PTRS_PER_PGD];
-#ifdef CONFIG_UNCACHED_MAPPING
-/*
- * This is the offset of the uncached section from its cached alias.
- *
- * Legacy platforms handle trivial transitions between cached and
- * uncached segments by making use of the 1:1 mapping relationship in
- * 512MB lowmem, others via a special uncached mapping.
- *
- * Default value only valid in 29 bit mode, in 32bit mode this will be
- * updated by the early PMB initialization code.
- */
-unsigned long cached_to_uncached = 0x20000000;
-unsigned long uncached_size = SZ_512M;
-#endif
-
#ifdef CONFIG_MMU
static pte_t *__get_pte_phys(unsigned long addr)
{
@@ -260,7 +245,7 @@ void __init mem_init(void)
memset(empty_zero_page, 0, PAGE_SIZE);
__flush_wback_region(empty_zero_page, PAGE_SIZE);
- /* Initialize the vDSO */
+ uncached_init();
vsyscall_init();
codesize = (unsigned long) &_etext - (unsigned long) &_text;
@@ -303,9 +288,7 @@ void __init mem_init(void)
((unsigned long)high_memory - (unsigned long)memory_start) >> 20,
#ifdef CONFIG_UNCACHED_MAPPING
- (unsigned long)memory_start + cached_to_uncached,
- (unsigned long)memory_start + cached_to_uncached + uncached_size,
- uncached_size >> 20,
+ uncached_start, uncached_end, uncached_size >> 20,
#endif
(unsigned long)&__init_begin, (unsigned long)&__init_end,
diff --git a/arch/sh/mm/uncached.c b/arch/sh/mm/uncached.c
new file mode 100644
index 000000000000..807906981d9d
--- /dev/null
+++ b/arch/sh/mm/uncached.c
@@ -0,0 +1,28 @@
+#include <linux/init.h>
+#include <asm/sizes.h>
+#include <asm/page.h>
+
+/*
+ * This is the offset of the uncached section from its cached alias.
+ *
+ * Legacy platforms handle trivial transitions between cached and
+ * uncached segments by making use of the 1:1 mapping relationship in
+ * 512MB lowmem, others via a special uncached mapping.
+ *
+ * Default value only valid in 29 bit mode, in 32bit mode this will be
+ * updated by the early PMB initialization code.
+ */
+unsigned long cached_to_uncached = SZ_512M;
+unsigned long uncached_size = SZ_512M;
+unsigned long uncached_start, uncached_end;
+
+int virt_addr_uncached(unsigned long kaddr)
+{
+ return (kaddr >= uncached_start) && (kaddr < uncached_end);
+}
+
+void __init uncached_init(void)
+{
+ uncached_start = memory_end;
+ uncached_end = uncached_start + uncached_size;
+}