diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index 329b3f3051de9d53bb5b58b7418e595d11d74e09..4688b890aef835d31db5c2dac2c0fb5d3445bfec 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c @@ -18,6 +18,7 @@ #include #include #include +#include #include static int hlt_counter; @@ -64,6 +65,7 @@ void cpu_idle(void) preempt_enable_no_resched(); schedule(); preempt_disable(); + check_pgt_cache(); } } diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig index 12f3d394dc28e97df806d7884cb92b890f681e92..b773361892c9a959b6e090355594bf7b8ecd498f 100644 --- a/arch/sh/mm/Kconfig +++ b/arch/sh/mm/Kconfig @@ -218,6 +218,9 @@ endmenu menu "Memory management options" +config QUICKLIST + def_bool y + config MMU bool "Support for memory management hardware" depends on !CPU_SH2 diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c index 4d030988b3681b3102e859d1f4464afbd23cdef8..8fe223a890ed4aaedf8947493f947041e4bed535 100644 --- a/arch/sh/mm/init.c +++ b/arch/sh/mm/init.c @@ -67,6 +67,8 @@ void show_mem(void) printk("%d slab pages\n", slab); printk("%d pages shared\n", shared); printk("%d pages swap cached\n", cached); + printk(KERN_INFO "Total of %ld pages in page table cache\n", + quicklist_total_size()); } #ifdef CONFIG_MMU diff --git a/include/asm-sh/pgalloc.h b/include/asm-sh/pgalloc.h index 888e4529e6fe3c4bb2108f134b8b7674435836c3..26e493f39dbb59212483c1c949ad714f96a48251 100644 --- a/include/asm-sh/pgalloc.h +++ b/include/asm-sh/pgalloc.h @@ -1,6 +1,12 @@ #ifndef __ASM_SH_PGALLOC_H #define __ASM_SH_PGALLOC_H +#include +#include + +#define QUICK_PGD 0 /* We preserve special mappings over free */ +#define QUICK_PT 1 /* Other page table pages that are zero on free */ + static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *pte) { @@ -13,48 +19,49 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, set_pmd(pmd, __pmd((unsigned long)page_address(pte))); } +static inline void pgd_ctor(void *x) +{ + pgd_t *pgd = x; + + memcpy(pgd + USER_PTRS_PER_PGD, + swapper_pg_dir + USER_PTRS_PER_PGD, + (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); +} + /* * Allocate and free page tables. */ static inline pgd_t *pgd_alloc(struct mm_struct *mm) { - pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT); - - if (pgd) { - memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t)); - memcpy(pgd + USER_PTRS_PER_PGD, - swapper_pg_dir + USER_PTRS_PER_PGD, - (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); - } - - return pgd; + return quicklist_alloc(QUICK_PGD, GFP_KERNEL | __GFP_REPEAT, pgd_ctor); } static inline void pgd_free(pgd_t *pgd) { - free_page((unsigned long)pgd); + quicklist_free(QUICK_PGD, NULL, pgd); } static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) { - return (pte_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO); + return quicklist_alloc(QUICK_PT, GFP_KERNEL, NULL); } static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) { - return alloc_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO); + void *pg = quicklist_alloc(QUICK_PT, GFP_KERNEL, NULL); + return pg ? virt_to_page(pg) : NULL; } static inline void pte_free_kernel(pte_t *pte) { - free_page((unsigned long)pte); + quicklist_free(QUICK_PT, NULL, pte); } static inline void pte_free(struct page *pte) { - __free_page(pte); + quicklist_free_page(QUICK_PT, NULL, pte); } #define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte)) @@ -66,6 +73,11 @@ static inline void pte_free(struct page *pte) #define pmd_free(x) do { } while (0) #define __pmd_free_tlb(tlb,x) do { } while (0) -#define check_pgt_cache() do { } while (0) + +static inline void check_pgt_cache(void) +{ + quicklist_trim(QUICK_PGD, NULL, 25, 16); + quicklist_trim(QUICK_PT, NULL, 25, 16); +} #endif /* __ASM_SH_PGALLOC_H */ diff --git a/mm/Kconfig b/mm/Kconfig index 1ac718f636ec6f5842217bd6b06c7ef0bff0dd21..a17da8bafe62758b6f0d86816d9d6c64b464e687 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -166,5 +166,5 @@ config ZONE_DMA_FLAG config NR_QUICK int depends on QUICKLIST + default "2" if SUPERH default "1" -