|
|
|
@ -9,6 +9,8 @@ |
|
|
|
|
#include <linux/mm.h> |
|
|
|
|
#include <linux/mutex.h> |
|
|
|
|
#include <linux/fs.h> |
|
|
|
|
#include <linux/highmem.h> |
|
|
|
|
#include <linux/module.h> |
|
|
|
|
#include <asm/mmu_context.h> |
|
|
|
|
#include <asm/cacheflush.h> |
|
|
|
|
|
|
|
|
@ -50,34 +52,61 @@ static inline void kunmap_coherent(struct page *page) |
|
|
|
|
void clear_user_page(void *to, unsigned long address, struct page *page) |
|
|
|
|
{ |
|
|
|
|
__set_bit(PG_mapped, &page->flags); |
|
|
|
|
if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) |
|
|
|
|
clear_page(to); |
|
|
|
|
else { |
|
|
|
|
void *vto = kmap_coherent(page, address); |
|
|
|
|
__clear_user_page(vto, to); |
|
|
|
|
kunmap_coherent(vto); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
clear_page(to); |
|
|
|
|
if ((((address & PAGE_MASK) ^ (unsigned long)to) & CACHE_ALIAS)) |
|
|
|
|
__flush_wback_region(to, PAGE_SIZE); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* copy_user_page |
|
|
|
|
* @to: P1 address |
|
|
|
|
* @from: P1 address |
|
|
|
|
* @address: U0 address to be mapped |
|
|
|
|
* @page: page (virt_to_page(to)) |
|
|
|
|
*/ |
|
|
|
|
void copy_user_page(void *to, void *from, unsigned long address, |
|
|
|
|
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 len) |
|
|
|
|
{ |
|
|
|
|
void *vto; |
|
|
|
|
|
|
|
|
|
__set_bit(PG_mapped, &page->flags); |
|
|
|
|
if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) |
|
|
|
|
copy_page(to, from); |
|
|
|
|
else { |
|
|
|
|
void *vfrom = kmap_coherent(page, address); |
|
|
|
|
__copy_user_page(vfrom, from, to); |
|
|
|
|
kunmap_coherent(vfrom); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); |
|
|
|
|
memcpy(vto, src, len); |
|
|
|
|
kunmap_coherent(vto); |
|
|
|
|
|
|
|
|
|
if (vma->vm_flags & VM_EXEC) |
|
|
|
|
flush_cache_page(vma, vaddr, page_to_pfn(page)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void copy_from_user_page(struct vm_area_struct *vma, struct page *page, |
|
|
|
|
unsigned long vaddr, void *dst, const void *src, |
|
|
|
|
unsigned long len) |
|
|
|
|
{ |
|
|
|
|
void *vfrom; |
|
|
|
|
|
|
|
|
|
__set_bit(PG_mapped, &page->flags); |
|
|
|
|
|
|
|
|
|
vfrom = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); |
|
|
|
|
memcpy(dst, vfrom, len); |
|
|
|
|
kunmap_coherent(vfrom); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void copy_user_highpage(struct page *to, struct page *from, |
|
|
|
|
unsigned long vaddr, struct vm_area_struct *vma) |
|
|
|
|
{ |
|
|
|
|
void *vfrom, *vto; |
|
|
|
|
|
|
|
|
|
__set_bit(PG_mapped, &to->flags); |
|
|
|
|
|
|
|
|
|
vto = kmap_atomic(to, KM_USER1); |
|
|
|
|
vfrom = kmap_coherent(from, vaddr); |
|
|
|
|
copy_page(vto, vfrom); |
|
|
|
|
kunmap_coherent(vfrom); |
|
|
|
|
|
|
|
|
|
if (((vaddr ^ (unsigned long)vto) & CACHE_ALIAS)) |
|
|
|
|
__flush_wback_region(vto, PAGE_SIZE); |
|
|
|
|
|
|
|
|
|
kunmap_atomic(vto, KM_USER1); |
|
|
|
|
/* Make sure this page is cleared on other CPU's too before using it */ |
|
|
|
|
smp_wmb(); |
|
|
|
|
} |
|
|
|
|
EXPORT_SYMBOL(copy_user_highpage); |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* For SH-4, we have our own implementation for ptep_get_and_clear |
|
|
|
|