WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] linux/x86: Adjust and fix page table hand

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] linux/x86: Adjust and fix page table handling.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Tue, 20 Feb 2007 08:20:07 -0800
Delivery-date: Tue, 20 Feb 2007 08:20:26 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1171963994 0
# Node ID d2dff286994d52b82111499c99a2c0e070104734
# Parent  89ca591a2c211caf487d20261692ef4a40170cf7
linux/x86: Adjust and fix page table handling.

Ensure that all and only those page table entries that have their
present bit set undergo p2m/m2p translation in all relevant places.
This should fix migration issues with _PAGE_PROTNONE pages which
previously could retain MFNs in PTEs while having the present bit
clear (and thus were not getting (un)canonicalized during save/
restore).

Many thanks to Keir Fraser for his analysis, suggestions, and
corrections.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>
---
 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/maddr.h          |   25 +++-
 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/page.h           |   53 
+++++-----
 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-2level.h |    7 -
 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-3level.h |   15 +-
 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable.h        |   23 ++--
 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/maddr.h        |   15 ++
 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/page.h         |   28 
+++--
 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgtable.h      |   38 
++++---
 8 files changed, 130 insertions(+), 74 deletions(-)

diff -r 89ca591a2c21 -r d2dff286994d 
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/maddr.h
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/maddr.h        Mon Feb 
19 20:44:42 2007 -0800
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/maddr.h        Tue Feb 
20 09:33:14 2007 +0000
@@ -21,6 +21,7 @@ typedef unsigned long maddr_t;
 #ifdef CONFIG_XEN
 
 extern unsigned long *phys_to_machine_mapping;
+extern unsigned long  max_mapnr;
 
 #undef machine_to_phys_mapping
 extern unsigned long *machine_to_phys_mapping;
