diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2008-10-31 11:08:35 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2008-11-27 18:53:47 -0500 |
commit | 063b0a4207e43acbeff3d4b09f43e750e0212b48 (patch) | |
tree | eb2a2c1faa732c763102040478830111fc13f2a5 /arch/arm/mm/copypage-v4mc.c | |
parent | d73e60b7144a86baf0fdfcc9537a70bb4f72e11c (diff) |
[ARM] copypage: provide our own copy_user_highpage()
We used to override the copy_user_page() function. However, this
is not only inefficient, it also causes additional complexity for
highmem support, since we convert from a struct page to a kernel
direct mapped address and back to a struct page again.
Moreover, with highmem support, we end up pointlessly setting up
kmap entries for pages which we're going to remap. So, push the
kmapping down into the copypage implementation files where it's
required.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mm/copypage-v4mc.c')
-rw-r--r-- | arch/arm/mm/copypage-v4mc.c | 21 |
1 files changed, 12 insertions, 9 deletions
diff --git a/arch/arm/mm/copypage-v4mc.c b/arch/arm/mm/copypage-v4mc.c index 8d33e2549344..a7dc838fee76 100644 --- a/arch/arm/mm/copypage-v4mc.c +++ b/arch/arm/mm/copypage-v4mc.c | |||
@@ -15,8 +15,8 @@ | |||
15 | */ | 15 | */ |
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/mm.h> | 17 | #include <linux/mm.h> |
18 | #include <linux/highmem.h> | ||
18 | 19 | ||
19 | #include <asm/page.h> | ||
20 | #include <asm/pgtable.h> | 20 | #include <asm/pgtable.h> |
21 | #include <asm/tlbflush.h> | 21 | #include <asm/tlbflush.h> |
22 | #include <asm/cacheflush.h> | 22 | #include <asm/cacheflush.h> |
@@ -33,7 +33,7 @@ | |||
33 | static DEFINE_SPINLOCK(minicache_lock); | 33 | static DEFINE_SPINLOCK(minicache_lock); |
34 | 34 | ||
35 | /* | 35 | /* |
36 | * ARMv4 mini-dcache optimised copy_user_page | 36 | * ARMv4 mini-dcache optimised copy_user_highpage |
37 | * | 37 | * |
38 | * We flush the destination cache lines just before we write the data into the | 38 | * We flush the destination cache lines just before we write the data into the |
39 | * corresponding address. Since the Dcache is read-allocate, this removes the | 39 | * corresponding address. Since the Dcache is read-allocate, this removes the |
@@ -42,7 +42,7 @@ static DEFINE_SPINLOCK(minicache_lock); | |||
42 | * | 42 | * |
43 | * Note: We rely on all ARMv4 processors implementing the "invalidate D line" | 43 | * Note: We rely on all ARMv4 processors implementing the "invalidate D line" |
44 | * instruction. If your processor does not supply this, you have to write your | 44 | * instruction. If your processor does not supply this, you have to write your |
45 | * own copy_user_page that does the right thing. | 45 | * own copy_user_highpage that does the right thing. |
46 | */ | 46 | */ |
47 | static void __attribute__((naked)) | 47 | static void __attribute__((naked)) |
48 | mc_copy_user_page(void *from, void *to) | 48 | mc_copy_user_page(void *from, void *to) |
@@ -68,21 +68,24 @@ mc_copy_user_page(void *from, void *to) | |||
68 | : "r" (from), "r" (to), "I" (PAGE_SIZE / 64)); | 68 | : "r" (from), "r" (to), "I" (PAGE_SIZE / 64)); |
69 | } | 69 | } |
70 | 70 | ||
71 | void v4_mc_copy_user_page(void *kto, const void *kfrom, unsigned long vaddr) | 71 | void v4_mc_copy_user_highpage(struct page *from, struct page *to, |
72 | unsigned long vaddr) | ||
72 | { | 73 | { |
73 | struct page *page = virt_to_page(kfrom); | 74 | void *kto = kmap_atomic(to, KM_USER1); |
74 | 75 | ||
75 | if (test_and_clear_bit(PG_dcache_dirty, &page->flags)) | 76 | if (test_and_clear_bit(PG_dcache_dirty, &from->flags)) |
76 | __flush_dcache_page(page_mapping(page), page); | 77 | __flush_dcache_page(page_mapping(from), from); |
77 | 78 | ||
78 | spin_lock(&minicache_lock); | 79 | spin_lock(&minicache_lock); |
79 | 80 | ||
80 | set_pte_ext(TOP_PTE(0xffff8000), pfn_pte(__pa(kfrom) >> PAGE_SHIFT, minicache_pgprot), 0); | 81 | set_pte_ext(TOP_PTE(0xffff8000), pfn_pte(page_to_pfn(from), minicache_pgprot), 0); |
81 | flush_tlb_kernel_page(0xffff8000); | 82 | flush_tlb_kernel_page(0xffff8000); |
82 | 83 | ||
83 | mc_copy_user_page((void *)0xffff8000, kto); | 84 | mc_copy_user_page((void *)0xffff8000, kto); |
84 | 85 | ||
85 | spin_unlock(&minicache_lock); | 86 | spin_unlock(&minicache_lock); |
87 | |||
88 | kunmap_atomic(kto, KM_USER1); | ||
86 | } | 89 | } |
87 | 90 | ||
88 | /* | 91 | /* |
@@ -113,5 +116,5 @@ v4_mc_clear_user_page(void *kaddr, unsigned long vaddr) | |||
113 | 116 | ||
114 | struct cpu_user_fns v4_mc_user_fns __initdata = { | 117 | struct cpu_user_fns v4_mc_user_fns __initdata = { |
115 | .cpu_clear_user_page = v4_mc_clear_user_page, | 118 | .cpu_clear_user_page = v4_mc_clear_user_page, |
116 | .cpu_copy_user_page = v4_mc_copy_user_page, | 119 | .cpu_copy_user_highpage = v4_mc_copy_user_highpage, |
117 | }; | 120 | }; |