summaryrefslogtreecommitdiffstats
path: root/arch/sh/mm
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-07-23 14:05:01 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-07-23 14:05:01 +0000
commitf3627cbe9236a062012c836f3b6ee311b43f63f2 (patch)
treeae854838b9a73b35bd0f3b8f42e5fb7f9cb1d5a9 /arch/sh/mm
parentfea12a7b3f20bc135ab533491411e9ff753c01c8 (diff)
Merge with Linux 2.4.0-test5-pre4.
Diffstat (limited to 'arch/sh/mm')
-rw-r--r--arch/sh/mm/cache.c10
-rw-r--r--arch/sh/mm/fault.c43
-rw-r--r--arch/sh/mm/init.c5
3 files changed, 54 insertions, 4 deletions
diff --git a/arch/sh/mm/cache.c b/arch/sh/mm/cache.c
index 895681fc6..56f444bf4 100644
--- a/arch/sh/mm/cache.c
+++ b/arch/sh/mm/cache.c
@@ -2,7 +2,7 @@
*
* linux/arch/sh/mm/cache.c
*
- * Copyright (C) 1999 Niibe Yutaka
+ * Copyright (C) 1999, 2000 Niibe Yutaka
*
*/
@@ -36,7 +36,10 @@ struct _cache_system_info {
int num_entries;
};
-static struct _cache_system_info cache_system_info;
+/* Data at BSS is cleared after setting this variable.
+ So, we Should not placed this variable at BSS section.
+ Initialize this, it is placed at data section. */
+static struct _cache_system_info cache_system_info = {0,};
#define CACHE_OC_WAY_SHIFT (cache_system_info.way_shift)
#define CACHE_IC_WAY_SHIFT (cache_system_info.way_shift)
@@ -97,7 +100,7 @@ static inline void cache_wback_all(void)
}
}
-static void
+static void __init
detect_cpu_and_cache_system(void)
{
#if defined(__sh3__)
@@ -338,6 +341,7 @@ void flush_cache_range(struct mm_struct *mm, unsigned long start,
void flush_cache_page(struct vm_area_struct *vma, unsigned long addr)
{
+ /* XXX: Umm... this flush out all the cache lines. Any improvement? */
flush_cache_range(vma->vm_mm, addr, addr+PAGE_SIZE);
}
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c
index 428bec21c..9dd6ae451 100644
--- a/arch/sh/mm/fault.c
+++ b/arch/sh/mm/fault.c
@@ -29,6 +29,9 @@
extern void die(const char *,struct pt_regs *,long);
static void __flush_tlb_page(struct mm_struct *mm, unsigned long page);
+#if defined(__SH4__)
+static void __flush_tlb_phys(struct mm_struct *mm, unsigned long phys);
+#endif
/*
* Ugly, ugly, but the goto's result in better assembly..
@@ -277,6 +280,19 @@ void update_mmu_cache(struct vm_area_struct * vma,
save_and_cli(flags);
+#if defined(__SH4__)
+ if ((vma->vm_flags & VM_SHARED)) {
+ pteval = pte_val(pte);
+ pteval &= PAGE_MASK; /* Physicall page address */
+
+ __flush_tlb_phys(vma->vm_mm, pteval);
+
+ /* It would be good we had routine which takes
+ physical memory as argument */
+ flush_cache_page(vma, address&PAGE_MASK);
+ }
+#endif
+
/* Set PTEH register */
if (vma) {
pteaddr = (address & MMU_VPN_MASK) |
@@ -328,6 +344,33 @@ static void __flush_tlb_page(struct mm_struct *mm, unsigned long page)
set_asid(saved_asid);
}
+#if defined(__SH4__)
+static void __flush_tlb_phys(struct mm_struct *mm, unsigned long phys)
+{
+ int i;
+ unsigned long addr, data;
+
+ jump_to_P2();
+ for (i = 0; i < MMU_UTLB_ENTRIES; i++) {
+ addr = MMU_UTLB_DATA_ARRAY | (i<<MMU_U_ENTRY_SHIFT);
+ data = ctrl_inl(addr);
+ if ((data & MMU_UTLB_VALID) && (data&PAGE_MASK) == phys) {
+ data &= ~MMU_UTLB_VALID;
+ ctrl_outl(data, addr);
+ }
+ }
+ for (i = 0; i < MMU_ITLB_ENTRIES; i++) {
+ addr = MMU_ITLB_DATA_ARRAY | (i<<MMU_I_ENTRY_SHIFT);
+ data = ctrl_inl(addr);
+ if ((data & MMU_ITLB_VALID) && (data&PAGE_MASK) == phys) {
+ data &= ~MMU_ITLB_VALID;
+ ctrl_outl(data, addr);
+ }
+ }
+ back_to_P1();
+}
+#endif
+
void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
{
unsigned long flags;
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index 931564cac..f798ef968 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.16 2000/02/14 15:19:05 gniibe Exp $
+/* $Id: init.c,v 1.17 2000-04-08 15:38:54+09 gniibe Exp $
*
* linux/arch/sh/mm/init.c
*
@@ -207,6 +207,9 @@ void __init paging_init(void)
/* Enable MMU */
ctrl_outl(MMU_CONTROL_INIT, MMUCR);
+ /* The manual suggests doing some nops after turning on the MMU */
+ asm volatile("nop;nop;nop;nop;nop;nop;");
+
mmu_context_cache = MMU_CONTEXT_FIRST_VERSION;
set_asid(mmu_context_cache & MMU_CONTEXT_ASID_MASK);