sh: wire up clear_user_highpage() for sh4, convert sh7705.
This wires up clear_user_highpage() on SH-4 and subsequently converts the SH7705 32kB cache mode over to using it. Now that the SH-4 implementation handles all of the dcache purging directly in the aliasing case, there is no need to do this in the default clear_page() implementation. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
This commit is contained in:
@@ -49,7 +49,7 @@ static inline void flush_kernel_dcache_page(struct page *page)
|
|||||||
flush_dcache_page(page);
|
flush_dcache_page(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_CACHE_OFF)
|
#if (defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)) && !defined(CONFIG_CACHE_OFF)
|
||||||
extern void copy_to_user_page(struct vm_area_struct *vma,
|
extern void copy_to_user_page(struct vm_area_struct *vma,
|
||||||
struct page *page, unsigned long vaddr, void *dst, const void *src,
|
struct page *page, unsigned long vaddr, void *dst, const void *src,
|
||||||
unsigned long len);
|
unsigned long len);
|
||||||
|
@@ -56,21 +56,25 @@ pages_do_alias(unsigned long addr1, unsigned long addr2)
|
|||||||
return (addr1 ^ addr2) & shm_align_mask;
|
return (addr1 ^ addr2) & shm_align_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void clear_page(void *to);
|
|
||||||
|
#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
|
||||||
extern void copy_page(void *to, void *from);
|
extern void copy_page(void *to, void *from);
|
||||||
|
|
||||||
|
struct page;
|
||||||
|
struct vm_area_struct;
|
||||||
|
|
||||||
#if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_MMU) && \
|
#if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_MMU) && \
|
||||||
(defined(CONFIG_CPU_SH5) || defined(CONFIG_CPU_SH4) || \
|
(defined(CONFIG_CPU_SH5) || defined(CONFIG_CPU_SH4) || \
|
||||||
defined(CONFIG_SH7705_CACHE_32KB))
|
defined(CONFIG_SH7705_CACHE_32KB))
|
||||||
struct page;
|
|
||||||
struct vm_area_struct;
|
|
||||||
extern void clear_user_page(void *to, unsigned long address, struct page *page);
|
extern void clear_user_page(void *to, unsigned long address, struct page *page);
|
||||||
extern void copy_user_page(void *to, void *from, unsigned long address,
|
extern void copy_user_page(void *to, void *from, unsigned long address,
|
||||||
struct page *page);
|
struct page *page);
|
||||||
#if defined(CONFIG_CPU_SH4)
|
#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)
|
||||||
extern void copy_user_highpage(struct page *to, struct page *from,
|
extern void copy_user_highpage(struct page *to, struct page *from,
|
||||||
unsigned long vaddr, struct vm_area_struct *vma);
|
unsigned long vaddr, struct vm_area_struct *vma);
|
||||||
#define __HAVE_ARCH_COPY_USER_HIGHPAGE
|
#define __HAVE_ARCH_COPY_USER_HIGHPAGE
|
||||||
|
extern void clear_user_highpage(struct page *page, unsigned long vaddr);
|
||||||
|
#define clear_user_highpage clear_user_highpage
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#define clear_user_page(page, vaddr, pg) clear_page(page)
|
#define clear_user_page(page, vaddr, pg) clear_page(page)
|
||||||
|
@@ -141,7 +141,8 @@ extern void paging_init(void);
|
|||||||
extern void page_table_range_init(unsigned long start, unsigned long end,
|
extern void page_table_range_init(unsigned long start, unsigned long end,
|
||||||
pgd_t *pgd);
|
pgd_t *pgd);
|
||||||
|
|
||||||
#if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_CPU_SH4) && defined(CONFIG_MMU)
|
#if !defined(CONFIG_CACHE_OFF) && (defined(CONFIG_CPU_SH4) || \
|
||||||
|
defined(CONFIG_SH7705_CACHE_32KB)) && defined(CONFIG_MMU)
|
||||||
extern void kmap_coherent_init(void);
|
extern void kmap_coherent_init(void);
|
||||||
#else
|
#else
|
||||||
#define kmap_coherent_init() do { } while (0)
|
#define kmap_coherent_init() do { } while (0)
|
||||||
|
@@ -101,11 +101,6 @@ EXPORT_SYMBOL(flush_cache_range);
|
|||||||
EXPORT_SYMBOL(flush_dcache_page);
|
EXPORT_SYMBOL(flush_dcache_page);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_MMU) && \
|
|
||||||
(defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB))
|
|
||||||
EXPORT_SYMBOL(clear_user_page);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_MCOUNT
|
#ifdef CONFIG_MCOUNT
|
||||||
DECLARE_EXPORT(mcount);
|
DECLARE_EXPORT(mcount);
|
||||||
#endif
|
#endif
|
||||||
@@ -114,7 +109,6 @@ EXPORT_SYMBOL(csum_partial_copy_generic);
|
|||||||
#ifdef CONFIG_IPV6
|
#ifdef CONFIG_IPV6
|
||||||
EXPORT_SYMBOL(csum_ipv6_magic);
|
EXPORT_SYMBOL(csum_ipv6_magic);
|
||||||
#endif
|
#endif
|
||||||
EXPORT_SYMBOL(clear_page);
|
|
||||||
EXPORT_SYMBOL(copy_page);
|
EXPORT_SYMBOL(copy_page);
|
||||||
EXPORT_SYMBOL(__clear_user);
|
EXPORT_SYMBOL(__clear_user);
|
||||||
EXPORT_SYMBOL(_ebss);
|
EXPORT_SYMBOL(_ebss);
|
||||||
|
@@ -8,52 +8,6 @@
|
|||||||
#include <linux/linkage.h>
|
#include <linux/linkage.h>
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
|
|
||||||
/*
|
|
||||||
* clear_page
|
|
||||||
* @to: P1 address
|
|
||||||
*
|
|
||||||
* void clear_page(void *to)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* r0 --- scratch
|
|
||||||
* r4 --- to
|
|
||||||
* r5 --- to + PAGE_SIZE
|
|
||||||
*/
|
|
||||||
ENTRY(clear_page)
|
|
||||||
mov r4,r5
|
|
||||||
mov.l .Llimit,r0
|
|
||||||
add r0,r5
|
|
||||||
mov #0,r0
|
|
||||||
!
|
|
||||||
1:
|
|
||||||
#if defined(CONFIG_CPU_SH4)
|
|
||||||
movca.l r0,@r4
|
|
||||||
mov r4,r1
|
|
||||||
#else
|
|
||||||
mov.l r0,@r4
|
|
||||||
#endif
|
|
||||||
add #32,r4
|
|
||||||
mov.l r0,@-r4
|
|
||||||
mov.l r0,@-r4
|
|
||||||
mov.l r0,@-r4
|
|
||||||
mov.l r0,@-r4
|
|
||||||
mov.l r0,@-r4
|
|
||||||
mov.l r0,@-r4
|
|
||||||
mov.l r0,@-r4
|
|
||||||
#if defined(CONFIG_CPU_SH4)
|
|
||||||
ocbwb @r1
|
|
||||||
#endif
|
|
||||||
cmp/eq r5,r4
|
|
||||||
bf/s 1b
|
|
||||||
add #28,r4
|
|
||||||
!
|
|
||||||
rts
|
|
||||||
nop
|
|
||||||
|
|
||||||
.balign 4
|
|
||||||
.Llimit: .long (PAGE_SIZE-28)
|
|
||||||
|
|
||||||
ENTRY(__clear_user)
|
ENTRY(__clear_user)
|
||||||
!
|
!
|
||||||
mov #0, r0
|
mov #0, r0
|
||||||
|
@@ -31,7 +31,7 @@ tlb-$(CONFIG_CPU_HAS_PTEAEX) := tlb-pteaex.o
|
|||||||
obj-y += $(tlb-y)
|
obj-y += $(tlb-y)
|
||||||
ifndef CONFIG_CACHE_OFF
|
ifndef CONFIG_CACHE_OFF
|
||||||
obj-$(CONFIG_CPU_SH4) += pg-sh4.o
|
obj-$(CONFIG_CPU_SH4) += pg-sh4.o
|
||||||
obj-$(CONFIG_SH7705_CACHE_32KB) += pg-sh7705.o
|
obj-$(CONFIG_SH7705_CACHE_32KB) += pg-sh4.o
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* arch/sh/mm/pg-nommu.c
|
* arch/sh/mm/pg-nommu.c
|
||||||
*
|
*
|
||||||
* clear_page()/copy_page() implementation for MMUless SH.
|
* copy_page()/__copy_user()/__clear_user() implementations for MMUless SH.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2003 Paul Mundt
|
* Copyright (C) 2003 Paul Mundt
|
||||||
*
|
*
|
||||||
@@ -20,11 +20,6 @@ void copy_page(void *to, void *from)
|
|||||||
memcpy(to, from, PAGE_SIZE);
|
memcpy(to, from, PAGE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear_page(void *to)
|
|
||||||
{
|
|
||||||
memset(to, 0, PAGE_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
__kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n)
|
__kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n)
|
||||||
{
|
{
|
||||||
memcpy(to, from, n);
|
memcpy(to, from, n);
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
* arch/sh/mm/pg-sh4.c
|
* arch/sh/mm/pg-sh4.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 1999, 2000, 2002 Niibe Yutaka
|
* Copyright (C) 1999, 2000, 2002 Niibe Yutaka
|
||||||
* Copyright (C) 2002 - 2007 Paul Mundt
|
* Copyright (C) 2002 - 2009 Paul Mundt
|
||||||
*
|
*
|
||||||
* Released under the terms of the GNU GPL v2.0.
|
* Released under the terms of the GNU GPL v2.0.
|
||||||
*/
|
*/
|
||||||
@@ -58,20 +58,6 @@ static inline void kunmap_coherent(struct page *page)
|
|||||||
preempt_check_resched();
|
preempt_check_resched();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* clear_user_page
|
|
||||||
* @to: P1 address
|
|
||||||
* @address: U0 address to be mapped
|
|
||||||
* @page: page (virt_to_page(to))
|
|
||||||
*/
|
|
||||||
void clear_user_page(void *to, unsigned long address, struct page *page)
|
|
||||||
{
|
|
||||||
clear_page(to);
|
|
||||||
|
|
||||||
if (pages_do_alias((unsigned long)to, address & PAGE_MASK))
|
|
||||||
__flush_wback_region(to, PAGE_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
|
void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
|
||||||
unsigned long vaddr, void *dst, const void *src,
|
unsigned long vaddr, void *dst, const void *src,
|
||||||
unsigned long len)
|
unsigned long len)
|
||||||
@@ -128,3 +114,16 @@ void copy_user_highpage(struct page *to, struct page *from,
|
|||||||
smp_wmb();
|
smp_wmb();
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(copy_user_highpage);
|
EXPORT_SYMBOL(copy_user_highpage);
|
||||||
|
|
||||||
|
void clear_user_highpage(struct page *page, unsigned long vaddr)
|
||||||
|
{
|
||||||
|
void *kaddr = kmap_atomic(page, KM_USER0);
|
||||||
|
|
||||||
|
clear_page(kaddr);
|
||||||
|
|
||||||
|
if (pages_do_alias((unsigned long)kaddr, vaddr & PAGE_MASK))
|
||||||
|
__flush_wback_region(kaddr, PAGE_SIZE);
|
||||||
|
|
||||||
|
kunmap_atomic(kaddr, KM_USER0);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(clear_user_highpage);
|
||||||
|
@@ -1,102 +0,0 @@
|
|||||||
/*
|
|
||||||
* arch/sh/mm/pg-sh7705.c
|
|
||||||
*
|
|
||||||
* Copyright (C) 1999, 2000 Niibe Yutaka
|
|
||||||
* Copyright (C) 2004 Alex Song
|
|
||||||
*
|
|
||||||
* This file is subject to the terms and conditions of the GNU General Public
|
|
||||||
* License. See the file "COPYING" in the main directory of this archive
|
|
||||||
* for more details.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/init.h>
|
|
||||||
#include <linux/mman.h>
|
|
||||||
#include <linux/mm.h>
|
|
||||||
#include <linux/threads.h>
|
|
||||||
#include <linux/fs.h>
|
|
||||||
#include <asm/addrspace.h>
|
|
||||||
#include <asm/page.h>
|
|
||||||
#include <asm/pgtable.h>
|
|
||||||
#include <asm/processor.h>
|
|
||||||
#include <asm/cache.h>
|
|
||||||
#include <asm/io.h>
|
|
||||||
#include <asm/uaccess.h>
|
|
||||||
#include <asm/pgalloc.h>
|
|
||||||
#include <asm/mmu_context.h>
|
|
||||||
#include <asm/cacheflush.h>
|
|
||||||
|
|
||||||
static void __flush_purge_virtual_region(void *p1, void *virt, int size)
|
|
||||||
{
|
|
||||||
unsigned long v;
|
|
||||||
unsigned long begin, end;
|
|
||||||
unsigned long p1_begin;
|
|
||||||
|
|
||||||
|
|
||||||
begin = L1_CACHE_ALIGN((unsigned long)virt);
|
|
||||||
end = L1_CACHE_ALIGN((unsigned long)virt + size);
|
|
||||||
|
|
||||||
p1_begin = (unsigned long)p1 & ~(L1_CACHE_BYTES - 1);
|
|
||||||
|
|
||||||
/* do this the slow way as we may not have TLB entries
|
|
||||||
* for virt yet. */
|
|
||||||
for (v = begin; v < end; v += L1_CACHE_BYTES) {
|
|
||||||
unsigned long p;
|
|
||||||
unsigned long ways, addr;
|
|
||||||
|
|
||||||
p = __pa(p1_begin);
|
|
||||||
|
|
||||||
ways = current_cpu_data.dcache.ways;
|
|
||||||
addr = CACHE_OC_ADDRESS_ARRAY;
|
|
||||||
|
|
||||||
do {
|
|
||||||
unsigned long data;
|
|
||||||
|
|
||||||
addr |= (v & current_cpu_data.dcache.entry_mask);
|
|
||||||
|
|
||||||
data = ctrl_inl(addr);
|
|
||||||
if ((data & CACHE_PHYSADDR_MASK) ==
|
|
||||||
(p & CACHE_PHYSADDR_MASK)) {
|
|
||||||
data &= ~(SH_CACHE_UPDATED|SH_CACHE_VALID);
|
|
||||||
ctrl_outl(data, addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
addr += current_cpu_data.dcache.way_incr;
|
|
||||||
} while (--ways);
|
|
||||||
|
|
||||||
p1_begin += L1_CACHE_BYTES;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* clear_user_page
|
|
||||||
* @to: P1 address
|
|
||||||
* @address: U0 address to be mapped
|
|
||||||
*/
|
|
||||||
void clear_user_page(void *to, unsigned long address, struct page *pg)
|
|
||||||
{
|
|
||||||
if (pages_do_alias(address, (unsigned long)to))
|
|
||||||
__flush_purge_virtual_region(to,
|
|
||||||
(void *)(address & 0xfffff000),
|
|
||||||
PAGE_SIZE);
|
|
||||||
|
|
||||||
clear_page(to);
|
|
||||||
__flush_wback_region(to, PAGE_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* copy_user_page
|
|
||||||
* @to: P1 address
|
|
||||||
* @from: P1 address
|
|
||||||
* @address: U0 address to be mapped
|
|
||||||
*/
|
|
||||||
void copy_user_page(void *to, void *from, unsigned long address, struct page *pg)
|
|
||||||
{
|
|
||||||
if (pages_do_alias(address, (unsigned long)to))
|
|
||||||
__flush_purge_virtual_region(to,
|
|
||||||
(void *)(address & 0xfffff000),
|
|
||||||
PAGE_SIZE);
|
|
||||||
|
|
||||||
copy_page(to, from);
|
|
||||||
__flush_wback_region(to, PAGE_SIZE);
|
|
||||||
}
|
|
Reference in New Issue
Block a user