blob: 4a707268d7cd1cb1e6a7349b99567ea781a054b8 [file] [log] [blame]
/*
* Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/sched.h>
#include <linux/mm.h>
#include <asm/cacheflush.h> /* for flush_dcache_page_virt */
#include <linux/module.h>
#ifndef NONINLINE_MEMSET
/* page functions */
void copy_page(void *to, void *from)
{
unsigned long reg1, reg2, reg3, reg4;
__asm__ __volatile__(
"mov lp_count,%6\n"
"lp 1f\n"
"ld.ab %0, [%5, 4]\n\t"
"ld.ab %1, [%5, 4]\n\t"
"ld.ab %2, [%5, 4]\n\t"
"ld.ab %3, [%5, 4]\n\t"
"st.ab %0, [%4, 4]\n\t"
"st.ab %1, [%4, 4]\n\t"
"st.ab %2, [%4, 4]\n\t"
"st.ab %3, [%4, 4]\n\t"
"1:\n"
:"=&r"(reg1), "=&r"(reg2), "=&r"(reg3), "=&r"(reg4)
:"r"(to), "r"(from), "ir"(PAGE_SIZE/4/4)
:"lp_count"
);
}
EXPORT_SYMBOL(copy_page);
/* Initialize the new pgd with invalid ptes */
void pgd_init(unsigned long page)
{
int zero = 0;
unsigned long dummy1, dummy2;
__asm__ __volatile__("sub %0, %0, 4\n\t"
"1:\n\t"
"st.a %2, [%0, 4]\n\t"
"st.a %2, [%0, 4]\n\t"
"st.a %2, [%0, 4]\n\t"
"st.a %2, [%0, 4]\n\t"
"st.a %2, [%0, 4]\n\t"
"st.a %2, [%0, 4]\n\t"
"st.a %2, [%0, 4]\n\t"
"st.a %2, [%0, 4]\n\t"
"sub.f %1, %1, 1\n\t"
"nop \n\t"
"bnz 1b\n\t":"=r"(dummy1), "=r"(dummy2)
:"r"(zero), "0"(page), "1"(USER_PTRS_PER_PGD / 8)
);
}
#else
void copy_page(void *to, void *from)
{
memcpy(to, from, PAGE_SIZE);
}
void pgd_init(unsigned long page)
{
memzero((void *)page, USER_PTRS_PER_PGD*4);
}
#endif
void clear_user_page(void *addr, unsigned long vaddr, struct page *page)
{
clear_page(addr);
if (cpuinfo_arc700[0].dcache.has_aliasing)
flush_dcache_page_virt((unsigned long *)page);
}
void copy_user_page(void *vto, void *vfrom, unsigned long vaddr, struct page *to)
{
copy_page(vto,vfrom);
if (cpuinfo_arc700[0].dcache.has_aliasing)
flush_dcache_page_virt((unsigned long*)vto);
}