Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7ef93905 authored by Jeff Dike's avatar Jeff Dike Committed by Linus Torvalds
Browse files

[PATCH] uml: fix x86_64 page leak



We were leaking pmd pages when 3_LEVEL_PGTABLES was enabled.  This fixes that.

Signed-off-by: default avatarJeff Dike <jdike@addtoit.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent f9dfefe4
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -6,11 +6,15 @@
#ifndef __SKAS_MMU_H
#define __SKAS_MMU_H

#include "linux/config.h"
#include "mm_id.h"

struct mmu_context_skas {
	struct mm_id id;
        unsigned long last_page_table;
#ifdef CONFIG_3_LEVEL_PGTABLES
        unsigned long last_pmd;
#endif
};

extern void switch_mm_skas(struct mm_id * mm_idp);
+8 −1
Original line number Diff line number Diff line
@@ -56,6 +56,9 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc,
	 */

        mm->context.skas.last_page_table = pmd_page_kernel(*pmd);
#ifdef CONFIG_3_LEVEL_PGTABLES
        mm->context.skas.last_pmd = (unsigned long) __va(pud_val(*pud));
#endif

	*pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT));
	*pte = pte_mkexec(*pte);
@@ -144,6 +147,10 @@ void destroy_context_skas(struct mm_struct *mm)

	if(!proc_mm || !ptrace_faultinfo){
		free_page(mmu->id.stack);
		free_page(mmu->last_page_table);
		pte_free_kernel((pte_t *) mmu->last_page_table);
                dec_page_state(nr_page_table_pages);
#ifdef CONFIG_3_LEVEL_PGTABLES
		pmd_free((pmd_t *) mmu->last_pmd);
#endif
	}
}
+7 −5
Original line number Diff line number Diff line
@@ -42,11 +42,13 @@ static inline void pte_free(struct page *pte)
#define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte))

#ifdef CONFIG_3_LEVEL_PGTABLES
/*
 * In the 3-level case we free the pmds as part of the pgd.
 */
#define pmd_free(x)			do { } while (0)
#define __pmd_free_tlb(tlb,x)		do { } while (0)

extern __inline__ void pmd_free(pmd_t *pmd)
{
	free_page((unsigned long)pmd);
}

#define __pmd_free_tlb(tlb,x)   tlb_remove_page((tlb),virt_to_page(x))
#endif

#define check_pgt_cache()	do { } while (0)
+3 −6
Original line number Diff line number Diff line
@@ -69,14 +69,11 @@ static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
        return pmd;
}

static inline void pmd_free(pmd_t *pmd){
	free_page((unsigned long) pmd);
extern inline void pud_clear (pud_t *pud)
{
        set_pud(pud, __pud(0));
}

#define __pmd_free_tlb(tlb,x)   do { } while (0)

static inline void pud_clear (pud_t * pud) { }

#define pud_page(pud) \
	((struct page *) __va(pud_val(pud) & PAGE_MASK))