# HG changeset patch
# User Jimi Xenidis <[EMAIL PROTECTED]>
# Node ID f18ec562c11cabed94d448a12754660c63497fac
# Parent  2765c83b576d5af048d381c481e33f597c2be258
[LINUX][XEN][POWERPC] More accurate Grant Table Ops

This patch add the following:
 - More DBG() points of interest
 - If we run out of Bolted PTEs simply report it and let the "natural"
   page fault occur
 - Use the page counters to track PTE redundancies
 - BUG() if GNTTABOP_transfer is ever used
 - Add GNTTABOP_copy

The use of page counters may have SMP ramifications since the Linear
map inits the refcount to 1 and there is no atomic methods to inc/dec
and see if counter == 1.

Signed-off-by: Jimi Xenidis <[EMAIL PROTECTED]>
---
 arch/powerpc/platforms/xen/gnttab.c |  109 +++++++++++++++++++++++++++---------
 1 files changed, 82 insertions(+), 27 deletions(-)

diff -r 2765c83b576d -r f18ec562c11c arch/powerpc/platforms/xen/gnttab.c
--- a/arch/powerpc/platforms/xen/gnttab.c       Mon Oct 09 19:57:42 2006 -0400
+++ b/arch/powerpc/platforms/xen/gnttab.c       Tue Oct 10 09:48:33 2006 -0400
@@ -39,6 +39,8 @@ static long map_to_linear(ulong paddr)
        mode = _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX;
        vaddr = (ulong)__va(paddr);
 
+       DBG("%s: 0x%lx: 0x%x\n",
+           __func__, paddr, page_count(virt_to_page(vaddr)));
        {
                unsigned long vpn, hash, hpteg;
                unsigned long vsid = get_kernel_vsid(vaddr);
@@ -57,25 +59,13 @@ static long map_to_linear(ulong paddr)
                BUG_ON(!ppc_md.hpte_insert);
                slot = ppc_md.hpte_insert(hpteg, va, paddr,
                                          tmp_mode, HPTE_V_BOLTED, psize);
-               BUG_ON(slot < 0);
+               if (slot < 0)
+                       printk(KERN_EMERG
+                              "%s: no more bolted entries "
+                              "HTAB[0x%lx]: 0x%lx\n",
+                              __func__, hpteg, paddr);
        }
        return slot;
-}
-
-static void gnttab_post_map_grant_ref(
-       struct gnttab_map_grant_ref *map, int count)
-{
-       int i;
-       long slot;
-
-       for (i = 0 ; i < count; i++) {
-               ulong pa = map[i].dev_bus_addr;
-               BUG_ON(pa < foreign_map_base || pa >= foreign_map_end);
-
-               slot = map_to_linear(pa);
-               /* store the slot somewhere */
-               map[i].host_addr = (ulong)__va(pa);
-       }
 }
 
 static unsigned long get_hpte_vsid(ulong slot)
@@ -128,29 +118,89 @@ static long find_hpte_slot(unsigned long
        return -1;
 } 
 
+static long find_map_slot(ulong ea)
+{
+       int psize = MMU_PAGE_4K;
+       ulong vsid;
+       ulong va;
+
+       vsid = get_kernel_vsid(ea);
+       va = (vsid << 28) | (ea & 0x0fffffff);
+       
+       return find_hpte_slot(va, psize);
+}
+
+
 static void gnttab_pre_unmap_grant_ref(
        struct gnttab_unmap_grant_ref *unmap, int count)
 {
        long slot;
-       ulong vsid;
-       ulong va;
-       int psize = MMU_PAGE_4K;
        int i;
        ulong ea;
        unsigned long dummy1, dummy2;
 
        for (i = 0 ; i < count; i++) {
+               struct page *page;
+
                ea = unmap[i].host_addr;
-               vsid = get_kernel_vsid(ea);
-               va = (vsid << 28) | (ea & 0x0fffffff);
-
-               slot = find_hpte_slot(va, psize);
-               BUG_ON(slot < 0);
-
+               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);
+                       continue;
+               }
+               slot = find_map_slot(ea);
+               if (slot < 0) {
+                       printk(KERN_EMERG "%s: PTE not found: 0x%lx\n",
+                              __func__, ea);
+                       continue;
+               }
+
+               DBG("%s: 0x%lx: 0x%x\n",
+                      __func__, ea, page_count(virt_to_page(ea)));
                plpar_pte_remove(0, slot, 0, &dummy1, &dummy2);
 
                DBG("%s: remove_pages(0x%lx, 0x%lx)\n",
                    __func__, unmap[i].host_addr, unmap[i].dev_bus_addr);
+       }
+}
+
+static void gnttab_post_map_grant_ref(
+       struct gnttab_map_grant_ref *map, int count)
+{
+       int i;
+       long slot;
+
+       for (i = 0 ; i < count; i++) {
+               ulong pa = map[i].dev_bus_addr;
+               struct page *page;
+
+               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);
+
+               if (page_count(page) == 1) {
+#ifdef DEBUG                   
+                       /* we need to get smarted than this */
+                       slot = find_map_slot((ulong)__va(pa));
+                       if (slot >= 0) {
+                               DBG("%s: redundant 0x%lx\n", __func__, pa);
+                               continue;
+                       }
+#endif
+                       slot = map_to_linear(pa);
+               } else {
+                       DBG("%s: skip 0x%lx\n", __func__, pa);
+               }
+               get_page(page);
        }
 }
 
@@ -175,7 +225,8 @@ int HYPERVISOR_grant_table_op(unsigned i
                memcpy(&setup, op, sizeof(setup));
                argsize = sizeof(setup);
 
-               frame_list = 
xencomm_create_inline(xen_guest_handle(setup.frame_list));
+               frame_list = xencomm_create_inline(
+                       xen_guest_handle(setup.frame_list));
 
                set_xen_guest_handle(setup.frame_list, frame_list);
                memcpy(op, &setup, sizeof(setup));
@@ -185,6 +236,10 @@ int HYPERVISOR_grant_table_op(unsigned i
                argsize = sizeof(struct gnttab_dump_table);
                break;
        case GNTTABOP_transfer:
+               BUG();
+               argsize = sizeof(struct gnttab_transfer);
+               break;
+       case GNTTABOP_copy:
                argsize = sizeof(struct gnttab_transfer);
                break;
        default:

_______________________________________________
Xen-ppc-devel mailing list
Xen-ppc-devel@lists.xensource.com
http://lists.xensource.com/xen-ppc-devel

Reply via email to