@@ -30,20 +31,20 @@ static inline unsigned long pfn_to_mfn(u
 {
        if (xen_feature(XENFEAT_auto_translated_physmap))
                return pfn;
-       return phys_to_machine_mapping[(unsigned int)(pfn)] &
-               ~FOREIGN_FRAME_BIT;
+       BUG_ON(max_mapnr && pfn >= max_mapnr);
+       return phys_to_machine_mapping[pfn] & ~FOREIGN_FRAME_BIT;
 }
 
 static inline int phys_to_machine_mapping_valid(unsigned long pfn)
 {
        if (xen_feature(XENFEAT_auto_translated_physmap))
                return 1;
+       BUG_ON(max_mapnr && pfn >= max_mapnr);
        return (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY);
 }
 
 static inline unsigned long mfn_to_pfn(unsigned long mfn)
 {
-       extern unsigned long max_mapnr;
        unsigned long pfn;
 
        if (xen_feature(XENFEAT_auto_translated_physmap))
@@ -92,7 +93,6 @@ static inline unsigned long mfn_to_pfn(u
  */
 static inline unsigned long mfn_to_local_pfn(unsigned long mfn)
 {
-       extern unsigned long max_mapnr;
        unsigned long pfn = mfn_to_pfn(mfn);
        if ((pfn < max_mapnr)
            && !xen_feature(XENFEAT_auto_translated_physmap)
@@ -103,6 +103,7 @@ static inline unsigned long mfn_to_local
 
 static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 {
+       BUG_ON(pfn >= max_mapnr);
        if (xen_feature(XENFEAT_auto_translated_physmap)) {
                BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
                return;
@@ -124,6 +125,20 @@ static inline paddr_t machine_to_phys(ma
        return phys;
 }
 
+#ifdef CONFIG_X86_PAE
+static inline paddr_t pte_phys_to_machine(paddr_t phys)
+{
+       /*
+        * In PAE mode, the NX bit needs to be dealt with in the value
+        * passed to pfn_to_mfn(). On x86_64, we need to mask it off,
+        * but for i386 the conversion to ulong for the argument will
+        * clip it off.
+        */
+       maddr_t machine = pfn_to_mfn(phys >> PAGE_SHIFT);
+       machine = (machine << PAGE_SHIFT) | (phys & ~PHYSICAL_PAGE_MASK);
+       return machine;
+}
+
 static inline paddr_t pte_machine_to_phys(maddr_t machine)
 {
        /*
@@ -136,6 +151,7 @@ static inline paddr_t pte_machine_to_phy
        phys = (phys << PAGE_SHIFT) | (machine & ~PHYSICAL_PAGE_MASK);
        return phys;
 }
+#endif
 
 #else /* !CONFIG_XEN */
 
@@ -146,7 +162,6 @@ static inline paddr_t pte_machine_to_phy
 #define phys_to_machine_mapping_valid(pfn) (1)
 #define phys_to_machine(phys) ((maddr_t)(phys))
 #define machine_to_phys(mach) ((paddr_t)(mach))
-#define pte_machine_to_phys(mach) ((paddr_t)(mach))
 
 #endif /* !CONFIG_XEN */
 
diff -r 89ca591a2c21 -r d2dff286994d 
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/page.h
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/page.h Mon Feb 19 
20:44:42 2007 -0800
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/page.h Tue Feb 20 
09:33:14 2007 +0000
@@ -28,6 +28,13 @@
 #include <asm/bug.h>
 #include <xen/interface/xen.h>
 #include <xen/features.h>
+
+/*
+ * Need to repeat this here in order to not include pgtable.h (which in turn
+ * depends on definitions made here), but to be able to use the symbolic
+ * below. The preprocessor will warn if the two definitions aren't identical.
+ */
+#define _PAGE_PRESENT  0x001
 
 #define arch_free_page(_page,_order)           \
 ({     int foreign = PageForeign(_page);       \
@@ -81,39 +88,37 @@ typedef struct { unsigned long long pgpr
 #define pgprot_val(x)  ((x).pgprot)
 #include <asm/maddr.h>
 #define __pte(x) ({ unsigned long long _x = (x);        \
-    if (_x & 1) _x = phys_to_machine(_x);               \
+    if (_x & _PAGE_PRESENT) _x = pte_phys_to_machine(_x);   \
     ((pte_t) {(unsigned long)(_x), (unsigned long)(_x>>32)}); })
 #define __pgd(x) ({ unsigned long long _x = (x); \
-    (((_x)&1) ? ((pgd_t) {phys_to_machine(_x)}) : ((pgd_t) {(_x)})); })
+    (pgd_t) {((_x) & _PAGE_PRESENT) ? pte_phys_to_machine(_x) : (_x)}; })
 #define __pmd(x) ({ unsigned long long _x = (x); \
-    (((_x)&1) ? ((pmd_t) {phys_to_machine(_x)}) : ((pmd_t) {(_x)})); })
+    (pmd_t) {((_x) & _PAGE_PRESENT) ? pte_phys_to_machine(_x) : (_x)}; })
+static inline unsigned long long pte_val_ma(pte_t x)
+{
+       return ((unsigned long long)x.pte_high << 32) | x.pte_low;
+}
 static inline unsigned long long pte_val(pte_t x)
 {
-       unsigned long long ret;
-
-       if (x.pte_low) {
-               ret = x.pte_low | (unsigned long long)x.pte_high << 32;
-               ret = pte_machine_to_phys(ret) | 1;
-       } else {
-               ret = 0;
-       }
+       unsigned long long ret = pte_val_ma(x);
+       if (x.pte_low & _PAGE_PRESENT) ret = pte_machine_to_phys(ret);
        return ret;
 }
 static inline unsigned long long pmd_val(pmd_t x)
 {
        unsigned long long ret = x.pmd;
-       if (ret) ret = pte_machine_to_phys(ret) | 1;
+#ifdef CONFIG_XEN_COMPAT_030002
+       if (ret) ret = pte_machine_to_phys(ret) | _PAGE_PRESENT;
+#else
+       if (ret & _PAGE_PRESENT) ret = pte_machine_to_phys(ret);
+#endif
        return ret;
 }
 static inline unsigned long long pgd_val(pgd_t x)
 {
        unsigned long long ret = x.pgd;
-       if (ret) ret = pte_machine_to_phys(ret) | 1;
-       return ret;
-}
-static inline unsigned long long pte_val_ma(pte_t x)
-{
-       return (unsigned long long)x.pte_high << 32 | x.pte_low;
+       if (ret & _PAGE_PRESENT) ret = pte_machine_to_phys(ret);
+       return ret;
 }
 #define HPAGE_SHIFT    21
 #else
@@ -123,23 +128,23 @@ typedef struct { unsigned long pgprot; }
 #define pgprot_val(x)  ((x).pgprot)
 #include <asm/maddr.h>
 #define boot_pte_t pte_t /* or would you rather have a typedef */
-#define pte_val(x)     (((x).pte_low & 1) ? \
-                        pte_machine_to_phys((x).pte_low) : \
+#define pte_val(x)     (((x).pte_low & _PAGE_PRESENT) ? \
+                        machine_to_phys((x).pte_low) : \
                         (x).pte_low)
 #define pte_val_ma(x)  ((x).pte_low)
 #define __pte(x) ({ unsigned long _x = (x); \
