[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [XenPPC] [linux-ppc-2.6] [XEN] The VIO rewrite
# HG changeset patch # User Jimi Xenidis <jimix@xxxxxxxxxxxxxx> # Node ID 2a9c6a23cd1292e9ed361e33d640ce84a6fbdb53 # Parent f4d382795e57b926cd82256bcb3a74c539731796 [XEN] The VIO rewrite Once you figure it all out, its time to do a rewrite, lots of code I thougth I needed is now removed and less PPC specific code now exists. This patch uses the MEMORY_HOTPLUG system to add a region to the Kernel Linear Mapping that will be used exclusively to map in Granted/Foreign pages. This creates "struct page" objects in Linux which are necessary to perform VIO operations. When one of these pages are grant_mapped the pfn2mfn() translation in Xen is updated to reflect the association and the subsequent H_ENTER() from the domain will contain the correct mapping. Signed-off-by: Jimi Xenidis <jimix@xxxxxxxxxxxxxx> --- arch/powerpc/platforms/xen/balloon.c | 20 +-- arch/powerpc/platforms/xen/gnttab.c | 186 +++++++++++++++++++++++-------- arch/powerpc/platforms/xen/setup.h | 4 arch/powerpc/platforms/xen/util.c | 18 +-- drivers/xen/blkback/blkback.c | 18 --- drivers/xen/blkback/interface.c | 1 drivers/xen/netback/interface.c | 3 drivers/xen/netback/netback.c | 45 ------- drivers/xen/netfront/netfront.c | 7 + drivers/xen/tpmback/interface.c | 1 include/asm-powerpc/xen/asm/hypervisor.h | 2 include/xen/driver_util.h | 5 include/xen/gnttab.h | 4 13 files changed, 173 insertions(+), 141 deletions(-) diff -r f4d382795e57 -r 2a9c6a23cd12 arch/powerpc/platforms/xen/balloon.c --- a/arch/powerpc/platforms/xen/balloon.c Wed Oct 25 17:22:54 2006 -0400 +++ b/arch/powerpc/platforms/xen/balloon.c Fri Nov 03 16:50:22 2006 -0500 @@ -1,6 +1,7 @@ #include <linux/module.h> #include <linux/mm.h> #include <asm/hypervisor.h> +#include "setup.h" /* * FIXME: Port balloon driver, if ever @@ -9,18 +10,23 @@ struct page **alloc_empty_pages_and_page struct page **alloc_empty_pages_and_pagevec(int nr_pages) { struct page *page, **pagevec; - void *vaddr; int i; + int scrub = 0; pagevec = kmalloc(sizeof(*pagevec) * nr_pages, GFP_KERNEL); if (pagevec == NULL) return NULL; for (i = 0; i < nr_pages; i++) { - page = alloc_page(GFP_KERNEL); + page = alloc_grant_page(); pagevec[i] = page; - vaddr = page_address(page); - scrub_pages(vaddr, 1); + + if (scrub) { + void *vaddr; + + vaddr = page_address(page); + scrub_pages(vaddr, 1); + } } return pagevec; @@ -28,17 +34,13 @@ struct page **alloc_empty_pages_and_page void free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages) { - int arch_is_foreign_page(struct page *page); - struct page *page; int i; if (pagevec == NULL) return; for (i = 0; i < nr_pages; i++) { - page = pagevec[i]; - if (!arch_is_foreign_page(page)) - __free_page(page); + free_grant_page(pagevec[i]); } kfree(pagevec); diff -r f4d382795e57 -r 2a9c6a23cd12 arch/powerpc/platforms/xen/gnttab.c --- a/arch/powerpc/platforms/xen/gnttab.c Wed Oct 25 17:22:54 2006 -0400 +++ b/arch/powerpc/platforms/xen/gnttab.c Fri Nov 03 16:50:22 2006 -0500 @@ -2,6 +2,7 @@ #include <linux/config.h> #include <linux/vmalloc.h> #include <linux/memory_hotplug.h> +#include <linux/mempool.h> #include <xen/gnttab.h> #include <asm/hypervisor.h> #include <xen/interface/grant_table.h> @@ -22,8 +23,37 @@ #define DBG(fmt...) #endif +struct address_space xen_foreign_dummy_mapping; + static ulong foreign_map_base; static ulong foreign_map_end; + + +/* hijack _mapcount */ +static inline int gnt_mapcount(struct page *page) +{ + return atomic_read(&(page)->_mapcount) + 1; +} + +static inline int gnt_map(struct page *page) +{ + /* return true is transition from -1 to 0 */ + return atomic_inc_and_test(&page->_mapcount); +} + +static inline int gnt_unmap(struct page *page) +{ + int val; + + val = atomic_dec_return(&page->_mapcount); + if (val < -1) { + atomic_inc(&page->_mapcount); + printk(KERN_EMERG "%s: %d\n", __func__, val); + } + + return (val == -1); +} + static long map_to_linear(ulong paddr) { @@ -136,21 +166,20 @@ static void gnttab_pre_unmap_grant_ref( int i; ulong ea; unsigned long dummy1, dummy2; + ulong flags; + + /* paranoia */ + local_irq_save(flags); for (i = 0 ; i < count; i++) { struct page *page; - ea = unmap[i].host_addr; + ea = (ulong)__va(unmap[i].host_addr); page = virt_to_page(ea); - - /* Unfortunately, there is no put_page_testone() like - * put_page_testzero(). The Linear Map starts all - * pages with a count of 1, so there may be SMP issues - * here. */ - - put_page(page); - if (page_count(page) > 1) { - DBG("%s: skip: 0x%lx\n", __func__, ea); + + if (!gnt_unmap(page)) { + DBG("%s[0x%x]: skip: 0x%lx, mapcount 0x%x\n", + __func__, i, ea, gnt_mapcount(page)); continue; } slot = find_map_slot(ea); @@ -160,10 +189,11 @@ static void gnttab_pre_unmap_grant_ref( continue; } - DBG("%s: 0x%lx: page count: 0x%x\n", - __func__, ea, page_count(virt_to_page(ea))); + DBG("%s[0x%x]: 0x%lx: mapcount: 0x%x\n", + __func__, i, ea, gnt_mapcount(page)); plpar_pte_remove(0, slot, 0, &dummy1, &dummy2); } + local_irq_restore(flags); } static void gnttab_post_map_grant_ref( @@ -171,21 +201,25 @@ static void gnttab_post_map_grant_ref( { int i; long slot; + ulong flags; + + /* paranoia */ + local_irq_save(flags); for (i = 0 ; i < count; i++) { - ulong pa = map[i].dev_bus_addr; + ulong pa = map[i].host_addr; struct page *page; + if (map[i].status != GNTST_okay) { + printk(KERN_EMERG "%s: status, skip\n", __func__); + continue; + } + BUG_ON(pa < foreign_map_base || pa >= foreign_map_end); - /* ??? store the slot somewhere ??? */ - map[i].host_addr = (ulong)__va(pa); - page = virt_to_page(map[i].host_addr); - - DBG("%s: 0x%lx: 0x%x\n", - __func__, pa, page_count(page)); - - if (page_count(page) == 1) { + page = virt_to_page(__va(pa)); + + if (gnt_map(page)) { #ifdef DEBUG /* we need to get smarted than this */ slot = find_map_slot((ulong)__va(pa)); @@ -195,11 +229,15 @@ static void gnttab_post_map_grant_ref( } #endif slot = map_to_linear(pa); + DBG("%s[0x%x]: 0x%lx, mapcount:0x%x\n", + __func__, i, pa, gnt_mapcount(page)); + } else { - DBG("%s: skip 0x%lx\n", __func__, pa); - } - get_page(page); - } + DBG("%s[0x%x] skip 0x%lx, mapcount:0x%x\n", + __func__, i, pa, gnt_mapcount(page)); + } + } + local_irq_restore(flags); } int HYPERVISOR_grant_table_op(unsigned int cmd, void *op, unsigned int count) @@ -257,7 +295,7 @@ int HYPERVISOR_grant_table_op(unsigned i } EXPORT_SYMBOL(HYPERVISOR_grant_table_op); -static ulong setup_grant_maps(void) +static ulong find_grant_maps(void) { struct device_node *xen; u64 *gm; @@ -282,7 +320,7 @@ static ulong setup_grant_maps(void) if (!is_initial_xendomain()) { printk("OF: /xen/foreign-map not present\n"); _gm[0] = expect; - _gm[1] = 1UL << expect; + _gm[1] = 1024; gm = _gm; } else panic("OF: /xen/foreign-map must be present\n"); @@ -298,11 +336,8 @@ static ulong setup_grant_maps(void) return gm[1]; } -static int add_grant_pages(ulong pfn, ulong pgs) -{ - struct zone *zone; - struct pglist_data *pgdata; - int nid; +static void setup_foreign_segment(void) +{ extern int *slb_miss_kernel_load_xen_nop; ulong iaddr = (ulong)slb_miss_kernel_load_xen_nop; @@ -310,36 +345,97 @@ static int add_grant_pages(ulong pfn, ul * the branch with a NOP to turn the logic on */ *slb_miss_kernel_load_xen_nop = 0x60000000; flush_icache_range(iaddr, iaddr + 4); +} + +int arch_gnttab_suspend(volatile void __iomem *shared) +{ + iounmap(shared); + return 0; +} + +static mempool_t *grant_pool; +struct page *alloc_grant_page(void) +{ + void *va; + + va = mempool_alloc(grant_pool, GFP_KERNEL); + + return virt_to_page(va); +} + +void free_grant_page(struct page *page) +{ + mempool_free(pfn_to_kaddr(page_to_pfn(page)), grant_pool); +} + +static void *gp_alloc(gfp_t gfp_mask, void *pool_data) +{ + static ulong count; + ulong max = (ulong)pool_data; + void *ret = NULL; + + if (count < max) { + ulong pfn; + + pfn = (foreign_map_base >> PAGE_SHIFT) + count; + ret = pfn_to_kaddr(pfn); + ++count; + } + return ret; +} + +static void gp_free(void *element, void *pool_data) +{ + BUG(); +} + +static void setup_grant_area(void) +{ + ulong pgs; + int err; + struct zone *zone; + struct pglist_data *pgdata; + int nid; + + pgs = find_grant_maps(); + setup_foreign_segment(); /* add pages to the zone */ nid = 0; pgdata = NODE_DATA(nid); zone = pgdata->node_zones; - /* add pages to the zone */ - return __add_pages(zone, pfn, pgs); -} - -int arch_gnttab_suspend(volatile void __iomem *shared) -{ - iounmap(shared); - return 0; + err = __add_pages(zone, foreign_map_base >> PAGE_SHIFT, pgs); + + if (err < 0) { + printk(KERN_EMERG "%s: add_pages(0x%lx, 0x%lx) = %d\n", + __func__, foreign_map_base >> PAGE_SHIFT, pgs, err); + BUG(); + } + + /* create a memory pool to manage these pages */ + grant_pool = mempool_create(pgs, gp_alloc, gp_free, (void *)pgs); + if (grant_pool == NULL) { + printk(KERN_EMERG "%s: mempool_create(): failed\n", __func__); + BUG(); + } } void *arch_gnttab_map(unsigned long *frames) { void *shared; ulong pa = frames[0] << PAGE_SHIFT; - ulong pgs; + static int resume; shared = ioremap(pa, PAGE_SIZE * NR_GRANT_FRAMES); BUG_ON(shared == NULL); printk("%s: grant table at %p\n", __func__, shared); - pgs = setup_grant_maps(); - - if (is_initial_xendomain()) - add_grant_pages(foreign_map_base >> PAGE_SHIFT, pgs); + /* no need to do the rest of this if we are resuming */ + if (!resume) + setup_grant_area(); + + resume = 1; return shared; } diff -r f4d382795e57 -r 2a9c6a23cd12 arch/powerpc/platforms/xen/setup.h --- a/arch/powerpc/platforms/xen/setup.h Wed Oct 25 17:22:54 2006 -0400 +++ b/arch/powerpc/platforms/xen/setup.h Fri Nov 03 16:50:22 2006 -0500 @@ -21,3 +21,7 @@ static inline u64 jiffies_to_ns(unsigned } #define xen_guest_handle(hnd) ((hnd).p) + +extern struct page *alloc_grant_page(void); +extern void free_grant_page(struct page *page); + diff -r f4d382795e57 -r 2a9c6a23cd12 arch/powerpc/platforms/xen/util.c --- a/arch/powerpc/platforms/xen/util.c Wed Oct 25 17:22:54 2006 -0400 +++ b/arch/powerpc/platforms/xen/util.c Fri Nov 03 16:50:22 2006 -0500 @@ -5,16 +5,23 @@ #include <linux/vmalloc.h> #include <asm/uaccess.h> #include <xen/driver_util.h> - +#include "setup.h" struct vm_struct *alloc_vm_area(unsigned long size) { struct vm_struct *area; + struct page *page; + + page = alloc_grant_page(); + if (page == NULL) { + BUG(); + return NULL; + } area = kmalloc(sizeof(*area), GFP_KERNEL); if (area != NULL) { area->flags = VM_MAP;//XXX - area->addr = (void *)0xdeadcab4beeff00dULL; + area->addr = pfn_to_kaddr(page_to_pfn(page)); area->size = size; area->pages = NULL; //XXX area->nr_pages = size >> PAGE_SHIFT; @@ -40,10 +47,3 @@ void unlock_vm_area(struct vm_struct *ar preempt_enable(); } EXPORT_SYMBOL_GPL(unlock_vm_area); - -void update_vm_area(struct vm_struct *area, struct gnttab_map_grant_ref *op) -{ - area->phys_addr = op->dev_bus_addr; - area->addr = __va(op->dev_bus_addr); -} -EXPORT_SYMBOL_GPL(update_vm_area); diff -r f4d382795e57 -r 2a9c6a23cd12 drivers/xen/blkback/blkback.c --- a/drivers/xen/blkback/blkback.c Wed Oct 25 17:22:54 2006 -0400 +++ b/drivers/xen/blkback/blkback.c Fri Nov 03 16:50:22 2006 -0500 @@ -98,20 +98,6 @@ static inline unsigned long vaddr(pendin unsigned long pfn = page_to_pfn(pending_pages[vaddr_pagenr(req, seg)]); return (unsigned long)pfn_to_kaddr(pfn); } - -#ifdef CONFIG_PPC_XEN -static inline void update_pending_pages( - unsigned int idx, gnttab_map_grant_ref_t *mop) -{ -#ifdef PPC_NOT_YET - extern int arch_is_foreign_page(struct page *page); - - if (!arch_is_foreign_page(pending_pages[idx])) - __free_page(pending_pages[idx]); -#endif - pending_pages[idx] = pfn_to_page(mop->dev_bus_addr >> PAGE_SHIFT); -} -#endif #define pending_handle(_req, _seg) \ (pending_grant_handles[vaddr_pagenr(_req, _seg)]) @@ -410,13 +396,9 @@ static void dispatch_rw_block_io(blkif_t } pending_handle(pending_req, i) = map[i].handle; -#ifdef CONFIG_PPC_XEN - update_pending_pages(vaddr_pagenr(pending_req, i), &map[i]); -#else set_phys_to_machine(__pa(vaddr( pending_req, i)) >> PAGE_SHIFT, FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT)); -#endif seg[i].buf = map[i].dev_bus_addr | (req->seg[i].first_sect << 9); } diff -r f4d382795e57 -r 2a9c6a23cd12 drivers/xen/blkback/interface.c --- a/drivers/xen/blkback/interface.c Wed Oct 25 17:22:54 2006 -0400 +++ b/drivers/xen/blkback/interface.c Fri Nov 03 16:50:22 2006 -0500 @@ -65,7 +65,6 @@ static int map_frontend_page(blkif_t *bl lock_vm_area(blkif->blk_ring_area); ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1); - update_vm_area(blkif->blk_ring_area, &op); unlock_vm_area(blkif->blk_ring_area); BUG_ON(ret); diff -r f4d382795e57 -r 2a9c6a23cd12 drivers/xen/netback/interface.c --- a/drivers/xen/netback/interface.c Wed Oct 25 17:22:54 2006 -0400 +++ b/drivers/xen/netback/interface.c Fri Nov 03 16:50:22 2006 -0500 @@ -209,7 +209,6 @@ static int map_frontend_pages( lock_vm_area(netif->tx_comms_area); ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1); - update_vm_area(netif->tx_comms_area, &op); unlock_vm_area(netif->tx_comms_area); BUG_ON(ret); @@ -226,8 +225,6 @@ static int map_frontend_pages( lock_vm_area(netif->rx_comms_area); ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1); - update_vm_area(netif->rx_comms_area, &op); - unlock_vm_area(netif->rx_comms_area); BUG_ON(ret); if (op.status) { diff -r f4d382795e57 -r 2a9c6a23cd12 drivers/xen/netback/netback.c --- a/drivers/xen/netback/netback.c Wed Oct 25 17:22:54 2006 -0400 +++ b/drivers/xen/netback/netback.c Fri Nov 03 16:50:22 2006 -0500 @@ -76,39 +76,6 @@ static inline unsigned long idx_to_kaddr return (unsigned long)pfn_to_kaddr(page_to_pfn(mmap_pages[idx])); } -#ifdef CONFIG_PPC_XEN - -struct address_space xen_foreign_dummy_mapping; - -static inline void update_mmap_pages( - unsigned int idx, gnttab_map_grant_ref_t *mop) -{ - struct page *p; -#ifdef PPC_NOT_YET - struct page *cp = mmap_pages[idx]; - extern int arch_is_foreign_page(struct page *page); - - if (arch_is_foreign_page(cp)) { - printk(KERN_EMERG "%s foreign: %p, 0x%x\n", - __func__, page_address(cp), page_count(cp)); - } else { - printk(KERN_EMERG "%s local: %p, 0x%x\n", - __func__, page_address(cp), page_count(cp)); - // __free_page(mmap_pages[idx]); - } - -#endif - p = pfn_to_page(mop->dev_bus_addr >> PAGE_SHIFT); - - DPRINTK(KERN_EMERG "%s insert[%d]: 0x%lx, 0x%x\n", - __func__, idx, __va(mop->dev_bus_addr), page_count(p)); - - SetPageForeign(p, netif_page_release); - p->index = idx; - mmap_pages[idx] = p; -} -#endif - #define PKT_PROT_LEN 64 static struct { @@ -990,13 +957,9 @@ static int netbk_tx_check_mop(struct sk_ pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx; netif_put(netif); } else { -#ifdef CONFIG_PPC_XEN - update_mmap_pages(pending_idx, mop); -#else set_phys_to_machine( __pa(idx_to_kaddr(pending_idx)) >> PAGE_SHIFT, FOREIGN_FRAME(mop->dev_bus_addr >> PAGE_SHIFT)); -#endif grant_tx_handle[pending_idx] = mop->handle; } @@ -1011,13 +974,9 @@ static int netbk_tx_check_mop(struct sk_ /* Check error status: if okay then remember grant handle. */ newerr = (++mop)->status; if (likely(!newerr)) { -#ifdef CONFIG_PPC_XEN - update_mmap_pages(pending_idx, mop); -#else set_phys_to_machine( __pa(idx_to_kaddr(pending_idx))>>PAGE_SHIFT, FOREIGN_FRAME(mop->dev_bus_addr>>PAGE_SHIFT)); -#endif grant_tx_handle[pending_idx] = mop->handle; /* Had a previous error? Invalidate this fragment. */ if (unlikely(err)) @@ -1379,10 +1338,6 @@ static void netif_page_release(struct pa { /* Ready for next use. */ init_page_count(page); -#ifdef CONFIG_PPC_XEN - /* we need the count to be 2 so the unmap occurs */ - get_page(page); -#endif netif_idx_release(page->index); } diff -r f4d382795e57 -r 2a9c6a23cd12 drivers/xen/netfront/netfront.c --- a/drivers/xen/netfront/netfront.c Wed Oct 25 17:22:54 2006 -0400 +++ b/drivers/xen/netfront/netfront.c Fri Nov 03 16:50:22 2006 -0500 @@ -655,6 +655,13 @@ static void network_tx_buf_gc(struct net "domain.\n"); BUG(); } + if ((ulong)skb < 0xc000000000000000ULL) { + printk(KERN_EMERG "%s: bad skb: %p id: %d " + "status: 0x%x\n", __func__, + skb, id, txrsp->status); + continue; +// asm volatile(".long 0x200;nop"); + } gnttab_end_foreign_access_ref( np->grant_tx_ref[id], GNTMAP_readonly); gnttab_release_grant_reference( diff -r f4d382795e57 -r 2a9c6a23cd12 drivers/xen/tpmback/interface.c --- a/drivers/xen/tpmback/interface.c Wed Oct 25 17:22:54 2006 -0400 +++ b/drivers/xen/tpmback/interface.c Fri Nov 03 16:50:22 2006 -0500 @@ -82,7 +82,6 @@ static int map_frontend_page(tpmif_t *tp lock_vm_area(tpmif->tx_area); ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1); - update_vm_area(tpmif->tx_area, op); unlock_vm_area(tpmif->tx_area); BUG_ON(ret); diff -r f4d382795e57 -r 2a9c6a23cd12 include/asm-powerpc/xen/asm/hypervisor.h --- a/include/asm-powerpc/xen/asm/hypervisor.h Wed Oct 25 17:22:54 2006 -0400 +++ b/include/asm-powerpc/xen/asm/hypervisor.h Fri Nov 03 16:50:22 2006 -0500 @@ -226,7 +226,7 @@ MULTI_update_va_mapping_otherdomain( } #define INVALID_P2M_ENTRY (~0UL) -#define FOREIGN_FRAME(m) (m) +#define FOREIGN_FRAME(m) (INVALID_P2M_ENTRY) static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn) { if (pfn != mfn && mfn != INVALID_P2M_ENTRY) diff -r f4d382795e57 -r 2a9c6a23cd12 include/xen/driver_util.h --- a/include/xen/driver_util.h Wed Oct 25 17:22:54 2006 -0400 +++ b/include/xen/driver_util.h Fri Nov 03 16:50:22 2006 -0500 @@ -10,11 +10,6 @@ /* Allocate/destroy a 'vmalloc' VM area. */ extern struct vm_struct *alloc_vm_area(unsigned long size); extern void free_vm_area(struct vm_struct *area); -#ifdef CONFIG_PPC_XEN -extern void update_vm_area(struct vm_struct *area, struct gnttab_map_grant_ref *op); -#else -#define update_vm_area(a,o) -#endif /* Lock an area so that PTEs are accessible in the current address space. */ extern void lock_vm_area(struct vm_struct *area); diff -r f4d382795e57 -r 2a9c6a23cd12 include/xen/gnttab.h --- a/include/xen/gnttab.h Wed Oct 25 17:22:54 2006 -0400 +++ b/include/xen/gnttab.h Fri Nov 03 16:50:22 2006 -0500 @@ -123,10 +123,8 @@ gnttab_set_map_op(struct gnttab_map_gran { if (flags & GNTMAP_contains_pte) map->host_addr = addr; -#ifndef CONFIG_PPC_XEN else if (xen_feature(XENFEAT_auto_translated_physmap)) map->host_addr = __pa(addr); -#endif else map->host_addr = addr; @@ -141,10 +139,8 @@ gnttab_set_unmap_op(struct gnttab_unmap_ { if (flags & GNTMAP_contains_pte) unmap->host_addr = addr; -#ifndef CONFIG_PPC_XEN else if (xen_feature(XENFEAT_auto_translated_physmap)) unmap->host_addr = __pa(addr); -#endif else unmap->host_addr = addr; _______________________________________________ Xen-ppc-devel mailing list Xen-ppc-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-ppc-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |