David Vrabel
2011-Sep-29 15:53 UTC
[Xen-devel] [PATCH 0/4] xen: map foreign pages for shared rings by updating the PTEs directly
[Resend as requested by Konrad.] This series of patches allows the vmalloc_sync_all() to be removed from alloc_vm_area() by getting the hypervisor to update the PTEs (in init_mm) directly rather than having the hypervisor look in the current page tables to find the PTEs. Once the hypervisor has updated the PTEs, the normal mechanism of syncing the page tables after a fault works as expected. This mechanism doesn''t currently work on the ia64 port as that does not support the GNTMAP_contains_pte flag. David _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
David Vrabel
2011-Sep-29 15:53 UTC
[Xen-devel] [PATCH 1/4] xen: use generic functions instead of xen_{alloc, free}_vm_area()
From: David Vrabel <david.vrabel@citrix.com> Replace calls to the Xen-specific xen_alloc_vm_area() and xen_free_vm_area() functions with the generic equivalent (alloc_vm_area() and free_vm_area()). On x86, these were identical already. Signed-off-by: David Vrabel <david.vrabel@citrix.com> --- arch/ia64/include/asm/xen/grant_table.h | 29 -------------- arch/ia64/xen/grant-table.c | 62 ------------------------------- arch/x86/include/asm/xen/grant_table.h | 7 --- arch/x86/xen/grant-table.c | 2 +- drivers/xen/xenbus/xenbus_client.c | 6 +- include/xen/grant_table.h | 1 - 6 files changed, 4 insertions(+), 103 deletions(-) delete mode 100644 arch/ia64/include/asm/xen/grant_table.h delete mode 100644 arch/x86/include/asm/xen/grant_table.h diff --git a/arch/ia64/include/asm/xen/grant_table.h b/arch/ia64/include/asm/xen/grant_table.h deleted file mode 100644 index 2b1fae0..0000000 --- a/arch/ia64/include/asm/xen/grant_table.h +++ /dev/null @@ -1,29 +0,0 @@ -/****************************************************************************** - * arch/ia64/include/asm/xen/grant_table.h - * - * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> - * VA Linux Systems Japan K.K. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef _ASM_IA64_XEN_GRANT_TABLE_H -#define _ASM_IA64_XEN_GRANT_TABLE_H - -struct vm_struct *xen_alloc_vm_area(unsigned long size); -void xen_free_vm_area(struct vm_struct *area); - -#endif /* _ASM_IA64_XEN_GRANT_TABLE_H */ diff --git a/arch/ia64/xen/grant-table.c b/arch/ia64/xen/grant-table.c index 48cca37..c182813 100644 --- a/arch/ia64/xen/grant-table.c +++ b/arch/ia64/xen/grant-table.c @@ -31,68 +31,6 @@ #include <asm/xen/hypervisor.h> -struct vm_struct *xen_alloc_vm_area(unsigned long size) -{ - int order; - unsigned long virt; - unsigned long nr_pages; - struct vm_struct *area; - - order = get_order(size); - virt = __get_free_pages(GFP_KERNEL, order); - if (virt == 0) - goto err0; - nr_pages = 1 << order; - scrub_pages(virt, nr_pages); - - area = kmalloc(sizeof(*area), GFP_KERNEL); - if (area == NULL) - goto err1; - - area->flags = VM_IOREMAP; - area->addr = (void *)virt; - area->size = size; - area->pages = NULL; - area->nr_pages = nr_pages; - area->phys_addr = 0; /* xenbus_map_ring_valloc uses this field! */ - - return area; - -err1: - free_pages(virt, order); -err0: - return NULL; -} -EXPORT_SYMBOL_GPL(xen_alloc_vm_area); - -void xen_free_vm_area(struct vm_struct *area) -{ - unsigned int order = get_order(area->size); - unsigned long i; - unsigned long phys_addr = __pa(area->addr); - - /* This area is used for foreign page mappping. - * So underlying machine page may not be assigned. */ - for (i = 0; i < (1 << order); i++) { - unsigned long ret; - unsigned long gpfn = (phys_addr >> PAGE_SHIFT) + i; - struct xen_memory_reservation reservation = { - .nr_extents = 1, - .address_bits = 0, - .extent_order = 0, - .domid = DOMID_SELF - }; - set_xen_guest_handle(reservation.extent_start, &gpfn); - ret = HYPERVISOR_memory_op(XENMEM_populate_physmap, - &reservation); - BUG_ON(ret != 1); - } - free_pages((unsigned long)area->addr, order); - kfree(area); -} -EXPORT_SYMBOL_GPL(xen_free_vm_area); - - /**************************************************************************** * grant table hack * cmd: GNTTABOP_xxx diff --git a/arch/x86/include/asm/xen/grant_table.h b/arch/x86/include/asm/xen/grant_table.h deleted file mode 100644 index fdbbb45..0000000 --- a/arch/x86/include/asm/xen/grant_table.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _ASM_X86_XEN_GRANT_TABLE_H -#define _ASM_X86_XEN_GRANT_TABLE_H - -#define xen_alloc_vm_area(size) alloc_vm_area(size) -#define xen_free_vm_area(area) free_vm_area(area) - -#endif /* _ASM_X86_XEN_GRANT_TABLE_H */ diff --git a/arch/x86/xen/grant-table.c b/arch/x86/xen/grant-table.c index 49ba9b5..6bbfd7a 100644 --- a/arch/x86/xen/grant-table.c +++ b/arch/x86/xen/grant-table.c @@ -71,7 +71,7 @@ int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes, if (shared == NULL) { struct vm_struct *area - xen_alloc_vm_area(PAGE_SIZE * max_nr_gframes); + alloc_vm_area(PAGE_SIZE * max_nr_gframes); BUG_ON(area == NULL); shared = area->addr; *__shared = shared; diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c index cdacf92..229d3ad 100644 --- a/drivers/xen/xenbus/xenbus_client.c +++ b/drivers/xen/xenbus/xenbus_client.c @@ -443,7 +443,7 @@ int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr) *vaddr = NULL; - area = xen_alloc_vm_area(PAGE_SIZE); + area = alloc_vm_area(PAGE_SIZE); if (!area) return -ENOMEM; @@ -453,7 +453,7 @@ int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr) BUG(); if (op.status != GNTST_okay) { - xen_free_vm_area(area); + free_vm_area(area); xenbus_dev_fatal(dev, op.status, "mapping in shared page %d from domain %d", gnt_ref, dev->otherend_id); @@ -552,7 +552,7 @@ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr) BUG(); if (op.status == GNTST_okay) - xen_free_vm_area(area); + free_vm_area(area); else xenbus_dev_error(dev, op.status, "unmapping page at handle %d error %d", diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h index b1fab6b..8a8bb76 100644 --- a/include/xen/grant_table.h +++ b/include/xen/grant_table.h @@ -43,7 +43,6 @@ #include <xen/interface/grant_table.h> #include <asm/xen/hypervisor.h> -#include <asm/xen/grant_table.h> #include <xen/features.h> -- 1.7.2.5 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
David Vrabel
2011-Sep-29 15:53 UTC
[Xen-devel] [PATCH 2/4] block: xen-blkback: use API provided by xenbus module to map rings
From: David Vrabel <david.vrabel@citrix.com> The xenbus module provides xenbus_map_ring_valloc() and xenbus_map_ring_vfree(). Use these to map the ring pages granted by the frontend. Signed-off-by: David Vrabel <david.vrabel@citrix.com> --- drivers/block/xen-blkback/common.h | 5 +-- drivers/block/xen-blkback/xenbus.c | 54 ++++------------------------------- 2 files changed, 8 insertions(+), 51 deletions(-) diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index 00c57c9..7ec0e88 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -139,7 +139,7 @@ struct xen_blkif { /* Comms information. */ enum blkif_protocol blk_protocol; union blkif_back_rings blk_rings; - struct vm_struct *blk_ring_area; + void *blk_ring; /* The VBD attached to this interface. */ struct xen_vbd vbd; /* Back pointer to the backend_info. */ @@ -163,9 +163,6 @@ struct xen_blkif { int st_wr_sect; wait_queue_head_t waiting_to_free; - - grant_handle_t shmem_handle; - grant_ref_t shmem_ref; }; diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 5fd2010..69233dd 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -120,38 +120,6 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid) return blkif; } -static int map_frontend_page(struct xen_blkif *blkif, unsigned long shared_page) -{ - struct gnttab_map_grant_ref op; - - gnttab_set_map_op(&op, (unsigned long)blkif->blk_ring_area->addr, - GNTMAP_host_map, shared_page, blkif->domid); - - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) - BUG(); - - if (op.status) { - DPRINTK("Grant table operation failure !\n"); - return op.status; - } - - blkif->shmem_ref = shared_page; - blkif->shmem_handle = op.handle; - - return 0; -} - -static void unmap_frontend_page(struct xen_blkif *blkif) -{ - struct gnttab_unmap_grant_ref op; - - gnttab_set_unmap_op(&op, (unsigned long)blkif->blk_ring_area->addr, - GNTMAP_host_map, blkif->shmem_handle); - - if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)) - BUG(); -} - static int xen_blkif_map(struct xen_blkif *blkif, unsigned long shared_page, unsigned int evtchn) { @@ -161,35 +129,29 @@ static int xen_blkif_map(struct xen_blkif *blkif, unsigned long shared_page, if (blkif->irq) return 0; - blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE); - if (!blkif->blk_ring_area) - return -ENOMEM; - - err = map_frontend_page(blkif, shared_page); - if (err) { - free_vm_area(blkif->blk_ring_area); + err = xenbus_map_ring_valloc(blkif->be->dev, shared_page, &blkif->blk_ring); + if (err < 0) return err; - } switch (blkif->blk_protocol) { case BLKIF_PROTOCOL_NATIVE: { struct blkif_sring *sring; - sring = (struct blkif_sring *)blkif->blk_ring_area->addr; + sring = (struct blkif_sring *)blkif->blk_ring; BACK_RING_INIT(&blkif->blk_rings.native, sring, PAGE_SIZE); break; } case BLKIF_PROTOCOL_X86_32: { struct blkif_x86_32_sring *sring_x86_32; - sring_x86_32 = (struct blkif_x86_32_sring *)blkif->blk_ring_area->addr; + sring_x86_32 = (struct blkif_x86_32_sring *)blkif->blk_ring; BACK_RING_INIT(&blkif->blk_rings.x86_32, sring_x86_32, PAGE_SIZE); break; } case BLKIF_PROTOCOL_X86_64: { struct blkif_x86_64_sring *sring_x86_64; - sring_x86_64 = (struct blkif_x86_64_sring *)blkif->blk_ring_area->addr; + sring_x86_64 = (struct blkif_x86_64_sring *)blkif->blk_ring; BACK_RING_INIT(&blkif->blk_rings.x86_64, sring_x86_64, PAGE_SIZE); break; } @@ -201,8 +163,7 @@ static int xen_blkif_map(struct xen_blkif *blkif, unsigned long shared_page, xen_blkif_be_int, 0, "blkif-backend", blkif); if (err < 0) { - unmap_frontend_page(blkif); - free_vm_area(blkif->blk_ring_area); + xenbus_unmap_ring_vfree(blkif->be->dev, blkif->blk_ring); blkif->blk_rings.common.sring = NULL; return err; } @@ -228,8 +189,7 @@ static void xen_blkif_disconnect(struct xen_blkif *blkif) } if (blkif->blk_rings.common.sring) { - unmap_frontend_page(blkif); - free_vm_area(blkif->blk_ring_area); + xenbus_unmap_ring_vfree(blkif->be->dev, blkif->blk_ring); blkif->blk_rings.common.sring = NULL; } } -- 1.7.2.5 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
David Vrabel
2011-Sep-29 15:53 UTC
[Xen-devel] [PATCH 3/4] net: xen-netback: use API provided by xenbus module to map rings
From: David Vrabel <david.vrabel@citrix.com> The xenbus module provides xenbus_map_ring_valloc() and xenbus_map_ring_vfree(). Use these to map the Tx and Rx ring pages granted by the frontend. Signed-off-by: David Vrabel <david.vrabel@citrix.com> Acked-by: Ian Campbell <ian.campbell@citrix.com> --- drivers/net/xen-netback/common.h | 11 ++--- drivers/net/xen-netback/netback.c | 80 ++++++++----------------------------- 2 files changed, 22 insertions(+), 69 deletions(-) diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 161f207..94b79c3 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h @@ -58,10 +58,6 @@ struct xenvif { u8 fe_dev_addr[6]; /* Physical parameters of the comms window. */ - grant_handle_t tx_shmem_handle; - grant_ref_t tx_shmem_ref; - grant_handle_t rx_shmem_handle; - grant_ref_t rx_shmem_ref; unsigned int irq; /* List of frontends to notify after a batch of frames sent. */ @@ -70,8 +66,6 @@ struct xenvif { /* The shared rings and indexes. */ struct xen_netif_tx_back_ring tx; struct xen_netif_rx_back_ring rx; - struct vm_struct *tx_comms_area; - struct vm_struct *rx_comms_area; /* Frontend feature information. */ u8 can_sg:1; @@ -106,6 +100,11 @@ struct xenvif { wait_queue_head_t waiting_to_free; }; +static inline struct xenbus_device *xenvif_to_xenbus_device(struct xenvif *vif) +{ + return to_xenbus_device(vif->dev->dev.parent); +} + #define XEN_NETIF_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, PAGE_SIZE) #define XEN_NETIF_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, PAGE_SIZE) diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index fd00f25..3af2924 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -1577,88 +1577,42 @@ static int xen_netbk_kthread(void *data) void xen_netbk_unmap_frontend_rings(struct xenvif *vif) { - struct gnttab_unmap_grant_ref op; - - if (vif->tx.sring) { - gnttab_set_unmap_op(&op, (unsigned long)vif->tx_comms_area->addr, - GNTMAP_host_map, vif->tx_shmem_handle); - - if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)) - BUG(); - } - - if (vif->rx.sring) { - gnttab_set_unmap_op(&op, (unsigned long)vif->rx_comms_area->addr, - GNTMAP_host_map, vif->rx_shmem_handle); - - if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)) - BUG(); - } - if (vif->rx_comms_area) - free_vm_area(vif->rx_comms_area); - if (vif->tx_comms_area) - free_vm_area(vif->tx_comms_area); + if (vif->tx.sring) + xenbus_unmap_ring_vfree(xenvif_to_xenbus_device(vif), + vif->tx.sring); + if (vif->rx.sring) + xenbus_unmap_ring_vfree(xenvif_to_xenbus_device(vif), + vif->rx.sring); } int xen_netbk_map_frontend_rings(struct xenvif *vif, grant_ref_t tx_ring_ref, grant_ref_t rx_ring_ref) { - struct gnttab_map_grant_ref op; + void *addr; struct xen_netif_tx_sring *txs; struct xen_netif_rx_sring *rxs; int err = -ENOMEM; - vif->tx_comms_area = alloc_vm_area(PAGE_SIZE); - if (vif->tx_comms_area == NULL) + err = xenbus_map_ring_valloc(xenvif_to_xenbus_device(vif), + tx_ring_ref, &addr); + if (err) goto err; - vif->rx_comms_area = alloc_vm_area(PAGE_SIZE); - if (vif->rx_comms_area == NULL) - goto err; - - gnttab_set_map_op(&op, (unsigned long)vif->tx_comms_area->addr, - GNTMAP_host_map, tx_ring_ref, vif->domid); - - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) - BUG(); - - if (op.status) { - netdev_warn(vif->dev, - "failed to map tx ring. err=%d status=%d\n", - err, op.status); - err = op.status; - goto err; - } - - vif->tx_shmem_ref = tx_ring_ref; - vif->tx_shmem_handle = op.handle; - - txs = (struct xen_netif_tx_sring *)vif->tx_comms_area->addr; + txs = (struct xen_netif_tx_sring *)addr; BACK_RING_INIT(&vif->tx, txs, PAGE_SIZE); - gnttab_set_map_op(&op, (unsigned long)vif->rx_comms_area->addr, - GNTMAP_host_map, rx_ring_ref, vif->domid); - - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) - BUG(); - - if (op.status) { - netdev_warn(vif->dev, - "failed to map rx ring. err=%d status=%d\n", - err, op.status); - err = op.status; + err = xenbus_map_ring_valloc(xenvif_to_xenbus_device(vif), + rx_ring_ref, &addr); + if (err) goto err; - } - - vif->rx_shmem_ref = rx_ring_ref; - vif->rx_shmem_handle = op.handle; - vif->rx_req_cons_peek = 0; - rxs = (struct xen_netif_rx_sring *)vif->rx_comms_area->addr; + rxs = (struct xen_netif_rx_sring *)addr; BACK_RING_INIT(&vif->rx, rxs, PAGE_SIZE); + vif->rx_req_cons_peek = 0; + return 0; err: -- 1.7.2.5 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
David Vrabel
2011-Sep-29 15:53 UTC
[Xen-devel] [PATCH 4/4] xen: map foreign pages for shared rings by updating the PTEs directly
From: David Vrabel <david.vrabel@citrix.com> When mapping a foreign page with xenbus_map_ring_valloc() with the GNTTABOP_map_grant_ref hypercall, set the GNTMAP_contains_pte flag and pass a pointer to the PTE (in init_mm). After the page is mapped, the usual fault mechanism can be used to update additional MMs. This allows the vmalloc_sync_all() to be removed from alloc_vm_area(). Signed-off-by: David Vrabel <david.vrabel@citrix.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Jeremy Fitzhardinge <jeremy@goop.org> --- arch/x86/xen/grant-table.c | 2 +- drivers/xen/xenbus/xenbus_client.c | 11 ++++++++--- include/linux/vmalloc.h | 2 +- mm/vmalloc.c | 27 +++++++++++++-------------- 4 files changed, 23 insertions(+), 19 deletions(-) diff --git a/arch/x86/xen/grant-table.c b/arch/x86/xen/grant-table.c index 6bbfd7a..5a40d24 100644 --- a/arch/x86/xen/grant-table.c +++ b/arch/x86/xen/grant-table.c @@ -71,7 +71,7 @@ int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes, if (shared == NULL) { struct vm_struct *area - alloc_vm_area(PAGE_SIZE * max_nr_gframes); + alloc_vm_area(PAGE_SIZE * max_nr_gframes, NULL); BUG_ON(area == NULL); shared = area->addr; *__shared = shared; diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c index 229d3ad..52bc57f 100644 --- a/drivers/xen/xenbus/xenbus_client.c +++ b/drivers/xen/xenbus/xenbus_client.c @@ -34,6 +34,7 @@ #include <linux/types.h> #include <linux/vmalloc.h> #include <asm/xen/hypervisor.h> +#include <asm/xen/page.h> #include <xen/interface/xen.h> #include <xen/interface/event_channel.h> #include <xen/events.h> @@ -435,19 +436,20 @@ EXPORT_SYMBOL_GPL(xenbus_free_evtchn); int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr) { struct gnttab_map_grant_ref op = { - .flags = GNTMAP_host_map, + .flags = GNTMAP_host_map | GNTMAP_contains_pte, .ref = gnt_ref, .dom = dev->otherend_id, }; struct vm_struct *area; + pte_t *pte; *vaddr = NULL; - area = alloc_vm_area(PAGE_SIZE); + area = alloc_vm_area(PAGE_SIZE, &pte); if (!area) return -ENOMEM; - op.host_addr = (unsigned long)area->addr; + op.host_addr = arbitrary_virt_to_machine(pte).maddr; if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) BUG(); @@ -526,6 +528,7 @@ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr) struct gnttab_unmap_grant_ref op = { .host_addr = (unsigned long)vaddr, }; + unsigned int level; /* It''d be nice if linux/vmalloc.h provided a find_vm_area(void *addr) * method so that we don''t have to muck with vmalloc internals here. @@ -547,6 +550,8 @@ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr) } op.handle = (grant_handle_t)area->phys_addr; + op.host_addr = arbitrary_virt_to_machine( + lookup_address((unsigned long)vaddr, &level)).maddr; if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)) BUG(); diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index 9332e52..1a77252 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -118,7 +118,7 @@ unmap_kernel_range(unsigned long addr, unsigned long size) #endif /* Allocate/destroy a ''vmalloc'' VM area. */ -extern struct vm_struct *alloc_vm_area(size_t size); +extern struct vm_struct *alloc_vm_area(size_t size, pte_t **ptes); extern void free_vm_area(struct vm_struct *area); /* for /dev/kmem */ diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 5016f19..b5deec6 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -2105,23 +2105,30 @@ void __attribute__((weak)) vmalloc_sync_all(void) static int f(pte_t *pte, pgtable_t table, unsigned long addr, void *data) { - /* apply_to_page_range() does all the hard work. */ + pte_t ***p = data; + + if (p) { + *(*p) = pte; + (*p)++; + } return 0; } /** * alloc_vm_area - allocate a range of kernel address space * @size: size of the area + * @ptes: returns the PTEs for the address space * * Returns: NULL on failure, vm_struct on success * * This function reserves a range of kernel address space, and * allocates pagetables to map that range. No actual mappings - * are created. If the kernel address space is not shared - * between processes, it syncs the pagetable across all - * processes. + * are created. + * + * If @ptes is non-NULL, pointers to the PTEs (in init_mm) + * allocated for the VM area are returned. */ -struct vm_struct *alloc_vm_area(size_t size) +struct vm_struct *alloc_vm_area(size_t size, pte_t **ptes) { struct vm_struct *area; @@ -2135,19 +2142,11 @@ struct vm_struct *alloc_vm_area(size_t size) * of kernel virtual address space and mapped into init_mm. */ if (apply_to_page_range(&init_mm, (unsigned long)area->addr, - area->size, f, NULL)) { + size, f, ptes ? &ptes : NULL)) { free_vm_area(area); return NULL; } - /* - * If the allocated address space is passed to a hypercall - * before being used then we cannot rely on a page fault to - * trigger an update of the page tables. So sync all the page - * tables here. - */ - vmalloc_sync_all(); - return area; } EXPORT_SYMBOL_GPL(alloc_vm_area); -- 1.7.2.5 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Jan Beulich
2011-Sep-29 16:07 UTC
Re: [Xen-devel] [PATCH 0/4] xen: map foreign pages for shared rings by updating the PTEs directly
>>> On 29.09.11 at 17:53, David Vrabel <david.vrabel@citrix.com> wrote: > [Resend as requested by Konrad.] > > This series of patches allows the vmalloc_sync_all() to be removed > from alloc_vm_area() by getting the hypervisor to update the PTEs (in > init_mm) directly rather than having the hypervisor look in the > current page tables to find the PTEs. > > Once the hypervisor has updated the PTEs, the normal mechanism of > syncing the page tables after a fault works as expected.Did you actually test that, and namely the case where alloc_vm_area() would result in a new top level page directory entry to get populated? I cannot see how this new entry would propagate into other mm-s, and hence I cannot see how you can do away with calling vmalloc_sync_all() just by changing how leaf page table entries get populated. Jan> This mechanism doesn''t currently work on the ia64 port as that does > not support the GNTMAP_contains_pte flag. > > David > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xensource.com > http://lists.xensource.com/xen-devel_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
David Vrabel
2011-Sep-29 16:45 UTC
Re: [Xen-devel] [PATCH 0/4] xen: map foreign pages for shared rings by updating the PTEs directly
On 29/09/11 17:07, Jan Beulich wrote:>>>> On 29.09.11 at 17:53, David Vrabel <david.vrabel@citrix.com> wrote: >> [Resend as requested by Konrad.] >> >> This series of patches allows the vmalloc_sync_all() to be removed >> from alloc_vm_area() by getting the hypervisor to update the PTEs (in >> init_mm) directly rather than having the hypervisor look in the >> current page tables to find the PTEs. >> >> Once the hypervisor has updated the PTEs, the normal mechanism of >> syncing the page tables after a fault works as expected. > > Did you actually test that, and namely the case where alloc_vm_area() > would result in a new top level page directory entry to get populated? > > I cannot see how this new entry would propagate into other mm-s, and > hence I cannot see how you can do away with calling vmalloc_sync_all() > just by changing how leaf page table entries get populated.I don''t think this new behaviour of alloc_vm_area() is any different from how a regular vmalloc() works. vmalloc_fault() copies the page table entries from init_mm into the current MM (on 32-bit it calls vmalloc_sync_one() which makes it obviously correct I think). David>> This mechanism doesn''t currently work on the ia64 port as that does >> not support the GNTMAP_contains_pte flag. >> >> David_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Jan Beulich
2011-Sep-30 08:08 UTC
Re: [Xen-devel] [PATCH 0/4] xen: map foreign pages for shared rings by updating the PTEs directly
>>> On 29.09.11 at 18:45, David Vrabel <david.vrabel@citrix.com> wrote: > On 29/09/11 17:07, Jan Beulich wrote: >>>>> On 29.09.11 at 17:53, David Vrabel <david.vrabel@citrix.com> wrote: >>> [Resend as requested by Konrad.] >>> >>> This series of patches allows the vmalloc_sync_all() to be removed >>> from alloc_vm_area() by getting the hypervisor to update the PTEs (in >>> init_mm) directly rather than having the hypervisor look in the >>> current page tables to find the PTEs. >>> >>> Once the hypervisor has updated the PTEs, the normal mechanism of >>> syncing the page tables after a fault works as expected. >> >> Did you actually test that, and namely the case where alloc_vm_area() >> would result in a new top level page directory entry to get populated? >> >> I cannot see how this new entry would propagate into other mm-s, and >> hence I cannot see how you can do away with calling vmalloc_sync_all() >> just by changing how leaf page table entries get populated. > > I don''t think this new behaviour of alloc_vm_area() is any different > from how a regular vmalloc() works.Of course not. Callers of vmalloc() need to use vmalloc_sync_all() too before it is permitted to access the allocated space from an NMI handler or pass it into a hypercall.> vmalloc_fault() copies the page table entries from init_mm into the > current MM (on 32-bit it calls vmalloc_sync_one() which makes it > obviously correct I think).No, vmalloc_fault() copies pmd-s (32-bit) or pgd-s (64-bit), but never pte-s. Avoiding this to be done in a fault (precisely for the NMI and hypercall cases named above) is what vmalloc_sync_all() was introduced for (really, the hypercall aspect didn''t matter back then, and alloc_vm_area() didn''t exist outside of Xenolinux then either). So eliminating it from alloc_vm_area() just pushes the need to call it to all callers that may have the obtained space accessed in NMI context (none at present, as only Xen code appears to call this function) or want to pass it to a hypercall without running on init_mm. Just to repeat the essence of my first reply: Fiddling with how pte-s get populated can not possibly eliminate the need to call a function that populates top level page directory entries (pmd-s/pgd-s). Jan>>> This mechanism doesn''t currently work on the ia64 port as that does >>> not support the GNTMAP_contains_pte flag. >>> >>> David_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
David Vrabel
2011-Sep-30 10:14 UTC
Re: [Xen-devel] [PATCH 0/4] xen: map foreign pages for shared rings by updating the PTEs directly
On 30/09/11 09:08, Jan Beulich wrote:>>>> On 29.09.11 at 18:45, David Vrabel <david.vrabel@citrix.com> wrote: >> On 29/09/11 17:07, Jan Beulich wrote: >>>>>> On 29.09.11 at 17:53, David Vrabel <david.vrabel@citrix.com> wrote: >>>> [Resend as requested by Konrad.] >>>> >>>> This series of patches allows the vmalloc_sync_all() to be removed >>>> from alloc_vm_area() by getting the hypervisor to update the PTEs (in >>>> init_mm) directly rather than having the hypervisor look in the >>>> current page tables to find the PTEs. >>>> >>>> Once the hypervisor has updated the PTEs, the normal mechanism of >>>> syncing the page tables after a fault works as expected. >>> >>> Did you actually test that, and namely the case where alloc_vm_area() >>> would result in a new top level page directory entry to get populated? >>> >>> I cannot see how this new entry would propagate into other mm-s, and >>> hence I cannot see how you can do away with calling vmalloc_sync_all() >>> just by changing how leaf page table entries get populated. >> >> I don''t think this new behaviour of alloc_vm_area() is any different >> from how a regular vmalloc() works. > > Of course not. Callers of vmalloc() need to use vmalloc_sync_all() too > before it is permitted to access the allocated space from an NMI > handler or pass it into a hypercall.The virtual addresses of the mapped rings are not accessed in an NMI handler or a hypercall (before this patch set they were accessed in the GNTTABOP_map_grant_ref hypercall, but no longer). In the future, if something did want to pass the virtual address to a hypercall it wouldn''t need the vmalloc_sync() as it could disable preemption, touch the page (so current->active_mm is updated), do the hypercall, then disable preemption.>> vmalloc_fault() copies the page table entries from init_mm into the >> current MM (on 32-bit it calls vmalloc_sync_one() which makes it >> obviously correct I think). > > No, vmalloc_fault() copies pmd-s (32-bit) or pgd-s (64-bit), but never > pte-s. Avoiding this to be done in a fault (precisely for the NMI and > hypercall cases named above) is what vmalloc_sync_all() was > introduced for (really, the hypercall aspect didn''t matter back then, > and alloc_vm_area() didn''t exist outside of Xenolinux then either). > > So eliminating it from alloc_vm_area() just pushes the need to call it > to all callers that may have the obtained space accessed in NMI > context (none at present, as only Xen code appears to call this > function) or want to pass it to a hypercall without running on init_mm. > > Just to repeat the essence of my first reply: Fiddling with how pte-s > get populated can not possibly eliminate the need to call a function > that populates top level page directory entries (pmd-s/pgd-s). > > Jan > >>>> This mechanism doesn''t currently work on the ia64 port as that does >>>> not support the GNTMAP_contains_pte flag. >>>> >>>> David_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Ian Campbell
2011-Sep-30 10:18 UTC
Re: [Xen-devel] [PATCH 0/4] xen: map foreign pages for shared rings by updating the PTEs directly
On Fri, 2011-09-30 at 09:08 +0100, Jan Beulich wrote:> >>> On 29.09.11 at 18:45, David Vrabel <david.vrabel@citrix.com> wrote: > > On 29/09/11 17:07, Jan Beulich wrote: > >>>>> On 29.09.11 at 17:53, David Vrabel <david.vrabel@citrix.com> wrote: > >>> [Resend as requested by Konrad.] > >>> > >>> This series of patches allows the vmalloc_sync_all() to be removed > >>> from alloc_vm_area() by getting the hypervisor to update the PTEs (in > >>> init_mm) directly rather than having the hypervisor look in the > >>> current page tables to find the PTEs. > >>> > >>> Once the hypervisor has updated the PTEs, the normal mechanism of > >>> syncing the page tables after a fault works as expected. > >> > >> Did you actually test that, and namely the case where alloc_vm_area() > >> would result in a new top level page directory entry to get populated? > >> > >> I cannot see how this new entry would propagate into other mm-s, and > >> hence I cannot see how you can do away with calling vmalloc_sync_all() > >> just by changing how leaf page table entries get populated. > > > > I don''t think this new behaviour of alloc_vm_area() is any different > > from how a regular vmalloc() works. > > Of course not. Callers of vmalloc() need to use vmalloc_sync_all() too > before it is permitted to access the allocated space from an NMI > handler or pass it into a hypercall. > > > vmalloc_fault() copies the page table entries from init_mm into the > > current MM (on 32-bit it calls vmalloc_sync_one() which makes it > > obviously correct I think). > > No, vmalloc_fault() copies pmd-s (32-bit) or pgd-s (64-bit), but never > pte-s.Right, but David has also changed the hypercall so that it now takes the specific pte to update, instead of taking the virtual address and relying on the hypervisor''s linear map of the guests page tables to do the update. So the hypercall can now update the pte regardless of whether it is actually hooked into the current set of page tables or not. Then once the hypercall is complete and the kernel comes to actually use the address the normal vmalloc fault stuff will happen and fault in the pmd/pgd which refers to those ptes which have been updated. Ian.> Avoiding this to be done in a fault (precisely for the NMI and > hypercall cases named above) is what vmalloc_sync_all() was > introduced for (really, the hypercall aspect didn''t matter back then, > and alloc_vm_area() didn''t exist outside of Xenolinux then either). > > So eliminating it from alloc_vm_area() just pushes the need to call it > to all callers that may have the obtained space accessed in NMI > context (none at present, as only Xen code appears to call this > function) or want to pass it to a hypercall without running on init_mm. > > Just to repeat the essence of my first reply: Fiddling with how pte-s > get populated can not possibly eliminate the need to call a function > that populates top level page directory entries (pmd-s/pgd-s). > > Jan > > >>> This mechanism doesn''t currently work on the ia64 port as that does > >>> not support the GNTMAP_contains_pte flag. > >>> > >>> David > > > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xensource.com > http://lists.xensource.com/xen-devel_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Jan Beulich
2011-Sep-30 10:50 UTC
Re: [Xen-devel] [PATCH 0/4] xen: map foreign pages for shared rings by updating the PTEs directly
>>> On 30.09.11 at 12:14, David Vrabel <david.vrabel@citrix.com> wrote: > On 30/09/11 09:08, Jan Beulich wrote: >>>>> On 29.09.11 at 18:45, David Vrabel <david.vrabel@citrix.com> wrote: >>> On 29/09/11 17:07, Jan Beulich wrote: >>>>>>> On 29.09.11 at 17:53, David Vrabel <david.vrabel@citrix.com> wrote: >>>>> [Resend as requested by Konrad.] >>>>> >>>>> This series of patches allows the vmalloc_sync_all() to be removed >>>>> from alloc_vm_area() by getting the hypervisor to update the PTEs (in >>>>> init_mm) directly rather than having the hypervisor look in the >>>>> current page tables to find the PTEs. >>>>> >>>>> Once the hypervisor has updated the PTEs, the normal mechanism of >>>>> syncing the page tables after a fault works as expected. >>>> >>>> Did you actually test that, and namely the case where alloc_vm_area() >>>> would result in a new top level page directory entry to get populated? >>>> >>>> I cannot see how this new entry would propagate into other mm-s, and >>>> hence I cannot see how you can do away with calling vmalloc_sync_all() >>>> just by changing how leaf page table entries get populated. >>> >>> I don''t think this new behaviour of alloc_vm_area() is any different >>> from how a regular vmalloc() works. >> >> Of course not. Callers of vmalloc() need to use vmalloc_sync_all() too >> before it is permitted to access the allocated space from an NMI >> handler or pass it into a hypercall. > > The virtual addresses of the mapped rings are not accessed in an NMI > handler or a hypercall (before this patch set they were accessed in the > GNTTABOP_map_grant_ref hypercall, but no longer). > > In the future, if something did want to pass the virtual address to a > hypercall it wouldn''t need the vmalloc_sync() as it could disable > preemption, touch the page (so current->active_mm is updated), do the > hypercall, then disable preemption.And you verified that no other hypercall gets, perhaps indirectly, passed alloc_vm_area()ed memory? Jan _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Ian Campbell
2011-Sep-30 11:04 UTC
Re: [Xen-devel] [PATCH 0/4] xen: map foreign pages for shared rings by updating the PTEs directly
On Fri, 2011-09-30 at 11:50 +0100, Jan Beulich wrote:> >>> On 30.09.11 at 12:14, David Vrabel <david.vrabel@citrix.com> wrote: > > On 30/09/11 09:08, Jan Beulich wrote: > >>>>> On 29.09.11 at 18:45, David Vrabel <david.vrabel@citrix.com> wrote: > >>> On 29/09/11 17:07, Jan Beulich wrote: > >>>>>>> On 29.09.11 at 17:53, David Vrabel <david.vrabel@citrix.com> wrote: > >>>>> [Resend as requested by Konrad.] > >>>>> > >>>>> This series of patches allows the vmalloc_sync_all() to be removed > >>>>> from alloc_vm_area() by getting the hypervisor to update the PTEs (in > >>>>> init_mm) directly rather than having the hypervisor look in the > >>>>> current page tables to find the PTEs. > >>>>> > >>>>> Once the hypervisor has updated the PTEs, the normal mechanism of > >>>>> syncing the page tables after a fault works as expected. > >>>> > >>>> Did you actually test that, and namely the case where alloc_vm_area() > >>>> would result in a new top level page directory entry to get populated? > >>>> > >>>> I cannot see how this new entry would propagate into other mm-s, and > >>>> hence I cannot see how you can do away with calling vmalloc_sync_all() > >>>> just by changing how leaf page table entries get populated. > >>> > >>> I don''t think this new behaviour of alloc_vm_area() is any different > >>> from how a regular vmalloc() works. > >> > >> Of course not. Callers of vmalloc() need to use vmalloc_sync_all() too > >> before it is permitted to access the allocated space from an NMI > >> handler or pass it into a hypercall. > > > > The virtual addresses of the mapped rings are not accessed in an NMI > > handler or a hypercall (before this patch set they were accessed in the > > GNTTABOP_map_grant_ref hypercall, but no longer). > > > > In the future, if something did want to pass the virtual address to a > > hypercall it wouldn''t need the vmalloc_sync() as it could disable > > preemption, touch the page (so current->active_mm is updated), do the > > hypercall, then disable preemption. > > And you verified that no other hypercall gets, perhaps indirectly, > passed alloc_vm_area()ed memory?In the specific case of these functions, which map the rings, we believe this is the case. If there are other unrelated callsites then the failure to deal with this is an existing bug at that callsite, before or after this series (modulo the short term sticking plaster of putting the vmalloc_sync_all back, which was known not to be acceptable longterm when it went in -- hence this series). The only other use of alloc_vm_area is arch_gnttab_map_shared. IIRC the hypervisor does not use the linear map to get a guests grant table but those pages are owned by Xen and hence it has and uses its own mapping of them. Ian.> > Jan > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xensource.com > http://lists.xensource.com/xen-devel_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
David Vrabel
2011-Oct-20 10:45 UTC
[Xen-devel] [PATCH 0/4] xen: map foreign pages for shared rings by updating the PTEs directly
This series of patches allows the vmalloc_sync_all() to be removed from alloc_vm_area() by getting the hypervisor to update the PTEs (in init_mm) directly rather than having the hypervisor look in the current page tables to find the PTEs. Once the hypervisor has updated the PTEs, the normal mechanism of syncing the page tables after a fault works as expected. This mechanism doesn''t currently work on the ia64 port as that does not support the GNTMAP_contains_pte flag. Andrew, patch 4 (xen: map foreign pages for shared rings by updating the PTEs directly) depends on patch 1 so it''s probably best to go via Konrad''s Xen tree with your acked-by. David David Vrabel (4): xen: use generic functions instead of xen_{alloc,free}_vm_area() block: xen-blkback: use API provided by xenbus module to map rings net: xen-netback: use API provided by xenbus module to map rings xen: map foreign pages for shared rings by updating the PTEs directly arch/ia64/include/asm/xen/grant_table.h | 29 ----------- arch/ia64/xen/grant-table.c | 62 ------------------------ arch/x86/include/asm/xen/grant_table.h | 7 --- arch/x86/xen/grant-table.c | 2 +- drivers/block/xen-blkback/common.h | 5 +-- drivers/block/xen-blkback/xenbus.c | 54 +++------------------ drivers/net/xen-netback/common.h | 11 ++-- drivers/net/xen-netback/netback.c | 80 +++++++------------------------ drivers/xen/xenbus/xenbus_client.c | 15 ++++-- include/linux/vmalloc.h | 2 +- include/xen/grant_table.h | 1 - mm/vmalloc.c | 27 +++++----- 12 files changed, 55 insertions(+), 240 deletions(-) delete mode 100644 arch/ia64/include/asm/xen/grant_table.h delete mode 100644 arch/x86/include/asm/xen/grant_table.h -- 1.7.2.5 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
David Vrabel
2011-Oct-20 10:45 UTC
[Xen-devel] [PATCH 1/4] xen: use generic functions instead of xen_{alloc, free}_vm_area()
Replace calls to the Xen-specific xen_alloc_vm_area() and xen_free_vm_area() functions with the generic equivalent (alloc_vm_area() and free_vm_area()). On x86, these were identical already. Signed-off-by: David Vrabel <david.vrabel@citrix.com> --- arch/ia64/include/asm/xen/grant_table.h | 29 -------------- arch/ia64/xen/grant-table.c | 62 ------------------------------- arch/x86/include/asm/xen/grant_table.h | 7 --- arch/x86/xen/grant-table.c | 2 +- drivers/xen/xenbus/xenbus_client.c | 6 +- include/xen/grant_table.h | 1 - 6 files changed, 4 insertions(+), 103 deletions(-) delete mode 100644 arch/ia64/include/asm/xen/grant_table.h delete mode 100644 arch/x86/include/asm/xen/grant_table.h diff --git a/arch/ia64/include/asm/xen/grant_table.h b/arch/ia64/include/asm/xen/grant_table.h deleted file mode 100644 index 2b1fae0..0000000 --- a/arch/ia64/include/asm/xen/grant_table.h +++ /dev/null @@ -1,29 +0,0 @@ -/****************************************************************************** - * arch/ia64/include/asm/xen/grant_table.h - * - * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> - * VA Linux Systems Japan K.K. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef _ASM_IA64_XEN_GRANT_TABLE_H -#define _ASM_IA64_XEN_GRANT_TABLE_H - -struct vm_struct *xen_alloc_vm_area(unsigned long size); -void xen_free_vm_area(struct vm_struct *area); - -#endif /* _ASM_IA64_XEN_GRANT_TABLE_H */ diff --git a/arch/ia64/xen/grant-table.c b/arch/ia64/xen/grant-table.c index 48cca37..c182813 100644 --- a/arch/ia64/xen/grant-table.c +++ b/arch/ia64/xen/grant-table.c @@ -31,68 +31,6 @@ #include <asm/xen/hypervisor.h> -struct vm_struct *xen_alloc_vm_area(unsigned long size) -{ - int order; - unsigned long virt; - unsigned long nr_pages; - struct vm_struct *area; - - order = get_order(size); - virt = __get_free_pages(GFP_KERNEL, order); - if (virt == 0) - goto err0; - nr_pages = 1 << order; - scrub_pages(virt, nr_pages); - - area = kmalloc(sizeof(*area), GFP_KERNEL); - if (area == NULL) - goto err1; - - area->flags = VM_IOREMAP; - area->addr = (void *)virt; - area->size = size; - area->pages = NULL; - area->nr_pages = nr_pages; - area->phys_addr = 0; /* xenbus_map_ring_valloc uses this field! */ - - return area; - -err1: - free_pages(virt, order); -err0: - return NULL; -} -EXPORT_SYMBOL_GPL(xen_alloc_vm_area); - -void xen_free_vm_area(struct vm_struct *area) -{ - unsigned int order = get_order(area->size); - unsigned long i; - unsigned long phys_addr = __pa(area->addr); - - /* This area is used for foreign page mappping. - * So underlying machine page may not be assigned. */ - for (i = 0; i < (1 << order); i++) { - unsigned long ret; - unsigned long gpfn = (phys_addr >> PAGE_SHIFT) + i; - struct xen_memory_reservation reservation = { - .nr_extents = 1, - .address_bits = 0, - .extent_order = 0, - .domid = DOMID_SELF - }; - set_xen_guest_handle(reservation.extent_start, &gpfn); - ret = HYPERVISOR_memory_op(XENMEM_populate_physmap, - &reservation); - BUG_ON(ret != 1); - } - free_pages((unsigned long)area->addr, order); - kfree(area); -} -EXPORT_SYMBOL_GPL(xen_free_vm_area); - - /**************************************************************************** * grant table hack * cmd: GNTTABOP_xxx diff --git a/arch/x86/include/asm/xen/grant_table.h b/arch/x86/include/asm/xen/grant_table.h deleted file mode 100644 index fdbbb45..0000000 --- a/arch/x86/include/asm/xen/grant_table.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _ASM_X86_XEN_GRANT_TABLE_H -#define _ASM_X86_XEN_GRANT_TABLE_H - -#define xen_alloc_vm_area(size) alloc_vm_area(size) -#define xen_free_vm_area(area) free_vm_area(area) - -#endif /* _ASM_X86_XEN_GRANT_TABLE_H */ diff --git a/arch/x86/xen/grant-table.c b/arch/x86/xen/grant-table.c index 49ba9b5..6bbfd7a 100644 --- a/arch/x86/xen/grant-table.c +++ b/arch/x86/xen/grant-table.c @@ -71,7 +71,7 @@ int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes, if (shared == NULL) { struct vm_struct *area - xen_alloc_vm_area(PAGE_SIZE * max_nr_gframes); + alloc_vm_area(PAGE_SIZE * max_nr_gframes); BUG_ON(area == NULL); shared = area->addr; *__shared = shared; diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c index cdacf92..229d3ad 100644 --- a/drivers/xen/xenbus/xenbus_client.c +++ b/drivers/xen/xenbus/xenbus_client.c @@ -443,7 +443,7 @@ int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr) *vaddr = NULL; - area = xen_alloc_vm_area(PAGE_SIZE); + area = alloc_vm_area(PAGE_SIZE); if (!area) return -ENOMEM; @@ -453,7 +453,7 @@ int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr) BUG(); if (op.status != GNTST_okay) { - xen_free_vm_area(area); + free_vm_area(area); xenbus_dev_fatal(dev, op.status, "mapping in shared page %d from domain %d", gnt_ref, dev->otherend_id); @@ -552,7 +552,7 @@ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr) BUG(); if (op.status == GNTST_okay) - xen_free_vm_area(area); + free_vm_area(area); else xenbus_dev_error(dev, op.status, "unmapping page at handle %d error %d", diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h index b1fab6b..8a8bb76 100644 --- a/include/xen/grant_table.h +++ b/include/xen/grant_table.h @@ -43,7 +43,6 @@ #include <xen/interface/grant_table.h> #include <asm/xen/hypervisor.h> -#include <asm/xen/grant_table.h> #include <xen/features.h> -- 1.7.2.5 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
David Vrabel
2011-Oct-20 10:45 UTC
[Xen-devel] [PATCH 2/4] block: xen-blkback: use API provided by xenbus module to map rings
The xenbus module provides xenbus_map_ring_valloc() and xenbus_map_ring_vfree(). Use these to map the ring pages granted by the frontend. Signed-off-by: David Vrabel <david.vrabel@citrix.com> --- drivers/block/xen-blkback/common.h | 5 +-- drivers/block/xen-blkback/xenbus.c | 54 ++++------------------------------- 2 files changed, 8 insertions(+), 51 deletions(-) diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index 00c57c9..7ec0e88 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -139,7 +139,7 @@ struct xen_blkif { /* Comms information. */ enum blkif_protocol blk_protocol; union blkif_back_rings blk_rings; - struct vm_struct *blk_ring_area; + void *blk_ring; /* The VBD attached to this interface. */ struct xen_vbd vbd; /* Back pointer to the backend_info. */ @@ -163,9 +163,6 @@ struct xen_blkif { int st_wr_sect; wait_queue_head_t waiting_to_free; - - grant_handle_t shmem_handle; - grant_ref_t shmem_ref; }; diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 5fd2010..69233dd 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -120,38 +120,6 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid) return blkif; } -static int map_frontend_page(struct xen_blkif *blkif, unsigned long shared_page) -{ - struct gnttab_map_grant_ref op; - - gnttab_set_map_op(&op, (unsigned long)blkif->blk_ring_area->addr, - GNTMAP_host_map, shared_page, blkif->domid); - - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) - BUG(); - - if (op.status) { - DPRINTK("Grant table operation failure !\n"); - return op.status; - } - - blkif->shmem_ref = shared_page; - blkif->shmem_handle = op.handle; - - return 0; -} - -static void unmap_frontend_page(struct xen_blkif *blkif) -{ - struct gnttab_unmap_grant_ref op; - - gnttab_set_unmap_op(&op, (unsigned long)blkif->blk_ring_area->addr, - GNTMAP_host_map, blkif->shmem_handle); - - if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)) - BUG(); -} - static int xen_blkif_map(struct xen_blkif *blkif, unsigned long shared_page, unsigned int evtchn) { @@ -161,35 +129,29 @@ static int xen_blkif_map(struct xen_blkif *blkif, unsigned long shared_page, if (blkif->irq) return 0; - blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE); - if (!blkif->blk_ring_area) - return -ENOMEM; - - err = map_frontend_page(blkif, shared_page); - if (err) { - free_vm_area(blkif->blk_ring_area); + err = xenbus_map_ring_valloc(blkif->be->dev, shared_page, &blkif->blk_ring); + if (err < 0) return err; - } switch (blkif->blk_protocol) { case BLKIF_PROTOCOL_NATIVE: { struct blkif_sring *sring; - sring = (struct blkif_sring *)blkif->blk_ring_area->addr; + sring = (struct blkif_sring *)blkif->blk_ring; BACK_RING_INIT(&blkif->blk_rings.native, sring, PAGE_SIZE); break; } case BLKIF_PROTOCOL_X86_32: { struct blkif_x86_32_sring *sring_x86_32; - sring_x86_32 = (struct blkif_x86_32_sring *)blkif->blk_ring_area->addr; + sring_x86_32 = (struct blkif_x86_32_sring *)blkif->blk_ring; BACK_RING_INIT(&blkif->blk_rings.x86_32, sring_x86_32, PAGE_SIZE); break; } case BLKIF_PROTOCOL_X86_64: { struct blkif_x86_64_sring *sring_x86_64; - sring_x86_64 = (struct blkif_x86_64_sring *)blkif->blk_ring_area->addr; + sring_x86_64 = (struct blkif_x86_64_sring *)blkif->blk_ring; BACK_RING_INIT(&blkif->blk_rings.x86_64, sring_x86_64, PAGE_SIZE); break; } @@ -201,8 +163,7 @@ static int xen_blkif_map(struct xen_blkif *blkif, unsigned long shared_page, xen_blkif_be_int, 0, "blkif-backend", blkif); if (err < 0) { - unmap_frontend_page(blkif); - free_vm_area(blkif->blk_ring_area); + xenbus_unmap_ring_vfree(blkif->be->dev, blkif->blk_ring); blkif->blk_rings.common.sring = NULL; return err; } @@ -228,8 +189,7 @@ static void xen_blkif_disconnect(struct xen_blkif *blkif) } if (blkif->blk_rings.common.sring) { - unmap_frontend_page(blkif); - free_vm_area(blkif->blk_ring_area); + xenbus_unmap_ring_vfree(blkif->be->dev, blkif->blk_ring); blkif->blk_rings.common.sring = NULL; } } -- 1.7.2.5 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
David Vrabel
2011-Oct-20 10:45 UTC
[Xen-devel] [PATCH 3/4] net: xen-netback: use API provided by xenbus module to map rings
The xenbus module provides xenbus_map_ring_valloc() and xenbus_map_ring_vfree(). Use these to map the Tx and Rx ring pages granted by the frontend. Signed-off-by: David Vrabel <david.vrabel@citrix.com> Acked-by: Ian Campbell <ian.campbell@citrix.com> --- Dave, this is a standalone patch and can be applied independently of the rest of the series. drivers/net/xen-netback/common.h | 11 ++--- drivers/net/xen-netback/netback.c | 80 ++++++++----------------------------- 2 files changed, 22 insertions(+), 69 deletions(-) diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 161f207..94b79c3 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h @@ -58,10 +58,6 @@ struct xenvif { u8 fe_dev_addr[6]; /* Physical parameters of the comms window. */ - grant_handle_t tx_shmem_handle; - grant_ref_t tx_shmem_ref; - grant_handle_t rx_shmem_handle; - grant_ref_t rx_shmem_ref; unsigned int irq; /* List of frontends to notify after a batch of frames sent. */ @@ -70,8 +66,6 @@ struct xenvif { /* The shared rings and indexes. */ struct xen_netif_tx_back_ring tx; struct xen_netif_rx_back_ring rx; - struct vm_struct *tx_comms_area; - struct vm_struct *rx_comms_area; /* Frontend feature information. */ u8 can_sg:1; @@ -106,6 +100,11 @@ struct xenvif { wait_queue_head_t waiting_to_free; }; +static inline struct xenbus_device *xenvif_to_xenbus_device(struct xenvif *vif) +{ + return to_xenbus_device(vif->dev->dev.parent); +} + #define XEN_NETIF_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, PAGE_SIZE) #define XEN_NETIF_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, PAGE_SIZE) diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index fd00f25..3af2924 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -1577,88 +1577,42 @@ static int xen_netbk_kthread(void *data) void xen_netbk_unmap_frontend_rings(struct xenvif *vif) { - struct gnttab_unmap_grant_ref op; - - if (vif->tx.sring) { - gnttab_set_unmap_op(&op, (unsigned long)vif->tx_comms_area->addr, - GNTMAP_host_map, vif->tx_shmem_handle); - - if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)) - BUG(); - } - - if (vif->rx.sring) { - gnttab_set_unmap_op(&op, (unsigned long)vif->rx_comms_area->addr, - GNTMAP_host_map, vif->rx_shmem_handle); - - if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)) - BUG(); - } - if (vif->rx_comms_area) - free_vm_area(vif->rx_comms_area); - if (vif->tx_comms_area) - free_vm_area(vif->tx_comms_area); + if (vif->tx.sring) + xenbus_unmap_ring_vfree(xenvif_to_xenbus_device(vif), + vif->tx.sring); + if (vif->rx.sring) + xenbus_unmap_ring_vfree(xenvif_to_xenbus_device(vif), + vif->rx.sring); } int xen_netbk_map_frontend_rings(struct xenvif *vif, grant_ref_t tx_ring_ref, grant_ref_t rx_ring_ref) { - struct gnttab_map_grant_ref op; + void *addr; struct xen_netif_tx_sring *txs; struct xen_netif_rx_sring *rxs; int err = -ENOMEM; - vif->tx_comms_area = alloc_vm_area(PAGE_SIZE); - if (vif->tx_comms_area == NULL) + err = xenbus_map_ring_valloc(xenvif_to_xenbus_device(vif), + tx_ring_ref, &addr); + if (err) goto err; - vif->rx_comms_area = alloc_vm_area(PAGE_SIZE); - if (vif->rx_comms_area == NULL) - goto err; - - gnttab_set_map_op(&op, (unsigned long)vif->tx_comms_area->addr, - GNTMAP_host_map, tx_ring_ref, vif->domid); - - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) - BUG(); - - if (op.status) { - netdev_warn(vif->dev, - "failed to map tx ring. err=%d status=%d\n", - err, op.status); - err = op.status; - goto err; - } - - vif->tx_shmem_ref = tx_ring_ref; - vif->tx_shmem_handle = op.handle; - - txs = (struct xen_netif_tx_sring *)vif->tx_comms_area->addr; + txs = (struct xen_netif_tx_sring *)addr; BACK_RING_INIT(&vif->tx, txs, PAGE_SIZE); - gnttab_set_map_op(&op, (unsigned long)vif->rx_comms_area->addr, - GNTMAP_host_map, rx_ring_ref, vif->domid); - - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) - BUG(); - - if (op.status) { - netdev_warn(vif->dev, - "failed to map rx ring. err=%d status=%d\n", - err, op.status); - err = op.status; + err = xenbus_map_ring_valloc(xenvif_to_xenbus_device(vif), + rx_ring_ref, &addr); + if (err) goto err; - } - - vif->rx_shmem_ref = rx_ring_ref; - vif->rx_shmem_handle = op.handle; - vif->rx_req_cons_peek = 0; - rxs = (struct xen_netif_rx_sring *)vif->rx_comms_area->addr; + rxs = (struct xen_netif_rx_sring *)addr; BACK_RING_INIT(&vif->rx, rxs, PAGE_SIZE); + vif->rx_req_cons_peek = 0; + return 0; err: -- 1.7.2.5 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
David Vrabel
2011-Oct-20 10:45 UTC
[Xen-devel] [PATCH 4/4] xen: map foreign pages for shared rings by updating the PTEs directly
When mapping a foreign page with xenbus_map_ring_valloc() with the GNTTABOP_map_grant_ref hypercall, set the GNTMAP_contains_pte flag and pass a pointer to the PTE (in init_mm). After the page is mapped, the usual fault mechanism can be used to update additional MMs. This allows the vmalloc_sync_all() to be removed from alloc_vm_area(). Signed-off-by: David Vrabel <david.vrabel@citrix.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Jeremy Fitzhardinge <jeremy@goop.org> --- arch/x86/xen/grant-table.c | 2 +- drivers/xen/xenbus/xenbus_client.c | 11 ++++++++--- include/linux/vmalloc.h | 2 +- mm/vmalloc.c | 27 +++++++++++++-------------- 4 files changed, 23 insertions(+), 19 deletions(-) diff --git a/arch/x86/xen/grant-table.c b/arch/x86/xen/grant-table.c index 6bbfd7a..5a40d24 100644 --- a/arch/x86/xen/grant-table.c +++ b/arch/x86/xen/grant-table.c @@ -71,7 +71,7 @@ int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes, if (shared == NULL) { struct vm_struct *area - alloc_vm_area(PAGE_SIZE * max_nr_gframes); + alloc_vm_area(PAGE_SIZE * max_nr_gframes, NULL); BUG_ON(area == NULL); shared = area->addr; *__shared = shared; diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c index 229d3ad..52bc57f 100644 --- a/drivers/xen/xenbus/xenbus_client.c +++ b/drivers/xen/xenbus/xenbus_client.c @@ -34,6 +34,7 @@ #include <linux/types.h> #include <linux/vmalloc.h> #include <asm/xen/hypervisor.h> +#include <asm/xen/page.h> #include <xen/interface/xen.h> #include <xen/interface/event_channel.h> #include <xen/events.h> @@ -435,19 +436,20 @@ EXPORT_SYMBOL_GPL(xenbus_free_evtchn); int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr) { struct gnttab_map_grant_ref op = { - .flags = GNTMAP_host_map, + .flags = GNTMAP_host_map | GNTMAP_contains_pte, .ref = gnt_ref, .dom = dev->otherend_id, }; struct vm_struct *area; + pte_t *pte; *vaddr = NULL; - area = alloc_vm_area(PAGE_SIZE); + area = alloc_vm_area(PAGE_SIZE, &pte); if (!area) return -ENOMEM; - op.host_addr = (unsigned long)area->addr; + op.host_addr = arbitrary_virt_to_machine(pte).maddr; if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) BUG(); @@ -526,6 +528,7 @@ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr) struct gnttab_unmap_grant_ref op = { .host_addr = (unsigned long)vaddr, }; + unsigned int level; /* It''d be nice if linux/vmalloc.h provided a find_vm_area(void *addr) * method so that we don''t have to muck with vmalloc internals here. @@ -547,6 +550,8 @@ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr) } op.handle = (grant_handle_t)area->phys_addr; + op.host_addr = arbitrary_virt_to_machine( + lookup_address((unsigned long)vaddr, &level)).maddr; if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)) BUG(); diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index 9332e52..1a77252 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -118,7 +118,7 @@ unmap_kernel_range(unsigned long addr, unsigned long size) #endif /* Allocate/destroy a ''vmalloc'' VM area. */ -extern struct vm_struct *alloc_vm_area(size_t size); +extern struct vm_struct *alloc_vm_area(size_t size, pte_t **ptes); extern void free_vm_area(struct vm_struct *area); /* for /dev/kmem */ diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 5016f19..b5deec6 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -2105,23 +2105,30 @@ void __attribute__((weak)) vmalloc_sync_all(void) static int f(pte_t *pte, pgtable_t table, unsigned long addr, void *data) { - /* apply_to_page_range() does all the hard work. */ + pte_t ***p = data; + + if (p) { + *(*p) = pte; + (*p)++; + } return 0; } /** * alloc_vm_area - allocate a range of kernel address space * @size: size of the area + * @ptes: returns the PTEs for the address space * * Returns: NULL on failure, vm_struct on success * * This function reserves a range of kernel address space, and * allocates pagetables to map that range. No actual mappings - * are created. If the kernel address space is not shared - * between processes, it syncs the pagetable across all - * processes. + * are created. + * + * If @ptes is non-NULL, pointers to the PTEs (in init_mm) + * allocated for the VM area are returned. */ -struct vm_struct *alloc_vm_area(size_t size) +struct vm_struct *alloc_vm_area(size_t size, pte_t **ptes) { struct vm_struct *area; @@ -2135,19 +2142,11 @@ struct vm_struct *alloc_vm_area(size_t size) * of kernel virtual address space and mapped into init_mm. */ if (apply_to_page_range(&init_mm, (unsigned long)area->addr, - area->size, f, NULL)) { + size, f, ptes ? &ptes : NULL)) { free_vm_area(area); return NULL; } - /* - * If the allocated address space is passed to a hypercall - * before being used then we cannot rely on a page fault to - * trigger an update of the page tables. So sync all the page - * tables here. - */ - vmalloc_sync_all(); - return area; } EXPORT_SYMBOL_GPL(alloc_vm_area); -- 1.7.2.5 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Konrad Rzeszutek Wilk
2011-Oct-20 21:00 UTC
[Xen-devel] Re: [PATCH 3/4] net: xen-netback: use API provided by xenbus module to map rings
On Thu, Oct 20, 2011 at 11:45:18AM +0100, David Vrabel wrote:> The xenbus module provides xenbus_map_ring_valloc() and > xenbus_map_ring_vfree(). Use these to map the Tx and Rx ring pages > granted by the frontend. > > Signed-off-by: David Vrabel <david.vrabel@citrix.com> > Acked-by: Ian Campbell <ian.campbell@citrix.com>Acked-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>> Dave, this is a standalone patch and can be applied independently of > the rest of the series... or Dave, if you would like I can carry these patches.> > drivers/net/xen-netback/common.h | 11 ++--- > drivers/net/xen-netback/netback.c | 80 ++++++++----------------------------- > 2 files changed, 22 insertions(+), 69 deletions(-) > > diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h > index 161f207..94b79c3 100644 > --- a/drivers/net/xen-netback/common.h > +++ b/drivers/net/xen-netback/common.h > @@ -58,10 +58,6 @@ struct xenvif { > u8 fe_dev_addr[6]; > > /* Physical parameters of the comms window. */ > - grant_handle_t tx_shmem_handle; > - grant_ref_t tx_shmem_ref; > - grant_handle_t rx_shmem_handle; > - grant_ref_t rx_shmem_ref; > unsigned int irq; > > /* List of frontends to notify after a batch of frames sent. */ > @@ -70,8 +66,6 @@ struct xenvif { > /* The shared rings and indexes. */ > struct xen_netif_tx_back_ring tx; > struct xen_netif_rx_back_ring rx; > - struct vm_struct *tx_comms_area; > - struct vm_struct *rx_comms_area; > > /* Frontend feature information. */ > u8 can_sg:1; > @@ -106,6 +100,11 @@ struct xenvif { > wait_queue_head_t waiting_to_free; > }; > > +static inline struct xenbus_device *xenvif_to_xenbus_device(struct xenvif *vif) > +{ > + return to_xenbus_device(vif->dev->dev.parent); > +} > + > #define XEN_NETIF_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, PAGE_SIZE) > #define XEN_NETIF_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, PAGE_SIZE) > > diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c > index fd00f25..3af2924 100644 > --- a/drivers/net/xen-netback/netback.c > +++ b/drivers/net/xen-netback/netback.c > @@ -1577,88 +1577,42 @@ static int xen_netbk_kthread(void *data) > > void xen_netbk_unmap_frontend_rings(struct xenvif *vif) > { > - struct gnttab_unmap_grant_ref op; > - > - if (vif->tx.sring) { > - gnttab_set_unmap_op(&op, (unsigned long)vif->tx_comms_area->addr, > - GNTMAP_host_map, vif->tx_shmem_handle); > - > - if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)) > - BUG(); > - } > - > - if (vif->rx.sring) { > - gnttab_set_unmap_op(&op, (unsigned long)vif->rx_comms_area->addr, > - GNTMAP_host_map, vif->rx_shmem_handle); > - > - if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)) > - BUG(); > - } > - if (vif->rx_comms_area) > - free_vm_area(vif->rx_comms_area); > - if (vif->tx_comms_area) > - free_vm_area(vif->tx_comms_area); > + if (vif->tx.sring) > + xenbus_unmap_ring_vfree(xenvif_to_xenbus_device(vif), > + vif->tx.sring); > + if (vif->rx.sring) > + xenbus_unmap_ring_vfree(xenvif_to_xenbus_device(vif), > + vif->rx.sring); > } > > int xen_netbk_map_frontend_rings(struct xenvif *vif, > grant_ref_t tx_ring_ref, > grant_ref_t rx_ring_ref) > { > - struct gnttab_map_grant_ref op; > + void *addr; > struct xen_netif_tx_sring *txs; > struct xen_netif_rx_sring *rxs; > > int err = -ENOMEM; > > - vif->tx_comms_area = alloc_vm_area(PAGE_SIZE); > - if (vif->tx_comms_area == NULL) > + err = xenbus_map_ring_valloc(xenvif_to_xenbus_device(vif), > + tx_ring_ref, &addr); > + if (err) > goto err; > > - vif->rx_comms_area = alloc_vm_area(PAGE_SIZE); > - if (vif->rx_comms_area == NULL) > - goto err; > - > - gnttab_set_map_op(&op, (unsigned long)vif->tx_comms_area->addr, > - GNTMAP_host_map, tx_ring_ref, vif->domid); > - > - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) > - BUG(); > - > - if (op.status) { > - netdev_warn(vif->dev, > - "failed to map tx ring. err=%d status=%d\n", > - err, op.status); > - err = op.status; > - goto err; > - } > - > - vif->tx_shmem_ref = tx_ring_ref; > - vif->tx_shmem_handle = op.handle; > - > - txs = (struct xen_netif_tx_sring *)vif->tx_comms_area->addr; > + txs = (struct xen_netif_tx_sring *)addr; > BACK_RING_INIT(&vif->tx, txs, PAGE_SIZE); > > - gnttab_set_map_op(&op, (unsigned long)vif->rx_comms_area->addr, > - GNTMAP_host_map, rx_ring_ref, vif->domid); > - > - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) > - BUG(); > - > - if (op.status) { > - netdev_warn(vif->dev, > - "failed to map rx ring. err=%d status=%d\n", > - err, op.status); > - err = op.status; > + err = xenbus_map_ring_valloc(xenvif_to_xenbus_device(vif), > + rx_ring_ref, &addr); > + if (err) > goto err; > - } > - > - vif->rx_shmem_ref = rx_ring_ref; > - vif->rx_shmem_handle = op.handle; > - vif->rx_req_cons_peek = 0; > > - rxs = (struct xen_netif_rx_sring *)vif->rx_comms_area->addr; > + rxs = (struct xen_netif_rx_sring *)addr; > BACK_RING_INIT(&vif->rx, rxs, PAGE_SIZE); > > + vif->rx_req_cons_peek = 0; > + > return 0; > > err: > -- > 1.7.2.5 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > Please read the FAQ at http://www.tux.org/lkml/_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Konrad Rzeszutek Wilk
2011-Oct-20 23:44 UTC
[Xen-devel] Re: [PATCH 0/4] xen: map foreign pages for shared rings by updating the PTEs directly
On Thu, Oct 20, 2011 at 11:45:15AM +0100, David Vrabel wrote:> This series of patches allows the vmalloc_sync_all() to be removed > from alloc_vm_area() by getting the hypervisor to update the PTEs (in > init_mm) directly rather than having the hypervisor look in the > current page tables to find the PTEs. > > Once the hypervisor has updated the PTEs, the normal mechanism of > syncing the page tables after a fault works as expected. > > This mechanism doesn''t currently work on the ia64 port as that does > not support the GNTMAP_contains_pte flag. > > Andrew, patch 4 (xen: map foreign pages for shared rings by updating > the PTEs directly) depends on patch 1 so it''s probably best to go via > Konrad''s Xen tree with your acked-by.Or I can Ack patch 1 and Andrew can pick both of them. Either way - but let mention the Ack on patch #1> > David > > David Vrabel (4): > xen: use generic functions instead of xen_{alloc,free}_vm_area() > block: xen-blkback: use API provided by xenbus module to map rings > net: xen-netback: use API provided by xenbus module to map rings > xen: map foreign pages for shared rings by updating the PTEs directly > > arch/ia64/include/asm/xen/grant_table.h | 29 ----------- > arch/ia64/xen/grant-table.c | 62 ------------------------ > arch/x86/include/asm/xen/grant_table.h | 7 --- > arch/x86/xen/grant-table.c | 2 +- > drivers/block/xen-blkback/common.h | 5 +-- > drivers/block/xen-blkback/xenbus.c | 54 +++------------------ > drivers/net/xen-netback/common.h | 11 ++-- > drivers/net/xen-netback/netback.c | 80 +++++++------------------------ > drivers/xen/xenbus/xenbus_client.c | 15 ++++-- > include/linux/vmalloc.h | 2 +- > include/xen/grant_table.h | 1 - > mm/vmalloc.c | 27 +++++----- > 12 files changed, 55 insertions(+), 240 deletions(-) > delete mode 100644 arch/ia64/include/asm/xen/grant_table.h > delete mode 100644 arch/x86/include/asm/xen/grant_table.h > > -- > 1.7.2.5_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Konrad Rzeszutek Wilk
2011-Oct-20 23:45 UTC
[Xen-devel] Re: [PATCH 1/4] xen: use generic functions instead of xen_{alloc,free}_vm_area()
On Thu, Oct 20, 2011 at 11:45:16AM +0100, David Vrabel wrote:> Replace calls to the Xen-specific xen_alloc_vm_area() and > xen_free_vm_area() functions with the generic equivalent > (alloc_vm_area() and free_vm_area()). > > On x86, these were identical already. > > Signed-off-by: David Vrabel <david.vrabel@citrix.com>Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>> --- > arch/ia64/include/asm/xen/grant_table.h | 29 -------------- > arch/ia64/xen/grant-table.c | 62 ------------------------------- > arch/x86/include/asm/xen/grant_table.h | 7 --- > arch/x86/xen/grant-table.c | 2 +- > drivers/xen/xenbus/xenbus_client.c | 6 +- > include/xen/grant_table.h | 1 - > 6 files changed, 4 insertions(+), 103 deletions(-) > delete mode 100644 arch/ia64/include/asm/xen/grant_table.h > delete mode 100644 arch/x86/include/asm/xen/grant_table.h > > diff --git a/arch/ia64/include/asm/xen/grant_table.h b/arch/ia64/include/asm/xen/grant_table.h > deleted file mode 100644 > index 2b1fae0..0000000 > --- a/arch/ia64/include/asm/xen/grant_table.h > +++ /dev/null > @@ -1,29 +0,0 @@ > -/****************************************************************************** > - * arch/ia64/include/asm/xen/grant_table.h > - * > - * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> > - * VA Linux Systems Japan K.K. > - * > - * This program is free software; you can redistribute it and/or modify > - * it under the terms of the GNU General Public License as published by > - * the Free Software Foundation; either version 2 of the License, or > - * (at your option) any later version. > - * > - * This program is distributed in the hope that it will be useful, > - * but WITHOUT ANY WARRANTY; without even the implied warranty of > - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > - * GNU General Public License for more details. > - * > - * You should have received a copy of the GNU General Public License > - * along with this program; if not, write to the Free Software > - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > - * > - */ > - > -#ifndef _ASM_IA64_XEN_GRANT_TABLE_H > -#define _ASM_IA64_XEN_GRANT_TABLE_H > - > -struct vm_struct *xen_alloc_vm_area(unsigned long size); > -void xen_free_vm_area(struct vm_struct *area); > - > -#endif /* _ASM_IA64_XEN_GRANT_TABLE_H */ > diff --git a/arch/ia64/xen/grant-table.c b/arch/ia64/xen/grant-table.c > index 48cca37..c182813 100644 > --- a/arch/ia64/xen/grant-table.c > +++ b/arch/ia64/xen/grant-table.c > @@ -31,68 +31,6 @@ > > #include <asm/xen/hypervisor.h> > > -struct vm_struct *xen_alloc_vm_area(unsigned long size) > -{ > - int order; > - unsigned long virt; > - unsigned long nr_pages; > - struct vm_struct *area; > - > - order = get_order(size); > - virt = __get_free_pages(GFP_KERNEL, order); > - if (virt == 0) > - goto err0; > - nr_pages = 1 << order; > - scrub_pages(virt, nr_pages); > - > - area = kmalloc(sizeof(*area), GFP_KERNEL); > - if (area == NULL) > - goto err1; > - > - area->flags = VM_IOREMAP; > - area->addr = (void *)virt; > - area->size = size; > - area->pages = NULL; > - area->nr_pages = nr_pages; > - area->phys_addr = 0; /* xenbus_map_ring_valloc uses this field! */ > - > - return area; > - > -err1: > - free_pages(virt, order); > -err0: > - return NULL; > -} > -EXPORT_SYMBOL_GPL(xen_alloc_vm_area); > - > -void xen_free_vm_area(struct vm_struct *area) > -{ > - unsigned int order = get_order(area->size); > - unsigned long i; > - unsigned long phys_addr = __pa(area->addr); > - > - /* This area is used for foreign page mappping. > - * So underlying machine page may not be assigned. */ > - for (i = 0; i < (1 << order); i++) { > - unsigned long ret; > - unsigned long gpfn = (phys_addr >> PAGE_SHIFT) + i; > - struct xen_memory_reservation reservation = { > - .nr_extents = 1, > - .address_bits = 0, > - .extent_order = 0, > - .domid = DOMID_SELF > - }; > - set_xen_guest_handle(reservation.extent_start, &gpfn); > - ret = HYPERVISOR_memory_op(XENMEM_populate_physmap, > - &reservation); > - BUG_ON(ret != 1); > - } > - free_pages((unsigned long)area->addr, order); > - kfree(area); > -} > -EXPORT_SYMBOL_GPL(xen_free_vm_area); > - > - > /**************************************************************************** > * grant table hack > * cmd: GNTTABOP_xxx > diff --git a/arch/x86/include/asm/xen/grant_table.h b/arch/x86/include/asm/xen/grant_table.h > deleted file mode 100644 > index fdbbb45..0000000 > --- a/arch/x86/include/asm/xen/grant_table.h > +++ /dev/null > @@ -1,7 +0,0 @@ > -#ifndef _ASM_X86_XEN_GRANT_TABLE_H > -#define _ASM_X86_XEN_GRANT_TABLE_H > - > -#define xen_alloc_vm_area(size) alloc_vm_area(size) > -#define xen_free_vm_area(area) free_vm_area(area) > - > -#endif /* _ASM_X86_XEN_GRANT_TABLE_H */ > diff --git a/arch/x86/xen/grant-table.c b/arch/x86/xen/grant-table.c > index 49ba9b5..6bbfd7a 100644 > --- a/arch/x86/xen/grant-table.c > +++ b/arch/x86/xen/grant-table.c > @@ -71,7 +71,7 @@ int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes, > > if (shared == NULL) { > struct vm_struct *area > - xen_alloc_vm_area(PAGE_SIZE * max_nr_gframes); > + alloc_vm_area(PAGE_SIZE * max_nr_gframes); > BUG_ON(area == NULL); > shared = area->addr; > *__shared = shared; > diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c > index cdacf92..229d3ad 100644 > --- a/drivers/xen/xenbus/xenbus_client.c > +++ b/drivers/xen/xenbus/xenbus_client.c > @@ -443,7 +443,7 @@ int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr) > > *vaddr = NULL; > > - area = xen_alloc_vm_area(PAGE_SIZE); > + area = alloc_vm_area(PAGE_SIZE); > if (!area) > return -ENOMEM; > > @@ -453,7 +453,7 @@ int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr) > BUG(); > > if (op.status != GNTST_okay) { > - xen_free_vm_area(area); > + free_vm_area(area); > xenbus_dev_fatal(dev, op.status, > "mapping in shared page %d from domain %d", > gnt_ref, dev->otherend_id); > @@ -552,7 +552,7 @@ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr) > BUG(); > > if (op.status == GNTST_okay) > - xen_free_vm_area(area); > + free_vm_area(area); > else > xenbus_dev_error(dev, op.status, > "unmapping page at handle %d error %d", > diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h > index b1fab6b..8a8bb76 100644 > --- a/include/xen/grant_table.h > +++ b/include/xen/grant_table.h > @@ -43,7 +43,6 @@ > #include <xen/interface/grant_table.h> > > #include <asm/xen/hypervisor.h> > -#include <asm/xen/grant_table.h> > > #include <xen/features.h> > > -- > 1.7.2.5_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Konrad Rzeszutek Wilk
2011-Oct-26 13:47 UTC
Re: [Xen-devel] [PATCH 2/4] block: xen-blkback: use API provided by xenbus module to map rings
On Thu, Oct 20, 2011 at 11:45:17AM +0100, David Vrabel wrote:> The xenbus module provides xenbus_map_ring_valloc() and > xenbus_map_ring_vfree(). Use these to map the ring pages granted by > the frontend.Jens, This patch paves the way for two other patches that are in the akpm''s MMU area of expertise. In other words, the last patch in this series (which should go through akpm''s tree or mine with his Ack) depends on this one. I can split this patchset in three different pieces - one for you, one for david miller, and one for akpm. But I was hoping to have it as one nice GIT PULL for Linus - hence I am wondering if it is OK if I get your Ack and do it through my tree? Thanks!> > Signed-off-by: David Vrabel <david.vrabel@citrix.com> > --- > drivers/block/xen-blkback/common.h | 5 +-- > drivers/block/xen-blkback/xenbus.c | 54 ++++------------------------------- > 2 files changed, 8 insertions(+), 51 deletions(-) > > diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h > index 00c57c9..7ec0e88 100644 > --- a/drivers/block/xen-blkback/common.h > +++ b/drivers/block/xen-blkback/common.h > @@ -139,7 +139,7 @@ struct xen_blkif { > /* Comms information. */ > enum blkif_protocol blk_protocol; > union blkif_back_rings blk_rings; > - struct vm_struct *blk_ring_area; > + void *blk_ring; > /* The VBD attached to this interface. */ > struct xen_vbd vbd; > /* Back pointer to the backend_info. */ > @@ -163,9 +163,6 @@ struct xen_blkif { > int st_wr_sect; > > wait_queue_head_t waiting_to_free; > - > - grant_handle_t shmem_handle; > - grant_ref_t shmem_ref; > }; > > > diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c > index 5fd2010..69233dd 100644 > --- a/drivers/block/xen-blkback/xenbus.c > +++ b/drivers/block/xen-blkback/xenbus.c > @@ -120,38 +120,6 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid) > return blkif; > } > > -static int map_frontend_page(struct xen_blkif *blkif, unsigned long shared_page) > -{ > - struct gnttab_map_grant_ref op; > - > - gnttab_set_map_op(&op, (unsigned long)blkif->blk_ring_area->addr, > - GNTMAP_host_map, shared_page, blkif->domid); > - > - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) > - BUG(); > - > - if (op.status) { > - DPRINTK("Grant table operation failure !\n"); > - return op.status; > - } > - > - blkif->shmem_ref = shared_page; > - blkif->shmem_handle = op.handle; > - > - return 0; > -} > - > -static void unmap_frontend_page(struct xen_blkif *blkif) > -{ > - struct gnttab_unmap_grant_ref op; > - > - gnttab_set_unmap_op(&op, (unsigned long)blkif->blk_ring_area->addr, > - GNTMAP_host_map, blkif->shmem_handle); > - > - if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)) > - BUG(); > -} > - > static int xen_blkif_map(struct xen_blkif *blkif, unsigned long shared_page, > unsigned int evtchn) > { > @@ -161,35 +129,29 @@ static int xen_blkif_map(struct xen_blkif *blkif, unsigned long shared_page, > if (blkif->irq) > return 0; > > - blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE); > - if (!blkif->blk_ring_area) > - return -ENOMEM; > - > - err = map_frontend_page(blkif, shared_page); > - if (err) { > - free_vm_area(blkif->blk_ring_area); > + err = xenbus_map_ring_valloc(blkif->be->dev, shared_page, &blkif->blk_ring); > + if (err < 0) > return err; > - } > > switch (blkif->blk_protocol) { > case BLKIF_PROTOCOL_NATIVE: > { > struct blkif_sring *sring; > - sring = (struct blkif_sring *)blkif->blk_ring_area->addr; > + sring = (struct blkif_sring *)blkif->blk_ring; > BACK_RING_INIT(&blkif->blk_rings.native, sring, PAGE_SIZE); > break; > } > case BLKIF_PROTOCOL_X86_32: > { > struct blkif_x86_32_sring *sring_x86_32; > - sring_x86_32 = (struct blkif_x86_32_sring *)blkif->blk_ring_area->addr; > + sring_x86_32 = (struct blkif_x86_32_sring *)blkif->blk_ring; > BACK_RING_INIT(&blkif->blk_rings.x86_32, sring_x86_32, PAGE_SIZE); > break; > } > case BLKIF_PROTOCOL_X86_64: > { > struct blkif_x86_64_sring *sring_x86_64; > - sring_x86_64 = (struct blkif_x86_64_sring *)blkif->blk_ring_area->addr; > + sring_x86_64 = (struct blkif_x86_64_sring *)blkif->blk_ring; > BACK_RING_INIT(&blkif->blk_rings.x86_64, sring_x86_64, PAGE_SIZE); > break; > } > @@ -201,8 +163,7 @@ static int xen_blkif_map(struct xen_blkif *blkif, unsigned long shared_page, > xen_blkif_be_int, 0, > "blkif-backend", blkif); > if (err < 0) { > - unmap_frontend_page(blkif); > - free_vm_area(blkif->blk_ring_area); > + xenbus_unmap_ring_vfree(blkif->be->dev, blkif->blk_ring); > blkif->blk_rings.common.sring = NULL; > return err; > } > @@ -228,8 +189,7 @@ static void xen_blkif_disconnect(struct xen_blkif *blkif) > } > > if (blkif->blk_rings.common.sring) { > - unmap_frontend_page(blkif); > - free_vm_area(blkif->blk_ring_area); > + xenbus_unmap_ring_vfree(blkif->be->dev, blkif->blk_ring); > blkif->blk_rings.common.sring = NULL; > } > } > -- > 1.7.2.5 > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xensource.com > http://lists.xensource.com/xen-devel_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Jens Axboe
2011-Oct-26 13:55 UTC
Re: [Xen-devel] [PATCH 2/4] block: xen-blkback: use API provided by xenbus module to map rings
On 2011-10-26 15:47, Konrad Rzeszutek Wilk wrote:> On Thu, Oct 20, 2011 at 11:45:17AM +0100, David Vrabel wrote: >> The xenbus module provides xenbus_map_ring_valloc() and >> xenbus_map_ring_vfree(). Use these to map the ring pages granted by >> the frontend. > > Jens, > > This patch paves the way for two other patches that are in the akpm''s > MMU area of expertise. In other words, the last patch in this series > (which should go through akpm''s tree or mine with his Ack) depends on > this one. > > I can split this patchset in three different pieces - one for you, one > for david miller, and one for akpm. But I was hoping to have it as one > nice GIT PULL for Linus - hence I am wondering if it is OK if I get > your Ack and do it through my tree?Sure, that''d be fine. -- Jens Axboe _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel