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