Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * arch/sh/mm/pg-sh4.c | |
3 | * | |
4 | * Copyright (C) 1999, 2000, 2002 Niibe Yutaka | |
8b395265 | 5 | * Copyright (C) 2002 - 2005 Paul Mundt |
1da177e4 LT |
6 | * |
7 | * Released under the terms of the GNU GPL v2.0. | |
8 | */ | |
1da177e4 | 9 | #include <linux/mm.h> |
52e27782 | 10 | #include <linux/mutex.h> |
1da177e4 LT |
11 | #include <asm/mmu_context.h> |
12 | #include <asm/cacheflush.h> | |
13 | ||
52e27782 | 14 | extern struct mutex p3map_mutex[]; |
1da177e4 | 15 | |
11c19656 | 16 | #define CACHE_ALIAS (current_cpu_data.dcache.alias_mask) |
8b395265 | 17 | |
1da177e4 LT |
18 | /* |
19 | * clear_user_page | |
20 | * @to: P1 address | |
21 | * @address: U0 address to be mapped | |
22 | * @page: page (virt_to_page(to)) | |
23 | */ | |
24 | void clear_user_page(void *to, unsigned long address, struct page *page) | |
25 | { | |
1da177e4 LT |
26 | if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) |
27 | clear_page(to); | |
28 | else { | |
1da177e4 LT |
29 | unsigned long phys_addr = PHYSADDR(to); |
30 | unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS); | |
8b395265 PM |
31 | pgd_t *pgd = pgd_offset_k(p3_addr); |
32 | pud_t *pud = pud_offset(pgd, p3_addr); | |
33 | pmd_t *pmd = pmd_offset(pud, p3_addr); | |
1da177e4 LT |
34 | pte_t *pte = pte_offset_kernel(pmd, p3_addr); |
35 | pte_t entry; | |
36 | unsigned long flags; | |
37 | ||
21440cf0 | 38 | entry = pfn_pte(phys_addr >> PAGE_SHIFT, PAGE_KERNEL); |
52e27782 | 39 | mutex_lock(&p3map_mutex[(address & CACHE_ALIAS)>>12]); |
1da177e4 LT |
40 | set_pte(pte, entry); |
41 | local_irq_save(flags); | |
ea9af694 | 42 | flush_tlb_one(get_asid(), p3_addr); |
1da177e4 LT |
43 | local_irq_restore(flags); |
44 | update_mmu_cache(NULL, p3_addr, entry); | |
45 | __clear_user_page((void *)p3_addr, to); | |
46 | pte_clear(&init_mm, p3_addr, pte); | |
52e27782 | 47 | mutex_unlock(&p3map_mutex[(address & CACHE_ALIAS)>>12]); |
1da177e4 LT |
48 | } |
49 | } | |
50 | ||
51 | /* | |
52 | * copy_user_page | |
53 | * @to: P1 address | |
54 | * @from: P1 address | |
55 | * @address: U0 address to be mapped | |
56 | * @page: page (virt_to_page(to)) | |
57 | */ | |
8b395265 | 58 | void copy_user_page(void *to, void *from, unsigned long address, |
1da177e4 LT |
59 | struct page *page) |
60 | { | |
1da177e4 LT |
61 | if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) |
62 | copy_page(to, from); | |
63 | else { | |
1da177e4 LT |
64 | unsigned long phys_addr = PHYSADDR(to); |
65 | unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS); | |
8b395265 PM |
66 | pgd_t *pgd = pgd_offset_k(p3_addr); |
67 | pud_t *pud = pud_offset(pgd, p3_addr); | |
68 | pmd_t *pmd = pmd_offset(pud, p3_addr); | |
1da177e4 LT |
69 | pte_t *pte = pte_offset_kernel(pmd, p3_addr); |
70 | pte_t entry; | |
71 | unsigned long flags; | |
72 | ||
21440cf0 | 73 | entry = pfn_pte(phys_addr >> PAGE_SHIFT, PAGE_KERNEL); |
52e27782 | 74 | mutex_lock(&p3map_mutex[(address & CACHE_ALIAS)>>12]); |
1da177e4 LT |
75 | set_pte(pte, entry); |
76 | local_irq_save(flags); | |
ea9af694 | 77 | flush_tlb_one(get_asid(), p3_addr); |
1da177e4 LT |
78 | local_irq_restore(flags); |
79 | update_mmu_cache(NULL, p3_addr, entry); | |
80 | __copy_user_page((void *)p3_addr, from, to); | |
81 | pte_clear(&init_mm, p3_addr, pte); | |
52e27782 | 82 | mutex_unlock(&p3map_mutex[(address & CACHE_ALIAS)>>12]); |
1da177e4 LT |
83 | } |
84 | } |