ia64/xen-unstable

changeset 8038:86964d50bcfa

Fix pgd allocation for PAE. We must handle the fact that
a PGD may get pinned under our feet by suspend/resume.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Thu Nov 24 18:19:51 2005 +0100 (2005-11-24)
parents a9fef115e8ec
children 0ec1d38f26f7
files linux-2.6-xen-sparse/arch/xen/i386/mm/pgtable.c
line diff
     1.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/mm/pgtable.c	Thu Nov 24 17:13:46 2005 +0100
     1.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/pgtable.c	Thu Nov 24 18:19:51 2005 +0100
     1.3 @@ -303,14 +303,15 @@ void pgd_dtor(void *pgd, kmem_cache_t *c
     1.4  {
     1.5  	unsigned long flags; /* can be called from interrupt context */
     1.6  
     1.7 -	BUG_ON(test_bit(PG_pinned, &virt_to_page(pgd)->flags));
     1.8 -
     1.9  	if (HAVE_SHARED_KERNEL_PMD)
    1.10  		return;
    1.11  
    1.12  	spin_lock_irqsave(&pgd_lock, flags);
    1.13  	pgd_list_del(pgd);
    1.14  	spin_unlock_irqrestore(&pgd_lock, flags);
    1.15 +
    1.16 +	if (test_bit(PG_pinned, &virt_to_page(pgd)->flags))
    1.17 +		__pgd_unpin(pgd);
    1.18  }
    1.19  
    1.20  pgd_t *pgd_alloc(struct mm_struct *mm)
    1.21 @@ -318,7 +319,8 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
    1.22  	int i = 0;
    1.23  	pgd_t *pgd = kmem_cache_alloc(pgd_cache, GFP_KERNEL);
    1.24  
    1.25 -	BUG_ON(test_bit(PG_pinned, &virt_to_page(pgd)->flags));
    1.26 +	if (test_bit(PG_pinned, &virt_to_page(pgd)->flags))
    1.27 +		__pgd_unpin(pgd);
    1.28  
    1.29  	if (PTRS_PER_PMD == 1 || !pgd)
    1.30  		return pgd;
    1.31 @@ -345,7 +347,11 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
    1.32  		pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
    1.33  		if (!pmd)
    1.34  			goto out_oom;
    1.35 +		preempt_disable();
    1.36 +		if (test_bit(PG_pinned, &virt_to_page(pgd)->flags))
    1.37 +			make_lowmem_page_readonly(pmd);
    1.38  		set_pgd(&pgd[i], __pgd(1 + __pa(pmd)));
    1.39 +		preempt_enable();
    1.40  	}
    1.41  	return pgd;
    1.42  
    1.43 @@ -367,11 +373,13 @@ void pgd_free(pgd_t *pgd)
    1.44  	if (PTRS_PER_PMD > 1) {
    1.45  		for (i = 0; i < USER_PTRS_PER_PGD; ++i) {
    1.46  			pmd_t *pmd = (void *)__va(pgd_val(pgd[i])-1);
    1.47 +			set_pgd(&pgd[i], __pgd(0));
    1.48  			make_lowmem_page_writable(pmd);
    1.49  			kmem_cache_free(pmd_cache, pmd);
    1.50  		}
    1.51  		if (!HAVE_SHARED_KERNEL_PMD) {
    1.52  			pmd_t *pmd = (void *)__va(pgd_val(pgd[USER_PTRS_PER_PGD])-1);
    1.53 +			set_pgd(&pgd[USER_PTRS_PER_PGD], __pgd(0));
    1.54  			make_lowmem_page_writable(pmd);
    1.55  			memset(pmd, 0, PTRS_PER_PMD*sizeof(pmd_t));
    1.56  			kmem_cache_free(pmd_cache, pmd);