From cd9edced7b75c82b53b578fbe751fc00735d4448 Mon Sep 17 00:00:00 2001 From: "sos22@douglas.cl.cam.ac.uk" Date: Wed, 25 Jan 2006 18:57:44 +0100 Subject: [PATCH] Make some basic cases of grant tables work in shadow translate mode. 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 --- tools/libxc/xc_linux_build.c | 23 ++++++++++++++++------- tools/libxc/xc_private.c | 29 +++++++++++++++++++++++++++++ tools/libxc/xc_private.h | 3 +++ xen/arch/x86/dom0_ops.c | 32 ++++++++++++++++++++++++++++++++ xen/common/grant_table.c | 10 +++++++--- xen/include/public/dom0_ops.h | 13 ++++++++++++- 6 files changed, 99 insertions(+), 11 deletions(-) diff --git a/tools/libxc/xc_linux_build.c b/tools/libxc/xc_linux_build.c index 27b60551f8..c0b0568811 100644 --- a/tools/libxc/xc_linux_build.c +++ b/tools/libxc/xc_linux_build.c @@ -3,6 +3,7 @@ */ #include "xg_private.h" +#include "xc_private.h" #include #if defined(__i386__) @@ -32,6 +33,8 @@ #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 @@ -504,6 +507,8 @@ static int setup_guest(int xc_handle, 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 @@ -587,7 +592,7 @@ static int setup_guest(int xc_handle, 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; @@ -622,19 +627,23 @@ static int setup_guest(int xc_handle, 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, diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c index 75556f6847..8993af0b57 100644 --- a/tools/libxc/xc_private.c +++ b/tools/libxc/xc_private.c @@ -314,6 +314,35 @@ int xc_get_pfn_list(int xc_handle, 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; diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h index 8c19ecd218..b366db69e5 100644 --- a/tools/libxc/xc_private.h +++ b/tools/libxc/xc_private.h @@ -111,6 +111,9 @@ static inline int do_dom0_op(int xc_handle, dom0_op_t *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 diff --git a/xen/arch/x86/dom0_ops.c b/xen/arch/x86/dom0_ops.c index 789d01899a..4a61ba4948 100644 --- a/xen/arch/x86/dom0_ops.c +++ b/xen/arch/x86/dom0_ops.c @@ -330,6 +330,38 @@ long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op) } 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; diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c index 7576d715d3..3f788ca34f 100644 --- a/xen/common/grant_table.c +++ b/xen/common/grant_table.c @@ -481,6 +481,7 @@ gnttab_setup_table( gnttab_setup_table_t op; struct domain *d; int i; + unsigned long mfn; if ( count != 1 ) return -EINVAL; @@ -520,9 +521,12 @@ gnttab_setup_table( { 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); diff --git a/xen/include/public/dom0_ops.h b/xen/include/public/dom0_ops.h index 4a70a77e49..6d6a04594e 100644 --- a/xen/include/public/dom0_ops.h +++ b/xen/include/public/dom0_ops.h @@ -430,7 +430,17 @@ typedef struct { 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 */ @@ -472,6 +482,7 @@ typedef struct { 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; -- 2.30.2