# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 0ec1d38f26f76512487717cf2109ada189efc3e4
# Parent 86964d50bcfac60dbbeba3866b32ad862ec70b2e
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@xxxxxxxxxxxxx>
diff -r 86964d50bcfa -r 0ec1d38f26f7
linux-2.6-xen-sparse/arch/xen/i386/mm/pgtable.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/mm/pgtable.c Thu Nov 24 17:19:51 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/pgtable.c Thu Nov 24 18:16:13 2005
@@ -27,8 +27,9 @@
#include <asm-xen/foreign_page.h>
#include <asm/hypervisor.h>
-static void __pgd_pin(pgd_t *pgd);
-static void __pgd_unpin(pgd_t *pgd);
+static void pgd_test_and_unpin(pgd_t *pgd);
+#define suspend_disable preempt_disable
+#define suspend_enable preempt_enable
void show_mem(void)
{
@@ -310,8 +311,7 @@
pgd_list_del(pgd);
spin_unlock_irqrestore(&pgd_lock, flags);
- if (test_bit(PG_pinned, &virt_to_page(pgd)->flags))
- __pgd_unpin(pgd);
+ pgd_test_and_unpin(pgd);
}
pgd_t *pgd_alloc(struct mm_struct *mm)
@@ -319,8 +319,7 @@
int i = 0;
pgd_t *pgd = kmem_cache_alloc(pgd_cache, GFP_KERNEL);
- if (test_bit(PG_pinned, &virt_to_page(pgd)->flags))
- __pgd_unpin(pgd);
+ pgd_test_and_unpin(pgd);
if (PTRS_PER_PMD == 1 || !pgd)
return pgd;
@@ -347,11 +346,11 @@
pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
if (!pmd)
goto out_oom;
- preempt_disable();
+ suspend_disable();
if (test_bit(PG_pinned, &virt_to_page(pgd)->flags))
make_lowmem_page_readonly(pmd);
set_pgd(&pgd[i], __pgd(1 + __pa(pmd)));
- preempt_enable();
+ suspend_enable();
}
return pgd;
@@ -366,8 +365,8 @@
{
int i;
- if (test_bit(PG_pinned, &virt_to_page(pgd)->flags))
- __pgd_unpin(pgd);
+ suspend_disable();
+ pgd_test_and_unpin(pgd);
/* in the PAE case user pgd entries are overwritten before usage */
if (PTRS_PER_PMD > 1) {
@@ -385,6 +384,9 @@
kmem_cache_free(pmd_cache, pmd);
}
}
+
+ suspend_enable();
+
/* in the non-PAE case, free_pgtables() clears user pgd entries */
kmem_cache_free(pgd_cache, pgd);
}
@@ -509,6 +511,9 @@
static void __pgd_pin(pgd_t *pgd)
{
+ /* PAE PGDs with no kernel PMD cannot be pinned. Bail right now. */
+ if ((PTRS_PER_PMD > 1) && pgd_none(pgd[USER_PTRS_PER_PGD]))
+ return;
pgd_walk(pgd, PAGE_KERNEL_RO);
xen_pgd_pin(__pa(pgd));
set_bit(PG_pinned, &virt_to_page(pgd)->flags);
@@ -519,6 +524,14 @@
xen_pgd_unpin(__pa(pgd));
pgd_walk(pgd, PAGE_KERNEL);
clear_bit(PG_pinned, &virt_to_page(pgd)->flags);
+}
+
+static void pgd_test_and_unpin(pgd_t *pgd)
+{
+ suspend_disable();
+ if (test_bit(PG_pinned, &virt_to_page(pgd)->flags))
+ __pgd_unpin(pgd);
+ suspend_enable();
}
void mm_pin(struct mm_struct *mm)
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|