[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH XEN RFC] libxc: use an uncached mapping of guest ram in domain builder
On Wed, Dec 18, 2013 at 05:30:47PM +0000, Ian Campbell wrote: > VERY MUCH A WIP. > > On ARM guest OSes are started with MMU and Caches disables (as they are on > native) however caching is enabled in the domain running the builder and > therefore we must use an explcitly uncached mapping, otherwise when the guest > starts running it may not see them. > > Cache flushes are not sufficient because there is a race between the flush and > the unmap, where the processor may speculatively fill a cache line. Thanks to > Catalin Marinas and Marc Zyngier for pointing this out. > > Therefore use the newly introduced IOCTL_PRIVCMD_MMAPBATCH_V2_UNCACHED on ARM > when mapping guest memory from xc_dom_* (which means xc_dom_boot_domU_map in > practice). This avoids issues with the processor dirtying cache lines while > the guest will then fail to see because it starts with MMU and caches > disabled. Why not make the default IOCTL_PRIVCMD_MMAPBATCH_V2 when running under ARM do this? > > The xc_map_foreign_* functions here are a bit of a twisty maze, so far I have > just updated exactly the call path which is used by the function which I > needed to update. I have not yet considered non-xc_linux*.c nor tried to > disentangle this into a saner patch, nor any level of consistency with the > other foreign mapping functions. I've not even tried to compile on x86. > > This applies on top of a revert of "tools: libxc: flush data cache after > loading images into guest memory" (a0035ecc0d82) which I will include in the > eventual proper posting. > > Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx> > Cc: Ian Jackson <ian.jackson@xxxxxxxxxxxxx> > --- > tools/include/xen-sys/Linux/privcmd.h | 2 ++ > tools/libxc/xc_core_x86.c | 4 ++-- > tools/libxc/xc_dom_boot.c | 2 +- > tools/libxc/xc_domain_restore.c | 4 ++-- > tools/libxc/xc_domain_save.c | 4 ++-- > tools/libxc/xc_foreign_memory.c | 19 ++++++++++++++----- > tools/libxc/xc_gnttab.c | 2 +- > tools/libxc/xc_linux_osdep.c | 18 +++++++++++++----- > tools/libxc/xc_private.h | 3 +++ > tools/libxc/xenctrl.h | 5 +++-- > tools/libxc/xenctrl_osdep_ENOSYS.c | 4 ++-- > tools/libxc/xenctrlosdep.h | 4 ++-- > 12 files changed, 47 insertions(+), 24 deletions(-) > > diff --git a/tools/include/xen-sys/Linux/privcmd.h > b/tools/include/xen-sys/Linux/privcmd.h > index 5be860a..e3a92a0 100644 > --- a/tools/include/xen-sys/Linux/privcmd.h > +++ b/tools/include/xen-sys/Linux/privcmd.h > @@ -88,5 +88,7 @@ typedef struct privcmd_mmapbatch_v2 { > _IOC(_IOC_NONE, 'P', 3, sizeof(privcmd_mmapbatch_t)) > #define IOCTL_PRIVCMD_MMAPBATCH_V2 \ > _IOC(_IOC_NONE, 'P', 4, sizeof(privcmd_mmapbatch_v2_t)) > +#define IOCTL_PRIVCMD_MMAPBATCH_V2_UNCACHED \ > + _IOC(_IOC_NONE, 'P', 5, sizeof(privcmd_mmapbatch_v2_t)) > > #endif /* __LINUX_PUBLIC_PRIVCMD_H__ */ > diff --git a/tools/libxc/xc_core_x86.c b/tools/libxc/xc_core_x86.c > index e328dcf..8e73bc4 100644 > --- a/tools/libxc/xc_core_x86.c > +++ b/tools/libxc/xc_core_x86.c > @@ -131,7 +131,7 @@ xc_core_arch_map_p2m_rw(xc_interface *xch, struct > domain_info_context *dinfo, xc > live_p2m_frame_list = > xc_map_foreign_pages(xch, dom, PROT_READ, > p2m_frame_list_list, > - P2M_FLL_ENTRIES); > + P2M_FLL_ENTRIES, 1); > > if ( !live_p2m_frame_list ) > { > @@ -159,7 +159,7 @@ xc_core_arch_map_p2m_rw(xc_interface *xch, struct > domain_info_context *dinfo, xc > *live_p2m = xc_map_foreign_pages(xch, dom, > rw ? (PROT_READ | PROT_WRITE) : > PROT_READ, > p2m_frame_list, > - P2M_FL_ENTRIES); > + P2M_FL_ENTRIES, 1); > > if ( !*live_p2m ) > { > diff --git a/tools/libxc/xc_dom_boot.c b/tools/libxc/xc_dom_boot.c > index fdfeaf8..691fc2b 100644 > --- a/tools/libxc/xc_dom_boot.c > +++ b/tools/libxc/xc_dom_boot.c > @@ -179,7 +179,7 @@ void *xc_dom_boot_domU_map(struct xc_dom_image *dom, > xen_pfn_t pfn, > for ( i = 0; i < count; i++ ) > entries[i].mfn = xc_dom_p2m_host(dom, pfn + i); > > - ptr = xc_map_foreign_ranges(dom->xch, dom->guest_domid, > + ptr = xc_map_foreign_ranges_uncached(dom->xch, dom->guest_domid, > count << page_shift, PROT_READ | PROT_WRITE, 1 << page_shift, > entries, count); > if ( ptr == NULL ) > diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c > index 80769a7..a4c621b 100644 > --- a/tools/libxc/xc_domain_restore.c > +++ b/tools/libxc/xc_domain_restore.c > @@ -1885,7 +1885,7 @@ int xc_domain_restore(xc_interface *xch, int io_fd, > uint32_t dom, > if ( (i == (dinfo->p2m_size-1)) || (j == MAX_BATCH_SIZE) ) > { > region_base = xc_map_foreign_pages( > - xch, dom, PROT_READ | PROT_WRITE, region_mfn, j); > + xch, dom, PROT_READ | PROT_WRITE, region_mfn, j, 1); > if ( region_base == NULL ) > { > PERROR("map batch failed"); > @@ -2222,7 +2222,7 @@ int xc_domain_restore(xc_interface *xch, int io_fd, > uint32_t dom, > > /* Copy the P2M we've constructed to the 'live' P2M */ > if ( !(ctx->live_p2m = xc_map_foreign_pages(xch, dom, PROT_WRITE, > - p2m_frame_list, P2M_FL_ENTRIES)) ) > + p2m_frame_list, > P2M_FL_ENTRIES, 1)) ) > { > PERROR("Couldn't map p2m table"); > goto out; > diff --git a/tools/libxc/xc_domain_save.c b/tools/libxc/xc_domain_save.c > index 42c4752..00c97f7 100644 > --- a/tools/libxc/xc_domain_save.c > +++ b/tools/libxc/xc_domain_save.c > @@ -631,7 +631,7 @@ static xen_pfn_t *map_and_save_p2m_table(xc_interface > *xch, > live_p2m_frame_list = > xc_map_foreign_pages(xch, dom, PROT_READ, > p2m_frame_list_list, > - P2M_FLL_ENTRIES); > + P2M_FLL_ENTRIES, 1); > if ( !live_p2m_frame_list ) > { > PERROR("Couldn't map p2m_frame_list"); > @@ -666,7 +666,7 @@ static xen_pfn_t *map_and_save_p2m_table(xc_interface > *xch, > > p2m = xc_map_foreign_pages(xch, dom, PROT_READ, > p2m_frame_list, > - P2M_FL_ENTRIES); > + P2M_FL_ENTRIES, 1); > if ( !p2m ) > { > PERROR("Couldn't map p2m table"); > diff --git a/tools/libxc/xc_foreign_memory.c b/tools/libxc/xc_foreign_memory.c > index 7dfc817..ac4793d 100644 > --- a/tools/libxc/xc_foreign_memory.c > +++ b/tools/libxc/xc_foreign_memory.c > @@ -21,7 +21,7 @@ > #include "xc_private.h" > > void *xc_map_foreign_pages(xc_interface *xch, uint32_t dom, int prot, > - const xen_pfn_t *arr, int num) > + const xen_pfn_t *arr, int num, int cached) > { > void *res; > int i, *err; > @@ -35,7 +35,7 @@ void *xc_map_foreign_pages(xc_interface *xch, uint32_t dom, > int prot, > if (!err) > return NULL; > > - res = xc_map_foreign_bulk(xch, dom, prot, arr, err, num); > + res = xc_map_foreign_bulk(xch, dom, prot, arr, err, num, cached); > if (res) { > for (i = 0; i < num; i++) { > if (err[i]) { > @@ -63,7 +63,15 @@ void *xc_map_foreign_ranges(xc_interface *xch, uint32_t > dom, > privcmd_mmap_entry_t entries[], int nentries) > { > return xch->ops->u.privcmd.map_foreign_ranges(xch, xch->ops_handle, > - dom, size, prot, > chunksize, entries, nentries); > + dom, size, prot, > chunksize, entries, nentries, 1); > +} > + > +void *xc_map_foreign_ranges_uncached(xc_interface *xch, uint32_t dom, > + size_t size, int prot, size_t chunksize, > + privcmd_mmap_entry_t entries[], int nentries) > +{ > + return xch->ops->u.privcmd.map_foreign_ranges(xch, xch->ops_handle, > + dom, size, prot, > chunksize, entries, nentries, 0); > } > > void *xc_map_foreign_batch(xc_interface *xch, uint32_t dom, int prot, > @@ -74,10 +82,11 @@ void *xc_map_foreign_batch(xc_interface *xch, uint32_t > dom, int prot, > } > > void *xc_map_foreign_bulk(xc_interface *xch, uint32_t dom, int prot, > - const xen_pfn_t *arr, int *err, unsigned int num) > + const xen_pfn_t *arr, int *err, unsigned int num, > + int cached) > { > return xch->ops->u.privcmd.map_foreign_bulk(xch, xch->ops_handle, > - dom, prot, arr, err, num); > + dom, prot, arr, err, num, > cached); > } > > /* stub for all not yet converted OSes */ > diff --git a/tools/libxc/xc_gnttab.c b/tools/libxc/xc_gnttab.c > index 79dab40..4774c69 100644 > --- a/tools/libxc/xc_gnttab.c > +++ b/tools/libxc/xc_gnttab.c > @@ -114,7 +114,7 @@ static void *_gnttab_map_table(xc_interface *xch, int > domid, int *gnt_num) > pfn_list[i] = frame_list[i]; > > gnt = xc_map_foreign_pages(xch, domid, PROT_READ, pfn_list, > - setup.nr_frames); > + setup.nr_frames, 1); > if ( !gnt ) > { > ERROR("Could not map grant table\n"); > diff --git a/tools/libxc/xc_linux_osdep.c b/tools/libxc/xc_linux_osdep.c > index 73860a2..09aae37 100644 > --- a/tools/libxc/xc_linux_osdep.c > +++ b/tools/libxc/xc_linux_osdep.c > @@ -246,7 +246,8 @@ out: > > static void *linux_privcmd_map_foreign_bulk(xc_interface *xch, > xc_osdep_handle h, > uint32_t dom, int prot, > - const xen_pfn_t *arr, int *err, > unsigned int num) > + const xen_pfn_t *arr, int *err, > + unsigned int num, int cached) > { > int fd = (int)h; > privcmd_mmapbatch_v2_t ioctlx; > @@ -254,6 +255,11 @@ static void *linux_privcmd_map_foreign_bulk(xc_interface > *xch, xc_osdep_handle h > unsigned int i; > int rc; > > +#if defined(__i386__) || defined(__x86_64__) > + /* No need for cache maintenance on x86 */ > + cached = 1; > +#endif > + > addr = mmap(NULL, (unsigned long)num << XC_PAGE_SHIFT, prot, MAP_SHARED, > fd, 0); > if ( addr == MAP_FAILED ) > @@ -268,7 +274,9 @@ static void *linux_privcmd_map_foreign_bulk(xc_interface > *xch, xc_osdep_handle h > ioctlx.arr = arr; > ioctlx.err = err; > > - rc = ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH_V2, &ioctlx); > + rc = ioctl(fd, cached ? IOCTL_PRIVCMD_MMAPBATCH_V2 > + : IOCTL_PRIVCMD_MMAPBATCH_V2_UNCACHED, > + &ioctlx); > > /* Command was recognized, some gfn in arr are in paging state */ > if ( rc < 0 && errno == ENOENT ) > @@ -384,7 +392,7 @@ static void *linux_privcmd_map_foreign_range(xc_interface > *xch, xc_osdep_handle > for ( i = 0; i < num; i++ ) > arr[i] = mfn + i; > > - ret = xc_map_foreign_pages(xch, dom, prot, arr, num); > + ret = xc_map_foreign_pages(xch, dom, prot, arr, num, 1); > free(arr); > return ret; > } > @@ -392,7 +400,7 @@ static void *linux_privcmd_map_foreign_range(xc_interface > *xch, xc_osdep_handle > static void *linux_privcmd_map_foreign_ranges(xc_interface *xch, > xc_osdep_handle h, > uint32_t dom, size_t size, int > prot, > size_t chunksize, > privcmd_mmap_entry_t entries[], > - int nentries) > + int nentries, int cached) > { > xen_pfn_t *arr; > int num_per_entry; > @@ -411,7 +419,7 @@ static void > *linux_privcmd_map_foreign_ranges(xc_interface *xch, xc_osdep_handle > for ( j = 0; j < num_per_entry; j++ ) > arr[i * num_per_entry + j] = entries[i].mfn + j; > > - ret = xc_map_foreign_pages(xch, dom, prot, arr, num); > + ret = xc_map_foreign_pages(xch, dom, prot, arr, num, 1); > free(arr); > return ret; > } > diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h > index 92271c9..e040179 100644 > --- a/tools/libxc/xc_private.h > +++ b/tools/libxc/xc_private.h > @@ -294,6 +294,9 @@ int do_memory_op(xc_interface *xch, int cmd, void *arg, > size_t len); > void *xc_map_foreign_ranges(xc_interface *xch, uint32_t dom, > size_t size, int prot, size_t chunksize, > privcmd_mmap_entry_t entries[], int nentries); > +void *xc_map_foreign_ranges_uncached(xc_interface *xch, uint32_t dom, > + size_t size, int prot, size_t chunksize, > + privcmd_mmap_entry_t entries[], int nentries); > > int xc_get_pfn_type_batch(xc_interface *xch, uint32_t dom, > unsigned int num, xen_pfn_t *); > diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h > index 6e58ebe..b20731c 100644 > --- a/tools/libxc/xenctrl.h > +++ b/tools/libxc/xenctrl.h > @@ -1324,7 +1324,7 @@ void *xc_map_foreign_range(xc_interface *xch, uint32_t > dom, > unsigned long mfn ); > > void *xc_map_foreign_pages(xc_interface *xch, uint32_t dom, int prot, > - const xen_pfn_t *arr, int num ); > + const xen_pfn_t *arr, int num, int cached); > > /** > * DEPRECATED - use xc_map_foreign_bulk() instead. > @@ -1342,7 +1342,8 @@ void *xc_map_foreign_batch(xc_interface *xch, uint32_t > dom, int prot, > * set to the corresponding errno value. > */ > void *xc_map_foreign_bulk(xc_interface *xch, uint32_t dom, int prot, > - const xen_pfn_t *arr, int *err, unsigned int num); > + const xen_pfn_t *arr, int *err, unsigned int num, > + int cached); > > /** > * Translates a virtual address in the context of a given domain and > diff --git a/tools/libxc/xenctrl_osdep_ENOSYS.c > b/tools/libxc/xenctrl_osdep_ENOSYS.c > index 4821342..d26c696 100644 > --- a/tools/libxc/xenctrl_osdep_ENOSYS.c > +++ b/tools/libxc/xenctrl_osdep_ENOSYS.c > @@ -42,7 +42,7 @@ static void *ENOSYS_privcmd_map_foreign_batch(xc_interface > *xch, xc_osdep_handle > } > > static void *ENOSYS_privcmd_map_foreign_bulk(xc_interface *xch, > xc_osdep_handle h, uint32_t dom, int prot, > - const xen_pfn_t *arr, int *err, > unsigned int num) > + const xen_pfn_t *arr, int *err, > unsigned int num, int cached) > { > IPRINTF(xch, "ENOSYS_privcmd %p: map_foreign_buld: dom%d prot %#x arr %p > err %p num %d\n", h, dom, prot, arr, err, num); > return MAP_FAILED; > @@ -57,7 +57,7 @@ static void *ENOSYS_privcmd_map_foreign_range(xc_interface > *xch, xc_osdep_handle > > static void *ENOSYS_privcmd_map_foreign_ranges(xc_interface *xch, > xc_osdep_handle h, uint32_t dom, size_t size, int prot, > size_t chunksize, > privcmd_mmap_entry_t entries[], > - int nentries) > + int nentries, int cached) > { > IPRINTF(xch, "ENOSYS_privcmd %p: map_foreign_ranges: dom%d size %zd prot > %#x chunksize %zd entries %p num %d\n", h, dom, size, prot, chunksize, > entries, nentries); > return MAP_FAILED; > diff --git a/tools/libxc/xenctrlosdep.h b/tools/libxc/xenctrlosdep.h > index e610a24..3daf757 100644 > --- a/tools/libxc/xenctrlosdep.h > +++ b/tools/libxc/xenctrlosdep.h > @@ -83,12 +83,12 @@ struct xc_osdep_ops > void *(*map_foreign_batch)(xc_interface *xch, xc_osdep_handle h, > uint32_t dom, int prot, > xen_pfn_t *arr, int num); > void *(*map_foreign_bulk)(xc_interface *xch, xc_osdep_handle h, > uint32_t dom, int prot, > - const xen_pfn_t *arr, int *err, > unsigned int num); > + const xen_pfn_t *arr, int *err, > unsigned int num, int cached); > void *(*map_foreign_range)(xc_interface *xch, xc_osdep_handle h, > uint32_t dom, int size, int prot, > unsigned long mfn); > void *(*map_foreign_ranges)(xc_interface *xch, xc_osdep_handle > h, uint32_t dom, size_t size, int prot, > size_t chunksize, > privcmd_mmap_entry_t entries[], > - int nentries); > + int nentries, int cached); > } privcmd; > struct { > int (*fd)(xc_evtchn *xce, xc_osdep_handle h); > -- > 1.7.10.4 > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@xxxxxxxxxxxxx > http://lists.xen.org/xen-devel _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |