Commit 7ef939054139ef857cebbec07cbd12d7cf7beedd
Committed by
Linus Torvalds
1 parent
f9dfefe423
Exists in
master
and in
7 other branches
[PATCH] uml: fix x86_64 page leak
We were leaking pmd pages when 3_LEVEL_PGTABLES was enabled. This fixes that. Signed-off-by: Jeff Dike <jdike@addtoit.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Showing 4 changed files with 22 additions and 12 deletions Side-by-side Diff
arch/um/kernel/skas/include/mmu-skas.h
... | ... | @@ -6,11 +6,15 @@ |
6 | 6 | #ifndef __SKAS_MMU_H |
7 | 7 | #define __SKAS_MMU_H |
8 | 8 | |
9 | +#include "linux/config.h" | |
9 | 10 | #include "mm_id.h" |
10 | 11 | |
11 | 12 | struct mmu_context_skas { |
12 | 13 | struct mm_id id; |
13 | 14 | unsigned long last_page_table; |
15 | +#ifdef CONFIG_3_LEVEL_PGTABLES | |
16 | + unsigned long last_pmd; | |
17 | +#endif | |
14 | 18 | }; |
15 | 19 | |
16 | 20 | extern void switch_mm_skas(struct mm_id * mm_idp); |
arch/um/kernel/skas/mmu.c
... | ... | @@ -56,6 +56,9 @@ |
56 | 56 | */ |
57 | 57 | |
58 | 58 | mm->context.skas.last_page_table = pmd_page_kernel(*pmd); |
59 | +#ifdef CONFIG_3_LEVEL_PGTABLES | |
60 | + mm->context.skas.last_pmd = (unsigned long) __va(pud_val(*pud)); | |
61 | +#endif | |
59 | 62 | |
60 | 63 | *pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT)); |
61 | 64 | *pte = pte_mkexec(*pte); |
... | ... | @@ -144,7 +147,11 @@ |
144 | 147 | |
145 | 148 | if(!proc_mm || !ptrace_faultinfo){ |
146 | 149 | free_page(mmu->id.stack); |
147 | - free_page(mmu->last_page_table); | |
150 | + pte_free_kernel((pte_t *) mmu->last_page_table); | |
151 | + dec_page_state(nr_page_table_pages); | |
152 | +#ifdef CONFIG_3_LEVEL_PGTABLES | |
153 | + pmd_free((pmd_t *) mmu->last_pmd); | |
154 | +#endif | |
148 | 155 | } |
149 | 156 | } |
include/asm-um/pgalloc.h
... | ... | @@ -42,11 +42,13 @@ |
42 | 42 | #define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte)) |
43 | 43 | |
44 | 44 | #ifdef CONFIG_3_LEVEL_PGTABLES |
45 | -/* | |
46 | - * In the 3-level case we free the pmds as part of the pgd. | |
47 | - */ | |
48 | -#define pmd_free(x) do { } while (0) | |
49 | -#define __pmd_free_tlb(tlb,x) do { } while (0) | |
45 | + | |
46 | +extern __inline__ void pmd_free(pmd_t *pmd) | |
47 | +{ | |
48 | + free_page((unsigned long)pmd); | |
49 | +} | |
50 | + | |
51 | +#define __pmd_free_tlb(tlb,x) tlb_remove_page((tlb),virt_to_page(x)) | |
50 | 52 | #endif |
51 | 53 | |
52 | 54 | #define check_pgt_cache() do { } while (0) |
include/asm-um/pgtable-3level.h
... | ... | @@ -69,13 +69,10 @@ |
69 | 69 | return pmd; |
70 | 70 | } |
71 | 71 | |
72 | -static inline void pmd_free(pmd_t *pmd){ | |
73 | - free_page((unsigned long) pmd); | |
72 | +extern inline void pud_clear (pud_t *pud) | |
73 | +{ | |
74 | + set_pud(pud, __pud(0)); | |
74 | 75 | } |
75 | - | |
76 | -#define __pmd_free_tlb(tlb,x) do { } while (0) | |
77 | - | |
78 | -static inline void pud_clear (pud_t * pud) { } | |
79 | 76 | |
80 | 77 | #define pud_page(pud) \ |
81 | 78 | ((struct page *) __va(pud_val(pud) & PAGE_MASK)) |