summaryrefslogtreecommitdiffstats
path: root/sys/i386/xen
diff options
context:
space:
mode:
Diffstat (limited to 'sys/i386/xen')
-rw-r--r--sys/i386/xen/pmap.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/sys/i386/xen/pmap.c b/sys/i386/xen/pmap.c
index 3c7c3f5..0f7a80f 100644
--- a/sys/i386/xen/pmap.c
+++ b/sys/i386/xen/pmap.c
@@ -3448,6 +3448,46 @@ pmap_copy_page(vm_page_t src, vm_page_t dst)
mtx_unlock(&sysmaps->lock);
}
+void
+pmap_copy_pages(vm_page_t ma[], vm_offset_t a_offset, vm_page_t mb[],
+ vm_offset_t b_offset, int xfersize)
+{
+ struct sysmaps *sysmaps;
+ vm_page_t a_pg, b_pg;
+ char *a_cp, *b_cp;
+ vm_offset_t a_pg_offset, b_pg_offset;
+ int cnt;
+
+ sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)];
+ mtx_lock(&sysmaps->lock);
+ if (*sysmaps->CMAP1 != 0)
+ panic("pmap_copy_pages: CMAP1 busy");
+ if (*sysmaps->CMAP2 != 0)
+ panic("pmap_copy_pages: CMAP2 busy");
+ sched_pin();
+ while (xfersize > 0) {
+ a_pg = ma[a_offset >> PAGE_SHIFT];
+ a_pg_offset = a_offset & PAGE_MASK;
+ cnt = min(xfersize, PAGE_SIZE - a_pg_offset);
+ b_pg = mb[b_offset >> PAGE_SHIFT];
+ b_pg_offset = b_offset & PAGE_MASK;
+ cnt = min(cnt, PAGE_SIZE - b_pg_offset);
+ PT_SET_MA(sysmaps->CADDR1, PG_V | VM_PAGE_TO_MACH(a_pg) | PG_A);
+ PT_SET_MA(sysmaps->CADDR2, PG_V | PG_RW |
+ VM_PAGE_TO_MACH(b_pg) | PG_A | PG_M);
+ a_cp = sysmaps->CADDR1 + a_pg_offset;
+ b_cp = sysmaps->CADDR2 + b_pg_offset;
+ bcopy(a_cp, b_cp, cnt);
+ a_offset += cnt;
+ b_offset += cnt;
+ xfersize -= cnt;
+ }
+ PT_SET_MA(sysmaps->CADDR1, 0);
+ PT_SET_MA(sysmaps->CADDR2, 0);
+ sched_unpin();
+ mtx_unlock(&sysmaps->lock);
+}
+
/*
* Returns true if the pmap's pv is one of the first
* 16 pvs linked to from this page. This count may
OpenPOWER on IntegriCloud