ia64/xen-unstable

changeset 8039:0ec1d38f26f7

More PAE PGD fixes. Ensure we do not pin PGDs with no kernel
PMD (Xen will not allow it). This is okay even across
suspend/resume -- such PGDs are completely empty and so
contain no PTEs that become garbage across suspend/resume.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Thu Nov 24 19:16:13 2005 +0100 (2005-11-24)
parents 86964d50bcfa
children 0ea18c1ea134
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 18:19:51 2005 +0100
     1.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/pgtable.c	Thu Nov 24 19:16:13 2005 +0100
     1.3 @@ -27,8 +27,9 @@
     1.4  #include <asm-xen/foreign_page.h>
     1.5  #include <asm/hypervisor.h>
     1.6  
     1.7 -static void __pgd_pin(pgd_t *pgd);
     1.8 -static void __pgd_unpin(pgd_t *pgd);
     1.9 +static void pgd_test_and_unpin(pgd_t *pgd);
    1.10 +#define suspend_disable	preempt_disable
    1.11 +#define suspend_enable	preempt_enable
    1.12  
    1.13  void show_mem(void)
    1.14  {
    1.15 @@ -310,8 +311,7 @@ void pgd_dtor(void *pgd, kmem_cache_t *c
    1.16  	pgd_list_del(pgd);
    1.17  	spin_unlock_irqrestore(&pgd_lock, flags);
    1.18  
    1.19 -	if (test_bit(PG_pinned, &virt_to_page(pgd)->flags))
    1.20 -		__pgd_unpin(pgd);
    1.21 +	pgd_test_and_unpin(pgd);
    1.22  }
    1.23  
    1.24  pgd_t *pgd_alloc(struct mm_struct *mm)
    1.25 @@ -319,8 +319,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
    1.26  	int i = 0;
    1.27  	pgd_t *pgd = kmem_cache_alloc(pgd_cache, GFP_KERNEL);
    1.28  
    1.29 -	if (test_bit(PG_pinned, &virt_to_page(pgd)->flags))
    1.30 -		__pgd_unpin(pgd);
    1.31 +	pgd_test_and_unpin(pgd);
    1.32  
    1.33  	if (PTRS_PER_PMD == 1 || !pgd)
    1.34  		return pgd;
    1.35 @@ -347,11 +346,11 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
    1.36  		pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
    1.37  		if (!pmd)
    1.38  			goto out_oom;
    1.39 -		preempt_disable();
    1.40 +		suspend_disable();
    1.41  		if (test_bit(PG_pinned, &virt_to_page(pgd)->flags))
    1.42  			make_lowmem_page_readonly(pmd);
    1.43  		set_pgd(&pgd[i], __pgd(1 + __pa(pmd)));
    1.44 -		preempt_enable();
    1.45 +		suspend_enable();
    1.46  	}
    1.47  	return pgd;
    1.48  
    1.49 @@ -366,8 +365,8 @@ void pgd_free(pgd_t *pgd)
    1.50  {
    1.51  	int i;
    1.52  
    1.53 -	if (test_bit(PG_pinned, &virt_to_page(pgd)->flags))
    1.54 -		__pgd_unpin(pgd);
    1.55 +	suspend_disable();
    1.56 +	pgd_test_and_unpin(pgd);
    1.57  
    1.58  	/* in the PAE case user pgd entries are overwritten before usage */
    1.59  	if (PTRS_PER_PMD > 1) {
    1.60 @@ -385,6 +384,9 @@ void pgd_free(pgd_t *pgd)
    1.61  			kmem_cache_free(pmd_cache, pmd);
    1.62  		}
    1.63  	}
    1.64 +
    1.65 +	suspend_enable();
    1.66 +
    1.67  	/* in the non-PAE case, free_pgtables() clears user pgd entries */
    1.68  	kmem_cache_free(pgd_cache, pgd);
    1.69  }
    1.70 @@ -509,6 +511,9 @@ static void pgd_walk(pgd_t *pgd_base, pg
    1.71  
    1.72  static void __pgd_pin(pgd_t *pgd)
    1.73  {
    1.74 +	/* PAE PGDs with no kernel PMD cannot be pinned. Bail right now. */
    1.75 +	if ((PTRS_PER_PMD > 1) && pgd_none(pgd[USER_PTRS_PER_PGD]))
    1.76 +		return;
    1.77  	pgd_walk(pgd, PAGE_KERNEL_RO);
    1.78  	xen_pgd_pin(__pa(pgd));
    1.79  	set_bit(PG_pinned, &virt_to_page(pgd)->flags);
    1.80 @@ -521,6 +526,14 @@ static void __pgd_unpin(pgd_t *pgd)
    1.81  	clear_bit(PG_pinned, &virt_to_page(pgd)->flags);
    1.82  }
    1.83  
    1.84 +static void pgd_test_and_unpin(pgd_t *pgd)
    1.85 +{
    1.86 +	suspend_disable();
    1.87 +	if (test_bit(PG_pinned, &virt_to_page(pgd)->flags))
    1.88 +		__pgd_unpin(pgd);
    1.89 +	suspend_enable();
    1.90 +}
    1.91 +
    1.92  void mm_pin(struct mm_struct *mm)
    1.93  {
    1.94  	spin_lock(&mm->page_table_lock);