Messages in this thread Patch in this message | | | From | "Fenghua Yu" <> | Subject | [PATCH] X86-32: Allocate 256 bytes for pgd in PAE paging | Date | Tue, 16 Dec 2014 18:45:31 -0800 |
| |
From: Fenghua Yu <fenghua.yu@intel.com>
X86 32-bit machine and kernel use PAE paging, which currently wastes about 4K of memory per process on Linux where we have to reserve an entire page to support a single 256-byte PGD structure. It would be a very good thing if we could eliminate that wastage.
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com> --- arch/x86/mm/pgtable.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c index 6fb6927..e75f923 100644 --- a/arch/x86/mm/pgtable.c +++ b/arch/x86/mm/pgtable.c @@ -1,5 +1,6 @@ #include <linux/mm.h> #include <linux/gfp.h> +#include <linux/slab.h> #include <asm/pgalloc.h> #include <asm/pgtable.h> #include <asm/tlb.h> @@ -276,7 +277,27 @@ pgd_t *pgd_alloc(struct mm_struct *mm) pgd_t *pgd; pmd_t *pmds[PREALLOCATED_PMDS]; + /* + * Xen paravirt assumes pgd table should be in one page. pgd in + * 64 bit also needs to be in one page. + * + * But PAE without Xen only needs to allocate 256 bytes for pgd. + * + * So if kernel is compiled as PAE model without Xen, we allocate + * 256 bytes for pgd entries to save memory space. + * + * In other cases, one page is allocated for pgd. In theory, a kernel + * in PAE mode not running in Xen could allocate 256 bytes for pgd + * as well. But that will make the allocation and free more complex + * but not useful in reality. To simplify the code and testing, we just + * allocate one page when CONFIG_XEN is enabled regardelss kernel + * is running in Xen or not. + */ +#if defined(CONFIG_X86_PAE) && !defined(CONFIG_XEN) + pgd = kmalloc(sizeof(pgdval_t) * PTRS_PER_PGD, PGALLOC_GFP); +#else pgd = (pgd_t *)__get_free_page(PGALLOC_GFP); +#endif if (pgd == NULL) goto out; @@ -306,7 +327,11 @@ pgd_t *pgd_alloc(struct mm_struct *mm) out_free_pmds: free_pmds(pmds); out_free_pgd: +#if defined(CONFIG_X86_PAE) && !defined(CONFIG_XEN) + kfree(pgd); +#else free_page((unsigned long)pgd); +#endif out: return NULL; } @@ -316,7 +341,12 @@ void pgd_free(struct mm_struct *mm, pgd_t *pgd) pgd_mop_up_pmds(mm, pgd); pgd_dtor(pgd); paravirt_pgd_free(mm, pgd); +#if defined(CONFIG_X86_PAE) && !defined(CONFIG_XEN) + kfree(pgd); +#else free_page((unsigned long)pgd); +#endif + } /* -- 1.8.1.2
| |