const char *version = NULL;
        const char *xen_prefix = "xen,xen-";
        struct resource res;
+       unsigned long grant_frames;
 
        node = of_find_compatible_node(NULL, NULL, "xen,xen");
        if (!node) {
        }
        if (of_address_to_resource(node, GRANT_TABLE_PHYSADDR, &res))
                return 0;
-       xen_hvm_resume_frames = res.start;
+       grant_frames = res.start;
        xen_events_irq = irq_of_parse_and_map(node, 0);
        pr_info("Xen %s support found, events_irq=%d gnttab_frame_pfn=%lx\n",
-                       version, xen_events_irq, (xen_hvm_resume_frames >> PAGE_SHIFT));
+                       version, xen_events_irq, (grant_frames >> PAGE_SHIFT));
        xen_domain_type = XEN_HVM_DOMAIN;
 
        xen_setup_features();
        if (xen_vcpu_info == NULL)
                return -ENOMEM;
 
+       if (gnttab_setup_auto_xlat_frames(grant_frames)) {
+               free_percpu(xen_vcpu_info);
+               return -ENOMEM;
+       }
        gnttab_init();
        if (!xen_initial_domain())
                xenbus_probe(NULL);
 
 static int gnttab_free_count;
 static grant_ref_t gnttab_free_head;
 static DEFINE_SPINLOCK(gnttab_list_lock);
-unsigned long xen_hvm_resume_frames;
-EXPORT_SYMBOL_GPL(xen_hvm_resume_frames);
+struct grant_frames xen_auto_xlat_grant_frames;
 
 static union {
        struct grant_entry_v1 *v1;
 }
 EXPORT_SYMBOL_GPL(gnttab_max_grant_frames);
 
+int gnttab_setup_auto_xlat_frames(unsigned long addr)
+{
+       xen_pfn_t *pfn;
+       unsigned int max_nr_gframes = __max_nr_grant_frames();
+       unsigned int i;
+       void *vaddr;
+
+       if (xen_auto_xlat_grant_frames.count)
+               return -EINVAL;
+
+       vaddr = xen_remap(addr, PAGE_SIZE * max_nr_gframes);
+       if (vaddr == NULL) {
+               pr_warn("Failed to ioremap gnttab share frames (addr=0x%08lx)!\n",
+                       addr);
+               return -ENOMEM;
+       }
+       pfn = kcalloc(max_nr_gframes, sizeof(pfn[0]), GFP_KERNEL);
+       if (!pfn) {
+               xen_unmap(vaddr);
+               return -ENOMEM;
+       }
+       for (i = 0; i < max_nr_gframes; i++)
+               pfn[i] = PFN_DOWN(addr) + i;
+
+       xen_auto_xlat_grant_frames.vaddr = vaddr;
+       xen_auto_xlat_grant_frames.pfn = pfn;
+       xen_auto_xlat_grant_frames.count = max_nr_gframes;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(gnttab_setup_auto_xlat_frames);
+
+void gnttab_free_auto_xlat_frames(void)
+{
+       if (!xen_auto_xlat_grant_frames.count)
+               return;
+       kfree(xen_auto_xlat_grant_frames.pfn);
+       xen_unmap(xen_auto_xlat_grant_frames.vaddr);
+
+       xen_auto_xlat_grant_frames.pfn = NULL;
+       xen_auto_xlat_grant_frames.count = 0;
+       xen_auto_xlat_grant_frames.vaddr = NULL;
+}
+EXPORT_SYMBOL_GPL(gnttab_free_auto_xlat_frames);
+
 /* Handling of paged out grant targets (GNTST_eagain) */
 #define MAX_DELAY 256
 static inline void
                struct xen_add_to_physmap xatp;
                unsigned int i = end_idx;
                rc = 0;
+               BUG_ON(xen_auto_xlat_grant_frames.count < nr_gframes);
                /*
                 * Loop backwards, so that the first hypercall has the largest
                 * index, ensuring that the table will grow only once.
                        xatp.domid = DOMID_SELF;
                        xatp.idx = i;
                        xatp.space = XENMAPSPACE_grant_table;
-                       xatp.gpfn = (xen_hvm_resume_frames >> PAGE_SHIFT) + i;
+                       xatp.gpfn = xen_auto_xlat_grant_frames.pfn[i];
                        rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp);
                        if (rc != 0) {
                                pr_warn("grant table add_to_physmap failed, err=%d\n",
                return -ENOSYS;
 
        if (xen_feature(XENFEAT_auto_translated_physmap) && gnttab_shared.addr == NULL) {
-               gnttab_shared.addr = xen_remap(xen_hvm_resume_frames,
-                                               PAGE_SIZE * max_nr_gframes);
+               gnttab_shared.addr = xen_auto_xlat_grant_frames.vaddr;
                if (gnttab_shared.addr == NULL) {
-                       pr_warn("Failed to ioremap gnttab share frames (addr=0x%08lx)!\n",
-                                       xen_hvm_resume_frames);
+                       pr_warn("gnttab share frames (addr=0x%08lx) is not mapped!\n",
+                               (unsigned long)xen_auto_xlat_grant_frames.vaddr);
                        return -ENOMEM;
                }
        }