-    (((_x)&1) ? ((pte_t) {phys_to_machine(_x)}) : ((pte_t) {(_x)})); })
+    (pte_t) {((_x) & _PAGE_PRESENT) ? phys_to_machine(_x) : (_x)}; })
 #define __pgd(x) ({ unsigned long _x = (x); \
-    (((_x)&1) ? ((pgd_t) {phys_to_machine(_x)}) : ((pgd_t) {(_x)})); })
+    (pgd_t) {((_x) & _PAGE_PRESENT) ? phys_to_machine(_x) : (_x)}; })
 static inline unsigned long pgd_val(pgd_t x)
 {
        unsigned long ret = x.pgd;
-       if (ret) ret = pte_machine_to_phys(ret) | 1;
+       if (ret & _PAGE_PRESENT) ret = machine_to_phys(ret);
        return ret;
 }
 #define HPAGE_SHIFT    22
 #endif
-#define PTE_MASK       PAGE_MASK
+#define PTE_MASK       PHYSICAL_PAGE_MASK
 
 #ifdef CONFIG_HUGETLB_PAGE
 #define HPAGE_SIZE     ((1UL) << HPAGE_SHIFT)
diff -r 89ca591a2c21 -r d2dff286994d 
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-2level.h
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-2level.h       
Mon Feb 19 20:44:42 2007 -0800
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-2level.h       
Tue Feb 20 09:33:14 2007 +0000
@@ -38,8 +38,11 @@
 
 #define ptep_get_and_clear(mm,addr,xp) __pte_ma(xchg(&(xp)->pte_low, 0))
 #define pte_same(a, b)         ((a).pte_low == (b).pte_low)
-#define pte_mfn(_pte) ((_pte).pte_low >> PAGE_SHIFT)
-#define pte_pfn(_pte) mfn_to_local_pfn(pte_mfn(_pte))
+#define __pte_mfn(_pte) ((_pte).pte_low >> PAGE_SHIFT)
+#define pte_mfn(_pte) ((_pte).pte_low & _PAGE_PRESENT ? \
+       __pte_mfn(_pte) : pfn_to_mfn(__pte_mfn(_pte)))
+#define pte_pfn(_pte) ((_pte).pte_low & _PAGE_PRESENT ? \
+       mfn_to_local_pfn(__pte_mfn(_pte)) : __pte_mfn(_pte))
 
 #define pte_page(_pte) pfn_to_page(pte_pfn(_pte))
 
