diff options
Diffstat (limited to 'include/asm-x86_64/pgalloc.h')
-rw-r--r-- | include/asm-x86_64/pgalloc.h | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/include/asm-x86_64/pgalloc.h b/include/asm-x86_64/pgalloc.h index 08cad2482bcb..43d4c333a8b1 100644 --- a/include/asm-x86_64/pgalloc.h +++ b/include/asm-x86_64/pgalloc.h | |||
@@ -45,12 +45,39 @@ static inline void pud_free (pud_t *pud) | |||
45 | free_page((unsigned long)pud); | 45 | free_page((unsigned long)pud); |
46 | } | 46 | } |
47 | 47 | ||
48 | static inline void pgd_list_add(pgd_t *pgd) | ||
49 | { | ||
50 | struct page *page = virt_to_page(pgd); | ||
51 | |||
52 | spin_lock(&pgd_lock); | ||
53 | page->index = (pgoff_t)pgd_list; | ||
54 | if (pgd_list) | ||
55 | pgd_list->private = (unsigned long)&page->index; | ||
56 | pgd_list = page; | ||
57 | page->private = (unsigned long)&pgd_list; | ||
58 | spin_unlock(&pgd_lock); | ||
59 | } | ||
60 | |||
61 | static inline void pgd_list_del(pgd_t *pgd) | ||
62 | { | ||
63 | struct page *next, **pprev, *page = virt_to_page(pgd); | ||
64 | |||
65 | spin_lock(&pgd_lock); | ||
66 | next = (struct page *)page->index; | ||
67 | pprev = (struct page **)page->private; | ||
68 | *pprev = next; | ||
69 | if (next) | ||
70 | next->private = (unsigned long)pprev; | ||
71 | spin_unlock(&pgd_lock); | ||
72 | } | ||
73 | |||
48 | static inline pgd_t *pgd_alloc(struct mm_struct *mm) | 74 | static inline pgd_t *pgd_alloc(struct mm_struct *mm) |
49 | { | 75 | { |
50 | unsigned boundary; | 76 | unsigned boundary; |
51 | pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT); | 77 | pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT); |
52 | if (!pgd) | 78 | if (!pgd) |
53 | return NULL; | 79 | return NULL; |
80 | pgd_list_add(pgd); | ||
54 | /* | 81 | /* |
55 | * Copy kernel pointers in from init. | 82 | * Copy kernel pointers in from init. |
56 | * Could keep a freelist or slab cache of those because the kernel | 83 | * Could keep a freelist or slab cache of those because the kernel |
@@ -67,6 +94,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm) | |||
67 | static inline void pgd_free(pgd_t *pgd) | 94 | static inline void pgd_free(pgd_t *pgd) |
68 | { | 95 | { |
69 | BUG_ON((unsigned long)pgd & (PAGE_SIZE-1)); | 96 | BUG_ON((unsigned long)pgd & (PAGE_SIZE-1)); |
97 | pgd_list_del(pgd); | ||
70 | free_page((unsigned long)pgd); | 98 | free_page((unsigned long)pgd); |
71 | } | 99 | } |
72 | 100 | ||