summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/vm/vm_page.c24
-rw-r--r--sys/vm/vm_page.h14
-rw-r--r--sys/vm/vm_phys.c117
-rw-r--r--sys/vm/vm_phys.h4
4 files changed, 146 insertions, 13 deletions
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index 832ab7e..281c101 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -633,6 +633,30 @@ vm_page_unhold_pages(vm_page_t *ma, int count)
mtx_unlock(mtx);
}
+vm_page_t
+PHYS_TO_VM_PAGE(vm_paddr_t pa)
+{
+ vm_page_t m;
+
+#ifdef VM_PHYSSEG_SPARSE
+ m = vm_phys_paddr_to_vm_page(pa);
+ if (m == NULL)
+ m = vm_phys_fictitious_to_vm_page(pa);
+ return (m);
+#elif defined(VM_PHYSSEG_DENSE)
+ long pi;
+
+ pi = atop(pa);
+ if (pi >= first_page && pi < vm_page_array_size) {
+ m = &vm_page_array[pi - first_page];
+ return (m);
+ }
+ return (vm_phys_fictitious_to_vm_page(pa));
+#else
+#error "Either VM_PHYSSEG_DENSE or VM_PHYSSEG_SPARSE must be defined."
+#endif
+}
+
/*
* vm_page_getfake:
*
diff --git a/sys/vm/vm_page.h b/sys/vm/vm_page.h
index cad8c03..479c5bf 100644
--- a/sys/vm/vm_page.h
+++ b/sys/vm/vm_page.h
@@ -321,19 +321,7 @@ extern long first_page; /* first physical page number */
vm_page_t vm_phys_paddr_to_vm_page(vm_paddr_t pa);
-static __inline vm_page_t PHYS_TO_VM_PAGE(vm_paddr_t pa);
-
-static __inline vm_page_t
-PHYS_TO_VM_PAGE(vm_paddr_t pa)
-{
-#ifdef VM_PHYSSEG_SPARSE
- return (vm_phys_paddr_to_vm_page(pa));
-#elif defined(VM_PHYSSEG_DENSE)
- return (&vm_page_array[atop(pa) - first_page]);
-#else
-#error "Either VM_PHYSSEG_DENSE or VM_PHYSSEG_SPARSE must be defined."
-#endif
-}
+vm_page_t PHYS_TO_VM_PAGE(vm_paddr_t pa);
extern struct vpglocks vm_page_queue_lock;
diff --git a/sys/vm/vm_phys.c b/sys/vm/vm_phys.c
index 8c026e6..9cfea23 100644
--- a/sys/vm/vm_phys.c
+++ b/sys/vm/vm_phys.c
@@ -87,6 +87,15 @@ static struct vm_phys_seg vm_phys_segs[VM_PHYSSEG_MAX];
static int vm_phys_nsegs;
+#define VM_PHYS_FICTITIOUS_NSEGS 8
+static struct vm_phys_fictitious_seg {
+ vm_paddr_t start;
+ vm_paddr_t end;
+ vm_page_t first_page;
+} vm_phys_fictitious_segs[VM_PHYS_FICTITIOUS_NSEGS];
+static struct mtx vm_phys_fictitious_reg_mtx;
+MALLOC_DEFINE(M_FICT_PAGES, "", "");
+
static struct vm_freelist
vm_phys_free_queues[VM_RAW_NFREELIST][VM_NFREEPOOL][VM_NFREEORDER];
static struct vm_freelist
@@ -366,6 +375,8 @@ vm_phys_init(void)
for (flind = 0; flind < vm_nfreelists; flind++)
vm_phys_lookup_lists[0][flind] = &vm_phys_free_queues[flind];
#endif
+
+ mtx_init(&vm_phys_fictitious_reg_mtx, "vmfctr", NULL, MTX_DEF);
}
/*
@@ -510,6 +521,112 @@ vm_phys_paddr_to_vm_page(vm_paddr_t pa)
return (NULL);
}
+vm_page_t
+vm_phys_fictitious_to_vm_page(vm_paddr_t pa)
+{
+ struct vm_phys_fictitious_seg *seg;
+ vm_page_t m;
+ int segind;
+
+ m = NULL;
+ for (segind = 0; segind < VM_PHYS_FICTITIOUS_NSEGS; segind++) {
+ seg = &vm_phys_fictitious_segs[segind];
+ if (pa >= seg->start && pa < seg->end) {
+ m = &seg->first_page[atop(pa - seg->start)];
+ KASSERT((m->flags & PG_FICTITIOUS) != 0,
+ ("%p not fictitious", m));
+ break;
+ }
+ }
+ return (m);
+}
+
+int
+vm_phys_fictitious_reg_range(vm_paddr_t start, vm_paddr_t end,
+ vm_memattr_t memattr)
+{
+ struct vm_phys_fictitious_seg *seg;
+ vm_page_t fp;
+ long i, page_count;
+ int segind;
+#ifdef VM_PHYSSEG_DENSE
+ long pi;
+ boolean_t malloced;
+#endif
+
+ page_count = (end - start) / PAGE_SIZE;
+
+#ifdef VM_PHYSSEG_DENSE
+ pi = atop(start);
+ if (pi >= first_page && atop(end) < vm_page_array_size) {
+ fp = &vm_page_array[pi - first_page];
+ malloced = FALSE;
+ } else
+#endif
+ {
+ fp = malloc(page_count * sizeof(struct vm_page), M_FICT_PAGES,
+ M_WAITOK | M_ZERO);
+#ifdef VM_PHYSSEG_DENSE
+ malloced = TRUE;
+#endif
+ }
+ for (i = 0; i < page_count; i++) {
+ vm_page_initfake(&fp[i], start + PAGE_SIZE * i, memattr);
+ pmap_page_init(&fp[i]);
+ fp[i].oflags &= ~(VPO_BUSY | VPO_UNMANAGED);
+ }
+ mtx_lock(&vm_phys_fictitious_reg_mtx);
+ for (segind = 0; segind < VM_PHYS_FICTITIOUS_NSEGS; segind++) {
+ seg = &vm_phys_fictitious_segs[segind];
+ if (seg->start == 0 && seg->end == 0) {
+ seg->start = start;
+ seg->end = end;
+ seg->first_page = fp;
+ mtx_unlock(&vm_phys_fictitious_reg_mtx);
+ return (0);
+ }
+ }
+ mtx_unlock(&vm_phys_fictitious_reg_mtx);
+#ifdef VM_PHYSSEG_DENSE
+ if (malloced)
+#endif
+ free(fp, M_FICT_PAGES);
+ return (EBUSY);
+}
+
+void
+vm_phys_fictitious_unreg_range(vm_paddr_t start, vm_paddr_t end)
+{
+ struct vm_phys_fictitious_seg *seg;
+ vm_page_t fp;
+ int segind;
+#ifdef VM_PHYSSEG_DENSE
+ long pi;
+#endif
+
+#ifdef VM_PHYSSEG_DENSE
+ pi = atop(start);
+#endif
+
+ mtx_lock(&vm_phys_fictitious_reg_mtx);
+ for (segind = 0; segind < VM_PHYS_FICTITIOUS_NSEGS; segind++) {
+ seg = &vm_phys_fictitious_segs[segind];
+ if (seg->start == start && seg->end == end) {
+ seg->start = seg->end = 0;
+ fp = seg->first_page;
+ seg->first_page = NULL;
+ mtx_unlock(&vm_phys_fictitious_reg_mtx);
+#ifdef VM_PHYSSEG_DENSE
+ if (pi < first_page || atop(end) >= vm_page_array_size)
+#endif
+ free(fp, M_FICT_PAGES);
+ return;
+ }
+ }
+ mtx_unlock(&vm_phys_fictitious_reg_mtx);
+ KASSERT(0, ("Unregistering not registered fictitious range"));
+}
+
/*
* Find the segment containing the given physical address.
*/
diff --git a/sys/vm/vm_phys.h b/sys/vm/vm_phys.h
index 047e4a9..902659b 100644
--- a/sys/vm/vm_phys.h
+++ b/sys/vm/vm_phys.h
@@ -57,6 +57,10 @@ vm_page_t vm_phys_alloc_contig(u_long npages, vm_paddr_t low, vm_paddr_t high,
u_long alignment, vm_paddr_t boundary);
vm_page_t vm_phys_alloc_freelist_pages(int flind, int pool, int order);
vm_page_t vm_phys_alloc_pages(int pool, int order);
+int vm_phys_fictitious_reg_range(vm_paddr_t start, vm_paddr_t end,
+ vm_memattr_t memattr);
+void vm_phys_fictitious_unreg_range(vm_paddr_t start, vm_paddr_t end);
+vm_page_t vm_phys_fictitious_to_vm_page(vm_paddr_t pa);
void vm_phys_free_contig(vm_page_t m, u_long npages);
void vm_phys_free_pages(vm_page_t m, int order);
void vm_phys_init(void);
OpenPOWER on IntegriCloud