diff -r 89ca591a2c21 -r d2dff286994d 
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-3level.h
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-3level.h       
Mon Feb 19 20:44:42 2007 -0800
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-3level.h       
Tue Feb 20 09:33:14 2007 +0000
@@ -145,21 +145,24 @@ static inline int pte_none(pte_t pte)
        return !pte.pte_low && !pte.pte_high;
 }
 
-#define pte_mfn(_pte) (((_pte).pte_low >> PAGE_SHIFT) |\
-                      (((_pte).pte_high & 0xfff) << (32-PAGE_SHIFT)))
-#define pte_pfn(_pte) mfn_to_local_pfn(pte_mfn(_pte))
+#define __pte_mfn(_pte) (((_pte).pte_low >> PAGE_SHIFT) | \
+                        ((_pte).pte_high << (32-PAGE_SHIFT)))
+#define pte_mfn(_pte) ((_pte).pte_low & _PAGE_PRESENT ? \
+       __pte_mfn(_pte) : pfn_to_mfn(__pte_mfn(_pte)))
+#define pte_pfn(_pte) ((_pte).pte_low & _PAGE_PRESENT ? \
+       mfn_to_local_pfn(__pte_mfn(_pte)) : __pte_mfn(_pte))
 
 extern unsigned long long __supported_pte_mask;
 
 static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot)
 {
-       return pfn_pte_ma(pfn_to_mfn(page_nr), pgprot);
+       return __pte((((unsigned long long)page_nr << PAGE_SHIFT) |
+                       pgprot_val(pgprot)) & __supported_pte_mask);
 }
 
 static inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot)
 {
-       BUG(); panic("needs review");
-       return __pmd((((unsigned long long)page_nr << PAGE_SHIFT) | \
+       return __pmd((((unsigned long long)page_nr << PAGE_SHIFT) |
                        pgprot_val(pgprot)) & __supported_pte_mask);
 }
 
diff -r 89ca591a2c21 -r d2dff286994d 
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable.h
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable.h      Mon Feb 
19 20:44:42 2007 -0800
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable.h      Tue Feb 
20 09:33:14 2007 +0000
@@ -315,18 +315,19 @@ static inline void clone_pgd_range(pgd_t
 
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
-       pte.pte_low &= _PAGE_CHG_MASK;
-       pte.pte_low |= pgprot_val(newprot);
+       /*
+        * Since this might change the present bit (which controls whether
+        * a pte_t object has undergone p2m translation), we must use
+        * pte_val() on the input pte and __pte() for the return value.
+        */
+       paddr_t pteval = pte_val(pte);
+
+       pteval &= _PAGE_CHG_MASK;
+       pteval |= pgprot_val(newprot);
 #ifdef CONFIG_X86_PAE
-       /*
-        * Chop off the NX bit (if present), and add the NX portion of
-        * the newprot (if present):
-        */
-       pte.pte_high &= ~(1 << (_PAGE_BIT_NX - 32));
-       pte.pte_high |= (pgprot_val(newprot) >> 32) & \
-                                       (__supported_pte_mask >> 32);
-#endif
-       return pte;
+       pteval &= __supported_pte_mask;
+#endif
+       return __pte(pteval);
 }
 
 #define pmd_large(pmd) \
diff -r 89ca591a2c21 -r d2dff286994d 
linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/maddr.h
--- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/maddr.h      Mon Feb 
19 20:44:42 2007 -0800
+++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/maddr.h      Tue Feb 
20 09:33:14 2007 +0000
@@ -25,14 +25,15 @@ static inline unsigned long pfn_to_mfn(u
 {
        if (xen_feature(XENFEAT_auto_translated_physmap))
                return pfn;
-       return phys_to_machine_mapping[(unsigned int)(pfn)] &
-               ~FOREIGN_FRAME_BIT;
+       BUG_ON(end_pfn && pfn >= end_pfn);
+       return phys_to_machine_mapping[pfn] & ~FOREIGN_FRAME_BIT;
 }
 
 static inline int phys_to_machine_mapping_valid(unsigned long pfn)
 {
        if (xen_feature(XENFEAT_auto_translated_physmap))
                return 1;
+       BUG_ON(end_pfn && pfn >= end_pfn);
        return (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY);
 }
 
@@ -96,6 +97,7 @@ static inline unsigned long mfn_to_local
 
 static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 {
+       BUG_ON(pfn >= end_pfn);
        if (xen_feature(XENFEAT_auto_translated_physmap)) {
                BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
                return;
@@ -117,6 +119,14 @@ static inline paddr_t machine_to_phys(ma
        return phys;
 }
 
+static inline paddr_t pte_phys_to_machine(paddr_t phys)
+{
+       maddr_t machine;
+       machine = pfn_to_mfn((phys & PHYSICAL_PAGE_MASK) >> PAGE_SHIFT);
+       machine = (machine << PAGE_SHIFT) | (phys & ~PHYSICAL_PAGE_MASK);
+       return machine;
+}
+
 static inline paddr_t pte_machine_to_phys(maddr_t machine)
 {
        paddr_t phys;
@@ -134,7 +144,6 @@ static inline paddr_t pte_machine_to_phy
 #define phys_to_machine_mapping_valid(pfn) (1)
 #define phys_to_machine(phys) ((maddr_t)(phys))
 #define machine_to_phys(mach) ((paddr_t)(mach))
-#define pte_machine_to_phys(mach) ((paddr_t)(mach))
 
 #endif /* !CONFIG_XEN */
 
diff -r 89ca591a2c21 -r d2dff286994d 
linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/page.h
--- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/page.h       Mon Feb 
19 20:44:42 2007 -0800
+++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/page.h       Tue Feb 
20 09:33:14 2007 +0000
@@ -8,6 +8,13 @@
 #include <asm/bug.h>
 #endif
 #include <xen/interface/xen.h> 
+
+/*
+ * Need to repeat this here in order to not include pgtable.h (which in turn
+ * depends on definitions made here), but to be able to use the symbolic
+ * below. The preprocessor will warn if the two definitions aren't identical.
+ */
+#define _PAGE_PRESENT  0x001
 
 #define arch_free_page(_page,_order)           \
 ({     int foreign = PageForeign(_page);       \
@@ -95,28 +102,33 @@ typedef struct { unsigned long pgd; } pg
 
 typedef struct { unsigned long pgprot; } pgprot_t;
 
-#define pte_val(x)     (((x).pte & 1) ? pte_machine_to_phys((x).pte) : \
+#define pte_val(x)     (((x).pte & _PAGE_PRESENT) ? \
+                        pte_machine_to_phys((x).pte) : \
                         (x).pte)
 #define pte_val_ma(x)  ((x).pte)
 
 static inline unsigned long pmd_val(pmd_t x)
 {
        unsigned long ret = x.pmd;
-       if (ret) ret = pte_machine_to_phys(ret);
+#ifdef CONFIG_XEN_COMPAT_030002
+       if (ret) ret = pte_machine_to_phys(ret) | _PAGE_PRESENT;
+#else
+       if (ret & _PAGE_PRESENT) ret = pte_machine_to_phys(ret);
+#endif
        return ret;
 }
 
 static inline unsigned long pud_val(pud_t x)
 {
        unsigned long ret = x.pud;
-       if (ret) ret = pte_machine_to_phys(ret);
+       if (ret & _PAGE_PRESENT) ret = pte_machine_to_phys(ret);
        return ret;
 }
 
 static inline unsigned long pgd_val(pgd_t x)
 {
        unsigned long ret = x.pgd;
-       if (ret) ret = pte_machine_to_phys(ret);
+       if (ret & _PAGE_PRESENT) ret = pte_machine_to_phys(ret);
        return ret;
 }
 
@@ -124,25 +136,25 @@ static inline unsigned long pgd_val(pgd_
 
 static inline pte_t __pte(unsigned long x)
 {
-       if (x & 1) x = phys_to_machine(x);
+       if (x & _PAGE_PRESENT) x = pte_phys_to_machine(x);
        return ((pte_t) { (x) });
 }
 
 static inline pmd_t __pmd(unsigned long x)
 {
-       if ((x & 1)) x = phys_to_machine(x);
+       if (x & _PAGE_PRESENT) x = pte_phys_to_machine(x);
        return ((pmd_t) { (x) });
 }
 
 static inline pud_t __pud(unsigned long x)
 {
-       if ((x & 1)) x = phys_to_machine(x);
+       if (x & _PAGE_PRESENT) x = pte_phys_to_machine(x);
        return ((pud_t) { (x) });
 }
 
 static inline pgd_t __pgd(unsigned long x)
 {
-       if ((x & 1)) x = phys_to_machine(x);
+       if (x & _PAGE_PRESENT) x = pte_phys_to_machine(x);
        return ((pgd_t) { (x) });
 }
 
diff -r 89ca591a2c21 -r d2dff286994d 
linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgtable.h
--- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgtable.h    Mon Feb 
19 20:44:42 2007 -0800
+++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgtable.h    Tue Feb 
20 09:33:14 2007 +0000
@@ -302,19 +302,20 @@ static inline unsigned long pud_bad(pud_
 
 #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
 
-#define pte_mfn(_pte) (((_pte).pte & PTE_MASK) >> PAGE_SHIFT)
-#define pte_pfn(_pte) mfn_to_local_pfn(pte_mfn(_pte))
+#define __pte_mfn(_pte) (((_pte).pte & PTE_MASK) >> PAGE_SHIFT)
+#define pte_mfn(_pte) ((_pte).pte & _PAGE_PRESENT ? \
+       __pte_mfn(_pte) : pfn_to_mfn(__pte_mfn(_pte)))
+#define pte_pfn(_pte) ((_pte).pte & _PAGE_PRESENT ? \
+       mfn_to_local_pfn(__pte_mfn(_pte)) : __pte_mfn(_pte))
 
 #define pte_page(x)    pfn_to_page(pte_pfn(x))
 
 static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot)
 {
-       pte_t pte;
-        
-       (pte).pte = (pfn_to_mfn(page_nr) << PAGE_SHIFT);
-       (pte).pte |= pgprot_val(pgprot);
-       (pte).pte &= __supported_pte_mask;
-       return pte;
+       unsigned long pte = page_nr << PAGE_SHIFT;
+       pte |= pgprot_val(pgprot);
+       pte &= __supported_pte_mask;
+       return __pte(pte);
 }
 
 /*
@@ -446,18 +447,25 @@ static inline pud_t *pud_offset_k(pgd_t 
 /* physical address -> PTE */
 static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
 { 
-       pte_t pte;
-       (pte).pte = physpage | pgprot_val(pgprot); 
-       return pte; 
+       unsigned long pteval;
+       pteval = physpage | pgprot_val(pgprot);
+       return __pte(pteval);
 }
  
 /* Change flags of a PTE */
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 { 
-        (pte).pte &= _PAGE_CHG_MASK;
-       (pte).pte |= pgprot_val(newprot);
-       (pte).pte &= __supported_pte_mask;
-       return pte; 
+       /*
+        * Since this might change the present bit (which controls whether
+        * a pte_t object has undergone p2m translation), we must use
+        * pte_val() on the input pte and __pte() for the return value.
+        */
+       unsigned long pteval = pte_val(pte);
+
+       pteval &= _PAGE_CHG_MASK;
+       pteval |= pgprot_val(newprot);
+       pteval &= __supported_pte_mask;
+       return __pte(pteval);
 }
 
 #define pte_index(address) \

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] linux/x86: Adjust and fix page table handling., Xen patchbot-unstable <=