This is enough to get block devices to work.
Note that this involves assigning PFNs to the machine frames used for
the grant table structures. While I'm here, I also assigned a PFN to
the shared info frame.
Signed-off-by: Steven Smith, sos22@cam.ac.uk
*/
#include "xg_private.h"
+#include "xc_private.h"
#include <xenctrl.h>
#if defined(__i386__)
#define L4_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
#endif
+#define NR_GRANT_FRAMES 4
+
#ifdef __ia64__
#define get_tot_pages xc_get_max_pages
#else
goto error_out;
}
+ shadow_mode_enabled = !!strstr(dsi.xen_guest_string,
+ "SHADOW=translate");
/*
* Why do we need this? The number of page-table frames depends on the
* size of the bootstrap address space. But the size of the address space
goto error_out;
}
- if ( (page_array = malloc((nr_pages + 1) * sizeof(unsigned long))) == NULL )
+ if ( (page_array = malloc((nr_pages + 1 + NR_GRANT_FRAMES) * sizeof(unsigned long))) == NULL )
{
PERROR("Could not allocate memory");
goto error_out;
if ( (mmu = xc_init_mmu_updates(xc_handle, dom)) == NULL )
goto error_out;
- shadow_mode_enabled = !!strstr(dsi.xen_guest_string,
- "SHADOW=translate");
-
/* Write the phys->machine and machine->phys table entries. */
physmap_pfn = (vphysmap_start - dsi.v_start) >> PAGE_SHIFT;
physmap = physmap_e = xc_map_foreign_range(
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
page_array[physmap_pfn++]);
- if (shadow_mode_enabled)
- page_array[nr_pages] = shared_info_frame;
+ 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 + shadow_mode_enabled; count++ )
+ for ( count = 0; count < nr_pages + 1 + NR_GRANT_FRAMES; count++ )
{
if ( xc_add_mmu_update(
xc_handle, mmu,
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
}
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;
gnttab_setup_table_t op;
struct domain *d;
int i;
+ unsigned long mfn;
if ( count != 1 )
return -EINVAL;
{
ASSERT(d->grant_table != NULL);
(void)put_user(GNTST_okay, &uop->status);
- for ( i = 0; i < op.nr_frames; i++ )
- (void)put_user(gnttab_shared_mfn(d, d->grant_table, i),
- &op.frame_list[i]);
+ for ( i = 0; i < op.nr_frames; i++ ) {
+ mfn = gnttab_shared_mfn(d, d->grant_table, i);
+ if (shadow_mode_translate(d))
+ mfn = __mfn_to_gpfn(d, mfn);
+ (void)put_user(mfn, &op.frame_list[i]);
+ }
}
put_domain(d);
domid_t domain; /* domain to be affected */
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;