[LINUX] Fix clear_fixmap().
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Mon, 13 Nov 2006 13:37:54 +0000 (13:37 +0000)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Mon, 13 Nov 2006 13:37:54 +0000 (13:37 +0000)
On i386-PAE, clear_fixmap() results in ill use of set_pte(). In all
contexts, p2m translations shouldn't occur here. Note that this is not
really an issue on native linux, as there is
(a) no pfn-to-mfn translation and
(b) __set_fixmap() takes an unsigned long physical address rather than
    a paddr_t, which makes it so that bits 32 and up of the physical
    address are always zero, permitting either order store when
    clearing the entry.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c
linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c

index d8435389177fc8df842a9b61a1fcaadb0d1c5458..0ff01f52f8d8b76360a169cf63a6c127da909e6f 100644 (file)
@@ -102,8 +102,11 @@ static void set_pte_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags)
                return;
        }
        pte = pte_offset_kernel(pmd, vaddr);
-       /* <pfn,flags> stored as-is, to permit clearing entries */
-       set_pte(pte, pfn_pte(pfn, flags));
+       if (pgprot_val(flags))
+               /* <pfn,flags> stored as-is, to permit clearing entries */
+               set_pte(pte, pfn_pte(pfn, flags));
+       else
+               pte_clear(&init_mm, vaddr, pte);
 
        /*
         * It's enough to flush this one mapping.
@@ -140,8 +143,11 @@ static void set_pte_pfn_ma(unsigned long vaddr, unsigned long pfn,
                return;
        }
        pte = pte_offset_kernel(pmd, vaddr);
-       /* <pfn,flags> stored as-is, to permit clearing entries */
-       set_pte(pte, pfn_pte_ma(pfn, flags));
+       if (pgprot_val(flags))
+               /* <pfn,flags> stored as-is, to permit clearing entries */
+               set_pte(pte, pfn_pte_ma(pfn, flags));
+       else
+               pte_clear(&init_mm, vaddr, pte);
 
        /*
         * It's enough to flush this one mapping.
index 61c75c08a6285cea852f38e249db6741f3f4d2f4..455b20b47ec6c7aed5dd1c6b64be6d75361c95f5 100644 (file)
@@ -260,7 +260,10 @@ static void set_pte_phys(unsigned long vaddr,
                        return;
                }
        }
-       new_pte = pfn_pte(phys >> PAGE_SHIFT, prot);
+       if (pgprot_val(prot))
+               new_pte = pfn_pte(phys >> PAGE_SHIFT, prot);
+       else
+               new_pte = __pte(0);
 
        pte = pte_offset_kernel(pmd, vaddr);
        if (!pte_none(*pte) &&