ia64/xen-unstable

changeset 2438:f084fe1dc76b

bitkeeper revision 1.1159.69.20 (413c7829P-RU1PkUqzwGG3rQ_fI5Qg)

Manage L1 pagetables in a kmem_cache, which allows us to keep the
pages pinned while they are not used.
author cl349@freefall.cl.cam.ac.uk
date Mon Sep 06 14:46:01 2004 +0000 (2004-09-06)
parents 07ee497a8090
children aed97013f9fe 2bbaf6d19a35
files linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/init.c linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/pgtable.c linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/pgalloc.h linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/pgtable.h
line diff
     1.1 --- a/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/init.c	Mon Sep 06 09:32:48 2004 +0000
     1.2 +++ b/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/init.c	Mon Sep 06 14:46:01 2004 +0000
     1.3 @@ -726,9 +726,18 @@ void __init mem_init(void)
     1.4  
     1.5  kmem_cache_t *pgd_cache;
     1.6  kmem_cache_t *pmd_cache;
     1.7 +kmem_cache_t *pte_cache;
     1.8  
     1.9  void __init pgtable_cache_init(void)
    1.10  {
    1.11 +	pte_cache = kmem_cache_create("pte",
    1.12 +				PTRS_PER_PTE*sizeof(pte_t),
    1.13 +				PTRS_PER_PTE*sizeof(pte_t),
    1.14 +				0,
    1.15 +				pte_ctor,
    1.16 +				pte_dtor);
    1.17 +	if (!pte_cache)
    1.18 +		panic("pgtable_cache_init(): Cannot create pte cache");
    1.19  	if (PTRS_PER_PMD > 1) {
    1.20  		pmd_cache = kmem_cache_create("pmd",
    1.21  					PTRS_PER_PMD*sizeof(pmd_t),
     2.1 --- a/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/pgtable.c	Mon Sep 06 09:32:48 2004 +0000
     2.2 +++ b/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/pgtable.c	Mon Sep 06 14:46:01 2004 +0000
     2.3 @@ -185,32 +185,44 @@ pte_t *pte_alloc_one_kernel(struct mm_st
     2.4  	return pte;
     2.5  }
     2.6  
     2.7 +void pte_ctor(void *pte, kmem_cache_t *cache, unsigned long unused)
     2.8 +{
     2.9 +
    2.10 +	clear_page(pte);
    2.11 +	__make_page_readonly(pte);
    2.12 +	queue_pte_pin(virt_to_phys(pte));
    2.13 +	flush_page_update_queue();
    2.14 +}
    2.15 +
    2.16 +void pte_dtor(void *pte, kmem_cache_t *cache, unsigned long unused)
    2.17 +{
    2.18 +
    2.19 +	queue_pte_unpin(virt_to_phys(pte));
    2.20 +	__make_page_writable(pte);
    2.21 +	flush_page_update_queue();
    2.22 +}
    2.23 +
    2.24  struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
    2.25  {
    2.26 -	struct page *pte;
    2.27 +	pte_t *ptep;
    2.28  
    2.29  #ifdef CONFIG_HIGHPTE
    2.30 +	struct page *pte;
    2.31 +
    2.32  	pte = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM|__GFP_REPEAT, 0);
    2.33 -#else
    2.34 -	pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0);
    2.35 -#endif
    2.36 -	if (pte) {
    2.37 -#ifdef CONFIG_HIGHPTE
    2.38 -		void *kaddr = kmap_atomic(pte, KM_USER0);
    2.39 -		clear_page(kaddr);
    2.40 -		kunmap_atomic_force(kaddr, KM_USER0);
    2.41 -#else
    2.42 +	if (pte == NULL)
    2.43 +		return pte;
    2.44 +	if (pte >= highmem_start_page) {
    2.45  		clear_highpage(pte);
    2.46 -#endif
    2.47 -#ifdef CONFIG_HIGHPTE
    2.48 -		if (pte < highmem_start_page)
    2.49 +		return pte;
    2.50 +	}
    2.51 +	/* not a highmem page -- free page and grab one from the cache */
    2.52 +	__free_page(pte);
    2.53  #endif
    2.54 -		{
    2.55 -			__make_page_readonly(phys_to_virt(page_to_pseudophys(pte)));
    2.56 -			flush_page_update_queue();
    2.57 -		}
    2.58 -	}
    2.59 -	return pte;
    2.60 +	ptep = kmem_cache_alloc(pte_cache, GFP_KERNEL);
    2.61 +	if (ptep)
    2.62 +		return virt_to_page(ptep);
    2.63 +	return NULL;
    2.64  }
    2.65  
    2.66  void pmd_ctor(void *pmd, kmem_cache_t *cache, unsigned long flags)
     3.1 --- a/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/pgalloc.h	Mon Sep 06 09:32:48 2004 +0000
     3.2 +++ b/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/pgalloc.h	Mon Sep 06 14:46:01 2004 +0000
     3.3 @@ -41,19 +41,16 @@ static inline void pte_free(struct page 
     3.4  #ifdef CONFIG_HIGHPTE
     3.5  	if (pte < highmem_start_page)
     3.6  #endif
     3.7 -	{
     3.8 -		__make_page_writable(phys_to_virt(page_to_pseudophys(pte)));
     3.9 +		kmem_cache_free(pte_cache,
    3.10 +				phys_to_virt(page_to_pseudophys(pte)));
    3.11 +#ifdef CONFIG_HIGHPTE
    3.12 +	else
    3.13  		__free_page(pte);
    3.14 -		flush_page_update_queue();
    3.15 -	}
    3.16 +#endif
    3.17  }
    3.18  
    3.19  
    3.20 -#define __pte_free_tlb(tlb,pte) do {			\
    3.21 -	tlb_remove_page((tlb),(pte));			\
    3.22 -	flush_page_update_queue();			\
    3.23 -	/* XXXcl queue */ \
    3.24 -} while (0)
    3.25 +#define __pte_free_tlb(tlb,pte)		pte_free(pte)
    3.26  
    3.27  /*
    3.28   * allocating and freeing a pmd is trivial: the 1-entry pmd is
     4.1 --- a/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/pgtable.h	Mon Sep 06 09:32:48 2004 +0000
     4.2 +++ b/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/pgtable.h	Mon Sep 06 14:46:01 2004 +0000
     4.3 @@ -35,9 +35,12 @@ extern unsigned long empty_zero_page[102
     4.4  extern pgd_t swapper_pg_dir[1024];
     4.5  extern kmem_cache_t *pgd_cache;
     4.6  extern kmem_cache_t *pmd_cache;
     4.7 +extern kmem_cache_t *pte_cache;
     4.8  extern spinlock_t pgd_lock;
     4.9  extern struct page *pgd_list;
    4.10  
    4.11 +void pte_ctor(void *, kmem_cache_t *, unsigned long);
    4.12 +void pte_dtor(void *, kmem_cache_t *, unsigned long);
    4.13  void pmd_ctor(void *, kmem_cache_t *, unsigned long);
    4.14  void pgd_ctor(void *, kmem_cache_t *, unsigned long);
    4.15  void pgd_dtor(void *, kmem_cache_t *, unsigned long);
    4.16 @@ -315,9 +318,7 @@ static inline pte_t pte_modify(pte_t pte
    4.17  ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
    4.18  
    4.19  #define pmd_clear(xp)	do {					\
    4.20 -	pmd_t p = *(xp);					\
    4.21  	set_pmd(xp, __pmd(0));					\
    4.22 -	__make_page_writable((void *)pmd_page_kernel(p));	\
    4.23  	xen_flush_page_update_queue();				\
    4.24  } while (0)
    4.25