All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/14] XSA-277 followup
@ 2018-11-21 13:21 Andrew Cooper
  2018-11-21 13:21 ` [PATCH 01/14] x86/soft-reset: Drop gfn reference after calling get_gfn_query() Andrew Cooper
                   ` (15 more replies)
  0 siblings, 16 replies; 59+ messages in thread
From: Andrew Cooper @ 2018-11-21 13:21 UTC (permalink / raw)
  To: Xen-devel
  Cc: Kevin Tian, Stefano Stabellini, Wei Liu, Jun Nakajima,
	Razvan Cojocaru, George Dunlap, Andrew Cooper, Tim Deegan,
	Julien Grall, Tamas K Lengyel, Jan Beulich, Boris Ostrovsky,
	Brian Woods, Suravee Suthikulpanit, Paul Durrant,
	Roger Pau Monné

This covers various fixes related to XSA-277 which weren't in security
supported areas, and associated cleanup.

The biggest issue noticed here is that altp2m's use of hardware #VE support
will cause general memory corruption if the guest ever balloons out the VEINFO
page.  The only safe way I think of doing this is for Xen to alloc annonymous
domheap pages for the VEINFO, and for the guest to map them in a similar way
to the shared info and grant table frames.

Andrew Cooper (14):
  x86/soft-reset: Drop gfn reference after calling get_gfn_query()
  x86/mem-sharing: Don't leave the altp2m lock held when nominating a page
  AMD/IOMMU: Fix multiple reference counting errors
  x86/p2m: Fix locking in p2m_altp2m_lazy_copy()
  x86/p2m: Don't overwrite p2m_altp2m_lazy_copy()'s callers p2m pointer
  x86/hvm: Make the altp2m locking easier to follow
  x86/p2m: Coding style cleanup
  xen/memory: Drop ARM put_gfn() stub
  x86/p2m: Switch the two_gfns infrastructure to using gfn_t
  x86/mm: Switch {get,put}_gfn() infrastructure to using gfn_t
  xen/mm: Switch mfn_to_virt()/virt_to_mfn() to using mfn_t
  xen/gnttab: Drop gnttab_create_{shared,status}_page()
  xen/gnttab: Simplify gnttab_map_frame()
  xen/gnttab: Minor improvements to arch header files

 xen/arch/arm/alternative.c                |   4 -
 xen/arch/arm/cpuerrata.c                  |   4 -
 xen/arch/arm/domain_build.c               |   4 -
 xen/arch/arm/livepatch.c                  |   4 -
 xen/arch/arm/mm.c                         |   6 -
 xen/arch/arm/setup.c                      |   4 +-
 xen/arch/x86/cpu/mcheck/mcaction.c        |   2 +-
 xen/arch/x86/cpu/mcheck/mce.c             |  14 +-
 xen/arch/x86/cpu/mcheck/vmce.c            |   4 +-
 xen/arch/x86/cpu/mcheck/vmce.h            |   2 +-
 xen/arch/x86/debug.c                      |   6 +-
 xen/arch/x86/domain.c                     |  23 ++--
 xen/arch/x86/domain_page.c                |  10 +-
 xen/arch/x86/domctl.c                     |   8 +-
 xen/arch/x86/guest/xen.c                  |   2 +-
 xen/arch/x86/hvm/dm.c                     |  12 +-
 xen/arch/x86/hvm/dom0_build.c             |   4 +-
 xen/arch/x86/hvm/emulate.c                |  16 +--
 xen/arch/x86/hvm/grant_table.c            |   4 +-
 xen/arch/x86/hvm/hvm.c                    |  50 +++----
 xen/arch/x86/hvm/mtrr.c                   |   2 +-
 xen/arch/x86/hvm/svm/svm.c                |   2 +-
 xen/arch/x86/hvm/vmx/vmx.c                |   7 +-
 xen/arch/x86/mm.c                         |  25 ++--
 xen/arch/x86/mm/hap/hap.c                 |   2 +-
 xen/arch/x86/mm/hap/nested_hap.c          |   6 +-
 xen/arch/x86/mm/mem_access.c              |   5 +-
 xen/arch/x86/mm/mem_sharing.c             |  33 ++---
 xen/arch/x86/mm/p2m.c                     | 115 ++++++++--------
 xen/arch/x86/mm/shadow/common.c           |   4 +-
 xen/arch/x86/mm/shadow/multi.c            |  68 +++++-----
 xen/arch/x86/mm/shadow/types.h            |   4 -
 xen/arch/x86/numa.c                       |   2 +-
 xen/arch/x86/pv/descriptor-tables.c       |   2 +-
 xen/arch/x86/pv/dom0_build.c              |   5 +-
 xen/arch/x86/pv/shim.c                    |   3 -
 xen/arch/x86/setup.c                      |  10 +-
 xen/arch/x86/srat.c                       |   2 +-
 xen/arch/x86/tboot.c                      |   4 +-
 xen/arch/x86/x86_64/mm.c                  |  10 +-
 xen/common/domctl.c                       |   2 +-
 xen/common/efi/boot.c                     |   7 +-
 xen/common/grant_table.c                  |  46 ++++---
 xen/common/memory.c                       |  39 ++++--
 xen/common/page_alloc.c                   |  10 +-
 xen/common/tmem.c                         |   2 +-
 xen/common/trace.c                        |  20 +--
 xen/common/xenoprof.c                     |   4 -
 xen/drivers/acpi/osl.c                    |   2 +-
 xen/drivers/passthrough/amd/iommu_guest.c | 218 +++++++++++++++++++-----------
 xen/include/asm-arm/grant_table.h         |  18 +--
 xen/include/asm-arm/mm.h                  |   8 +-
 xen/include/asm-x86/grant_table.h         |  23 +---
 xen/include/asm-x86/guest_pt.h            |   4 -
 xen/include/asm-x86/mm.h                  |   2 +-
 xen/include/asm-x86/p2m.h                 | 128 ++++++++++--------
 xen/include/asm-x86/page.h                |   4 +-
 xen/include/xen/domain_page.h             |   6 +-
 58 files changed, 533 insertions(+), 504 deletions(-)

-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* [PATCH 01/14] x86/soft-reset: Drop gfn reference after calling get_gfn_query()
  2018-11-21 13:21 [PATCH 00/14] XSA-277 followup Andrew Cooper
@ 2018-11-21 13:21 ` Andrew Cooper
  2018-11-22 14:45   ` Jan Beulich
  2018-11-21 13:21 ` [PATCH 02/14] x86/mem-sharing: Don't leave the altp2m lock held when nominating a page Andrew Cooper
                   ` (14 subsequent siblings)
  15 siblings, 1 reply; 59+ messages in thread
From: Andrew Cooper @ 2018-11-21 13:21 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper, Wei Liu, Jan Beulich, Roger Pau Monné

get_gfn_query() internally takes the p2m lock, and this error path leaves it
locked.

This wasn't included in XSA-277 because the error path can only be triggered
by a carefully timed phymap operation concurrent with the domain being paused
and the toolstack issuing DOMCTL_soft_reset.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
---
 xen/arch/x86/domain.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index 295b10c..b4d5948 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -725,7 +725,7 @@ int arch_domain_soft_reset(struct domain *d)
         printk(XENLOG_G_ERR "Failed to get Dom%d's shared_info GFN (%lx)\n",
                d->domain_id, gfn);
         ret = -EINVAL;
-        goto exit_put_page;
+        goto exit_put_gfn;
     }
 
     new_page = alloc_domheap_page(d, 0);
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 02/14] x86/mem-sharing: Don't leave the altp2m lock held when nominating a page
  2018-11-21 13:21 [PATCH 00/14] XSA-277 followup Andrew Cooper
  2018-11-21 13:21 ` [PATCH 01/14] x86/soft-reset: Drop gfn reference after calling get_gfn_query() Andrew Cooper
@ 2018-11-21 13:21 ` Andrew Cooper
  2018-11-21 16:56   ` Tamas K Lengyel
  2018-11-22 14:46   ` Jan Beulich
  2018-11-21 13:21 ` [PATCH 03/14] AMD/IOMMU: Fix multiple reference counting errors Andrew Cooper
                   ` (13 subsequent siblings)
  15 siblings, 2 replies; 59+ messages in thread
From: Andrew Cooper @ 2018-11-21 13:21 UTC (permalink / raw)
  To: Xen-devel
  Cc: Andrew Cooper, Tamas K Lengyel, Wei Liu, Jan Beulich,
	Roger Pau Monné

get_gfn_type_access() internally takes the p2m lock, and nothing ever unlocks
it.  Switch to using the unlocked accessor instead.

This wasn't included in XSA-277 because neither mem-sharing nor altp2m are
supported.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Tamas K Lengyel <tamas@tklengyel.com>
---
 xen/arch/x86/mm/mem_sharing.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/xen/arch/x86/mm/mem_sharing.c b/xen/arch/x86/mm/mem_sharing.c
index f4c5074..77f0d3f 100644
--- a/xen/arch/x86/mm/mem_sharing.c
+++ b/xen/arch/x86/mm/mem_sharing.c
@@ -820,7 +820,8 @@ static int nominate_page(struct domain *d, gfn_t gfn,
             if ( !ap2m )
                 continue;
 
-            amfn = get_gfn_type_access(ap2m, gfn_x(gfn), &ap2mt, &ap2ma, 0, NULL);
+            amfn = __get_gfn_type_access(ap2m, gfn_x(gfn), &ap2mt, &ap2ma,
+                                         0, NULL, false);
             if ( mfn_valid(amfn) && (!mfn_eq(amfn, mfn) || ap2ma != p2ma) )
             {
                 altp2m_list_unlock(d);
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 03/14] AMD/IOMMU: Fix multiple reference counting errors
  2018-11-21 13:21 [PATCH 00/14] XSA-277 followup Andrew Cooper
  2018-11-21 13:21 ` [PATCH 01/14] x86/soft-reset: Drop gfn reference after calling get_gfn_query() Andrew Cooper
  2018-11-21 13:21 ` [PATCH 02/14] x86/mem-sharing: Don't leave the altp2m lock held when nominating a page Andrew Cooper
@ 2018-11-21 13:21 ` Andrew Cooper
  2018-11-22 14:51   ` Jan Beulich
  2019-01-31 15:59   ` Woods, Brian
  2018-11-21 13:21 ` [PATCH 04/14] x86/p2m: Fix locking in p2m_altp2m_lazy_copy() Andrew Cooper
                   ` (12 subsequent siblings)
  15 siblings, 2 replies; 59+ messages in thread
From: Andrew Cooper @ 2018-11-21 13:21 UTC (permalink / raw)
  To: Xen-devel
  Cc: Wei Liu, Jan Beulich, Andrew Cooper, Suravee Suthikulpanit,
	Brian Woods, Roger Pau Monné

Most of these issues would be XSAs if these paths were accessible to guests.

First, override the {get,put}_gfn() helpers to use gfn_t, which was the
original purpose of this patch.

guest_iommu_get_table_mfn() has two bugs.  First, it gets a ref on one gfn,
and puts a ref for a different gfn.  This is only a latent bug for now, as we
don't do per-gfn locking yet.  Next, the mfn return value is unsafe to use
after put_gfn() is called, as the guest could have freed the page in the
meantime.

In addition, get_gfn_from_base_reg() erroneously asserts that base_raw can't
be 0, but it may legitimately be.  On top of that, the return value from
guest_iommu_get_table_mfn() is passed into map_domain_page() before checking
that it is a real mfn.

Most of the complexity here is inlining guest_iommu_get_table_mfn() and
holding the gfn reference until the operation is complete.

Furthermore, guest_iommu_process_command() is altered to take a local copy of
cmd_entry_t, rather than passing a pointer to guest controlled memory into
each of the handling functions.  It is also modified to break on error rather
than continue.  These changes are in line with the spec which states that the
IOMMU will strictly read a command entry once, and will cease processing if an
error is encountered.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
CC: Brian Woods <brian.woods@amd.com>

This patch my no means indicates that the code is ready for production use.
---
 xen/drivers/passthrough/amd/iommu_guest.c | 224 +++++++++++++++++++-----------
 1 file changed, 146 insertions(+), 78 deletions(-)

diff --git a/xen/drivers/passthrough/amd/iommu_guest.c b/xen/drivers/passthrough/amd/iommu_guest.c
index 96175bb..03ca0cf 100644
--- a/xen/drivers/passthrough/amd/iommu_guest.c
+++ b/xen/drivers/passthrough/amd/iommu_guest.c
@@ -21,6 +21,13 @@
 #include <asm/amd-iommu.h>
 #include <asm/hvm/svm/amd-iommu-proto.h>
 
+/* Override {get,put}_gfn to work with gfn_t */
+#undef get_gfn
+#define get_gfn(d, g, t) get_gfn_type(d, gfn_x(g), t, P2M_ALLOC)
+#undef get_gfn_query
+#define get_gfn_query(d, g, t) get_gfn_type(d, gfn_x(g), t, 0)
+#undef put_gfn
+#define put_gfn(d, g) __put_gfn(p2m_get_hostp2m(d), gfn_x(g))
 
 #define IOMMU_MMIO_SIZE                         0x8000
 #define IOMMU_MMIO_PAGE_NR                      0x8
@@ -117,13 +124,6 @@ static unsigned int host_domid(struct domain *d, uint64_t g_domid)
     return d->domain_id;
 }
 
-static unsigned long get_gfn_from_base_reg(uint64_t base_raw)
-{
-    base_raw &= PADDR_MASK;
-    ASSERT ( base_raw != 0 );
-    return base_raw >> PAGE_SHIFT;
-}
-
 static void guest_iommu_deliver_msi(struct domain *d)
 {
     uint8_t vector, dest, dest_mode, delivery_mode, trig_mode;
@@ -138,23 +138,6 @@ static void guest_iommu_deliver_msi(struct domain *d)
     vmsi_deliver(d, vector, dest, dest_mode, delivery_mode, trig_mode);
 }
 
-static unsigned long guest_iommu_get_table_mfn(struct domain *d,
-                                               uint64_t base_raw,
-                                               unsigned int entry_size,
-                                               unsigned int pos)
-{
-    unsigned long idx, gfn, mfn;
-    p2m_type_t p2mt;
-
-    gfn = get_gfn_from_base_reg(base_raw);
-    idx = (pos * entry_size) >> PAGE_SHIFT;
-
-    mfn = mfn_x(get_gfn(d, gfn + idx, &p2mt));
-    put_gfn(d, gfn);
-
-    return mfn;
-}
-
 static void guest_iommu_enable_dev_table(struct guest_iommu *iommu)
 {
     uint32_t length_raw = get_field_from_reg_u32(iommu->dev_table.reg_base.lo,
@@ -176,7 +159,10 @@ static void guest_iommu_enable_ring_buffer(struct guest_iommu *iommu,
 void guest_iommu_add_ppr_log(struct domain *d, u32 entry[])
 {
     uint16_t gdev_id;
-    unsigned long mfn, tail, head;
+    unsigned long tail, head;
+    mfn_t mfn;
+    gfn_t gfn;
+    p2m_type_t p2mt;
     ppr_entry_t *log, *log_base;
     struct guest_iommu *iommu;
 
@@ -197,11 +183,24 @@ void guest_iommu_add_ppr_log(struct domain *d, u32 entry[])
         return;
     }
 
-    mfn = guest_iommu_get_table_mfn(d, reg_to_u64(iommu->ppr_log.reg_base),
-                                    sizeof(ppr_entry_t), tail);
-    ASSERT(mfn_valid(_mfn(mfn)));
+    gfn = _gfn(PFN_DOWN(reg_to_u64(iommu->ppr_log.reg_base)) +
+               PFN_DOWN(tail * sizeof(*log)));
 
-    log_base = map_domain_page(_mfn(mfn));
+    mfn = get_gfn(d, gfn, &p2mt);
+    if ( mfn_eq(mfn, INVALID_MFN) || !p2m_is_ram(p2mt) )
+    {
+        AMD_IOMMU_DEBUG(
+            "Error: guest iommu ppr log bad gfn %"PRI_gfn", type %u, mfn %"
+            PRI_mfn", reg_base %#"PRIx64", tail %#lx\n",
+            gfn_x(gfn), p2mt, mfn_x(mfn),
+            reg_to_u64(iommu->ppr_log.reg_base), tail);
+        guest_iommu_disable(iommu);
+        goto out;
+    }
+
+    ASSERT(mfn_valid(mfn));
+
+    log_base = map_domain_page(mfn);
     log = log_base + tail % (PAGE_SIZE / sizeof(ppr_entry_t));
 
     /* Convert physical device id back into virtual device id */
@@ -220,12 +219,18 @@ void guest_iommu_add_ppr_log(struct domain *d, u32 entry[])
     unmap_domain_page(log_base);
 
     guest_iommu_deliver_msi(d);
+
+out:
+    put_gfn(d, gfn);
 }
 
 void guest_iommu_add_event_log(struct domain *d, u32 entry[])
 {
     uint16_t dev_id;
-    unsigned long mfn, tail, head;
+    unsigned long tail, head;
+    mfn_t mfn;
+    gfn_t gfn;
+    p2m_type_t p2mt;
     event_entry_t *log, *log_base;
     struct guest_iommu *iommu;
 
@@ -246,11 +251,24 @@ void guest_iommu_add_event_log(struct domain *d, u32 entry[])
         return;
     }
 
-    mfn = guest_iommu_get_table_mfn(d, reg_to_u64(iommu->event_log.reg_base),
-                                    sizeof(event_entry_t), tail);
-    ASSERT(mfn_valid(_mfn(mfn)));
+    gfn = _gfn(PFN_DOWN(reg_to_u64(iommu->event_log.reg_base)) +
+               PFN_DOWN(tail * sizeof(*log)));
+
+    mfn = get_gfn(d, gfn, &p2mt);
+    if ( mfn_eq(mfn, INVALID_MFN) || !p2m_is_ram(p2mt) )
+    {
+        AMD_IOMMU_DEBUG(
+            "Error: guest iommu event log bad gfn %"PRI_gfn", type %u, mfn %"
+            PRI_mfn", reg_base %#"PRIx64", tail %#lx\n",
+            gfn_x(gfn), p2mt, mfn_x(mfn),
+            reg_to_u64(iommu->ppr_log.reg_base), tail);
+        guest_iommu_disable(iommu);
+        goto out;
+    }
+
+    ASSERT(mfn_valid(mfn));
 
-    log_base = map_domain_page(_mfn(mfn));
+    log_base = map_domain_page(mfn);
     log = log_base + tail % (PAGE_SIZE / sizeof(event_entry_t));
 
     /* re-write physical device id into virtual device id */
@@ -269,6 +287,9 @@ void guest_iommu_add_event_log(struct domain *d, u32 entry[])
     unmap_domain_page(log_base);
 
     guest_iommu_deliver_msi(d);
+
+out:
+    put_gfn(d, gfn);
 }
 
 static int do_complete_ppr_request(struct domain *d, cmd_entry_t *cmd)
@@ -346,10 +367,8 @@ static int do_invalidate_iotlb_pages(struct domain *d, cmd_entry_t *cmd)
 
 static int do_completion_wait(struct domain *d, cmd_entry_t *cmd)
 {
-    bool_t com_wait_int_en, com_wait_int, i, s;
+    bool com_wait_int_en, com_wait_int, i, s;
     struct guest_iommu *iommu;
-    unsigned long gfn;
-    p2m_type_t p2mt;
 
     iommu = domain_iommu(d);
 
@@ -362,7 +381,10 @@ static int do_completion_wait(struct domain *d, cmd_entry_t *cmd)
     if ( s )
     {
         uint64_t gaddr_lo, gaddr_hi, gaddr_64, data;
-        void *vaddr;
+        mfn_t mfn;
+        gfn_t gfn;
+        p2m_type_t p2mt;
+        uint64_t *ptr;
 
         data = (uint64_t)cmd->data[3] << 32 | cmd->data[2];
         gaddr_lo = get_field_from_reg_u32(cmd->data[0],
@@ -374,13 +396,24 @@ static int do_completion_wait(struct domain *d, cmd_entry_t *cmd)
 
         gaddr_64 = (gaddr_hi << 32) | (gaddr_lo << 3);
 
-        gfn = gaddr_64 >> PAGE_SHIFT;
-        vaddr = map_domain_page(get_gfn(d, gfn ,&p2mt));
-        put_gfn(d, gfn);
+        gfn = _gfn(gaddr_64 >> PAGE_SHIFT);
+        mfn = get_gfn(d, gfn, &p2mt);
 
-        write_u64_atomic((uint64_t *)(vaddr + (gaddr_64 & (PAGE_SIZE-1))),
-                         data);
-        unmap_domain_page(vaddr);
+        if ( mfn_eq(mfn, INVALID_MFN) || !p2m_is_ram(p2mt) )
+        {
+            /* XXX - What to do here, error wise? */
+            guest_iommu_disable(iommu);
+            put_gfn(d, gfn);
+
+            return 0;
+        }
+
+        ptr = map_domain_page(mfn) + (gaddr_64 & ~PAGE_MASK);
+
+        write_u64_atomic(ptr, data);
+        unmap_domain_page(ptr);
+
+        put_gfn(d, gfn);
     }
 
     com_wait_int_en = iommu_get_bit(iommu->reg_ctrl.lo,
@@ -400,9 +433,10 @@ static int do_invalidate_dte(struct domain *d, cmd_entry_t *cmd)
     dev_entry_t *gdte, *mdte, *dte_base;
     struct amd_iommu *iommu = NULL;
     struct guest_iommu *g_iommu;
-    uint64_t gcr3_gfn, gcr3_mfn;
+    mfn_t dte_mfn, gcr3_mfn;
+    gfn_t dte_gfn, gcr3_gfn;
     uint8_t glx, gv;
-    unsigned long dte_mfn, flags;
+    unsigned long flags;
     p2m_type_t p2mt;
 
     g_iommu = domain_iommu(d);
@@ -417,35 +451,49 @@ static int do_invalidate_dte(struct domain *d, cmd_entry_t *cmd)
     if ( (gbdf * sizeof(dev_entry_t)) > g_iommu->dev_table.size )
         return 0;
 
-    dte_mfn = guest_iommu_get_table_mfn(d,
-                                        reg_to_u64(g_iommu->dev_table.reg_base),
-                                        sizeof(dev_entry_t), gbdf);
-    ASSERT(mfn_valid(_mfn(dte_mfn)));
+    dte_gfn = _gfn(PFN_DOWN(reg_to_u64(g_iommu->dev_table.reg_base)) +
+                   PFN_DOWN(gbdf * sizeof(*gdte)));
+    dte_mfn = get_gfn(d, dte_gfn, &p2mt);
+
+    if ( mfn_eq(dte_mfn, INVALID_MFN) || !p2m_is_ram(p2mt) )
+    {
+        put_gfn(d, dte_gfn);
+        return 0;
+    }
+
+    ASSERT(mfn_valid(dte_mfn));
 
     /* Read guest dte information */
-    dte_base = map_domain_page(_mfn(dte_mfn));
+    dte_base = map_domain_page(dte_mfn);
 
     gdte = dte_base + gbdf % (PAGE_SIZE / sizeof(dev_entry_t));
 
     gdom_id  = get_domid_from_dte(gdte);
-    gcr3_gfn = get_guest_cr3_from_dte(gdte);
+    gcr3_gfn = _gfn(get_guest_cr3_from_dte(gdte));
     glx      = get_glx_from_dte(gdte);
     gv       = get_gv_from_dte(gdte);
 
     unmap_domain_page(dte_base);
+    put_gfn(d, dte_gfn);
 
     /* Do not update host dte before gcr3 has been set */
-    if ( gcr3_gfn == 0 )
+    if ( gfn_x(gcr3_gfn) == 0 )
         return 0;
 
-    gcr3_mfn = mfn_x(get_gfn(d, gcr3_gfn, &p2mt));
-    put_gfn(d, gcr3_gfn);
+    gcr3_mfn = get_gfn(d, gcr3_gfn, &p2mt);
 
-    ASSERT(mfn_valid(_mfn(gcr3_mfn)));
+    if ( mfn_eq(gcr3_mfn, INVALID_MFN) || !p2m_is_ram(p2mt) )
+    {
+        put_gfn(d, gcr3_gfn);
+        return 0;
+    }
+
+    ASSERT(mfn_valid(gcr3_mfn));
 
     iommu = find_iommu_for_device(0, mbdf);
     if ( !iommu )
     {
+        put_gfn(d, gcr3_gfn);
         AMD_IOMMU_DEBUG("%s: Fail to find iommu for bdf %x!\n",
                         __func__, mbdf);
         return -ENODEV;
@@ -458,18 +506,19 @@ static int do_invalidate_dte(struct domain *d, cmd_entry_t *cmd)
 
     spin_lock_irqsave(&iommu->lock, flags);
     iommu_dte_set_guest_cr3((u32 *)mdte, hdom_id,
-                            gcr3_mfn << PAGE_SHIFT, gv, glx);
+                            mfn_to_maddr(gcr3_mfn), gv, glx);
 
     amd_iommu_flush_device(iommu, req_id);
     spin_unlock_irqrestore(&iommu->lock, flags);
 
+    put_gfn(d, gcr3_gfn);
+
     return 0;
 }
 
 static void guest_iommu_process_command(unsigned long _d)
 {
-    unsigned long opcode, tail, head, entries_per_page, cmd_mfn;
-    cmd_entry_t *cmd, *cmd_base;
+    unsigned long tail, head;
     struct domain *d = (struct domain *)_d;
     struct guest_iommu *iommu;
 
@@ -493,56 +542,75 @@ static void guest_iommu_process_command(unsigned long _d)
         return;
     }
 
-    entries_per_page = PAGE_SIZE / sizeof(cmd_entry_t);
-
     while ( head != tail )
     {
+        mfn_t mfn;
+        gfn_t gfn;
+        p2m_type_t p2mt;
+        cmd_entry_t cmd, *ptr;
         int ret = 0;
+        unsigned int opcode;
+
+        gfn = _gfn(PFN_DOWN(reg_to_u64(iommu->cmd_buffer.reg_base)) +
+                   PFN_DOWN(head * sizeof(cmd)));
 
-        cmd_mfn = guest_iommu_get_table_mfn(d,
-                                            reg_to_u64(iommu->cmd_buffer.reg_base),
-                                            sizeof(cmd_entry_t), head);
-        ASSERT(mfn_valid(_mfn(cmd_mfn)));
+        mfn = get_gfn(d, gfn, &p2mt);
+        if ( mfn_eq(mfn, INVALID_MFN) || !p2m_is_ram(p2mt) )
+        {
+            AMD_IOMMU_DEBUG(
+                "Error: guest iommu cmd buffer bad gfn %"PRI_gfn", type %u, mfn %"
+                PRI_mfn", reg_base %#"PRIx64", head %#lx\n",
+                gfn_x(gfn), p2mt, mfn_x(mfn),
+                reg_to_u64(iommu->cmd_buffer.reg_base), head);
+            put_gfn(d, gfn);
+            guest_iommu_disable(iommu);
+            return;
+        }
 
-        cmd_base = map_domain_page(_mfn(cmd_mfn));
-        cmd = cmd_base + head % entries_per_page;
+        ptr = map_domain_page(mfn) + head % (PAGE_SIZE / sizeof(cmd_entry_t));
+        memcpy(&cmd, ptr, sizeof(cmd));
+        unmap_domain_page(ptr);
+        put_gfn(d, gfn);
 
-        opcode = get_field_from_reg_u32(cmd->data[1],
+        opcode = get_field_from_reg_u32(cmd.data[1],
                                         IOMMU_CMD_OPCODE_MASK,
                                         IOMMU_CMD_OPCODE_SHIFT);
         switch ( opcode )
         {
         case IOMMU_CMD_COMPLETION_WAIT:
-            ret = do_completion_wait(d, cmd);
+            ret = do_completion_wait(d, &cmd);
             break;
         case IOMMU_CMD_INVALIDATE_DEVTAB_ENTRY:
-            ret = do_invalidate_dte(d, cmd);
+            ret = do_invalidate_dte(d, &cmd);
             break;
         case IOMMU_CMD_INVALIDATE_IOMMU_PAGES:
-            ret = do_invalidate_pages(d, cmd);
+            ret = do_invalidate_pages(d, &cmd);
             break;
         case IOMMU_CMD_INVALIDATE_IOTLB_PAGES:
-            ret = do_invalidate_iotlb_pages(d, cmd);
+            ret = do_invalidate_iotlb_pages(d, &cmd);
             break;
         case IOMMU_CMD_INVALIDATE_INT_TABLE:
             break;
         case IOMMU_CMD_COMPLETE_PPR_REQUEST:
-            ret = do_complete_ppr_request(d, cmd);
+            ret = do_complete_ppr_request(d, &cmd);
             break;
         case IOMMU_CMD_INVALIDATE_IOMMU_ALL:
-            ret = do_invalidate_all(d, cmd);
+            ret = do_invalidate_all(d, &cmd);
             break;
         default:
-            AMD_IOMMU_DEBUG("CMD: Unknown command cmd_type = %lx "
+            AMD_IOMMU_DEBUG("CMD: Unknown command cmd_type = %#x "
                             "head = %ld\n", opcode, head);
+            ret = -EINVAL;
             break;
         }
 
-        unmap_domain_page(cmd_base);
         if ( ++head >= iommu->cmd_buffer.entries )
             head = 0;
         if ( ret )
+        {
             guest_iommu_disable(iommu);
+            break;
+        }
     }
 
     /* Now shift cmd buffer head pointer */
@@ -818,10 +886,10 @@ int guest_iommu_set_base(struct domain *d, uint64_t base)
 
     for ( int i = 0; i < IOMMU_MMIO_PAGE_NR; i++ )
     {
-        unsigned long gfn = base + i;
+        gfn_t gfn = _gfn(base + i);
 
         get_gfn_query(d, gfn, &t);
-        p2m_change_type_one(d, gfn, t, p2m_mmio_dm);
+        p2m_change_type_one(d, gfn_x(gfn), t, p2m_mmio_dm);
         put_gfn(d, gfn);
     }
 
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 04/14] x86/p2m: Fix locking in p2m_altp2m_lazy_copy()
  2018-11-21 13:21 [PATCH 00/14] XSA-277 followup Andrew Cooper
                   ` (2 preceding siblings ...)
  2018-11-21 13:21 ` [PATCH 03/14] AMD/IOMMU: Fix multiple reference counting errors Andrew Cooper
@ 2018-11-21 13:21 ` Andrew Cooper
  2018-11-21 13:59   ` Razvan Cojocaru
  2018-11-22 15:01   ` Jan Beulich
  2018-11-21 13:21 ` [PATCH 05/14] x86/p2m: Don't overwrite p2m_altp2m_lazy_copy()'s callers p2m pointer Andrew Cooper
                   ` (11 subsequent siblings)
  15 siblings, 2 replies; 59+ messages in thread
From: Andrew Cooper @ 2018-11-21 13:21 UTC (permalink / raw)
  To: Xen-devel
  Cc: Tamas K Lengyel, Wei Liu, Razvan Cojocaru, George Dunlap,
	Andrew Cooper, Jan Beulich, Roger Pau Monné

The gfn references need to remain held until after the p2m_set_entry() has
completed.  This is only a latent bug for now, because there is no per-gfn
locking and we recursively hold the main p2m locks.

Rearrange the code to have a single exit path, and defer taking the ap2m lock
until it is necessary to do so.  Leave some comments behind to help people
attempting to follow the logic.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Razvan Cojocaru <rcojocaru@bitdefender.com>
CC: Tamas K Lengyel <tamas@tklengyel.com>
CC: George Dunlap <george.dunlap@eu.citrix.com>
---
 xen/arch/x86/mm/p2m.c | 27 ++++++++++++++++++++-------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
index b5a59d6..ae9cb20 100644
--- a/xen/arch/x86/mm/p2m.c
+++ b/xen/arch/x86/mm/p2m.c
@@ -2184,24 +2184,29 @@ bool_t p2m_altp2m_lazy_copy(struct vcpu *v, paddr_t gpa,
     unsigned long mask;
     mfn_t mfn;
     int rv;
+    bool ret;
 
     *ap2m = p2m_get_altp2m(v);
 
     mfn = get_gfn_type_access(*ap2m, gfn_x(gfn), &p2mt, &p2ma,
                               0, &page_order);
-    __put_gfn(*ap2m, gfn_x(gfn));
 
+    /* Entry already present in ap2m?  Caller should handle the fault. */
     if ( !mfn_eq(mfn, INVALID_MFN) )
-        return 0;
+    {
+        ret = false;
+        goto put_ap2m;
+    }
 
     mfn = get_gfn_type_access(hp2m, gfn_x(gfn), &p2mt, &p2ma,
                               P2M_ALLOC, &page_order);
-    __put_gfn(hp2m, gfn_x(gfn));
 
+    /* Entry not present in hp2m?  Caller should handle the fault. */
     if ( mfn_eq(mfn, INVALID_MFN) )
-        return 0;
-
-    p2m_lock(*ap2m);
+    {
+        ret = false;
+        goto put_hp2m;
+    }
 
     /*
      * If this is a superpage mapping, round down both frame numbers
@@ -2211,6 +2216,7 @@ bool_t p2m_altp2m_lazy_copy(struct vcpu *v, paddr_t gpa,
     mfn = _mfn(mfn_x(mfn) & mask);
     gfn = _gfn(gfn_x(gfn) & mask);
 
+    p2m_lock(*ap2m);
     rv = p2m_set_entry(*ap2m, gfn, mfn, page_order, p2mt, p2ma);
     p2m_unlock(*ap2m);
 
@@ -2222,7 +2228,14 @@ bool_t p2m_altp2m_lazy_copy(struct vcpu *v, paddr_t gpa,
         domain_crash(hp2m->domain);
     }
 
-    return 1;
+    ret = true;
+
+put_hp2m:
+    __put_gfn(hp2m, gfn_x(gfn));
+put_ap2m:
+    __put_gfn(*ap2m, gfn_x(gfn));
+
+    return ret;
 }
 
 void p2m_flush_altp2m(struct domain *d)
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 05/14] x86/p2m: Don't overwrite p2m_altp2m_lazy_copy()'s callers p2m pointer
  2018-11-21 13:21 [PATCH 00/14] XSA-277 followup Andrew Cooper
                   ` (3 preceding siblings ...)
  2018-11-21 13:21 ` [PATCH 04/14] x86/p2m: Fix locking in p2m_altp2m_lazy_copy() Andrew Cooper
@ 2018-11-21 13:21 ` Andrew Cooper
  2018-11-21 14:07   ` Razvan Cojocaru
  2018-11-22 15:03   ` Jan Beulich
  2018-11-21 13:21 ` [PATCH 06/14] x86/hvm: Make the altp2m locking easier to follow Andrew Cooper
                   ` (10 subsequent siblings)
  15 siblings, 2 replies; 59+ messages in thread
From: Andrew Cooper @ 2018-11-21 13:21 UTC (permalink / raw)
  To: Xen-devel
  Cc: Tamas K Lengyel, Wei Liu, Razvan Cojocaru, George Dunlap,
	Andrew Cooper, Jan Beulich, Roger Pau Monné

The final parameter to p2m_altp2m_lazy_copy() appears to be unnecessary, and
results in very hard-to-follow code.  Have the sole caller set its local p2m
pointer appropriately, and drop the parameter.

With that done, a level of indirection of ap2m can be dropped inside
p2m_altp2m_lazy_copy().  While changing the API, switch it from bool_t to
bool, and drop printing of the altp2m's virtual address, because it is of no
use even when debugging.

No (intended) overall change in behaviour.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
--
CC: Jan Beulich <JBeulich@suse.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Razvan Cojocaru <rcojocaru@bitdefender.com>
CC: Tamas K Lengyel <tamas@tklengyel.com>
CC: George Dunlap <george.dunlap@eu.citrix.com>
---
 xen/arch/x86/hvm/hvm.c    |  4 +++-
 xen/arch/x86/mm/p2m.c     | 24 ++++++++++++------------
 xen/include/asm-x86/p2m.h |  4 ++--
 3 files changed, 17 insertions(+), 15 deletions(-)

diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index e2e4204..94fe441 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -1760,7 +1760,9 @@ int hvm_hap_nested_page_fault(paddr_t gpa, unsigned long gla,
 
     if ( ap2m_active )
     {
-        if ( p2m_altp2m_lazy_copy(curr, gpa, gla, npfec, &p2m) )
+        p2m = p2m_get_altp2m(curr);
+
+        if ( p2m_altp2m_lazy_copy(curr, gpa, gla, npfec) )
         {
             /* entry was lazily copied from host -- retry */
             __put_gfn(hostp2m, gfn);
diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
index ae9cb20..8b9898a 100644
--- a/xen/arch/x86/mm/p2m.c
+++ b/xen/arch/x86/mm/p2m.c
@@ -2172,23 +2172,23 @@ bool_t p2m_switch_vcpu_altp2m_by_id(struct vcpu *v, unsigned int idx)
  *     indicate that outer handler should handle fault
  */
 
-bool_t p2m_altp2m_lazy_copy(struct vcpu *v, paddr_t gpa,
-                            unsigned long gla, struct npfec npfec,
-                            struct p2m_domain **ap2m)
+bool p2m_altp2m_lazy_copy(struct vcpu *v, paddr_t gpa,
+                          unsigned long gla, struct npfec npfec)
 {
     struct p2m_domain *hp2m = p2m_get_hostp2m(v->domain);
+    struct p2m_domain *ap2m = p2m_get_altp2m(v);
     p2m_type_t p2mt;
     p2m_access_t p2ma;
     unsigned int page_order;
-    gfn_t gfn = _gfn(paddr_to_pfn(gpa));
+    gfn_t gfn = gaddr_to_gfn(gpa);
     unsigned long mask;
     mfn_t mfn;
     int rv;
     bool ret;
 
-    *ap2m = p2m_get_altp2m(v);
+    ASSERT(p2m_locked_by_me(hp2m));
 
-    mfn = get_gfn_type_access(*ap2m, gfn_x(gfn), &p2mt, &p2ma,
+    mfn = get_gfn_type_access(ap2m, gfn_x(gfn), &p2mt, &p2ma,
                               0, &page_order);
 
     /* Entry already present in ap2m?  Caller should handle the fault. */
@@ -2216,15 +2216,15 @@ bool_t p2m_altp2m_lazy_copy(struct vcpu *v, paddr_t gpa,
     mfn = _mfn(mfn_x(mfn) & mask);
     gfn = _gfn(gfn_x(gfn) & mask);
 
-    p2m_lock(*ap2m);
-    rv = p2m_set_entry(*ap2m, gfn, mfn, page_order, p2mt, p2ma);
-    p2m_unlock(*ap2m);
+    p2m_lock(ap2m);
+    rv = p2m_set_entry(ap2m, gfn, mfn, page_order, p2mt, p2ma);
+    p2m_unlock(ap2m);
 
     if ( rv )
     {
         gdprintk(XENLOG_ERR,
-	    "failed to set entry for %#"PRIx64" -> %#"PRIx64" p2m %#"PRIx64"\n",
-	    gfn_x(gfn), mfn_x(mfn), (unsigned long)*ap2m);
+	    "failed to set entry for %#"PRIx64" -> %#"PRIx64"\n",
+	    gfn_x(gfn), mfn_x(mfn));
         domain_crash(hp2m->domain);
     }
 
@@ -2233,7 +2233,7 @@ bool_t p2m_altp2m_lazy_copy(struct vcpu *v, paddr_t gpa,
 put_hp2m:
     __put_gfn(hp2m, gfn_x(gfn));
 put_ap2m:
-    __put_gfn(*ap2m, gfn_x(gfn));
+    __put_gfn(ap2m, gfn_x(gfn));
 
     return ret;
 }
diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h
index 6d849a5..04c2104 100644
--- a/xen/include/asm-x86/p2m.h
+++ b/xen/include/asm-x86/p2m.h
@@ -868,8 +868,8 @@ void p2m_altp2m_check(struct vcpu *v, uint16_t idx);
 void p2m_flush_altp2m(struct domain *d);
 
 /* Alternate p2m paging */
-bool_t p2m_altp2m_lazy_copy(struct vcpu *v, paddr_t gpa,
-    unsigned long gla, struct npfec npfec, struct p2m_domain **ap2m);
+bool p2m_altp2m_lazy_copy(struct vcpu *v, paddr_t gpa,
+                          unsigned long gla, struct npfec npfec);
 
 /* Make a specific alternate p2m valid */
 int p2m_init_altp2m_by_id(struct domain *d, unsigned int idx);
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 06/14] x86/hvm: Make the altp2m locking easier to follow
  2018-11-21 13:21 [PATCH 00/14] XSA-277 followup Andrew Cooper
                   ` (4 preceding siblings ...)
  2018-11-21 13:21 ` [PATCH 05/14] x86/p2m: Don't overwrite p2m_altp2m_lazy_copy()'s callers p2m pointer Andrew Cooper
@ 2018-11-21 13:21 ` Andrew Cooper
  2018-11-21 14:43   ` Razvan Cojocaru
  2018-11-22 15:08   ` Jan Beulich
  2018-11-21 13:21 ` [PATCH 07/14] x86/p2m: Coding style cleanup Andrew Cooper
                   ` (9 subsequent siblings)
  15 siblings, 2 replies; 59+ messages in thread
From: Andrew Cooper @ 2018-11-21 13:21 UTC (permalink / raw)
  To: Xen-devel
  Cc: Tamas K Lengyel, Wei Liu, Razvan Cojocaru, George Dunlap,
	Andrew Cooper, Jan Beulich, Roger Pau Monné

Drop the ap2m_active boolean, and consistently use the unlocking form:

  if ( p2m != hostp2m )
       __put_gfn(p2m, gfn);
  __put_gfn(hostp2m, gfn);

which makes it clear that we always unlock the altp2m's gfn if it is in use,
and always unlock the hostp2m's gfn.  This also drops the ternary expression
in the logdirty case.

Extend the logdirty comment to identify where the locking violation is liable
to occur.

No (intended) overall change in behaviour.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Razvan Cojocaru <rcojocaru@bitdefender.com>
CC: Tamas K Lengyel <tamas@tklengyel.com>
CC: George Dunlap <george.dunlap@eu.citrix.com>
---
 xen/arch/x86/hvm/hvm.c | 21 ++++++++++-----------
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 94fe441..db60f23 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -1689,7 +1689,7 @@ int hvm_hap_nested_page_fault(paddr_t gpa, unsigned long gla,
     int rc, fall_through = 0, paged = 0;
     int sharing_enomem = 0;
     vm_event_request_t *req_ptr = NULL;
-    bool_t ap2m_active, sync = 0;
+    bool sync = false;
 
     /* On Nested Virtualization, walk the guest page table.
      * If this succeeds, all is fine.
@@ -1747,8 +1747,6 @@ int hvm_hap_nested_page_fault(paddr_t gpa, unsigned long gla,
         goto out;
     }
 
-    ap2m_active = altp2m_active(currd);
-
     /*
      * Take a lock on the host p2m speculatively, to avoid potential
      * locking order problems later and to handle unshare etc.
@@ -1758,7 +1756,7 @@ int hvm_hap_nested_page_fault(paddr_t gpa, unsigned long gla,
                               P2M_ALLOC | (npfec.write_access ? P2M_UNSHARE : 0),
                               NULL);
 
-    if ( ap2m_active )
+    if ( altp2m_active(currd) )
     {
         p2m = p2m_get_altp2m(curr);
 
@@ -1882,13 +1880,14 @@ int hvm_hap_nested_page_fault(paddr_t gpa, unsigned long gla,
         {
             paging_mark_pfn_dirty(currd, _pfn(gfn));
             /*
-             * If p2m is really an altp2m, unlock here to avoid lock ordering
-             * violation when the change below is propagated from host p2m.
+             * If p2m is really an altp2m, unlock it before changing the type,
+             * as p2m_altp2m_propagate_change() needs to acquire the
+             * altp2m_list lock.
              */
-            if ( ap2m_active )
+            if ( p2m != hostp2m )
                 __put_gfn(p2m, gfn);
             p2m_change_type_one(currd, gfn, p2m_ram_logdirty, p2m_ram_rw);
-            __put_gfn(ap2m_active ? hostp2m : p2m, gfn);
+            __put_gfn(hostp2m, gfn);
 
             goto out;
         }
@@ -1909,9 +1908,9 @@ int hvm_hap_nested_page_fault(paddr_t gpa, unsigned long gla,
     rc = fall_through;
 
  out_put_gfn:
-    __put_gfn(p2m, gfn);
-    if ( ap2m_active )
-        __put_gfn(hostp2m, gfn);
+    if ( p2m != hostp2m )
+        __put_gfn(p2m, gfn);
+    __put_gfn(hostp2m, gfn);
  out:
     /* All of these are delayed until we exit, since we might 
      * sleep on event ring wait queues, and we must not hold
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 07/14] x86/p2m: Coding style cleanup
  2018-11-21 13:21 [PATCH 00/14] XSA-277 followup Andrew Cooper
                   ` (5 preceding siblings ...)
  2018-11-21 13:21 ` [PATCH 06/14] x86/hvm: Make the altp2m locking easier to follow Andrew Cooper
@ 2018-11-21 13:21 ` Andrew Cooper
  2018-11-22 15:12   ` Jan Beulich
  2018-11-21 13:21 ` [PATCH 08/14] xen/memory: Drop ARM put_gfn() stub Andrew Cooper
                   ` (8 subsequent siblings)
  15 siblings, 1 reply; 59+ messages in thread
From: Andrew Cooper @ 2018-11-21 13:21 UTC (permalink / raw)
  To: Xen-devel
  Cc: George Dunlap, Andrew Cooper, Wei Liu, Jan Beulich, Roger Pau Monné

No functional change.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: George Dunlap <george.dunlap@eu.citrix.com>
---
 xen/arch/x86/mm/p2m.c     | 29 ++++++++-------
 xen/include/asm-x86/p2m.h | 91 ++++++++++++++++++++++++++---------------------
 2 files changed, 65 insertions(+), 55 deletions(-)

diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
index 8b9898a..f52a71e 100644
--- a/xen/arch/x86/mm/p2m.c
+++ b/xen/arch/x86/mm/p2m.c
@@ -444,7 +444,7 @@ mfn_t __get_gfn_type_access(struct p2m_domain *p2m, unsigned long gfn_l,
         mfn = p2m->get_entry(p2m, gfn, t, a, q, page_order, NULL);
     }
 
-    if (unlikely((p2m_is_broken(*t))))
+    if ( unlikely(p2m_is_broken(*t)) )
     {
         /* Return invalid_mfn to avoid caller's access */
         mfn = INVALID_MFN;
@@ -669,7 +669,7 @@ void p2m_teardown(struct p2m_domain *p2m)
     struct page_info *pg;
     struct domain *d;
 
-    if (p2m == NULL)
+    if ( p2m == NULL )
         return;
 
     d = p2m->domain;
@@ -776,7 +776,7 @@ guest_physmap_add_entry(struct domain *d, gfn_t gfn, mfn_t mfn,
                               &a, 0, NULL, NULL);
         if ( p2m_is_shared(ot) )
         {
-            /* Do an unshare to cleanly take care of all corner 
+            /* Do an unshare to cleanly take care of all corner
              * cases. */
             int rc;
             rc = mem_sharing_unshare_page(p2m->domain,
@@ -793,7 +793,7 @@ guest_physmap_add_entry(struct domain *d, gfn_t gfn, mfn_t mfn,
                  * However, all current (changeset 3432abcf9380) code
                  * paths avoid this unsavoury situation. For now.
                  *
-                 * Foreign domains are okay to place an event as they 
+                 * Foreign domains are okay to place an event as they
                  * won't go to sleep. */
                 (void)mem_sharing_notify_enomem(p2m->domain,
                                                 gfn_x(gfn_add(gfn, i)), false);
@@ -808,7 +808,7 @@ guest_physmap_add_entry(struct domain *d, gfn_t gfn, mfn_t mfn,
             /* Really shouldn't be unmapping grant/foreign maps this way */
             domain_crash(d);
             p2m_unlock(p2m);
-            
+
             return -EINVAL;
         }
         else if ( p2m_is_ram(ot) && !p2m_is_paged(ot) )
@@ -934,7 +934,7 @@ int p2m_change_type_one(struct domain *d, unsigned long gfn_l,
 }
 
 /* Modify the p2m type of a range of gfns from ot to nt. */
-void p2m_change_type_range(struct domain *d, 
+void p2m_change_type_range(struct domain *d,
                            unsigned long start, unsigned long end,
                            p2m_type_t ot, p2m_type_t nt)
 {
@@ -1568,7 +1568,7 @@ int p2m_mem_paging_prep(struct domain *d, unsigned long gfn_l, uint64_t buffer)
 
     if ( user_ptr )
         /* Sanity check the buffer and bail out early if trouble */
-        if ( (buffer & (PAGE_SIZE - 1)) || 
+        if ( (buffer & (PAGE_SIZE - 1)) ||
              (!access_ok(user_ptr, PAGE_SIZE)) )
             return -EINVAL;
 
@@ -1613,7 +1613,7 @@ int p2m_mem_paging_prep(struct domain *d, unsigned long gfn_l, uint64_t buffer)
                                  "bytes left %d\n", gfn_l, d->domain_id, rc);
             ret = -EFAULT;
             put_page(page); /* Don't leak pages */
-            goto out;            
+            goto out;
         }
     }
 
@@ -1685,7 +1685,7 @@ static struct p2m_domain *
 p2m_getlru_nestedp2m(struct domain *d, struct p2m_domain *p2m)
 {
     struct list_head *lru_list = &p2m_get_hostp2m(d)->np2m_list;
-    
+
     ASSERT(!list_empty(lru_list));
 
     if ( p2m == NULL )
@@ -1825,13 +1825,12 @@ p2m_get_nestedp2m_locked(struct vcpu *v)
     /* Mask out low bits; this avoids collisions with P2M_BASE_EADDR */
     np2m_base &= ~(0xfffull);
 
-    if (nv->nv_flushp2m && nv->nv_p2m) {
+    if ( nv->nv_flushp2m && nv->nv_p2m )
         nv->nv_p2m = NULL;
-    }
 
     nestedp2m_lock(d);
     p2m = nv->nv_p2m;
-    if ( p2m ) 
+    if ( p2m )
     {
         p2m_lock(p2m);
         if ( p2m->np2m_base == np2m_base )
@@ -1889,7 +1888,7 @@ struct p2m_domain *p2m_get_nestedp2m(struct vcpu *v)
 struct p2m_domain *
 p2m_get_p2m(struct vcpu *v)
 {
-    if (!nestedhvm_is_n2(v))
+    if ( !nestedhvm_is_n2(v) )
         return p2m_get_hostp2m(v->domain);
 
     return p2m_get_nestedp2m(v);
@@ -2554,7 +2553,7 @@ void audit_p2m(struct domain *d,
     p2m_lock(p2m);
     pod_lock(p2m);
 
-    if (p2m->audit_p2m)
+    if ( p2m->audit_p2m )
         pmbad = p2m->audit_p2m(p2m);
 
     /* Audit part two: walk the domain's page allocation list, checking
@@ -2615,7 +2614,7 @@ void audit_p2m(struct domain *d,
 
     pod_unlock(p2m);
     p2m_unlock(p2m);
- 
+
     P2M_PRINTK("p2m audit complete\n");
     if ( orphans_count | mpbad | pmbad )
         P2M_PRINTK("p2m audit found %lu orphans\n", orphans_count);
diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h
index 04c2104..74d0cf6 100644
--- a/xen/include/asm-x86/p2m.h
+++ b/xen/include/asm-x86/p2m.h
@@ -34,9 +34,9 @@
 extern bool_t opt_hap_1gb, opt_hap_2mb;
 
 /*
- * The upper levels of the p2m pagetable always contain full rights; all 
+ * The upper levels of the p2m pagetable always contain full rights; all
  * variation in the access control bits is made in the level-1 PTEs.
- * 
+ *
  * In addition to the phys-to-machine translation, each p2m PTE contains
  * *type* information about the gfn it translates, helping Xen to decide
  * on the correct course of action when handling a page-fault to that
@@ -47,8 +47,8 @@ extern bool_t opt_hap_1gb, opt_hap_2mb;
  */
 
 /*
- * AMD IOMMU: When we share p2m table with iommu, bit 52 -bit 58 in pte 
- * cannot be non-zero, otherwise, hardware generates io page faults when 
+ * AMD IOMMU: When we share p2m table with iommu, bit 52 -bit 58 in pte
+ * cannot be non-zero, otherwise, hardware generates io page faults when
  * device access those pages. Therefore, p2m_ram_rw has to be defined as 0.
  */
 typedef enum {
@@ -212,9 +212,11 @@ struct p2m_domain {
     uint64_t           np2m_base;
     uint64_t           np2m_generation;
 
-    /* Nested p2ms: linked list of n2pms allocated to this domain. 
-     * The host p2m hasolds the head of the list and the np2ms are 
-     * threaded on in LRU order. */
+    /*
+     * Nested p2ms: linked list of n2pms allocated to this domain.
+     * The host p2m hasolds the head of the list and the np2ms are
+     * threaded on in LRU order.
+     */
     struct list_head   np2m_list;
 #endif
 
@@ -224,10 +226,12 @@ struct p2m_domain {
     /* Host p2m: Global log-dirty mode enabled for the domain. */
     bool_t             global_logdirty;
 
-    /* Host p2m: when this flag is set, don't flush all the nested-p2m 
-     * tables on every host-p2m change.  The setter of this flag 
+    /*
+     * Host p2m: when this flag is set, don't flush all the nested-p2m
+     * tables on every host-p2m change.  The setter of this flag
      * is responsible for performing the full flush before releasing the
-     * host p2m's lock. */
+     * host p2m's lock.
+     */
     int                defer_nested_flush;
 
 #ifdef CONFIG_HVM
@@ -264,7 +268,7 @@ struct p2m_domain {
                                                   unsigned long first_gfn,
                                                   unsigned long last_gfn);
     void               (*memory_type_changed)(struct p2m_domain *p2m);
-    
+
     void               (*write_p2m_entry)(struct p2m_domain *p2m,
                                           unsigned long gfn, l1_pgentry_t *p,
                                           l1_pgentry_t new, unsigned int level);
@@ -291,8 +295,10 @@ struct p2m_domain {
      * retyped get this access type.  See definition of p2m_access_t. */
     p2m_access_t default_access;
 
-    /* If true, and an access fault comes in and there is no vm_event listener, 
-     * pause domain.  Otherwise, remove access restrictions. */
+    /*
+     * If true, and an access fault comes in and there is no vm_event listener,
+     * pause domain.  Otherwise, remove access restrictions.
+     */
     bool_t       access_required;
 
     /* Highest guest frame that's ever been mapped in the p2m */
@@ -310,13 +316,15 @@ struct p2m_domain {
     unsigned long next_shared_gfn_to_relinquish;
 
 #ifdef CONFIG_HVM
-    /* Populate-on-demand variables
+    /*
+     * Populate-on-demand variables
      * All variables are protected with the pod lock. We cannot rely on
      * the p2m lock if it's turned into a fine-grained lock.
-     * We only use the domain page_alloc lock for additions and 
+     * We only use the domain page_alloc lock for additions and
      * deletions to the domain's page list. Because we use it nested
      * within the PoD lock, we enforce it's ordering (by remembering
-     * the unlock level in the arch_domain sub struct). */
+     * the unlock level in the arch_domain sub struct).
+     */
     struct {
         struct page_list_head super,   /* List of superpages                */
                          single;       /* Non-super lists                   */
@@ -426,13 +434,15 @@ mfn_t __nonnull(3, 4) __get_gfn_type_access(
     struct p2m_domain *p2m, unsigned long gfn, p2m_type_t *t,
     p2m_access_t *a, p2m_query_t q, unsigned int *page_order, bool_t locked);
 
-/* Read a particular P2M table, mapping pages as we go.  Most callers
+/*
+ * Read a particular P2M table, mapping pages as we go.  Most callers
  * should _not_ call this directly; use the other get_gfn* functions
  * below unless you know you want to walk a p2m that isn't a domain's
  * main one.
- * If the lookup succeeds, the return value is != INVALID_MFN and 
+ * If the lookup succeeds, the return value is != INVALID_MFN and
  * *page_order is filled in with the order of the superpage (if any) that
- * the entry was found in.  */
+ * the entry was found in.
+ */
 static inline mfn_t __nonnull(3, 4) get_gfn_type_access(
     struct p2m_domain *p2m, unsigned long gfn, p2m_type_t *t,
     p2m_access_t *a, p2m_query_t q, unsigned int *page_order)
@@ -459,10 +469,11 @@ void __put_gfn(struct p2m_domain *p2m, unsigned long gfn);
 
 #define put_gfn(d, gfn) __put_gfn(p2m_get_hostp2m((d)), (gfn))
 
-/* The intent of the "unlocked" accessor is to have the caller not worry about
- * put_gfn. They apply to very specific situations: debug printk's, dumps 
- * during a domain crash, or to peek at a p2m entry/type. Caller is not 
- * holding the p2m entry exclusively during or after calling this. 
+/*
+ * The intent of the "unlocked" accessor is to have the caller not worry about
+ * put_gfn. They apply to very specific situations: debug printk's, dumps
+ * during a domain crash, or to peek at a p2m entry/type. Caller is not
+ * holding the p2m entry exclusively during or after calling this.
  *
  * This is also used in the shadow code whenever the paging lock is
  * held -- in those cases, the caller is protected against concurrent
@@ -473,19 +484,21 @@ void __put_gfn(struct p2m_domain *p2m, unsigned long gfn);
  * Any other type of query can cause a change in the p2m and may need to
  * perform locking.
  */
-static inline mfn_t get_gfn_query_unlocked(struct domain *d, 
-                                           unsigned long gfn, 
+static inline mfn_t get_gfn_query_unlocked(struct domain *d,
+                                           unsigned long gfn,
                                            p2m_type_t *t)
 {
     p2m_access_t a;
     return __get_gfn_type_access(p2m_get_hostp2m(d), gfn, t, &a, 0, NULL, 0);
 }
 
-/* Atomically look up a GFN and take a reference count on the backing page.
+/*
+ * Atomically look up a GFN and take a reference count on the backing page.
  * This makes sure the page doesn't get freed (or shared) underfoot,
  * and should be used by any path that intends to write to the backing page.
  * Returns NULL if the page is not backed by RAM.
- * The caller is responsible for calling put_page() afterwards. */
+ * The caller is responsible for calling put_page() afterwards.
+ */
 struct page_info *p2m_get_page_from_gfn(struct p2m_domain *p2m, gfn_t gfn,
                                         p2m_type_t *t, p2m_access_t *a,
                                         p2m_query_t q);
@@ -525,7 +538,7 @@ struct two_gfns {
 /* Returns mfn, type and access for potential caller consumption, but any
  * of those can be NULL */
 static inline void get_two_gfns(struct domain *rd, unsigned long rgfn,
-        p2m_type_t *rt, p2m_access_t *ra, mfn_t *rmfn, struct domain *ld, 
+        p2m_type_t *rt, p2m_access_t *ra, mfn_t *rmfn, struct domain *ld,
         unsigned long lgfn, p2m_type_t *lt, p2m_access_t *la, mfn_t *lmfn,
         p2m_query_t q, struct two_gfns *rval)
 {
@@ -556,9 +569,9 @@ do {                                                    \
 #undef assign_pointers
 
     /* Now do the gets */
-    *first_mfn  = get_gfn_type_access(p2m_get_hostp2m(rval->first_domain), 
+    *first_mfn  = get_gfn_type_access(p2m_get_hostp2m(rval->first_domain),
                                       rval->first_gfn, first_t, first_a, q, NULL);
-    *second_mfn = get_gfn_type_access(p2m_get_hostp2m(rval->second_domain), 
+    *second_mfn = get_gfn_type_access(p2m_get_hostp2m(rval->second_domain),
                                       rval->second_gfn, second_t, second_a, q, NULL);
 }
 
@@ -574,9 +587,7 @@ static inline void put_two_gfns(struct two_gfns *arg)
 /* Init the datastructures for later use by the p2m code */
 int p2m_init(struct domain *d);
 
-/* Allocate a new p2m table for a domain. 
- *
- * Returns 0 for success or -errno. */
+/* Allocate a new p2m table for a domain.  Returns 0 for success or -errno. */
 int p2m_alloc_table(struct p2m_domain *p2m);
 
 /* Return all the p2m resources to Xen. */
@@ -610,11 +621,11 @@ void p2m_disable_hardware_log_dirty(struct domain *d);
 void p2m_flush_hardware_cached_dirty(struct domain *d);
 
 /* Change types across all p2m entries in a domain */
-void p2m_change_entry_type_global(struct domain *d, 
+void p2m_change_entry_type_global(struct domain *d,
                                   p2m_type_t ot, p2m_type_t nt);
 
 /* Change types across a range of p2m entries (start ... end-1) */
-void p2m_change_type_range(struct domain *d, 
+void p2m_change_type_range(struct domain *d,
                            unsigned long start, unsigned long end,
                            p2m_type_t ot, p2m_type_t nt);
 
@@ -651,7 +662,7 @@ int clear_identity_p2m_entry(struct domain *d, unsigned long gfn);
 int p2m_add_foreign(struct domain *tdom, unsigned long fgfn,
                     unsigned long gpfn, domid_t foreign_domid);
 
-/* 
+/*
  * Populate-on-demand
  */
 
@@ -732,7 +743,7 @@ int p2m_mem_paging_nominate(struct domain *d, unsigned long gfn);
 /* Evict a frame */
 int p2m_mem_paging_evict(struct domain *d, unsigned long gfn);
 /* Tell xenpaging to drop a paged out frame */
-void p2m_mem_paging_drop_page(struct domain *d, unsigned long gfn, 
+void p2m_mem_paging_drop_page(struct domain *d, unsigned long gfn,
                                 p2m_type_t p2mt);
 /* Start populating a paged out frame */
 void p2m_mem_paging_populate(struct domain *d, unsigned long gfn);
@@ -741,7 +752,7 @@ int p2m_mem_paging_prep(struct domain *d, unsigned long gfn, uint64_t buffer);
 /* Resume normal operation (in case a domain was paused) */
 void p2m_mem_paging_resume(struct domain *d, vm_event_response_t *rsp);
 
-/* 
+/*
  * Internal functions, only called by other p2m code
  */
 
@@ -796,7 +807,7 @@ static inline p2m_type_t p2m_flags_to_type(unsigned long flags)
 {
     /* For AMD IOMMUs we need to use type 0 for plain RAM, but we need
      * to make sure that an entirely empty PTE doesn't have RAM type */
-    if ( flags == 0 ) 
+    if ( flags == 0 )
         return p2m_invalid;
     /* AMD IOMMUs use bits 9-11 to encode next io page level and bits
      * 59-62 for iommu flags so we can't use them to store p2m type info. */
@@ -828,7 +839,7 @@ static inline p2m_type_t p2m_recalc_type(bool recalc, p2m_type_t t,
 int p2m_pt_handle_deferred_changes(uint64_t gpa);
 
 /*
- * Nested p2m: shadow p2m tables used for nested HVM virtualization 
+ * Nested p2m: shadow p2m tables used for nested HVM virtualization
  */
 
 /* Flushes specified p2m table */
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 08/14] xen/memory: Drop ARM put_gfn() stub
  2018-11-21 13:21 [PATCH 00/14] XSA-277 followup Andrew Cooper
                   ` (6 preceding siblings ...)
  2018-11-21 13:21 ` [PATCH 07/14] x86/p2m: Coding style cleanup Andrew Cooper
@ 2018-11-21 13:21 ` Andrew Cooper
  2018-11-22 14:07   ` Julien Grall
  2018-11-22 15:15   ` Jan Beulich
  2018-11-21 13:21 ` [PATCH 09/14] x86/p2m: Switch the two_gfns infrastructure to using gfn_t Andrew Cooper
                   ` (7 subsequent siblings)
  15 siblings, 2 replies; 59+ messages in thread
From: Andrew Cooper @ 2018-11-21 13:21 UTC (permalink / raw)
  To: Xen-devel
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Julien Grall,
	Jan Beulich, Roger Pau Monné

On x86, get_gfn_*() and put_gfn() are reference counting pairs.  All the
get_gfn_*() functions are called from within CONFIG_X86 sections, but
put_gfn() is stubbed out on ARM.

As a result, the common code reads as if ARM is dropping references it never
acquired.

Put all put_gfn() calls in common code inside CONFIG_X86 to make the code
properly balanced, and drop the ARM stub.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Stefano Stabellini <sstabellini@kernel.org>
CC: Julien Grall <julien.grall@arm.com>
CC: Jan Beulich <JBeulich@suse.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
---
 xen/common/grant_table.c |  8 ++++++++
 xen/common/memory.c      | 15 ++++++++++++++-
 xen/include/asm-arm/mm.h |  2 --
 3 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
index fc41b65..f7860f6 100644
--- a/xen/common/grant_table.c
+++ b/xen/common/grant_table.c
@@ -2110,7 +2110,9 @@ gnttab_transfer(
         /* Check the passed page frame for basic validity. */
         if ( unlikely(!mfn_valid(mfn)) )
         {
+#ifdef CONFIG_X86
             put_gfn(d, gop.mfn);
+#endif
             gdprintk(XENLOG_INFO, "out-of-range %lx\n", (unsigned long)gop.mfn);
             gop.status = GNTST_bad_page;
             goto copyback;
@@ -2119,7 +2121,9 @@ gnttab_transfer(
         page = mfn_to_page(mfn);
         if ( (rc = steal_page(d, page, 0)) < 0 )
         {
+#ifdef CONFIG_X86
             put_gfn(d, gop.mfn);
+#endif
             gop.status = rc == -EINVAL ? GNTST_bad_page : GNTST_general_error;
             goto copyback;
         }
@@ -2149,7 +2153,9 @@ gnttab_transfer(
         unlock_and_copyback:
             rcu_unlock_domain(e);
         put_gfn_and_copyback:
+#ifdef CONFIG_X86
             put_gfn(d, gop.mfn);
+#endif
             page->count_info &= ~(PGC_count_mask|PGC_allocated);
             free_domheap_page(page);
             goto copyback;
@@ -2236,7 +2242,9 @@ gnttab_transfer(
         page_set_owner(page, e);
 
         spin_unlock(&e->page_alloc_lock);
+#ifdef CONFIG_X86
         put_gfn(d, gop.mfn);
+#endif
 
         TRACE_1D(TRC_MEM_PAGE_GRANT_TRANSFER, e->domain_id);
 
diff --git a/xen/common/memory.c b/xen/common/memory.c
index 58194b9..175bd62 100644
--- a/xen/common/memory.c
+++ b/xen/common/memory.c
@@ -358,7 +358,9 @@ int guest_remove_page(struct domain *d, unsigned long gmfn)
 #endif
     if ( unlikely(!mfn_valid(mfn)) )
     {
+#ifdef CONFIG_X86
         put_gfn(d, gmfn);
+#endif
         gdprintk(XENLOG_INFO, "Domain %u page number %lx invalid\n",
                 d->domain_id, gmfn);
 
@@ -388,7 +390,9 @@ int guest_remove_page(struct domain *d, unsigned long gmfn)
     page = mfn_to_page(mfn);
     if ( unlikely(!get_page(page, d)) )
     {
+#ifdef CONFIG_X86
         put_gfn(d, gmfn);
+#endif
         gdprintk(XENLOG_INFO, "Bad page free for domain %u\n", d->domain_id);
 
         return -ENXIO;
@@ -409,8 +413,11 @@ int guest_remove_page(struct domain *d, unsigned long gmfn)
         put_page(page);
 
     put_page(page);
- out_put_gfn: __maybe_unused;
+
+#ifdef CONFIG_X86
+ out_put_gfn:
     put_gfn(d, gmfn);
+#endif
 
     /*
      * Filter out -ENOENT return values that aren't a result of an empty p2m
@@ -656,7 +663,9 @@ static long memory_exchange(XEN_GUEST_HANDLE_PARAM(xen_memory_exchange_t) arg)
 #endif
                 if ( unlikely(!mfn_valid(mfn)) )
                 {
+#ifdef CONFIG_X86
                     put_gfn(d, gmfn + k);
+#endif
                     rc = -EINVAL;
                     goto fail;
                 }
@@ -666,12 +675,16 @@ static long memory_exchange(XEN_GUEST_HANDLE_PARAM(xen_memory_exchange_t) arg)
                 rc = steal_page(d, page, MEMF_no_refcount);
                 if ( unlikely(rc) )
                 {
+#ifdef CONFIG_X86
                     put_gfn(d, gmfn + k);
+#endif
                     goto fail;
                 }
 
                 page_list_add(page, &in_chunk_list);
+#ifdef CONFIG_X86
                 put_gfn(d, gmfn + k);
+#endif
             }
         }
 
diff --git a/xen/include/asm-arm/mm.h b/xen/include/asm-arm/mm.h
index 940b74b..b2f6104 100644
--- a/xen/include/asm-arm/mm.h
+++ b/xen/include/asm-arm/mm.h
@@ -313,8 +313,6 @@ static inline void *page_to_virt(const struct page_info *pg)
 struct page_info *get_page_from_gva(struct vcpu *v, vaddr_t va,
                                     unsigned long flags);
 
-static inline void put_gfn(struct domain *d, unsigned long gfn) {}
-
 /*
  * Arm does not have an M2P, but common code expects a handful of
  * M2P-related defines and functions. Provide dummy versions of these.
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 09/14] x86/p2m: Switch the two_gfns infrastructure to using gfn_t
  2018-11-21 13:21 [PATCH 00/14] XSA-277 followup Andrew Cooper
                   ` (7 preceding siblings ...)
  2018-11-21 13:21 ` [PATCH 08/14] xen/memory: Drop ARM put_gfn() stub Andrew Cooper
@ 2018-11-21 13:21 ` Andrew Cooper
  2018-11-21 17:06   ` Tamas K Lengyel
  2018-11-22 15:17   ` Jan Beulich
  2018-11-21 13:21 ` [PATCH 10/14] x86/mm: Switch {get, put}_gfn() " Andrew Cooper
                   ` (6 subsequent siblings)
  15 siblings, 2 replies; 59+ messages in thread
From: Andrew Cooper @ 2018-11-21 13:21 UTC (permalink / raw)
  To: Xen-devel
  Cc: George Dunlap, Andrew Cooper, Tamas K Lengyel, Wei Liu, Jan Beulich

Additionally, drop surrounding trailing whitespace.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: George Dunlap <george.dunlap@eu.citrix.com>
CC: Tamas K Lengyel <tamas@tklengyel.com>
---
 xen/arch/x86/mm/mem_sharing.c |  8 ++++----
 xen/include/asm-x86/p2m.h     | 21 ++++++++++-----------
 2 files changed, 14 insertions(+), 15 deletions(-)

diff --git a/xen/arch/x86/mm/mem_sharing.c b/xen/arch/x86/mm/mem_sharing.c
index 77f0d3f..573d354 100644
--- a/xen/arch/x86/mm/mem_sharing.c
+++ b/xen/arch/x86/mm/mem_sharing.c
@@ -901,8 +901,8 @@ static int share_pages(struct domain *sd, gfn_t sgfn, shr_handle_t sh,
     struct two_gfns tg;
     struct rmap_iterator ri;
 
-    get_two_gfns(sd, gfn_x(sgfn), &smfn_type, NULL, &smfn,
-                 cd, gfn_x(cgfn), &cmfn_type, NULL, &cmfn,
+    get_two_gfns(sd, sgfn, &smfn_type, NULL, &smfn,
+                 cd, cgfn, &cmfn_type, NULL, &cmfn,
                  0, &tg);
 
     /* This tricky business is to avoid two callers deadlocking if 
@@ -1027,8 +1027,8 @@ int mem_sharing_add_to_physmap(struct domain *sd, unsigned long sgfn, shr_handle
     p2m_access_t a;
     struct two_gfns tg;
 
-    get_two_gfns(sd, sgfn, &smfn_type, NULL, &smfn,
-                 cd, cgfn, &cmfn_type, &a, &cmfn,
+    get_two_gfns(sd, _gfn(sgfn), &smfn_type, NULL, &smfn,
+                 cd, _gfn(cgfn), &cmfn_type, &a, &cmfn,
                  0, &tg);
 
     /* Get the source shared page, check and lock */
diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h
index 74d0cf6..8bd6f64 100644
--- a/xen/include/asm-x86/p2m.h
+++ b/xen/include/asm-x86/p2m.h
@@ -529,17 +529,15 @@ static inline unsigned long mfn_to_gfn(struct domain *d, mfn_t mfn)
 
 /* Deadlock-avoidance scheme when calling get_gfn on different gfn's */
 struct two_gfns {
-    struct domain  *first_domain;
-    unsigned long   first_gfn;
-    struct domain  *second_domain;
-    unsigned long   second_gfn;
+    struct domain *first_domain, *second_domain;
+    gfn_t          first_gfn,     second_gfn;
 };
 
 /* Returns mfn, type and access for potential caller consumption, but any
  * of those can be NULL */
-static inline void get_two_gfns(struct domain *rd, unsigned long rgfn,
+static inline void get_two_gfns(struct domain *rd, gfn_t rgfn,
         p2m_type_t *rt, p2m_access_t *ra, mfn_t *rmfn, struct domain *ld,
-        unsigned long lgfn, p2m_type_t *lt, p2m_access_t *la, mfn_t *lmfn,
+        gfn_t lgfn, p2m_type_t *lt, p2m_access_t *la, mfn_t *lmfn,
         p2m_query_t q, struct two_gfns *rval)
 {
     mfn_t           *first_mfn, *second_mfn, scratch_mfn;
@@ -557,7 +555,8 @@ do {                                                    \
     dest ## _t   = (source ## t)   ?: &scratch_t;       \
 } while (0)
 
-    if ( (rd->domain_id <= ld->domain_id) || ((rd == ld) && (rgfn <= lgfn)) )
+    if ( (rd->domain_id <= ld->domain_id) ||
+         ((rd == ld) && (gfn_x(rgfn) <= gfn_x(lgfn))) )
     {
         assign_pointers(first, r);
         assign_pointers(second, l);
@@ -570,9 +569,9 @@ do {                                                    \
 
     /* Now do the gets */
     *first_mfn  = get_gfn_type_access(p2m_get_hostp2m(rval->first_domain),
-                                      rval->first_gfn, first_t, first_a, q, NULL);
+                                      gfn_x(rval->first_gfn), first_t, first_a, q, NULL);
     *second_mfn = get_gfn_type_access(p2m_get_hostp2m(rval->second_domain),
-                                      rval->second_gfn, second_t, second_a, q, NULL);
+                                      gfn_x(rval->second_gfn), second_t, second_a, q, NULL);
 }
 
 static inline void put_two_gfns(struct two_gfns *arg)
@@ -580,8 +579,8 @@ static inline void put_two_gfns(struct two_gfns *arg)
     if ( !arg )
         return;
 
-    put_gfn(arg->second_domain, arg->second_gfn);
-    put_gfn(arg->first_domain, arg->first_gfn);
+    put_gfn(arg->second_domain, gfn_x(arg->second_gfn));
+    put_gfn(arg->first_domain,  gfn_x(arg->first_gfn));
 }
 
 /* Init the datastructures for later use by the p2m code */
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 10/14] x86/mm: Switch {get, put}_gfn() infrastructure to using gfn_t
  2018-11-21 13:21 [PATCH 00/14] XSA-277 followup Andrew Cooper
                   ` (8 preceding siblings ...)
  2018-11-21 13:21 ` [PATCH 09/14] x86/p2m: Switch the two_gfns infrastructure to using gfn_t Andrew Cooper
@ 2018-11-21 13:21 ` Andrew Cooper
  2018-11-21 14:48   ` Razvan Cojocaru
                     ` (4 more replies)
  2018-11-21 13:21 ` [PATCH 11/14] xen/mm: Switch mfn_to_virt()/virt_to_mfn() to using mfn_t Andrew Cooper
                   ` (5 subsequent siblings)
  15 siblings, 5 replies; 59+ messages in thread
From: Andrew Cooper @ 2018-11-21 13:21 UTC (permalink / raw)
  To: Xen-devel
  Cc: Kevin Tian, Tamas K Lengyel, Wei Liu, Jun Nakajima,
	Razvan Cojocaru, George Dunlap, Andrew Cooper, Tim Deegan,
	Paul Durrant, Jan Beulich, Boris Ostrovsky, Brian Woods,
	Suravee Suthikulpanit, Roger Pau Monné

Seemingly, a majority of users either override the helpers anyway, or have an
gfn_t in their hands.

Update the API, and adjust all users to match.

Doing this highlighted a gaping altp2m security hole in
vmx_vcpu_update_vmfunc_ve(), which will need addressing now we can discuss the
problem and options publicly.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Razvan Cojocaru <rcojocaru@bitdefender.com>
CC: Tamas K Lengyel <tamas@tklengyel.com>
CC: George Dunlap <george.dunlap@eu.citrix.com>
CC: Tim Deegan <tim@xen.org>
CC: Paul Durrant <paul.durrant@citrix.com>
CC: Jun Nakajima <jun.nakajima@intel.com>
CC: Kevin Tian <kevin.tian@intel.com>
CC: Boris Ostrovsky <boris.ostrovsky@oracle.com>
CC: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
CC: Brian Woods <brian.woods@amd.com>
---
 xen/arch/x86/cpu/mcheck/mcaction.c        |  2 +-
 xen/arch/x86/cpu/mcheck/mce.c             | 14 +++----
 xen/arch/x86/cpu/mcheck/vmce.c            |  4 +-
 xen/arch/x86/cpu/mcheck/vmce.h            |  2 +-
 xen/arch/x86/debug.c                      |  6 +--
 xen/arch/x86/domain.c                     | 19 ++++-----
 xen/arch/x86/domctl.c                     |  8 ++--
 xen/arch/x86/hvm/dm.c                     | 12 +++---
 xen/arch/x86/hvm/emulate.c                | 16 ++++----
 xen/arch/x86/hvm/grant_table.c            |  4 +-
 xen/arch/x86/hvm/hvm.c                    | 25 ++++++------
 xen/arch/x86/hvm/mtrr.c                   |  2 +-
 xen/arch/x86/hvm/svm/svm.c                |  2 +-
 xen/arch/x86/hvm/vmx/vmx.c                |  7 ++--
 xen/arch/x86/mm.c                         | 10 ++---
 xen/arch/x86/mm/hap/hap.c                 |  2 +-
 xen/arch/x86/mm/hap/nested_hap.c          |  6 +--
 xen/arch/x86/mm/mem_access.c              |  5 +--
 xen/arch/x86/mm/mem_sharing.c             | 24 +++++------
 xen/arch/x86/mm/p2m.c                     | 45 ++++++++++----------
 xen/arch/x86/mm/shadow/common.c           |  4 +-
 xen/arch/x86/mm/shadow/multi.c            | 68 +++++++++++++++----------------
 xen/arch/x86/mm/shadow/types.h            |  4 --
 xen/common/grant_table.c                  | 10 ++---
 xen/common/memory.c                       | 24 +++++------
 xen/drivers/passthrough/amd/iommu_guest.c |  8 ----
 xen/include/asm-x86/guest_pt.h            |  4 --
 xen/include/asm-x86/p2m.h                 | 30 +++++++-------
 28 files changed, 172 insertions(+), 195 deletions(-)

diff --git a/xen/arch/x86/cpu/mcheck/mcaction.c b/xen/arch/x86/cpu/mcheck/mcaction.c
index e422674..c8e0cf2 100644
--- a/xen/arch/x86/cpu/mcheck/mcaction.c
+++ b/xen/arch/x86/cpu/mcheck/mcaction.c
@@ -89,7 +89,7 @@ mc_memerr_dhandler(struct mca_binfo *binfo,
                 ASSERT(d);
                 gfn = get_gpfn_from_mfn((bank->mc_addr) >> PAGE_SHIFT);
 
-                if ( unmmap_broken_page(d, _mfn(mfn), gfn) )
+                if ( unmmap_broken_page(d, _mfn(mfn), _gfn(gfn)) )
                 {
                     printk("Unmap broken memory %lx for DOM%d failed\n",
                            mfn, d->domain_id);
diff --git a/xen/arch/x86/cpu/mcheck/mce.c b/xen/arch/x86/cpu/mcheck/mce.c
index 30cdb06..c96c053 100644
--- a/xen/arch/x86/cpu/mcheck/mce.c
+++ b/xen/arch/x86/cpu/mcheck/mce.c
@@ -1469,9 +1469,6 @@ long do_mca(XEN_GUEST_HANDLE_PARAM(xen_mc_t) u_xen_mc)
             struct domain *d;
             struct mcinfo_msr *msr;
             unsigned int i;
-            paddr_t gaddr;
-            unsigned long gfn, mfn;
-            p2m_type_t t;
 
             domid = (mc_msrinject->mcinj_domid == DOMID_SELF) ?
                     current->domain->domain_id : mc_msrinject->mcinj_domid;
@@ -1489,11 +1486,12 @@ long do_mca(XEN_GUEST_HANDLE_PARAM(xen_mc_t) u_xen_mc)
                   i < mc_msrinject->mcinj_count;
                   i++, msr++ )
             {
-                gaddr = msr->value;
-                gfn = PFN_DOWN(gaddr);
-                mfn = mfn_x(get_gfn(d, gfn, &t));
+                p2m_type_t t;
+                paddr_t gaddr = msr->value;
+                gfn_t gfn = _gfn(PFN_DOWN(gaddr));
+                mfn_t mfn = get_gfn(d, gfn, &t);
 
-                if ( mfn == mfn_x(INVALID_MFN) )
+                if ( mfn_eq(mfn, INVALID_MFN) )
                 {
                     put_gfn(d, gfn);
                     put_domain(d);
@@ -1501,7 +1499,7 @@ long do_mca(XEN_GUEST_HANDLE_PARAM(xen_mc_t) u_xen_mc)
                                      -EINVAL, gfn, domid);
                 }
 
-                msr->value = pfn_to_paddr(mfn) | (gaddr & (PAGE_SIZE - 1));
+                msr->value = mfn_to_maddr(mfn) | (gaddr & (PAGE_SIZE - 1));
 
                 put_gfn(d, gfn);
             }
diff --git a/xen/arch/x86/cpu/mcheck/vmce.c b/xen/arch/x86/cpu/mcheck/vmce.c
index f15835e..e257e94 100644
--- a/xen/arch/x86/cpu/mcheck/vmce.c
+++ b/xen/arch/x86/cpu/mcheck/vmce.c
@@ -512,7 +512,7 @@ int fill_vmsr_data(struct mcinfo_bank *mc_bank, struct domain *d,
  * XXX following situation missed:
  * PoD, Foreign mapped, Granted, Shared
  */
-int unmmap_broken_page(struct domain *d, mfn_t mfn, unsigned long gfn)
+int unmmap_broken_page(struct domain *d, mfn_t mfn, gfn_t gfn)
 {
     mfn_t r_mfn;
     p2m_type_t pt;
@@ -533,7 +533,7 @@ int unmmap_broken_page(struct domain *d, mfn_t mfn, unsigned long gfn)
     if ( p2m_to_mask(pt) & P2M_UNMAP_TYPES)
     {
         ASSERT(mfn_eq(r_mfn, mfn));
-        rc = p2m_change_type_one(d, gfn, pt, p2m_ram_broken);
+        rc = p2m_change_type_one(d, gfn_x(gfn), pt, p2m_ram_broken);
     }
     put_gfn(d, gfn);
 
diff --git a/xen/arch/x86/cpu/mcheck/vmce.h b/xen/arch/x86/cpu/mcheck/vmce.h
index 2797e00..a37f3be 100644
--- a/xen/arch/x86/cpu/mcheck/vmce.h
+++ b/xen/arch/x86/cpu/mcheck/vmce.h
@@ -9,7 +9,7 @@ int vmce_init(struct cpuinfo_x86 *c);
         && hardware_domain->vcpu[0] \
         && guest_enabled_event(hardware_domain->vcpu[0], VIRQ_MCA))
 
-int unmmap_broken_page(struct domain *d, mfn_t mfn, unsigned long gfn);
+int unmmap_broken_page(struct domain *d, mfn_t mfn, gfn_t gfn);
 
 int vmce_intel_rdmsr(const struct vcpu *, uint32_t msr, uint64_t *val);
 int vmce_intel_wrmsr(struct vcpu *, uint32_t msr, uint64_t val);
diff --git a/xen/arch/x86/debug.c b/xen/arch/x86/debug.c
index a500df0..7c2dc8c 100644
--- a/xen/arch/x86/debug.c
+++ b/xen/arch/x86/debug.c
@@ -58,7 +58,7 @@ dbg_hvm_va2mfn(dbgva_t vaddr, struct domain *dp, int toaddr, gfn_t *gfn)
         return INVALID_MFN;
     }
 
-    mfn = get_gfn(dp, gfn_x(*gfn), &gfntype);
+    mfn = get_gfn(dp, *gfn, &gfntype);
     if ( p2m_is_readonly(gfntype) && toaddr )
     {
         DBGP2("kdb:p2m_is_readonly: gfntype:%x\n", gfntype);
@@ -70,7 +70,7 @@ dbg_hvm_va2mfn(dbgva_t vaddr, struct domain *dp, int toaddr, gfn_t *gfn)
 
     if ( mfn_eq(mfn, INVALID_MFN) )
     {
-        put_gfn(dp, gfn_x(*gfn));
+        put_gfn(dp, *gfn);
         *gfn = INVALID_GFN;
     }
 
@@ -189,7 +189,7 @@ static unsigned int dbg_rw_guest_mem(struct domain *dp, void * __user gaddr,
 
         unmap_domain_page(va);
         if ( !gfn_eq(gfn, INVALID_GFN) )
-            put_gfn(dp, gfn_x(gfn));
+            put_gfn(dp, gfn);
 
         addr += pagecnt;
         buf += pagecnt;
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index b4d5948..327c961 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -677,7 +677,7 @@ int arch_domain_soft_reset(struct domain *d)
     int ret = 0;
     struct domain *owner;
     mfn_t mfn;
-    unsigned long gfn;
+    gfn_t gfn;
     p2m_type_t p2mt;
     unsigned int i;
 
@@ -711,19 +711,19 @@ int arch_domain_soft_reset(struct domain *d)
     ASSERT( owner == d );
 
     mfn = page_to_mfn(page);
-    gfn = mfn_to_gmfn(d, mfn_x(mfn));
+    gfn = _gfn(mfn_to_gmfn(d, mfn_x(mfn)));
 
     /*
      * gfn == INVALID_GFN indicates that the shared_info page was never mapped
      * to the domain's address space and there is nothing to replace.
      */
-    if ( gfn == gfn_x(INVALID_GFN) )
+    if ( gfn_eq(gfn, INVALID_GFN) )
         goto exit_put_page;
 
     if ( !mfn_eq(get_gfn_query(d, gfn, &p2mt), mfn) )
     {
         printk(XENLOG_G_ERR "Failed to get Dom%d's shared_info GFN (%lx)\n",
-               d->domain_id, gfn);
+               d->domain_id, gfn_x(gfn));
         ret = -EINVAL;
         goto exit_put_gfn;
     }
@@ -732,26 +732,25 @@ int arch_domain_soft_reset(struct domain *d)
     if ( !new_page )
     {
         printk(XENLOG_G_ERR "Failed to alloc a page to replace"
-               " Dom%d's shared_info frame %lx\n", d->domain_id, gfn);
+               " Dom%d's shared_info frame %lx\n", d->domain_id, gfn_x(gfn));
         ret = -ENOMEM;
         goto exit_put_gfn;
     }
 
-    ret = guest_physmap_remove_page(d, _gfn(gfn), mfn, PAGE_ORDER_4K);
+    ret = guest_physmap_remove_page(d, gfn, mfn, PAGE_ORDER_4K);
     if ( ret )
     {
         printk(XENLOG_G_ERR "Failed to remove Dom%d's shared_info frame %lx\n",
-               d->domain_id, gfn);
+               d->domain_id, gfn_x(gfn));
         free_domheap_page(new_page);
         goto exit_put_gfn;
     }
 
-    ret = guest_physmap_add_page(d, _gfn(gfn), page_to_mfn(new_page),
-                                 PAGE_ORDER_4K);
+    ret = guest_physmap_add_page(d, gfn, page_to_mfn(new_page), PAGE_ORDER_4K);
     if ( ret )
     {
         printk(XENLOG_G_ERR "Failed to add a page to replace"
-               " Dom%d's shared_info frame %lx\n", d->domain_id, gfn);
+               " Dom%d's shared_info frame %lx\n", d->domain_id, gfn_x(gfn));
         free_domheap_page(new_page);
     }
  exit_put_gfn:
diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
index aa8ad19..694b4d5 100644
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -1253,15 +1253,15 @@ long arch_do_domctl(
     case XEN_DOMCTL_set_broken_page_p2m:
     {
         p2m_type_t pt;
-        unsigned long pfn = domctl->u.set_broken_page_p2m.pfn;
-        mfn_t mfn = get_gfn_query(d, pfn, &pt);
+        gfn_t gfn = _gfn(domctl->u.set_broken_page_p2m.pfn);
+        mfn_t mfn = get_gfn_query(d, gfn, &pt);
 
         if ( unlikely(!mfn_valid(mfn)) || unlikely(!p2m_is_ram(pt)) )
             ret = -EINVAL;
         else
-            ret = p2m_change_type_one(d, pfn, pt, p2m_ram_broken);
+            ret = p2m_change_type_one(d, gfn_x(gfn), pt, p2m_ram_broken);
 
-        put_gfn(d, pfn);
+        put_gfn(d, gfn);
         break;
     }
 
diff --git a/xen/arch/x86/hvm/dm.c b/xen/arch/x86/hvm/dm.c
index d6d0e8b..9938f4b 100644
--- a/xen/arch/x86/hvm/dm.c
+++ b/xen/arch/x86/hvm/dm.c
@@ -269,14 +269,14 @@ static int set_mem_type(struct domain *d,
 
     while ( iter < data->nr )
     {
-        unsigned long pfn = data->first_pfn + iter;
+        gfn_t gfn = _gfn(data->first_pfn + iter);
         p2m_type_t t;
 
-        get_gfn_unshare(d, pfn, &t);
+        get_gfn_unshare(d, gfn, &t);
         if ( p2m_is_paging(t) )
         {
-            put_gfn(d, pfn);
-            p2m_mem_paging_populate(d, pfn);
+            put_gfn(d, gfn);
+            p2m_mem_paging_populate(d, gfn_x(gfn));
             return -EAGAIN;
         }
 
@@ -285,9 +285,9 @@ static int set_mem_type(struct domain *d,
         else if ( !allow_p2m_type_change(t, memtype[mem_type]) )
             rc = -EINVAL;
         else
-            rc = p2m_change_type_one(d, pfn, t, memtype[mem_type]);
+            rc = p2m_change_type_one(d, gfn_x(gfn), t, memtype[mem_type]);
 
-        put_gfn(d, pfn);
+        put_gfn(d, gfn);
 
         if ( rc )
             break;
diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c
index 2d02ef1..1335b2c 100644
--- a/xen/arch/x86/hvm/emulate.c
+++ b/xen/arch/x86/hvm/emulate.c
@@ -255,13 +255,13 @@ static int hvmemul_do_io(
          * so the device model side needs to check the incoming ioreq event.
          */
         struct hvm_ioreq_server *s = NULL;
-        p2m_type_t p2mt = p2m_invalid;
 
         if ( is_mmio )
         {
-            unsigned long gmfn = paddr_to_pfn(addr);
+            p2m_type_t p2mt = p2m_invalid;
+            gfn_t gfn = gaddr_to_gfn(addr);
 
-            get_gfn_query_unlocked(currd, gmfn, &p2mt);
+            get_gfn_query_unlocked(currd, gfn, &p2mt);
 
             if ( p2mt == p2m_ioreq_server )
             {
@@ -1590,7 +1590,7 @@ static int hvmemul_rep_ins(
     if ( rc != X86EMUL_OKAY )
         return rc;
 
-    (void) get_gfn_query_unlocked(current->domain, gpa >> PAGE_SHIFT, &p2mt);
+    get_gfn_query_unlocked(current->domain, gaddr_to_gfn(gpa), &p2mt);
     if ( p2mt == p2m_mmio_direct || p2mt == p2m_mmio_dm )
         return X86EMUL_UNHANDLEABLE;
 
@@ -1671,7 +1671,7 @@ static int hvmemul_rep_outs(
     if ( rc != X86EMUL_OKAY )
         return rc;
 
-    (void) get_gfn_query_unlocked(current->domain, gpa >> PAGE_SHIFT, &p2mt);
+    get_gfn_query_unlocked(current->domain, gaddr_to_gfn(gpa), &p2mt);
     if ( p2mt == p2m_mmio_direct || p2mt == p2m_mmio_dm )
         return X86EMUL_UNHANDLEABLE;
 
@@ -1750,8 +1750,8 @@ static int hvmemul_rep_movs(
     }
 
     /* Check for MMIO ops */
-    (void) get_gfn_query_unlocked(current->domain, sgpa >> PAGE_SHIFT, &sp2mt);
-    (void) get_gfn_query_unlocked(current->domain, dgpa >> PAGE_SHIFT, &dp2mt);
+    get_gfn_query_unlocked(current->domain, gaddr_to_gfn(sgpa), &sp2mt);
+    get_gfn_query_unlocked(current->domain, gaddr_to_gfn(dgpa), &dp2mt);
 
     if ( sp2mt == p2m_mmio_direct || dp2mt == p2m_mmio_direct ||
          (sp2mt == p2m_mmio_dm && dp2mt == p2m_mmio_dm) )
@@ -1878,7 +1878,7 @@ static int hvmemul_rep_stos(
     }
 
     /* Check for MMIO op */
-    (void)get_gfn_query_unlocked(current->domain, gpa >> PAGE_SHIFT, &p2mt);
+    get_gfn_query_unlocked(current->domain, gaddr_to_gfn(gpa), &p2mt);
 
     switch ( p2mt )
     {
diff --git a/xen/arch/x86/hvm/grant_table.c b/xen/arch/x86/hvm/grant_table.c
index ecd7d07..04a3106 100644
--- a/xen/arch/x86/hvm/grant_table.c
+++ b/xen/arch/x86/hvm/grant_table.c
@@ -51,7 +51,7 @@ int create_grant_p2m_mapping(uint64_t addr, mfn_t frame,
 int replace_grant_p2m_mapping(uint64_t addr, mfn_t frame,
                               uint64_t new_addr, unsigned int flags)
 {
-    unsigned long gfn = (unsigned long)(addr >> PAGE_SHIFT);
+    gfn_t gfn = gaddr_to_gfn(addr);
     p2m_type_t type;
     mfn_t old_mfn;
     struct domain *d = current->domain;
@@ -68,7 +68,7 @@ int replace_grant_p2m_mapping(uint64_t addr, mfn_t frame,
                  type, mfn_x(old_mfn), mfn_x(frame));
         return GNTST_general_error;
     }
-    if ( guest_physmap_remove_page(d, _gfn(gfn), frame, PAGE_ORDER_4K) )
+    if ( guest_physmap_remove_page(d, gfn, frame, PAGE_ORDER_4K) )
     {
         put_gfn(d, gfn);
         return GNTST_general_error;
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index db60f23..987c26a 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -1679,7 +1679,7 @@ void hvm_inject_event(const struct x86_event *event)
 int hvm_hap_nested_page_fault(paddr_t gpa, unsigned long gla,
                               struct npfec npfec)
 {
-    unsigned long gfn = gpa >> PAGE_SHIFT;
+    gfn_t gfn = gaddr_to_gfn(gpa);
     p2m_type_t p2mt;
     p2m_access_t p2ma;
     mfn_t mfn;
@@ -1729,7 +1729,7 @@ int hvm_hap_nested_page_fault(paddr_t gpa, unsigned long gla,
             return 1;
         case NESTEDHVM_PAGEFAULT_L0_ERROR:
             /* gpa is now translated to l1 guest address, update gfn. */
-            gfn = gpa >> PAGE_SHIFT;
+            gfn = gaddr_to_gfn(gpa);
             break;
         }
     }
@@ -1817,7 +1817,7 @@ int hvm_hap_nested_page_fault(paddr_t gpa, unsigned long gla,
             {
                 bool_t sve;
 
-                p2m->get_entry(p2m, _gfn(gfn), &p2mt, &p2ma, 0, NULL, &sve);
+                p2m->get_entry(p2m, gfn, &p2mt, &p2ma, 0, NULL, &sve);
 
                 if ( !sve && altp2m_vcpu_emulate_ve(curr) )
                 {
@@ -1862,7 +1862,7 @@ int hvm_hap_nested_page_fault(paddr_t gpa, unsigned long gla,
     {
         ASSERT(p2m_is_hostp2m(p2m));
         sharing_enomem = 
-            (mem_sharing_unshare_page(currd, gfn, 0) < 0);
+            (mem_sharing_unshare_page(currd, gfn_x(gfn), 0) < 0);
         rc = 1;
         goto out_put_gfn;
     }
@@ -1878,7 +1878,7 @@ int hvm_hap_nested_page_fault(paddr_t gpa, unsigned long gla,
          */
         if ( npfec.write_access )
         {
-            paging_mark_pfn_dirty(currd, _pfn(gfn));
+            paging_mark_pfn_dirty(currd, _pfn(gfn_x(gfn)));
             /*
              * If p2m is really an altp2m, unlock it before changing the type,
              * as p2m_altp2m_propagate_change() needs to acquire the
@@ -1886,7 +1886,7 @@ int hvm_hap_nested_page_fault(paddr_t gpa, unsigned long gla,
              */
             if ( p2m != hostp2m )
                 __put_gfn(p2m, gfn);
-            p2m_change_type_one(currd, gfn, p2m_ram_logdirty, p2m_ram_rw);
+            p2m_change_type_one(currd, gfn_x(gfn), p2m_ram_logdirty, p2m_ram_rw);
             __put_gfn(hostp2m, gfn);
 
             goto out;
@@ -1916,16 +1916,16 @@ int hvm_hap_nested_page_fault(paddr_t gpa, unsigned long gla,
      * sleep on event ring wait queues, and we must not hold
      * locks in such circumstance */
     if ( paged )
-        p2m_mem_paging_populate(currd, gfn);
+        p2m_mem_paging_populate(currd, gfn_x(gfn));
     if ( sharing_enomem )
     {
         int rv;
 
-        if ( (rv = mem_sharing_notify_enomem(currd, gfn, true)) < 0 )
+        if ( (rv = mem_sharing_notify_enomem(currd, gfn_x(gfn), true)) < 0 )
         {
             gdprintk(XENLOG_ERR, "Domain %hu attempt to unshare "
                      "gfn %lx, ENOMEM and no helper (rc %d)\n",
-                     currd->domain_id, gfn, rv);
+                     currd->domain_id, gfn_x(gfn), rv);
             /* Crash the domain */
             rc = 0;
         }
@@ -4601,8 +4601,9 @@ static int do_altp2m_op(
         v = d->vcpu[a.u.enable_notify.vcpu_id];
 
         if ( !gfn_eq(vcpu_altp2m(v).veinfo_gfn, INVALID_GFN) ||
-             mfn_eq(get_gfn_query_unlocked(v->domain,
-                    a.u.enable_notify.gfn, &p2mt), INVALID_MFN) )
+             mfn_eq(get_gfn_query_unlocked(
+                        v->domain, _gfn(a.u.enable_notify.gfn), &p2mt),
+                    INVALID_MFN) )
         {
             rc = -EINVAL;
             break;
@@ -4866,7 +4867,7 @@ static int hvmop_get_mem_type(
      * type, not in allocating or unsharing. That'll happen
      * on access.
      */
-    get_gfn_query_unlocked(d, a.pfn, &t);
+    get_gfn_query_unlocked(d, _gfn(a.pfn), &t);
     if ( p2m_is_mmio(t) )
         a.mem_type =  HVMMEM_mmio_dm;
     else if ( t == p2m_ioreq_server )
diff --git a/xen/arch/x86/hvm/mtrr.c b/xen/arch/x86/hvm/mtrr.c
index b8fa340..f553e4d 100644
--- a/xen/arch/x86/hvm/mtrr.c
+++ b/xen/arch/x86/hvm/mtrr.c
@@ -366,7 +366,7 @@ uint32_t get_pat_flags(struct vcpu *v,
     {
         struct domain *d = v->domain;
         p2m_type_t p2mt;
-        get_gfn_query_unlocked(d, paddr_to_pfn(gpaddr), &p2mt);
+        get_gfn_query_unlocked(d, gaddr_to_gfn(gpaddr), &p2mt);
         if (p2m_is_ram(p2mt))
             gdprintk(XENLOG_WARNING,
                     "Conflict occurs for a given guest l1e flags:%x "
diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index b9a8900..46f9893 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -1762,7 +1762,7 @@ static void svm_do_nested_pgfault(struct vcpu *v,
     struct cpu_user_regs *regs, uint64_t pfec, paddr_t gpa)
 {
     int ret;
-    unsigned long gfn = gpa >> PAGE_SHIFT;
+    gfn_t gfn = gaddr_to_gfn(gpa);
     mfn_t mfn;
     p2m_type_t p2mt;
     p2m_access_t p2ma;
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index 365eeb2..b5370dd 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -2199,7 +2199,8 @@ static void vmx_vcpu_update_vmfunc_ve(struct vcpu *v)
             p2m_type_t t;
             mfn_t mfn;
 
-            mfn = get_gfn_query_unlocked(d, gfn_x(vcpu_altp2m(v).veinfo_gfn), &t);
+            /* TODO: This is a security issue... */
+            mfn = get_gfn_query_unlocked(d, vcpu_altp2m(v).veinfo_gfn, &t);
 
             if ( !mfn_eq(mfn, INVALID_MFN) )
             {
@@ -3328,7 +3329,7 @@ static void ept_handle_violation(ept_qual_t q, paddr_t gpa)
 
         _d.gpa = gpa;
         _d.qualification = q.raw;
-        _d.mfn = mfn_x(get_gfn_query_unlocked(d, gfn, &_d.p2mt));
+        _d.mfn = mfn_x(get_gfn_query_unlocked(d, _gfn(gfn), &_d.p2mt));
 
         __trace_var(TRC_HVM_NPF, 0, sizeof(_d), &_d);
     }
@@ -3358,7 +3359,7 @@ static void ept_handle_violation(ept_qual_t q, paddr_t gpa)
     }
 
     /* Everything else is an error. */
-    mfn = get_gfn_query_unlocked(d, gfn, &p2mt);
+    mfn = get_gfn_query_unlocked(d, _gfn(gfn), &p2mt);
     gprintk(XENLOG_ERR,
             "EPT violation %#lx (%c%c%c/%c%c%c) gpa %#"PRIpaddr" mfn %#lx type %i\n",
             q.raw,
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index 28a0030..c3c7628 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -4364,11 +4364,11 @@ int xenmem_add_to_physmap_one(
             p2m_type_t p2mt;
 
             gfn = idx;
-            mfn = get_gfn_unshare(d, gfn, &p2mt);
+            mfn = get_gfn_unshare(d, _gfn(gfn), &p2mt);
             /* If the page is still shared, exit early */
             if ( p2m_is_shared(p2mt) )
             {
-                put_gfn(d, gfn);
+                put_gfn(d, _gfn(gfn));
                 return -ENOMEM;
             }
             page = get_page_from_mfn(mfn, d);
@@ -4389,7 +4389,7 @@ int xenmem_add_to_physmap_one(
     }
 
     /* Remove previously mapped page if it was present. */
-    prev_mfn = mfn_x(get_gfn(d, gfn_x(gpfn), &p2mt));
+    prev_mfn = mfn_x(get_gfn(d, gpfn, &p2mt));
     if ( mfn_valid(_mfn(prev_mfn)) )
     {
         if ( is_xen_heap_mfn(prev_mfn) )
@@ -4400,7 +4400,7 @@ int xenmem_add_to_physmap_one(
             rc = guest_remove_page(d, gfn_x(gpfn));
     }
     /* In the XENMAPSPACE_gmfn case we still hold a ref on the old page. */
-    put_gfn(d, gfn_x(gpfn));
+    put_gfn(d, gpfn);
 
     if ( rc )
         goto put_both;
@@ -4423,7 +4423,7 @@ int xenmem_add_to_physmap_one(
  put_both:
     /* In the XENMAPSPACE_gmfn case, we took a ref of the gfn at the top. */
     if ( space == XENMAPSPACE_gmfn )
-        put_gfn(d, gfn);
+        put_gfn(d, _gfn(gfn));
 
     if ( page )
         put_page(page);
diff --git a/xen/arch/x86/mm/hap/hap.c b/xen/arch/x86/mm/hap/hap.c
index 3d651b9..0ac7d10 100644
--- a/xen/arch/x86/mm/hap/hap.c
+++ b/xen/arch/x86/mm/hap/hap.c
@@ -681,7 +681,7 @@ hap_paging_get_mode(struct vcpu *v)
 static void hap_update_paging_modes(struct vcpu *v)
 {
     struct domain *d = v->domain;
-    unsigned long cr3_gfn = v->arch.hvm.guest_cr[3] >> PAGE_SHIFT;
+    gfn_t cr3_gfn = gaddr_to_gfn(v->arch.hvm.guest_cr[3]);
     p2m_type_t t;
 
     /* We hold onto the cr3 as it may be modified later, and
diff --git a/xen/arch/x86/mm/hap/nested_hap.c b/xen/arch/x86/mm/hap/nested_hap.c
index d2a07a5..d83c436 100644
--- a/xen/arch/x86/mm/hap/nested_hap.c
+++ b/xen/arch/x86/mm/hap/nested_hap.c
@@ -150,12 +150,12 @@ nestedhap_walk_L0_p2m(struct p2m_domain *p2m, paddr_t L1_gpa, paddr_t *L0_gpa,
                       unsigned int *page_order,
                       bool_t access_r, bool_t access_w, bool_t access_x)
 {
+    gfn_t l1_gfn = gaddr_to_gfn(L1_gpa);
     mfn_t mfn;
     int rc;
 
     /* walk L0 P2M table */
-    mfn = get_gfn_type_access(p2m, L1_gpa >> PAGE_SHIFT, p2mt, p2ma,
-                              0, page_order);
+    mfn = get_gfn_type_access(p2m, l1_gfn, p2mt, p2ma, 0, page_order);
 
     rc = NESTEDHVM_PAGEFAULT_DIRECT_MMIO;
     if ( *p2mt == p2m_mmio_direct )
@@ -178,7 +178,7 @@ nestedhap_walk_L0_p2m(struct p2m_domain *p2m, paddr_t L1_gpa, paddr_t *L0_gpa,
 direct_mmio_out:
     *L0_gpa = (mfn_x(mfn) << PAGE_SHIFT) + (L1_gpa & ~PAGE_MASK);
 out:
-    __put_gfn(p2m, L1_gpa >> PAGE_SHIFT);
+    __put_gfn(p2m, l1_gfn);
     return rc;
 }
 
diff --git a/xen/arch/x86/mm/mem_access.c b/xen/arch/x86/mm/mem_access.c
index 30c2f1a..caa33c3 100644
--- a/xen/arch/x86/mm/mem_access.c
+++ b/xen/arch/x86/mm/mem_access.c
@@ -263,7 +263,6 @@ int p2m_set_altp2m_mem_access(struct domain *d, struct p2m_domain *hp2m,
     p2m_type_t t;
     p2m_access_t old_a;
     unsigned int page_order;
-    unsigned long gfn_l = gfn_x(gfn);
     int rc;
 
     mfn = ap2m->get_entry(ap2m, gfn, &t, &old_a, 0, NULL, NULL);
@@ -272,7 +271,7 @@ int p2m_set_altp2m_mem_access(struct domain *d, struct p2m_domain *hp2m,
     if ( !mfn_valid(mfn) )
     {
 
-        mfn = __get_gfn_type_access(hp2m, gfn_l, &t, &old_a,
+        mfn = __get_gfn_type_access(hp2m, gfn, &t, &old_a,
                                     P2M_ALLOC | P2M_UNSHARE, &page_order, 0);
 
         rc = -ESRCH;
@@ -283,7 +282,7 @@ int p2m_set_altp2m_mem_access(struct domain *d, struct p2m_domain *hp2m,
         if ( page_order != PAGE_ORDER_4K )
         {
             unsigned long mask = ~((1UL << page_order) - 1);
-            gfn_t gfn2 = _gfn(gfn_l & mask);
+            gfn_t gfn2 = _gfn(gfn_x(gfn) & mask);
             mfn_t mfn2 = _mfn(mfn_x(mfn) & mask);
 
             rc = ap2m->set_entry(ap2m, gfn2, mfn2, page_order, t, old_a, 1);
diff --git a/xen/arch/x86/mm/mem_sharing.c b/xen/arch/x86/mm/mem_sharing.c
index 573d354..7f2bf80 100644
--- a/xen/arch/x86/mm/mem_sharing.c
+++ b/xen/arch/x86/mm/mem_sharing.c
@@ -499,7 +499,7 @@ static int audit(void)
                 errors++;
                 continue;
             }
-            o_mfn = get_gfn_query_unlocked(d, g->gfn, &t); 
+            o_mfn = get_gfn_query_unlocked(d, _gfn(g->gfn), &t);
             if ( !mfn_eq(o_mfn, mfn) )
             {
                 MEM_SHARING_DEBUG("Incorrect P2M for d=%hu, PFN=%lx."
@@ -732,12 +732,12 @@ static int debug_gfn(struct domain *d, gfn_t gfn)
     mfn_t mfn;
     int num_refs;
 
-    mfn = get_gfn_query(d, gfn_x(gfn), &p2mt);
+    mfn = get_gfn_query(d, gfn, &p2mt);
 
     MEM_SHARING_DEBUG("Debug for dom%d, gfn=%" PRI_gfn "\n", 
                       d->domain_id, gfn_x(gfn));
     num_refs = debug_mfn(mfn);
-    put_gfn(d, gfn_x(gfn));
+    put_gfn(d, gfn);
 
     return num_refs;
 }
@@ -775,7 +775,7 @@ static int nominate_page(struct domain *d, gfn_t gfn,
 
     *phandle = 0UL;
 
-    mfn = get_gfn_type_access(hp2m, gfn_x(gfn), &p2mt, &p2ma, 0, NULL);
+    mfn = get_gfn_type_access(hp2m, gfn, &p2mt, &p2ma, 0, NULL);
 
     /* Check if mfn is valid */
     ret = -EINVAL;
@@ -820,7 +820,7 @@ static int nominate_page(struct domain *d, gfn_t gfn,
             if ( !ap2m )
                 continue;
 
-            amfn = __get_gfn_type_access(ap2m, gfn_x(gfn), &ap2mt, &ap2ma,
+            amfn = __get_gfn_type_access(ap2m, gfn, &ap2mt, &ap2ma,
                                          0, NULL, false);
             if ( mfn_valid(amfn) && (!mfn_eq(amfn, mfn) || ap2ma != p2ma) )
             {
@@ -885,7 +885,7 @@ static int nominate_page(struct domain *d, gfn_t gfn,
     ret = 0;
 
 out:
-    put_gfn(d, gfn_x(gfn));
+    put_gfn(d, gfn);
     return ret;
 }
 
@@ -1124,11 +1124,11 @@ int __mem_sharing_unshare_page(struct domain *d,
     int last_gfn;
     gfn_info_t *gfn_info = NULL;
    
-    mfn = get_gfn(d, gfn, &p2mt);
+    mfn = get_gfn(d, _gfn(gfn), &p2mt);
     
     /* Has someone already unshared it? */
     if ( !p2m_is_shared(p2mt) ) {
-        put_gfn(d, gfn);
+        put_gfn(d, _gfn(gfn));
         return 0;
     }
 
@@ -1175,7 +1175,7 @@ int __mem_sharing_unshare_page(struct domain *d,
         {
             if ( !get_page(page, d) )
             {
-                put_gfn(d, gfn);
+                put_gfn(d, _gfn(gfn));
                 domain_crash(d);
                 return -EOVERFLOW;
             }
@@ -1183,7 +1183,7 @@ int __mem_sharing_unshare_page(struct domain *d,
                 put_page(page);
             put_page(page);
         }
-        put_gfn(d, gfn);
+        put_gfn(d, _gfn(gfn));
 
         return 0;
     }
@@ -1202,7 +1202,7 @@ int __mem_sharing_unshare_page(struct domain *d,
         /* Undo dec of nr_saved_mfns, as the retry will decrease again. */
         atomic_inc(&nr_saved_mfns);
         mem_sharing_page_unlock(old_page);
-        put_gfn(d, gfn);
+        put_gfn(d, _gfn(gfn));
         /* Caller is responsible for placing an event
          * in the ring */
         return -ENOMEM;
@@ -1230,7 +1230,7 @@ int __mem_sharing_unshare_page(struct domain *d,
      * marking dirty is feasible */
     paging_mark_dirty(d, page_to_mfn(page));
     /* We do not need to unlock a private page */
-    put_gfn(d, gfn);
+    put_gfn(d, _gfn(gfn));
     return 0;
 }
 
diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
index f52a71e..19b383f 100644
--- a/xen/arch/x86/mm/p2m.c
+++ b/xen/arch/x86/mm/p2m.c
@@ -409,12 +409,11 @@ void p2m_unlock_and_tlb_flush(struct p2m_domain *p2m)
         mm_write_unlock(&p2m->lock);
 }
 
-mfn_t __get_gfn_type_access(struct p2m_domain *p2m, unsigned long gfn_l,
+mfn_t __get_gfn_type_access(struct p2m_domain *p2m, gfn_t gfn,
                     p2m_type_t *t, p2m_access_t *a, p2m_query_t q,
                     unsigned int *page_order, bool_t locked)
 {
     mfn_t mfn;
-    gfn_t gfn = _gfn(gfn_l);
 
     /* Unshare makes no sense withuot populate. */
     if ( q & P2M_UNSHARE )
@@ -425,7 +424,7 @@ mfn_t __get_gfn_type_access(struct p2m_domain *p2m, unsigned long gfn_l,
         /* Not necessarily true, but for non-translated guests, we claim
          * it's the most generic kind of memory */
         *t = p2m_ram_rw;
-        return _mfn(gfn_l);
+        return _mfn(gfn_x(gfn));
     }
 
     if ( locked )
@@ -439,8 +438,8 @@ mfn_t __get_gfn_type_access(struct p2m_domain *p2m, unsigned long gfn_l,
         ASSERT(p2m_is_hostp2m(p2m));
         /* Try to unshare. If we fail, communicate ENOMEM without
          * sleeping. */
-        if ( mem_sharing_unshare_page(p2m->domain, gfn_l, 0) < 0 )
-            mem_sharing_notify_enomem(p2m->domain, gfn_l, false);
+        if ( mem_sharing_unshare_page(p2m->domain, gfn_x(gfn), 0) < 0 )
+            mem_sharing_notify_enomem(p2m->domain, gfn_x(gfn), false);
         mfn = p2m->get_entry(p2m, gfn, t, a, q, page_order, NULL);
     }
 
@@ -455,7 +454,7 @@ mfn_t __get_gfn_type_access(struct p2m_domain *p2m, unsigned long gfn_l,
     return mfn;
 }
 
-void __put_gfn(struct p2m_domain *p2m, unsigned long gfn)
+void __put_gfn(struct p2m_domain *p2m, gfn_t gfn)
 {
     if ( !p2m || !paging_mode_translate(p2m->domain) )
         /* Nothing to do in this case */
@@ -484,7 +483,7 @@ struct page_info *p2m_get_page_from_gfn(
     {
         /* Fast path: look up and get out */
         p2m_read_lock(p2m);
-        mfn = __get_gfn_type_access(p2m, gfn_x(gfn), t, a, 0, NULL, 0);
+        mfn = __get_gfn_type_access(p2m, gfn, t, a, 0, NULL, 0);
         if ( p2m_is_any_ram(*t) && mfn_valid(mfn)
              && !((q & P2M_UNSHARE) && p2m_is_shared(*t)) )
         {
@@ -513,14 +512,14 @@ struct page_info *p2m_get_page_from_gfn(
     }
 
     /* Slow path: take the write lock and do fixups */
-    mfn = get_gfn_type_access(p2m, gfn_x(gfn), t, a, q, NULL);
+    mfn = get_gfn_type_access(p2m, gfn, t, a, q, NULL);
     if ( p2m_is_ram(*t) && mfn_valid(mfn) )
     {
         page = mfn_to_page(mfn);
         if ( !get_page(page, p2m->domain) )
             page = NULL;
     }
-    put_gfn(p2m->domain, gfn_x(gfn));
+    put_gfn(p2m->domain, gfn);
 
     return page;
 }
@@ -1278,7 +1277,7 @@ int set_shared_p2m_entry(struct domain *d, unsigned long gfn_l, mfn_t mfn)
     if ( rc )
         gdprintk(XENLOG_ERR,
                  "p2m_set_entry failed! mfn=%08lx rc:%d\n",
-                 mfn_x(get_gfn_query_unlocked(p2m->domain, gfn_l, &ot)), rc);
+                 mfn_x(get_gfn_query_unlocked(p2m->domain, gfn, &ot)), rc);
     return rc;
 }
 
@@ -2187,8 +2186,7 @@ bool p2m_altp2m_lazy_copy(struct vcpu *v, paddr_t gpa,
 
     ASSERT(p2m_locked_by_me(hp2m));
 
-    mfn = get_gfn_type_access(ap2m, gfn_x(gfn), &p2mt, &p2ma,
-                              0, &page_order);
+    mfn = get_gfn_type_access(ap2m, gfn, &p2mt, &p2ma, 0, &page_order);
 
     /* Entry already present in ap2m?  Caller should handle the fault. */
     if ( !mfn_eq(mfn, INVALID_MFN) )
@@ -2197,8 +2195,7 @@ bool p2m_altp2m_lazy_copy(struct vcpu *v, paddr_t gpa,
         goto put_ap2m;
     }
 
-    mfn = get_gfn_type_access(hp2m, gfn_x(gfn), &p2mt, &p2ma,
-                              P2M_ALLOC, &page_order);
+    mfn = get_gfn_type_access(hp2m, gfn, &p2mt, &p2ma, P2M_ALLOC, &page_order);
 
     /* Entry not present in hp2m?  Caller should handle the fault. */
     if ( mfn_eq(mfn, INVALID_MFN) )
@@ -2230,9 +2227,9 @@ bool p2m_altp2m_lazy_copy(struct vcpu *v, paddr_t gpa,
     ret = true;
 
 put_hp2m:
-    __put_gfn(hp2m, gfn_x(gfn));
+    __put_gfn(hp2m, gfn);
 put_ap2m:
-    __put_gfn(ap2m, gfn_x(gfn));
+    __put_gfn(ap2m, gfn);
 
     return ret;
 }
@@ -2396,7 +2393,7 @@ int p2m_change_altp2m_gfn(struct domain *d, unsigned int idx,
     /* Check host p2m if no valid entry in alternate */
     if ( !mfn_valid(mfn) )
     {
-        mfn = __get_gfn_type_access(hp2m, gfn_x(old_gfn), &t, &a,
+        mfn = __get_gfn_type_access(hp2m, old_gfn, &t, &a,
                                     P2M_ALLOC, &page_order, 0);
 
         if ( !mfn_valid(mfn) || t != p2m_ram_rw )
@@ -2477,7 +2474,7 @@ int p2m_altp2m_propagate_change(struct domain *d, gfn_t gfn,
             continue;
 
         p2m = d->arch.altp2m_p2m[i];
-        m = get_gfn_type_access(p2m, gfn_x(gfn), &t, &a, 0, NULL);
+        m = get_gfn_type_access(p2m, gfn, &t, &a, 0, NULL);
 
         /* Check for a dropped page that may impact this altp2m */
         if ( mfn_eq(mfn, INVALID_MFN) &&
@@ -2492,7 +2489,7 @@ int p2m_altp2m_propagate_change(struct domain *d, gfn_t gfn,
             else
             {
                 /* At least 2 altp2m's impacted, so reset everything */
-                __put_gfn(p2m, gfn_x(gfn));
+                __put_gfn(p2m, gfn);
 
                 for ( i = 0; i < MAX_ALTP2M; i++ )
                 {
@@ -2519,7 +2516,7 @@ int p2m_altp2m_propagate_change(struct domain *d, gfn_t gfn,
                 ret = rc;
         }
 
-        __put_gfn(p2m, gfn_x(gfn));
+        __put_gfn(p2m, gfn);
     }
 
     altp2m_list_unlock(d);
@@ -2590,7 +2587,7 @@ void audit_p2m(struct domain *d,
             continue;
         }
 
-        p2mfn = get_gfn_type_access(p2m, gfn, &type, &p2ma, 0, NULL);
+        p2mfn = get_gfn_type_access(p2m, _gfn(gfn), &type, &p2ma, 0, NULL);
         if ( mfn_x(p2mfn) != mfn )
         {
             mpbad++;
@@ -2605,7 +2602,7 @@ void audit_p2m(struct domain *d,
              * blow away the m2p entry. */
             set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY);
         }
-        __put_gfn(p2m, gfn);
+        __put_gfn(p2m, _gfn(gfn));
 
         P2M_PRINTK("OK: mfn=%#lx, gfn=%#lx, p2mfn=%#lx\n",
                        mfn, gfn, mfn_x(p2mfn));
@@ -2698,7 +2695,7 @@ int p2m_add_foreign(struct domain *tdom, unsigned long fgfn,
     mfn = page_to_mfn(page);
 
     /* Remove previously mapped page if it is present. */
-    prev_mfn = get_gfn(tdom, gpfn, &p2mt_prev);
+    prev_mfn = get_gfn(tdom, _gfn(gpfn), &p2mt_prev);
     if ( mfn_valid(prev_mfn) )
     {
         if ( is_xen_heap_mfn(mfn_x(prev_mfn)) )
@@ -2729,7 +2726,7 @@ int p2m_add_foreign(struct domain *tdom, unsigned long fgfn,
      * after set_foreign_p2m_entry so another cpu doesn't populate the gpfn
      * before us.
      */
-    put_gfn(tdom, gpfn);
+    put_gfn(tdom, _gfn(gpfn));
 
 out:
     if ( fdom )
diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c
index 61304d7..85ce761 100644
--- a/xen/arch/x86/mm/shadow/common.c
+++ b/xen/arch/x86/mm/shadow/common.c
@@ -3338,7 +3338,7 @@ int shadow_track_dirty_vram(struct domain *d,
 
         /* Iterate over VRAM to track dirty bits. */
         for ( i = 0; i < nr; i++ ) {
-            mfn_t mfn = get_gfn_query_unlocked(d, begin_pfn + i, &t);
+            mfn_t mfn = get_gfn_query_unlocked(d, _gfn(begin_pfn + i), &t);
             struct page_info *page;
             int dirty = 0;
             paddr_t sl1ma = dirty_vram->sl1ma[i];
@@ -3418,7 +3418,7 @@ int shadow_track_dirty_vram(struct domain *d,
              * write access */
             for ( i = begin_pfn; i < end_pfn; i++ )
             {
-                mfn_t mfn = get_gfn_query_unlocked(d, i, &t);
+                mfn_t mfn = get_gfn_query_unlocked(d, _gfn(i), &t);
                 if ( !mfn_eq(mfn, INVALID_MFN) )
                     flush_tlb |= sh_remove_write_access(d, mfn, 1, 0);
             }
diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c
index 7e9cbc6..de3fcd7 100644
--- a/xen/arch/x86/mm/shadow/multi.c
+++ b/xen/arch/x86/mm/shadow/multi.c
@@ -2126,7 +2126,8 @@ static int validate_gl4e(struct vcpu *v, void *new_ge, mfn_t sl4mfn, void *se)
          !guest_l4e_rsvd_bits(v, new_gl4e) )
     {
         gfn_t gl3gfn = guest_l4e_get_gfn(new_gl4e);
-        mfn_t gl3mfn = get_gfn_query_unlocked(d, gfn_x(gl3gfn), &p2mt);
+        mfn_t gl3mfn = get_gfn_query_unlocked(d, gl3gfn, &p2mt);
+
         if ( p2m_is_ram(p2mt) )
             sl3mfn = get_shadow_status(d, gl3mfn, SH_type_l3_shadow);
         else if ( p2mt != p2m_populate_on_demand )
@@ -2185,7 +2186,8 @@ static int validate_gl3e(struct vcpu *v, void *new_ge, mfn_t sl3mfn, void *se)
          !guest_l3e_rsvd_bits(v, new_gl3e) )
     {
         gfn_t gl2gfn = guest_l3e_get_gfn(new_gl3e);
-        mfn_t gl2mfn = get_gfn_query_unlocked(d, gfn_x(gl2gfn), &p2mt);
+        mfn_t gl2mfn = get_gfn_query_unlocked(d, gl2gfn, &p2mt);
+
         if ( p2m_is_ram(p2mt) )
             sl2mfn = get_shadow_status(d, gl2mfn, SH_type_l2_shadow);
         else if ( p2mt != p2m_populate_on_demand )
@@ -2236,7 +2238,8 @@ static int validate_gl2e(struct vcpu *v, void *new_ge, mfn_t sl2mfn, void *se)
         }
         else
         {
-            mfn_t gl1mfn = get_gfn_query_unlocked(d, gfn_x(gl1gfn), &p2mt);
+            mfn_t gl1mfn = get_gfn_query_unlocked(d, gl1gfn, &p2mt);
+
             if ( p2m_is_ram(p2mt) )
                 sl1mfn = get_shadow_status(d, gl1mfn, SH_type_l1_shadow);
             else if ( p2mt != p2m_populate_on_demand )
@@ -2270,7 +2273,7 @@ static int validate_gl1e(struct vcpu *v, void *new_ge, mfn_t sl1mfn, void *se)
          !guest_l1e_rsvd_bits(v, new_gl1e) )
     {
         gfn = guest_l1e_get_gfn(new_gl1e);
-        gmfn = get_gfn_query_unlocked(d, gfn_x(gfn), &p2mt);
+        gmfn = get_gfn_query_unlocked(d, gfn, &p2mt);
     }
 
     l1e_propagate_from_guest(v, new_gl1e, gmfn, &new_sl1e, ft_prefetch, p2mt);
@@ -2335,7 +2338,7 @@ void sh_resync_l1(struct vcpu *v, mfn_t gl1mfn, mfn_t snpmfn)
                  !guest_l1e_rsvd_bits(v, gl1e) )
             {
                 gfn = guest_l1e_get_gfn(gl1e);
-                gmfn = get_gfn_query_unlocked(d, gfn_x(gfn), &p2mt);
+                gmfn = get_gfn_query_unlocked(d, gfn, &p2mt);
             }
 
             l1e_propagate_from_guest(v, gl1e, gmfn, &nsl1e, ft_prefetch, p2mt);
@@ -2615,7 +2618,7 @@ static void sh_prefetch(struct vcpu *v, walk_t *gw,
              !guest_l1e_rsvd_bits(v, gl1e) )
         {
             gfn = guest_l1e_get_gfn(gl1e);
-            gmfn = get_gfn_query_unlocked(d, gfn_x(gfn), &p2mt);
+            gmfn = get_gfn_query_unlocked(d, gfn, &p2mt);
         }
         else
         {
@@ -3071,7 +3074,7 @@ static int sh_page_fault(struct vcpu *v,
         SHADOW_PRINTK("BAD gfn=%"SH_PRI_gfn" gmfn=%"PRI_mfn"\n",
                       gfn_x(gfn), mfn_x(gmfn));
         sh_reset_early_unshadow(v);
-        put_gfn(d, gfn_x(gfn));
+        put_gfn(d, gfn);
         goto propagate;
     }
 
@@ -3117,7 +3120,7 @@ static int sh_page_fault(struct vcpu *v,
     if ( rc & GW_RMWR_REWALK )
     {
         paging_unlock(d);
-        put_gfn(d, gfn_x(gfn));
+        put_gfn(d, gfn);
         goto rewalk;
     }
 #endif /* OOS */
@@ -3126,7 +3129,7 @@ static int sh_page_fault(struct vcpu *v,
     {
         perfc_incr(shadow_inconsistent_gwalk);
         paging_unlock(d);
-        put_gfn(d, gfn_x(gfn));
+        put_gfn(d, gfn);
         goto rewalk;
     }
 
@@ -3153,7 +3156,7 @@ static int sh_page_fault(struct vcpu *v,
         ASSERT(d->is_shutting_down);
 #endif
         paging_unlock(d);
-        put_gfn(d, gfn_x(gfn));
+        put_gfn(d, gfn);
         trace_shadow_gen(TRC_SHADOW_DOMF_DYING, va);
         return 0;
     }
@@ -3171,7 +3174,7 @@ static int sh_page_fault(struct vcpu *v,
          * failed. We cannot safely continue since some page is still
          * OOS but not in the hash table anymore. */
         paging_unlock(d);
-        put_gfn(d, gfn_x(gfn));
+        put_gfn(d, gfn);
         return 0;
     }
 
@@ -3181,7 +3184,7 @@ static int sh_page_fault(struct vcpu *v,
     {
         perfc_incr(shadow_inconsistent_gwalk);
         paging_unlock(d);
-        put_gfn(d, gfn_x(gfn));
+        put_gfn(d, gfn);
         goto rewalk;
     }
 #endif /* OOS */
@@ -3267,7 +3270,7 @@ static int sh_page_fault(struct vcpu *v,
     SHADOW_PRINTK("fixed\n");
     shadow_audit_tables(v);
     paging_unlock(d);
-    put_gfn(d, gfn_x(gfn));
+    put_gfn(d, gfn);
     return EXCRET_fault_fixed;
 
  emulate:
@@ -3337,7 +3340,7 @@ static int sh_page_fault(struct vcpu *v,
     sh_audit_gw(v, &gw);
     shadow_audit_tables(v);
     paging_unlock(d);
-    put_gfn(d, gfn_x(gfn));
+    put_gfn(d, gfn);
 
     this_cpu(trace_emulate_write_val) = 0;
 
@@ -3521,7 +3524,7 @@ static int sh_page_fault(struct vcpu *v,
     shadow_audit_tables(v);
     sh_reset_early_unshadow(v);
     paging_unlock(d);
-    put_gfn(d, gfn_x(gfn));
+    put_gfn(d, gfn);
     trace_shadow_gen(TRC_SHADOW_MMIO, va);
     return (handle_mmio_with_translation(va, gpa >> PAGE_SHIFT, access)
             ? EXCRET_fault_fixed : 0);
@@ -3535,7 +3538,7 @@ static int sh_page_fault(struct vcpu *v,
     shadow_audit_tables(v);
     sh_reset_early_unshadow(v);
     paging_unlock(d);
-    put_gfn(d, gfn_x(gfn));
+    put_gfn(d, gfn);
 
 propagate:
     trace_not_shadow_fault(gw.l1e, va);
@@ -4116,7 +4119,7 @@ sh_update_cr3(struct vcpu *v, int do_locking, bool noflush)
             if ( guest_l3e_get_flags(gl3e[i]) & _PAGE_PRESENT )
             {
                 gl2gfn = guest_l3e_get_gfn(gl3e[i]);
-                gl2mfn = get_gfn_query_unlocked(d, gfn_x(gl2gfn), &p2mt);
+                gl2mfn = get_gfn_query_unlocked(d, gl2gfn, &p2mt);
                 if ( p2m_is_ram(p2mt) )
                     flush |= sh_remove_write_access(d, gl2mfn, 2, 0);
             }
@@ -4129,7 +4132,7 @@ sh_update_cr3(struct vcpu *v, int do_locking, bool noflush)
             if ( guest_l3e_get_flags(gl3e[i]) & _PAGE_PRESENT )
             {
                 gl2gfn = guest_l3e_get_gfn(gl3e[i]);
-                gl2mfn = get_gfn_query_unlocked(d, gfn_x(gl2gfn), &p2mt);
+                gl2mfn = get_gfn_query_unlocked(d, gl2gfn, &p2mt);
                 if ( p2m_is_ram(p2mt) )
                     sh_set_toplevel_shadow(v, i, gl2mfn, (i == 3)
                                            ? SH_type_l2h_shadow
@@ -4536,7 +4539,7 @@ static void sh_pagetable_dying(paddr_t gpa)
     p2m_type_t p2mt;
     char *gl3pa = NULL;
     guest_l3e_t *gl3e = NULL;
-    unsigned long l3gfn;
+    gfn_t l3gfn;
     mfn_t l3mfn;
 
     gcr3 = v->arch.hvm.guest_cr[3];
@@ -4544,8 +4547,8 @@ static void sh_pagetable_dying(paddr_t gpa)
     if ( gcr3 == gpa )
         fast_path = 1;
 
-    l3gfn = gpa >> PAGE_SHIFT;
-    l3mfn = get_gfn_query(d, _gfn(l3gfn), &p2mt);
+    l3gfn = gaddr_to_gfn(gpa);
+    l3mfn = get_gfn_query(d, l3gfn, &p2mt);
     if ( !mfn_valid(l3mfn) || !p2m_is_ram(p2mt) )
     {
         printk(XENLOG_DEBUG "sh_pagetable_dying: gpa not valid %"PRIpaddr"\n",
@@ -4573,8 +4576,7 @@ static void sh_pagetable_dying(paddr_t gpa)
         else
         {
             /* retrieving the l2s */
-            gmfn = get_gfn_query_unlocked(d, gfn_x(guest_l3e_get_gfn(gl3e[i])),
-                                          &p2mt);
+            gmfn = get_gfn_query_unlocked(d, guest_l3e_get_gfn(gl3e[i]), &p2mt);
             smfn = unlikely(mfn_eq(gmfn, INVALID_MFN))
                    ? INVALID_MFN
                    : shadow_hash_lookup(d, mfn_x(gmfn), SH_type_l2_pae_shadow);
@@ -4609,10 +4611,11 @@ static void sh_pagetable_dying(paddr_t gpa)
 {
     struct vcpu *v = current;
     struct domain *d = v->domain;
+    gfn_t gfn = gaddr_to_gfn(gpa);
     mfn_t smfn, gmfn;
     p2m_type_t p2mt;
 
-    gmfn = get_gfn_query(d, _gfn(gpa >> PAGE_SHIFT), &p2mt);
+    gmfn = get_gfn_query(d, gfn, &p2mt);
     paging_lock(d);
 
 #if GUEST_PAGING_LEVELS == 2
@@ -4637,7 +4640,7 @@ static void sh_pagetable_dying(paddr_t gpa)
     v->arch.paging.shadow.pagetable_dying = 1;
 
     paging_unlock(d);
-    put_gfn(d, gpa >> PAGE_SHIFT);
+    put_gfn(d, gfn);
 }
 #endif
 
@@ -4759,7 +4762,7 @@ int sh_audit_l1_table(struct vcpu *v, mfn_t sl1mfn, mfn_t x)
             {
                 gfn = guest_l1e_get_gfn(*gl1e);
                 mfn = shadow_l1e_get_mfn(*sl1e);
-                gmfn = get_gfn_query_unlocked(v->domain, gfn_x(gfn), &p2mt);
+                gmfn = get_gfn_query_unlocked(v->domain, gfn, &p2mt);
                 if ( !p2m_is_grant(p2mt) && !mfn_eq(gmfn, mfn) )
                     AUDIT_FAIL(1, "bad translation: gfn %" SH_PRI_gfn
                                " --> %" PRI_mfn " != mfn %" PRI_mfn,
@@ -4832,16 +4835,15 @@ int sh_audit_l2_table(struct vcpu *v, mfn_t sl2mfn, mfn_t x)
             gmfn = (guest_l2e_get_flags(*gl2e) & _PAGE_PSE)
                 ? get_fl1_shadow_status(d, gfn)
                 : get_shadow_status(d,
-                    get_gfn_query_unlocked(d, gfn_x(gfn),
-                                        &p2mt), SH_type_l1_shadow);
+                    get_gfn_query_unlocked(d, gfn, &p2mt), SH_type_l1_shadow);
             if ( !mfn_eq(gmfn, mfn) )
                 AUDIT_FAIL(2, "bad translation: gfn %" SH_PRI_gfn
                            " (--> %" PRI_mfn ")"
                            " --> %" PRI_mfn " != mfn %" PRI_mfn,
                            gfn_x(gfn),
                            (guest_l2e_get_flags(*gl2e) & _PAGE_PSE) ? 0
-                           : mfn_x(get_gfn_query_unlocked(d,
-                                   gfn_x(gfn), &p2mt)), mfn_x(gmfn), mfn_x(mfn));
+                           : mfn_x(get_gfn_query_unlocked(d, gfn, &p2mt)),
+                           mfn_x(gmfn), mfn_x(mfn));
         }
     });
     unmap_domain_page(gp);
@@ -4881,8 +4883,7 @@ int sh_audit_l3_table(struct vcpu *v, mfn_t sl3mfn, mfn_t x)
         {
             gfn = guest_l3e_get_gfn(*gl3e);
             mfn = shadow_l3e_get_mfn(*sl3e);
-            gmfn = get_shadow_status(d, get_gfn_query_unlocked(
-                                        d, gfn_x(gfn), &p2mt),
+            gmfn = get_shadow_status(d, get_gfn_query_unlocked(d, gfn, &p2mt),
                                      ((GUEST_PAGING_LEVELS == 3 ||
                                        is_pv_32bit_domain(d))
                                       && !shadow_mode_external(d)
@@ -4931,8 +4932,7 @@ int sh_audit_l4_table(struct vcpu *v, mfn_t sl4mfn, mfn_t x)
         {
             gfn = guest_l4e_get_gfn(*gl4e);
             mfn = shadow_l4e_get_mfn(*sl4e);
-            gmfn = get_shadow_status(d, get_gfn_query_unlocked(
-                                     d, gfn_x(gfn), &p2mt),
+            gmfn = get_shadow_status(d, get_gfn_query_unlocked(d, gfn, &p2mt),
                                      SH_type_l3_shadow);
             if ( !mfn_eq(gmfn, mfn) )
                 AUDIT_FAIL(4, "bad translation: gfn %" SH_PRI_gfn
diff --git a/xen/arch/x86/mm/shadow/types.h b/xen/arch/x86/mm/shadow/types.h
index d509674..f688919 100644
--- a/xen/arch/x86/mm/shadow/types.h
+++ b/xen/arch/x86/mm/shadow/types.h
@@ -193,10 +193,6 @@ static inline shadow_l4e_t shadow_l4e_from_mfn(mfn_t mfn, u32 flags)
 })
 #endif
 
- /* Override get_gfn to work with gfn_t */
-#undef get_gfn_query
-#define get_gfn_query(d, g, t) get_gfn_type((d), gfn_x(g), (t), 0)
-
 /* The shadow types needed for the various levels. */
 
 #if GUEST_PAGING_LEVELS == 2
diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
index f7860f6..54f909f 100644
--- a/xen/common/grant_table.c
+++ b/xen/common/grant_table.c
@@ -2099,7 +2099,7 @@ gnttab_transfer(
         {
             p2m_type_t p2mt;
 
-            mfn = get_gfn_unshare(d, gop.mfn, &p2mt);
+            mfn = get_gfn_unshare(d, _gfn(gop.mfn), &p2mt);
             if ( p2m_is_shared(p2mt) || !p2m_is_valid(p2mt) )
                 mfn = INVALID_MFN;
         }
@@ -2111,7 +2111,7 @@ gnttab_transfer(
         if ( unlikely(!mfn_valid(mfn)) )
         {
 #ifdef CONFIG_X86
-            put_gfn(d, gop.mfn);
+            put_gfn(d, _gfn(gop.mfn));
 #endif
             gdprintk(XENLOG_INFO, "out-of-range %lx\n", (unsigned long)gop.mfn);
             gop.status = GNTST_bad_page;
@@ -2122,7 +2122,7 @@ gnttab_transfer(
         if ( (rc = steal_page(d, page, 0)) < 0 )
         {
 #ifdef CONFIG_X86
-            put_gfn(d, gop.mfn);
+            put_gfn(d, _gfn(gop.mfn));
 #endif
             gop.status = rc == -EINVAL ? GNTST_bad_page : GNTST_general_error;
             goto copyback;
@@ -2154,7 +2154,7 @@ gnttab_transfer(
             rcu_unlock_domain(e);
         put_gfn_and_copyback:
 #ifdef CONFIG_X86
-            put_gfn(d, gop.mfn);
+            put_gfn(d, _gfn(gop.mfn));
 #endif
             page->count_info &= ~(PGC_count_mask|PGC_allocated);
             free_domheap_page(page);
@@ -2243,7 +2243,7 @@ gnttab_transfer(
 
         spin_unlock(&e->page_alloc_lock);
 #ifdef CONFIG_X86
-        put_gfn(d, gop.mfn);
+        put_gfn(d, _gfn(gop.mfn));
 #endif
 
         TRACE_1D(TRC_MEM_PAGE_GRANT_TRANSFER, e->domain_id);
diff --git a/xen/common/memory.c b/xen/common/memory.c
index 175bd62..c59a017 100644
--- a/xen/common/memory.c
+++ b/xen/common/memory.c
@@ -303,10 +303,10 @@ int guest_remove_page(struct domain *d, unsigned long gmfn)
     int rc;
 
 #ifdef CONFIG_X86
-    mfn = get_gfn_query(d, gmfn, &p2mt);
+    mfn = get_gfn_query(d, _gfn(gmfn), &p2mt);
     if ( unlikely(p2mt == p2m_invalid) || unlikely(p2mt == p2m_mmio_dm) )
     {
-        put_gfn(d, gmfn);
+        put_gfn(d, _gfn(gmfn));
 
         return -ENOENT;
     }
@@ -336,7 +336,7 @@ int guest_remove_page(struct domain *d, unsigned long gmfn)
             goto out_put_gfn;
         }
 
-        put_gfn(d, gmfn);
+        put_gfn(d, _gfn(gmfn));
 
         if ( page )
         {
@@ -359,7 +359,7 @@ int guest_remove_page(struct domain *d, unsigned long gmfn)
     if ( unlikely(!mfn_valid(mfn)) )
     {
 #ifdef CONFIG_X86
-        put_gfn(d, gmfn);
+        put_gfn(d, _gfn(gmfn));
 #endif
         gdprintk(XENLOG_INFO, "Domain %u page number %lx invalid\n",
                 d->domain_id, gmfn);
@@ -382,7 +382,7 @@ int guest_remove_page(struct domain *d, unsigned long gmfn)
             goto out_put_gfn;
         }
         /* Maybe the mfn changed */
-        mfn = get_gfn_query_unlocked(d, gmfn, &p2mt);
+        mfn = get_gfn_query_unlocked(d, _gfn(gmfn), &p2mt);
         ASSERT(!p2m_is_shared(p2mt));
     }
 #endif /* CONFIG_X86 */
@@ -391,7 +391,7 @@ int guest_remove_page(struct domain *d, unsigned long gmfn)
     if ( unlikely(!get_page(page, d)) )
     {
 #ifdef CONFIG_X86
-        put_gfn(d, gmfn);
+        put_gfn(d, _gfn(gmfn));
 #endif
         gdprintk(XENLOG_INFO, "Bad page free for domain %u\n", d->domain_id);
 
@@ -416,7 +416,7 @@ int guest_remove_page(struct domain *d, unsigned long gmfn)
 
 #ifdef CONFIG_X86
  out_put_gfn:
-    put_gfn(d, gmfn);
+    put_gfn(d, _gfn(gmfn));
 #endif
 
     /*
@@ -651,10 +651,10 @@ static long memory_exchange(XEN_GUEST_HANDLE_PARAM(xen_memory_exchange_t) arg)
                 p2m_type_t p2mt;
 
                 /* Shared pages cannot be exchanged */
-                mfn = get_gfn_unshare(d, gmfn + k, &p2mt);
+                mfn = get_gfn_unshare(d, _gfn(gmfn + k), &p2mt);
                 if ( p2m_is_shared(p2mt) )
                 {
-                    put_gfn(d, gmfn + k);
+                    put_gfn(d, _gfn(gmfn + k));
                     rc = -ENOMEM;
                     goto fail; 
                 }
@@ -664,7 +664,7 @@ static long memory_exchange(XEN_GUEST_HANDLE_PARAM(xen_memory_exchange_t) arg)
                 if ( unlikely(!mfn_valid(mfn)) )
                 {
 #ifdef CONFIG_X86
-                    put_gfn(d, gmfn + k);
+                    put_gfn(d, _gfn(gmfn + k));
 #endif
                     rc = -EINVAL;
                     goto fail;
@@ -676,14 +676,14 @@ static long memory_exchange(XEN_GUEST_HANDLE_PARAM(xen_memory_exchange_t) arg)
                 if ( unlikely(rc) )
                 {
 #ifdef CONFIG_X86
-                    put_gfn(d, gmfn + k);
+                    put_gfn(d, _gfn(gmfn + k));
 #endif
                     goto fail;
                 }
 
                 page_list_add(page, &in_chunk_list);
 #ifdef CONFIG_X86
-                put_gfn(d, gmfn + k);
+                put_gfn(d, _gfn(gmfn + k));
 #endif
             }
         }
diff --git a/xen/drivers/passthrough/amd/iommu_guest.c b/xen/drivers/passthrough/amd/iommu_guest.c
index 03ca0cf..7ab3c77 100644
--- a/xen/drivers/passthrough/amd/iommu_guest.c
+++ b/xen/drivers/passthrough/amd/iommu_guest.c
@@ -21,14 +21,6 @@
 #include <asm/amd-iommu.h>
 #include <asm/hvm/svm/amd-iommu-proto.h>
 
-/* Override {get,put}_gfn to work with gfn_t */
-#undef get_gfn
-#define get_gfn(d, g, t) get_gfn_type(d, gfn_x(g), t, P2M_ALLOC)
-#undef get_gfn_query
-#define get_gfn_query(d, g, t) get_gfn_type(d, gfn_x(g), t, 0)
-#undef put_gfn
-#define put_gfn(d, g) __put_gfn(p2m_get_hostp2m(d), gfn_x(g))
-
 #define IOMMU_MMIO_SIZE                         0x8000
 #define IOMMU_MMIO_PAGE_NR                      0x8
 #define RING_BF_LENGTH_MASK                     0x0F000000
diff --git a/xen/include/asm-x86/guest_pt.h b/xen/include/asm-x86/guest_pt.h
index 8684b83..87c6815 100644
--- a/xen/include/asm-x86/guest_pt.h
+++ b/xen/include/asm-x86/guest_pt.h
@@ -38,10 +38,6 @@ gfn_to_paddr(gfn_t gfn)
     return ((paddr_t)gfn_x(gfn)) << PAGE_SHIFT;
 }
 
-/* Override get_gfn to work with gfn_t */
-#undef get_gfn
-#define get_gfn(d, g, t) get_gfn_type((d), gfn_x(g), (t), P2M_ALLOC)
-
 /* Mask covering the reserved bits from superpage alignment. */
 #define SUPERPAGE_RSVD(bit)                                             \
     (((1ul << (bit)) - 1) & ~(_PAGE_PSE_PAT | (_PAGE_PSE_PAT - 1ul)))
diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h
index 8bd6f64..e332f06 100644
--- a/xen/include/asm-x86/p2m.h
+++ b/xen/include/asm-x86/p2m.h
@@ -431,7 +431,7 @@ void p2m_unlock_and_tlb_flush(struct p2m_domain *p2m);
  * put_gfn. ****/
 
 mfn_t __nonnull(3, 4) __get_gfn_type_access(
-    struct p2m_domain *p2m, unsigned long gfn, p2m_type_t *t,
+    struct p2m_domain *p2m, gfn_t gfn, p2m_type_t *t,
     p2m_access_t *a, p2m_query_t q, unsigned int *page_order, bool_t locked);
 
 /*
@@ -444,7 +444,7 @@ mfn_t __nonnull(3, 4) __get_gfn_type_access(
  * the entry was found in.
  */
 static inline mfn_t __nonnull(3, 4) get_gfn_type_access(
-    struct p2m_domain *p2m, unsigned long gfn, p2m_type_t *t,
+    struct p2m_domain *p2m, gfn_t gfn, p2m_type_t *t,
     p2m_access_t *a, p2m_query_t q, unsigned int *page_order)
 {
     return __get_gfn_type_access(p2m, gfn, t, a, q, page_order, true);
@@ -452,22 +452,21 @@ static inline mfn_t __nonnull(3, 4) get_gfn_type_access(
 
 /* General conversion function from gfn to mfn */
 static inline mfn_t __nonnull(3) get_gfn_type(
-    struct domain *d, unsigned long gfn, p2m_type_t *t, p2m_query_t q)
+    struct domain *d, gfn_t gfn, p2m_type_t *t, p2m_query_t q)
 {
     p2m_access_t a;
     return get_gfn_type_access(p2m_get_hostp2m(d), gfn, t, &a, q, NULL);
 }
 
 /* Syntactic sugar: most callers will use one of these. */
-#define get_gfn(d, g, t)         get_gfn_type((d), (g), (t), P2M_ALLOC)
-#define get_gfn_query(d, g, t)   get_gfn_type((d), (g), (t), 0)
-#define get_gfn_unshare(d, g, t) get_gfn_type((d), (g), (t), \
-                                              P2M_ALLOC | P2M_UNSHARE)
+#define get_gfn(d, g, t)         get_gfn_type(d, g, t, P2M_ALLOC)
+#define get_gfn_query(d, g, t)   get_gfn_type(d, g, t, 0)
+#define get_gfn_unshare(d, g, t) get_gfn_type(d, g, t, P2M_ALLOC | P2M_UNSHARE)
 
 /* Will release the p2m_lock for this gfn entry. */
-void __put_gfn(struct p2m_domain *p2m, unsigned long gfn);
+void __put_gfn(struct p2m_domain *p2m, gfn_t gfn);
 
-#define put_gfn(d, gfn) __put_gfn(p2m_get_hostp2m((d)), (gfn))
+#define put_gfn(d, g) __put_gfn(p2m_get_hostp2m(d), g)
 
 /*
  * The intent of the "unlocked" accessor is to have the caller not worry about
@@ -484,9 +483,8 @@ void __put_gfn(struct p2m_domain *p2m, unsigned long gfn);
  * Any other type of query can cause a change in the p2m and may need to
  * perform locking.
  */
-static inline mfn_t get_gfn_query_unlocked(struct domain *d,
-                                           unsigned long gfn,
-                                           p2m_type_t *t)
+static inline mfn_t get_gfn_query_unlocked(
+    struct domain *d, gfn_t gfn, p2m_type_t *t)
 {
     p2m_access_t a;
     return __get_gfn_type_access(p2m_get_hostp2m(d), gfn, t, &a, 0, NULL, 0);
@@ -569,9 +567,9 @@ do {                                                    \
 
     /* Now do the gets */
     *first_mfn  = get_gfn_type_access(p2m_get_hostp2m(rval->first_domain),
-                                      gfn_x(rval->first_gfn), first_t, first_a, q, NULL);
+                                      rval->first_gfn, first_t, first_a, q, NULL);
     *second_mfn = get_gfn_type_access(p2m_get_hostp2m(rval->second_domain),
-                                      gfn_x(rval->second_gfn), second_t, second_a, q, NULL);
+                                      rval->second_gfn, second_t, second_a, q, NULL);
 }
 
 static inline void put_two_gfns(struct two_gfns *arg)
@@ -579,8 +577,8 @@ static inline void put_two_gfns(struct two_gfns *arg)
     if ( !arg )
         return;
 
-    put_gfn(arg->second_domain, gfn_x(arg->second_gfn));
-    put_gfn(arg->first_domain,  gfn_x(arg->first_gfn));
+    put_gfn(arg->second_domain, arg->second_gfn);
+    put_gfn(arg->first_domain,  arg->first_gfn);
 }
 
 /* Init the datastructures for later use by the p2m code */
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 11/14] xen/mm: Switch mfn_to_virt()/virt_to_mfn() to using mfn_t
  2018-11-21 13:21 [PATCH 00/14] XSA-277 followup Andrew Cooper
                   ` (9 preceding siblings ...)
  2018-11-21 13:21 ` [PATCH 10/14] x86/mm: Switch {get, put}_gfn() " Andrew Cooper
@ 2018-11-21 13:21 ` Andrew Cooper
  2018-11-22 14:32   ` Julien Grall
  2018-11-22 15:44   ` Jan Beulich
  2018-11-21 13:21 ` [PATCH 12/14] xen/gnttab: Drop gnttab_create_{shared, status}_page() Andrew Cooper
                   ` (4 subsequent siblings)
  15 siblings, 2 replies; 59+ messages in thread
From: Andrew Cooper @ 2018-11-21 13:21 UTC (permalink / raw)
  To: Xen-devel
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Julien Grall,
	Jan Beulich, Roger Pau Monné

Seemingly, a majority of users either override the helpers anyway, or have an
mfn_t in their hands.

Update the API, and adjust all users to match.  In some places, use the
unsigned long variant in places where we are interacting with an external
struct and there is no chance of them switching to mfn_t.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Stefano Stabellini <sstabellini@kernel.org>
CC: Julien Grall <julien.grall@arm.com>
---
 xen/arch/arm/alternative.c          |  4 ----
 xen/arch/arm/cpuerrata.c            |  4 ----
 xen/arch/arm/domain_build.c         |  4 ----
 xen/arch/arm/livepatch.c            |  4 ----
 xen/arch/arm/mm.c                   |  6 ------
 xen/arch/arm/setup.c                |  4 ++--
 xen/arch/x86/domain.c               |  2 +-
 xen/arch/x86/domain_page.c          | 10 +++++-----
 xen/arch/x86/guest/xen.c            |  2 +-
 xen/arch/x86/hvm/dom0_build.c       |  4 ++--
 xen/arch/x86/mm.c                   | 15 ++++++---------
 xen/arch/x86/numa.c                 |  2 +-
 xen/arch/x86/pv/descriptor-tables.c |  2 +-
 xen/arch/x86/pv/dom0_build.c        |  5 ++---
 xen/arch/x86/pv/shim.c              |  3 ---
 xen/arch/x86/setup.c                | 10 +++++-----
 xen/arch/x86/srat.c                 |  2 +-
 xen/arch/x86/tboot.c                |  4 ++--
 xen/arch/x86/x86_64/mm.c            | 10 +++++-----
 xen/common/domctl.c                 |  2 +-
 xen/common/efi/boot.c               |  7 ++++---
 xen/common/grant_table.c            |  4 ++--
 xen/common/page_alloc.c             | 10 +++++-----
 xen/common/tmem.c                   |  2 +-
 xen/common/trace.c                  | 20 +++++++++++---------
 xen/common/xenoprof.c               |  4 ----
 xen/drivers/acpi/osl.c              |  2 +-
 xen/include/asm-arm/mm.h            |  6 +++---
 xen/include/asm-x86/mm.h            |  2 +-
 xen/include/asm-x86/page.h          |  4 ++--
 xen/include/xen/domain_page.h       |  6 +++---
 31 files changed, 68 insertions(+), 98 deletions(-)

diff --git a/xen/arch/arm/alternative.c b/xen/arch/arm/alternative.c
index 52ed7ed..22ab4e2 100644
--- a/xen/arch/arm/alternative.c
+++ b/xen/arch/arm/alternative.c
@@ -34,10 +34,6 @@
 #include <asm/livepatch.h>
 #include <asm/page.h>
 
-/* Override macros from asm/page.h to make them work with mfn_t */
-#undef virt_to_mfn
-#define virt_to_mfn(va) _mfn(__virt_to_mfn(va))
-
 extern const struct alt_instr __alt_instructions[], __alt_instructions_end[];
 
 struct alt_region {
diff --git a/xen/arch/arm/cpuerrata.c b/xen/arch/arm/cpuerrata.c
index adf88e7..992c3a7 100644
--- a/xen/arch/arm/cpuerrata.c
+++ b/xen/arch/arm/cpuerrata.c
@@ -13,10 +13,6 @@
 #include <asm/insn.h>
 #include <asm/psci.h>
 
-/* Override macros from asm/page.h to make them work with mfn_t */
-#undef virt_to_mfn
-#define virt_to_mfn(va) _mfn(__virt_to_mfn(va))
-
 /* Hardening Branch predictor code for Arm64 */
 #ifdef CONFIG_ARM64_HARDEN_BRANCH_PREDICTOR
 
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index b0ec3f0..e201787 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -47,10 +47,6 @@ struct map_range_data
     p2m_type_t p2mt;
 };
 
-/* Override macros from asm/page.h to make them work with mfn_t */
-#undef virt_to_mfn
-#define virt_to_mfn(va) _mfn(__virt_to_mfn(va))
-
 //#define DEBUG_11_ALLOCATION
 #ifdef DEBUG_11_ALLOCATION
 # define D11PRINT(fmt, args...) printk(XENLOG_DEBUG fmt, ##args)
diff --git a/xen/arch/arm/livepatch.c b/xen/arch/arm/livepatch.c
index 279d52c..a8c6e24 100644
--- a/xen/arch/arm/livepatch.c
+++ b/xen/arch/arm/livepatch.c
@@ -12,10 +12,6 @@
 #include <asm/livepatch.h>
 #include <asm/mm.h>
 
-/* Override macros from asm/page.h to make them work with mfn_t */
-#undef virt_to_mfn
-#define virt_to_mfn(va) _mfn(__virt_to_mfn(va))
-
 void *vmap_of_xen_text;
 
 int arch_livepatch_quiesce(void)
diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
index 7a06a33..9db69e6 100644
--- a/xen/arch/arm/mm.c
+++ b/xen/arch/arm/mm.c
@@ -44,12 +44,6 @@
 
 struct domain *dom_xen, *dom_io, *dom_cow;
 
-/* Override macros from asm/page.h to make them work with mfn_t */
-#undef virt_to_mfn
-#define virt_to_mfn(va) _mfn(__virt_to_mfn(va))
-#undef mfn_to_virt
-#define mfn_to_virt(mfn) __mfn_to_virt(mfn_x(mfn))
-
 /* Static start-of-day pagetables that we use before the allocators
  * are up. These are used by all CPUs during bringup before switching
  * to the CPUs own pagetables.
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index e83221a..77d19a8 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -655,7 +655,7 @@ static void __init setup_mm(unsigned long dtb_paddr, size_t dtb_size)
     init_boot_pages(pfn_to_paddr(boot_mfn_start), pfn_to_paddr(boot_mfn_end));
 
     /* Copy the DTB. */
-    fdt = mfn_to_virt(mfn_x(alloc_boot_pages(dtb_pages, 1)));
+    fdt = mfn_to_virt(alloc_boot_pages(dtb_pages, 1));
     copy_from_paddr(fdt, dtb_paddr, dtb_size);
     device_tree_flattened = fdt;
 
@@ -765,7 +765,7 @@ static void __init setup_mm(unsigned long dtb_paddr, size_t dtb_size)
     dtb_pages = (dtb_size + PAGE_SIZE-1) >> PAGE_SHIFT;
 
     /* Copy the DTB. */
-    fdt = mfn_to_virt(mfn_x(alloc_boot_pages(dtb_pages, 1)));
+    fdt = mfn_to_virt(alloc_boot_pages(dtb_pages, 1));
     copy_from_paddr(fdt, dtb_paddr, dtb_size);
     device_tree_flattened = fdt;
 
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index 327c961..14902fe 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -1709,7 +1709,7 @@ static void __context_switch(void)
                                     per_cpu(compat_gdt_table, cpu);
     if ( need_full_gdt(nd) )
     {
-        unsigned long mfn = virt_to_mfn(gdt);
+        unsigned long mfn = mfn_x(virt_to_mfn(gdt));
         l1_pgentry_t *pl1e = pv_gdt_ptes(n);
         unsigned int i;
 
diff --git a/xen/arch/x86/domain_page.c b/xen/arch/x86/domain_page.c
index 4a07cfb..0d7cafc 100644
--- a/xen/arch/x86/domain_page.c
+++ b/xen/arch/x86/domain_page.c
@@ -78,17 +78,17 @@ void *map_domain_page(mfn_t mfn)
 
 #ifdef NDEBUG
     if ( mfn_x(mfn) <= PFN_DOWN(__pa(HYPERVISOR_VIRT_END - 1)) )
-        return mfn_to_virt(mfn_x(mfn));
+        return mfn_to_virt(mfn);
 #endif
 
     v = mapcache_current_vcpu();
     if ( !v || !is_pv_vcpu(v) )
-        return mfn_to_virt(mfn_x(mfn));
+        return mfn_to_virt(mfn);
 
     dcache = &v->domain->arch.pv.mapcache;
     vcache = &v->arch.pv.mapcache;
     if ( !dcache->inuse )
-        return mfn_to_virt(mfn_x(mfn));
+        return mfn_to_virt(mfn);
 
     perfc_incr(map_domain_page_count);
 
@@ -311,7 +311,7 @@ void *map_domain_page_global(mfn_t mfn)
 
 #ifdef NDEBUG
     if ( mfn_x(mfn) <= PFN_DOWN(__pa(HYPERVISOR_VIRT_END - 1)) )
-        return mfn_to_virt(mfn_x(mfn));
+        return mfn_to_virt(mfn);
 #endif
 
     return vmap(&mfn, 1);
@@ -336,7 +336,7 @@ mfn_t domain_page_map_to_mfn(const void *ptr)
     const l1_pgentry_t *pl1e;
 
     if ( va >= DIRECTMAP_VIRT_START )
-        return _mfn(virt_to_mfn(ptr));
+        return virt_to_mfn(ptr);
 
     if ( va >= VMAP_VIRT_START && va < VMAP_VIRT_END )
     {
diff --git a/xen/arch/x86/guest/xen.c b/xen/arch/x86/guest/xen.c
index 8cee880..b2c7306 100644
--- a/xen/arch/x86/guest/xen.c
+++ b/xen/arch/x86/guest/xen.c
@@ -131,7 +131,7 @@ static int map_vcpuinfo(void)
         return 0;
     }
 
-    info.mfn = virt_to_mfn(&vcpu_info[vcpu]);
+    info.mfn = __virt_to_mfn(&vcpu_info[vcpu]);
     info.offset = (unsigned long)&vcpu_info[vcpu] & ~PAGE_MASK;
     rc = xen_hypercall_vcpu_op(VCPUOP_register_vcpu_info, vcpu, &info);
     if ( rc )
diff --git a/xen/arch/x86/hvm/dom0_build.c b/xen/arch/x86/hvm/dom0_build.c
index 3e29cd3..88bb4ca 100644
--- a/xen/arch/x86/hvm/dom0_build.c
+++ b/xen/arch/x86/hvm/dom0_build.c
@@ -403,7 +403,7 @@ static int __init pvh_setup_p2m(struct domain *d)
                                  d->arch.e820[i].addr + d->arch.e820[i].size);
             enum hvm_translation_result res =
                  hvm_copy_to_guest_phys(mfn_to_maddr(_mfn(addr)),
-                                        mfn_to_virt(addr),
+                                        mfn_to_virt(_mfn(addr)),
                                         d->arch.e820[i].addr - end,
                                         v);
 
@@ -489,7 +489,7 @@ static int __init pvh_load_kernel(struct domain *d, const module_t *image,
 
     if ( initrd != NULL )
     {
-        rc = hvm_copy_to_guest_phys(last_addr, mfn_to_virt(initrd->mod_start),
+        rc = hvm_copy_to_guest_phys(last_addr, __mfn_to_virt(initrd->mod_start),
                                     initrd->mod_end, v);
         if ( rc )
         {
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index c3c7628..901c56f 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -132,10 +132,6 @@
 
 #include "pv/mm.h"
 
-/* Override macros from asm/page.h to make them work with mfn_t */
-#undef virt_to_mfn
-#define virt_to_mfn(v) _mfn(__virt_to_mfn(v))
-
 /* Mapping of the fixmap space needed early. */
 l1_pgentry_t __section(".bss.page_aligned") __aligned(PAGE_SIZE)
     l1_fixmap[L1_PAGETABLE_ENTRIES];
@@ -330,8 +326,8 @@ void __init arch_init_memory(void)
         iostart_pfn = max_t(unsigned long, pfn, 1UL << (20 - PAGE_SHIFT));
         ioend_pfn = min(rstart_pfn, 16UL << (20 - PAGE_SHIFT));
         if ( iostart_pfn < ioend_pfn )
-            destroy_xen_mappings((unsigned long)mfn_to_virt(iostart_pfn),
-                                 (unsigned long)mfn_to_virt(ioend_pfn));
+            destroy_xen_mappings((unsigned long)mfn_to_virt(_mfn(iostart_pfn)),
+                                 (unsigned long)mfn_to_virt(_mfn(ioend_pfn)));
 
         /* Mark as I/O up to next RAM region. */
         for ( ; pfn < rstart_pfn; pfn++ )
@@ -833,8 +829,9 @@ static int update_xen_mappings(unsigned long mfn, unsigned int cacheattr)
     if ( unlikely(alias) && cacheattr )
         err = map_pages_to_xen(xen_va, _mfn(mfn), 1, 0);
     if ( !err )
-        err = map_pages_to_xen((unsigned long)mfn_to_virt(mfn), _mfn(mfn), 1,
-                     PAGE_HYPERVISOR | cacheattr_to_pte_flags(cacheattr));
+        err = map_pages_to_xen(
+            (unsigned long)mfn_to_virt(_mfn(mfn)), _mfn(mfn), 1,
+            PAGE_HYPERVISOR | cacheattr_to_pte_flags(cacheattr));
     if ( unlikely(alias) && !cacheattr && !err )
         err = map_pages_to_xen(xen_va, _mfn(mfn), 1, PAGE_HYPERVISOR);
     return err;
@@ -4769,7 +4766,7 @@ void *alloc_xen_pagetable(void)
         return ptr;
     }
 
-    return mfn_to_virt(mfn_x(alloc_boot_pages(1, 1)));
+    return mfn_to_virt(alloc_boot_pages(1, 1));
 }
 
 void free_xen_pagetable(void *v)
diff --git a/xen/arch/x86/numa.c b/xen/arch/x86/numa.c
index b3c9c12..d18164b 100644
--- a/xen/arch/x86/numa.c
+++ b/xen/arch/x86/numa.c
@@ -101,7 +101,7 @@ static int __init allocate_cachealigned_memnodemap(void)
     unsigned long size = PFN_UP(memnodemapsize * sizeof(*memnodemap));
     unsigned long mfn = mfn_x(alloc_boot_pages(size, 1));
 
-    memnodemap = mfn_to_virt(mfn);
+    memnodemap = mfn_to_virt(_mfn(mfn));
     mfn <<= PAGE_SHIFT;
     size <<= PAGE_SHIFT;
     printk(KERN_DEBUG "NUMA: Allocated memnodemap from %lx - %lx\n",
diff --git a/xen/arch/x86/pv/descriptor-tables.c b/xen/arch/x86/pv/descriptor-tables.c
index 8b2d55f..1950c39 100644
--- a/xen/arch/x86/pv/descriptor-tables.c
+++ b/xen/arch/x86/pv/descriptor-tables.c
@@ -76,7 +76,7 @@ bool pv_destroy_ldt(struct vcpu *v)
 void pv_destroy_gdt(struct vcpu *v)
 {
     l1_pgentry_t *pl1e = pv_gdt_ptes(v);
-    mfn_t zero_mfn = _mfn(virt_to_mfn(zero_page));
+    mfn_t zero_mfn = virt_to_mfn(zero_page);
     l1_pgentry_t zero_l1e = l1e_from_mfn(zero_mfn, __PAGE_HYPERVISOR_RO);
     unsigned int i;
 
diff --git a/xen/arch/x86/pv/dom0_build.c b/xen/arch/x86/pv/dom0_build.c
index dc3c1e1..145488d 100644
--- a/xen/arch/x86/pv/dom0_build.c
+++ b/xen/arch/x86/pv/dom0_build.c
@@ -528,7 +528,7 @@ int __init dom0_construct_pv(struct domain *d,
                     free_domheap_pages(page, order);
                     page += 1UL << order;
                 }
-            memcpy(page_to_virt(page), mfn_to_virt(initrd->mod_start),
+            memcpy(page_to_virt(page), __mfn_to_virt(initrd->mod_start),
                    initrd_len);
             mpt_alloc = (paddr_t)initrd->mod_start << PAGE_SHIFT;
             init_domheap_pages(mpt_alloc,
@@ -617,8 +617,7 @@ int __init dom0_construct_pv(struct domain *d,
         l3start = __va(mpt_alloc); mpt_alloc += PAGE_SIZE;
     }
     clear_page(l4tab);
-    init_xen_l4_slots(l4tab, _mfn(virt_to_mfn(l4start)),
-                      d, INVALID_MFN, true);
+    init_xen_l4_slots(l4tab, virt_to_mfn(l4start), d, INVALID_MFN, true);
     v->arch.guest_table = pagetable_from_paddr(__pa(l4start));
     if ( is_pv_32bit_domain(d) )
         v->arch.guest_table_user = v->arch.guest_table;
diff --git a/xen/arch/x86/pv/shim.c b/xen/arch/x86/pv/shim.c
index cdc72f7..b89fa46 100644
--- a/xen/arch/x86/pv/shim.c
+++ b/xen/arch/x86/pv/shim.c
@@ -37,9 +37,6 @@
 
 #include <compat/grant_table.h>
 
-#undef virt_to_mfn
-#define virt_to_mfn(va) _mfn(__virt_to_mfn(va))
-
 #ifndef CONFIG_PV_SHIM_EXCLUSIVE
 bool pv_shim;
 boolean_param("pv-shim", pv_shim);
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index 9cbff22..f3345d0 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -343,7 +343,7 @@ void *__init bootstrap_map(const module_t *mod)
     void *ret;
 
     if ( system_state != SYS_STATE_early_boot )
-        return mod ? mfn_to_virt(mod->mod_start) : NULL;
+        return mod ? __mfn_to_virt(mod->mod_start) : NULL;
 
     if ( !mod )
     {
@@ -970,7 +970,7 @@ void __init noreturn __start_xen(unsigned long mbi_p)
          * This needs to remain in sync with xen_in_range() and the
          * respective reserve_e820_ram() invocation below.
          */
-        mod[mbi->mods_count].mod_start = virt_to_mfn(_stext);
+        mod[mbi->mods_count].mod_start = __virt_to_mfn(_stext);
         mod[mbi->mods_count].mod_end = __2M_rwdata_end - _stext;
     }
 
@@ -1363,7 +1363,7 @@ void __init noreturn __start_xen(unsigned long mbi_p)
     {
         set_pdx_range(mod[i].mod_start,
                       mod[i].mod_start + PFN_UP(mod[i].mod_end));
-        map_pages_to_xen((unsigned long)mfn_to_virt(mod[i].mod_start),
+        map_pages_to_xen((unsigned long)__mfn_to_virt(mod[i].mod_start),
                          _mfn(mod[i].mod_start),
                          PFN_UP(mod[i].mod_end), PAGE_HYPERVISOR);
     }
@@ -1453,9 +1453,9 @@ void __init noreturn __start_xen(unsigned long mbi_p)
 
     numa_initmem_init(0, raw_max_page);
 
-    if ( max_page - 1 > virt_to_mfn(HYPERVISOR_VIRT_END - 1) )
+    if ( max_page - 1 > __virt_to_mfn(HYPERVISOR_VIRT_END - 1) )
     {
-        unsigned long limit = virt_to_mfn(HYPERVISOR_VIRT_END - 1);
+        unsigned long limit = __virt_to_mfn(HYPERVISOR_VIRT_END - 1);
         uint64_t mask = PAGE_SIZE - 1;
 
         if ( !highmem_start )
diff --git a/xen/arch/x86/srat.c b/xen/arch/x86/srat.c
index 2d70b45..8ca1b65 100644
--- a/xen/arch/x86/srat.c
+++ b/xen/arch/x86/srat.c
@@ -196,7 +196,7 @@ void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
 		return;
 	}
 	mfn = alloc_boot_pages(PFN_UP(slit->header.length), 1);
-	acpi_slit = mfn_to_virt(mfn_x(mfn));
+	acpi_slit = mfn_to_virt(mfn);
 	memcpy(acpi_slit, slit, slit->header.length);
 }
 
diff --git a/xen/arch/x86/tboot.c b/xen/arch/x86/tboot.c
index f3fdee4..221be1d 100644
--- a/xen/arch/x86/tboot.c
+++ b/xen/arch/x86/tboot.c
@@ -259,7 +259,7 @@ static int mfn_in_guarded_stack(unsigned long mfn)
             continue;
         p = (void *)((unsigned long)stack_base[i] + STACK_SIZE -
                      PRIMARY_STACK_SIZE - PAGE_SIZE);
-        if ( mfn == virt_to_mfn(p) )
+        if ( mfn == mfn_x(virt_to_mfn(p)) )
             return -1;
     }
 
@@ -295,7 +295,7 @@ static void tboot_gen_xenheap_integrity(const uint8_t key[TB_KEY_SIZE],
             if ( mfn_in_guarded_stack(mfn) )
                 continue; /* skip guard stack, see memguard_guard_stack() in mm.c */
 
-            pg = mfn_to_virt(mfn);
+            pg = mfn_to_virt(_mfn(mfn));
             vmac_update((uint8_t *)pg, PAGE_SIZE, &ctx);
         }
     }
diff --git a/xen/arch/x86/x86_64/mm.c b/xen/arch/x86/x86_64/mm.c
index 11977f2..863c49a 100644
--- a/xen/arch/x86/x86_64/mm.c
+++ b/xen/arch/x86/x86_64/mm.c
@@ -1366,10 +1366,10 @@ int memory_add(unsigned long spfn, unsigned long epfn, unsigned int pxm)
         return -EINVAL;
     }
 
-    i = virt_to_mfn(HYPERVISOR_VIRT_END - 1) + 1;
+    i = mfn_x(virt_to_mfn(HYPERVISOR_VIRT_END - 1)) + 1;
     if ( spfn < i )
     {
-        ret = map_pages_to_xen((unsigned long)mfn_to_virt(spfn), _mfn(spfn),
+        ret = map_pages_to_xen((unsigned long)mfn_to_virt(_mfn(spfn)), _mfn(spfn),
                                min(epfn, i) - spfn, PAGE_HYPERVISOR);
         if ( ret )
             goto destroy_directmap;
@@ -1378,7 +1378,7 @@ int memory_add(unsigned long spfn, unsigned long epfn, unsigned int pxm)
     {
         if ( i < spfn )
             i = spfn;
-        ret = map_pages_to_xen((unsigned long)mfn_to_virt(i), _mfn(i),
+        ret = map_pages_to_xen((unsigned long)mfn_to_virt(_mfn(i)), _mfn(i),
                                epfn - i, __PAGE_HYPERVISOR_RW);
         if ( ret )
             goto destroy_directmap;
@@ -1469,8 +1469,8 @@ int memory_add(unsigned long spfn, unsigned long epfn, unsigned int pxm)
     NODE_DATA(node)->node_start_pfn = old_node_start;
     NODE_DATA(node)->node_spanned_pages = old_node_span;
  destroy_directmap:
-    destroy_xen_mappings((unsigned long)mfn_to_virt(spfn),
-                         (unsigned long)mfn_to_virt(epfn));
+    destroy_xen_mappings((unsigned long)mfn_to_virt(_mfn(spfn)),
+                         (unsigned long)mfn_to_virt(_mfn(epfn)));
 
     return ret;
 }
diff --git a/xen/common/domctl.c b/xen/common/domctl.c
index d08b627..5500dfb 100644
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -205,7 +205,7 @@ void getdomaininfo(struct domain *d, struct xen_domctl_getdomaininfo *info)
     info->outstanding_pages = d->outstanding_pages;
     info->shr_pages         = atomic_read(&d->shr_pages);
     info->paged_pages       = atomic_read(&d->paged_pages);
-    info->shared_info_frame = mfn_to_gmfn(d, virt_to_mfn(d->shared_info));
+    info->shared_info_frame = mfn_to_gmfn(d, mfn_x(virt_to_mfn(d->shared_info)));
     BUG_ON(SHARED_M2P(info->shared_info_frame));
 
     info->cpupool = d->cpupool ? d->cpupool->cpupool_id : CPUPOOLID_NONE;
diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c
index 2ed5403..07fe775 100644
--- a/xen/common/efi/boot.c
+++ b/xen/common/efi/boot.c
@@ -1431,7 +1431,7 @@ static __init void copy_mapping(unsigned long mfn, unsigned long end,
     {
         l4_pgentry_t l4e = efi_l4_pgtable[l4_table_offset(mfn << PAGE_SHIFT)];
         l3_pgentry_t *l3src, *l3dst;
-        unsigned long va = (unsigned long)mfn_to_virt(mfn);
+        unsigned long va = (unsigned long)mfn_to_virt(_mfn(mfn));
 
         next = mfn + (1UL << (L3_PAGETABLE_SHIFT - PAGE_SHIFT));
         if ( !is_valid(mfn, min(next, end)) )
@@ -1551,9 +1551,10 @@ void __init efi_init_memory(void)
              !(smfn & pfn_hole_mask) &&
              !((smfn ^ (emfn - 1)) & ~pfn_pdx_bottom_mask) )
         {
-            if ( (unsigned long)mfn_to_virt(emfn - 1) >= HYPERVISOR_VIRT_END )
+            if ( (unsigned long)mfn_to_virt(_mfn(emfn - 1)) >=
+                 HYPERVISOR_VIRT_END )
                 prot &= ~_PAGE_GLOBAL;
-            if ( map_pages_to_xen((unsigned long)mfn_to_virt(smfn),
+            if ( map_pages_to_xen((unsigned long)mfn_to_virt(_mfn(smfn)),
                                   _mfn(smfn), emfn - smfn, prot) == 0 )
                 desc->VirtualStart =
                     (unsigned long)maddr_to_virt(desc->PhysicalStart);
diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
index 54f909f..6fc26cf 100644
--- a/xen/common/grant_table.c
+++ b/xen/common/grant_table.c
@@ -3835,7 +3835,7 @@ static int gnttab_get_status_frame_mfn(struct domain *d,
             return -EINVAL;
     }
 
-    *mfn = _mfn(virt_to_mfn(gt->status[idx]));
+    *mfn = virt_to_mfn(gt->status[idx]);
     return 0;
 }
 
@@ -3864,7 +3864,7 @@ static int gnttab_get_shared_frame_mfn(struct domain *d,
             return -EINVAL;
     }
 
-    *mfn = _mfn(virt_to_mfn(gt->shared_raw[idx]));
+    *mfn = virt_to_mfn(gt->shared_raw[idx]);
     return 0;
 }
 
diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c
index 08ee8cf..92e1a65 100644
--- a/xen/common/page_alloc.c
+++ b/xen/common/page_alloc.c
@@ -253,7 +253,7 @@ static void __init bootmem_region_add(unsigned long s, unsigned long e)
     unsigned int i;
 
     if ( (bootmem_region_list == NULL) && (s < e) )
-        bootmem_region_list = mfn_to_virt(s++);
+        bootmem_region_list = mfn_to_virt(_mfn(s++));
 
     if ( s >= e )
         return;
@@ -590,8 +590,8 @@ static unsigned long init_node_heap(int node, unsigned long mfn,
               (!xenheap_bits ||
                !((mfn + nr - 1) >> (xenheap_bits - PAGE_SHIFT))) )
     {
-        _heap[node] = mfn_to_virt(mfn + nr - needed);
-        avail[node] = mfn_to_virt(mfn + nr - 1) +
+        _heap[node] = mfn_to_virt(_mfn(mfn + nr - needed));
+        avail[node] = mfn_to_virt(_mfn(mfn + nr - 1)) +
                       PAGE_SIZE - sizeof(**avail) * NR_ZONES;
     }
     else if ( nr >= needed &&
@@ -599,8 +599,8 @@ static unsigned long init_node_heap(int node, unsigned long mfn,
               (!xenheap_bits ||
                !((mfn + needed - 1) >> (xenheap_bits - PAGE_SHIFT))) )
     {
-        _heap[node] = mfn_to_virt(mfn);
-        avail[node] = mfn_to_virt(mfn + needed - 1) +
+        _heap[node] = mfn_to_virt(_mfn(mfn));
+        avail[node] = mfn_to_virt(_mfn(mfn + needed - 1)) +
                       PAGE_SIZE - sizeof(**avail) * NR_ZONES;
         *use_tail = 0;
     }
diff --git a/xen/common/tmem.c b/xen/common/tmem.c
index c077f87..e749cba 100644
--- a/xen/common/tmem.c
+++ b/xen/common/tmem.c
@@ -243,7 +243,7 @@ static void tmem_persistent_pool_page_put(void *page_va)
     struct page_info *pi;
 
     ASSERT(IS_PAGE_ALIGNED(page_va));
-    pi = mfn_to_page(_mfn(virt_to_mfn(page_va)));
+    pi = virt_to_page(page_va);
     ASSERT(IS_VALID_PAGE(pi));
     __tmem_free_page_thispool(pi);
 }
diff --git a/xen/common/trace.c b/xen/common/trace.c
index cc294fc..3e43976 100644
--- a/xen/common/trace.c
+++ b/xen/common/trace.c
@@ -217,7 +217,7 @@ static int alloc_trace_bufs(unsigned int pages)
                 t_info_mfn_list[offset + i] = 0;
                 goto out_dealloc;
             }
-            t_info_mfn_list[offset + i] = virt_to_mfn(p);
+            t_info_mfn_list[offset + i] = __virt_to_mfn(p);
         }
     }
 
@@ -233,7 +233,7 @@ static int alloc_trace_bufs(unsigned int pages)
         offset = t_info->mfn_offset[cpu];
 
         /* Initialize the buffer metadata */
-        per_cpu(t_bufs, cpu) = buf = mfn_to_virt(t_info_mfn_list[offset]);
+        per_cpu(t_bufs, cpu) = buf = __mfn_to_virt(t_info_mfn_list[offset]);
         buf->cons = buf->prod = 0;
 
         printk(XENLOG_INFO "xentrace: p%d mfn %x offset %u\n",
@@ -268,10 +268,12 @@ static int alloc_trace_bufs(unsigned int pages)
             continue;
         for ( i = 0; i < pages; i++ )
         {
-            uint32_t mfn = t_info_mfn_list[offset + i];
-            if ( !mfn )
+            mfn_t mfn = _mfn(t_info_mfn_list[offset + i]);
+
+            if ( !mfn_x(mfn) )
                 break;
-            ASSERT(!(mfn_to_page(_mfn(mfn))->count_info & PGC_allocated));
+
+            ASSERT(!(mfn_to_page(mfn)->count_info & PGC_allocated));
             free_xenheap_pages(mfn_to_virt(mfn), 0);
         }
     }
@@ -377,7 +379,7 @@ int tb_control(struct xen_sysctl_tbuf_op *tbc)
     {
     case XEN_SYSCTL_TBUFOP_get_info:
         tbc->evt_mask   = tb_event_mask;
-        tbc->buffer_mfn = t_info ? virt_to_mfn(t_info) : 0;
+        tbc->buffer_mfn = t_info ? __virt_to_mfn(t_info) : 0;
         tbc->size = t_info_pages * PAGE_SIZE;
         break;
     case XEN_SYSCTL_TBUFOP_set_cpu_mask:
@@ -511,7 +513,7 @@ static unsigned char *next_record(const struct t_buf *buf, uint32_t *next,
     uint16_t per_cpu_mfn_offset;
     uint32_t per_cpu_mfn_nr;
     uint32_t *mfn_list;
-    uint32_t mfn;
+    mfn_t mfn;
     unsigned char *this_page;
 
     barrier(); /* must read buf->prod and buf->cons only once */
@@ -532,7 +534,7 @@ static unsigned char *next_record(const struct t_buf *buf, uint32_t *next,
     per_cpu_mfn_nr = x >> PAGE_SHIFT;
     per_cpu_mfn_offset = t_info->mfn_offset[smp_processor_id()];
     mfn_list = (uint32_t *)t_info;
-    mfn = mfn_list[per_cpu_mfn_offset + per_cpu_mfn_nr];
+    mfn = _mfn(mfn_list[per_cpu_mfn_offset + per_cpu_mfn_nr]);
     this_page = mfn_to_virt(mfn);
     if (per_cpu_mfn_nr + 1 >= opt_tbuf_size)
     {
@@ -541,7 +543,7 @@ static unsigned char *next_record(const struct t_buf *buf, uint32_t *next,
     }
     else
     {
-        mfn = mfn_list[per_cpu_mfn_offset + per_cpu_mfn_nr + 1];
+        mfn = _mfn(mfn_list[per_cpu_mfn_offset + per_cpu_mfn_nr + 1]);
         *next_page = mfn_to_virt(mfn);
     }
     return this_page;
diff --git a/xen/common/xenoprof.c b/xen/common/xenoprof.c
index 8a72e38..02b015f 100644
--- a/xen/common/xenoprof.c
+++ b/xen/common/xenoprof.c
@@ -19,10 +19,6 @@
 #include <xsm/xsm.h>
 #include <xen/hypercall.h>
 
-/* Override macros from asm/page.h to make them work with mfn_t */
-#undef virt_to_mfn
-#define virt_to_mfn(va) _mfn(__virt_to_mfn(va))
-
 /* Limit amount of pages used for shared buffer (per domain) */
 #define MAX_OPROF_SHARED_PAGES 32
 
diff --git a/xen/drivers/acpi/osl.c b/xen/drivers/acpi/osl.c
index 4c8bb78..ca38565 100644
--- a/xen/drivers/acpi/osl.c
+++ b/xen/drivers/acpi/osl.c
@@ -219,7 +219,7 @@ void *__init acpi_os_alloc_memory(size_t sz)
 	void *ptr;
 
 	if (system_state == SYS_STATE_early_boot)
-		return mfn_to_virt(mfn_x(alloc_boot_pages(PFN_UP(sz), 1)));
+		return mfn_to_virt(alloc_boot_pages(PFN_UP(sz), 1));
 
 	ptr = xmalloc_bytes(sz);
 	ASSERT(!ptr || is_xmalloc_memory(ptr));
diff --git a/xen/include/asm-arm/mm.h b/xen/include/asm-arm/mm.h
index b2f6104..388d353 100644
--- a/xen/include/asm-arm/mm.h
+++ b/xen/include/asm-arm/mm.h
@@ -288,8 +288,8 @@ static inline uint64_t gvirt_to_maddr(vaddr_t va, paddr_t *pa,
  * These are overriden in various source files while underscored version
  * remain intact.
  */
-#define virt_to_mfn(va)     __virt_to_mfn(va)
-#define mfn_to_virt(mfn)    __mfn_to_virt(mfn)
+#define virt_to_mfn(va)     _mfn(__virt_to_mfn(va))
+#define mfn_to_virt(mfn)    __mfn_to_virt(mfn_x(mfn))
 
 /* Convert between Xen-heap virtual addresses and page-info structures. */
 static inline struct page_info *virt_to_page(const void *v)
@@ -307,7 +307,7 @@ static inline struct page_info *virt_to_page(const void *v)
 
 static inline void *page_to_virt(const struct page_info *pg)
 {
-    return mfn_to_virt(mfn_x(page_to_mfn(pg)));
+    return mfn_to_virt(page_to_mfn(pg));
 }
 
 struct page_info *get_page_from_gva(struct vcpu *v, vaddr_t va,
diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h
index 1ea173c..bd714d1 100644
--- a/xen/include/asm-x86/mm.h
+++ b/xen/include/asm-x86/mm.h
@@ -633,7 +633,7 @@ static inline bool arch_mfn_in_directmap(unsigned long mfn)
 {
     unsigned long eva = min(DIRECTMAP_VIRT_END, HYPERVISOR_VIRT_END);
 
-    return mfn <= (virt_to_mfn(eva - 1) + 1);
+    return mfn <= (__virt_to_mfn(eva - 1) + 1);
 }
 
 int arch_acquire_resource(struct domain *d, unsigned int type,
diff --git a/xen/include/asm-x86/page.h b/xen/include/asm-x86/page.h
index c1e9293..74ac64a 100644
--- a/xen/include/asm-x86/page.h
+++ b/xen/include/asm-x86/page.h
@@ -260,8 +260,8 @@ void copy_page_sse2(void *, const void *);
  * overridden in various source files while underscored versions remain intact.
  */
 #define mfn_valid(mfn)      __mfn_valid(mfn_x(mfn))
-#define virt_to_mfn(va)     __virt_to_mfn(va)
-#define mfn_to_virt(mfn)    __mfn_to_virt(mfn)
+#define virt_to_mfn(va)     _mfn(__virt_to_mfn(va))
+#define mfn_to_virt(mfn)    __mfn_to_virt(mfn_x(mfn))
 #define virt_to_maddr(va)   __virt_to_maddr((unsigned long)(va))
 #define maddr_to_virt(ma)   __maddr_to_virt((unsigned long)(ma))
 #define maddr_to_page(ma)   __maddr_to_page(ma)
diff --git a/xen/include/xen/domain_page.h b/xen/include/xen/domain_page.h
index 32669a3..518d874 100644
--- a/xen/include/xen/domain_page.h
+++ b/xen/include/xen/domain_page.h
@@ -53,14 +53,14 @@ static inline void *__map_domain_page_global(const struct page_info *pg)
 
 #else /* !CONFIG_DOMAIN_PAGE */
 
-#define map_domain_page(mfn)                __mfn_to_virt(mfn_x(mfn))
+#define map_domain_page(mfn)                mfn_to_virt(mfn)
 #define __map_domain_page(pg)               page_to_virt(pg)
 #define unmap_domain_page(va)               ((void)(va))
-#define domain_page_map_to_mfn(va)          _mfn(virt_to_mfn((unsigned long)(va)))
+#define domain_page_map_to_mfn(va)          virt_to_mfn(va)
 
 static inline void *map_domain_page_global(mfn_t mfn)
 {
-    return mfn_to_virt(mfn_x(mfn));
+    return mfn_to_virt(mfn);
 }
 
 static inline void *__map_domain_page_global(const struct page_info *pg)
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 12/14] xen/gnttab: Drop gnttab_create_{shared, status}_page()
  2018-11-21 13:21 [PATCH 00/14] XSA-277 followup Andrew Cooper
                   ` (10 preceding siblings ...)
  2018-11-21 13:21 ` [PATCH 11/14] xen/mm: Switch mfn_to_virt()/virt_to_mfn() to using mfn_t Andrew Cooper
@ 2018-11-21 13:21 ` Andrew Cooper
  2018-11-22 14:35   ` Julien Grall
  2018-11-22 15:47   ` Jan Beulich
  2018-11-21 13:21 ` [PATCH 13/14] xen/gnttab: Simplify gnttab_map_frame() Andrew Cooper
                   ` (3 subsequent siblings)
  15 siblings, 2 replies; 59+ messages in thread
From: Andrew Cooper @ 2018-11-21 13:21 UTC (permalink / raw)
  To: Xen-devel
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Julien Grall,
	Jan Beulich, Roger Pau Monné

share_xen_page_with_guest() is a common API.  Use it directly rather than
wrapping it with unnecessary boilerplate.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Stefano Stabellini <sstabellini@kernel.org>
CC: Julien Grall <julien.grall@arm.com>
---
 xen/common/grant_table.c          |  7 ++++---
 xen/include/asm-arm/grant_table.h | 12 ------------
 xen/include/asm-x86/grant_table.h | 13 -------------
 3 files changed, 4 insertions(+), 28 deletions(-)

diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
index 6fc26cf..d5a1a00 100644
--- a/xen/common/grant_table.c
+++ b/xen/common/grant_table.c
@@ -1635,7 +1635,7 @@ gnttab_populate_status_frames(struct domain *d, struct grant_table *gt,
     }
     /* Share the new status frames with the recipient domain */
     for ( i = nr_status_frames(gt); i < req_status_frames; i++ )
-        gnttab_create_status_page(d, gt, i);
+        share_xen_page_with_guest(virt_to_page(gt->status[i]), d, SHARE_rw);
 
     gt->nr_status_frames = req_status_frames;
 
@@ -1702,7 +1702,8 @@ gnttab_unpopulate_status_frames(struct domain *d, struct grant_table *gt)
                 if ( get_page(pg, d) )
                     set_bit(_PGC_allocated, &pg->count_info);
                 while ( i-- )
-                    gnttab_create_status_page(d, gt, i);
+                    share_xen_page_with_guest(virt_to_page(gt->status[i]),
+                                              d, SHARE_rw);
             }
             return -EBUSY;
         }
@@ -1773,7 +1774,7 @@ gnttab_grow_table(struct domain *d, unsigned int req_nr_frames)
 
     /* Share the new shared frames with the recipient domain */
     for ( i = nr_grant_frames(gt); i < req_nr_frames; i++ )
-        gnttab_create_shared_page(d, gt, i);
+        share_xen_page_with_guest(virt_to_page(gt->shared_raw[i]), d, SHARE_rw);
     gt->nr_grant_frames = req_nr_frames;
 
     return 0;
diff --git a/xen/include/asm-arm/grant_table.h b/xen/include/asm-arm/grant_table.h
index 37415b7..816e3c6 100644
--- a/xen/include/asm-arm/grant_table.h
+++ b/xen/include/asm-arm/grant_table.h
@@ -71,18 +71,6 @@ void gnttab_mark_dirty(struct domain *d, mfn_t mfn);
              : gnttab_shared_gmfn(NULL, gt, idx));                       \
 })
 
-#define gnttab_create_shared_page(d, t, i)                               \
-    do {                                                                 \
-        share_xen_page_with_guest(                                       \
-            virt_to_page((char *)(t)->shared_raw[i]), d, SHARE_rw);      \
-    } while ( 0 )
-
-#define gnttab_create_status_page(d, t, i)                               \
-    do {                                                                 \
-        share_xen_page_with_guest(                                       \
-            virt_to_page((char *)(t)->status[i]), d, SHARE_rw);          \
-    } while ( 0 )
-
 #define gnttab_shared_gmfn(d, t, i)                                      \
     gfn_x(((i) >= nr_grant_frames(t)) ? INVALID_GFN : (t)->arch.shared_gfn[i])
 
diff --git a/xen/include/asm-x86/grant_table.h b/xen/include/asm-x86/grant_table.h
index 1e6a988..4b8c4f9 100644
--- a/xen/include/asm-x86/grant_table.h
+++ b/xen/include/asm-x86/grant_table.h
@@ -49,19 +49,6 @@ static inline int replace_grant_host_mapping(uint64_t addr, mfn_t frame,
     VALID_M2P(gpfn_) ? _gfn(gpfn_) : INVALID_GFN;                        \
 })
 
-#define gnttab_create_shared_page(d, t, i)                               \
-    do {                                                                 \
-        share_xen_page_with_guest(                                       \
-            virt_to_page((char *)(t)->shared_raw[i]), d, SHARE_rw);      \
-    } while ( 0 )
-
-#define gnttab_create_status_page(d, t, i)                               \
-    do {                                                                 \
-        share_xen_page_with_guest(                                       \
-            virt_to_page((char *)(t)->status[i]), d, SHARE_rw);          \
-    } while ( 0 )
-
-
 #define gnttab_shared_mfn(t, i)                         \
     ((virt_to_maddr((t)->shared_raw[i]) >> PAGE_SHIFT))
 
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 13/14] xen/gnttab: Simplify gnttab_map_frame()
  2018-11-21 13:21 [PATCH 00/14] XSA-277 followup Andrew Cooper
                   ` (11 preceding siblings ...)
  2018-11-21 13:21 ` [PATCH 12/14] xen/gnttab: Drop gnttab_create_{shared, status}_page() Andrew Cooper
@ 2018-11-21 13:21 ` Andrew Cooper
  2018-11-22 14:36   ` Julien Grall
  2018-11-22 15:48   ` Jan Beulich
  2018-11-21 13:21 ` [PATCH 14/14] xen/gnttab: Minor improvements to arch header files Andrew Cooper
                   ` (2 subsequent siblings)
  15 siblings, 2 replies; 59+ messages in thread
From: Andrew Cooper @ 2018-11-21 13:21 UTC (permalink / raw)
  To: Xen-devel
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Julien Grall,
	Jan Beulich, Roger Pau Monné

 * Reflow some lines to remove unnecessary line breaks.
 * Factor out the gnttab_get_frame_gfn() calculation.  Neither x86 nor ARM
   builds seem to be able to fold the two calls, and the resulting code is far
   easier to follow.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Stefano Stabellini <sstabellini@kernel.org>
CC: Julien Grall <julien.grall@arm.com>
---
 xen/common/grant_table.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
index d5a1a00..f00eba9 100644
--- a/xen/common/grant_table.c
+++ b/xen/common/grant_table.c
@@ -3869,8 +3869,7 @@ static int gnttab_get_shared_frame_mfn(struct domain *d,
     return 0;
 }
 
-int gnttab_map_frame(struct domain *d, unsigned long idx, gfn_t gfn,
-                     mfn_t *mfn)
+int gnttab_map_frame(struct domain *d, unsigned long idx, gfn_t gfn, mfn_t *mfn)
 {
     int rc = 0;
     struct grant_table *gt = d->grant_table;
@@ -3878,8 +3877,7 @@ int gnttab_map_frame(struct domain *d, unsigned long idx, gfn_t gfn,
 
     grant_write_lock(gt);
 
-    if ( gt->gt_version == 2 &&
-         (idx & XENMAPIDX_grant_table_status) )
+    if ( gt->gt_version == 2 && (idx & XENMAPIDX_grant_table_status) )
     {
         idx &= ~XENMAPIDX_grant_table_status;
         status = true;
@@ -3889,10 +3887,13 @@ int gnttab_map_frame(struct domain *d, unsigned long idx, gfn_t gfn,
     else
         rc = gnttab_get_shared_frame_mfn(d, idx, mfn);
 
-    if ( !rc && paging_mode_translate(d) &&
-         !gfn_eq(gnttab_get_frame_gfn(gt, status, idx), INVALID_GFN) )
-        rc = guest_physmap_remove_page(d, gnttab_get_frame_gfn(gt, status, idx),
-                                       *mfn, 0);
+    if ( !rc && paging_mode_translate(d) )
+    {
+        gfn_t gfn = gnttab_get_frame_gfn(gt, status, idx);
+
+        if ( !gfn_eq(gfn, INVALID_GFN) )
+            rc = guest_physmap_remove_page(d, gfn, *mfn, 0);
+    }
 
     if ( !rc )
         gnttab_set_frame_gfn(gt, status, idx, gfn);
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 14/14] xen/gnttab: Minor improvements to arch header files
  2018-11-21 13:21 [PATCH 00/14] XSA-277 followup Andrew Cooper
                   ` (12 preceding siblings ...)
  2018-11-21 13:21 ` [PATCH 13/14] xen/gnttab: Simplify gnttab_map_frame() Andrew Cooper
@ 2018-11-21 13:21 ` Andrew Cooper
  2018-11-22 15:51   ` Jan Beulich
  2018-11-22 17:56   ` Andrew Cooper
  2018-11-21 17:19 ` [PATCH 00/14] XSA-277 followup Tamas K Lengyel
  2019-01-30 18:36 ` Pings for 4.12 " Andrew Cooper
  15 siblings, 2 replies; 59+ messages in thread
From: Andrew Cooper @ 2018-11-21 13:21 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper, Wei Liu, Jan Beulich, Roger Pau Monné

 * Use XFREE() when appropriate
 * Drop stale comments and unnecessary brackets
 * Fold asm constraints

No functional change.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
---
 xen/include/asm-arm/grant_table.h |  6 ++----
 xen/include/asm-x86/grant_table.h | 10 +++-------
 2 files changed, 5 insertions(+), 11 deletions(-)

diff --git a/xen/include/asm-arm/grant_table.h b/xen/include/asm-arm/grant_table.h
index 816e3c6..051db13 100644
--- a/xen/include/asm-arm/grant_table.h
+++ b/xen/include/asm-arm/grant_table.h
@@ -54,10 +54,8 @@ void gnttab_mark_dirty(struct domain *d, mfn_t mfn);
 
 #define gnttab_destroy_arch(gt)                                          \
     do {                                                                 \
-        xfree((gt)->arch.shared_gfn);                                    \
-        (gt)->arch.shared_gfn = NULL;                                    \
-        xfree((gt)->arch.status_gfn);                                    \
-        (gt)->arch.status_gfn = NULL;                                    \
+        XFREE((gt)->arch.shared_gfn);                                    \
+        XFREE((gt)->arch.status_gfn);                                    \
     } while ( 0 )
 
 #define gnttab_set_frame_gfn(gt, st, idx, gfn)                           \
diff --git a/xen/include/asm-x86/grant_table.h b/xen/include/asm-x86/grant_table.h
index 4b8c4f9..8b604ed 100644
--- a/xen/include/asm-x86/grant_table.h
+++ b/xen/include/asm-x86/grant_table.h
@@ -17,10 +17,6 @@
 struct grant_table_arch {
 };
 
-/*
- * Caller must own caller's BIGLOCK, is responsible for flushing the TLB, and
- * must hold a reference to the page.
- */
 static inline int create_grant_host_mapping(uint64_t addr, mfn_t frame,
                                             unsigned int flags,
                                             unsigned int cache_flags)
@@ -62,7 +58,7 @@ static inline int replace_grant_host_mapping(uint64_t addr, mfn_t frame,
 #define gnttab_status_gmfn(d, t, i)                     \
     (mfn_to_gmfn(d, gnttab_status_mfn(t, i)))
 
-#define gnttab_mark_dirty(d, f) paging_mark_dirty((d), f)
+#define gnttab_mark_dirty(d, f) paging_mark_dirty(d, f)
 
 static inline void gnttab_clear_flag(unsigned int nr, uint16_t *st)
 {
@@ -70,10 +66,10 @@ static inline void gnttab_clear_flag(unsigned int nr, uint16_t *st)
      * Note that this cannot be clear_bit(), as the access must be
      * confined to the specified 2 bytes.
      */
-    asm volatile ("lock btrw %w1,%0" : "=m" (*st) : "Ir" (nr), "m" (*st));
+    asm volatile ("lock btrw %w1,%0" : "+m" (*st) : "Ir" (nr));
 }
 
-/* Foreign mappings of HHVM-guest pages do not modify the type count. */
+/* Foreign mappings of HVM-guest pages do not modify the type count. */
 #define gnttab_host_mapping_get_page_type(ro, ld, rd)   \
     (!(ro) && (((ld) == (rd)) || !paging_mode_external(rd)))
 
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* Re: [PATCH 04/14] x86/p2m: Fix locking in p2m_altp2m_lazy_copy()
  2018-11-21 13:21 ` [PATCH 04/14] x86/p2m: Fix locking in p2m_altp2m_lazy_copy() Andrew Cooper
@ 2018-11-21 13:59   ` Razvan Cojocaru
  2018-11-22 15:01   ` Jan Beulich
  1 sibling, 0 replies; 59+ messages in thread
From: Razvan Cojocaru @ 2018-11-21 13:59 UTC (permalink / raw)
  To: Andrew Cooper, Xen-devel
  Cc: George Dunlap, Tamas K Lengyel, Wei Liu, Jan Beulich,
	Roger Pau Monné

On 11/21/18 3:21 PM, Andrew Cooper wrote:
> The gfn references need to remain held until after the p2m_set_entry() has
> completed.  This is only a latent bug for now, because there is no per-gfn
> locking and we recursively hold the main p2m locks.
> 
> Rearrange the code to have a single exit path, and defer taking the ap2m lock
> until it is necessary to do so.  Leave some comments behind to help people
> attempting to follow the logic.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
> ---
> CC: Jan Beulich <JBeulich@suse.com>
> CC: Wei Liu <wei.liu2@citrix.com>
> CC: Roger Pau Monné <roger.pau@citrix.com>
> CC: Razvan Cojocaru <rcojocaru@bitdefender.com>
> CC: Tamas K Lengyel <tamas@tklengyel.com>
> CC: George Dunlap <george.dunlap@eu.citrix.com>
> ---
>  xen/arch/x86/mm/p2m.c | 27 ++++++++++++++++++++-------
>  1 file changed, 20 insertions(+), 7 deletions(-)
> 
> diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
> index b5a59d6..ae9cb20 100644
> --- a/xen/arch/x86/mm/p2m.c
> +++ b/xen/arch/x86/mm/p2m.c
> @@ -2184,24 +2184,29 @@ bool_t p2m_altp2m_lazy_copy(struct vcpu *v, paddr_t gpa,
>      unsigned long mask;
>      mfn_t mfn;
>      int rv;
> +    bool ret;

Thanks for the patches! This one looks good, except I think you'll want
to also change the return type of p2m_altp2m_lazy_copy() from bool_t to
bool.

With that:
Reviewed-by: Razvan Cojocaru <rcojocaru@bitdefender.com>


Thanks,
Razvan

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 05/14] x86/p2m: Don't overwrite p2m_altp2m_lazy_copy()'s callers p2m pointer
  2018-11-21 13:21 ` [PATCH 05/14] x86/p2m: Don't overwrite p2m_altp2m_lazy_copy()'s callers p2m pointer Andrew Cooper
@ 2018-11-21 14:07   ` Razvan Cojocaru
  2018-11-22 15:03   ` Jan Beulich
  1 sibling, 0 replies; 59+ messages in thread
From: Razvan Cojocaru @ 2018-11-21 14:07 UTC (permalink / raw)
  To: Andrew Cooper, Xen-devel
  Cc: George Dunlap, Tamas K Lengyel, Wei Liu, Jan Beulich,
	Roger Pau Monné

On 11/21/18 3:21 PM, Andrew Cooper wrote:
> The final parameter to p2m_altp2m_lazy_copy() appears to be unnecessary, and
> results in very hard-to-follow code.  Have the sole caller set its local p2m
> pointer appropriately, and drop the parameter.
> 
> With that done, a level of indirection of ap2m can be dropped inside
> p2m_altp2m_lazy_copy().  While changing the API, switch it from bool_t to
> bool, and drop printing of the altp2m's virtual address, because it is of no
> use even when debugging.
> 
> No (intended) overall change in behaviour.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Right, I see you've changed the return type of p2m_altp2m_lazy_copy()
from bool_t to bool here, so please disregard my previous comment.

Reviewed-by: Razvan Cojocaru <rcojocaru@bitdefender.com>


Thanks,
Razvan

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 06/14] x86/hvm: Make the altp2m locking easier to follow
  2018-11-21 13:21 ` [PATCH 06/14] x86/hvm: Make the altp2m locking easier to follow Andrew Cooper
@ 2018-11-21 14:43   ` Razvan Cojocaru
  2018-11-22 15:08   ` Jan Beulich
  1 sibling, 0 replies; 59+ messages in thread
From: Razvan Cojocaru @ 2018-11-21 14:43 UTC (permalink / raw)
  To: Andrew Cooper, Xen-devel
  Cc: George Dunlap, Tamas K Lengyel, Wei Liu, Jan Beulich,
	Roger Pau Monné

On 11/21/18 3:21 PM, Andrew Cooper wrote:
> Drop the ap2m_active boolean, and consistently use the unlocking form:
> 
>   if ( p2m != hostp2m )
>        __put_gfn(p2m, gfn);
>   __put_gfn(hostp2m, gfn);
> 
> which makes it clear that we always unlock the altp2m's gfn if it is in use,
> and always unlock the hostp2m's gfn.  This also drops the ternary expression
> in the logdirty case.
> 
> Extend the logdirty comment to identify where the locking violation is liable
> to occur.
> 
> No (intended) overall change in behaviour.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Reviewed-by: Razvan Cojocaru <rcojocaru@bitdefender.com>

FWIW, I've also applied this and the previous two patches I've reviewed
to the end of my altp2m series and gave them a spin with introspection
with no apparent problems.


Thanks,
Razvan

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 10/14] x86/mm: Switch {get, put}_gfn() infrastructure to using gfn_t
  2018-11-21 13:21 ` [PATCH 10/14] x86/mm: Switch {get, put}_gfn() " Andrew Cooper
@ 2018-11-21 14:48   ` Razvan Cojocaru
  2018-11-21 16:12   ` Paul Durrant
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 59+ messages in thread
From: Razvan Cojocaru @ 2018-11-21 14:48 UTC (permalink / raw)
  To: Andrew Cooper, Xen-devel
  Cc: Kevin Tian, Tamas K Lengyel, Wei Liu, Jun Nakajima,
	George Dunlap, Tim Deegan, Paul Durrant, Jan Beulich,
	Boris Ostrovsky, Brian Woods, Suravee Suthikulpanit,
	Roger Pau Monné

On 11/21/18 3:21 PM, Andrew Cooper wrote:
> Seemingly, a majority of users either override the helpers anyway, or have an
> gfn_t in their hands.
> 
> Update the API, and adjust all users to match.
> 
> Doing this highlighted a gaping altp2m security hole in
> vmx_vcpu_update_vmfunc_ve(), which will need addressing now we can discuss the
> problem and options publicly.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

For the mem_access bits:
Acked-by: Razvan Cojocaru <rcojocaru@bitdefender.com>


Thanks,
Razvan

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 10/14] x86/mm: Switch {get, put}_gfn() infrastructure to using gfn_t
  2018-11-21 13:21 ` [PATCH 10/14] x86/mm: Switch {get, put}_gfn() " Andrew Cooper
  2018-11-21 14:48   ` Razvan Cojocaru
@ 2018-11-21 16:12   ` Paul Durrant
  2018-11-22 15:34   ` Jan Beulich
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 59+ messages in thread
From: Paul Durrant @ 2018-11-21 16:12 UTC (permalink / raw)
  To: Xen-devel
  Cc: Kevin Tian, Tamas K Lengyel, Wei Liu, Jun Nakajima,
	Razvan Cojocaru, Andrew Cooper, Tim (Xen.org),
	George Dunlap, Jan Beulich, Boris Ostrovsky, Brian Woods,
	Suravee Suthikulpanit, Roger Pau Monne

> -----Original Message-----
> From: Andrew Cooper [mailto:andrew.cooper3@citrix.com]
> Sent: 21 November 2018 13:21
> To: Xen-devel <xen-devel@lists.xen.org>
> Cc: Andrew Cooper <Andrew.Cooper3@citrix.com>; Jan Beulich
> <JBeulich@suse.com>; Wei Liu <wei.liu2@citrix.com>; Roger Pau Monne
> <roger.pau@citrix.com>; Razvan Cojocaru <rcojocaru@bitdefender.com>; Tamas
> K Lengyel <tamas@tklengyel.com>; George Dunlap <George.Dunlap@citrix.com>;
> Tim (Xen.org) <tim@xen.org>; Paul Durrant <Paul.Durrant@citrix.com>; Jun
> Nakajima <jun.nakajima@intel.com>; Kevin Tian <kevin.tian@intel.com>;
> Boris Ostrovsky <boris.ostrovsky@oracle.com>; Suravee Suthikulpanit
> <suravee.suthikulpanit@amd.com>; Brian Woods <brian.woods@amd.com>
> Subject: [PATCH 10/14] x86/mm: Switch {get,put}_gfn() infrastructure to
> using gfn_t
> 
> Seemingly, a majority of users either override the helpers anyway, or have
> an
> gfn_t in their hands.
> 
> Update the API, and adjust all users to match.
> 
> Doing this highlighted a gaping altp2m security hole in
> vmx_vcpu_update_vmfunc_ve(), which will need addressing now we can discuss
> the
> problem and options publicly.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Reviewed-by: Paul Durrant <paul.durrant@citrix.com>

> ---
> CC: Jan Beulich <JBeulich@suse.com>
> CC: Wei Liu <wei.liu2@citrix.com>
> CC: Roger Pau Monné <roger.pau@citrix.com>
> CC: Razvan Cojocaru <rcojocaru@bitdefender.com>
> CC: Tamas K Lengyel <tamas@tklengyel.com>
> CC: George Dunlap <george.dunlap@eu.citrix.com>
> CC: Tim Deegan <tim@xen.org>
> CC: Paul Durrant <paul.durrant@citrix.com>
> CC: Jun Nakajima <jun.nakajima@intel.com>
> CC: Kevin Tian <kevin.tian@intel.com>
> CC: Boris Ostrovsky <boris.ostrovsky@oracle.com>
> CC: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
> CC: Brian Woods <brian.woods@amd.com>
> ---
>  xen/arch/x86/cpu/mcheck/mcaction.c        |  2 +-
>  xen/arch/x86/cpu/mcheck/mce.c             | 14 +++----
>  xen/arch/x86/cpu/mcheck/vmce.c            |  4 +-
>  xen/arch/x86/cpu/mcheck/vmce.h            |  2 +-
>  xen/arch/x86/debug.c                      |  6 +--
>  xen/arch/x86/domain.c                     | 19 ++++-----
>  xen/arch/x86/domctl.c                     |  8 ++--
>  xen/arch/x86/hvm/dm.c                     | 12 +++---
>  xen/arch/x86/hvm/emulate.c                | 16 ++++----
>  xen/arch/x86/hvm/grant_table.c            |  4 +-
>  xen/arch/x86/hvm/hvm.c                    | 25 ++++++------
>  xen/arch/x86/hvm/mtrr.c                   |  2 +-
>  xen/arch/x86/hvm/svm/svm.c                |  2 +-
>  xen/arch/x86/hvm/vmx/vmx.c                |  7 ++--
>  xen/arch/x86/mm.c                         | 10 ++---
>  xen/arch/x86/mm/hap/hap.c                 |  2 +-
>  xen/arch/x86/mm/hap/nested_hap.c          |  6 +--
>  xen/arch/x86/mm/mem_access.c              |  5 +--
>  xen/arch/x86/mm/mem_sharing.c             | 24 +++++------
>  xen/arch/x86/mm/p2m.c                     | 45 ++++++++++----------
>  xen/arch/x86/mm/shadow/common.c           |  4 +-
>  xen/arch/x86/mm/shadow/multi.c            | 68 +++++++++++++++-----------
> -----
>  xen/arch/x86/mm/shadow/types.h            |  4 --
>  xen/common/grant_table.c                  | 10 ++---
>  xen/common/memory.c                       | 24 +++++------
>  xen/drivers/passthrough/amd/iommu_guest.c |  8 ----
>  xen/include/asm-x86/guest_pt.h            |  4 --
>  xen/include/asm-x86/p2m.h                 | 30 +++++++-------
>  28 files changed, 172 insertions(+), 195 deletions(-)
> 
> diff --git a/xen/arch/x86/cpu/mcheck/mcaction.c
> b/xen/arch/x86/cpu/mcheck/mcaction.c
> index e422674..c8e0cf2 100644
> --- a/xen/arch/x86/cpu/mcheck/mcaction.c
> +++ b/xen/arch/x86/cpu/mcheck/mcaction.c
> @@ -89,7 +89,7 @@ mc_memerr_dhandler(struct mca_binfo *binfo,
>                  ASSERT(d);
>                  gfn = get_gpfn_from_mfn((bank->mc_addr) >> PAGE_SHIFT);
> 
> -                if ( unmmap_broken_page(d, _mfn(mfn), gfn) )
> +                if ( unmmap_broken_page(d, _mfn(mfn), _gfn(gfn)) )
>                  {
>                      printk("Unmap broken memory %lx for DOM%d failed\n",
>                             mfn, d->domain_id);
> diff --git a/xen/arch/x86/cpu/mcheck/mce.c b/xen/arch/x86/cpu/mcheck/mce.c
> index 30cdb06..c96c053 100644
> --- a/xen/arch/x86/cpu/mcheck/mce.c
> +++ b/xen/arch/x86/cpu/mcheck/mce.c
> @@ -1469,9 +1469,6 @@ long do_mca(XEN_GUEST_HANDLE_PARAM(xen_mc_t)
> u_xen_mc)
>              struct domain *d;
>              struct mcinfo_msr *msr;
>              unsigned int i;
> -            paddr_t gaddr;
> -            unsigned long gfn, mfn;
> -            p2m_type_t t;
> 
>              domid = (mc_msrinject->mcinj_domid == DOMID_SELF) ?
>                      current->domain->domain_id : mc_msrinject-
> >mcinj_domid;
> @@ -1489,11 +1486,12 @@ long do_mca(XEN_GUEST_HANDLE_PARAM(xen_mc_t)
> u_xen_mc)
>                    i < mc_msrinject->mcinj_count;
>                    i++, msr++ )
>              {
> -                gaddr = msr->value;
> -                gfn = PFN_DOWN(gaddr);
> -                mfn = mfn_x(get_gfn(d, gfn, &t));
> +                p2m_type_t t;
> +                paddr_t gaddr = msr->value;
> +                gfn_t gfn = _gfn(PFN_DOWN(gaddr));
> +                mfn_t mfn = get_gfn(d, gfn, &t);
> 
> -                if ( mfn == mfn_x(INVALID_MFN) )
> +                if ( mfn_eq(mfn, INVALID_MFN) )
>                  {
>                      put_gfn(d, gfn);
>                      put_domain(d);
> @@ -1501,7 +1499,7 @@ long do_mca(XEN_GUEST_HANDLE_PARAM(xen_mc_t)
> u_xen_mc)
>                                       -EINVAL, gfn, domid);
>                  }
> 
> -                msr->value = pfn_to_paddr(mfn) | (gaddr & (PAGE_SIZE -
> 1));
> +                msr->value = mfn_to_maddr(mfn) | (gaddr & (PAGE_SIZE -
> 1));
> 
>                  put_gfn(d, gfn);
>              }
> diff --git a/xen/arch/x86/cpu/mcheck/vmce.c
> b/xen/arch/x86/cpu/mcheck/vmce.c
> index f15835e..e257e94 100644
> --- a/xen/arch/x86/cpu/mcheck/vmce.c
> +++ b/xen/arch/x86/cpu/mcheck/vmce.c
> @@ -512,7 +512,7 @@ int fill_vmsr_data(struct mcinfo_bank *mc_bank, struct
> domain *d,
>   * XXX following situation missed:
>   * PoD, Foreign mapped, Granted, Shared
>   */
> -int unmmap_broken_page(struct domain *d, mfn_t mfn, unsigned long gfn)
> +int unmmap_broken_page(struct domain *d, mfn_t mfn, gfn_t gfn)
>  {
>      mfn_t r_mfn;
>      p2m_type_t pt;
> @@ -533,7 +533,7 @@ int unmmap_broken_page(struct domain *d, mfn_t mfn,
> unsigned long gfn)
>      if ( p2m_to_mask(pt) & P2M_UNMAP_TYPES)
>      {
>          ASSERT(mfn_eq(r_mfn, mfn));
> -        rc = p2m_change_type_one(d, gfn, pt, p2m_ram_broken);
> +        rc = p2m_change_type_one(d, gfn_x(gfn), pt, p2m_ram_broken);
>      }
>      put_gfn(d, gfn);
> 
> diff --git a/xen/arch/x86/cpu/mcheck/vmce.h
> b/xen/arch/x86/cpu/mcheck/vmce.h
> index 2797e00..a37f3be 100644
> --- a/xen/arch/x86/cpu/mcheck/vmce.h
> +++ b/xen/arch/x86/cpu/mcheck/vmce.h
> @@ -9,7 +9,7 @@ int vmce_init(struct cpuinfo_x86 *c);
>          && hardware_domain->vcpu[0] \
>          && guest_enabled_event(hardware_domain->vcpu[0], VIRQ_MCA))
> 
> -int unmmap_broken_page(struct domain *d, mfn_t mfn, unsigned long gfn);
> +int unmmap_broken_page(struct domain *d, mfn_t mfn, gfn_t gfn);
> 
>  int vmce_intel_rdmsr(const struct vcpu *, uint32_t msr, uint64_t *val);
>  int vmce_intel_wrmsr(struct vcpu *, uint32_t msr, uint64_t val);
> diff --git a/xen/arch/x86/debug.c b/xen/arch/x86/debug.c
> index a500df0..7c2dc8c 100644
> --- a/xen/arch/x86/debug.c
> +++ b/xen/arch/x86/debug.c
> @@ -58,7 +58,7 @@ dbg_hvm_va2mfn(dbgva_t vaddr, struct domain *dp, int
> toaddr, gfn_t *gfn)
>          return INVALID_MFN;
>      }
> 
> -    mfn = get_gfn(dp, gfn_x(*gfn), &gfntype);
> +    mfn = get_gfn(dp, *gfn, &gfntype);
>      if ( p2m_is_readonly(gfntype) && toaddr )
>      {
>          DBGP2("kdb:p2m_is_readonly: gfntype:%x\n", gfntype);
> @@ -70,7 +70,7 @@ dbg_hvm_va2mfn(dbgva_t vaddr, struct domain *dp, int
> toaddr, gfn_t *gfn)
> 
>      if ( mfn_eq(mfn, INVALID_MFN) )
>      {
> -        put_gfn(dp, gfn_x(*gfn));
> +        put_gfn(dp, *gfn);
>          *gfn = INVALID_GFN;
>      }
> 
> @@ -189,7 +189,7 @@ static unsigned int dbg_rw_guest_mem(struct domain
> *dp, void * __user gaddr,
> 
>          unmap_domain_page(va);
>          if ( !gfn_eq(gfn, INVALID_GFN) )
> -            put_gfn(dp, gfn_x(gfn));
> +            put_gfn(dp, gfn);
> 
>          addr += pagecnt;
>          buf += pagecnt;
> diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
> index b4d5948..327c961 100644
> --- a/xen/arch/x86/domain.c
> +++ b/xen/arch/x86/domain.c
> @@ -677,7 +677,7 @@ int arch_domain_soft_reset(struct domain *d)
>      int ret = 0;
>      struct domain *owner;
>      mfn_t mfn;
> -    unsigned long gfn;
> +    gfn_t gfn;
>      p2m_type_t p2mt;
>      unsigned int i;
> 
> @@ -711,19 +711,19 @@ int arch_domain_soft_reset(struct domain *d)
>      ASSERT( owner == d );
> 
>      mfn = page_to_mfn(page);
> -    gfn = mfn_to_gmfn(d, mfn_x(mfn));
> +    gfn = _gfn(mfn_to_gmfn(d, mfn_x(mfn)));
> 
>      /*
>       * gfn == INVALID_GFN indicates that the shared_info page was never
> mapped
>       * to the domain's address space and there is nothing to replace.
>       */
> -    if ( gfn == gfn_x(INVALID_GFN) )
> +    if ( gfn_eq(gfn, INVALID_GFN) )
>          goto exit_put_page;
> 
>      if ( !mfn_eq(get_gfn_query(d, gfn, &p2mt), mfn) )
>      {
>          printk(XENLOG_G_ERR "Failed to get Dom%d's shared_info GFN
> (%lx)\n",
> -               d->domain_id, gfn);
> +               d->domain_id, gfn_x(gfn));
>          ret = -EINVAL;
>          goto exit_put_gfn;
>      }
> @@ -732,26 +732,25 @@ int arch_domain_soft_reset(struct domain *d)
>      if ( !new_page )
>      {
>          printk(XENLOG_G_ERR "Failed to alloc a page to replace"
> -               " Dom%d's shared_info frame %lx\n", d->domain_id, gfn);
> +               " Dom%d's shared_info frame %lx\n", d->domain_id,
> gfn_x(gfn));
>          ret = -ENOMEM;
>          goto exit_put_gfn;
>      }
> 
> -    ret = guest_physmap_remove_page(d, _gfn(gfn), mfn, PAGE_ORDER_4K);
> +    ret = guest_physmap_remove_page(d, gfn, mfn, PAGE_ORDER_4K);
>      if ( ret )
>      {
>          printk(XENLOG_G_ERR "Failed to remove Dom%d's shared_info frame
> %lx\n",
> -               d->domain_id, gfn);
> +               d->domain_id, gfn_x(gfn));
>          free_domheap_page(new_page);
>          goto exit_put_gfn;
>      }
> 
> -    ret = guest_physmap_add_page(d, _gfn(gfn), page_to_mfn(new_page),
> -                                 PAGE_ORDER_4K);
> +    ret = guest_physmap_add_page(d, gfn, page_to_mfn(new_page),
> PAGE_ORDER_4K);
>      if ( ret )
>      {
>          printk(XENLOG_G_ERR "Failed to add a page to replace"
> -               " Dom%d's shared_info frame %lx\n", d->domain_id, gfn);
> +               " Dom%d's shared_info frame %lx\n", d->domain_id,
> gfn_x(gfn));
>          free_domheap_page(new_page);
>      }
>   exit_put_gfn:
> diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
> index aa8ad19..694b4d5 100644
> --- a/xen/arch/x86/domctl.c
> +++ b/xen/arch/x86/domctl.c
> @@ -1253,15 +1253,15 @@ long arch_do_domctl(
>      case XEN_DOMCTL_set_broken_page_p2m:
>      {
>          p2m_type_t pt;
> -        unsigned long pfn = domctl->u.set_broken_page_p2m.pfn;
> -        mfn_t mfn = get_gfn_query(d, pfn, &pt);
> +        gfn_t gfn = _gfn(domctl->u.set_broken_page_p2m.pfn);
> +        mfn_t mfn = get_gfn_query(d, gfn, &pt);
> 
>          if ( unlikely(!mfn_valid(mfn)) || unlikely(!p2m_is_ram(pt)) )
>              ret = -EINVAL;
>          else
> -            ret = p2m_change_type_one(d, pfn, pt, p2m_ram_broken);
> +            ret = p2m_change_type_one(d, gfn_x(gfn), pt, p2m_ram_broken);
> 
> -        put_gfn(d, pfn);
> +        put_gfn(d, gfn);
>          break;
>      }
> 
> diff --git a/xen/arch/x86/hvm/dm.c b/xen/arch/x86/hvm/dm.c
> index d6d0e8b..9938f4b 100644
> --- a/xen/arch/x86/hvm/dm.c
> +++ b/xen/arch/x86/hvm/dm.c
> @@ -269,14 +269,14 @@ static int set_mem_type(struct domain *d,
> 
>      while ( iter < data->nr )
>      {
> -        unsigned long pfn = data->first_pfn + iter;
> +        gfn_t gfn = _gfn(data->first_pfn + iter);
>          p2m_type_t t;
> 
> -        get_gfn_unshare(d, pfn, &t);
> +        get_gfn_unshare(d, gfn, &t);
>          if ( p2m_is_paging(t) )
>          {
> -            put_gfn(d, pfn);
> -            p2m_mem_paging_populate(d, pfn);
> +            put_gfn(d, gfn);
> +            p2m_mem_paging_populate(d, gfn_x(gfn));
>              return -EAGAIN;
>          }
> 
> @@ -285,9 +285,9 @@ static int set_mem_type(struct domain *d,
>          else if ( !allow_p2m_type_change(t, memtype[mem_type]) )
>              rc = -EINVAL;
>          else
> -            rc = p2m_change_type_one(d, pfn, t, memtype[mem_type]);
> +            rc = p2m_change_type_one(d, gfn_x(gfn), t,
> memtype[mem_type]);
> 
> -        put_gfn(d, pfn);
> +        put_gfn(d, gfn);
> 
>          if ( rc )
>              break;
> diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c
> index 2d02ef1..1335b2c 100644
> --- a/xen/arch/x86/hvm/emulate.c
> +++ b/xen/arch/x86/hvm/emulate.c
> @@ -255,13 +255,13 @@ static int hvmemul_do_io(
>           * so the device model side needs to check the incoming ioreq
> event.
>           */
>          struct hvm_ioreq_server *s = NULL;
> -        p2m_type_t p2mt = p2m_invalid;
> 
>          if ( is_mmio )
>          {
> -            unsigned long gmfn = paddr_to_pfn(addr);
> +            p2m_type_t p2mt = p2m_invalid;
> +            gfn_t gfn = gaddr_to_gfn(addr);
> 
> -            get_gfn_query_unlocked(currd, gmfn, &p2mt);
> +            get_gfn_query_unlocked(currd, gfn, &p2mt);
> 
>              if ( p2mt == p2m_ioreq_server )
>              {
> @@ -1590,7 +1590,7 @@ static int hvmemul_rep_ins(
>      if ( rc != X86EMUL_OKAY )
>          return rc;
> 
> -    (void) get_gfn_query_unlocked(current->domain, gpa >> PAGE_SHIFT,
> &p2mt);
> +    get_gfn_query_unlocked(current->domain, gaddr_to_gfn(gpa), &p2mt);
>      if ( p2mt == p2m_mmio_direct || p2mt == p2m_mmio_dm )
>          return X86EMUL_UNHANDLEABLE;
> 
> @@ -1671,7 +1671,7 @@ static int hvmemul_rep_outs(
>      if ( rc != X86EMUL_OKAY )
>          return rc;
> 
> -    (void) get_gfn_query_unlocked(current->domain, gpa >> PAGE_SHIFT,
> &p2mt);
> +    get_gfn_query_unlocked(current->domain, gaddr_to_gfn(gpa), &p2mt);
>      if ( p2mt == p2m_mmio_direct || p2mt == p2m_mmio_dm )
>          return X86EMUL_UNHANDLEABLE;
> 
> @@ -1750,8 +1750,8 @@ static int hvmemul_rep_movs(
>      }
> 
>      /* Check for MMIO ops */
> -    (void) get_gfn_query_unlocked(current->domain, sgpa >> PAGE_SHIFT,
> &sp2mt);
> -    (void) get_gfn_query_unlocked(current->domain, dgpa >> PAGE_SHIFT,
> &dp2mt);
> +    get_gfn_query_unlocked(current->domain, gaddr_to_gfn(sgpa), &sp2mt);
> +    get_gfn_query_unlocked(current->domain, gaddr_to_gfn(dgpa), &dp2mt);
> 
>      if ( sp2mt == p2m_mmio_direct || dp2mt == p2m_mmio_direct ||
>           (sp2mt == p2m_mmio_dm && dp2mt == p2m_mmio_dm) )
> @@ -1878,7 +1878,7 @@ static int hvmemul_rep_stos(
>      }
> 
>      /* Check for MMIO op */
> -    (void)get_gfn_query_unlocked(current->domain, gpa >> PAGE_SHIFT,
> &p2mt);
> +    get_gfn_query_unlocked(current->domain, gaddr_to_gfn(gpa), &p2mt);
> 
>      switch ( p2mt )
>      {
> diff --git a/xen/arch/x86/hvm/grant_table.c
> b/xen/arch/x86/hvm/grant_table.c
> index ecd7d07..04a3106 100644
> --- a/xen/arch/x86/hvm/grant_table.c
> +++ b/xen/arch/x86/hvm/grant_table.c
> @@ -51,7 +51,7 @@ int create_grant_p2m_mapping(uint64_t addr, mfn_t frame,
>  int replace_grant_p2m_mapping(uint64_t addr, mfn_t frame,
>                                uint64_t new_addr, unsigned int flags)
>  {
> -    unsigned long gfn = (unsigned long)(addr >> PAGE_SHIFT);
> +    gfn_t gfn = gaddr_to_gfn(addr);
>      p2m_type_t type;
>      mfn_t old_mfn;
>      struct domain *d = current->domain;
> @@ -68,7 +68,7 @@ int replace_grant_p2m_mapping(uint64_t addr, mfn_t
> frame,
>                   type, mfn_x(old_mfn), mfn_x(frame));
>          return GNTST_general_error;
>      }
> -    if ( guest_physmap_remove_page(d, _gfn(gfn), frame, PAGE_ORDER_4K) )
> +    if ( guest_physmap_remove_page(d, gfn, frame, PAGE_ORDER_4K) )
>      {
>          put_gfn(d, gfn);
>          return GNTST_general_error;
> diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
> index db60f23..987c26a 100644
> --- a/xen/arch/x86/hvm/hvm.c
> +++ b/xen/arch/x86/hvm/hvm.c
> @@ -1679,7 +1679,7 @@ void hvm_inject_event(const struct x86_event *event)
>  int hvm_hap_nested_page_fault(paddr_t gpa, unsigned long gla,
>                                struct npfec npfec)
>  {
> -    unsigned long gfn = gpa >> PAGE_SHIFT;
> +    gfn_t gfn = gaddr_to_gfn(gpa);
>      p2m_type_t p2mt;
>      p2m_access_t p2ma;
>      mfn_t mfn;
> @@ -1729,7 +1729,7 @@ int hvm_hap_nested_page_fault(paddr_t gpa, unsigned
> long gla,
>              return 1;
>          case NESTEDHVM_PAGEFAULT_L0_ERROR:
>              /* gpa is now translated to l1 guest address, update gfn. */
> -            gfn = gpa >> PAGE_SHIFT;
> +            gfn = gaddr_to_gfn(gpa);
>              break;
>          }
>      }
> @@ -1817,7 +1817,7 @@ int hvm_hap_nested_page_fault(paddr_t gpa, unsigned
> long gla,
>              {
>                  bool_t sve;
> 
> -                p2m->get_entry(p2m, _gfn(gfn), &p2mt, &p2ma, 0, NULL,
> &sve);
> +                p2m->get_entry(p2m, gfn, &p2mt, &p2ma, 0, NULL, &sve);
> 
>                  if ( !sve && altp2m_vcpu_emulate_ve(curr) )
>                  {
> @@ -1862,7 +1862,7 @@ int hvm_hap_nested_page_fault(paddr_t gpa, unsigned
> long gla,
>      {
>          ASSERT(p2m_is_hostp2m(p2m));
>          sharing_enomem =
> -            (mem_sharing_unshare_page(currd, gfn, 0) < 0);
> +            (mem_sharing_unshare_page(currd, gfn_x(gfn), 0) < 0);
>          rc = 1;
>          goto out_put_gfn;
>      }
> @@ -1878,7 +1878,7 @@ int hvm_hap_nested_page_fault(paddr_t gpa, unsigned
> long gla,
>           */
>          if ( npfec.write_access )
>          {
> -            paging_mark_pfn_dirty(currd, _pfn(gfn));
> +            paging_mark_pfn_dirty(currd, _pfn(gfn_x(gfn)));
>              /*
>               * If p2m is really an altp2m, unlock it before changing the
> type,
>               * as p2m_altp2m_propagate_change() needs to acquire the
> @@ -1886,7 +1886,7 @@ int hvm_hap_nested_page_fault(paddr_t gpa, unsigned
> long gla,
>               */
>              if ( p2m != hostp2m )
>                  __put_gfn(p2m, gfn);
> -            p2m_change_type_one(currd, gfn, p2m_ram_logdirty,
> p2m_ram_rw);
> +            p2m_change_type_one(currd, gfn_x(gfn), p2m_ram_logdirty,
> p2m_ram_rw);
>              __put_gfn(hostp2m, gfn);
> 
>              goto out;
> @@ -1916,16 +1916,16 @@ int hvm_hap_nested_page_fault(paddr_t gpa,
> unsigned long gla,
>       * sleep on event ring wait queues, and we must not hold
>       * locks in such circumstance */
>      if ( paged )
> -        p2m_mem_paging_populate(currd, gfn);
> +        p2m_mem_paging_populate(currd, gfn_x(gfn));
>      if ( sharing_enomem )
>      {
>          int rv;
> 
> -        if ( (rv = mem_sharing_notify_enomem(currd, gfn, true)) < 0 )
> +        if ( (rv = mem_sharing_notify_enomem(currd, gfn_x(gfn), true)) <
> 0 )
>          {
>              gdprintk(XENLOG_ERR, "Domain %hu attempt to unshare "
>                       "gfn %lx, ENOMEM and no helper (rc %d)\n",
> -                     currd->domain_id, gfn, rv);
> +                     currd->domain_id, gfn_x(gfn), rv);
>              /* Crash the domain */
>              rc = 0;
>          }
> @@ -4601,8 +4601,9 @@ static int do_altp2m_op(
>          v = d->vcpu[a.u.enable_notify.vcpu_id];
> 
>          if ( !gfn_eq(vcpu_altp2m(v).veinfo_gfn, INVALID_GFN) ||
> -             mfn_eq(get_gfn_query_unlocked(v->domain,
> -                    a.u.enable_notify.gfn, &p2mt), INVALID_MFN) )
> +             mfn_eq(get_gfn_query_unlocked(
> +                        v->domain, _gfn(a.u.enable_notify.gfn), &p2mt),
> +                    INVALID_MFN) )
>          {
>              rc = -EINVAL;
>              break;
> @@ -4866,7 +4867,7 @@ static int hvmop_get_mem_type(
>       * type, not in allocating or unsharing. That'll happen
>       * on access.
>       */
> -    get_gfn_query_unlocked(d, a.pfn, &t);
> +    get_gfn_query_unlocked(d, _gfn(a.pfn), &t);
>      if ( p2m_is_mmio(t) )
>          a.mem_type =  HVMMEM_mmio_dm;
>      else if ( t == p2m_ioreq_server )
> diff --git a/xen/arch/x86/hvm/mtrr.c b/xen/arch/x86/hvm/mtrr.c
> index b8fa340..f553e4d 100644
> --- a/xen/arch/x86/hvm/mtrr.c
> +++ b/xen/arch/x86/hvm/mtrr.c
> @@ -366,7 +366,7 @@ uint32_t get_pat_flags(struct vcpu *v,
>      {
>          struct domain *d = v->domain;
>          p2m_type_t p2mt;
> -        get_gfn_query_unlocked(d, paddr_to_pfn(gpaddr), &p2mt);
> +        get_gfn_query_unlocked(d, gaddr_to_gfn(gpaddr), &p2mt);
>          if (p2m_is_ram(p2mt))
>              gdprintk(XENLOG_WARNING,
>                      "Conflict occurs for a given guest l1e flags:%x "
> diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
> index b9a8900..46f9893 100644
> --- a/xen/arch/x86/hvm/svm/svm.c
> +++ b/xen/arch/x86/hvm/svm/svm.c
> @@ -1762,7 +1762,7 @@ static void svm_do_nested_pgfault(struct vcpu *v,
>      struct cpu_user_regs *regs, uint64_t pfec, paddr_t gpa)
>  {
>      int ret;
> -    unsigned long gfn = gpa >> PAGE_SHIFT;
> +    gfn_t gfn = gaddr_to_gfn(gpa);
>      mfn_t mfn;
>      p2m_type_t p2mt;
>      p2m_access_t p2ma;
> diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
> index 365eeb2..b5370dd 100644
> --- a/xen/arch/x86/hvm/vmx/vmx.c
> +++ b/xen/arch/x86/hvm/vmx/vmx.c
> @@ -2199,7 +2199,8 @@ static void vmx_vcpu_update_vmfunc_ve(struct vcpu
> *v)
>              p2m_type_t t;
>              mfn_t mfn;
> 
> -            mfn = get_gfn_query_unlocked(d,
> gfn_x(vcpu_altp2m(v).veinfo_gfn), &t);
> +            /* TODO: This is a security issue... */
> +            mfn = get_gfn_query_unlocked(d, vcpu_altp2m(v).veinfo_gfn,
> &t);
> 
>              if ( !mfn_eq(mfn, INVALID_MFN) )
>              {
> @@ -3328,7 +3329,7 @@ static void ept_handle_violation(ept_qual_t q,
> paddr_t gpa)
> 
>          _d.gpa = gpa;
>          _d.qualification = q.raw;
> -        _d.mfn = mfn_x(get_gfn_query_unlocked(d, gfn, &_d.p2mt));
> +        _d.mfn = mfn_x(get_gfn_query_unlocked(d, _gfn(gfn), &_d.p2mt));
> 
>          __trace_var(TRC_HVM_NPF, 0, sizeof(_d), &_d);
>      }
> @@ -3358,7 +3359,7 @@ static void ept_handle_violation(ept_qual_t q,
> paddr_t gpa)
>      }
> 
>      /* Everything else is an error. */
> -    mfn = get_gfn_query_unlocked(d, gfn, &p2mt);
> +    mfn = get_gfn_query_unlocked(d, _gfn(gfn), &p2mt);
>      gprintk(XENLOG_ERR,
>              "EPT violation %#lx (%c%c%c/%c%c%c) gpa %#"PRIpaddr" mfn %#lx
> type %i\n",
>              q.raw,
> diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
> index 28a0030..c3c7628 100644
> --- a/xen/arch/x86/mm.c
> +++ b/xen/arch/x86/mm.c
> @@ -4364,11 +4364,11 @@ int xenmem_add_to_physmap_one(
>              p2m_type_t p2mt;
> 
>              gfn = idx;
> -            mfn = get_gfn_unshare(d, gfn, &p2mt);
> +            mfn = get_gfn_unshare(d, _gfn(gfn), &p2mt);
>              /* If the page is still shared, exit early */
>              if ( p2m_is_shared(p2mt) )
>              {
> -                put_gfn(d, gfn);
> +                put_gfn(d, _gfn(gfn));
>                  return -ENOMEM;
>              }
>              page = get_page_from_mfn(mfn, d);
> @@ -4389,7 +4389,7 @@ int xenmem_add_to_physmap_one(
>      }
> 
>      /* Remove previously mapped page if it was present. */
> -    prev_mfn = mfn_x(get_gfn(d, gfn_x(gpfn), &p2mt));
> +    prev_mfn = mfn_x(get_gfn(d, gpfn, &p2mt));
>      if ( mfn_valid(_mfn(prev_mfn)) )
>      {
>          if ( is_xen_heap_mfn(prev_mfn) )
> @@ -4400,7 +4400,7 @@ int xenmem_add_to_physmap_one(
>              rc = guest_remove_page(d, gfn_x(gpfn));
>      }
>      /* In the XENMAPSPACE_gmfn case we still hold a ref on the old page.
> */
> -    put_gfn(d, gfn_x(gpfn));
> +    put_gfn(d, gpfn);
> 
>      if ( rc )
>          goto put_both;
> @@ -4423,7 +4423,7 @@ int xenmem_add_to_physmap_one(
>   put_both:
>      /* In the XENMAPSPACE_gmfn case, we took a ref of the gfn at the top.
> */
>      if ( space == XENMAPSPACE_gmfn )
> -        put_gfn(d, gfn);
> +        put_gfn(d, _gfn(gfn));
> 
>      if ( page )
>          put_page(page);
> diff --git a/xen/arch/x86/mm/hap/hap.c b/xen/arch/x86/mm/hap/hap.c
> index 3d651b9..0ac7d10 100644
> --- a/xen/arch/x86/mm/hap/hap.c
> +++ b/xen/arch/x86/mm/hap/hap.c
> @@ -681,7 +681,7 @@ hap_paging_get_mode(struct vcpu *v)
>  static void hap_update_paging_modes(struct vcpu *v)
>  {
>      struct domain *d = v->domain;
> -    unsigned long cr3_gfn = v->arch.hvm.guest_cr[3] >> PAGE_SHIFT;
> +    gfn_t cr3_gfn = gaddr_to_gfn(v->arch.hvm.guest_cr[3]);
>      p2m_type_t t;
> 
>      /* We hold onto the cr3 as it may be modified later, and
> diff --git a/xen/arch/x86/mm/hap/nested_hap.c
> b/xen/arch/x86/mm/hap/nested_hap.c
> index d2a07a5..d83c436 100644
> --- a/xen/arch/x86/mm/hap/nested_hap.c
> +++ b/xen/arch/x86/mm/hap/nested_hap.c
> @@ -150,12 +150,12 @@ nestedhap_walk_L0_p2m(struct p2m_domain *p2m,
> paddr_t L1_gpa, paddr_t *L0_gpa,
>                        unsigned int *page_order,
>                        bool_t access_r, bool_t access_w, bool_t access_x)
>  {
> +    gfn_t l1_gfn = gaddr_to_gfn(L1_gpa);
>      mfn_t mfn;
>      int rc;
> 
>      /* walk L0 P2M table */
> -    mfn = get_gfn_type_access(p2m, L1_gpa >> PAGE_SHIFT, p2mt, p2ma,
> -                              0, page_order);
> +    mfn = get_gfn_type_access(p2m, l1_gfn, p2mt, p2ma, 0, page_order);
> 
>      rc = NESTEDHVM_PAGEFAULT_DIRECT_MMIO;
>      if ( *p2mt == p2m_mmio_direct )
> @@ -178,7 +178,7 @@ nestedhap_walk_L0_p2m(struct p2m_domain *p2m, paddr_t
> L1_gpa, paddr_t *L0_gpa,
>  direct_mmio_out:
>      *L0_gpa = (mfn_x(mfn) << PAGE_SHIFT) + (L1_gpa & ~PAGE_MASK);
>  out:
> -    __put_gfn(p2m, L1_gpa >> PAGE_SHIFT);
> +    __put_gfn(p2m, l1_gfn);
>      return rc;
>  }
> 
> diff --git a/xen/arch/x86/mm/mem_access.c b/xen/arch/x86/mm/mem_access.c
> index 30c2f1a..caa33c3 100644
> --- a/xen/arch/x86/mm/mem_access.c
> +++ b/xen/arch/x86/mm/mem_access.c
> @@ -263,7 +263,6 @@ int p2m_set_altp2m_mem_access(struct domain *d, struct
> p2m_domain *hp2m,
>      p2m_type_t t;
>      p2m_access_t old_a;
>      unsigned int page_order;
> -    unsigned long gfn_l = gfn_x(gfn);
>      int rc;
> 
>      mfn = ap2m->get_entry(ap2m, gfn, &t, &old_a, 0, NULL, NULL);
> @@ -272,7 +271,7 @@ int p2m_set_altp2m_mem_access(struct domain *d, struct
> p2m_domain *hp2m,
>      if ( !mfn_valid(mfn) )
>      {
> 
> -        mfn = __get_gfn_type_access(hp2m, gfn_l, &t, &old_a,
> +        mfn = __get_gfn_type_access(hp2m, gfn, &t, &old_a,
>                                      P2M_ALLOC | P2M_UNSHARE, &page_order,
> 0);
> 
>          rc = -ESRCH;
> @@ -283,7 +282,7 @@ int p2m_set_altp2m_mem_access(struct domain *d, struct
> p2m_domain *hp2m,
>          if ( page_order != PAGE_ORDER_4K )
>          {
>              unsigned long mask = ~((1UL << page_order) - 1);
> -            gfn_t gfn2 = _gfn(gfn_l & mask);
> +            gfn_t gfn2 = _gfn(gfn_x(gfn) & mask);
>              mfn_t mfn2 = _mfn(mfn_x(mfn) & mask);
> 
>              rc = ap2m->set_entry(ap2m, gfn2, mfn2, page_order, t, old_a,
> 1);
> diff --git a/xen/arch/x86/mm/mem_sharing.c b/xen/arch/x86/mm/mem_sharing.c
> index 573d354..7f2bf80 100644
> --- a/xen/arch/x86/mm/mem_sharing.c
> +++ b/xen/arch/x86/mm/mem_sharing.c
> @@ -499,7 +499,7 @@ static int audit(void)
>                  errors++;
>                  continue;
>              }
> -            o_mfn = get_gfn_query_unlocked(d, g->gfn, &t);
> +            o_mfn = get_gfn_query_unlocked(d, _gfn(g->gfn), &t);
>              if ( !mfn_eq(o_mfn, mfn) )
>              {
>                  MEM_SHARING_DEBUG("Incorrect P2M for d=%hu, PFN=%lx."
> @@ -732,12 +732,12 @@ static int debug_gfn(struct domain *d, gfn_t gfn)
>      mfn_t mfn;
>      int num_refs;
> 
> -    mfn = get_gfn_query(d, gfn_x(gfn), &p2mt);
> +    mfn = get_gfn_query(d, gfn, &p2mt);
> 
>      MEM_SHARING_DEBUG("Debug for dom%d, gfn=%" PRI_gfn "\n",
>                        d->domain_id, gfn_x(gfn));
>      num_refs = debug_mfn(mfn);
> -    put_gfn(d, gfn_x(gfn));
> +    put_gfn(d, gfn);
> 
>      return num_refs;
>  }
> @@ -775,7 +775,7 @@ static int nominate_page(struct domain *d, gfn_t gfn,
> 
>      *phandle = 0UL;
> 
> -    mfn = get_gfn_type_access(hp2m, gfn_x(gfn), &p2mt, &p2ma, 0, NULL);
> +    mfn = get_gfn_type_access(hp2m, gfn, &p2mt, &p2ma, 0, NULL);
> 
>      /* Check if mfn is valid */
>      ret = -EINVAL;
> @@ -820,7 +820,7 @@ static int nominate_page(struct domain *d, gfn_t gfn,
>              if ( !ap2m )
>                  continue;
> 
> -            amfn = __get_gfn_type_access(ap2m, gfn_x(gfn), &ap2mt,
> &ap2ma,
> +            amfn = __get_gfn_type_access(ap2m, gfn, &ap2mt, &ap2ma,
>                                           0, NULL, false);
>              if ( mfn_valid(amfn) && (!mfn_eq(amfn, mfn) || ap2ma != p2ma)
> )
>              {
> @@ -885,7 +885,7 @@ static int nominate_page(struct domain *d, gfn_t gfn,
>      ret = 0;
> 
>  out:
> -    put_gfn(d, gfn_x(gfn));
> +    put_gfn(d, gfn);
>      return ret;
>  }
> 
> @@ -1124,11 +1124,11 @@ int __mem_sharing_unshare_page(struct domain *d,
>      int last_gfn;
>      gfn_info_t *gfn_info = NULL;
> 
> -    mfn = get_gfn(d, gfn, &p2mt);
> +    mfn = get_gfn(d, _gfn(gfn), &p2mt);
> 
>      /* Has someone already unshared it? */
>      if ( !p2m_is_shared(p2mt) ) {
> -        put_gfn(d, gfn);
> +        put_gfn(d, _gfn(gfn));
>          return 0;
>      }
> 
> @@ -1175,7 +1175,7 @@ int __mem_sharing_unshare_page(struct domain *d,
>          {
>              if ( !get_page(page, d) )
>              {
> -                put_gfn(d, gfn);
> +                put_gfn(d, _gfn(gfn));
>                  domain_crash(d);
>                  return -EOVERFLOW;
>              }
> @@ -1183,7 +1183,7 @@ int __mem_sharing_unshare_page(struct domain *d,
>                  put_page(page);
>              put_page(page);
>          }
> -        put_gfn(d, gfn);
> +        put_gfn(d, _gfn(gfn));
> 
>          return 0;
>      }
> @@ -1202,7 +1202,7 @@ int __mem_sharing_unshare_page(struct domain *d,
>          /* Undo dec of nr_saved_mfns, as the retry will decrease again.
> */
>          atomic_inc(&nr_saved_mfns);
>          mem_sharing_page_unlock(old_page);
> -        put_gfn(d, gfn);
> +        put_gfn(d, _gfn(gfn));
>          /* Caller is responsible for placing an event
>           * in the ring */
>          return -ENOMEM;
> @@ -1230,7 +1230,7 @@ int __mem_sharing_unshare_page(struct domain *d,
>       * marking dirty is feasible */
>      paging_mark_dirty(d, page_to_mfn(page));
>      /* We do not need to unlock a private page */
> -    put_gfn(d, gfn);
> +    put_gfn(d, _gfn(gfn));
>      return 0;
>  }
> 
> diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
> index f52a71e..19b383f 100644
> --- a/xen/arch/x86/mm/p2m.c
> +++ b/xen/arch/x86/mm/p2m.c
> @@ -409,12 +409,11 @@ void p2m_unlock_and_tlb_flush(struct p2m_domain
> *p2m)
>          mm_write_unlock(&p2m->lock);
>  }
> 
> -mfn_t __get_gfn_type_access(struct p2m_domain *p2m, unsigned long gfn_l,
> +mfn_t __get_gfn_type_access(struct p2m_domain *p2m, gfn_t gfn,
>                      p2m_type_t *t, p2m_access_t *a, p2m_query_t q,
>                      unsigned int *page_order, bool_t locked)
>  {
>      mfn_t mfn;
> -    gfn_t gfn = _gfn(gfn_l);
> 
>      /* Unshare makes no sense withuot populate. */
>      if ( q & P2M_UNSHARE )
> @@ -425,7 +424,7 @@ mfn_t __get_gfn_type_access(struct p2m_domain *p2m,
> unsigned long gfn_l,
>          /* Not necessarily true, but for non-translated guests, we claim
>           * it's the most generic kind of memory */
>          *t = p2m_ram_rw;
> -        return _mfn(gfn_l);
> +        return _mfn(gfn_x(gfn));
>      }
> 
>      if ( locked )
> @@ -439,8 +438,8 @@ mfn_t __get_gfn_type_access(struct p2m_domain *p2m,
> unsigned long gfn_l,
>          ASSERT(p2m_is_hostp2m(p2m));
>          /* Try to unshare. If we fail, communicate ENOMEM without
>           * sleeping. */
> -        if ( mem_sharing_unshare_page(p2m->domain, gfn_l, 0) < 0 )
> -            mem_sharing_notify_enomem(p2m->domain, gfn_l, false);
> +        if ( mem_sharing_unshare_page(p2m->domain, gfn_x(gfn), 0) < 0 )
> +            mem_sharing_notify_enomem(p2m->domain, gfn_x(gfn), false);
>          mfn = p2m->get_entry(p2m, gfn, t, a, q, page_order, NULL);
>      }
> 
> @@ -455,7 +454,7 @@ mfn_t __get_gfn_type_access(struct p2m_domain *p2m,
> unsigned long gfn_l,
>      return mfn;
>  }
> 
> -void __put_gfn(struct p2m_domain *p2m, unsigned long gfn)
> +void __put_gfn(struct p2m_domain *p2m, gfn_t gfn)
>  {
>      if ( !p2m || !paging_mode_translate(p2m->domain) )
>          /* Nothing to do in this case */
> @@ -484,7 +483,7 @@ struct page_info *p2m_get_page_from_gfn(
>      {
>          /* Fast path: look up and get out */
>          p2m_read_lock(p2m);
> -        mfn = __get_gfn_type_access(p2m, gfn_x(gfn), t, a, 0, NULL, 0);
> +        mfn = __get_gfn_type_access(p2m, gfn, t, a, 0, NULL, 0);
>          if ( p2m_is_any_ram(*t) && mfn_valid(mfn)
>               && !((q & P2M_UNSHARE) && p2m_is_shared(*t)) )
>          {
> @@ -513,14 +512,14 @@ struct page_info *p2m_get_page_from_gfn(
>      }
> 
>      /* Slow path: take the write lock and do fixups */
> -    mfn = get_gfn_type_access(p2m, gfn_x(gfn), t, a, q, NULL);
> +    mfn = get_gfn_type_access(p2m, gfn, t, a, q, NULL);
>      if ( p2m_is_ram(*t) && mfn_valid(mfn) )
>      {
>          page = mfn_to_page(mfn);
>          if ( !get_page(page, p2m->domain) )
>              page = NULL;
>      }
> -    put_gfn(p2m->domain, gfn_x(gfn));
> +    put_gfn(p2m->domain, gfn);
> 
>      return page;
>  }
> @@ -1278,7 +1277,7 @@ int set_shared_p2m_entry(struct domain *d, unsigned
> long gfn_l, mfn_t mfn)
>      if ( rc )
>          gdprintk(XENLOG_ERR,
>                   "p2m_set_entry failed! mfn=%08lx rc:%d\n",
> -                 mfn_x(get_gfn_query_unlocked(p2m->domain, gfn_l, &ot)),
> rc);
> +                 mfn_x(get_gfn_query_unlocked(p2m->domain, gfn, &ot)),
> rc);
>      return rc;
>  }
> 
> @@ -2187,8 +2186,7 @@ bool p2m_altp2m_lazy_copy(struct vcpu *v, paddr_t
> gpa,
> 
>      ASSERT(p2m_locked_by_me(hp2m));
> 
> -    mfn = get_gfn_type_access(ap2m, gfn_x(gfn), &p2mt, &p2ma,
> -                              0, &page_order);
> +    mfn = get_gfn_type_access(ap2m, gfn, &p2mt, &p2ma, 0, &page_order);
> 
>      /* Entry already present in ap2m?  Caller should handle the fault. */
>      if ( !mfn_eq(mfn, INVALID_MFN) )
> @@ -2197,8 +2195,7 @@ bool p2m_altp2m_lazy_copy(struct vcpu *v, paddr_t
> gpa,
>          goto put_ap2m;
>      }
> 
> -    mfn = get_gfn_type_access(hp2m, gfn_x(gfn), &p2mt, &p2ma,
> -                              P2M_ALLOC, &page_order);
> +    mfn = get_gfn_type_access(hp2m, gfn, &p2mt, &p2ma, P2M_ALLOC,
> &page_order);
> 
>      /* Entry not present in hp2m?  Caller should handle the fault. */
>      if ( mfn_eq(mfn, INVALID_MFN) )
> @@ -2230,9 +2227,9 @@ bool p2m_altp2m_lazy_copy(struct vcpu *v, paddr_t
> gpa,
>      ret = true;
> 
>  put_hp2m:
> -    __put_gfn(hp2m, gfn_x(gfn));
> +    __put_gfn(hp2m, gfn);
>  put_ap2m:
> -    __put_gfn(ap2m, gfn_x(gfn));
> +    __put_gfn(ap2m, gfn);
> 
>      return ret;
>  }
> @@ -2396,7 +2393,7 @@ int p2m_change_altp2m_gfn(struct domain *d, unsigned
> int idx,
>      /* Check host p2m if no valid entry in alternate */
>      if ( !mfn_valid(mfn) )
>      {
> -        mfn = __get_gfn_type_access(hp2m, gfn_x(old_gfn), &t, &a,
> +        mfn = __get_gfn_type_access(hp2m, old_gfn, &t, &a,
>                                      P2M_ALLOC, &page_order, 0);
> 
>          if ( !mfn_valid(mfn) || t != p2m_ram_rw )
> @@ -2477,7 +2474,7 @@ int p2m_altp2m_propagate_change(struct domain *d,
> gfn_t gfn,
>              continue;
> 
>          p2m = d->arch.altp2m_p2m[i];
> -        m = get_gfn_type_access(p2m, gfn_x(gfn), &t, &a, 0, NULL);
> +        m = get_gfn_type_access(p2m, gfn, &t, &a, 0, NULL);
> 
>          /* Check for a dropped page that may impact this altp2m */
>          if ( mfn_eq(mfn, INVALID_MFN) &&
> @@ -2492,7 +2489,7 @@ int p2m_altp2m_propagate_change(struct domain *d,
> gfn_t gfn,
>              else
>              {
>                  /* At least 2 altp2m's impacted, so reset everything */
> -                __put_gfn(p2m, gfn_x(gfn));
> +                __put_gfn(p2m, gfn);
> 
>                  for ( i = 0; i < MAX_ALTP2M; i++ )
>                  {
> @@ -2519,7 +2516,7 @@ int p2m_altp2m_propagate_change(struct domain *d,
> gfn_t gfn,
>                  ret = rc;
>          }
> 
> -        __put_gfn(p2m, gfn_x(gfn));
> +        __put_gfn(p2m, gfn);
>      }
> 
>      altp2m_list_unlock(d);
> @@ -2590,7 +2587,7 @@ void audit_p2m(struct domain *d,
>              continue;
>          }
> 
> -        p2mfn = get_gfn_type_access(p2m, gfn, &type, &p2ma, 0, NULL);
> +        p2mfn = get_gfn_type_access(p2m, _gfn(gfn), &type, &p2ma, 0,
> NULL);
>          if ( mfn_x(p2mfn) != mfn )
>          {
>              mpbad++;
> @@ -2605,7 +2602,7 @@ void audit_p2m(struct domain *d,
>               * blow away the m2p entry. */
>              set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY);
>          }
> -        __put_gfn(p2m, gfn);
> +        __put_gfn(p2m, _gfn(gfn));
> 
>          P2M_PRINTK("OK: mfn=%#lx, gfn=%#lx, p2mfn=%#lx\n",
>                         mfn, gfn, mfn_x(p2mfn));
> @@ -2698,7 +2695,7 @@ int p2m_add_foreign(struct domain *tdom, unsigned
> long fgfn,
>      mfn = page_to_mfn(page);
> 
>      /* Remove previously mapped page if it is present. */
> -    prev_mfn = get_gfn(tdom, gpfn, &p2mt_prev);
> +    prev_mfn = get_gfn(tdom, _gfn(gpfn), &p2mt_prev);
>      if ( mfn_valid(prev_mfn) )
>      {
>          if ( is_xen_heap_mfn(mfn_x(prev_mfn)) )
> @@ -2729,7 +2726,7 @@ int p2m_add_foreign(struct domain *tdom, unsigned
> long fgfn,
>       * after set_foreign_p2m_entry so another cpu doesn't populate the
> gpfn
>       * before us.
>       */
> -    put_gfn(tdom, gpfn);
> +    put_gfn(tdom, _gfn(gpfn));
> 
>  out:
>      if ( fdom )
> diff --git a/xen/arch/x86/mm/shadow/common.c
> b/xen/arch/x86/mm/shadow/common.c
> index 61304d7..85ce761 100644
> --- a/xen/arch/x86/mm/shadow/common.c
> +++ b/xen/arch/x86/mm/shadow/common.c
> @@ -3338,7 +3338,7 @@ int shadow_track_dirty_vram(struct domain *d,
> 
>          /* Iterate over VRAM to track dirty bits. */
>          for ( i = 0; i < nr; i++ ) {
> -            mfn_t mfn = get_gfn_query_unlocked(d, begin_pfn + i, &t);
> +            mfn_t mfn = get_gfn_query_unlocked(d, _gfn(begin_pfn + i),
> &t);
>              struct page_info *page;
>              int dirty = 0;
>              paddr_t sl1ma = dirty_vram->sl1ma[i];
> @@ -3418,7 +3418,7 @@ int shadow_track_dirty_vram(struct domain *d,
>               * write access */
>              for ( i = begin_pfn; i < end_pfn; i++ )
>              {
> -                mfn_t mfn = get_gfn_query_unlocked(d, i, &t);
> +                mfn_t mfn = get_gfn_query_unlocked(d, _gfn(i), &t);
>                  if ( !mfn_eq(mfn, INVALID_MFN) )
>                      flush_tlb |= sh_remove_write_access(d, mfn, 1, 0);
>              }
> diff --git a/xen/arch/x86/mm/shadow/multi.c
> b/xen/arch/x86/mm/shadow/multi.c
> index 7e9cbc6..de3fcd7 100644
> --- a/xen/arch/x86/mm/shadow/multi.c
> +++ b/xen/arch/x86/mm/shadow/multi.c
> @@ -2126,7 +2126,8 @@ static int validate_gl4e(struct vcpu *v, void
> *new_ge, mfn_t sl4mfn, void *se)
>           !guest_l4e_rsvd_bits(v, new_gl4e) )
>      {
>          gfn_t gl3gfn = guest_l4e_get_gfn(new_gl4e);
> -        mfn_t gl3mfn = get_gfn_query_unlocked(d, gfn_x(gl3gfn), &p2mt);
> +        mfn_t gl3mfn = get_gfn_query_unlocked(d, gl3gfn, &p2mt);
> +
>          if ( p2m_is_ram(p2mt) )
>              sl3mfn = get_shadow_status(d, gl3mfn, SH_type_l3_shadow);
>          else if ( p2mt != p2m_populate_on_demand )
> @@ -2185,7 +2186,8 @@ static int validate_gl3e(struct vcpu *v, void
> *new_ge, mfn_t sl3mfn, void *se)
>           !guest_l3e_rsvd_bits(v, new_gl3e) )
>      {
>          gfn_t gl2gfn = guest_l3e_get_gfn(new_gl3e);
> -        mfn_t gl2mfn = get_gfn_query_unlocked(d, gfn_x(gl2gfn), &p2mt);
> +        mfn_t gl2mfn = get_gfn_query_unlocked(d, gl2gfn, &p2mt);
> +
>          if ( p2m_is_ram(p2mt) )
>              sl2mfn = get_shadow_status(d, gl2mfn, SH_type_l2_shadow);
>          else if ( p2mt != p2m_populate_on_demand )
> @@ -2236,7 +2238,8 @@ static int validate_gl2e(struct vcpu *v, void
> *new_ge, mfn_t sl2mfn, void *se)
>          }
>          else
>          {
> -            mfn_t gl1mfn = get_gfn_query_unlocked(d, gfn_x(gl1gfn),
> &p2mt);
> +            mfn_t gl1mfn = get_gfn_query_unlocked(d, gl1gfn, &p2mt);
> +
>              if ( p2m_is_ram(p2mt) )
>                  sl1mfn = get_shadow_status(d, gl1mfn, SH_type_l1_shadow);
>              else if ( p2mt != p2m_populate_on_demand )
> @@ -2270,7 +2273,7 @@ static int validate_gl1e(struct vcpu *v, void
> *new_ge, mfn_t sl1mfn, void *se)
>           !guest_l1e_rsvd_bits(v, new_gl1e) )
>      {
>          gfn = guest_l1e_get_gfn(new_gl1e);
> -        gmfn = get_gfn_query_unlocked(d, gfn_x(gfn), &p2mt);
> +        gmfn = get_gfn_query_unlocked(d, gfn, &p2mt);
>      }
> 
>      l1e_propagate_from_guest(v, new_gl1e, gmfn, &new_sl1e, ft_prefetch,
> p2mt);
> @@ -2335,7 +2338,7 @@ void sh_resync_l1(struct vcpu *v, mfn_t gl1mfn,
> mfn_t snpmfn)
>                   !guest_l1e_rsvd_bits(v, gl1e) )
>              {
>                  gfn = guest_l1e_get_gfn(gl1e);
> -                gmfn = get_gfn_query_unlocked(d, gfn_x(gfn), &p2mt);
> +                gmfn = get_gfn_query_unlocked(d, gfn, &p2mt);
>              }
> 
>              l1e_propagate_from_guest(v, gl1e, gmfn, &nsl1e, ft_prefetch,
> p2mt);
> @@ -2615,7 +2618,7 @@ static void sh_prefetch(struct vcpu *v, walk_t *gw,
>               !guest_l1e_rsvd_bits(v, gl1e) )
>          {
>              gfn = guest_l1e_get_gfn(gl1e);
> -            gmfn = get_gfn_query_unlocked(d, gfn_x(gfn), &p2mt);
> +            gmfn = get_gfn_query_unlocked(d, gfn, &p2mt);
>          }
>          else
>          {
> @@ -3071,7 +3074,7 @@ static int sh_page_fault(struct vcpu *v,
>          SHADOW_PRINTK("BAD gfn=%"SH_PRI_gfn" gmfn=%"PRI_mfn"\n",
>                        gfn_x(gfn), mfn_x(gmfn));
>          sh_reset_early_unshadow(v);
> -        put_gfn(d, gfn_x(gfn));
> +        put_gfn(d, gfn);
>          goto propagate;
>      }
> 
> @@ -3117,7 +3120,7 @@ static int sh_page_fault(struct vcpu *v,
>      if ( rc & GW_RMWR_REWALK )
>      {
>          paging_unlock(d);
> -        put_gfn(d, gfn_x(gfn));
> +        put_gfn(d, gfn);
>          goto rewalk;
>      }
>  #endif /* OOS */
> @@ -3126,7 +3129,7 @@ static int sh_page_fault(struct vcpu *v,
>      {
>          perfc_incr(shadow_inconsistent_gwalk);
>          paging_unlock(d);
> -        put_gfn(d, gfn_x(gfn));
> +        put_gfn(d, gfn);
>          goto rewalk;
>      }
> 
> @@ -3153,7 +3156,7 @@ static int sh_page_fault(struct vcpu *v,
>          ASSERT(d->is_shutting_down);
>  #endif
>          paging_unlock(d);
> -        put_gfn(d, gfn_x(gfn));
> +        put_gfn(d, gfn);
>          trace_shadow_gen(TRC_SHADOW_DOMF_DYING, va);
>          return 0;
>      }
> @@ -3171,7 +3174,7 @@ static int sh_page_fault(struct vcpu *v,
>           * failed. We cannot safely continue since some page is still
>           * OOS but not in the hash table anymore. */
>          paging_unlock(d);
> -        put_gfn(d, gfn_x(gfn));
> +        put_gfn(d, gfn);
>          return 0;
>      }
> 
> @@ -3181,7 +3184,7 @@ static int sh_page_fault(struct vcpu *v,
>      {
>          perfc_incr(shadow_inconsistent_gwalk);
>          paging_unlock(d);
> -        put_gfn(d, gfn_x(gfn));
> +        put_gfn(d, gfn);
>          goto rewalk;
>      }
>  #endif /* OOS */
> @@ -3267,7 +3270,7 @@ static int sh_page_fault(struct vcpu *v,
>      SHADOW_PRINTK("fixed\n");
>      shadow_audit_tables(v);
>      paging_unlock(d);
> -    put_gfn(d, gfn_x(gfn));
> +    put_gfn(d, gfn);
>      return EXCRET_fault_fixed;
> 
>   emulate:
> @@ -3337,7 +3340,7 @@ static int sh_page_fault(struct vcpu *v,
>      sh_audit_gw(v, &gw);
>      shadow_audit_tables(v);
>      paging_unlock(d);
> -    put_gfn(d, gfn_x(gfn));
> +    put_gfn(d, gfn);
> 
>      this_cpu(trace_emulate_write_val) = 0;
> 
> @@ -3521,7 +3524,7 @@ static int sh_page_fault(struct vcpu *v,
>      shadow_audit_tables(v);
>      sh_reset_early_unshadow(v);
>      paging_unlock(d);
> -    put_gfn(d, gfn_x(gfn));
> +    put_gfn(d, gfn);
>      trace_shadow_gen(TRC_SHADOW_MMIO, va);
>      return (handle_mmio_with_translation(va, gpa >> PAGE_SHIFT, access)
>              ? EXCRET_fault_fixed : 0);
> @@ -3535,7 +3538,7 @@ static int sh_page_fault(struct vcpu *v,
>      shadow_audit_tables(v);
>      sh_reset_early_unshadow(v);
>      paging_unlock(d);
> -    put_gfn(d, gfn_x(gfn));
> +    put_gfn(d, gfn);
> 
>  propagate:
>      trace_not_shadow_fault(gw.l1e, va);
> @@ -4116,7 +4119,7 @@ sh_update_cr3(struct vcpu *v, int do_locking, bool
> noflush)
>              if ( guest_l3e_get_flags(gl3e[i]) & _PAGE_PRESENT )
>              {
>                  gl2gfn = guest_l3e_get_gfn(gl3e[i]);
> -                gl2mfn = get_gfn_query_unlocked(d, gfn_x(gl2gfn), &p2mt);
> +                gl2mfn = get_gfn_query_unlocked(d, gl2gfn, &p2mt);
>                  if ( p2m_is_ram(p2mt) )
>                      flush |= sh_remove_write_access(d, gl2mfn, 2, 0);
>              }
> @@ -4129,7 +4132,7 @@ sh_update_cr3(struct vcpu *v, int do_locking, bool
> noflush)
>              if ( guest_l3e_get_flags(gl3e[i]) & _PAGE_PRESENT )
>              {
>                  gl2gfn = guest_l3e_get_gfn(gl3e[i]);
> -                gl2mfn = get_gfn_query_unlocked(d, gfn_x(gl2gfn), &p2mt);
> +                gl2mfn = get_gfn_query_unlocked(d, gl2gfn, &p2mt);
>                  if ( p2m_is_ram(p2mt) )
>                      sh_set_toplevel_shadow(v, i, gl2mfn, (i == 3)
>                                             ? SH_type_l2h_shadow
> @@ -4536,7 +4539,7 @@ static void sh_pagetable_dying(paddr_t gpa)
>      p2m_type_t p2mt;
>      char *gl3pa = NULL;
>      guest_l3e_t *gl3e = NULL;
> -    unsigned long l3gfn;
> +    gfn_t l3gfn;
>      mfn_t l3mfn;
> 
>      gcr3 = v->arch.hvm.guest_cr[3];
> @@ -4544,8 +4547,8 @@ static void sh_pagetable_dying(paddr_t gpa)
>      if ( gcr3 == gpa )
>          fast_path = 1;
> 
> -    l3gfn = gpa >> PAGE_SHIFT;
> -    l3mfn = get_gfn_query(d, _gfn(l3gfn), &p2mt);
> +    l3gfn = gaddr_to_gfn(gpa);
> +    l3mfn = get_gfn_query(d, l3gfn, &p2mt);
>      if ( !mfn_valid(l3mfn) || !p2m_is_ram(p2mt) )
>      {
>          printk(XENLOG_DEBUG "sh_pagetable_dying: gpa not valid
> %"PRIpaddr"\n",
> @@ -4573,8 +4576,7 @@ static void sh_pagetable_dying(paddr_t gpa)
>          else
>          {
>              /* retrieving the l2s */
> -            gmfn = get_gfn_query_unlocked(d,
> gfn_x(guest_l3e_get_gfn(gl3e[i])),
> -                                          &p2mt);
> +            gmfn = get_gfn_query_unlocked(d, guest_l3e_get_gfn(gl3e[i]),
> &p2mt);
>              smfn = unlikely(mfn_eq(gmfn, INVALID_MFN))
>                     ? INVALID_MFN
>                     : shadow_hash_lookup(d, mfn_x(gmfn),
> SH_type_l2_pae_shadow);
> @@ -4609,10 +4611,11 @@ static void sh_pagetable_dying(paddr_t gpa)
>  {
>      struct vcpu *v = current;
>      struct domain *d = v->domain;
> +    gfn_t gfn = gaddr_to_gfn(gpa);
>      mfn_t smfn, gmfn;
>      p2m_type_t p2mt;
> 
> -    gmfn = get_gfn_query(d, _gfn(gpa >> PAGE_SHIFT), &p2mt);
> +    gmfn = get_gfn_query(d, gfn, &p2mt);
>      paging_lock(d);
> 
>  #if GUEST_PAGING_LEVELS == 2
> @@ -4637,7 +4640,7 @@ static void sh_pagetable_dying(paddr_t gpa)
>      v->arch.paging.shadow.pagetable_dying = 1;
> 
>      paging_unlock(d);
> -    put_gfn(d, gpa >> PAGE_SHIFT);
> +    put_gfn(d, gfn);
>  }
>  #endif
> 
> @@ -4759,7 +4762,7 @@ int sh_audit_l1_table(struct vcpu *v, mfn_t sl1mfn,
> mfn_t x)
>              {
>                  gfn = guest_l1e_get_gfn(*gl1e);
>                  mfn = shadow_l1e_get_mfn(*sl1e);
> -                gmfn = get_gfn_query_unlocked(v->domain, gfn_x(gfn),
> &p2mt);
> +                gmfn = get_gfn_query_unlocked(v->domain, gfn, &p2mt);
>                  if ( !p2m_is_grant(p2mt) && !mfn_eq(gmfn, mfn) )
>                      AUDIT_FAIL(1, "bad translation: gfn %" SH_PRI_gfn
>                                 " --> %" PRI_mfn " != mfn %" PRI_mfn,
> @@ -4832,16 +4835,15 @@ int sh_audit_l2_table(struct vcpu *v, mfn_t
> sl2mfn, mfn_t x)
>              gmfn = (guest_l2e_get_flags(*gl2e) & _PAGE_PSE)
>                  ? get_fl1_shadow_status(d, gfn)
>                  : get_shadow_status(d,
> -                    get_gfn_query_unlocked(d, gfn_x(gfn),
> -                                        &p2mt), SH_type_l1_shadow);
> +                    get_gfn_query_unlocked(d, gfn, &p2mt),
> SH_type_l1_shadow);
>              if ( !mfn_eq(gmfn, mfn) )
>                  AUDIT_FAIL(2, "bad translation: gfn %" SH_PRI_gfn
>                             " (--> %" PRI_mfn ")"
>                             " --> %" PRI_mfn " != mfn %" PRI_mfn,
>                             gfn_x(gfn),
>                             (guest_l2e_get_flags(*gl2e) & _PAGE_PSE) ? 0
> -                           : mfn_x(get_gfn_query_unlocked(d,
> -                                   gfn_x(gfn), &p2mt)), mfn_x(gmfn),
> mfn_x(mfn));
> +                           : mfn_x(get_gfn_query_unlocked(d, gfn,
> &p2mt)),
> +                           mfn_x(gmfn), mfn_x(mfn));
>          }
>      });
>      unmap_domain_page(gp);
> @@ -4881,8 +4883,7 @@ int sh_audit_l3_table(struct vcpu *v, mfn_t sl3mfn,
> mfn_t x)
>          {
>              gfn = guest_l3e_get_gfn(*gl3e);
>              mfn = shadow_l3e_get_mfn(*sl3e);
> -            gmfn = get_shadow_status(d, get_gfn_query_unlocked(
> -                                        d, gfn_x(gfn), &p2mt),
> +            gmfn = get_shadow_status(d, get_gfn_query_unlocked(d, gfn,
> &p2mt),
>                                       ((GUEST_PAGING_LEVELS == 3 ||
>                                         is_pv_32bit_domain(d))
>                                        && !shadow_mode_external(d)
> @@ -4931,8 +4932,7 @@ int sh_audit_l4_table(struct vcpu *v, mfn_t sl4mfn,
> mfn_t x)
>          {
>              gfn = guest_l4e_get_gfn(*gl4e);
>              mfn = shadow_l4e_get_mfn(*sl4e);
> -            gmfn = get_shadow_status(d, get_gfn_query_unlocked(
> -                                     d, gfn_x(gfn), &p2mt),
> +            gmfn = get_shadow_status(d, get_gfn_query_unlocked(d, gfn,
> &p2mt),
>                                       SH_type_l3_shadow);
>              if ( !mfn_eq(gmfn, mfn) )
>                  AUDIT_FAIL(4, "bad translation: gfn %" SH_PRI_gfn
> diff --git a/xen/arch/x86/mm/shadow/types.h
> b/xen/arch/x86/mm/shadow/types.h
> index d509674..f688919 100644
> --- a/xen/arch/x86/mm/shadow/types.h
> +++ b/xen/arch/x86/mm/shadow/types.h
> @@ -193,10 +193,6 @@ static inline shadow_l4e_t shadow_l4e_from_mfn(mfn_t
> mfn, u32 flags)
>  })
>  #endif
> 
> - /* Override get_gfn to work with gfn_t */
> -#undef get_gfn_query
> -#define get_gfn_query(d, g, t) get_gfn_type((d), gfn_x(g), (t), 0)
> -
>  /* The shadow types needed for the various levels. */
> 
>  #if GUEST_PAGING_LEVELS == 2
> diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
> index f7860f6..54f909f 100644
> --- a/xen/common/grant_table.c
> +++ b/xen/common/grant_table.c
> @@ -2099,7 +2099,7 @@ gnttab_transfer(
>          {
>              p2m_type_t p2mt;
> 
> -            mfn = get_gfn_unshare(d, gop.mfn, &p2mt);
> +            mfn = get_gfn_unshare(d, _gfn(gop.mfn), &p2mt);
>              if ( p2m_is_shared(p2mt) || !p2m_is_valid(p2mt) )
>                  mfn = INVALID_MFN;
>          }
> @@ -2111,7 +2111,7 @@ gnttab_transfer(
>          if ( unlikely(!mfn_valid(mfn)) )
>          {
>  #ifdef CONFIG_X86
> -            put_gfn(d, gop.mfn);
> +            put_gfn(d, _gfn(gop.mfn));
>  #endif
>              gdprintk(XENLOG_INFO, "out-of-range %lx\n", (unsigned
> long)gop.mfn);
>              gop.status = GNTST_bad_page;
> @@ -2122,7 +2122,7 @@ gnttab_transfer(
>          if ( (rc = steal_page(d, page, 0)) < 0 )
>          {
>  #ifdef CONFIG_X86
> -            put_gfn(d, gop.mfn);
> +            put_gfn(d, _gfn(gop.mfn));
>  #endif
>              gop.status = rc == -EINVAL ? GNTST_bad_page :
> GNTST_general_error;
>              goto copyback;
> @@ -2154,7 +2154,7 @@ gnttab_transfer(
>              rcu_unlock_domain(e);
>          put_gfn_and_copyback:
>  #ifdef CONFIG_X86
> -            put_gfn(d, gop.mfn);
> +            put_gfn(d, _gfn(gop.mfn));
>  #endif
>              page->count_info &= ~(PGC_count_mask|PGC_allocated);
>              free_domheap_page(page);
> @@ -2243,7 +2243,7 @@ gnttab_transfer(
> 
>          spin_unlock(&e->page_alloc_lock);
>  #ifdef CONFIG_X86
> -        put_gfn(d, gop.mfn);
> +        put_gfn(d, _gfn(gop.mfn));
>  #endif
> 
>          TRACE_1D(TRC_MEM_PAGE_GRANT_TRANSFER, e->domain_id);
> diff --git a/xen/common/memory.c b/xen/common/memory.c
> index 175bd62..c59a017 100644
> --- a/xen/common/memory.c
> +++ b/xen/common/memory.c
> @@ -303,10 +303,10 @@ int guest_remove_page(struct domain *d, unsigned
> long gmfn)
>      int rc;
> 
>  #ifdef CONFIG_X86
> -    mfn = get_gfn_query(d, gmfn, &p2mt);
> +    mfn = get_gfn_query(d, _gfn(gmfn), &p2mt);
>      if ( unlikely(p2mt == p2m_invalid) || unlikely(p2mt == p2m_mmio_dm) )
>      {
> -        put_gfn(d, gmfn);
> +        put_gfn(d, _gfn(gmfn));
> 
>          return -ENOENT;
>      }
> @@ -336,7 +336,7 @@ int guest_remove_page(struct domain *d, unsigned long
> gmfn)
>              goto out_put_gfn;
>          }
> 
> -        put_gfn(d, gmfn);
> +        put_gfn(d, _gfn(gmfn));
> 
>          if ( page )
>          {
> @@ -359,7 +359,7 @@ int guest_remove_page(struct domain *d, unsigned long
> gmfn)
>      if ( unlikely(!mfn_valid(mfn)) )
>      {
>  #ifdef CONFIG_X86
> -        put_gfn(d, gmfn);
> +        put_gfn(d, _gfn(gmfn));
>  #endif
>          gdprintk(XENLOG_INFO, "Domain %u page number %lx invalid\n",
>                  d->domain_id, gmfn);
> @@ -382,7 +382,7 @@ int guest_remove_page(struct domain *d, unsigned long
> gmfn)
>              goto out_put_gfn;
>          }
>          /* Maybe the mfn changed */
> -        mfn = get_gfn_query_unlocked(d, gmfn, &p2mt);
> +        mfn = get_gfn_query_unlocked(d, _gfn(gmfn), &p2mt);
>          ASSERT(!p2m_is_shared(p2mt));
>      }
>  #endif /* CONFIG_X86 */
> @@ -391,7 +391,7 @@ int guest_remove_page(struct domain *d, unsigned long
> gmfn)
>      if ( unlikely(!get_page(page, d)) )
>      {
>  #ifdef CONFIG_X86
> -        put_gfn(d, gmfn);
> +        put_gfn(d, _gfn(gmfn));
>  #endif
>          gdprintk(XENLOG_INFO, "Bad page free for domain %u\n", d-
> >domain_id);
> 
> @@ -416,7 +416,7 @@ int guest_remove_page(struct domain *d, unsigned long
> gmfn)
> 
>  #ifdef CONFIG_X86
>   out_put_gfn:
> -    put_gfn(d, gmfn);
> +    put_gfn(d, _gfn(gmfn));
>  #endif
> 
>      /*
> @@ -651,10 +651,10 @@ static long
> memory_exchange(XEN_GUEST_HANDLE_PARAM(xen_memory_exchange_t) arg)
>                  p2m_type_t p2mt;
> 
>                  /* Shared pages cannot be exchanged */
> -                mfn = get_gfn_unshare(d, gmfn + k, &p2mt);
> +                mfn = get_gfn_unshare(d, _gfn(gmfn + k), &p2mt);
>                  if ( p2m_is_shared(p2mt) )
>                  {
> -                    put_gfn(d, gmfn + k);
> +                    put_gfn(d, _gfn(gmfn + k));
>                      rc = -ENOMEM;
>                      goto fail;
>                  }
> @@ -664,7 +664,7 @@ static long
> memory_exchange(XEN_GUEST_HANDLE_PARAM(xen_memory_exchange_t) arg)
>                  if ( unlikely(!mfn_valid(mfn)) )
>                  {
>  #ifdef CONFIG_X86
> -                    put_gfn(d, gmfn + k);
> +                    put_gfn(d, _gfn(gmfn + k));
>  #endif
>                      rc = -EINVAL;
>                      goto fail;
> @@ -676,14 +676,14 @@ static long
> memory_exchange(XEN_GUEST_HANDLE_PARAM(xen_memory_exchange_t) arg)
>                  if ( unlikely(rc) )
>                  {
>  #ifdef CONFIG_X86
> -                    put_gfn(d, gmfn + k);
> +                    put_gfn(d, _gfn(gmfn + k));
>  #endif
>                      goto fail;
>                  }
> 
>                  page_list_add(page, &in_chunk_list);
>  #ifdef CONFIG_X86
> -                put_gfn(d, gmfn + k);
> +                put_gfn(d, _gfn(gmfn + k));
>  #endif
>              }
>          }
> diff --git a/xen/drivers/passthrough/amd/iommu_guest.c
> b/xen/drivers/passthrough/amd/iommu_guest.c
> index 03ca0cf..7ab3c77 100644
> --- a/xen/drivers/passthrough/amd/iommu_guest.c
> +++ b/xen/drivers/passthrough/amd/iommu_guest.c
> @@ -21,14 +21,6 @@
>  #include <asm/amd-iommu.h>
>  #include <asm/hvm/svm/amd-iommu-proto.h>
> 
> -/* Override {get,put}_gfn to work with gfn_t */
> -#undef get_gfn
> -#define get_gfn(d, g, t) get_gfn_type(d, gfn_x(g), t, P2M_ALLOC)
> -#undef get_gfn_query
> -#define get_gfn_query(d, g, t) get_gfn_type(d, gfn_x(g), t, 0)
> -#undef put_gfn
> -#define put_gfn(d, g) __put_gfn(p2m_get_hostp2m(d), gfn_x(g))
> -
>  #define IOMMU_MMIO_SIZE                         0x8000
>  #define IOMMU_MMIO_PAGE_NR                      0x8
>  #define RING_BF_LENGTH_MASK                     0x0F000000
> diff --git a/xen/include/asm-x86/guest_pt.h b/xen/include/asm-
> x86/guest_pt.h
> index 8684b83..87c6815 100644
> --- a/xen/include/asm-x86/guest_pt.h
> +++ b/xen/include/asm-x86/guest_pt.h
> @@ -38,10 +38,6 @@ gfn_to_paddr(gfn_t gfn)
>      return ((paddr_t)gfn_x(gfn)) << PAGE_SHIFT;
>  }
> 
> -/* Override get_gfn to work with gfn_t */
> -#undef get_gfn
> -#define get_gfn(d, g, t) get_gfn_type((d), gfn_x(g), (t), P2M_ALLOC)
> -
>  /* Mask covering the reserved bits from superpage alignment. */
>  #define SUPERPAGE_RSVD(bit)                                             \
>      (((1ul << (bit)) - 1) & ~(_PAGE_PSE_PAT | (_PAGE_PSE_PAT - 1ul)))
> diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h
> index 8bd6f64..e332f06 100644
> --- a/xen/include/asm-x86/p2m.h
> +++ b/xen/include/asm-x86/p2m.h
> @@ -431,7 +431,7 @@ void p2m_unlock_and_tlb_flush(struct p2m_domain *p2m);
>   * put_gfn. ****/
> 
>  mfn_t __nonnull(3, 4) __get_gfn_type_access(
> -    struct p2m_domain *p2m, unsigned long gfn, p2m_type_t *t,
> +    struct p2m_domain *p2m, gfn_t gfn, p2m_type_t *t,
>      p2m_access_t *a, p2m_query_t q, unsigned int *page_order, bool_t
> locked);
> 
>  /*
> @@ -444,7 +444,7 @@ mfn_t __nonnull(3, 4) __get_gfn_type_access(
>   * the entry was found in.
>   */
>  static inline mfn_t __nonnull(3, 4) get_gfn_type_access(
> -    struct p2m_domain *p2m, unsigned long gfn, p2m_type_t *t,
> +    struct p2m_domain *p2m, gfn_t gfn, p2m_type_t *t,
>      p2m_access_t *a, p2m_query_t q, unsigned int *page_order)
>  {
>      return __get_gfn_type_access(p2m, gfn, t, a, q, page_order, true);
> @@ -452,22 +452,21 @@ static inline mfn_t __nonnull(3, 4)
> get_gfn_type_access(
> 
>  /* General conversion function from gfn to mfn */
>  static inline mfn_t __nonnull(3) get_gfn_type(
> -    struct domain *d, unsigned long gfn, p2m_type_t *t, p2m_query_t q)
> +    struct domain *d, gfn_t gfn, p2m_type_t *t, p2m_query_t q)
>  {
>      p2m_access_t a;
>      return get_gfn_type_access(p2m_get_hostp2m(d), gfn, t, &a, q, NULL);
>  }
> 
>  /* Syntactic sugar: most callers will use one of these. */
> -#define get_gfn(d, g, t)         get_gfn_type((d), (g), (t), P2M_ALLOC)
> -#define get_gfn_query(d, g, t)   get_gfn_type((d), (g), (t), 0)
> -#define get_gfn_unshare(d, g, t) get_gfn_type((d), (g), (t), \
> -                                              P2M_ALLOC | P2M_UNSHARE)
> +#define get_gfn(d, g, t)         get_gfn_type(d, g, t, P2M_ALLOC)
> +#define get_gfn_query(d, g, t)   get_gfn_type(d, g, t, 0)
> +#define get_gfn_unshare(d, g, t) get_gfn_type(d, g, t, P2M_ALLOC |
> P2M_UNSHARE)
> 
>  /* Will release the p2m_lock for this gfn entry. */
> -void __put_gfn(struct p2m_domain *p2m, unsigned long gfn);
> +void __put_gfn(struct p2m_domain *p2m, gfn_t gfn);
> 
> -#define put_gfn(d, gfn) __put_gfn(p2m_get_hostp2m((d)), (gfn))
> +#define put_gfn(d, g) __put_gfn(p2m_get_hostp2m(d), g)
> 
>  /*
>   * The intent of the "unlocked" accessor is to have the caller not worry
> about
> @@ -484,9 +483,8 @@ void __put_gfn(struct p2m_domain *p2m, unsigned long
> gfn);
>   * Any other type of query can cause a change in the p2m and may need to
>   * perform locking.
>   */
> -static inline mfn_t get_gfn_query_unlocked(struct domain *d,
> -                                           unsigned long gfn,
> -                                           p2m_type_t *t)
> +static inline mfn_t get_gfn_query_unlocked(
> +    struct domain *d, gfn_t gfn, p2m_type_t *t)
>  {
>      p2m_access_t a;
>      return __get_gfn_type_access(p2m_get_hostp2m(d), gfn, t, &a, 0, NULL,
> 0);
> @@ -569,9 +567,9 @@ do {
> \
> 
>      /* Now do the gets */
>      *first_mfn  = get_gfn_type_access(p2m_get_hostp2m(rval-
> >first_domain),
> -                                      gfn_x(rval->first_gfn), first_t,
> first_a, q, NULL);
> +                                      rval->first_gfn, first_t, first_a,
> q, NULL);
>      *second_mfn = get_gfn_type_access(p2m_get_hostp2m(rval-
> >second_domain),
> -                                      gfn_x(rval->second_gfn), second_t,
> second_a, q, NULL);
> +                                      rval->second_gfn, second_t,
> second_a, q, NULL);
>  }
> 
>  static inline void put_two_gfns(struct two_gfns *arg)
> @@ -579,8 +577,8 @@ static inline void put_two_gfns(struct two_gfns *arg)
>      if ( !arg )
>          return;
> 
> -    put_gfn(arg->second_domain, gfn_x(arg->second_gfn));
> -    put_gfn(arg->first_domain,  gfn_x(arg->first_gfn));
> +    put_gfn(arg->second_domain, arg->second_gfn);
> +    put_gfn(arg->first_domain,  arg->first_gfn);
>  }
> 
>  /* Init the datastructures for later use by the p2m code */
> --
> 2.1.4

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 02/14] x86/mem-sharing: Don't leave the altp2m lock held when nominating a page
  2018-11-21 13:21 ` [PATCH 02/14] x86/mem-sharing: Don't leave the altp2m lock held when nominating a page Andrew Cooper
@ 2018-11-21 16:56   ` Tamas K Lengyel
  2018-11-22 14:46   ` Jan Beulich
  1 sibling, 0 replies; 59+ messages in thread
From: Tamas K Lengyel @ 2018-11-21 16:56 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Roger Pau Monné, Wei Liu, Jan Beulich, Xen-devel

On Wed, Nov 21, 2018 at 6:21 AM Andrew Cooper <andrew.cooper3@citrix.com> wrote:
>
> get_gfn_type_access() internally takes the p2m lock, and nothing ever unlocks
> it.  Switch to using the unlocked accessor instead.
>
> This wasn't included in XSA-277 because neither mem-sharing nor altp2m are
> supported.
>
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Acked-by: Tamas K Lengyel <tamas@tklengyel.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 09/14] x86/p2m: Switch the two_gfns infrastructure to using gfn_t
  2018-11-21 13:21 ` [PATCH 09/14] x86/p2m: Switch the two_gfns infrastructure to using gfn_t Andrew Cooper
@ 2018-11-21 17:06   ` Tamas K Lengyel
  2018-11-22 15:17   ` Jan Beulich
  1 sibling, 0 replies; 59+ messages in thread
From: Tamas K Lengyel @ 2018-11-21 17:06 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: George Dunlap, Wei Liu, Jan Beulich, Xen-devel

On Wed, Nov 21, 2018 at 6:21 AM Andrew Cooper <andrew.cooper3@citrix.com> wrote:
>
> Additionally, drop surrounding trailing whitespace.
>
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Acked-by: Tamas K Lengyel <tamas@tklengyel.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 00/14] XSA-277 followup
  2018-11-21 13:21 [PATCH 00/14] XSA-277 followup Andrew Cooper
                   ` (13 preceding siblings ...)
  2018-11-21 13:21 ` [PATCH 14/14] xen/gnttab: Minor improvements to arch header files Andrew Cooper
@ 2018-11-21 17:19 ` Tamas K Lengyel
  2018-11-21 21:22   ` Andrew Cooper
  2019-01-30 18:36 ` Pings for 4.12 " Andrew Cooper
  15 siblings, 1 reply; 59+ messages in thread
From: Tamas K Lengyel @ 2018-11-21 17:19 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Kevin Tian, Stefano Stabellini, Wei Liu, Jun Nakajima,
	Razvan Cojocaru, George Dunlap, Tim Deegan, Xen-devel,
	Julien Grall, Paul Durrant, Jan Beulich, Boris Ostrovsky,
	Brian Woods, Suravee Suthikulpanit, Roger Pau Monné

On Wed, Nov 21, 2018 at 6:21 AM Andrew Cooper <andrew.cooper3@citrix.com> wrote:
>
> This covers various fixes related to XSA-277 which weren't in security
> supported areas, and associated cleanup.
>
> The biggest issue noticed here is that altp2m's use of hardware #VE support
> will cause general memory corruption if the guest ever balloons out the VEINFO
> page.  The only safe way I think of doing this is for Xen to alloc annonymous
> domheap pages for the VEINFO, and for the guest to map them in a similar way
> to the shared info and grant table frames.

Since ballooning presents all sorts of problems when used with altp2m
I would suggest just making the two explicitly incompatible during
domain creation. Beside the info page being possibly ballooned out the
other problem is when ballooning causes altp2m views to be reset
completely, removing mem_access permissions and remapped entries.

Tamas

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 00/14] XSA-277 followup
  2018-11-21 17:19 ` [PATCH 00/14] XSA-277 followup Tamas K Lengyel
@ 2018-11-21 21:22   ` Andrew Cooper
  2018-11-21 22:42     ` Tamas K Lengyel
  2018-11-23 15:46     ` Roger Pau Monné
  0 siblings, 2 replies; 59+ messages in thread
From: Andrew Cooper @ 2018-11-21 21:22 UTC (permalink / raw)
  To: Tamas K Lengyel
  Cc: Juergen Gross, Kevin Tian, Stefano Stabellini, Wei Liu,
	Jun Nakajima, Razvan Cojocaru, George Dunlap, Tim Deegan,
	Xen-devel, Julien Grall, Paul Durrant, Jan Beulich,
	Boris Ostrovsky, Brian Woods, Suravee Suthikulpanit,
	Roger Pau Monné

On 21/11/2018 17:19, Tamas K Lengyel wrote:
> On Wed, Nov 21, 2018 at 6:21 AM Andrew Cooper <andrew.cooper3@citrix.com> wrote:
>> This covers various fixes related to XSA-277 which weren't in security
>> supported areas, and associated cleanup.
>>
>> The biggest issue noticed here is that altp2m's use of hardware #VE support
>> will cause general memory corruption if the guest ever balloons out the VEINFO
>> page.  The only safe way I think of doing this is for Xen to alloc annonymous
>> domheap pages for the VEINFO, and for the guest to map them in a similar way
>> to the shared info and grant table frames.
> Since ballooning presents all sorts of problems when used with altp2m
> I would suggest just making the two explicitly incompatible during
> domain creation. Beside the info page being possibly ballooned out the
> other problem is when ballooning causes altp2m views to be reset
> completely, removing mem_access permissions and remapped entries.

If only it were that simple.

For reasons of history and/or poor terminology, "ballooning" means two
things.

1) The act of the Toolstack interacting with the balloon driver inside a
VM, to change the current amount of RAM used by the guest.

2) XENMEM_{increase,decrease}_reservation which are the underlying
hypercalls used by guest kernels.

For the toolstack interaction side of things, this is a mess.  There is
a single xenstore key, and a blind assumption that all guests know what
changes to memory/target mean.  There is no negotiation of whether a
balloon driver is running in the guest, and if one is running, there is
no ability for the balloon driver to nack a request it can't fulfil. 
The sole feedback mechanism which exists is the toolstack looking to see
whether the domain has changed the amount of RAM it is using.

PV guests are fairly "special" by any reasonable judgement.  They are
fully aware of their memory layout , an of changes to it across
migrate.  "Ballooning" was implemented at a time when most computers had
MB of RAM rather than GB, and the knowledge a PV guest had was "I've got
a random set of MFNs which aren't currently used by anything important,
and can be handed back to Xen on request.  Xen guests also have shared
memory constructs such as the shared_info page, and grant tables.  A PV
guest gets access to these by programming the frame straight into to the
pagetables, and Xen's permission model DTRT.

Then HVM guests came along.  For reasons of trying to get things
working, they inherited a lot of same interfaces as PV guests, despite
the fundamental differences in the way they work.  One of the biggest
differences was the fact that HVM guests have their gfn=>mfn space
managed by Xen rather than themselves, and in particular, you can no
longer map shared memory structures in the PV way.

For a shared memory structure to be usable, a mapping has to be put into
the guests P2M, so the guest can create a regular pagetable entry
pointing at it.  For reasons which are beyond me, Xen doesn't have any
knowledge of the guests physical layout, and guests arbitrary mutative
capabilities on their GFN space, but with a hypercall set that has
properties such as a return value of "how many items of this batch
succeeded", and replacement properties rather than error properties when
trying to modify a GFN which already has something in it.

Whatever the reasons, it is commonplace for guests to
decrease_reservation out some RAM to create holes for the shared memory
mappings, because it is the only safe way to avoid irreparably
clobbering something else (especially if you're HVMLoader and in charge
of trying to construct the E820/ACPI tables).

tl;dr If you actually prohibit XENMEM_decrease_reservation, HVM guests
don't boot, and that's long before a balloon driver gets up and running.


Now, all of that said, there are a number of very good reasons why a
host administrator might want to prohibit the guest from having
arbitrary mutative capabilities, chief among them being to prevent the
guest from shattering host superpagpes, but also due to
incompatibilities with some of our more interesting features.

The only way I see of fixing this to teach Xen about the guests gfn
layout (as chosen by the domainbuilder), and include within that "space
which definitely doesn't have anything in, and is safe to put shared
mappings into".  Beyond that, we'll need some administrator level
knowledge of which guests are safe to have XENMEM_decrease_reservation
prohibited, or some interlocks inside Xen to disable unsafe features as
soon as we spot a guest which isn't playing by the new rules.

This probably needs some more more thought, but fundamentally, we have
to undo more than a decades worth of "doing it wrong" which has
percolated through the Xen ecosystem.

I'm half tempted to put together a big hammer bit in the domain creation
path which turns off everything like this (and other areas where we know
Xen is lacking, such as default readability/write-ignore of all MSRs),
after which we'll have a rather a more concrete baseline to discuss what
the guests are actually doing, and how to get them back into a working
state while maintaining architectural.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 00/14] XSA-277 followup
  2018-11-21 21:22   ` Andrew Cooper
@ 2018-11-21 22:42     ` Tamas K Lengyel
  2018-11-22  0:08       ` Andrew Cooper
  2018-11-23 15:46     ` Roger Pau Monné
  1 sibling, 1 reply; 59+ messages in thread
From: Tamas K Lengyel @ 2018-11-21 22:42 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: JGross, Kevin Tian, Stefano Stabellini, Wei Liu, Jun Nakajima,
	Razvan Cojocaru, George Dunlap, Tim Deegan, Xen-devel,
	Julien Grall, Paul Durrant, Jan Beulich, Boris Ostrovsky,
	Brian Woods, Suravee Suthikulpanit, Roger Pau Monné

On Wed, Nov 21, 2018 at 2:22 PM Andrew Cooper <andrew.cooper3@citrix.com> wrote:
>
> On 21/11/2018 17:19, Tamas K Lengyel wrote:
> > On Wed, Nov 21, 2018 at 6:21 AM Andrew Cooper <andrew.cooper3@citrix.com> wrote:
> >> This covers various fixes related to XSA-277 which weren't in security
> >> supported areas, and associated cleanup.
> >>
> >> The biggest issue noticed here is that altp2m's use of hardware #VE support
> >> will cause general memory corruption if the guest ever balloons out the VEINFO
> >> page.  The only safe way I think of doing this is for Xen to alloc annonymous
> >> domheap pages for the VEINFO, and for the guest to map them in a similar way
> >> to the shared info and grant table frames.
> > Since ballooning presents all sorts of problems when used with altp2m
> > I would suggest just making the two explicitly incompatible during
> > domain creation. Beside the info page being possibly ballooned out the
> > other problem is when ballooning causes altp2m views to be reset
> > completely, removing mem_access permissions and remapped entries.
>
> If only it were that simple.
>
> For reasons of history and/or poor terminology, "ballooning" means two
> things.
>
> 1) The act of the Toolstack interacting with the balloon driver inside a
> VM, to change the current amount of RAM used by the guest.
>
> 2) XENMEM_{increase,decrease}_reservation which are the underlying
> hypercalls used by guest kernels.
>
> For the toolstack interaction side of things, this is a mess.  There is
> a single xenstore key, and a blind assumption that all guests know what
> changes to memory/target mean.  There is no negotiation of whether a
> balloon driver is running in the guest, and if one is running, there is
> no ability for the balloon driver to nack a request it can't fulfil.
> The sole feedback mechanism which exists is the toolstack looking to see
> whether the domain has changed the amount of RAM it is using.
>
> PV guests are fairly "special" by any reasonable judgement.  They are
> fully aware of their memory layout , an of changes to it across
> migrate.  "Ballooning" was implemented at a time when most computers had
> MB of RAM rather than GB, and the knowledge a PV guest had was "I've got
> a random set of MFNs which aren't currently used by anything important,
> and can be handed back to Xen on request.  Xen guests also have shared
> memory constructs such as the shared_info page, and grant tables.  A PV
> guest gets access to these by programming the frame straight into to the
> pagetables, and Xen's permission model DTRT.
>
> Then HVM guests came along.  For reasons of trying to get things
> working, they inherited a lot of same interfaces as PV guests, despite
> the fundamental differences in the way they work.  One of the biggest
> differences was the fact that HVM guests have their gfn=>mfn space
> managed by Xen rather than themselves, and in particular, you can no
> longer map shared memory structures in the PV way.
>
> For a shared memory structure to be usable, a mapping has to be put into
> the guests P2M, so the guest can create a regular pagetable entry
> pointing at it.  For reasons which are beyond me, Xen doesn't have any
> knowledge of the guests physical layout, and guests arbitrary mutative
> capabilities on their GFN space, but with a hypercall set that has
> properties such as a return value of "how many items of this batch
> succeeded", and replacement properties rather than error properties when
> trying to modify a GFN which already has something in it.
>
> Whatever the reasons, it is commonplace for guests to
> decrease_reservation out some RAM to create holes for the shared memory
> mappings, because it is the only safe way to avoid irreparably
> clobbering something else (especially if you're HVMLoader and in charge
> of trying to construct the E820/ACPI tables).
>
> tl;dr If you actually prohibit XENMEM_decrease_reservation, HVM guests
> don't boot, and that's long before a balloon driver gets up and running.

Thanks for the detailed write-up. This explains why I could never get
altp2m working from domain start, no matter where in the startup logic
of the toolstack I placed the altp2m activation (had to resort to
activating altp2m settings only after I detect the guest OS is fully
booted and things have settled down).

>
> Now, all of that said, there are a number of very good reasons why a
> host administrator might want to prohibit the guest from having
> arbitrary mutative capabilities, chief among them being to prevent the
> guest from shattering host superpagpes, but also due to
> incompatibilities with some of our more interesting features.
>
> The only way I see of fixing this to teach Xen about the guests gfn
> layout (as chosen by the domainbuilder), and include within that "space
> which definitely doesn't have anything in, and is safe to put shared
> mappings into".

Yes, that would be great - especially if this was something we could
query from the toolstack too. Right now we resorted to parsing the
E820 map as it shows up in the domain creation logs and whatever
xc_domain_maximum_gpfn returns to get some idea of what memory layout
looks like in the guest and where the holes are, but there is still a
lot of guessing involved.

> Beyond that, we'll need some administrator level
> knowledge of which guests are safe to have XENMEM_decrease_reservation
> prohibited, or some interlocks inside Xen to disable unsafe features as
> soon as we spot a guest which isn't playing by the new rules.
>
> This probably needs some more more thought, but fundamentally, we have
> to undo more than a decades worth of "doing it wrong" which has
> percolated through the Xen ecosystem.
>
> I'm half tempted to put together a big hammer bit in the domain creation
> path which turns off everything like this (and other areas where we know
> Xen is lacking, such as default readability/write-ignore of all MSRs),
> after which we'll have a rather a more concrete baseline to discuss what
> the guests are actually doing, and how to get them back into a working
> state while maintaining architectural.
>

+1, bringing some sanity to this (and documentation) would be of great
value! I would be very interested in this line of work and happy to
help however I can.

Cheers,
Tamas

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 00/14] XSA-277 followup
  2018-11-21 22:42     ` Tamas K Lengyel
@ 2018-11-22  0:08       ` Andrew Cooper
  2018-11-26 17:48         ` Tamas K Lengyel
  0 siblings, 1 reply; 59+ messages in thread
From: Andrew Cooper @ 2018-11-22  0:08 UTC (permalink / raw)
  To: Tamas K Lengyel
  Cc: JGross, Kevin Tian, Stefano Stabellini, Wei Liu, Jun Nakajima,
	Razvan Cojocaru, George Dunlap, Tim Deegan, Xen-devel,
	Julien Grall, Paul Durrant, Jan Beulich, Boris Ostrovsky,
	Brian Woods, Suravee Suthikulpanit, Roger Pau Monné

On 21/11/2018 22:42, Tamas K Lengyel wrote:
> On Wed, Nov 21, 2018 at 2:22 PM Andrew Cooper <andrew.cooper3@citrix.com> wrote:
>> On 21/11/2018 17:19, Tamas K Lengyel wrote:
>>> On Wed, Nov 21, 2018 at 6:21 AM Andrew Cooper <andrew.cooper3@citrix.com> wrote:
>>>> This covers various fixes related to XSA-277 which weren't in security
>>>> supported areas, and associated cleanup.
>>>>
>>>> The biggest issue noticed here is that altp2m's use of hardware #VE support
>>>> will cause general memory corruption if the guest ever balloons out the VEINFO
>>>> page.  The only safe way I think of doing this is for Xen to alloc annonymous
>>>> domheap pages for the VEINFO, and for the guest to map them in a similar way
>>>> to the shared info and grant table frames.
>>> Since ballooning presents all sorts of problems when used with altp2m
>>> I would suggest just making the two explicitly incompatible during
>>> domain creation. Beside the info page being possibly ballooned out the
>>> other problem is when ballooning causes altp2m views to be reset
>>> completely, removing mem_access permissions and remapped entries.
>> If only it were that simple.
>>
>> For reasons of history and/or poor terminology, "ballooning" means two
>> things.
>>
>> 1) The act of the Toolstack interacting with the balloon driver inside a
>> VM, to change the current amount of RAM used by the guest.
>>
>> 2) XENMEM_{increase,decrease}_reservation which are the underlying
>> hypercalls used by guest kernels.
>>
>> For the toolstack interaction side of things, this is a mess.  There is
>> a single xenstore key, and a blind assumption that all guests know what
>> changes to memory/target mean.  There is no negotiation of whether a
>> balloon driver is running in the guest, and if one is running, there is
>> no ability for the balloon driver to nack a request it can't fulfil.
>> The sole feedback mechanism which exists is the toolstack looking to see
>> whether the domain has changed the amount of RAM it is using.
>>
>> PV guests are fairly "special" by any reasonable judgement.  They are
>> fully aware of their memory layout , an of changes to it across
>> migrate.  "Ballooning" was implemented at a time when most computers had
>> MB of RAM rather than GB, and the knowledge a PV guest had was "I've got
>> a random set of MFNs which aren't currently used by anything important,
>> and can be handed back to Xen on request.  Xen guests also have shared
>> memory constructs such as the shared_info page, and grant tables.  A PV
>> guest gets access to these by programming the frame straight into to the
>> pagetables, and Xen's permission model DTRT.
>>
>> Then HVM guests came along.  For reasons of trying to get things
>> working, they inherited a lot of same interfaces as PV guests, despite
>> the fundamental differences in the way they work.  One of the biggest
>> differences was the fact that HVM guests have their gfn=>mfn space
>> managed by Xen rather than themselves, and in particular, you can no
>> longer map shared memory structures in the PV way.
>>
>> For a shared memory structure to be usable, a mapping has to be put into
>> the guests P2M, so the guest can create a regular pagetable entry
>> pointing at it.  For reasons which are beyond me, Xen doesn't have any
>> knowledge of the guests physical layout, and guests arbitrary mutative
>> capabilities on their GFN space, but with a hypercall set that has
>> properties such as a return value of "how many items of this batch
>> succeeded", and replacement properties rather than error properties when
>> trying to modify a GFN which already has something in it.
>>
>> Whatever the reasons, it is commonplace for guests to
>> decrease_reservation out some RAM to create holes for the shared memory
>> mappings, because it is the only safe way to avoid irreparably
>> clobbering something else (especially if you're HVMLoader and in charge
>> of trying to construct the E820/ACPI tables).
>>
>> tl;dr If you actually prohibit XENMEM_decrease_reservation, HVM guests
>> don't boot, and that's long before a balloon driver gets up and running.
> Thanks for the detailed write-up. This explains why I could never get
> altp2m working from domain start, no matter where in the startup logic
> of the toolstack I placed the altp2m activation (had to resort to
> activating altp2m settings only after I detect the guest OS is fully
> booted and things have settled down).

So, in theory it should all work, even from the start.

In practice, the implementation quality of altp2m leaves a lot to be
desired, and it was designed to have the "all logic inside the guest"
model, which in practice means that it only ever started once the guest
had come up sufficiently.

Do you recall more specifically where you tried inserting startup
logic?  It sounds like something which wants fixing, irrespective of the
other concerns here.

>
>> Now, all of that said, there are a number of very good reasons why a
>> host administrator might want to prohibit the guest from having
>> arbitrary mutative capabilities, chief among them being to prevent the
>> guest from shattering host superpagpes, but also due to
>> incompatibilities with some of our more interesting features.
>>
>> The only way I see of fixing this to teach Xen about the guests gfn
>> layout (as chosen by the domainbuilder), and include within that "space
>> which definitely doesn't have anything in, and is safe to put shared
>> mappings into".
> Yes, that would be great - especially if this was something we could
> query from the toolstack too. Right now we resorted to parsing the
> E820 map as it shows up in the domain creation logs and whatever
> xc_domain_maximum_gpfn returns to get some idea of what memory layout
> looks like in the guest and where the holes are, but there is still a
> lot of guessing involved.

Eww :(

So, we've got a number of issues which need addressing.  For a start,
there isn't a clear understanding of how much RAM a guest has, and
previous attempts to resolve this have only succeeded in demonstrating
that the core maintainers can't even agree on what it means, let alone
how to calculate it.  Things get especially complicates with VRAM and
ROMs, and the overall answer is some mix of information in Xen,
xenstore, qemu and the guest.

In reality, whomever actually does the legwork to resolve the problems
will get to define the terms, and how they get calculated.

Ultimately, it is the domain builder which knows all the pertinent
details, and is in a position to operate on them - it is already
responsible for doing the initial memory layout calculations, and
stashing an E820 table in the hypervisor (see XENMEM_{,set_}memory_map).

The main problem we have is that we need more types than exist in the
E820 spec, so my plan is to have the domain builder construct an
E820-like table with Xen-defined types and pass that to the
hypervisors.  It shall be the single and authoritative source of guest
physmap information, and will most likely be immutable once the guest
has started.

From this, we can trivially derive a real E820, but we can also fix
other problems such as Xen not actually knowing where MMIO holes are. 
It would be lovely if we could reject emulation attempts if they occur
in unexpected locations, as an attack surface reduction action.  Also,
we'd at least be able to restrict a guests ballooning operations to be
within prescribed RAM regions.

>
>> Beyond that, we'll need some administrator level
>> knowledge of which guests are safe to have XENMEM_decrease_reservation
>> prohibited, or some interlocks inside Xen to disable unsafe features as
>> soon as we spot a guest which isn't playing by the new rules.
>>
>> This probably needs some more more thought, but fundamentally, we have
>> to undo more than a decades worth of "doing it wrong" which has
>> percolated through the Xen ecosystem.
>>
>> I'm half tempted to put together a big hammer bit in the domain creation
>> path which turns off everything like this (and other areas where we know
>> Xen is lacking, such as default readability/write-ignore of all MSRs),
>> after which we'll have a rather a more concrete baseline to discuss what
>> the guests are actually doing, and how to get them back into a working
>> state while maintaining architectural.
>>
> +1, bringing some sanity to this (and documentation) would be of great
> value! I would be very interested in this line of work and happy to
> help however I can.

I need to find some copious free time :)

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 08/14] xen/memory: Drop ARM put_gfn() stub
  2018-11-21 13:21 ` [PATCH 08/14] xen/memory: Drop ARM put_gfn() stub Andrew Cooper
@ 2018-11-22 14:07   ` Julien Grall
  2018-11-22 15:15   ` Jan Beulich
  1 sibling, 0 replies; 59+ messages in thread
From: Julien Grall @ 2018-11-22 14:07 UTC (permalink / raw)
  To: Andrew Cooper, Xen-devel
  Cc: Stefano Stabellini, Wei Liu, Jan Beulich, Roger Pau Monné

Hi Andrew,

On 11/21/18 1:21 PM, Andrew Cooper wrote:
> On x86, get_gfn_*() and put_gfn() are reference counting pairs.  All the
> get_gfn_*() functions are called from within CONFIG_X86 sections, but
> put_gfn() is stubbed out on ARM.
> 
> As a result, the common code reads as if ARM is dropping references it never
> acquired.
> 
> Put all put_gfn() calls in common code inside CONFIG_X86 to make the code
> properly balanced, and drop the ARM stub.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Acked-by: Julien Grall <julien.grall@arm.com>

Cheers,

> ---
> CC: Stefano Stabellini <sstabellini@kernel.org>
> CC: Julien Grall <julien.grall@arm.com>
> CC: Jan Beulich <JBeulich@suse.com>
> CC: Wei Liu <wei.liu2@citrix.com>
> CC: Roger Pau Monné <roger.pau@citrix.com>
> ---
>   xen/common/grant_table.c |  8 ++++++++
>   xen/common/memory.c      | 15 ++++++++++++++-
>   xen/include/asm-arm/mm.h |  2 --
>   3 files changed, 22 insertions(+), 3 deletions(-)
> 
> diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
> index fc41b65..f7860f6 100644
> --- a/xen/common/grant_table.c
> +++ b/xen/common/grant_table.c
> @@ -2110,7 +2110,9 @@ gnttab_transfer(
>           /* Check the passed page frame for basic validity. */
>           if ( unlikely(!mfn_valid(mfn)) )
>           {
> +#ifdef CONFIG_X86
>               put_gfn(d, gop.mfn);
> +#endif
>               gdprintk(XENLOG_INFO, "out-of-range %lx\n", (unsigned long)gop.mfn);
>               gop.status = GNTST_bad_page;
>               goto copyback;
> @@ -2119,7 +2121,9 @@ gnttab_transfer(
>           page = mfn_to_page(mfn);
>           if ( (rc = steal_page(d, page, 0)) < 0 )
>           {
> +#ifdef CONFIG_X86
>               put_gfn(d, gop.mfn);
> +#endif
>               gop.status = rc == -EINVAL ? GNTST_bad_page : GNTST_general_error;
>               goto copyback;
>           }
> @@ -2149,7 +2153,9 @@ gnttab_transfer(
>           unlock_and_copyback:
>               rcu_unlock_domain(e);
>           put_gfn_and_copyback:
> +#ifdef CONFIG_X86
>               put_gfn(d, gop.mfn);
> +#endif
>               page->count_info &= ~(PGC_count_mask|PGC_allocated);
>               free_domheap_page(page);
>               goto copyback;
> @@ -2236,7 +2242,9 @@ gnttab_transfer(
>           page_set_owner(page, e);
>   
>           spin_unlock(&e->page_alloc_lock);
> +#ifdef CONFIG_X86
>           put_gfn(d, gop.mfn);
> +#endif
>   
>           TRACE_1D(TRC_MEM_PAGE_GRANT_TRANSFER, e->domain_id);
>   
> diff --git a/xen/common/memory.c b/xen/common/memory.c
> index 58194b9..175bd62 100644
> --- a/xen/common/memory.c
> +++ b/xen/common/memory.c
> @@ -358,7 +358,9 @@ int guest_remove_page(struct domain *d, unsigned long gmfn)
>   #endif
>       if ( unlikely(!mfn_valid(mfn)) )
>       {
> +#ifdef CONFIG_X86
>           put_gfn(d, gmfn);
> +#endif
>           gdprintk(XENLOG_INFO, "Domain %u page number %lx invalid\n",
>                   d->domain_id, gmfn);
>   
> @@ -388,7 +390,9 @@ int guest_remove_page(struct domain *d, unsigned long gmfn)
>       page = mfn_to_page(mfn);
>       if ( unlikely(!get_page(page, d)) )
>       {
> +#ifdef CONFIG_X86
>           put_gfn(d, gmfn);
> +#endif
>           gdprintk(XENLOG_INFO, "Bad page free for domain %u\n", d->domain_id);
>   
>           return -ENXIO;
> @@ -409,8 +413,11 @@ int guest_remove_page(struct domain *d, unsigned long gmfn)
>           put_page(page);
>   
>       put_page(page);
> - out_put_gfn: __maybe_unused;
> +
> +#ifdef CONFIG_X86
> + out_put_gfn:
>       put_gfn(d, gmfn);
> +#endif
>   
>       /*
>        * Filter out -ENOENT return values that aren't a result of an empty p2m
> @@ -656,7 +663,9 @@ static long memory_exchange(XEN_GUEST_HANDLE_PARAM(xen_memory_exchange_t) arg)
>   #endif
>                   if ( unlikely(!mfn_valid(mfn)) )
>                   {
> +#ifdef CONFIG_X86
>                       put_gfn(d, gmfn + k);
> +#endif
>                       rc = -EINVAL;
>                       goto fail;
>                   }
> @@ -666,12 +675,16 @@ static long memory_exchange(XEN_GUEST_HANDLE_PARAM(xen_memory_exchange_t) arg)
>                   rc = steal_page(d, page, MEMF_no_refcount);
>                   if ( unlikely(rc) )
>                   {
> +#ifdef CONFIG_X86
>                       put_gfn(d, gmfn + k);
> +#endif
>                       goto fail;
>                   }
>   
>                   page_list_add(page, &in_chunk_list);
> +#ifdef CONFIG_X86
>                   put_gfn(d, gmfn + k);
> +#endif
>               }
>           }
>   
> diff --git a/xen/include/asm-arm/mm.h b/xen/include/asm-arm/mm.h
> index 940b74b..b2f6104 100644
> --- a/xen/include/asm-arm/mm.h
> +++ b/xen/include/asm-arm/mm.h
> @@ -313,8 +313,6 @@ static inline void *page_to_virt(const struct page_info *pg)
>   struct page_info *get_page_from_gva(struct vcpu *v, vaddr_t va,
>                                       unsigned long flags);
>   
> -static inline void put_gfn(struct domain *d, unsigned long gfn) {}
> -
>   /*
>    * Arm does not have an M2P, but common code expects a handful of
>    * M2P-related defines and functions. Provide dummy versions of these.
> 

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 11/14] xen/mm: Switch mfn_to_virt()/virt_to_mfn() to using mfn_t
  2018-11-21 13:21 ` [PATCH 11/14] xen/mm: Switch mfn_to_virt()/virt_to_mfn() to using mfn_t Andrew Cooper
@ 2018-11-22 14:32   ` Julien Grall
  2018-11-22 15:44   ` Jan Beulich
  1 sibling, 0 replies; 59+ messages in thread
From: Julien Grall @ 2018-11-22 14:32 UTC (permalink / raw)
  To: Andrew Cooper, Xen-devel
  Cc: Stefano Stabellini, Wei Liu, Jan Beulich, Roger Pau Monné

Hi Andrew,

On 11/21/18 1:21 PM, Andrew Cooper wrote:
> Seemingly, a majority of users either override the helpers anyway, or have an
> mfn_t in their hands.
> 
> Update the API, and adjust all users to match.  In some places, use the
> unsigned long variant in places where we are interacting with an external
> struct and there is no chance of them switching to mfn_t.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

ARM & common code:

Reviewed-by: Julien Grall <julien.grall@arm.com>

Cheers,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 12/14] xen/gnttab: Drop gnttab_create_{shared, status}_page()
  2018-11-21 13:21 ` [PATCH 12/14] xen/gnttab: Drop gnttab_create_{shared, status}_page() Andrew Cooper
@ 2018-11-22 14:35   ` Julien Grall
  2018-11-22 15:47   ` Jan Beulich
  1 sibling, 0 replies; 59+ messages in thread
From: Julien Grall @ 2018-11-22 14:35 UTC (permalink / raw)
  To: Andrew Cooper, Xen-devel
  Cc: Stefano Stabellini, Wei Liu, Jan Beulich, Roger Pau Monné

Hi Andrew,

On 11/21/18 1:21 PM, Andrew Cooper wrote:
> share_xen_page_with_guest() is a common API.  Use it directly rather than
> wrapping it with unnecessary boilerplate.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Acked-by: Julien Grall <julien.grall@arm.com>

Cheers,

> ---
> CC: Jan Beulich <JBeulich@suse.com>
> CC: Wei Liu <wei.liu2@citrix.com>
> CC: Roger Pau Monné <roger.pau@citrix.com>
> CC: Stefano Stabellini <sstabellini@kernel.org>
> CC: Julien Grall <julien.grall@arm.com>
> ---
>   xen/common/grant_table.c          |  7 ++++---
>   xen/include/asm-arm/grant_table.h | 12 ------------
>   xen/include/asm-x86/grant_table.h | 13 -------------
>   3 files changed, 4 insertions(+), 28 deletions(-)
> 
> diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
> index 6fc26cf..d5a1a00 100644
> --- a/xen/common/grant_table.c
> +++ b/xen/common/grant_table.c
> @@ -1635,7 +1635,7 @@ gnttab_populate_status_frames(struct domain *d, struct grant_table *gt,
>       }
>       /* Share the new status frames with the recipient domain */
>       for ( i = nr_status_frames(gt); i < req_status_frames; i++ )
> -        gnttab_create_status_page(d, gt, i);
> +        share_xen_page_with_guest(virt_to_page(gt->status[i]), d, SHARE_rw);
>   
>       gt->nr_status_frames = req_status_frames;
>   
> @@ -1702,7 +1702,8 @@ gnttab_unpopulate_status_frames(struct domain *d, struct grant_table *gt)
>                   if ( get_page(pg, d) )
>                       set_bit(_PGC_allocated, &pg->count_info);
>                   while ( i-- )
> -                    gnttab_create_status_page(d, gt, i);
> +                    share_xen_page_with_guest(virt_to_page(gt->status[i]),
> +                                              d, SHARE_rw);
>               }
>               return -EBUSY;
>           }
> @@ -1773,7 +1774,7 @@ gnttab_grow_table(struct domain *d, unsigned int req_nr_frames)
>   
>       /* Share the new shared frames with the recipient domain */
>       for ( i = nr_grant_frames(gt); i < req_nr_frames; i++ )
> -        gnttab_create_shared_page(d, gt, i);
> +        share_xen_page_with_guest(virt_to_page(gt->shared_raw[i]), d, SHARE_rw);
>       gt->nr_grant_frames = req_nr_frames;
>   
>       return 0;
> diff --git a/xen/include/asm-arm/grant_table.h b/xen/include/asm-arm/grant_table.h
> index 37415b7..816e3c6 100644
> --- a/xen/include/asm-arm/grant_table.h
> +++ b/xen/include/asm-arm/grant_table.h
> @@ -71,18 +71,6 @@ void gnttab_mark_dirty(struct domain *d, mfn_t mfn);
>                : gnttab_shared_gmfn(NULL, gt, idx));                       \
>   })
>   
> -#define gnttab_create_shared_page(d, t, i)                               \
> -    do {                                                                 \
> -        share_xen_page_with_guest(                                       \
> -            virt_to_page((char *)(t)->shared_raw[i]), d, SHARE_rw);      \
> -    } while ( 0 )
> -
> -#define gnttab_create_status_page(d, t, i)                               \
> -    do {                                                                 \
> -        share_xen_page_with_guest(                                       \
> -            virt_to_page((char *)(t)->status[i]), d, SHARE_rw);          \
> -    } while ( 0 )
> -
>   #define gnttab_shared_gmfn(d, t, i)                                      \
>       gfn_x(((i) >= nr_grant_frames(t)) ? INVALID_GFN : (t)->arch.shared_gfn[i])
>   
> diff --git a/xen/include/asm-x86/grant_table.h b/xen/include/asm-x86/grant_table.h
> index 1e6a988..4b8c4f9 100644
> --- a/xen/include/asm-x86/grant_table.h
> +++ b/xen/include/asm-x86/grant_table.h
> @@ -49,19 +49,6 @@ static inline int replace_grant_host_mapping(uint64_t addr, mfn_t frame,
>       VALID_M2P(gpfn_) ? _gfn(gpfn_) : INVALID_GFN;                        \
>   })
>   
> -#define gnttab_create_shared_page(d, t, i)                               \
> -    do {                                                                 \
> -        share_xen_page_with_guest(                                       \
> -            virt_to_page((char *)(t)->shared_raw[i]), d, SHARE_rw);      \
> -    } while ( 0 )
> -
> -#define gnttab_create_status_page(d, t, i)                               \
> -    do {                                                                 \
> -        share_xen_page_with_guest(                                       \
> -            virt_to_page((char *)(t)->status[i]), d, SHARE_rw);          \
> -    } while ( 0 )
> -
> -
>   #define gnttab_shared_mfn(t, i)                         \
>       ((virt_to_maddr((t)->shared_raw[i]) >> PAGE_SHIFT))
>   
> 

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 13/14] xen/gnttab: Simplify gnttab_map_frame()
  2018-11-21 13:21 ` [PATCH 13/14] xen/gnttab: Simplify gnttab_map_frame() Andrew Cooper
@ 2018-11-22 14:36   ` Julien Grall
  2018-11-22 15:48   ` Jan Beulich
  1 sibling, 0 replies; 59+ messages in thread
From: Julien Grall @ 2018-11-22 14:36 UTC (permalink / raw)
  To: Andrew Cooper, Xen-devel
  Cc: Stefano Stabellini, Wei Liu, Jan Beulich, Roger Pau Monné

Hi Andrew,

On 11/21/18 1:21 PM, Andrew Cooper wrote:
>   * Reflow some lines to remove unnecessary line breaks.
>   * Factor out the gnttab_get_frame_gfn() calculation.  Neither x86 nor ARM
>     builds seem to be able to fold the two calls, and the resulting code is far
>     easier to follow.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Reviewed-by: Julien Grall <julien.grall@arm.com>

Cheers,

> ---
> CC: Jan Beulich <JBeulich@suse.com>
> CC: Wei Liu <wei.liu2@citrix.com>
> CC: Roger Pau Monné <roger.pau@citrix.com>
> CC: Stefano Stabellini <sstabellini@kernel.org>
> CC: Julien Grall <julien.grall@arm.com>
> ---
>   xen/common/grant_table.c | 17 +++++++++--------
>   1 file changed, 9 insertions(+), 8 deletions(-)
> 
> diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
> index d5a1a00..f00eba9 100644
> --- a/xen/common/grant_table.c
> +++ b/xen/common/grant_table.c
> @@ -3869,8 +3869,7 @@ static int gnttab_get_shared_frame_mfn(struct domain *d,
>       return 0;
>   }
>   
> -int gnttab_map_frame(struct domain *d, unsigned long idx, gfn_t gfn,
> -                     mfn_t *mfn)
> +int gnttab_map_frame(struct domain *d, unsigned long idx, gfn_t gfn, mfn_t *mfn)
>   {
>       int rc = 0;
>       struct grant_table *gt = d->grant_table;
> @@ -3878,8 +3877,7 @@ int gnttab_map_frame(struct domain *d, unsigned long idx, gfn_t gfn,
>   
>       grant_write_lock(gt);
>   
> -    if ( gt->gt_version == 2 &&
> -         (idx & XENMAPIDX_grant_table_status) )
> +    if ( gt->gt_version == 2 && (idx & XENMAPIDX_grant_table_status) )
>       {
>           idx &= ~XENMAPIDX_grant_table_status;
>           status = true;
> @@ -3889,10 +3887,13 @@ int gnttab_map_frame(struct domain *d, unsigned long idx, gfn_t gfn,
>       else
>           rc = gnttab_get_shared_frame_mfn(d, idx, mfn);
>   
> -    if ( !rc && paging_mode_translate(d) &&
> -         !gfn_eq(gnttab_get_frame_gfn(gt, status, idx), INVALID_GFN) )
> -        rc = guest_physmap_remove_page(d, gnttab_get_frame_gfn(gt, status, idx),
> -                                       *mfn, 0);
> +    if ( !rc && paging_mode_translate(d) )
> +    {
> +        gfn_t gfn = gnttab_get_frame_gfn(gt, status, idx);
> +
> +        if ( !gfn_eq(gfn, INVALID_GFN) )
> +            rc = guest_physmap_remove_page(d, gfn, *mfn, 0);
> +    }
>   
>       if ( !rc )
>           gnttab_set_frame_gfn(gt, status, idx, gfn);
> 

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 01/14] x86/soft-reset: Drop gfn reference after calling get_gfn_query()
  2018-11-21 13:21 ` [PATCH 01/14] x86/soft-reset: Drop gfn reference after calling get_gfn_query() Andrew Cooper
@ 2018-11-22 14:45   ` Jan Beulich
  0 siblings, 0 replies; 59+ messages in thread
From: Jan Beulich @ 2018-11-22 14:45 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Xen-devel, Wei Liu, Roger Pau Monne

>>> On 21.11.18 at 14:21, <andrew.cooper3@citrix.com> wrote:
> get_gfn_query() internally takes the p2m lock, and this error path leaves it
> locked.
> 
> This wasn't included in XSA-277 because the error path can only be triggered
> by a carefully timed phymap operation concurrent with the domain being paused
> and the toolstack issuing DOMCTL_soft_reset.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

You could have retained my
Reviewed-by: Jan Beulich <jbeulich@suse.com>
from when this was still part of the XSA-277 patch itself.

Jan



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 02/14] x86/mem-sharing: Don't leave the altp2m lock held when nominating a page
  2018-11-21 13:21 ` [PATCH 02/14] x86/mem-sharing: Don't leave the altp2m lock held when nominating a page Andrew Cooper
  2018-11-21 16:56   ` Tamas K Lengyel
@ 2018-11-22 14:46   ` Jan Beulich
  1 sibling, 0 replies; 59+ messages in thread
From: Jan Beulich @ 2018-11-22 14:46 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Xen-devel, Wei Liu, Tamas K Lengyel, Roger Pau Monne

>>> On 21.11.18 at 14:21, <andrew.cooper3@citrix.com> wrote:
> get_gfn_type_access() internally takes the p2m lock, and nothing ever unlocks
> it.  Switch to using the unlocked accessor instead.
> 
> This wasn't included in XSA-277 because neither mem-sharing nor altp2m are
> supported.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Same here:
Reviewed-by: Jan Beulich <jbeulich@suse.com>
was effectively already given.

Jan



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 03/14] AMD/IOMMU: Fix multiple reference counting errors
  2018-11-21 13:21 ` [PATCH 03/14] AMD/IOMMU: Fix multiple reference counting errors Andrew Cooper
@ 2018-11-22 14:51   ` Jan Beulich
  2018-11-22 17:46     ` Andrew Cooper
  2019-01-31 15:59   ` Woods, Brian
  1 sibling, 1 reply; 59+ messages in thread
From: Jan Beulich @ 2018-11-22 14:51 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Wei Liu, Xen-devel, Brian Woods, Suravee Suthikulpanit, Roger Pau Monne

>>> On 21.11.18 at 14:21, <andrew.cooper3@citrix.com> wrote:
> Most of these issues would be XSAs if these paths were accessible to guests.
> 
> First, override the {get,put}_gfn() helpers to use gfn_t, which was the
> original purpose of this patch.
> 
> guest_iommu_get_table_mfn() has two bugs.  First, it gets a ref on one gfn,
> and puts a ref for a different gfn.  This is only a latent bug for now, as we
> don't do per-gfn locking yet.  Next, the mfn return value is unsafe to use
> after put_gfn() is called, as the guest could have freed the page in the
> meantime.
> 
> In addition, get_gfn_from_base_reg() erroneously asserts that base_raw can't
> be 0, but it may legitimately be.  On top of that, the return value from
> guest_iommu_get_table_mfn() is passed into map_domain_page() before checking
> that it is a real mfn.
> 
> Most of the complexity here is inlining guest_iommu_get_table_mfn() and
> holding the gfn reference until the operation is complete.
> 
> Furthermore, guest_iommu_process_command() is altered to take a local copy of
> cmd_entry_t, rather than passing a pointer to guest controlled memory into
> each of the handling functions.  It is also modified to break on error rather
> than continue.  These changes are in line with the spec which states that the
> IOMMU will strictly read a command entry once, and will cease processing if an
> error is encountered.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Looks all plausible, but I haven't looked closely enough to give
an R-b and an A-b would be meaningless. One cosmetic remark
though:


> @@ -220,12 +219,18 @@ void guest_iommu_add_ppr_log(struct domain *d, u32 entry[])
>      unmap_domain_page(log_base);
>  
>      guest_iommu_deliver_msi(d);
> +
> +out:

Please indent by at least one blank (same further down).

Jan



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 04/14] x86/p2m: Fix locking in p2m_altp2m_lazy_copy()
  2018-11-21 13:21 ` [PATCH 04/14] x86/p2m: Fix locking in p2m_altp2m_lazy_copy() Andrew Cooper
  2018-11-21 13:59   ` Razvan Cojocaru
@ 2018-11-22 15:01   ` Jan Beulich
  2018-12-05 19:53     ` Andrew Cooper
  1 sibling, 1 reply; 59+ messages in thread
From: Jan Beulich @ 2018-11-22 15:01 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Tamas K Lengyel, Wei Liu, Razvan Cojocaru, George Dunlap,
	Xen-devel, Roger Pau Monne

>>> On 21.11.18 at 14:21, <andrew.cooper3@citrix.com> wrote:
> --- a/xen/arch/x86/mm/p2m.c
> +++ b/xen/arch/x86/mm/p2m.c
> @@ -2184,24 +2184,29 @@ bool_t p2m_altp2m_lazy_copy(struct vcpu *v, paddr_t gpa,
>      unsigned long mask;
>      mfn_t mfn;
>      int rv;
> +    bool ret;
>  
>      *ap2m = p2m_get_altp2m(v);
>  
>      mfn = get_gfn_type_access(*ap2m, gfn_x(gfn), &p2mt, &p2ma,
>                                0, &page_order);
> -    __put_gfn(*ap2m, gfn_x(gfn));
>  
> +    /* Entry already present in ap2m?  Caller should handle the fault. */
>      if ( !mfn_eq(mfn, INVALID_MFN) )
> -        return 0;
> +    {
> +        ret = false;
> +        goto put_ap2m;
> +    }
>  
>      mfn = get_gfn_type_access(hp2m, gfn_x(gfn), &p2mt, &p2ma,
>                                P2M_ALLOC, &page_order);
> -    __put_gfn(hp2m, gfn_x(gfn));
>  
> +    /* Entry not present in hp2m?  Caller should handle the fault. */
>      if ( mfn_eq(mfn, INVALID_MFN) )
> -        return 0;
> -
> -    p2m_lock(*ap2m);
> +    {
> +        ret = false;
> +        goto put_hp2m;

Wouldn't this better be named "put_gfn" (or "drop_gfn" to avoid the
name collision with the function)? With this and with ...

> @@ -2222,7 +2228,14 @@ bool_t p2m_altp2m_lazy_copy(struct vcpu *v, paddr_t gpa,
>          domain_crash(hp2m->domain);
>      }
>  
> -    return 1;
> +    ret = true;
> +
> +put_hp2m:
> +    __put_gfn(hp2m, gfn_x(gfn));
> +put_ap2m:
> +    __put_gfn(*ap2m, gfn_x(gfn));

... label indentation once again corrected,
Reviewed-by: Jan Beulich <jbeulich@suse.com>

Jan



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 05/14] x86/p2m: Don't overwrite p2m_altp2m_lazy_copy()'s callers p2m pointer
  2018-11-21 13:21 ` [PATCH 05/14] x86/p2m: Don't overwrite p2m_altp2m_lazy_copy()'s callers p2m pointer Andrew Cooper
  2018-11-21 14:07   ` Razvan Cojocaru
@ 2018-11-22 15:03   ` Jan Beulich
  1 sibling, 0 replies; 59+ messages in thread
From: Jan Beulich @ 2018-11-22 15:03 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Tamas K Lengyel, Wei Liu, Razvan Cojocaru, George Dunlap,
	Xen-devel, Roger Pau Monne

>>> On 21.11.18 at 14:21, <andrew.cooper3@citrix.com> wrote:
> The final parameter to p2m_altp2m_lazy_copy() appears to be unnecessary, and
> results in very hard-to-follow code.  Have the sole caller set its local p2m
> pointer appropriately, and drop the parameter.
> 
> With that done, a level of indirection of ap2m can be dropped inside
> p2m_altp2m_lazy_copy().  While changing the API, switch it from bool_t to
> bool, and drop printing of the altp2m's virtual address, because it is of no
> use even when debugging.
> 
> No (intended) overall change in behaviour.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Reviewed-by: Jan Beulich <jbeulich@suse.com>



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 06/14] x86/hvm: Make the altp2m locking easier to follow
  2018-11-21 13:21 ` [PATCH 06/14] x86/hvm: Make the altp2m locking easier to follow Andrew Cooper
  2018-11-21 14:43   ` Razvan Cojocaru
@ 2018-11-22 15:08   ` Jan Beulich
  1 sibling, 0 replies; 59+ messages in thread
From: Jan Beulich @ 2018-11-22 15:08 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Tamas K Lengyel, Wei Liu, Razvan Cojocaru, George Dunlap,
	Xen-devel, Roger Pau Monne

>>> On 21.11.18 at 14:21, <andrew.cooper3@citrix.com> wrote:
> Drop the ap2m_active boolean, and consistently use the unlocking form:
> 
>   if ( p2m != hostp2m )
>        __put_gfn(p2m, gfn);
>   __put_gfn(hostp2m, gfn);
> 
> which makes it clear that we always unlock the altp2m's gfn if it is in use,
> and always unlock the hostp2m's gfn.  This also drops the ternary expression
> in the logdirty case.
> 
> Extend the logdirty comment to identify where the locking violation is liable
> to occur.
> 
> No (intended) overall change in behaviour.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Reviewed-by: Jan Beulich <jbeulich@suse.com>
albeit I think the title could do with some improvement: As it stands
it reads as if you do an altp2m-global change, but it's all limited to
hvm_hap_nested_page_fault().

Jan



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 07/14] x86/p2m: Coding style cleanup
  2018-11-21 13:21 ` [PATCH 07/14] x86/p2m: Coding style cleanup Andrew Cooper
@ 2018-11-22 15:12   ` Jan Beulich
  0 siblings, 0 replies; 59+ messages in thread
From: Jan Beulich @ 2018-11-22 15:12 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: George Dunlap, Xen-devel, Wei Liu, Roger Pau Monne

>>> On 21.11.18 at 14:21, <andrew.cooper3@citrix.com> wrote:
> @@ -776,7 +776,7 @@ guest_physmap_add_entry(struct domain *d, gfn_t gfn, mfn_t mfn,
>                                &a, 0, NULL, NULL);
>          if ( p2m_is_shared(ot) )
>          {
> -            /* Do an unshare to cleanly take care of all corner 
> +            /* Do an unshare to cleanly take care of all corner
>               * cases. */

Please leave a well formed comment if you already touch it in a patch
with this kind of a title. Same further down. Interestingly enough you
do so in p2m.h. With this
Reviewed-by: Jan Beulich <jbeulich@suse.com>

Jan



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 08/14] xen/memory: Drop ARM put_gfn() stub
  2018-11-21 13:21 ` [PATCH 08/14] xen/memory: Drop ARM put_gfn() stub Andrew Cooper
  2018-11-22 14:07   ` Julien Grall
@ 2018-11-22 15:15   ` Jan Beulich
  1 sibling, 0 replies; 59+ messages in thread
From: Jan Beulich @ 2018-11-22 15:15 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Julien Grall, Stefano Stabellini, Wei Liu, Xen-devel, Roger Pau Monne

>>> On 21.11.18 at 14:21, <andrew.cooper3@citrix.com> wrote:
> On x86, get_gfn_*() and put_gfn() are reference counting pairs.  All the
> get_gfn_*() functions are called from within CONFIG_X86 sections, but
> put_gfn() is stubbed out on ARM.
> 
> As a result, the common code reads as if ARM is dropping references it never
> acquired.
> 
> Put all put_gfn() calls in common code inside CONFIG_X86 to make the code
> properly balanced, and drop the ARM stub.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Reviewed-by: Jan Beulich <jbeulich@suse.com>



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 09/14] x86/p2m: Switch the two_gfns infrastructure to using gfn_t
  2018-11-21 13:21 ` [PATCH 09/14] x86/p2m: Switch the two_gfns infrastructure to using gfn_t Andrew Cooper
  2018-11-21 17:06   ` Tamas K Lengyel
@ 2018-11-22 15:17   ` Jan Beulich
  1 sibling, 0 replies; 59+ messages in thread
From: Jan Beulich @ 2018-11-22 15:17 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: George Dunlap, Tamas K Lengyel, Wei Liu, Xen-devel

>>> On 21.11.18 at 14:21, <andrew.cooper3@citrix.com> wrote:
> --- a/xen/arch/x86/mm/mem_sharing.c
> +++ b/xen/arch/x86/mm/mem_sharing.c
> @@ -901,8 +901,8 @@ static int share_pages(struct domain *sd, gfn_t sgfn, shr_handle_t sh,
>      struct two_gfns tg;
>      struct rmap_iterator ri;
>  
> -    get_two_gfns(sd, gfn_x(sgfn), &smfn_type, NULL, &smfn,
> -                 cd, gfn_x(cgfn), &cmfn_type, NULL, &cmfn,
> +    get_two_gfns(sd, sgfn, &smfn_type, NULL, &smfn,
> +                 cd, cgfn, &cmfn_type, NULL, &cmfn,
>                   0, &tg);

I guess the function invocation fits on two lines now. In any
event
Reviewed-by: Jan Beulich <jbeulich@suse.com>

Jan



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 10/14] x86/mm: Switch {get, put}_gfn() infrastructure to using gfn_t
  2018-11-21 13:21 ` [PATCH 10/14] x86/mm: Switch {get, put}_gfn() " Andrew Cooper
  2018-11-21 14:48   ` Razvan Cojocaru
  2018-11-21 16:12   ` Paul Durrant
@ 2018-11-22 15:34   ` Jan Beulich
  2018-11-23  2:58   ` Tian, Kevin
  2018-11-26 15:51   ` Woods, Brian
  4 siblings, 0 replies; 59+ messages in thread
From: Jan Beulich @ 2018-11-22 15:34 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Kevin Tian, Tamas K Lengyel, Wei Liu, Jun Nakajima,
	Razvan Cojocaru, George Dunlap, Tim Deegan, Xen-devel,
	Paul Durrant, Suravee Suthikulpanit, Boris Ostrovsky,
	Brian Woods, Roger Pau Monne

>>> On 21.11.18 at 14:21, <andrew.cooper3@citrix.com> wrote:
> --- a/xen/arch/x86/cpu/mcheck/vmce.c
> +++ b/xen/arch/x86/cpu/mcheck/vmce.c
> @@ -512,7 +512,7 @@ int fill_vmsr_data(struct mcinfo_bank *mc_bank, struct 
> domain *d,
>   * XXX following situation missed:
>   * PoD, Foreign mapped, Granted, Shared
>   */
> -int unmmap_broken_page(struct domain *d, mfn_t mfn, unsigned long gfn)
> +int unmmap_broken_page(struct domain *d, mfn_t mfn, gfn_t gfn)

Since you touch it and its caller anyway - could I talk you into dropping
the stray extra 'm' from the name at the same time?

> --- a/xen/arch/x86/hvm/vmx/vmx.c
> +++ b/xen/arch/x86/hvm/vmx/vmx.c
> @@ -2199,7 +2199,8 @@ static void vmx_vcpu_update_vmfunc_ve(struct vcpu *v)
>              p2m_type_t t;
>              mfn_t mfn;
>  
> -            mfn = get_gfn_query_unlocked(d, gfn_x(vcpu_altp2m(v).veinfo_gfn), &t);
> +            /* TODO: This is a security issue... */
> +            mfn = get_gfn_query_unlocked(d, vcpu_altp2m(v).veinfo_gfn, &t);

I think the comment could do with being slightly less vague. You
and I can see right now what the issue is, but I'm not sure I'll
remember in a year or two without having to spend extra time.

> @@ -3418,7 +3418,7 @@ int shadow_track_dirty_vram(struct domain *d,
>               * write access */
>              for ( i = begin_pfn; i < end_pfn; i++ )
>              {
> -                mfn_t mfn = get_gfn_query_unlocked(d, i, &t);
> +                mfn_t mfn = get_gfn_query_unlocked(d, _gfn(i), &t);
>                  if ( !mfn_eq(mfn, INVALID_MFN) )

Would you mind adding the missing blank line at this occasion? You
already do so elsewhere.

In any event:
Reviewed-by: Jan Beulich <jbeulich@suse.com>

Jan



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 11/14] xen/mm: Switch mfn_to_virt()/virt_to_mfn() to using mfn_t
  2018-11-21 13:21 ` [PATCH 11/14] xen/mm: Switch mfn_to_virt()/virt_to_mfn() to using mfn_t Andrew Cooper
  2018-11-22 14:32   ` Julien Grall
@ 2018-11-22 15:44   ` Jan Beulich
  2018-11-22 15:49     ` Andrew Cooper
  1 sibling, 1 reply; 59+ messages in thread
From: Jan Beulich @ 2018-11-22 15:44 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Julien Grall, Stefano Stabellini, Wei Liu, Xen-devel, Roger Pau Monne

>>> On 21.11.18 at 14:21, <andrew.cooper3@citrix.com> wrote:
> Seemingly, a majority of users either override the helpers anyway, or have an
> mfn_t in their hands.
> 
> Update the API, and adjust all users to match.  In some places, use the
> unsigned long variant in places where we are interacting with an external
> struct and there is no chance of them switching to mfn_t.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Reviewed-by: Jan Beulich <jbeulich@suse.com>

Some of the changes to trace.c look as if you were fixing an address
truncation bug, but allocations appear to be done with a respective
width restriction.

Jan



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 12/14] xen/gnttab: Drop gnttab_create_{shared, status}_page()
  2018-11-21 13:21 ` [PATCH 12/14] xen/gnttab: Drop gnttab_create_{shared, status}_page() Andrew Cooper
  2018-11-22 14:35   ` Julien Grall
@ 2018-11-22 15:47   ` Jan Beulich
  1 sibling, 0 replies; 59+ messages in thread
From: Jan Beulich @ 2018-11-22 15:47 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Julien Grall, Stefano Stabellini, Wei Liu, Xen-devel, Roger Pau Monne

>>> On 21.11.18 at 14:21, <andrew.cooper3@citrix.com> wrote:
> share_xen_page_with_guest() is a common API.  Use it directly rather than
> wrapping it with unnecessary boilerplate.

I was wondering a couple of times whether we should undo this "abstraction".
I simply wasn't sure why this had been introduced in the first place - perhaps
just during early Arm bringup.

> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Reviewed-by: Jan Beulich <jbeulich@suse.com>
as long as the Arm guys don't expect to need this back at some point.

Jan



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 13/14] xen/gnttab: Simplify gnttab_map_frame()
  2018-11-21 13:21 ` [PATCH 13/14] xen/gnttab: Simplify gnttab_map_frame() Andrew Cooper
  2018-11-22 14:36   ` Julien Grall
@ 2018-11-22 15:48   ` Jan Beulich
  1 sibling, 0 replies; 59+ messages in thread
From: Jan Beulich @ 2018-11-22 15:48 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Julien Grall, Stefano Stabellini, Wei Liu, Xen-devel, Roger Pau Monne

 >>> On 21.11.18 at 14:21, <andrew.cooper3@citrix.com> wrote:
> * Reflow some lines to remove unnecessary line breaks.
>  * Factor out the gnttab_get_frame_gfn() calculation.  Neither x86 nor ARM
>    builds seem to be able to fold the two calls, and the resulting code is far
>    easier to follow.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Reviewed-by: Jan Beulich <jbeulich@suse.com>



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 11/14] xen/mm: Switch mfn_to_virt()/virt_to_mfn() to using mfn_t
  2018-11-22 15:44   ` Jan Beulich
@ 2018-11-22 15:49     ` Andrew Cooper
  0 siblings, 0 replies; 59+ messages in thread
From: Andrew Cooper @ 2018-11-22 15:49 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Julien Grall, Stefano Stabellini, Wei Liu, Xen-devel, Roger Pau Monne

On 22/11/2018 15:44, Jan Beulich wrote:
>>>> On 21.11.18 at 14:21, <andrew.cooper3@citrix.com> wrote:
>> Seemingly, a majority of users either override the helpers anyway, or have an
>> mfn_t in their hands.
>>
>> Update the API, and adjust all users to match.  In some places, use the
>> unsigned long variant in places where we are interacting with an external
>> struct and there is no chance of them switching to mfn_t.
>>
>> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
> Reviewed-by: Jan Beulich <jbeulich@suse.com>
>
> Some of the changes to trace.c look as if you were fixing an address
> truncation bug, but allocations appear to be done with a respective
> width restriction.

The ABI uses 32bit integers for MFNs.  The interface is undocumented and
uses raw arrays of integers.  It is borderline impossible to follow.

The correct way to do this would be to use the new resource mapping API,
but its not something I've got time to do in the short or medium term.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 14/14] xen/gnttab: Minor improvements to arch header files
  2018-11-21 13:21 ` [PATCH 14/14] xen/gnttab: Minor improvements to arch header files Andrew Cooper
@ 2018-11-22 15:51   ` Jan Beulich
  2018-11-22 17:56   ` Andrew Cooper
  1 sibling, 0 replies; 59+ messages in thread
From: Jan Beulich @ 2018-11-22 15:51 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Xen-devel, Wei Liu, Roger Pau Monne

 >>> On 21.11.18 at 14:21, <andrew.cooper3@citrix.com> wrote:
> * Use XFREE() when appropriate
>  * Drop stale comments and unnecessary brackets
>  * Fold asm constraints
> 
> No functional change.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Reviewed-by: Jan Beulich <jbeulich@suse.com>



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 03/14] AMD/IOMMU: Fix multiple reference counting errors
  2018-11-22 14:51   ` Jan Beulich
@ 2018-11-22 17:46     ` Andrew Cooper
  2018-11-23  8:23       ` Jan Beulich
  0 siblings, 1 reply; 59+ messages in thread
From: Andrew Cooper @ 2018-11-22 17:46 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Wei Liu, Xen-devel, Brian Woods, Suravee Suthikulpanit, Roger Pau Monne

On 22/11/2018 14:51, Jan Beulich wrote:
>
>> @@ -220,12 +219,18 @@ void guest_iommu_add_ppr_log(struct domain *d, u32 entry[])
>>      unmap_domain_page(log_base);
>>  
>>      guest_iommu_deliver_msi(d);
>> +
>> +out:
> Please indent by at least one blank (same further down).

I thought you've said that you're no longer using an obsolete version of
diff.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 14/14] xen/gnttab: Minor improvements to arch header files
  2018-11-21 13:21 ` [PATCH 14/14] xen/gnttab: Minor improvements to arch header files Andrew Cooper
  2018-11-22 15:51   ` Jan Beulich
@ 2018-11-22 17:56   ` Andrew Cooper
  2019-01-30 20:04     ` Julien Grall
  1 sibling, 1 reply; 59+ messages in thread
From: Andrew Cooper @ 2018-11-22 17:56 UTC (permalink / raw)
  To: Xen-devel
  Cc: Julien Grall, Stefano Stabellini, Wei Liu, Jan Beulich,
	Roger Pau Monné

On 21/11/2018 13:21, Andrew Cooper wrote:
>  * Use XFREE() when appropriate
>  * Drop stale comments and unnecessary brackets
>  * Fold asm constraints
>
> No functional change.
>
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
> ---
> CC: Jan Beulich <JBeulich@suse.com>
> CC: Wei Liu <wei.liu2@citrix.com>
> CC: Roger Pau Monné <roger.pau@citrix.com>
> ---
>  xen/include/asm-arm/grant_table.h |  6 ++----
>  xen/include/asm-x86/grant_table.h | 10 +++-------

CC'ing ARM maintainers.  I'm sorry for missing you out originally - I
folded two separate patches and forgot to adjust the CC list.

~Andrew

>  2 files changed, 5 insertions(+), 11 deletions(-)
>
> diff --git a/xen/include/asm-arm/grant_table.h b/xen/include/asm-arm/grant_table.h
> index 816e3c6..051db13 100644
> --- a/xen/include/asm-arm/grant_table.h
> +++ b/xen/include/asm-arm/grant_table.h
> @@ -54,10 +54,8 @@ void gnttab_mark_dirty(struct domain *d, mfn_t mfn);
>  
>  #define gnttab_destroy_arch(gt)                                          \
>      do {                                                                 \
> -        xfree((gt)->arch.shared_gfn);                                    \
> -        (gt)->arch.shared_gfn = NULL;                                    \
> -        xfree((gt)->arch.status_gfn);                                    \
> -        (gt)->arch.status_gfn = NULL;                                    \
> +        XFREE((gt)->arch.shared_gfn);                                    \
> +        XFREE((gt)->arch.status_gfn);                                    \
>      } while ( 0 )
>  
>  #define gnttab_set_frame_gfn(gt, st, idx, gfn)                           \
> diff --git a/xen/include/asm-x86/grant_table.h b/xen/include/asm-x86/grant_table.h
> index 4b8c4f9..8b604ed 100644
> --- a/xen/include/asm-x86/grant_table.h
> +++ b/xen/include/asm-x86/grant_table.h
> @@ -17,10 +17,6 @@
>  struct grant_table_arch {
>  };
>  
> -/*
> - * Caller must own caller's BIGLOCK, is responsible for flushing the TLB, and
> - * must hold a reference to the page.
> - */
>  static inline int create_grant_host_mapping(uint64_t addr, mfn_t frame,
>                                              unsigned int flags,
>                                              unsigned int cache_flags)
> @@ -62,7 +58,7 @@ static inline int replace_grant_host_mapping(uint64_t addr, mfn_t frame,
>  #define gnttab_status_gmfn(d, t, i)                     \
>      (mfn_to_gmfn(d, gnttab_status_mfn(t, i)))
>  
> -#define gnttab_mark_dirty(d, f) paging_mark_dirty((d), f)
> +#define gnttab_mark_dirty(d, f) paging_mark_dirty(d, f)
>  
>  static inline void gnttab_clear_flag(unsigned int nr, uint16_t *st)
>  {
> @@ -70,10 +66,10 @@ static inline void gnttab_clear_flag(unsigned int nr, uint16_t *st)
>       * Note that this cannot be clear_bit(), as the access must be
>       * confined to the specified 2 bytes.
>       */
> -    asm volatile ("lock btrw %w1,%0" : "=m" (*st) : "Ir" (nr), "m" (*st));
> +    asm volatile ("lock btrw %w1,%0" : "+m" (*st) : "Ir" (nr));
>  }
>  
> -/* Foreign mappings of HHVM-guest pages do not modify the type count. */
> +/* Foreign mappings of HVM-guest pages do not modify the type count. */
>  #define gnttab_host_mapping_get_page_type(ro, ld, rd)   \
>      (!(ro) && (((ld) == (rd)) || !paging_mode_external(rd)))
>  


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 10/14] x86/mm: Switch {get, put}_gfn() infrastructure to using gfn_t
  2018-11-21 13:21 ` [PATCH 10/14] x86/mm: Switch {get, put}_gfn() " Andrew Cooper
                     ` (2 preceding siblings ...)
  2018-11-22 15:34   ` Jan Beulich
@ 2018-11-23  2:58   ` Tian, Kevin
  2018-11-26 15:51   ` Woods, Brian
  4 siblings, 0 replies; 59+ messages in thread
From: Tian, Kevin @ 2018-11-23  2:58 UTC (permalink / raw)
  To: Andrew Cooper, Xen-devel
  Cc: Tamas K Lengyel, Wei Liu, Nakajima, Jun, Razvan Cojocaru,
	George Dunlap, Tim Deegan, Paul Durrant, Jan Beulich,
	Boris Ostrovsky, Brian Woods, Suravee Suthikulpanit,
	Roger Pau Monné

> From: Andrew Cooper [mailto:andrew.cooper3@citrix.com]
> Sent: Wednesday, November 21, 2018 9:21 PM
> 
> Seemingly, a majority of users either override the helpers anyway, or have
> an
> gfn_t in their hands.
> 
> Update the API, and adjust all users to match.
> 
> Doing this highlighted a gaping altp2m security hole in
> vmx_vcpu_update_vmfunc_ve(), which will need addressing now we can
> discuss the
> problem and options publicly.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Reviewed-by: Kevin Tian <kevin.tian@intel.com>
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 03/14] AMD/IOMMU: Fix multiple reference counting errors
  2018-11-22 17:46     ` Andrew Cooper
@ 2018-11-23  8:23       ` Jan Beulich
  2018-11-23 16:03         ` Andrew Cooper
  0 siblings, 1 reply; 59+ messages in thread
From: Jan Beulich @ 2018-11-23  8:23 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Wei Liu, Xen-devel, Brian Woods, Suravee Suthikulpanit, Roger Pau Monne

>>> On 22.11.18 at 18:46, <andrew.cooper3@citrix.com> wrote:
> On 22/11/2018 14:51, Jan Beulich wrote:
>>> @@ -220,12 +219,18 @@ void guest_iommu_add_ppr_log(struct domain *d, u32 entry[])
>>>      unmap_domain_page(log_base);
>>>  
>>>      guest_iommu_deliver_msi(d);
>>> +
>>> +out:
>> Please indent by at least one blank (same further down).
> 
> I thought you've said that you're no longer using an obsolete version of
> diff.

I don't think I've ever said so, and I don't think it matters much what
I personally use.

Jan



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 00/14] XSA-277 followup
  2018-11-21 21:22   ` Andrew Cooper
  2018-11-21 22:42     ` Tamas K Lengyel
@ 2018-11-23 15:46     ` Roger Pau Monné
  1 sibling, 0 replies; 59+ messages in thread
From: Roger Pau Monné @ 2018-11-23 15:46 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Juergen Gross, Kevin Tian, Tamas K Lengyel, Wei Liu,
	Jun Nakajima, Razvan Cojocaru, George Dunlap, Tim Deegan,
	Xen-devel, Julien Grall, Stefano Stabellini, Jan Beulich,
	Boris Ostrovsky, Brian Woods, Suravee Suthikulpanit,
	Paul Durrant

On Wed, Nov 21, 2018 at 09:22:25PM +0000, Andrew Cooper wrote:
[...]
> The only way I see of fixing this to teach Xen about the guests gfn
> layout (as chosen by the domainbuilder), and include within that "space
> which definitely doesn't have anything in, and is safe to put shared
> mappings into".  Beyond that, we'll need some administrator level
> knowledge of which guests are safe to have XENMEM_decrease_reservation
> prohibited, or some interlocks inside Xen to disable unsafe features as
> soon as we spot a guest which isn't playing by the new rules.

I agree, this is becoming quite cumbersome for PVH Dom0 specially,
where Xen has to keep track of MMIO regions, emulated regions that
must not have anything else mapped in and normal RAM ranges. Since the
hypervisor doesn't keep track of the memory layout every time there's
a p2m change (ie: BAR mapping and unmapping for example) there's a lot
of logic to avoid overlaps.

Having some kind of memory map that can be used to look up what's
supposed to be in a memory region would be quite helpful IMO.

Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 03/14] AMD/IOMMU: Fix multiple reference counting errors
  2018-11-23  8:23       ` Jan Beulich
@ 2018-11-23 16:03         ` Andrew Cooper
  2018-11-26  9:05           ` Jan Beulich
  0 siblings, 1 reply; 59+ messages in thread
From: Andrew Cooper @ 2018-11-23 16:03 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Wei Liu, Xen-devel, Brian Woods, Suravee Suthikulpanit, Roger Pau Monne

On 23/11/2018 08:23, Jan Beulich wrote:
>>>> On 22.11.18 at 18:46, <andrew.cooper3@citrix.com> wrote:
>> On 22/11/2018 14:51, Jan Beulich wrote:
>>>> @@ -220,12 +219,18 @@ void guest_iommu_add_ppr_log(struct domain *d, u32 entry[])
>>>>      unmap_domain_page(log_base);
>>>>  
>>>>      guest_iommu_deliver_msi(d);
>>>> +
>>>> +out:
>>> Please indent by at least one blank (same further down).
>> I thought you've said that you're no longer using an obsolete version of
>> diff.
> I don't think I've ever said so, and I don't think it matters much what
> I personally use.

The only reason we have this quirk of a coding style is because you
insisted when David was putting together CODING_STYLE, and the reason
you gave was to work around versions of `diff -u` which mistook the case
label for the function name when creating the unified header.  v1 of
David's patch very specifically didn't have the one space, because he
was actually trying to get rid of that, as it was (and still is)
completely unexpected for new developers, and a frequent source of curt
review responses.

If this is no longer a concern, can I suggest we update CODING_STYLE. 
This is one particular divergence from more normal styles which doesn't
add to code clarity in any way I can spot.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 03/14] AMD/IOMMU: Fix multiple reference counting errors
  2018-11-23 16:03         ` Andrew Cooper
@ 2018-11-26  9:05           ` Jan Beulich
  0 siblings, 0 replies; 59+ messages in thread
From: Jan Beulich @ 2018-11-26  9:05 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Wei Liu, Xen-devel, Brian Woods, Suravee Suthikulpanit, Roger Pau Monne

>>> On 23.11.18 at 17:03, <andrew.cooper3@citrix.com> wrote:
> On 23/11/2018 08:23, Jan Beulich wrote:
>>>>> On 22.11.18 at 18:46, <andrew.cooper3@citrix.com> wrote:
>>> On 22/11/2018 14:51, Jan Beulich wrote:
>>>>> @@ -220,12 +219,18 @@ void guest_iommu_add_ppr_log(struct domain *d, u32 entry[])
>>>>>      unmap_domain_page(log_base);
>>>>>  
>>>>>      guest_iommu_deliver_msi(d);
>>>>> +
>>>>> +out:
>>>> Please indent by at least one blank (same further down).
>>> I thought you've said that you're no longer using an obsolete version of
>>> diff.
>> I don't think I've ever said so, and I don't think it matters much what
>> I personally use.
> 
> The only reason we have this quirk of a coding style is because you
> insisted when David was putting together CODING_STYLE, and the reason
> you gave was to work around versions of `diff -u` which mistook the case
> label for the function name when creating the unified header.  v1 of
> David's patch very specifically didn't have the one space, because he
> was actually trying to get rid of that, as it was (and still is)
> completely unexpected for new developers, and a frequent source of curt
> review responses.

Personally I find it undesirable to have anything other that file
scope things to start in column 1. Of course, as you're likely
aware, I'm an opponent of labels and goto-s altogether, and
probably the former dislike is sort of a result of the latter.

> If this is no longer a concern, can I suggest we update CODING_STYLE. 

Even the version of diff on my main most modern system (3.6)
gets this wrong, so I'd prefer if we could stick to indented labels.
I continue to be of the opinion that the use of git should not be
a requirement for developers; plain diff and patch ought to
suffice for people to produce acceptable patches.

I'd like to note though that ./CODING_STYLE says nothing either
way afaics, so I also have no basis to _insist_ on this style. I've
just sent a patch to rectify this.

Jan



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 10/14] x86/mm: Switch {get, put}_gfn() infrastructure to using gfn_t
  2018-11-21 13:21 ` [PATCH 10/14] x86/mm: Switch {get, put}_gfn() " Andrew Cooper
                     ` (3 preceding siblings ...)
  2018-11-23  2:58   ` Tian, Kevin
@ 2018-11-26 15:51   ` Woods, Brian
  4 siblings, 0 replies; 59+ messages in thread
From: Woods, Brian @ 2018-11-26 15:51 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Kevin Tian, Tamas K Lengyel, Wei Liu, Jun Nakajima,
	Razvan Cojocaru, George Dunlap, Tim Deegan, Xen-devel,
	Paul Durrant, Jan Beulich, Boris Ostrovsky, Woods, Brian,
	Suthikulpanit, Suravee, Roger Pau Monné

On Wed, Nov 21, 2018 at 01:21:18PM +0000, Andy Cooper wrote:
> Seemingly, a majority of users either override the helpers anyway, or have an
> gfn_t in their hands.
> 
> Update the API, and adjust all users to match.
> 
> Doing this highlighted a gaping altp2m security hole in
> vmx_vcpu_update_vmfunc_ve(), which will need addressing now we can discuss the
> problem and options publicly.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

As far as the svm and iommu parts

Acked-by: Brian Woods <brian.woods@amd.com>

> ---
> CC: Jan Beulich <JBeulich@suse.com>
> CC: Wei Liu <wei.liu2@citrix.com>
> CC: Roger Pau Monné <roger.pau@citrix.com>
> CC: Razvan Cojocaru <rcojocaru@bitdefender.com>
> CC: Tamas K Lengyel <tamas@tklengyel.com>
> CC: George Dunlap <george.dunlap@eu.citrix.com>
> CC: Tim Deegan <tim@xen.org>
> CC: Paul Durrant <paul.durrant@citrix.com>
> CC: Jun Nakajima <jun.nakajima@intel.com>
> CC: Kevin Tian <kevin.tian@intel.com>
> CC: Boris Ostrovsky <boris.ostrovsky@oracle.com>
> CC: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
> CC: Brian Woods <brian.woods@amd.com>
> ---
>  xen/arch/x86/cpu/mcheck/mcaction.c        |  2 +-
>  xen/arch/x86/cpu/mcheck/mce.c             | 14 +++----
>  xen/arch/x86/cpu/mcheck/vmce.c            |  4 +-
>  xen/arch/x86/cpu/mcheck/vmce.h            |  2 +-
>  xen/arch/x86/debug.c                      |  6 +--
>  xen/arch/x86/domain.c                     | 19 ++++-----
>  xen/arch/x86/domctl.c                     |  8 ++--
>  xen/arch/x86/hvm/dm.c                     | 12 +++---
>  xen/arch/x86/hvm/emulate.c                | 16 ++++----
>  xen/arch/x86/hvm/grant_table.c            |  4 +-
>  xen/arch/x86/hvm/hvm.c                    | 25 ++++++------
>  xen/arch/x86/hvm/mtrr.c                   |  2 +-
>  xen/arch/x86/hvm/svm/svm.c                |  2 +-
>  xen/arch/x86/hvm/vmx/vmx.c                |  7 ++--
>  xen/arch/x86/mm.c                         | 10 ++---
>  xen/arch/x86/mm/hap/hap.c                 |  2 +-
>  xen/arch/x86/mm/hap/nested_hap.c          |  6 +--
>  xen/arch/x86/mm/mem_access.c              |  5 +--
>  xen/arch/x86/mm/mem_sharing.c             | 24 +++++------
>  xen/arch/x86/mm/p2m.c                     | 45 ++++++++++----------
>  xen/arch/x86/mm/shadow/common.c           |  4 +-
>  xen/arch/x86/mm/shadow/multi.c            | 68 +++++++++++++++----------------
>  xen/arch/x86/mm/shadow/types.h            |  4 --
>  xen/common/grant_table.c                  | 10 ++---
>  xen/common/memory.c                       | 24 +++++------
>  xen/drivers/passthrough/amd/iommu_guest.c |  8 ----
>  xen/include/asm-x86/guest_pt.h            |  4 --
>  xen/include/asm-x86/p2m.h                 | 30 +++++++-------
>  28 files changed, 172 insertions(+), 195 deletions(-)
> 
> diff --git a/xen/arch/x86/cpu/mcheck/mcaction.c b/xen/arch/x86/cpu/mcheck/mcaction.c
> index e422674..c8e0cf2 100644
> --- a/xen/arch/x86/cpu/mcheck/mcaction.c
> +++ b/xen/arch/x86/cpu/mcheck/mcaction.c
> @@ -89,7 +89,7 @@ mc_memerr_dhandler(struct mca_binfo *binfo,
>                  ASSERT(d);
>                  gfn = get_gpfn_from_mfn((bank->mc_addr) >> PAGE_SHIFT);
>  
> -                if ( unmmap_broken_page(d, _mfn(mfn), gfn) )
> +                if ( unmmap_broken_page(d, _mfn(mfn), _gfn(gfn)) )
>                  {
>                      printk("Unmap broken memory %lx for DOM%d failed\n",
>                             mfn, d->domain_id);
> diff --git a/xen/arch/x86/cpu/mcheck/mce.c b/xen/arch/x86/cpu/mcheck/mce.c
> index 30cdb06..c96c053 100644
> --- a/xen/arch/x86/cpu/mcheck/mce.c
> +++ b/xen/arch/x86/cpu/mcheck/mce.c
> @@ -1469,9 +1469,6 @@ long do_mca(XEN_GUEST_HANDLE_PARAM(xen_mc_t) u_xen_mc)
>              struct domain *d;
>              struct mcinfo_msr *msr;
>              unsigned int i;
> -            paddr_t gaddr;
> -            unsigned long gfn, mfn;
> -            p2m_type_t t;
>  
>              domid = (mc_msrinject->mcinj_domid == DOMID_SELF) ?
>                      current->domain->domain_id : mc_msrinject->mcinj_domid;
> @@ -1489,11 +1486,12 @@ long do_mca(XEN_GUEST_HANDLE_PARAM(xen_mc_t) u_xen_mc)
>                    i < mc_msrinject->mcinj_count;
>                    i++, msr++ )
>              {
> -                gaddr = msr->value;
> -                gfn = PFN_DOWN(gaddr);
> -                mfn = mfn_x(get_gfn(d, gfn, &t));
> +                p2m_type_t t;
> +                paddr_t gaddr = msr->value;
> +                gfn_t gfn = _gfn(PFN_DOWN(gaddr));
> +                mfn_t mfn = get_gfn(d, gfn, &t);
>  
> -                if ( mfn == mfn_x(INVALID_MFN) )
> +                if ( mfn_eq(mfn, INVALID_MFN) )
>                  {
>                      put_gfn(d, gfn);
>                      put_domain(d);
> @@ -1501,7 +1499,7 @@ long do_mca(XEN_GUEST_HANDLE_PARAM(xen_mc_t) u_xen_mc)
>                                       -EINVAL, gfn, domid);
>                  }
>  
> -                msr->value = pfn_to_paddr(mfn) | (gaddr & (PAGE_SIZE - 1));
> +                msr->value = mfn_to_maddr(mfn) | (gaddr & (PAGE_SIZE - 1));
>  
>                  put_gfn(d, gfn);
>              }
> diff --git a/xen/arch/x86/cpu/mcheck/vmce.c b/xen/arch/x86/cpu/mcheck/vmce.c
> index f15835e..e257e94 100644
> --- a/xen/arch/x86/cpu/mcheck/vmce.c
> +++ b/xen/arch/x86/cpu/mcheck/vmce.c
> @@ -512,7 +512,7 @@ int fill_vmsr_data(struct mcinfo_bank *mc_bank, struct domain *d,
>   * XXX following situation missed:
>   * PoD, Foreign mapped, Granted, Shared
>   */
> -int unmmap_broken_page(struct domain *d, mfn_t mfn, unsigned long gfn)
> +int unmmap_broken_page(struct domain *d, mfn_t mfn, gfn_t gfn)
>  {
>      mfn_t r_mfn;
>      p2m_type_t pt;
> @@ -533,7 +533,7 @@ int unmmap_broken_page(struct domain *d, mfn_t mfn, unsigned long gfn)
>      if ( p2m_to_mask(pt) & P2M_UNMAP_TYPES)
>      {
>          ASSERT(mfn_eq(r_mfn, mfn));
> -        rc = p2m_change_type_one(d, gfn, pt, p2m_ram_broken);
> +        rc = p2m_change_type_one(d, gfn_x(gfn), pt, p2m_ram_broken);
>      }
>      put_gfn(d, gfn);
>  
> diff --git a/xen/arch/x86/cpu/mcheck/vmce.h b/xen/arch/x86/cpu/mcheck/vmce.h
> index 2797e00..a37f3be 100644
> --- a/xen/arch/x86/cpu/mcheck/vmce.h
> +++ b/xen/arch/x86/cpu/mcheck/vmce.h
> @@ -9,7 +9,7 @@ int vmce_init(struct cpuinfo_x86 *c);
>          && hardware_domain->vcpu[0] \
>          && guest_enabled_event(hardware_domain->vcpu[0], VIRQ_MCA))
>  
> -int unmmap_broken_page(struct domain *d, mfn_t mfn, unsigned long gfn);
> +int unmmap_broken_page(struct domain *d, mfn_t mfn, gfn_t gfn);
>  
>  int vmce_intel_rdmsr(const struct vcpu *, uint32_t msr, uint64_t *val);
>  int vmce_intel_wrmsr(struct vcpu *, uint32_t msr, uint64_t val);
> diff --git a/xen/arch/x86/debug.c b/xen/arch/x86/debug.c
> index a500df0..7c2dc8c 100644
> --- a/xen/arch/x86/debug.c
> +++ b/xen/arch/x86/debug.c
> @@ -58,7 +58,7 @@ dbg_hvm_va2mfn(dbgva_t vaddr, struct domain *dp, int toaddr, gfn_t *gfn)
>          return INVALID_MFN;
>      }
>  
> -    mfn = get_gfn(dp, gfn_x(*gfn), &gfntype);
> +    mfn = get_gfn(dp, *gfn, &gfntype);
>      if ( p2m_is_readonly(gfntype) && toaddr )
>      {
>          DBGP2("kdb:p2m_is_readonly: gfntype:%x\n", gfntype);
> @@ -70,7 +70,7 @@ dbg_hvm_va2mfn(dbgva_t vaddr, struct domain *dp, int toaddr, gfn_t *gfn)
>  
>      if ( mfn_eq(mfn, INVALID_MFN) )
>      {
> -        put_gfn(dp, gfn_x(*gfn));
> +        put_gfn(dp, *gfn);
>          *gfn = INVALID_GFN;
>      }
>  
> @@ -189,7 +189,7 @@ static unsigned int dbg_rw_guest_mem(struct domain *dp, void * __user gaddr,
>  
>          unmap_domain_page(va);
>          if ( !gfn_eq(gfn, INVALID_GFN) )
> -            put_gfn(dp, gfn_x(gfn));
> +            put_gfn(dp, gfn);
>  
>          addr += pagecnt;
>          buf += pagecnt;
> diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
> index b4d5948..327c961 100644
> --- a/xen/arch/x86/domain.c
> +++ b/xen/arch/x86/domain.c
> @@ -677,7 +677,7 @@ int arch_domain_soft_reset(struct domain *d)
>      int ret = 0;
>      struct domain *owner;
>      mfn_t mfn;
> -    unsigned long gfn;
> +    gfn_t gfn;
>      p2m_type_t p2mt;
>      unsigned int i;
>  
> @@ -711,19 +711,19 @@ int arch_domain_soft_reset(struct domain *d)
>      ASSERT( owner == d );
>  
>      mfn = page_to_mfn(page);
> -    gfn = mfn_to_gmfn(d, mfn_x(mfn));
> +    gfn = _gfn(mfn_to_gmfn(d, mfn_x(mfn)));
>  
>      /*
>       * gfn == INVALID_GFN indicates that the shared_info page was never mapped
>       * to the domain's address space and there is nothing to replace.
>       */
> -    if ( gfn == gfn_x(INVALID_GFN) )
> +    if ( gfn_eq(gfn, INVALID_GFN) )
>          goto exit_put_page;
>  
>      if ( !mfn_eq(get_gfn_query(d, gfn, &p2mt), mfn) )
>      {
>          printk(XENLOG_G_ERR "Failed to get Dom%d's shared_info GFN (%lx)\n",
> -               d->domain_id, gfn);
> +               d->domain_id, gfn_x(gfn));
>          ret = -EINVAL;
>          goto exit_put_gfn;
>      }
> @@ -732,26 +732,25 @@ int arch_domain_soft_reset(struct domain *d)
>      if ( !new_page )
>      {
>          printk(XENLOG_G_ERR "Failed to alloc a page to replace"
> -               " Dom%d's shared_info frame %lx\n", d->domain_id, gfn);
> +               " Dom%d's shared_info frame %lx\n", d->domain_id, gfn_x(gfn));
>          ret = -ENOMEM;
>          goto exit_put_gfn;
>      }
>  
> -    ret = guest_physmap_remove_page(d, _gfn(gfn), mfn, PAGE_ORDER_4K);
> +    ret = guest_physmap_remove_page(d, gfn, mfn, PAGE_ORDER_4K);
>      if ( ret )
>      {
>          printk(XENLOG_G_ERR "Failed to remove Dom%d's shared_info frame %lx\n",
> -               d->domain_id, gfn);
> +               d->domain_id, gfn_x(gfn));
>          free_domheap_page(new_page);
>          goto exit_put_gfn;
>      }
>  
> -    ret = guest_physmap_add_page(d, _gfn(gfn), page_to_mfn(new_page),
> -                                 PAGE_ORDER_4K);
> +    ret = guest_physmap_add_page(d, gfn, page_to_mfn(new_page), PAGE_ORDER_4K);
>      if ( ret )
>      {
>          printk(XENLOG_G_ERR "Failed to add a page to replace"
> -               " Dom%d's shared_info frame %lx\n", d->domain_id, gfn);
> +               " Dom%d's shared_info frame %lx\n", d->domain_id, gfn_x(gfn));
>          free_domheap_page(new_page);
>      }
>   exit_put_gfn:
> diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
> index aa8ad19..694b4d5 100644
> --- a/xen/arch/x86/domctl.c
> +++ b/xen/arch/x86/domctl.c
> @@ -1253,15 +1253,15 @@ long arch_do_domctl(
>      case XEN_DOMCTL_set_broken_page_p2m:
>      {
>          p2m_type_t pt;
> -        unsigned long pfn = domctl->u.set_broken_page_p2m.pfn;
> -        mfn_t mfn = get_gfn_query(d, pfn, &pt);
> +        gfn_t gfn = _gfn(domctl->u.set_broken_page_p2m.pfn);
> +        mfn_t mfn = get_gfn_query(d, gfn, &pt);
>  
>          if ( unlikely(!mfn_valid(mfn)) || unlikely(!p2m_is_ram(pt)) )
>              ret = -EINVAL;
>          else
> -            ret = p2m_change_type_one(d, pfn, pt, p2m_ram_broken);
> +            ret = p2m_change_type_one(d, gfn_x(gfn), pt, p2m_ram_broken);
>  
> -        put_gfn(d, pfn);
> +        put_gfn(d, gfn);
>          break;
>      }
>  
> diff --git a/xen/arch/x86/hvm/dm.c b/xen/arch/x86/hvm/dm.c
> index d6d0e8b..9938f4b 100644
> --- a/xen/arch/x86/hvm/dm.c
> +++ b/xen/arch/x86/hvm/dm.c
> @@ -269,14 +269,14 @@ static int set_mem_type(struct domain *d,
>  
>      while ( iter < data->nr )
>      {
> -        unsigned long pfn = data->first_pfn + iter;
> +        gfn_t gfn = _gfn(data->first_pfn + iter);
>          p2m_type_t t;
>  
> -        get_gfn_unshare(d, pfn, &t);
> +        get_gfn_unshare(d, gfn, &t);
>          if ( p2m_is_paging(t) )
>          {
> -            put_gfn(d, pfn);
> -            p2m_mem_paging_populate(d, pfn);
> +            put_gfn(d, gfn);
> +            p2m_mem_paging_populate(d, gfn_x(gfn));
>              return -EAGAIN;
>          }
>  
> @@ -285,9 +285,9 @@ static int set_mem_type(struct domain *d,
>          else if ( !allow_p2m_type_change(t, memtype[mem_type]) )
>              rc = -EINVAL;
>          else
> -            rc = p2m_change_type_one(d, pfn, t, memtype[mem_type]);
> +            rc = p2m_change_type_one(d, gfn_x(gfn), t, memtype[mem_type]);
>  
> -        put_gfn(d, pfn);
> +        put_gfn(d, gfn);
>  
>          if ( rc )
>              break;
> diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c
> index 2d02ef1..1335b2c 100644
> --- a/xen/arch/x86/hvm/emulate.c
> +++ b/xen/arch/x86/hvm/emulate.c
> @@ -255,13 +255,13 @@ static int hvmemul_do_io(
>           * so the device model side needs to check the incoming ioreq event.
>           */
>          struct hvm_ioreq_server *s = NULL;
> -        p2m_type_t p2mt = p2m_invalid;
>  
>          if ( is_mmio )
>          {
> -            unsigned long gmfn = paddr_to_pfn(addr);
> +            p2m_type_t p2mt = p2m_invalid;
> +            gfn_t gfn = gaddr_to_gfn(addr);
>  
> -            get_gfn_query_unlocked(currd, gmfn, &p2mt);
> +            get_gfn_query_unlocked(currd, gfn, &p2mt);
>  
>              if ( p2mt == p2m_ioreq_server )
>              {
> @@ -1590,7 +1590,7 @@ static int hvmemul_rep_ins(
>      if ( rc != X86EMUL_OKAY )
>          return rc;
>  
> -    (void) get_gfn_query_unlocked(current->domain, gpa >> PAGE_SHIFT, &p2mt);
> +    get_gfn_query_unlocked(current->domain, gaddr_to_gfn(gpa), &p2mt);
>      if ( p2mt == p2m_mmio_direct || p2mt == p2m_mmio_dm )
>          return X86EMUL_UNHANDLEABLE;
>  
> @@ -1671,7 +1671,7 @@ static int hvmemul_rep_outs(
>      if ( rc != X86EMUL_OKAY )
>          return rc;
>  
> -    (void) get_gfn_query_unlocked(current->domain, gpa >> PAGE_SHIFT, &p2mt);
> +    get_gfn_query_unlocked(current->domain, gaddr_to_gfn(gpa), &p2mt);
>      if ( p2mt == p2m_mmio_direct || p2mt == p2m_mmio_dm )
>          return X86EMUL_UNHANDLEABLE;
>  
> @@ -1750,8 +1750,8 @@ static int hvmemul_rep_movs(
>      }
>  
>      /* Check for MMIO ops */
> -    (void) get_gfn_query_unlocked(current->domain, sgpa >> PAGE_SHIFT, &sp2mt);
> -    (void) get_gfn_query_unlocked(current->domain, dgpa >> PAGE_SHIFT, &dp2mt);
> +    get_gfn_query_unlocked(current->domain, gaddr_to_gfn(sgpa), &sp2mt);
> +    get_gfn_query_unlocked(current->domain, gaddr_to_gfn(dgpa), &dp2mt);
>  
>      if ( sp2mt == p2m_mmio_direct || dp2mt == p2m_mmio_direct ||
>           (sp2mt == p2m_mmio_dm && dp2mt == p2m_mmio_dm) )
> @@ -1878,7 +1878,7 @@ static int hvmemul_rep_stos(
>      }
>  
>      /* Check for MMIO op */
> -    (void)get_gfn_query_unlocked(current->domain, gpa >> PAGE_SHIFT, &p2mt);
> +    get_gfn_query_unlocked(current->domain, gaddr_to_gfn(gpa), &p2mt);
>  
>      switch ( p2mt )
>      {
> diff --git a/xen/arch/x86/hvm/grant_table.c b/xen/arch/x86/hvm/grant_table.c
> index ecd7d07..04a3106 100644
> --- a/xen/arch/x86/hvm/grant_table.c
> +++ b/xen/arch/x86/hvm/grant_table.c
> @@ -51,7 +51,7 @@ int create_grant_p2m_mapping(uint64_t addr, mfn_t frame,
>  int replace_grant_p2m_mapping(uint64_t addr, mfn_t frame,
>                                uint64_t new_addr, unsigned int flags)
>  {
> -    unsigned long gfn = (unsigned long)(addr >> PAGE_SHIFT);
> +    gfn_t gfn = gaddr_to_gfn(addr);
>      p2m_type_t type;
>      mfn_t old_mfn;
>      struct domain *d = current->domain;
> @@ -68,7 +68,7 @@ int replace_grant_p2m_mapping(uint64_t addr, mfn_t frame,
>                   type, mfn_x(old_mfn), mfn_x(frame));
>          return GNTST_general_error;
>      }
> -    if ( guest_physmap_remove_page(d, _gfn(gfn), frame, PAGE_ORDER_4K) )
> +    if ( guest_physmap_remove_page(d, gfn, frame, PAGE_ORDER_4K) )
>      {
>          put_gfn(d, gfn);
>          return GNTST_general_error;
> diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
> index db60f23..987c26a 100644
> --- a/xen/arch/x86/hvm/hvm.c
> +++ b/xen/arch/x86/hvm/hvm.c
> @@ -1679,7 +1679,7 @@ void hvm_inject_event(const struct x86_event *event)
>  int hvm_hap_nested_page_fault(paddr_t gpa, unsigned long gla,
>                                struct npfec npfec)
>  {
> -    unsigned long gfn = gpa >> PAGE_SHIFT;
> +    gfn_t gfn = gaddr_to_gfn(gpa);
>      p2m_type_t p2mt;
>      p2m_access_t p2ma;
>      mfn_t mfn;
> @@ -1729,7 +1729,7 @@ int hvm_hap_nested_page_fault(paddr_t gpa, unsigned long gla,
>              return 1;
>          case NESTEDHVM_PAGEFAULT_L0_ERROR:
>              /* gpa is now translated to l1 guest address, update gfn. */
> -            gfn = gpa >> PAGE_SHIFT;
> +            gfn = gaddr_to_gfn(gpa);
>              break;
>          }
>      }
> @@ -1817,7 +1817,7 @@ int hvm_hap_nested_page_fault(paddr_t gpa, unsigned long gla,
>              {
>                  bool_t sve;
>  
> -                p2m->get_entry(p2m, _gfn(gfn), &p2mt, &p2ma, 0, NULL, &sve);
> +                p2m->get_entry(p2m, gfn, &p2mt, &p2ma, 0, NULL, &sve);
>  
>                  if ( !sve && altp2m_vcpu_emulate_ve(curr) )
>                  {
> @@ -1862,7 +1862,7 @@ int hvm_hap_nested_page_fault(paddr_t gpa, unsigned long gla,
>      {
>          ASSERT(p2m_is_hostp2m(p2m));
>          sharing_enomem = 
> -            (mem_sharing_unshare_page(currd, gfn, 0) < 0);
> +            (mem_sharing_unshare_page(currd, gfn_x(gfn), 0) < 0);
>          rc = 1;
>          goto out_put_gfn;
>      }
> @@ -1878,7 +1878,7 @@ int hvm_hap_nested_page_fault(paddr_t gpa, unsigned long gla,
>           */
>          if ( npfec.write_access )
>          {
> -            paging_mark_pfn_dirty(currd, _pfn(gfn));
> +            paging_mark_pfn_dirty(currd, _pfn(gfn_x(gfn)));
>              /*
>               * If p2m is really an altp2m, unlock it before changing the type,
>               * as p2m_altp2m_propagate_change() needs to acquire the
> @@ -1886,7 +1886,7 @@ int hvm_hap_nested_page_fault(paddr_t gpa, unsigned long gla,
>               */
>              if ( p2m != hostp2m )
>                  __put_gfn(p2m, gfn);
> -            p2m_change_type_one(currd, gfn, p2m_ram_logdirty, p2m_ram_rw);
> +            p2m_change_type_one(currd, gfn_x(gfn), p2m_ram_logdirty, p2m_ram_rw);
>              __put_gfn(hostp2m, gfn);
>  
>              goto out;
> @@ -1916,16 +1916,16 @@ int hvm_hap_nested_page_fault(paddr_t gpa, unsigned long gla,
>       * sleep on event ring wait queues, and we must not hold
>       * locks in such circumstance */
>      if ( paged )
> -        p2m_mem_paging_populate(currd, gfn);
> +        p2m_mem_paging_populate(currd, gfn_x(gfn));
>      if ( sharing_enomem )
>      {
>          int rv;
>  
> -        if ( (rv = mem_sharing_notify_enomem(currd, gfn, true)) < 0 )
> +        if ( (rv = mem_sharing_notify_enomem(currd, gfn_x(gfn), true)) < 0 )
>          {
>              gdprintk(XENLOG_ERR, "Domain %hu attempt to unshare "
>                       "gfn %lx, ENOMEM and no helper (rc %d)\n",
> -                     currd->domain_id, gfn, rv);
> +                     currd->domain_id, gfn_x(gfn), rv);
>              /* Crash the domain */
>              rc = 0;
>          }
> @@ -4601,8 +4601,9 @@ static int do_altp2m_op(
>          v = d->vcpu[a.u.enable_notify.vcpu_id];
>  
>          if ( !gfn_eq(vcpu_altp2m(v).veinfo_gfn, INVALID_GFN) ||
> -             mfn_eq(get_gfn_query_unlocked(v->domain,
> -                    a.u.enable_notify.gfn, &p2mt), INVALID_MFN) )
> +             mfn_eq(get_gfn_query_unlocked(
> +                        v->domain, _gfn(a.u.enable_notify.gfn), &p2mt),
> +                    INVALID_MFN) )
>          {
>              rc = -EINVAL;
>              break;
> @@ -4866,7 +4867,7 @@ static int hvmop_get_mem_type(
>       * type, not in allocating or unsharing. That'll happen
>       * on access.
>       */
> -    get_gfn_query_unlocked(d, a.pfn, &t);
> +    get_gfn_query_unlocked(d, _gfn(a.pfn), &t);
>      if ( p2m_is_mmio(t) )
>          a.mem_type =  HVMMEM_mmio_dm;
>      else if ( t == p2m_ioreq_server )
> diff --git a/xen/arch/x86/hvm/mtrr.c b/xen/arch/x86/hvm/mtrr.c
> index b8fa340..f553e4d 100644
> --- a/xen/arch/x86/hvm/mtrr.c
> +++ b/xen/arch/x86/hvm/mtrr.c
> @@ -366,7 +366,7 @@ uint32_t get_pat_flags(struct vcpu *v,
>      {
>          struct domain *d = v->domain;
>          p2m_type_t p2mt;
> -        get_gfn_query_unlocked(d, paddr_to_pfn(gpaddr), &p2mt);
> +        get_gfn_query_unlocked(d, gaddr_to_gfn(gpaddr), &p2mt);
>          if (p2m_is_ram(p2mt))
>              gdprintk(XENLOG_WARNING,
>                      "Conflict occurs for a given guest l1e flags:%x "
> diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
> index b9a8900..46f9893 100644
> --- a/xen/arch/x86/hvm/svm/svm.c
> +++ b/xen/arch/x86/hvm/svm/svm.c
> @@ -1762,7 +1762,7 @@ static void svm_do_nested_pgfault(struct vcpu *v,
>      struct cpu_user_regs *regs, uint64_t pfec, paddr_t gpa)
>  {
>      int ret;
> -    unsigned long gfn = gpa >> PAGE_SHIFT;
> +    gfn_t gfn = gaddr_to_gfn(gpa);
>      mfn_t mfn;
>      p2m_type_t p2mt;
>      p2m_access_t p2ma;
> diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
> index 365eeb2..b5370dd 100644
> --- a/xen/arch/x86/hvm/vmx/vmx.c
> +++ b/xen/arch/x86/hvm/vmx/vmx.c
> @@ -2199,7 +2199,8 @@ static void vmx_vcpu_update_vmfunc_ve(struct vcpu *v)
>              p2m_type_t t;
>              mfn_t mfn;
>  
> -            mfn = get_gfn_query_unlocked(d, gfn_x(vcpu_altp2m(v).veinfo_gfn), &t);
> +            /* TODO: This is a security issue... */
> +            mfn = get_gfn_query_unlocked(d, vcpu_altp2m(v).veinfo_gfn, &t);
>  
>              if ( !mfn_eq(mfn, INVALID_MFN) )
>              {
> @@ -3328,7 +3329,7 @@ static void ept_handle_violation(ept_qual_t q, paddr_t gpa)
>  
>          _d.gpa = gpa;
>          _d.qualification = q.raw;
> -        _d.mfn = mfn_x(get_gfn_query_unlocked(d, gfn, &_d.p2mt));
> +        _d.mfn = mfn_x(get_gfn_query_unlocked(d, _gfn(gfn), &_d.p2mt));
>  
>          __trace_var(TRC_HVM_NPF, 0, sizeof(_d), &_d);
>      }
> @@ -3358,7 +3359,7 @@ static void ept_handle_violation(ept_qual_t q, paddr_t gpa)
>      }
>  
>      /* Everything else is an error. */
> -    mfn = get_gfn_query_unlocked(d, gfn, &p2mt);
> +    mfn = get_gfn_query_unlocked(d, _gfn(gfn), &p2mt);
>      gprintk(XENLOG_ERR,
>              "EPT violation %#lx (%c%c%c/%c%c%c) gpa %#"PRIpaddr" mfn %#lx type %i\n",
>              q.raw,
> diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
> index 28a0030..c3c7628 100644
> --- a/xen/arch/x86/mm.c
> +++ b/xen/arch/x86/mm.c
> @@ -4364,11 +4364,11 @@ int xenmem_add_to_physmap_one(
>              p2m_type_t p2mt;
>  
>              gfn = idx;
> -            mfn = get_gfn_unshare(d, gfn, &p2mt);
> +            mfn = get_gfn_unshare(d, _gfn(gfn), &p2mt);
>              /* If the page is still shared, exit early */
>              if ( p2m_is_shared(p2mt) )
>              {
> -                put_gfn(d, gfn);
> +                put_gfn(d, _gfn(gfn));
>                  return -ENOMEM;
>              }
>              page = get_page_from_mfn(mfn, d);
> @@ -4389,7 +4389,7 @@ int xenmem_add_to_physmap_one(
>      }
>  
>      /* Remove previously mapped page if it was present. */
> -    prev_mfn = mfn_x(get_gfn(d, gfn_x(gpfn), &p2mt));
> +    prev_mfn = mfn_x(get_gfn(d, gpfn, &p2mt));
>      if ( mfn_valid(_mfn(prev_mfn)) )
>      {
>          if ( is_xen_heap_mfn(prev_mfn) )
> @@ -4400,7 +4400,7 @@ int xenmem_add_to_physmap_one(
>              rc = guest_remove_page(d, gfn_x(gpfn));
>      }
>      /* In the XENMAPSPACE_gmfn case we still hold a ref on the old page. */
> -    put_gfn(d, gfn_x(gpfn));
> +    put_gfn(d, gpfn);
>  
>      if ( rc )
>          goto put_both;
> @@ -4423,7 +4423,7 @@ int xenmem_add_to_physmap_one(
>   put_both:
>      /* In the XENMAPSPACE_gmfn case, we took a ref of the gfn at the top. */
>      if ( space == XENMAPSPACE_gmfn )
> -        put_gfn(d, gfn);
> +        put_gfn(d, _gfn(gfn));
>  
>      if ( page )
>          put_page(page);
> diff --git a/xen/arch/x86/mm/hap/hap.c b/xen/arch/x86/mm/hap/hap.c
> index 3d651b9..0ac7d10 100644
> --- a/xen/arch/x86/mm/hap/hap.c
> +++ b/xen/arch/x86/mm/hap/hap.c
> @@ -681,7 +681,7 @@ hap_paging_get_mode(struct vcpu *v)
>  static void hap_update_paging_modes(struct vcpu *v)
>  {
>      struct domain *d = v->domain;
> -    unsigned long cr3_gfn = v->arch.hvm.guest_cr[3] >> PAGE_SHIFT;
> +    gfn_t cr3_gfn = gaddr_to_gfn(v->arch.hvm.guest_cr[3]);
>      p2m_type_t t;
>  
>      /* We hold onto the cr3 as it may be modified later, and
> diff --git a/xen/arch/x86/mm/hap/nested_hap.c b/xen/arch/x86/mm/hap/nested_hap.c
> index d2a07a5..d83c436 100644
> --- a/xen/arch/x86/mm/hap/nested_hap.c
> +++ b/xen/arch/x86/mm/hap/nested_hap.c
> @@ -150,12 +150,12 @@ nestedhap_walk_L0_p2m(struct p2m_domain *p2m, paddr_t L1_gpa, paddr_t *L0_gpa,
>                        unsigned int *page_order,
>                        bool_t access_r, bool_t access_w, bool_t access_x)
>  {
> +    gfn_t l1_gfn = gaddr_to_gfn(L1_gpa);
>      mfn_t mfn;
>      int rc;
>  
>      /* walk L0 P2M table */
> -    mfn = get_gfn_type_access(p2m, L1_gpa >> PAGE_SHIFT, p2mt, p2ma,
> -                              0, page_order);
> +    mfn = get_gfn_type_access(p2m, l1_gfn, p2mt, p2ma, 0, page_order);
>  
>      rc = NESTEDHVM_PAGEFAULT_DIRECT_MMIO;
>      if ( *p2mt == p2m_mmio_direct )
> @@ -178,7 +178,7 @@ nestedhap_walk_L0_p2m(struct p2m_domain *p2m, paddr_t L1_gpa, paddr_t *L0_gpa,
>  direct_mmio_out:
>      *L0_gpa = (mfn_x(mfn) << PAGE_SHIFT) + (L1_gpa & ~PAGE_MASK);
>  out:
> -    __put_gfn(p2m, L1_gpa >> PAGE_SHIFT);
> +    __put_gfn(p2m, l1_gfn);
>      return rc;
>  }
>  
> diff --git a/xen/arch/x86/mm/mem_access.c b/xen/arch/x86/mm/mem_access.c
> index 30c2f1a..caa33c3 100644
> --- a/xen/arch/x86/mm/mem_access.c
> +++ b/xen/arch/x86/mm/mem_access.c
> @@ -263,7 +263,6 @@ int p2m_set_altp2m_mem_access(struct domain *d, struct p2m_domain *hp2m,
>      p2m_type_t t;
>      p2m_access_t old_a;
>      unsigned int page_order;
> -    unsigned long gfn_l = gfn_x(gfn);
>      int rc;
>  
>      mfn = ap2m->get_entry(ap2m, gfn, &t, &old_a, 0, NULL, NULL);
> @@ -272,7 +271,7 @@ int p2m_set_altp2m_mem_access(struct domain *d, struct p2m_domain *hp2m,
>      if ( !mfn_valid(mfn) )
>      {
>  
> -        mfn = __get_gfn_type_access(hp2m, gfn_l, &t, &old_a,
> +        mfn = __get_gfn_type_access(hp2m, gfn, &t, &old_a,
>                                      P2M_ALLOC | P2M_UNSHARE, &page_order, 0);
>  
>          rc = -ESRCH;
> @@ -283,7 +282,7 @@ int p2m_set_altp2m_mem_access(struct domain *d, struct p2m_domain *hp2m,
>          if ( page_order != PAGE_ORDER_4K )
>          {
>              unsigned long mask = ~((1UL << page_order) - 1);
> -            gfn_t gfn2 = _gfn(gfn_l & mask);
> +            gfn_t gfn2 = _gfn(gfn_x(gfn) & mask);
>              mfn_t mfn2 = _mfn(mfn_x(mfn) & mask);
>  
>              rc = ap2m->set_entry(ap2m, gfn2, mfn2, page_order, t, old_a, 1);
> diff --git a/xen/arch/x86/mm/mem_sharing.c b/xen/arch/x86/mm/mem_sharing.c
> index 573d354..7f2bf80 100644
> --- a/xen/arch/x86/mm/mem_sharing.c
> +++ b/xen/arch/x86/mm/mem_sharing.c
> @@ -499,7 +499,7 @@ static int audit(void)
>                  errors++;
>                  continue;
>              }
> -            o_mfn = get_gfn_query_unlocked(d, g->gfn, &t); 
> +            o_mfn = get_gfn_query_unlocked(d, _gfn(g->gfn), &t);
>              if ( !mfn_eq(o_mfn, mfn) )
>              {
>                  MEM_SHARING_DEBUG("Incorrect P2M for d=%hu, PFN=%lx."
> @@ -732,12 +732,12 @@ static int debug_gfn(struct domain *d, gfn_t gfn)
>      mfn_t mfn;
>      int num_refs;
>  
> -    mfn = get_gfn_query(d, gfn_x(gfn), &p2mt);
> +    mfn = get_gfn_query(d, gfn, &p2mt);
>  
>      MEM_SHARING_DEBUG("Debug for dom%d, gfn=%" PRI_gfn "\n", 
>                        d->domain_id, gfn_x(gfn));
>      num_refs = debug_mfn(mfn);
> -    put_gfn(d, gfn_x(gfn));
> +    put_gfn(d, gfn);
>  
>      return num_refs;
>  }
> @@ -775,7 +775,7 @@ static int nominate_page(struct domain *d, gfn_t gfn,
>  
>      *phandle = 0UL;
>  
> -    mfn = get_gfn_type_access(hp2m, gfn_x(gfn), &p2mt, &p2ma, 0, NULL);
> +    mfn = get_gfn_type_access(hp2m, gfn, &p2mt, &p2ma, 0, NULL);
>  
>      /* Check if mfn is valid */
>      ret = -EINVAL;
> @@ -820,7 +820,7 @@ static int nominate_page(struct domain *d, gfn_t gfn,
>              if ( !ap2m )
>                  continue;
>  
> -            amfn = __get_gfn_type_access(ap2m, gfn_x(gfn), &ap2mt, &ap2ma,
> +            amfn = __get_gfn_type_access(ap2m, gfn, &ap2mt, &ap2ma,
>                                           0, NULL, false);
>              if ( mfn_valid(amfn) && (!mfn_eq(amfn, mfn) || ap2ma != p2ma) )
>              {
> @@ -885,7 +885,7 @@ static int nominate_page(struct domain *d, gfn_t gfn,
>      ret = 0;
>  
>  out:
> -    put_gfn(d, gfn_x(gfn));
> +    put_gfn(d, gfn);
>      return ret;
>  }
>  
> @@ -1124,11 +1124,11 @@ int __mem_sharing_unshare_page(struct domain *d,
>      int last_gfn;
>      gfn_info_t *gfn_info = NULL;
>     
> -    mfn = get_gfn(d, gfn, &p2mt);
> +    mfn = get_gfn(d, _gfn(gfn), &p2mt);
>      
>      /* Has someone already unshared it? */
>      if ( !p2m_is_shared(p2mt) ) {
> -        put_gfn(d, gfn);
> +        put_gfn(d, _gfn(gfn));
>          return 0;
>      }
>  
> @@ -1175,7 +1175,7 @@ int __mem_sharing_unshare_page(struct domain *d,
>          {
>              if ( !get_page(page, d) )
>              {
> -                put_gfn(d, gfn);
> +                put_gfn(d, _gfn(gfn));
>                  domain_crash(d);
>                  return -EOVERFLOW;
>              }
> @@ -1183,7 +1183,7 @@ int __mem_sharing_unshare_page(struct domain *d,
>                  put_page(page);
>              put_page(page);
>          }
> -        put_gfn(d, gfn);
> +        put_gfn(d, _gfn(gfn));
>  
>          return 0;
>      }
> @@ -1202,7 +1202,7 @@ int __mem_sharing_unshare_page(struct domain *d,
>          /* Undo dec of nr_saved_mfns, as the retry will decrease again. */
>          atomic_inc(&nr_saved_mfns);
>          mem_sharing_page_unlock(old_page);
> -        put_gfn(d, gfn);
> +        put_gfn(d, _gfn(gfn));
>          /* Caller is responsible for placing an event
>           * in the ring */
>          return -ENOMEM;
> @@ -1230,7 +1230,7 @@ int __mem_sharing_unshare_page(struct domain *d,
>       * marking dirty is feasible */
>      paging_mark_dirty(d, page_to_mfn(page));
>      /* We do not need to unlock a private page */
> -    put_gfn(d, gfn);
> +    put_gfn(d, _gfn(gfn));
>      return 0;
>  }
>  
> diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
> index f52a71e..19b383f 100644
> --- a/xen/arch/x86/mm/p2m.c
> +++ b/xen/arch/x86/mm/p2m.c
> @@ -409,12 +409,11 @@ void p2m_unlock_and_tlb_flush(struct p2m_domain *p2m)
>          mm_write_unlock(&p2m->lock);
>  }
>  
> -mfn_t __get_gfn_type_access(struct p2m_domain *p2m, unsigned long gfn_l,
> +mfn_t __get_gfn_type_access(struct p2m_domain *p2m, gfn_t gfn,
>                      p2m_type_t *t, p2m_access_t *a, p2m_query_t q,
>                      unsigned int *page_order, bool_t locked)
>  {
>      mfn_t mfn;
> -    gfn_t gfn = _gfn(gfn_l);
>  
>      /* Unshare makes no sense withuot populate. */
>      if ( q & P2M_UNSHARE )
> @@ -425,7 +424,7 @@ mfn_t __get_gfn_type_access(struct p2m_domain *p2m, unsigned long gfn_l,
>          /* Not necessarily true, but for non-translated guests, we claim
>           * it's the most generic kind of memory */
>          *t = p2m_ram_rw;
> -        return _mfn(gfn_l);
> +        return _mfn(gfn_x(gfn));
>      }
>  
>      if ( locked )
> @@ -439,8 +438,8 @@ mfn_t __get_gfn_type_access(struct p2m_domain *p2m, unsigned long gfn_l,
>          ASSERT(p2m_is_hostp2m(p2m));
>          /* Try to unshare. If we fail, communicate ENOMEM without
>           * sleeping. */
> -        if ( mem_sharing_unshare_page(p2m->domain, gfn_l, 0) < 0 )
> -            mem_sharing_notify_enomem(p2m->domain, gfn_l, false);
> +        if ( mem_sharing_unshare_page(p2m->domain, gfn_x(gfn), 0) < 0 )
> +            mem_sharing_notify_enomem(p2m->domain, gfn_x(gfn), false);
>          mfn = p2m->get_entry(p2m, gfn, t, a, q, page_order, NULL);
>      }
>  
> @@ -455,7 +454,7 @@ mfn_t __get_gfn_type_access(struct p2m_domain *p2m, unsigned long gfn_l,
>      return mfn;
>  }
>  
> -void __put_gfn(struct p2m_domain *p2m, unsigned long gfn)
> +void __put_gfn(struct p2m_domain *p2m, gfn_t gfn)
>  {
>      if ( !p2m || !paging_mode_translate(p2m->domain) )
>          /* Nothing to do in this case */
> @@ -484,7 +483,7 @@ struct page_info *p2m_get_page_from_gfn(
>      {
>          /* Fast path: look up and get out */
>          p2m_read_lock(p2m);
> -        mfn = __get_gfn_type_access(p2m, gfn_x(gfn), t, a, 0, NULL, 0);
> +        mfn = __get_gfn_type_access(p2m, gfn, t, a, 0, NULL, 0);
>          if ( p2m_is_any_ram(*t) && mfn_valid(mfn)
>               && !((q & P2M_UNSHARE) && p2m_is_shared(*t)) )
>          {
> @@ -513,14 +512,14 @@ struct page_info *p2m_get_page_from_gfn(
>      }
>  
>      /* Slow path: take the write lock and do fixups */
> -    mfn = get_gfn_type_access(p2m, gfn_x(gfn), t, a, q, NULL);
> +    mfn = get_gfn_type_access(p2m, gfn, t, a, q, NULL);
>      if ( p2m_is_ram(*t) && mfn_valid(mfn) )
>      {
>          page = mfn_to_page(mfn);
>          if ( !get_page(page, p2m->domain) )
>              page = NULL;
>      }
> -    put_gfn(p2m->domain, gfn_x(gfn));
> +    put_gfn(p2m->domain, gfn);
>  
>      return page;
>  }
> @@ -1278,7 +1277,7 @@ int set_shared_p2m_entry(struct domain *d, unsigned long gfn_l, mfn_t mfn)
>      if ( rc )
>          gdprintk(XENLOG_ERR,
>                   "p2m_set_entry failed! mfn=%08lx rc:%d\n",
> -                 mfn_x(get_gfn_query_unlocked(p2m->domain, gfn_l, &ot)), rc);
> +                 mfn_x(get_gfn_query_unlocked(p2m->domain, gfn, &ot)), rc);
>      return rc;
>  }
>  
> @@ -2187,8 +2186,7 @@ bool p2m_altp2m_lazy_copy(struct vcpu *v, paddr_t gpa,
>  
>      ASSERT(p2m_locked_by_me(hp2m));
>  
> -    mfn = get_gfn_type_access(ap2m, gfn_x(gfn), &p2mt, &p2ma,
> -                              0, &page_order);
> +    mfn = get_gfn_type_access(ap2m, gfn, &p2mt, &p2ma, 0, &page_order);
>  
>      /* Entry already present in ap2m?  Caller should handle the fault. */
>      if ( !mfn_eq(mfn, INVALID_MFN) )
> @@ -2197,8 +2195,7 @@ bool p2m_altp2m_lazy_copy(struct vcpu *v, paddr_t gpa,
>          goto put_ap2m;
>      }
>  
> -    mfn = get_gfn_type_access(hp2m, gfn_x(gfn), &p2mt, &p2ma,
> -                              P2M_ALLOC, &page_order);
> +    mfn = get_gfn_type_access(hp2m, gfn, &p2mt, &p2ma, P2M_ALLOC, &page_order);
>  
>      /* Entry not present in hp2m?  Caller should handle the fault. */
>      if ( mfn_eq(mfn, INVALID_MFN) )
> @@ -2230,9 +2227,9 @@ bool p2m_altp2m_lazy_copy(struct vcpu *v, paddr_t gpa,
>      ret = true;
>  
>  put_hp2m:
> -    __put_gfn(hp2m, gfn_x(gfn));
> +    __put_gfn(hp2m, gfn);
>  put_ap2m:
> -    __put_gfn(ap2m, gfn_x(gfn));
> +    __put_gfn(ap2m, gfn);
>  
>      return ret;
>  }
> @@ -2396,7 +2393,7 @@ int p2m_change_altp2m_gfn(struct domain *d, unsigned int idx,
>      /* Check host p2m if no valid entry in alternate */
>      if ( !mfn_valid(mfn) )
>      {
> -        mfn = __get_gfn_type_access(hp2m, gfn_x(old_gfn), &t, &a,
> +        mfn = __get_gfn_type_access(hp2m, old_gfn, &t, &a,
>                                      P2M_ALLOC, &page_order, 0);
>  
>          if ( !mfn_valid(mfn) || t != p2m_ram_rw )
> @@ -2477,7 +2474,7 @@ int p2m_altp2m_propagate_change(struct domain *d, gfn_t gfn,
>              continue;
>  
>          p2m = d->arch.altp2m_p2m[i];
> -        m = get_gfn_type_access(p2m, gfn_x(gfn), &t, &a, 0, NULL);
> +        m = get_gfn_type_access(p2m, gfn, &t, &a, 0, NULL);
>  
>          /* Check for a dropped page that may impact this altp2m */
>          if ( mfn_eq(mfn, INVALID_MFN) &&
> @@ -2492,7 +2489,7 @@ int p2m_altp2m_propagate_change(struct domain *d, gfn_t gfn,
>              else
>              {
>                  /* At least 2 altp2m's impacted, so reset everything */
> -                __put_gfn(p2m, gfn_x(gfn));
> +                __put_gfn(p2m, gfn);
>  
>                  for ( i = 0; i < MAX_ALTP2M; i++ )
>                  {
> @@ -2519,7 +2516,7 @@ int p2m_altp2m_propagate_change(struct domain *d, gfn_t gfn,
>                  ret = rc;
>          }
>  
> -        __put_gfn(p2m, gfn_x(gfn));
> +        __put_gfn(p2m, gfn);
>      }
>  
>      altp2m_list_unlock(d);
> @@ -2590,7 +2587,7 @@ void audit_p2m(struct domain *d,
>              continue;
>          }
>  
> -        p2mfn = get_gfn_type_access(p2m, gfn, &type, &p2ma, 0, NULL);
> +        p2mfn = get_gfn_type_access(p2m, _gfn(gfn), &type, &p2ma, 0, NULL);
>          if ( mfn_x(p2mfn) != mfn )
>          {
>              mpbad++;
> @@ -2605,7 +2602,7 @@ void audit_p2m(struct domain *d,
>               * blow away the m2p entry. */
>              set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY);
>          }
> -        __put_gfn(p2m, gfn);
> +        __put_gfn(p2m, _gfn(gfn));
>  
>          P2M_PRINTK("OK: mfn=%#lx, gfn=%#lx, p2mfn=%#lx\n",
>                         mfn, gfn, mfn_x(p2mfn));
> @@ -2698,7 +2695,7 @@ int p2m_add_foreign(struct domain *tdom, unsigned long fgfn,
>      mfn = page_to_mfn(page);
>  
>      /* Remove previously mapped page if it is present. */
> -    prev_mfn = get_gfn(tdom, gpfn, &p2mt_prev);
> +    prev_mfn = get_gfn(tdom, _gfn(gpfn), &p2mt_prev);
>      if ( mfn_valid(prev_mfn) )
>      {
>          if ( is_xen_heap_mfn(mfn_x(prev_mfn)) )
> @@ -2729,7 +2726,7 @@ int p2m_add_foreign(struct domain *tdom, unsigned long fgfn,
>       * after set_foreign_p2m_entry so another cpu doesn't populate the gpfn
>       * before us.
>       */
> -    put_gfn(tdom, gpfn);
> +    put_gfn(tdom, _gfn(gpfn));
>  
>  out:
>      if ( fdom )
> diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c
> index 61304d7..85ce761 100644
> --- a/xen/arch/x86/mm/shadow/common.c
> +++ b/xen/arch/x86/mm/shadow/common.c
> @@ -3338,7 +3338,7 @@ int shadow_track_dirty_vram(struct domain *d,
>  
>          /* Iterate over VRAM to track dirty bits. */
>          for ( i = 0; i < nr; i++ ) {
> -            mfn_t mfn = get_gfn_query_unlocked(d, begin_pfn + i, &t);
> +            mfn_t mfn = get_gfn_query_unlocked(d, _gfn(begin_pfn + i), &t);
>              struct page_info *page;
>              int dirty = 0;
>              paddr_t sl1ma = dirty_vram->sl1ma[i];
> @@ -3418,7 +3418,7 @@ int shadow_track_dirty_vram(struct domain *d,
>               * write access */
>              for ( i = begin_pfn; i < end_pfn; i++ )
>              {
> -                mfn_t mfn = get_gfn_query_unlocked(d, i, &t);
> +                mfn_t mfn = get_gfn_query_unlocked(d, _gfn(i), &t);
>                  if ( !mfn_eq(mfn, INVALID_MFN) )
>                      flush_tlb |= sh_remove_write_access(d, mfn, 1, 0);
>              }
> diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c
> index 7e9cbc6..de3fcd7 100644
> --- a/xen/arch/x86/mm/shadow/multi.c
> +++ b/xen/arch/x86/mm/shadow/multi.c
> @@ -2126,7 +2126,8 @@ static int validate_gl4e(struct vcpu *v, void *new_ge, mfn_t sl4mfn, void *se)
>           !guest_l4e_rsvd_bits(v, new_gl4e) )
>      {
>          gfn_t gl3gfn = guest_l4e_get_gfn(new_gl4e);
> -        mfn_t gl3mfn = get_gfn_query_unlocked(d, gfn_x(gl3gfn), &p2mt);
> +        mfn_t gl3mfn = get_gfn_query_unlocked(d, gl3gfn, &p2mt);
> +
>          if ( p2m_is_ram(p2mt) )
>              sl3mfn = get_shadow_status(d, gl3mfn, SH_type_l3_shadow);
>          else if ( p2mt != p2m_populate_on_demand )
> @@ -2185,7 +2186,8 @@ static int validate_gl3e(struct vcpu *v, void *new_ge, mfn_t sl3mfn, void *se)
>           !guest_l3e_rsvd_bits(v, new_gl3e) )
>      {
>          gfn_t gl2gfn = guest_l3e_get_gfn(new_gl3e);
> -        mfn_t gl2mfn = get_gfn_query_unlocked(d, gfn_x(gl2gfn), &p2mt);
> +        mfn_t gl2mfn = get_gfn_query_unlocked(d, gl2gfn, &p2mt);
> +
>          if ( p2m_is_ram(p2mt) )
>              sl2mfn = get_shadow_status(d, gl2mfn, SH_type_l2_shadow);
>          else if ( p2mt != p2m_populate_on_demand )
> @@ -2236,7 +2238,8 @@ static int validate_gl2e(struct vcpu *v, void *new_ge, mfn_t sl2mfn, void *se)
>          }
>          else
>          {
> -            mfn_t gl1mfn = get_gfn_query_unlocked(d, gfn_x(gl1gfn), &p2mt);
> +            mfn_t gl1mfn = get_gfn_query_unlocked(d, gl1gfn, &p2mt);
> +
>              if ( p2m_is_ram(p2mt) )
>                  sl1mfn = get_shadow_status(d, gl1mfn, SH_type_l1_shadow);
>              else if ( p2mt != p2m_populate_on_demand )
> @@ -2270,7 +2273,7 @@ static int validate_gl1e(struct vcpu *v, void *new_ge, mfn_t sl1mfn, void *se)
>           !guest_l1e_rsvd_bits(v, new_gl1e) )
>      {
>          gfn = guest_l1e_get_gfn(new_gl1e);
> -        gmfn = get_gfn_query_unlocked(d, gfn_x(gfn), &p2mt);
> +        gmfn = get_gfn_query_unlocked(d, gfn, &p2mt);
>      }
>  
>      l1e_propagate_from_guest(v, new_gl1e, gmfn, &new_sl1e, ft_prefetch, p2mt);
> @@ -2335,7 +2338,7 @@ void sh_resync_l1(struct vcpu *v, mfn_t gl1mfn, mfn_t snpmfn)
>                   !guest_l1e_rsvd_bits(v, gl1e) )
>              {
>                  gfn = guest_l1e_get_gfn(gl1e);
> -                gmfn = get_gfn_query_unlocked(d, gfn_x(gfn), &p2mt);
> +                gmfn = get_gfn_query_unlocked(d, gfn, &p2mt);
>              }
>  
>              l1e_propagate_from_guest(v, gl1e, gmfn, &nsl1e, ft_prefetch, p2mt);
> @@ -2615,7 +2618,7 @@ static void sh_prefetch(struct vcpu *v, walk_t *gw,
>               !guest_l1e_rsvd_bits(v, gl1e) )
>          {
>              gfn = guest_l1e_get_gfn(gl1e);
> -            gmfn = get_gfn_query_unlocked(d, gfn_x(gfn), &p2mt);
> +            gmfn = get_gfn_query_unlocked(d, gfn, &p2mt);
>          }
>          else
>          {
> @@ -3071,7 +3074,7 @@ static int sh_page_fault(struct vcpu *v,
>          SHADOW_PRINTK("BAD gfn=%"SH_PRI_gfn" gmfn=%"PRI_mfn"\n",
>                        gfn_x(gfn), mfn_x(gmfn));
>          sh_reset_early_unshadow(v);
> -        put_gfn(d, gfn_x(gfn));
> +        put_gfn(d, gfn);
>          goto propagate;
>      }
>  
> @@ -3117,7 +3120,7 @@ static int sh_page_fault(struct vcpu *v,
>      if ( rc & GW_RMWR_REWALK )
>      {
>          paging_unlock(d);
> -        put_gfn(d, gfn_x(gfn));
> +        put_gfn(d, gfn);
>          goto rewalk;
>      }
>  #endif /* OOS */
> @@ -3126,7 +3129,7 @@ static int sh_page_fault(struct vcpu *v,
>      {
>          perfc_incr(shadow_inconsistent_gwalk);
>          paging_unlock(d);
> -        put_gfn(d, gfn_x(gfn));
> +        put_gfn(d, gfn);
>          goto rewalk;
>      }
>  
> @@ -3153,7 +3156,7 @@ static int sh_page_fault(struct vcpu *v,
>          ASSERT(d->is_shutting_down);
>  #endif
>          paging_unlock(d);
> -        put_gfn(d, gfn_x(gfn));
> +        put_gfn(d, gfn);
>          trace_shadow_gen(TRC_SHADOW_DOMF_DYING, va);
>          return 0;
>      }
> @@ -3171,7 +3174,7 @@ static int sh_page_fault(struct vcpu *v,
>           * failed. We cannot safely continue since some page is still
>           * OOS but not in the hash table anymore. */
>          paging_unlock(d);
> -        put_gfn(d, gfn_x(gfn));
> +        put_gfn(d, gfn);
>          return 0;
>      }
>  
> @@ -3181,7 +3184,7 @@ static int sh_page_fault(struct vcpu *v,
>      {
>          perfc_incr(shadow_inconsistent_gwalk);
>          paging_unlock(d);
> -        put_gfn(d, gfn_x(gfn));
> +        put_gfn(d, gfn);
>          goto rewalk;
>      }
>  #endif /* OOS */
> @@ -3267,7 +3270,7 @@ static int sh_page_fault(struct vcpu *v,
>      SHADOW_PRINTK("fixed\n");
>      shadow_audit_tables(v);
>      paging_unlock(d);
> -    put_gfn(d, gfn_x(gfn));
> +    put_gfn(d, gfn);
>      return EXCRET_fault_fixed;
>  
>   emulate:
> @@ -3337,7 +3340,7 @@ static int sh_page_fault(struct vcpu *v,
>      sh_audit_gw(v, &gw);
>      shadow_audit_tables(v);
>      paging_unlock(d);
> -    put_gfn(d, gfn_x(gfn));
> +    put_gfn(d, gfn);
>  
>      this_cpu(trace_emulate_write_val) = 0;
>  
> @@ -3521,7 +3524,7 @@ static int sh_page_fault(struct vcpu *v,
>      shadow_audit_tables(v);
>      sh_reset_early_unshadow(v);
>      paging_unlock(d);
> -    put_gfn(d, gfn_x(gfn));
> +    put_gfn(d, gfn);
>      trace_shadow_gen(TRC_SHADOW_MMIO, va);
>      return (handle_mmio_with_translation(va, gpa >> PAGE_SHIFT, access)
>              ? EXCRET_fault_fixed : 0);
> @@ -3535,7 +3538,7 @@ static int sh_page_fault(struct vcpu *v,
>      shadow_audit_tables(v);
>      sh_reset_early_unshadow(v);
>      paging_unlock(d);
> -    put_gfn(d, gfn_x(gfn));
> +    put_gfn(d, gfn);
>  
>  propagate:
>      trace_not_shadow_fault(gw.l1e, va);
> @@ -4116,7 +4119,7 @@ sh_update_cr3(struct vcpu *v, int do_locking, bool noflush)
>              if ( guest_l3e_get_flags(gl3e[i]) & _PAGE_PRESENT )
>              {
>                  gl2gfn = guest_l3e_get_gfn(gl3e[i]);
> -                gl2mfn = get_gfn_query_unlocked(d, gfn_x(gl2gfn), &p2mt);
> +                gl2mfn = get_gfn_query_unlocked(d, gl2gfn, &p2mt);
>                  if ( p2m_is_ram(p2mt) )
>                      flush |= sh_remove_write_access(d, gl2mfn, 2, 0);
>              }
> @@ -4129,7 +4132,7 @@ sh_update_cr3(struct vcpu *v, int do_locking, bool noflush)
>              if ( guest_l3e_get_flags(gl3e[i]) & _PAGE_PRESENT )
>              {
>                  gl2gfn = guest_l3e_get_gfn(gl3e[i]);
> -                gl2mfn = get_gfn_query_unlocked(d, gfn_x(gl2gfn), &p2mt);
> +                gl2mfn = get_gfn_query_unlocked(d, gl2gfn, &p2mt);
>                  if ( p2m_is_ram(p2mt) )
>                      sh_set_toplevel_shadow(v, i, gl2mfn, (i == 3)
>                                             ? SH_type_l2h_shadow
> @@ -4536,7 +4539,7 @@ static void sh_pagetable_dying(paddr_t gpa)
>      p2m_type_t p2mt;
>      char *gl3pa = NULL;
>      guest_l3e_t *gl3e = NULL;
> -    unsigned long l3gfn;
> +    gfn_t l3gfn;
>      mfn_t l3mfn;
>  
>      gcr3 = v->arch.hvm.guest_cr[3];
> @@ -4544,8 +4547,8 @@ static void sh_pagetable_dying(paddr_t gpa)
>      if ( gcr3 == gpa )
>          fast_path = 1;
>  
> -    l3gfn = gpa >> PAGE_SHIFT;
> -    l3mfn = get_gfn_query(d, _gfn(l3gfn), &p2mt);
> +    l3gfn = gaddr_to_gfn(gpa);
> +    l3mfn = get_gfn_query(d, l3gfn, &p2mt);
>      if ( !mfn_valid(l3mfn) || !p2m_is_ram(p2mt) )
>      {
>          printk(XENLOG_DEBUG "sh_pagetable_dying: gpa not valid %"PRIpaddr"\n",
> @@ -4573,8 +4576,7 @@ static void sh_pagetable_dying(paddr_t gpa)
>          else
>          {
>              /* retrieving the l2s */
> -            gmfn = get_gfn_query_unlocked(d, gfn_x(guest_l3e_get_gfn(gl3e[i])),
> -                                          &p2mt);
> +            gmfn = get_gfn_query_unlocked(d, guest_l3e_get_gfn(gl3e[i]), &p2mt);
>              smfn = unlikely(mfn_eq(gmfn, INVALID_MFN))
>                     ? INVALID_MFN
>                     : shadow_hash_lookup(d, mfn_x(gmfn), SH_type_l2_pae_shadow);
> @@ -4609,10 +4611,11 @@ static void sh_pagetable_dying(paddr_t gpa)
>  {
>      struct vcpu *v = current;
>      struct domain *d = v->domain;
> +    gfn_t gfn = gaddr_to_gfn(gpa);
>      mfn_t smfn, gmfn;
>      p2m_type_t p2mt;
>  
> -    gmfn = get_gfn_query(d, _gfn(gpa >> PAGE_SHIFT), &p2mt);
> +    gmfn = get_gfn_query(d, gfn, &p2mt);
>      paging_lock(d);
>  
>  #if GUEST_PAGING_LEVELS == 2
> @@ -4637,7 +4640,7 @@ static void sh_pagetable_dying(paddr_t gpa)
>      v->arch.paging.shadow.pagetable_dying = 1;
>  
>      paging_unlock(d);
> -    put_gfn(d, gpa >> PAGE_SHIFT);
> +    put_gfn(d, gfn);
>  }
>  #endif
>  
> @@ -4759,7 +4762,7 @@ int sh_audit_l1_table(struct vcpu *v, mfn_t sl1mfn, mfn_t x)
>              {
>                  gfn = guest_l1e_get_gfn(*gl1e);
>                  mfn = shadow_l1e_get_mfn(*sl1e);
> -                gmfn = get_gfn_query_unlocked(v->domain, gfn_x(gfn), &p2mt);
> +                gmfn = get_gfn_query_unlocked(v->domain, gfn, &p2mt);
>                  if ( !p2m_is_grant(p2mt) && !mfn_eq(gmfn, mfn) )
>                      AUDIT_FAIL(1, "bad translation: gfn %" SH_PRI_gfn
>                                 " --> %" PRI_mfn " != mfn %" PRI_mfn,
> @@ -4832,16 +4835,15 @@ int sh_audit_l2_table(struct vcpu *v, mfn_t sl2mfn, mfn_t x)
>              gmfn = (guest_l2e_get_flags(*gl2e) & _PAGE_PSE)
>                  ? get_fl1_shadow_status(d, gfn)
>                  : get_shadow_status(d,
> -                    get_gfn_query_unlocked(d, gfn_x(gfn),
> -                                        &p2mt), SH_type_l1_shadow);
> +                    get_gfn_query_unlocked(d, gfn, &p2mt), SH_type_l1_shadow);
>              if ( !mfn_eq(gmfn, mfn) )
>                  AUDIT_FAIL(2, "bad translation: gfn %" SH_PRI_gfn
>                             " (--> %" PRI_mfn ")"
>                             " --> %" PRI_mfn " != mfn %" PRI_mfn,
>                             gfn_x(gfn),
>                             (guest_l2e_get_flags(*gl2e) & _PAGE_PSE) ? 0
> -                           : mfn_x(get_gfn_query_unlocked(d,
> -                                   gfn_x(gfn), &p2mt)), mfn_x(gmfn), mfn_x(mfn));
> +                           : mfn_x(get_gfn_query_unlocked(d, gfn, &p2mt)),
> +                           mfn_x(gmfn), mfn_x(mfn));
>          }
>      });
>      unmap_domain_page(gp);
> @@ -4881,8 +4883,7 @@ int sh_audit_l3_table(struct vcpu *v, mfn_t sl3mfn, mfn_t x)
>          {
>              gfn = guest_l3e_get_gfn(*gl3e);
>              mfn = shadow_l3e_get_mfn(*sl3e);
> -            gmfn = get_shadow_status(d, get_gfn_query_unlocked(
> -                                        d, gfn_x(gfn), &p2mt),
> +            gmfn = get_shadow_status(d, get_gfn_query_unlocked(d, gfn, &p2mt),
>                                       ((GUEST_PAGING_LEVELS == 3 ||
>                                         is_pv_32bit_domain(d))
>                                        && !shadow_mode_external(d)
> @@ -4931,8 +4932,7 @@ int sh_audit_l4_table(struct vcpu *v, mfn_t sl4mfn, mfn_t x)
>          {
>              gfn = guest_l4e_get_gfn(*gl4e);
>              mfn = shadow_l4e_get_mfn(*sl4e);
> -            gmfn = get_shadow_status(d, get_gfn_query_unlocked(
> -                                     d, gfn_x(gfn), &p2mt),
> +            gmfn = get_shadow_status(d, get_gfn_query_unlocked(d, gfn, &p2mt),
>                                       SH_type_l3_shadow);
>              if ( !mfn_eq(gmfn, mfn) )
>                  AUDIT_FAIL(4, "bad translation: gfn %" SH_PRI_gfn
> diff --git a/xen/arch/x86/mm/shadow/types.h b/xen/arch/x86/mm/shadow/types.h
> index d509674..f688919 100644
> --- a/xen/arch/x86/mm/shadow/types.h
> +++ b/xen/arch/x86/mm/shadow/types.h
> @@ -193,10 +193,6 @@ static inline shadow_l4e_t shadow_l4e_from_mfn(mfn_t mfn, u32 flags)
>  })
>  #endif
>  
> - /* Override get_gfn to work with gfn_t */
> -#undef get_gfn_query
> -#define get_gfn_query(d, g, t) get_gfn_type((d), gfn_x(g), (t), 0)
> -
>  /* The shadow types needed for the various levels. */
>  
>  #if GUEST_PAGING_LEVELS == 2
> diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
> index f7860f6..54f909f 100644
> --- a/xen/common/grant_table.c
> +++ b/xen/common/grant_table.c
> @@ -2099,7 +2099,7 @@ gnttab_transfer(
>          {
>              p2m_type_t p2mt;
>  
> -            mfn = get_gfn_unshare(d, gop.mfn, &p2mt);
> +            mfn = get_gfn_unshare(d, _gfn(gop.mfn), &p2mt);
>              if ( p2m_is_shared(p2mt) || !p2m_is_valid(p2mt) )
>                  mfn = INVALID_MFN;
>          }
> @@ -2111,7 +2111,7 @@ gnttab_transfer(
>          if ( unlikely(!mfn_valid(mfn)) )
>          {
>  #ifdef CONFIG_X86
> -            put_gfn(d, gop.mfn);
> +            put_gfn(d, _gfn(gop.mfn));
>  #endif
>              gdprintk(XENLOG_INFO, "out-of-range %lx\n", (unsigned long)gop.mfn);
>              gop.status = GNTST_bad_page;
> @@ -2122,7 +2122,7 @@ gnttab_transfer(
>          if ( (rc = steal_page(d, page, 0)) < 0 )
>          {
>  #ifdef CONFIG_X86
> -            put_gfn(d, gop.mfn);
> +            put_gfn(d, _gfn(gop.mfn));
>  #endif
>              gop.status = rc == -EINVAL ? GNTST_bad_page : GNTST_general_error;
>              goto copyback;
> @@ -2154,7 +2154,7 @@ gnttab_transfer(
>              rcu_unlock_domain(e);
>          put_gfn_and_copyback:
>  #ifdef CONFIG_X86
> -            put_gfn(d, gop.mfn);
> +            put_gfn(d, _gfn(gop.mfn));
>  #endif
>              page->count_info &= ~(PGC_count_mask|PGC_allocated);
>              free_domheap_page(page);
> @@ -2243,7 +2243,7 @@ gnttab_transfer(
>  
>          spin_unlock(&e->page_alloc_lock);
>  #ifdef CONFIG_X86
> -        put_gfn(d, gop.mfn);
> +        put_gfn(d, _gfn(gop.mfn));
>  #endif
>  
>          TRACE_1D(TRC_MEM_PAGE_GRANT_TRANSFER, e->domain_id);
> diff --git a/xen/common/memory.c b/xen/common/memory.c
> index 175bd62..c59a017 100644
> --- a/xen/common/memory.c
> +++ b/xen/common/memory.c
> @@ -303,10 +303,10 @@ int guest_remove_page(struct domain *d, unsigned long gmfn)
>      int rc;
>  
>  #ifdef CONFIG_X86
> -    mfn = get_gfn_query(d, gmfn, &p2mt);
> +    mfn = get_gfn_query(d, _gfn(gmfn), &p2mt);
>      if ( unlikely(p2mt == p2m_invalid) || unlikely(p2mt == p2m_mmio_dm) )
>      {
> -        put_gfn(d, gmfn);
> +        put_gfn(d, _gfn(gmfn));
>  
>          return -ENOENT;
>      }
> @@ -336,7 +336,7 @@ int guest_remove_page(struct domain *d, unsigned long gmfn)
>              goto out_put_gfn;
>          }
>  
> -        put_gfn(d, gmfn);
> +        put_gfn(d, _gfn(gmfn));
>  
>          if ( page )
>          {
> @@ -359,7 +359,7 @@ int guest_remove_page(struct domain *d, unsigned long gmfn)
>      if ( unlikely(!mfn_valid(mfn)) )
>      {
>  #ifdef CONFIG_X86
> -        put_gfn(d, gmfn);
> +        put_gfn(d, _gfn(gmfn));
>  #endif
>          gdprintk(XENLOG_INFO, "Domain %u page number %lx invalid\n",
>                  d->domain_id, gmfn);
> @@ -382,7 +382,7 @@ int guest_remove_page(struct domain *d, unsigned long gmfn)
>              goto out_put_gfn;
>          }
>          /* Maybe the mfn changed */
> -        mfn = get_gfn_query_unlocked(d, gmfn, &p2mt);
> +        mfn = get_gfn_query_unlocked(d, _gfn(gmfn), &p2mt);
>          ASSERT(!p2m_is_shared(p2mt));
>      }
>  #endif /* CONFIG_X86 */
> @@ -391,7 +391,7 @@ int guest_remove_page(struct domain *d, unsigned long gmfn)
>      if ( unlikely(!get_page(page, d)) )
>      {
>  #ifdef CONFIG_X86
> -        put_gfn(d, gmfn);
> +        put_gfn(d, _gfn(gmfn));
>  #endif
>          gdprintk(XENLOG_INFO, "Bad page free for domain %u\n", d->domain_id);
>  
> @@ -416,7 +416,7 @@ int guest_remove_page(struct domain *d, unsigned long gmfn)
>  
>  #ifdef CONFIG_X86
>   out_put_gfn:
> -    put_gfn(d, gmfn);
> +    put_gfn(d, _gfn(gmfn));
>  #endif
>  
>      /*
> @@ -651,10 +651,10 @@ static long memory_exchange(XEN_GUEST_HANDLE_PARAM(xen_memory_exchange_t) arg)
>                  p2m_type_t p2mt;
>  
>                  /* Shared pages cannot be exchanged */
> -                mfn = get_gfn_unshare(d, gmfn + k, &p2mt);
> +                mfn = get_gfn_unshare(d, _gfn(gmfn + k), &p2mt);
>                  if ( p2m_is_shared(p2mt) )
>                  {
> -                    put_gfn(d, gmfn + k);
> +                    put_gfn(d, _gfn(gmfn + k));
>                      rc = -ENOMEM;
>                      goto fail; 
>                  }
> @@ -664,7 +664,7 @@ static long memory_exchange(XEN_GUEST_HANDLE_PARAM(xen_memory_exchange_t) arg)
>                  if ( unlikely(!mfn_valid(mfn)) )
>                  {
>  #ifdef CONFIG_X86
> -                    put_gfn(d, gmfn + k);
> +                    put_gfn(d, _gfn(gmfn + k));
>  #endif
>                      rc = -EINVAL;
>                      goto fail;
> @@ -676,14 +676,14 @@ static long memory_exchange(XEN_GUEST_HANDLE_PARAM(xen_memory_exchange_t) arg)
>                  if ( unlikely(rc) )
>                  {
>  #ifdef CONFIG_X86
> -                    put_gfn(d, gmfn + k);
> +                    put_gfn(d, _gfn(gmfn + k));
>  #endif
>                      goto fail;
>                  }
>  
>                  page_list_add(page, &in_chunk_list);
>  #ifdef CONFIG_X86
> -                put_gfn(d, gmfn + k);
> +                put_gfn(d, _gfn(gmfn + k));
>  #endif
>              }
>          }
> diff --git a/xen/drivers/passthrough/amd/iommu_guest.c b/xen/drivers/passthrough/amd/iommu_guest.c
> index 03ca0cf..7ab3c77 100644
> --- a/xen/drivers/passthrough/amd/iommu_guest.c
> +++ b/xen/drivers/passthrough/amd/iommu_guest.c
> @@ -21,14 +21,6 @@
>  #include <asm/amd-iommu.h>
>  #include <asm/hvm/svm/amd-iommu-proto.h>
>  
> -/* Override {get,put}_gfn to work with gfn_t */
> -#undef get_gfn
> -#define get_gfn(d, g, t) get_gfn_type(d, gfn_x(g), t, P2M_ALLOC)
> -#undef get_gfn_query
> -#define get_gfn_query(d, g, t) get_gfn_type(d, gfn_x(g), t, 0)
> -#undef put_gfn
> -#define put_gfn(d, g) __put_gfn(p2m_get_hostp2m(d), gfn_x(g))
> -
>  #define IOMMU_MMIO_SIZE                         0x8000
>  #define IOMMU_MMIO_PAGE_NR                      0x8
>  #define RING_BF_LENGTH_MASK                     0x0F000000
> diff --git a/xen/include/asm-x86/guest_pt.h b/xen/include/asm-x86/guest_pt.h
> index 8684b83..87c6815 100644
> --- a/xen/include/asm-x86/guest_pt.h
> +++ b/xen/include/asm-x86/guest_pt.h
> @@ -38,10 +38,6 @@ gfn_to_paddr(gfn_t gfn)
>      return ((paddr_t)gfn_x(gfn)) << PAGE_SHIFT;
>  }
>  
> -/* Override get_gfn to work with gfn_t */
> -#undef get_gfn
> -#define get_gfn(d, g, t) get_gfn_type((d), gfn_x(g), (t), P2M_ALLOC)
> -
>  /* Mask covering the reserved bits from superpage alignment. */
>  #define SUPERPAGE_RSVD(bit)                                             \
>      (((1ul << (bit)) - 1) & ~(_PAGE_PSE_PAT | (_PAGE_PSE_PAT - 1ul)))
> diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h
> index 8bd6f64..e332f06 100644
> --- a/xen/include/asm-x86/p2m.h
> +++ b/xen/include/asm-x86/p2m.h
> @@ -431,7 +431,7 @@ void p2m_unlock_and_tlb_flush(struct p2m_domain *p2m);
>   * put_gfn. ****/
>  
>  mfn_t __nonnull(3, 4) __get_gfn_type_access(
> -    struct p2m_domain *p2m, unsigned long gfn, p2m_type_t *t,
> +    struct p2m_domain *p2m, gfn_t gfn, p2m_type_t *t,
>      p2m_access_t *a, p2m_query_t q, unsigned int *page_order, bool_t locked);
>  
>  /*
> @@ -444,7 +444,7 @@ mfn_t __nonnull(3, 4) __get_gfn_type_access(
>   * the entry was found in.
>   */
>  static inline mfn_t __nonnull(3, 4) get_gfn_type_access(
> -    struct p2m_domain *p2m, unsigned long gfn, p2m_type_t *t,
> +    struct p2m_domain *p2m, gfn_t gfn, p2m_type_t *t,
>      p2m_access_t *a, p2m_query_t q, unsigned int *page_order)
>  {
>      return __get_gfn_type_access(p2m, gfn, t, a, q, page_order, true);
> @@ -452,22 +452,21 @@ static inline mfn_t __nonnull(3, 4) get_gfn_type_access(
>  
>  /* General conversion function from gfn to mfn */
>  static inline mfn_t __nonnull(3) get_gfn_type(
> -    struct domain *d, unsigned long gfn, p2m_type_t *t, p2m_query_t q)
> +    struct domain *d, gfn_t gfn, p2m_type_t *t, p2m_query_t q)
>  {
>      p2m_access_t a;
>      return get_gfn_type_access(p2m_get_hostp2m(d), gfn, t, &a, q, NULL);
>  }
>  
>  /* Syntactic sugar: most callers will use one of these. */
> -#define get_gfn(d, g, t)         get_gfn_type((d), (g), (t), P2M_ALLOC)
> -#define get_gfn_query(d, g, t)   get_gfn_type((d), (g), (t), 0)
> -#define get_gfn_unshare(d, g, t) get_gfn_type((d), (g), (t), \
> -                                              P2M_ALLOC | P2M_UNSHARE)
> +#define get_gfn(d, g, t)         get_gfn_type(d, g, t, P2M_ALLOC)
> +#define get_gfn_query(d, g, t)   get_gfn_type(d, g, t, 0)
> +#define get_gfn_unshare(d, g, t) get_gfn_type(d, g, t, P2M_ALLOC | P2M_UNSHARE)
>  
>  /* Will release the p2m_lock for this gfn entry. */
> -void __put_gfn(struct p2m_domain *p2m, unsigned long gfn);
> +void __put_gfn(struct p2m_domain *p2m, gfn_t gfn);
>  
> -#define put_gfn(d, gfn) __put_gfn(p2m_get_hostp2m((d)), (gfn))
> +#define put_gfn(d, g) __put_gfn(p2m_get_hostp2m(d), g)
>  
>  /*
>   * The intent of the "unlocked" accessor is to have the caller not worry about
> @@ -484,9 +483,8 @@ void __put_gfn(struct p2m_domain *p2m, unsigned long gfn);
>   * Any other type of query can cause a change in the p2m and may need to
>   * perform locking.
>   */
> -static inline mfn_t get_gfn_query_unlocked(struct domain *d,
> -                                           unsigned long gfn,
> -                                           p2m_type_t *t)
> +static inline mfn_t get_gfn_query_unlocked(
> +    struct domain *d, gfn_t gfn, p2m_type_t *t)
>  {
>      p2m_access_t a;
>      return __get_gfn_type_access(p2m_get_hostp2m(d), gfn, t, &a, 0, NULL, 0);
> @@ -569,9 +567,9 @@ do {                                                    \
>  
>      /* Now do the gets */
>      *first_mfn  = get_gfn_type_access(p2m_get_hostp2m(rval->first_domain),
> -                                      gfn_x(rval->first_gfn), first_t, first_a, q, NULL);
> +                                      rval->first_gfn, first_t, first_a, q, NULL);
>      *second_mfn = get_gfn_type_access(p2m_get_hostp2m(rval->second_domain),
> -                                      gfn_x(rval->second_gfn), second_t, second_a, q, NULL);
> +                                      rval->second_gfn, second_t, second_a, q, NULL);
>  }
>  
>  static inline void put_two_gfns(struct two_gfns *arg)
> @@ -579,8 +577,8 @@ static inline void put_two_gfns(struct two_gfns *arg)
>      if ( !arg )
>          return;
>  
> -    put_gfn(arg->second_domain, gfn_x(arg->second_gfn));
> -    put_gfn(arg->first_domain,  gfn_x(arg->first_gfn));
> +    put_gfn(arg->second_domain, arg->second_gfn);
> +    put_gfn(arg->first_domain,  arg->first_gfn);
>  }
>  
>  /* Init the datastructures for later use by the p2m code */
> -- 
> 2.1.4
> 

-- 
Brian Woods

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 00/14] XSA-277 followup
  2018-11-22  0:08       ` Andrew Cooper
@ 2018-11-26 17:48         ` Tamas K Lengyel
  0 siblings, 0 replies; 59+ messages in thread
From: Tamas K Lengyel @ 2018-11-26 17:48 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: JGross, Kevin Tian, Stefano Stabellini, Wei Liu, Jun Nakajima,
	Razvan Cojocaru, George Dunlap, Tim Deegan, Xen-devel,
	Julien Grall, Paul Durrant, Jan Beulich, Boris Ostrovsky,
	Brian Woods, Suravee Suthikulpanit, Roger Pau Monné

On Wed, Nov 21, 2018 at 5:08 PM Andrew Cooper <andrew.cooper3@citrix.com> wrote:
>
> On 21/11/2018 22:42, Tamas K Lengyel wrote:
> > On Wed, Nov 21, 2018 at 2:22 PM Andrew Cooper <andrew.cooper3@citrix.com> wrote:
> >> On 21/11/2018 17:19, Tamas K Lengyel wrote:
> >>> On Wed, Nov 21, 2018 at 6:21 AM Andrew Cooper <andrew.cooper3@citrix.com> wrote:
> >>>> This covers various fixes related to XSA-277 which weren't in security
> >>>> supported areas, and associated cleanup.
> >>>>
> >>>> The biggest issue noticed here is that altp2m's use of hardware #VE support
> >>>> will cause general memory corruption if the guest ever balloons out the VEINFO
> >>>> page.  The only safe way I think of doing this is for Xen to alloc annonymous
> >>>> domheap pages for the VEINFO, and for the guest to map them in a similar way
> >>>> to the shared info and grant table frames.
> >>> Since ballooning presents all sorts of problems when used with altp2m
> >>> I would suggest just making the two explicitly incompatible during
> >>> domain creation. Beside the info page being possibly ballooned out the
> >>> other problem is when ballooning causes altp2m views to be reset
> >>> completely, removing mem_access permissions and remapped entries.
> >> If only it were that simple.
> >>
> >> For reasons of history and/or poor terminology, "ballooning" means two
> >> things.
> >>
> >> 1) The act of the Toolstack interacting with the balloon driver inside a
> >> VM, to change the current amount of RAM used by the guest.
> >>
> >> 2) XENMEM_{increase,decrease}_reservation which are the underlying
> >> hypercalls used by guest kernels.
> >>
> >> For the toolstack interaction side of things, this is a mess.  There is
> >> a single xenstore key, and a blind assumption that all guests know what
> >> changes to memory/target mean.  There is no negotiation of whether a
> >> balloon driver is running in the guest, and if one is running, there is
> >> no ability for the balloon driver to nack a request it can't fulfil.
> >> The sole feedback mechanism which exists is the toolstack looking to see
> >> whether the domain has changed the amount of RAM it is using.
> >>
> >> PV guests are fairly "special" by any reasonable judgement.  They are
> >> fully aware of their memory layout , an of changes to it across
> >> migrate.  "Ballooning" was implemented at a time when most computers had
> >> MB of RAM rather than GB, and the knowledge a PV guest had was "I've got
> >> a random set of MFNs which aren't currently used by anything important,
> >> and can be handed back to Xen on request.  Xen guests also have shared
> >> memory constructs such as the shared_info page, and grant tables.  A PV
> >> guest gets access to these by programming the frame straight into to the
> >> pagetables, and Xen's permission model DTRT.
> >>
> >> Then HVM guests came along.  For reasons of trying to get things
> >> working, they inherited a lot of same interfaces as PV guests, despite
> >> the fundamental differences in the way they work.  One of the biggest
> >> differences was the fact that HVM guests have their gfn=>mfn space
> >> managed by Xen rather than themselves, and in particular, you can no
> >> longer map shared memory structures in the PV way.
> >>
> >> For a shared memory structure to be usable, a mapping has to be put into
> >> the guests P2M, so the guest can create a regular pagetable entry
> >> pointing at it.  For reasons which are beyond me, Xen doesn't have any
> >> knowledge of the guests physical layout, and guests arbitrary mutative
> >> capabilities on their GFN space, but with a hypercall set that has
> >> properties such as a return value of "how many items of this batch
> >> succeeded", and replacement properties rather than error properties when
> >> trying to modify a GFN which already has something in it.
> >>
> >> Whatever the reasons, it is commonplace for guests to
> >> decrease_reservation out some RAM to create holes for the shared memory
> >> mappings, because it is the only safe way to avoid irreparably
> >> clobbering something else (especially if you're HVMLoader and in charge
> >> of trying to construct the E820/ACPI tables).
> >>
> >> tl;dr If you actually prohibit XENMEM_decrease_reservation, HVM guests
> >> don't boot, and that's long before a balloon driver gets up and running.
> > Thanks for the detailed write-up. This explains why I could never get
> > altp2m working from domain start, no matter where in the startup logic
> > of the toolstack I placed the altp2m activation (had to resort to
> > activating altp2m settings only after I detect the guest OS is fully
> > booted and things have settled down).
>
> So, in theory it should all work, even from the start.
>
> In practice, the implementation quality of altp2m leaves a lot to be
> desired, and it was designed to have the "all logic inside the guest"
> model, which in practice means that it only ever started once the guest
> had come up sufficiently.
>
> Do you recall more specifically where you tried inserting startup
> logic?  It sounds like something which wants fixing, irrespective of the
> other concerns here.

Right after the xl toolstack calls xc_dom_boot_mem_init I was trying
to do some funky stuff with gfn remapping in an altp2m view. I
couldn't pinpoint why but the guest wouldn't boot properly and it
would fail at different points shortly afterwards. The nature of the
crashes suggested that the remappings would disappear after some point
in the boot process. So what you say would explain why that would
happen.

Tamas

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 04/14] x86/p2m: Fix locking in p2m_altp2m_lazy_copy()
  2018-11-22 15:01   ` Jan Beulich
@ 2018-12-05 19:53     ` Andrew Cooper
  0 siblings, 0 replies; 59+ messages in thread
From: Andrew Cooper @ 2018-12-05 19:53 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Tamas K Lengyel, Wei Liu, Razvan Cojocaru, George Dunlap,
	Xen-devel, Roger Pau Monne

On 22/11/2018 15:01, Jan Beulich wrote:
>>>> On 21.11.18 at 14:21, <andrew.cooper3@citrix.com> wrote:
>> --- a/xen/arch/x86/mm/p2m.c
>> +++ b/xen/arch/x86/mm/p2m.c
>> @@ -2184,24 +2184,29 @@ bool_t p2m_altp2m_lazy_copy(struct vcpu *v, paddr_t gpa,
>>      unsigned long mask;
>>      mfn_t mfn;
>>      int rv;
>> +    bool ret;
>>  
>>      *ap2m = p2m_get_altp2m(v);
>>  
>>      mfn = get_gfn_type_access(*ap2m, gfn_x(gfn), &p2mt, &p2ma,
>>                                0, &page_order);
>> -    __put_gfn(*ap2m, gfn_x(gfn));
>>  
>> +    /* Entry already present in ap2m?  Caller should handle the fault. */
>>      if ( !mfn_eq(mfn, INVALID_MFN) )
>> -        return 0;
>> +    {
>> +        ret = false;
>> +        goto put_ap2m;
>> +    }
>>  
>>      mfn = get_gfn_type_access(hp2m, gfn_x(gfn), &p2mt, &p2ma,
>>                                P2M_ALLOC, &page_order);
>> -    __put_gfn(hp2m, gfn_x(gfn));
>>  
>> +    /* Entry not present in hp2m?  Caller should handle the fault. */
>>      if ( mfn_eq(mfn, INVALID_MFN) )
>> -        return 0;
>> -
>> -    p2m_lock(*ap2m);
>> +    {
>> +        ret = false;
>> +        goto put_hp2m;
> Wouldn't this better be named "put_gfn" (or "drop_gfn" to avoid the
> name collision with the function)?

No - I don't think so.  We have two separate refs to drop, one from the
hp2m and one from the ap2m.

This is why the labels are named symmetrically.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Pings for 4.12 [PATCH 00/14] XSA-277 followup
  2018-11-21 13:21 [PATCH 00/14] XSA-277 followup Andrew Cooper
                   ` (14 preceding siblings ...)
  2018-11-21 17:19 ` [PATCH 00/14] XSA-277 followup Tamas K Lengyel
@ 2019-01-30 18:36 ` Andrew Cooper
  15 siblings, 0 replies; 59+ messages in thread
From: Andrew Cooper @ 2019-01-30 18:36 UTC (permalink / raw)
  To: Xen-devel
  Cc: George Dunlap, Julien Grall, Stefano Stabellini, Brian Woods,
	Suravee Suthikulpanit

On 21/11/2018 13:21, Andrew Cooper wrote:
> This covers various fixes related to XSA-277 which weren't in security
> supported areas, and associated cleanup.
>
> The biggest issue noticed here is that altp2m's use of hardware #VE support
> will cause general memory corruption if the guest ever balloons out the VEINFO
> page.  The only safe way I think of doing this is for Xen to alloc annonymous
> domheap pages for the VEINFO, and for the guest to map them in a similar way
> to the shared info and grant table frames.
>
> Andrew Cooper (14):
>   x86/soft-reset: Drop gfn reference after calling get_gfn_query()
>   x86/mem-sharing: Don't leave the altp2m lock held when nominating a page
>   AMD/IOMMU: Fix multiple reference counting errors
>   x86/p2m: Fix locking in p2m_altp2m_lazy_copy()
>   x86/p2m: Don't overwrite p2m_altp2m_lazy_copy()'s callers p2m pointer
>   x86/hvm: Make the altp2m locking easier to follow
>   x86/p2m: Coding style cleanup
>   xen/memory: Drop ARM put_gfn() stub
>   x86/p2m: Switch the two_gfns infrastructure to using gfn_t
>   x86/mm: Switch {get,put}_gfn() infrastructure to using gfn_t
>   xen/mm: Switch mfn_to_virt()/virt_to_mfn() to using mfn_t
>   xen/gnttab: Drop gnttab_create_{shared,status}_page()
>   xen/gnttab: Simplify gnttab_map_frame()
>   xen/gnttab: Minor improvements to arch header files

A number of these patches are still pending maintainer review. 

The p2m patches all need George as the MM maintainer.  The AMD/IOMMU
patch is all unreachable code, but needs AMD input.  The final patch
needs ARM input.

Given that these are mostly reviewed and non-controversial, it would be
nice to get them into 4.12, so I guess at this point I could also do
with a release ack.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 14/14] xen/gnttab: Minor improvements to arch header files
  2018-11-22 17:56   ` Andrew Cooper
@ 2019-01-30 20:04     ` Julien Grall
  2019-01-30 20:05       ` Andrew Cooper
  0 siblings, 1 reply; 59+ messages in thread
From: Julien Grall @ 2019-01-30 20:04 UTC (permalink / raw)
  To: Andrew Cooper, Xen-devel
  Cc: Stefano Stabellini, Wei Liu, Jan Beulich, Roger Pau Monné

Hi Andrew,

On 11/22/18 5:56 PM, Andrew Cooper wrote:
> On 21/11/2018 13:21, Andrew Cooper wrote:
>>   * Use XFREE() when appropriate
>>   * Drop stale comments and unnecessary brackets
>>   * Fold asm constraints
>>
>> No functional change.
>>
>> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
>> ---
>> CC: Jan Beulich <JBeulich@suse.com>
>> CC: Wei Liu <wei.liu2@citrix.com>
>> CC: Roger Pau Monné <roger.pau@citrix.com>
>> ---
>>   xen/include/asm-arm/grant_table.h |  6 ++----
>>   xen/include/asm-x86/grant_table.h | 10 +++-------
> 
> CC'ing ARM maintainers.  I'm sorry for missing you out originally - I
> folded two separate patches and forgot to adjust the CC list.

Sorry it fell through the cracks.

Acked-by: Julien Grall <julien.grall@arm.com>

Cheers,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 14/14] xen/gnttab: Minor improvements to arch header files
  2019-01-30 20:04     ` Julien Grall
@ 2019-01-30 20:05       ` Andrew Cooper
  0 siblings, 0 replies; 59+ messages in thread
From: Andrew Cooper @ 2019-01-30 20:05 UTC (permalink / raw)
  To: Julien Grall, Xen-devel
  Cc: Stefano Stabellini, Wei Liu, Jan Beulich, Roger Pau Monné

On 30/01/2019 20:04, Julien Grall wrote:
> Hi Andrew,
>
> On 11/22/18 5:56 PM, Andrew Cooper wrote:
>> On 21/11/2018 13:21, Andrew Cooper wrote:
>>>   * Use XFREE() when appropriate
>>>   * Drop stale comments and unnecessary brackets
>>>   * Fold asm constraints
>>>
>>> No functional change.
>>>
>>> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
>>> ---
>>> CC: Jan Beulich <JBeulich@suse.com>
>>> CC: Wei Liu <wei.liu2@citrix.com>
>>> CC: Roger Pau Monné <roger.pau@citrix.com>
>>> ---
>>>   xen/include/asm-arm/grant_table.h |  6 ++----
>>>   xen/include/asm-x86/grant_table.h | 10 +++-------
>>
>> CC'ing ARM maintainers.  I'm sorry for missing you out originally - I
>> folded two separate patches and forgot to adjust the CC list.
>
> Sorry it fell through the cracks.
>
> Acked-by: Julien Grall <julien.grall@arm.com>

No problem.  Thanks.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 03/14] AMD/IOMMU: Fix multiple reference counting errors
  2018-11-21 13:21 ` [PATCH 03/14] AMD/IOMMU: Fix multiple reference counting errors Andrew Cooper
  2018-11-22 14:51   ` Jan Beulich
@ 2019-01-31 15:59   ` Woods, Brian
  1 sibling, 0 replies; 59+ messages in thread
From: Woods, Brian @ 2019-01-31 15:59 UTC (permalink / raw)
  To: Andrew Cooper, Xen-devel
  Cc: Wei Liu, Suthikulpanit, Suravee, Jan Beulich, Roger Pau Monné

On 11/21/18 7:21 AM, Andrew Cooper wrote:
> Most of these issues would be XSAs if these paths were accessible to guests.
> 
> First, override the {get,put}_gfn() helpers to use gfn_t, which was the
> original purpose of this patch.
> 
> guest_iommu_get_table_mfn() has two bugs.  First, it gets a ref on one gfn,
> and puts a ref for a different gfn.  This is only a latent bug for now, as we
> don't do per-gfn locking yet.  Next, the mfn return value is unsafe to use
> after put_gfn() is called, as the guest could have freed the page in the
> meantime.
> 
> In addition, get_gfn_from_base_reg() erroneously asserts that base_raw can't
> be 0, but it may legitimately be.  On top of that, the return value from
> guest_iommu_get_table_mfn() is passed into map_domain_page() before checking
> that it is a real mfn.
> 
> Most of the complexity here is inlining guest_iommu_get_table_mfn() and
> holding the gfn reference until the operation is complete.
> 
> Furthermore, guest_iommu_process_command() is altered to take a local copy of
> cmd_entry_t, rather than passing a pointer to guest controlled memory into
> each of the handling functions.  It is also modified to break on error rather
> than continue.  These changes are in line with the spec which states that the
> IOMMU will strictly read a command entry once, and will cease processing if an
> error is encountered.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Acked-by: Brian Woods <brian.woods@amd.com>

> ---
> CC: Jan Beulich <JBeulich@suse.com>
> CC: Wei Liu <wei.liu2@citrix.com>
> CC: Roger Pau Monné <roger.pau@citrix.com>
> CC: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
> CC: Brian Woods <brian.woods@amd.com>
> 
> This patch my no means indicates that the code is ready for production use.
> ---
>   xen/drivers/passthrough/amd/iommu_guest.c | 224 +++++++++++++++++++-----------
>   1 file changed, 146 insertions(+), 78 deletions(-)
> 
> diff --git a/xen/drivers/passthrough/amd/iommu_guest.c b/xen/drivers/passthrough/amd/iommu_guest.c
> index 96175bb..03ca0cf 100644
> --- a/xen/drivers/passthrough/amd/iommu_guest.c
> +++ b/xen/drivers/passthrough/amd/iommu_guest.c
> @@ -21,6 +21,13 @@
>   #include <asm/amd-iommu.h>
>   #include <asm/hvm/svm/amd-iommu-proto.h>
>   
> +/* Override {get,put}_gfn to work with gfn_t */
> +#undef get_gfn
> +#define get_gfn(d, g, t) get_gfn_type(d, gfn_x(g), t, P2M_ALLOC)
> +#undef get_gfn_query
> +#define get_gfn_query(d, g, t) get_gfn_type(d, gfn_x(g), t, 0)
> +#undef put_gfn
> +#define put_gfn(d, g) __put_gfn(p2m_get_hostp2m(d), gfn_x(g))
>   
>   #define IOMMU_MMIO_SIZE                         0x8000
>   #define IOMMU_MMIO_PAGE_NR                      0x8
> @@ -117,13 +124,6 @@ static unsigned int host_domid(struct domain *d, uint64_t g_domid)
>       return d->domain_id;
>   }
>   
> -static unsigned long get_gfn_from_base_reg(uint64_t base_raw)
> -{
> -    base_raw &= PADDR_MASK;
> -    ASSERT ( base_raw != 0 );
> -    return base_raw >> PAGE_SHIFT;
> -}
> -
>   static void guest_iommu_deliver_msi(struct domain *d)
>   {
>       uint8_t vector, dest, dest_mode, delivery_mode, trig_mode;
> @@ -138,23 +138,6 @@ static void guest_iommu_deliver_msi(struct domain *d)
>       vmsi_deliver(d, vector, dest, dest_mode, delivery_mode, trig_mode);
>   }
>   
> -static unsigned long guest_iommu_get_table_mfn(struct domain *d,
> -                                               uint64_t base_raw,
> -                                               unsigned int entry_size,
> -                                               unsigned int pos)
> -{
> -    unsigned long idx, gfn, mfn;
> -    p2m_type_t p2mt;
> -
> -    gfn = get_gfn_from_base_reg(base_raw);
> -    idx = (pos * entry_size) >> PAGE_SHIFT;
> -
> -    mfn = mfn_x(get_gfn(d, gfn + idx, &p2mt));
> -    put_gfn(d, gfn);
> -
> -    return mfn;
> -}
> -
>   static void guest_iommu_enable_dev_table(struct guest_iommu *iommu)
>   {
>       uint32_t length_raw = get_field_from_reg_u32(iommu->dev_table.reg_base.lo,
> @@ -176,7 +159,10 @@ static void guest_iommu_enable_ring_buffer(struct guest_iommu *iommu,
>   void guest_iommu_add_ppr_log(struct domain *d, u32 entry[])
>   {
>       uint16_t gdev_id;
> -    unsigned long mfn, tail, head;
> +    unsigned long tail, head;
> +    mfn_t mfn;
> +    gfn_t gfn;
> +    p2m_type_t p2mt;
>       ppr_entry_t *log, *log_base;
>       struct guest_iommu *iommu;
>   
> @@ -197,11 +183,24 @@ void guest_iommu_add_ppr_log(struct domain *d, u32 entry[])
>           return;
>       }
>   
> -    mfn = guest_iommu_get_table_mfn(d, reg_to_u64(iommu->ppr_log.reg_base),
> -                                    sizeof(ppr_entry_t), tail);
> -    ASSERT(mfn_valid(_mfn(mfn)));
> +    gfn = _gfn(PFN_DOWN(reg_to_u64(iommu->ppr_log.reg_base)) +
> +               PFN_DOWN(tail * sizeof(*log)));
>   
> -    log_base = map_domain_page(_mfn(mfn));
> +    mfn = get_gfn(d, gfn, &p2mt);
> +    if ( mfn_eq(mfn, INVALID_MFN) || !p2m_is_ram(p2mt) )
> +    {
> +        AMD_IOMMU_DEBUG(
> +            "Error: guest iommu ppr log bad gfn %"PRI_gfn", type %u, mfn %"
> +            PRI_mfn", reg_base %#"PRIx64", tail %#lx\n",
> +            gfn_x(gfn), p2mt, mfn_x(mfn),
> +            reg_to_u64(iommu->ppr_log.reg_base), tail);
> +        guest_iommu_disable(iommu);
> +        goto out;
> +    }
> +
> +    ASSERT(mfn_valid(mfn));
> +
> +    log_base = map_domain_page(mfn);
>       log = log_base + tail % (PAGE_SIZE / sizeof(ppr_entry_t));
>   
>       /* Convert physical device id back into virtual device id */
> @@ -220,12 +219,18 @@ void guest_iommu_add_ppr_log(struct domain *d, u32 entry[])
>       unmap_domain_page(log_base);
>   
>       guest_iommu_deliver_msi(d);
> +
> +out:
> +    put_gfn(d, gfn);
>   }
>   
>   void guest_iommu_add_event_log(struct domain *d, u32 entry[])
>   {
>       uint16_t dev_id;
> -    unsigned long mfn, tail, head;
> +    unsigned long tail, head;
> +    mfn_t mfn;
> +    gfn_t gfn;
> +    p2m_type_t p2mt;
>       event_entry_t *log, *log_base;
>       struct guest_iommu *iommu;
>   
> @@ -246,11 +251,24 @@ void guest_iommu_add_event_log(struct domain *d, u32 entry[])
>           return;
>       }
>   
> -    mfn = guest_iommu_get_table_mfn(d, reg_to_u64(iommu->event_log.reg_base),
> -                                    sizeof(event_entry_t), tail);
> -    ASSERT(mfn_valid(_mfn(mfn)));
> +    gfn = _gfn(PFN_DOWN(reg_to_u64(iommu->event_log.reg_base)) +
> +               PFN_DOWN(tail * sizeof(*log)));
> +
> +    mfn = get_gfn(d, gfn, &p2mt);
> +    if ( mfn_eq(mfn, INVALID_MFN) || !p2m_is_ram(p2mt) )
> +    {
> +        AMD_IOMMU_DEBUG(
> +            "Error: guest iommu event log bad gfn %"PRI_gfn", type %u, mfn %"
> +            PRI_mfn", reg_base %#"PRIx64", tail %#lx\n",
> +            gfn_x(gfn), p2mt, mfn_x(mfn),
> +            reg_to_u64(iommu->ppr_log.reg_base), tail);
> +        guest_iommu_disable(iommu);
> +        goto out;
> +    }
> +
> +    ASSERT(mfn_valid(mfn));
>   
> -    log_base = map_domain_page(_mfn(mfn));
> +    log_base = map_domain_page(mfn);
>       log = log_base + tail % (PAGE_SIZE / sizeof(event_entry_t));
>   
>       /* re-write physical device id into virtual device id */
> @@ -269,6 +287,9 @@ void guest_iommu_add_event_log(struct domain *d, u32 entry[])
>       unmap_domain_page(log_base);
>   
>       guest_iommu_deliver_msi(d);
> +
> +out:
> +    put_gfn(d, gfn);
>   }
>   
>   static int do_complete_ppr_request(struct domain *d, cmd_entry_t *cmd)
> @@ -346,10 +367,8 @@ static int do_invalidate_iotlb_pages(struct domain *d, cmd_entry_t *cmd)
>   
>   static int do_completion_wait(struct domain *d, cmd_entry_t *cmd)
>   {
> -    bool_t com_wait_int_en, com_wait_int, i, s;
> +    bool com_wait_int_en, com_wait_int, i, s;
>       struct guest_iommu *iommu;
> -    unsigned long gfn;
> -    p2m_type_t p2mt;
>   
>       iommu = domain_iommu(d);
>   
> @@ -362,7 +381,10 @@ static int do_completion_wait(struct domain *d, cmd_entry_t *cmd)
>       if ( s )
>       {
>           uint64_t gaddr_lo, gaddr_hi, gaddr_64, data;
> -        void *vaddr;
> +        mfn_t mfn;
> +        gfn_t gfn;
> +        p2m_type_t p2mt;
> +        uint64_t *ptr;
>   
>           data = (uint64_t)cmd->data[3] << 32 | cmd->data[2];
>           gaddr_lo = get_field_from_reg_u32(cmd->data[0],
> @@ -374,13 +396,24 @@ static int do_completion_wait(struct domain *d, cmd_entry_t *cmd)
>   
>           gaddr_64 = (gaddr_hi << 32) | (gaddr_lo << 3);
>   
> -        gfn = gaddr_64 >> PAGE_SHIFT;
> -        vaddr = map_domain_page(get_gfn(d, gfn ,&p2mt));
> -        put_gfn(d, gfn);
> +        gfn = _gfn(gaddr_64 >> PAGE_SHIFT);
> +        mfn = get_gfn(d, gfn, &p2mt);
>   
> -        write_u64_atomic((uint64_t *)(vaddr + (gaddr_64 & (PAGE_SIZE-1))),
> -                         data);
> -        unmap_domain_page(vaddr);
> +        if ( mfn_eq(mfn, INVALID_MFN) || !p2m_is_ram(p2mt) )
> +        {
> +            /* XXX - What to do here, error wise? */
> +            guest_iommu_disable(iommu);
> +            put_gfn(d, gfn);
> +
> +            return 0;
> +        }
> +
> +        ptr = map_domain_page(mfn) + (gaddr_64 & ~PAGE_MASK);
> +
> +        write_u64_atomic(ptr, data);
> +        unmap_domain_page(ptr);
> +
> +        put_gfn(d, gfn);
>       }
>   
>       com_wait_int_en = iommu_get_bit(iommu->reg_ctrl.lo,
> @@ -400,9 +433,10 @@ static int do_invalidate_dte(struct domain *d, cmd_entry_t *cmd)
>       dev_entry_t *gdte, *mdte, *dte_base;
>       struct amd_iommu *iommu = NULL;
>       struct guest_iommu *g_iommu;
> -    uint64_t gcr3_gfn, gcr3_mfn;
> +    mfn_t dte_mfn, gcr3_mfn;
> +    gfn_t dte_gfn, gcr3_gfn;
>       uint8_t glx, gv;
> -    unsigned long dte_mfn, flags;
> +    unsigned long flags;
>       p2m_type_t p2mt;
>   
>       g_iommu = domain_iommu(d);
> @@ -417,35 +451,49 @@ static int do_invalidate_dte(struct domain *d, cmd_entry_t *cmd)
>       if ( (gbdf * sizeof(dev_entry_t)) > g_iommu->dev_table.size )
>           return 0;
>   
> -    dte_mfn = guest_iommu_get_table_mfn(d,
> -                                        reg_to_u64(g_iommu->dev_table.reg_base),
> -                                        sizeof(dev_entry_t), gbdf);
> -    ASSERT(mfn_valid(_mfn(dte_mfn)));
> +    dte_gfn = _gfn(PFN_DOWN(reg_to_u64(g_iommu->dev_table.reg_base)) +
> +                   PFN_DOWN(gbdf * sizeof(*gdte)));
> +    dte_mfn = get_gfn(d, dte_gfn, &p2mt);
> +
> +    if ( mfn_eq(dte_mfn, INVALID_MFN) || !p2m_is_ram(p2mt) )
> +    {
> +        put_gfn(d, dte_gfn);
> +        return 0;
> +    }
> +
> +    ASSERT(mfn_valid(dte_mfn));
>   
>       /* Read guest dte information */
> -    dte_base = map_domain_page(_mfn(dte_mfn));
> +    dte_base = map_domain_page(dte_mfn);
>   
>       gdte = dte_base + gbdf % (PAGE_SIZE / sizeof(dev_entry_t));
>   
>       gdom_id  = get_domid_from_dte(gdte);
> -    gcr3_gfn = get_guest_cr3_from_dte(gdte);
> +    gcr3_gfn = _gfn(get_guest_cr3_from_dte(gdte));
>       glx      = get_glx_from_dte(gdte);
>       gv       = get_gv_from_dte(gdte);
>   
>       unmap_domain_page(dte_base);
> +    put_gfn(d, dte_gfn);
>   
>       /* Do not update host dte before gcr3 has been set */
> -    if ( gcr3_gfn == 0 )
> +    if ( gfn_x(gcr3_gfn) == 0 )
>           return 0;
>   
> -    gcr3_mfn = mfn_x(get_gfn(d, gcr3_gfn, &p2mt));
> -    put_gfn(d, gcr3_gfn);
> +    gcr3_mfn = get_gfn(d, gcr3_gfn, &p2mt);
>   
> -    ASSERT(mfn_valid(_mfn(gcr3_mfn)));
> +    if ( mfn_eq(gcr3_mfn, INVALID_MFN) || !p2m_is_ram(p2mt) )
> +    {
> +        put_gfn(d, gcr3_gfn);
> +        return 0;
> +    }
> +
> +    ASSERT(mfn_valid(gcr3_mfn));
>   
>       iommu = find_iommu_for_device(0, mbdf);
>       if ( !iommu )
>       {
> +        put_gfn(d, gcr3_gfn);
>           AMD_IOMMU_DEBUG("%s: Fail to find iommu for bdf %x!\n",
>                           __func__, mbdf);
>           return -ENODEV;
> @@ -458,18 +506,19 @@ static int do_invalidate_dte(struct domain *d, cmd_entry_t *cmd)
>   
>       spin_lock_irqsave(&iommu->lock, flags);
>       iommu_dte_set_guest_cr3((u32 *)mdte, hdom_id,
> -                            gcr3_mfn << PAGE_SHIFT, gv, glx);
> +                            mfn_to_maddr(gcr3_mfn), gv, glx);
>   
>       amd_iommu_flush_device(iommu, req_id);
>       spin_unlock_irqrestore(&iommu->lock, flags);
>   
> +    put_gfn(d, gcr3_gfn);
> +
>       return 0;
>   }
>   
>   static void guest_iommu_process_command(unsigned long _d)
>   {
> -    unsigned long opcode, tail, head, entries_per_page, cmd_mfn;
> -    cmd_entry_t *cmd, *cmd_base;
> +    unsigned long tail, head;
>       struct domain *d = (struct domain *)_d;
>       struct guest_iommu *iommu;
>   
> @@ -493,56 +542,75 @@ static void guest_iommu_process_command(unsigned long _d)
>           return;
>       }
>   
> -    entries_per_page = PAGE_SIZE / sizeof(cmd_entry_t);
> -
>       while ( head != tail )
>       {
> +        mfn_t mfn;
> +        gfn_t gfn;
> +        p2m_type_t p2mt;
> +        cmd_entry_t cmd, *ptr;
>           int ret = 0;
> +        unsigned int opcode;
> +
> +        gfn = _gfn(PFN_DOWN(reg_to_u64(iommu->cmd_buffer.reg_base)) +
> +                   PFN_DOWN(head * sizeof(cmd)));
>   
> -        cmd_mfn = guest_iommu_get_table_mfn(d,
> -                                            reg_to_u64(iommu->cmd_buffer.reg_base),
> -                                            sizeof(cmd_entry_t), head);
> -        ASSERT(mfn_valid(_mfn(cmd_mfn)));
> +        mfn = get_gfn(d, gfn, &p2mt);
> +        if ( mfn_eq(mfn, INVALID_MFN) || !p2m_is_ram(p2mt) )
> +        {
> +            AMD_IOMMU_DEBUG(
> +                "Error: guest iommu cmd buffer bad gfn %"PRI_gfn", type %u, mfn %"
> +                PRI_mfn", reg_base %#"PRIx64", head %#lx\n",
> +                gfn_x(gfn), p2mt, mfn_x(mfn),
> +                reg_to_u64(iommu->cmd_buffer.reg_base), head);
> +            put_gfn(d, gfn);
> +            guest_iommu_disable(iommu);
> +            return;
> +        }
>   
> -        cmd_base = map_domain_page(_mfn(cmd_mfn));
> -        cmd = cmd_base + head % entries_per_page;
> +        ptr = map_domain_page(mfn) + head % (PAGE_SIZE / sizeof(cmd_entry_t));
> +        memcpy(&cmd, ptr, sizeof(cmd));
> +        unmap_domain_page(ptr);
> +        put_gfn(d, gfn);
>   
> -        opcode = get_field_from_reg_u32(cmd->data[1],
> +        opcode = get_field_from_reg_u32(cmd.data[1],
>                                           IOMMU_CMD_OPCODE_MASK,
>                                           IOMMU_CMD_OPCODE_SHIFT);
>           switch ( opcode )
>           {
>           case IOMMU_CMD_COMPLETION_WAIT:
> -            ret = do_completion_wait(d, cmd);
> +            ret = do_completion_wait(d, &cmd);
>               break;
>           case IOMMU_CMD_INVALIDATE_DEVTAB_ENTRY:
> -            ret = do_invalidate_dte(d, cmd);
> +            ret = do_invalidate_dte(d, &cmd);
>               break;
>           case IOMMU_CMD_INVALIDATE_IOMMU_PAGES:
> -            ret = do_invalidate_pages(d, cmd);
> +            ret = do_invalidate_pages(d, &cmd);
>               break;
>           case IOMMU_CMD_INVALIDATE_IOTLB_PAGES:
> -            ret = do_invalidate_iotlb_pages(d, cmd);
> +            ret = do_invalidate_iotlb_pages(d, &cmd);
>               break;
>           case IOMMU_CMD_INVALIDATE_INT_TABLE:
>               break;
>           case IOMMU_CMD_COMPLETE_PPR_REQUEST:
> -            ret = do_complete_ppr_request(d, cmd);
> +            ret = do_complete_ppr_request(d, &cmd);
>               break;
>           case IOMMU_CMD_INVALIDATE_IOMMU_ALL:
> -            ret = do_invalidate_all(d, cmd);
> +            ret = do_invalidate_all(d, &cmd);
>               break;
>           default:
> -            AMD_IOMMU_DEBUG("CMD: Unknown command cmd_type = %lx "
> +            AMD_IOMMU_DEBUG("CMD: Unknown command cmd_type = %#x "
>                               "head = %ld\n", opcode, head);
> +            ret = -EINVAL;
>               break;
>           }
>   
> -        unmap_domain_page(cmd_base);
>           if ( ++head >= iommu->cmd_buffer.entries )
>               head = 0;
>           if ( ret )
> +        {
>               guest_iommu_disable(iommu);
> +            break;
> +        }
>       }
>   
>       /* Now shift cmd buffer head pointer */
> @@ -818,10 +886,10 @@ int guest_iommu_set_base(struct domain *d, uint64_t base)
>   
>       for ( int i = 0; i < IOMMU_MMIO_PAGE_NR; i++ )
>       {
> -        unsigned long gfn = base + i;
> +        gfn_t gfn = _gfn(base + i);
>   
>           get_gfn_query(d, gfn, &t);
> -        p2m_change_type_one(d, gfn, t, p2m_mmio_dm);
> +        p2m_change_type_one(d, gfn_x(gfn), t, p2m_mmio_dm);
>           put_gfn(d, gfn);
>       }
>   
> 

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 59+ messages in thread

end of thread, other threads:[~2019-01-31 15:59 UTC | newest]

Thread overview: 59+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-21 13:21 [PATCH 00/14] XSA-277 followup Andrew Cooper
2018-11-21 13:21 ` [PATCH 01/14] x86/soft-reset: Drop gfn reference after calling get_gfn_query() Andrew Cooper
2018-11-22 14:45   ` Jan Beulich
2018-11-21 13:21 ` [PATCH 02/14] x86/mem-sharing: Don't leave the altp2m lock held when nominating a page Andrew Cooper
2018-11-21 16:56   ` Tamas K Lengyel
2018-11-22 14:46   ` Jan Beulich
2018-11-21 13:21 ` [PATCH 03/14] AMD/IOMMU: Fix multiple reference counting errors Andrew Cooper
2018-11-22 14:51   ` Jan Beulich
2018-11-22 17:46     ` Andrew Cooper
2018-11-23  8:23       ` Jan Beulich
2018-11-23 16:03         ` Andrew Cooper
2018-11-26  9:05           ` Jan Beulich
2019-01-31 15:59   ` Woods, Brian
2018-11-21 13:21 ` [PATCH 04/14] x86/p2m: Fix locking in p2m_altp2m_lazy_copy() Andrew Cooper
2018-11-21 13:59   ` Razvan Cojocaru
2018-11-22 15:01   ` Jan Beulich
2018-12-05 19:53     ` Andrew Cooper
2018-11-21 13:21 ` [PATCH 05/14] x86/p2m: Don't overwrite p2m_altp2m_lazy_copy()'s callers p2m pointer Andrew Cooper
2018-11-21 14:07   ` Razvan Cojocaru
2018-11-22 15:03   ` Jan Beulich
2018-11-21 13:21 ` [PATCH 06/14] x86/hvm: Make the altp2m locking easier to follow Andrew Cooper
2018-11-21 14:43   ` Razvan Cojocaru
2018-11-22 15:08   ` Jan Beulich
2018-11-21 13:21 ` [PATCH 07/14] x86/p2m: Coding style cleanup Andrew Cooper
2018-11-22 15:12   ` Jan Beulich
2018-11-21 13:21 ` [PATCH 08/14] xen/memory: Drop ARM put_gfn() stub Andrew Cooper
2018-11-22 14:07   ` Julien Grall
2018-11-22 15:15   ` Jan Beulich
2018-11-21 13:21 ` [PATCH 09/14] x86/p2m: Switch the two_gfns infrastructure to using gfn_t Andrew Cooper
2018-11-21 17:06   ` Tamas K Lengyel
2018-11-22 15:17   ` Jan Beulich
2018-11-21 13:21 ` [PATCH 10/14] x86/mm: Switch {get, put}_gfn() " Andrew Cooper
2018-11-21 14:48   ` Razvan Cojocaru
2018-11-21 16:12   ` Paul Durrant
2018-11-22 15:34   ` Jan Beulich
2018-11-23  2:58   ` Tian, Kevin
2018-11-26 15:51   ` Woods, Brian
2018-11-21 13:21 ` [PATCH 11/14] xen/mm: Switch mfn_to_virt()/virt_to_mfn() to using mfn_t Andrew Cooper
2018-11-22 14:32   ` Julien Grall
2018-11-22 15:44   ` Jan Beulich
2018-11-22 15:49     ` Andrew Cooper
2018-11-21 13:21 ` [PATCH 12/14] xen/gnttab: Drop gnttab_create_{shared, status}_page() Andrew Cooper
2018-11-22 14:35   ` Julien Grall
2018-11-22 15:47   ` Jan Beulich
2018-11-21 13:21 ` [PATCH 13/14] xen/gnttab: Simplify gnttab_map_frame() Andrew Cooper
2018-11-22 14:36   ` Julien Grall
2018-11-22 15:48   ` Jan Beulich
2018-11-21 13:21 ` [PATCH 14/14] xen/gnttab: Minor improvements to arch header files Andrew Cooper
2018-11-22 15:51   ` Jan Beulich
2018-11-22 17:56   ` Andrew Cooper
2019-01-30 20:04     ` Julien Grall
2019-01-30 20:05       ` Andrew Cooper
2018-11-21 17:19 ` [PATCH 00/14] XSA-277 followup Tamas K Lengyel
2018-11-21 21:22   ` Andrew Cooper
2018-11-21 22:42     ` Tamas K Lengyel
2018-11-22  0:08       ` Andrew Cooper
2018-11-26 17:48         ` Tamas K Lengyel
2018-11-23 15:46     ` Roger Pau Monné
2019-01-30 18:36 ` Pings for 4.12 " Andrew Cooper

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.