Commit 7ef939054139ef857cebbec07cbd12d7cf7beedd

Authored by Jeff Dike
Committed by Linus Torvalds
1 parent f9dfefe423

[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))