Commit | Line | Data |
---|---|---|
5f97f7f9 HS |
1 | /* |
2 | * Copyright (C) 2004-2006 Atmel Corporation | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License version 2 as | |
6 | * published by the Free Software Foundation. | |
7 | */ | |
8 | #ifndef __ASM_AVR32_PGALLOC_H | |
9 | #define __ASM_AVR32_PGALLOC_H | |
10 | ||
6cb8e872 | 11 | #include <linux/mm.h> |
5a4d5292 HS |
12 | #include <linux/quicklist.h> |
13 | #include <asm/page.h> | |
14 | #include <asm/pgtable.h> | |
15 | ||
16 | #define QUICK_PGD 0 /* Preserve kernel mappings over free */ | |
38510754 | 17 | #define QUICK_PT 1 /* Zero on free */ |
5f97f7f9 | 18 | |
cfd23e93 HS |
19 | static inline void pmd_populate_kernel(struct mm_struct *mm, |
20 | pmd_t *pmd, pte_t *pte) | |
21 | { | |
22 | set_pmd(pmd, __pmd((unsigned long)pte)); | |
23 | } | |
5f97f7f9 | 24 | |
cfd23e93 | 25 | static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, |
2f569afd | 26 | pgtable_t pte) |
5f97f7f9 | 27 | { |
cfd23e93 | 28 | set_pmd(pmd, __pmd((unsigned long)page_address(pte))); |
5f97f7f9 | 29 | } |
2f569afd | 30 | #define pmd_pgtable(pmd) pmd_page(pmd) |
5f97f7f9 | 31 | |
5a4d5292 HS |
32 | static inline void pgd_ctor(void *x) |
33 | { | |
34 | pgd_t *pgd = x; | |
35 | ||
36 | memcpy(pgd + USER_PTRS_PER_PGD, | |
37 | swapper_pg_dir + USER_PTRS_PER_PGD, | |
38 | (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); | |
39 | } | |
40 | ||
5f97f7f9 HS |
41 | /* |
42 | * Allocate and free page tables | |
43 | */ | |
cfd23e93 | 44 | static inline pgd_t *pgd_alloc(struct mm_struct *mm) |
5f97f7f9 | 45 | { |
32d6bd90 | 46 | return quicklist_alloc(QUICK_PGD, GFP_KERNEL, pgd_ctor); |
5f97f7f9 HS |
47 | } |
48 | ||
5e541973 | 49 | static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) |
5f97f7f9 | 50 | { |
5a4d5292 | 51 | quicklist_free(QUICK_PGD, NULL, pgd); |
5f97f7f9 HS |
52 | } |
53 | ||
54 | static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, | |
55 | unsigned long address) | |
56 | { | |
32d6bd90 | 57 | return quicklist_alloc(QUICK_PT, GFP_KERNEL, NULL); |
5f97f7f9 HS |
58 | } |
59 | ||
38510754 | 60 | static inline pgtable_t pte_alloc_one(struct mm_struct *mm, |
5f97f7f9 HS |
61 | unsigned long address) |
62 | { | |
38510754 HS |
63 | struct page *page; |
64 | void *pg; | |
5f97f7f9 | 65 | |
32d6bd90 | 66 | pg = quicklist_alloc(QUICK_PT, GFP_KERNEL, NULL); |
38510754 | 67 | if (!pg) |
2f569afd | 68 | return NULL; |
38510754 HS |
69 | |
70 | page = virt_to_page(pg); | |
2cb6182b KS |
71 | if (!pgtable_page_ctor(page)) { |
72 | quicklist_free(QUICK_PT, NULL, pg); | |
73 | return NULL; | |
74 | } | |
38510754 HS |
75 | |
76 | return page; | |
5f97f7f9 HS |
77 | } |
78 | ||
5e541973 | 79 | static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) |
5f97f7f9 | 80 | { |
38510754 | 81 | quicklist_free(QUICK_PT, NULL, pte); |
5f97f7f9 HS |
82 | } |
83 | ||
2f569afd | 84 | static inline void pte_free(struct mm_struct *mm, pgtable_t pte) |
5f97f7f9 | 85 | { |
2f569afd | 86 | pgtable_page_dtor(pte); |
38510754 | 87 | quicklist_free_page(QUICK_PT, NULL, pte); |
5f97f7f9 HS |
88 | } |
89 | ||
9e1b32ca | 90 | #define __pte_free_tlb(tlb,pte,addr) \ |
2f569afd MS |
91 | do { \ |
92 | pgtable_page_dtor(pte); \ | |
93 | tlb_remove_page((tlb), pte); \ | |
94 | } while (0) | |
5f97f7f9 | 95 | |
5a4d5292 HS |
96 | static inline void check_pgt_cache(void) |
97 | { | |
98 | quicklist_trim(QUICK_PGD, NULL, 25, 16); | |
38510754 | 99 | quicklist_trim(QUICK_PT, NULL, 25, 16); |
5a4d5292 | 100 | } |
5f97f7f9 HS |
101 | |
102 | #endif /* __ASM_AVR32_PGALLOC_H */ |