goto error_out;
}
- if ( (page_array = malloc((nr_pages + 1 + NR_GRANT_FRAMES) * sizeof(unsigned long))) == NULL )
+ if ( (page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL )
{
PERROR("Could not allocate memory");
goto error_out;
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
page_array[physmap_pfn++]);
- page_array[nr_pages] = shared_info_frame;
-
- if ( xc_get_gnttab_frames(xc_handle,
- dom,
- page_array + 1 + nr_pages,
- NR_GRANT_FRAMES) <= 0) {
- fprintf(stderr, "cannot get grant table frames\n");
- goto error_out;
- }
-
- for ( count = 0; count < nr_pages + 1 + NR_GRANT_FRAMES; count++ )
+ for ( count = 0; count < nr_pages; count++ )
{
if ( xc_add_mmu_update(
xc_handle, mmu,
PERROR("Could not enable translation mode");
goto error_out;
}
+
+ /* Find the shared info frame. It's guaranteed to be at the
+ start of the PFN hole. */
+ guest_shared_info_mfn = xc_get_pfn_hole_start(xc_handle, dom);
+ if (guest_shared_info_mfn <= 0) {
+ PERROR("Cannot find shared info pfn");
+ goto error_out;
+ }
+ } else {
+ guest_shared_info_mfn = shared_info_frame;
}
/* setup page tables */
if (shadow_mode_enabled) {
guest_store_mfn = (vstoreinfo_start-dsi.v_start) >> PAGE_SHIFT;
guest_console_mfn = (vconsole_start-dsi.v_start) >> PAGE_SHIFT;
- guest_shared_info_mfn = nr_pages;
} else {
guest_store_mfn = *store_mfn;
guest_console_mfn = *console_mfn;
- guest_shared_info_mfn = shared_info_frame;
}
start_info = xc_map_foreign_range(
return rc;
}
+int xc_get_pfn_hole_start(int xc_handle, domid_t dom)
+{
+ struct mmuext_op op = {0};
+ op.cmd = MMUEXT_PFN_HOLE_BASE;
+ return xc_mmuext_op(xc_handle, &op, 1, dom);
+}
+
+
/*
* Local variables:
* mode: C
return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
}
-int xc_get_gnttab_frames(int xc_handle,
- uint32_t domid,
- unsigned long *pfn_buf,
- unsigned long max_pfns)
-{
- DECLARE_DOM0_OP;
- int ret;
- op.cmd = DOM0_GETGNTTABLIST;
- op.u.getgnttablist.domain = (domid_t)domid;
- op.u.getgnttablist.max_pfns = max_pfns;
- op.u.getgnttablist.buffer = pfn_buf;
-
-#ifdef VALGRIND
- memset(pfn_buf, 0, max_pfns * sizeof(unsigned long));
-#endif
-
- if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
- {
- PERROR("xc_get_pfn_list: pfn_buf mlock failed");
- return -1;
- }
-
- ret = do_dom0_op(xc_handle, &op);
-
- safe_munlock(pfn_buf, max_pfns * sizeof(unsigned long));
-
- return (ret < 0) ? -1 : op.u.getgnttablist.num_pfns;
-}
-
long xc_get_tot_pages(int xc_handle, uint32_t domid)
{
DECLARE_DOM0_OP;
return ret;
}
-int xc_get_gnttab_frames(int xc_handle, uint32_t domid, unsigned long *pfn_buf,
- unsigned long max_pfns);
-
/*
* ioctl-based mfn mapping interface
unsigned long long ptr, unsigned long long val);
int xc_finish_mmu_updates(int xc_handle, xc_mmu_t *mmu);
+int xc_get_pfn_hole_start(int xc_handle, domid_t dom);
+
#endif
}
break;
- case DOM0_GETGNTTABLIST:
- {
- int i;
- struct domain *d = find_domain_by_id(op->u.getgnttablist.domain);
- unsigned long max_pfns = op->u.getgnttablist.max_pfns;
- unsigned long pfn;
- unsigned long *buffer = op->u.getgnttablist.buffer;
-
- ret = -EINVAL;
- if ( d != NULL )
- {
- ret = 0;
-
- for ( i = 0; i < max_pfns && i < NR_GRANT_FRAMES; i++ )
- {
- pfn = gnttab_shared_mfn(d, d->grant_table, i);
- if ( put_user(pfn, buffer) )
- {
- ret = -EFAULT;
- break;
- }
- buffer++;
- }
-
- op->u.getgnttablist.num_pfns = i;
- copy_to_user(u_dom0_op, op, sizeof(*op));
-
- put_domain(d);
- }
- }
- break;
-
case DOM0_GETMEMLIST:
{
int i;
}
break;
}
-
+
+ case MMUEXT_PFN_HOLE_BASE:
+ {
+ if (FOREIGNDOM->start_pfn_hole) {
+ rc = FOREIGNDOM->start_pfn_hole;
+ okay = 1;
+ } else {
+ rc = FOREIGNDOM->start_pfn_hole =
+ FOREIGNDOM->max_pages;
+ okay = 1;
+ if (shadow_mode_translate(FOREIGNDOM)) {
+ /* Fill in a few entries in the hole. At the
+ moment, this means the shared info page and the
+ grant table pages. */
+ struct domain_mmap_cache c1, c2;
+ unsigned long pfn, mfn, x;
+ domain_mmap_cache_init(&c1);
+ domain_mmap_cache_init(&c2);
+ shadow_lock(FOREIGNDOM);
+ pfn = FOREIGNDOM->start_pfn_hole;
+ mfn = virt_to_phys(FOREIGNDOM->shared_info) >> PAGE_SHIFT;
+ set_p2m_entry(FOREIGNDOM, pfn, mfn, &c1, &c2);
+ set_pfn_from_mfn(mfn, pfn);
+ pfn++;
+ for (x = 0; x < NR_GRANT_FRAMES; x++) {
+ mfn = gnttab_shared_mfn(FOREIGNDOM,
+ FOREIGNDOM->grant_table,
+ x);
+ set_p2m_entry(FOREIGNDOM, pfn, mfn, &c1, &c2);
+ set_pfn_from_mfn(mfn, pfn);
+ pfn++;
+ }
+ shadow_unlock(FOREIGNDOM);
+ domain_mmap_cache_destroy(&c1);
+ domain_mmap_cache_destroy(&c2);
+ }
+ }
+ break;
+ }
+
+ case MMUEXT_PFN_HOLE_SIZE:
+ {
+ if (shadow_mode_translate(FOREIGNDOM)) {
+ rc = PFN_HOLE_SIZE;
+ } else {
+ rc = 0;
+ }
+ okay = 1;
+ break;
+ }
+
default:
MEM_LOG("Invalid extended pt command 0x%x", op.cmd);
okay = 0;
long do_set_gdt(unsigned long *frame_list, unsigned int entries)
{
- int i, nr_pages = (entries + 511) / 512;
+ int nr_pages = (entries + 511) / 512;
unsigned long frames[16];
long ret;
#endif
#endif
+/* How large is the PFN reserved area, when we have one? */
+#define PFN_HOLE_SIZE 32
+
#ifndef STACK_ORDER
#define STACK_ORDER 1
#endif
unsigned long mfn; /* machine frame to be initialised */
} dom0_hypercall_init_t;
-#define DOM0_GETGNTTABLIST 49
-typedef struct {
- /* IN variables. */
- domid_t domain;
- unsigned long max_pfns;
- void *buffer;
- /* OUT variables. */
- unsigned long num_pfns;
-} dom0_getgnttablist_t;
-
typedef struct {
uint32_t cmd;
uint32_t interface_version; /* DOM0_INTERFACE_VERSION */
dom0_irq_permission_t irq_permission;
dom0_iomem_permission_t iomem_permission;
dom0_hypercall_init_t hypercall_init;
- dom0_getgnttablist_t getgnttablist;
uint8_t pad[128];
} u;
} dom0_op_t;
* cmd: MMUEXT_SET_LDT
* linear_addr: Linear address of LDT base (NB. must be page-aligned).
* nr_ents: Number of entries in LDT.
+ *
+ * cmd: MMUEXT_PFN_HOLE_BASE
+ * No additional arguments. Returns the first pfn in the Xen-reserved
+ * pfn hole. Note that we delay allocating the hole until the first
+ * time this is called.
+ *
+ * cmd: MMUEXT_PFN_HOLE_SIZE
+ * No additional arguments. Returns the number of pfns in the
+ * Xen-reserved pfn hole.
*/
#define MMUEXT_PIN_L1_TABLE 0
#define MMUEXT_PIN_L2_TABLE 1
#define MMUEXT_FLUSH_CACHE 12
#define MMUEXT_SET_LDT 13
#define MMUEXT_NEW_USER_BASEPTR 15
+#define MMUEXT_PFN_HOLE_BASE 16
+#define MMUEXT_PFN_HOLE_SIZE 17
#ifndef __ASSEMBLY__
struct mmuext_op {
/* Control-plane tools handle for this domain. */
xen_domain_handle_t handle;
+
+ /* Start of the PFN hole */
+ unsigned long start_pfn_hole;
};
struct domain_setup_info