tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Device page



This kills phys_addr member at all.  I don't think UVM_PAGE_TO_PHYS() is
called often.  If we need performance, we should probably vectorize this
operation, like:

        struct vm_page *pgs[16];
        paddr_t pas[16];
        uvm_page_to_phys(pgs, 16, pas);

Index: sys/uvm/uvm_page.c
===================================================================
RCS file: /cvsroot/src/sys/uvm/uvm_page.c,v
retrieving revision 1.153
diff -u -p -r1.153 uvm_page.c
--- sys/uvm/uvm_page.c  27 Jan 2010 03:56:33 -0000      1.153
+++ sys/uvm/uvm_page.c  5 Feb 2010 15:21:51 -0000
@@ -441,7 +441,6 @@ uvm_page_init(vaddr_t *kvm_startp, vaddr
                /* init and free vm_pages (we've already zeroed them) */
                paddr = ptoa(vm_physmem[lcv].start);
                for (i = 0 ; i < n ; i++, paddr += PAGE_SIZE) {
-                       vm_physmem[lcv].pgs[i].phys_addr = paddr;
 #ifdef __HAVE_VM_PAGE_MD
                        VM_MDPAGE_INIT(&vm_physmem[lcv].pgs[i]);
 #endif
@@ -795,7 +794,6 @@ uvm_page_physload(paddr_t start, paddr_t
                memset(pgs, 0, sizeof(struct vm_page) * npages);
                for (lcv = 0, paddr = ptoa(start) ;
                                 lcv < npages ; lcv++, paddr += PAGE_SIZE) {
-                       pgs[lcv].phys_addr = paddr;
                        pgs[lcv].free_list = free_list;
                        if (atop(paddr) >= avail_start &&
                            atop(paddr) <= avail_end)
@@ -1876,6 +1874,76 @@ uvm_page_lookup_freelist(struct vm_page 
        return (vm_physmem[lcv].free_list);
 }
 
+paddr_t
+uvm_page_to_phys(const struct vm_page *pg)
+{
+       paddr_t pa;
+       struct vm_physseg *seg;
+
+#if VM_PHYSSEG_MAX == 1
+       /* 'contig' case */
+       if (pg >= vm_physmem[0].pgs && pg <= vm_physmem[0].lastpg) {
+               seg = &vm_physmem[0];
+               goto done;
+       }
+       return(-1);
+
+#elif (VM_PHYSSEG_STRAT == VM_PSTRAT_BSEARCH)
+       /* binary search for it */
+       u_int   start, len, try;
+
+       /*
+        * if try is too large (thus target is less than try) we reduce
+        * the length to trunc(len/2) [i.e. everything smaller than "try"]
+        *
+        * if the try is too small (thus target is greater than try) then
+        * we set the new start to be (try + 1).   this means we need to
+        * reduce the length to (round(len/2) - 1).
+        *
+        * note "adjust" below which takes advantage of the fact that
+        *  (round(len/2) - 1) == trunc((len - 1) / 2)
+        * for any value of len we may have
+        */
+
+       for (start = 0, len = vm_nphysseg ; len != 0 ; len = len / 2) {
+               try = start + (len / 2);        /* try in the middle */
+
+               /* start past our try? */
+               if (pg >= vm_physmem[try].pgs[0]) {
+                       /* was try correct? */
+                       if (pg <= vm_physmem[try].lastpg) {
+                               seg = &vm_physmem[try];
+                               goto done;
+                       }
+                       start = try + 1;        /* next time, start here */
+                       len--;                  /* "adjust" */
+               } else {
+                       /*
+                        * pframe before try, just reduce length of
+                        * region, done in "for" loop
+                        */
+               }
+       }
+       panic("invalid pg=%p\n", pg);
+
+#else
+       /* linear search for it */
+       int     lcv;
+
+       for (lcv = 0; lcv < vm_nphysseg; lcv++) {
+               if (pg >= vm_physmem[lcv].pgs &&
+                   pg <= vm_physmem[lcv].lastpg) {
+                       seg = &vm_physmem[lcv];
+                       goto done;
+               }
+       }
+       panic("invalid pg=%p\n", pg);
+
+#endif
+done:
+       pa = (seg->start + pg - seg->pgs) * PAGE_SIZE;
+               return pa;
+}
 #if defined(DDB) || defined(DEBUGPRINT)
 
 /*
Index: sys/uvm/uvm_page.h
===================================================================
RCS file: /cvsroot/src/sys/uvm/uvm_page.h,v
retrieving revision 1.57
diff -u -p -r1.57 uvm_page.h
--- sys/uvm/uvm_page.h  18 Aug 2009 18:06:54 -0000      1.57
+++ sys/uvm/uvm_page.h  5 Feb 2010 15:21:51 -0000
@@ -142,7 +142,6 @@ struct vm_page {
                                                 * to modify: [O _and_ P] */
        uint16_t                wire_count;     /* wired down map refs [P] */
        uint16_t                pqflags;        /* page queue flags [P] */
-       paddr_t                 phys_addr;      /* physical address of page */
 
 #ifdef __HAVE_VM_PAGE_MD
        struct vm_page_md       mdpage;         /* pmap-specific data */
@@ -298,7 +297,12 @@ static int vm_physseg_find(paddr_t, int 
 
 #define UVM_PAGE_TREE_PENALTY  4       /* XXX: a guess */
 
+#if 0
 #define VM_PAGE_TO_PHYS(entry) ((entry)->phys_addr)
+#else
+paddr_t uvm_page_to_phys(const struct vm_page *);
+#define VM_PAGE_TO_PHYS(entry) uvm_page_to_phys(entry)
+#endif
 
 /*
  * Compute the page color bucket for a given page.


Home | Main Index | Thread Index | Old Index