diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-07-23 14:05:01 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-07-23 14:05:01 +0000 |
commit | f3627cbe9236a062012c836f3b6ee311b43f63f2 (patch) | |
tree | ae854838b9a73b35bd0f3b8f42e5fb7f9cb1d5a9 /arch/sh/mm | |
parent | fea12a7b3f20bc135ab533491411e9ff753c01c8 (diff) |
Merge with Linux 2.4.0-test5-pre4.
Diffstat (limited to 'arch/sh/mm')
-rw-r--r-- | arch/sh/mm/cache.c | 10 | ||||
-rw-r--r-- | arch/sh/mm/fault.c | 43 | ||||
-rw-r--r-- | arch/sh/mm/init.c | 5 |
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); |