aboutsummaryrefslogtreecommitdiffstats
path: root/tools/xc/lib/xc_private.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/xc/lib/xc_private.c')
-rw-r--r--tools/xc/lib/xc_private.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/tools/xc/lib/xc_private.c b/tools/xc/lib/xc_private.c
index 4331cc943c..3b634148eb 100644
--- a/tools/xc/lib/xc_private.c
+++ b/tools/xc/lib/xc_private.c
@@ -38,3 +38,73 @@ void unmap_pfn(int pm_handle, void *vaddr)
{
(void)munmap(vaddr, PAGE_SIZE);
}
+
+#define FIRST_MMU_UPDATE 2
+
+static int flush_mmu_updates(int xc_handle, mmu_t *mmu)
+{
+ int err = 0;
+ privcmd_hypercall_t hypercall;
+
+ if ( mmu->idx == FIRST_MMU_UPDATE )
+ return 0;
+
+ /* The first two requests set the correct subject domain. */
+ mmu->updates[0].val = (unsigned long)(mmu->subject<<16) & ~0xFFFFUL;
+ mmu->updates[0].ptr = (unsigned long)(mmu->subject<< 0) & ~0xFFFFUL;
+ mmu->updates[1].val = (unsigned long)(mmu->subject>>16) & ~0xFFFFUL;
+ mmu->updates[1].ptr = (unsigned long)(mmu->subject>>32) & ~0xFFFFUL;
+ mmu->updates[0].ptr |= MMU_EXTENDED_COMMAND;
+ mmu->updates[0].val |= MMUEXT_SET_SUBJECTDOM_L;
+ mmu->updates[1].ptr |= MMU_EXTENDED_COMMAND;
+ mmu->updates[1].val |= MMUEXT_SET_SUBJECTDOM_H;
+
+ hypercall.op = __HYPERVISOR_mmu_update;
+ hypercall.arg[0] = (unsigned long)mmu->updates;
+ hypercall.arg[1] = (unsigned long)mmu->idx;
+
+ if ( mlock(mmu->updates, sizeof(mmu->updates)) != 0 )
+ {
+ PERROR("Could not lock pagetable update array");
+ err = 1;
+ goto out;
+ }
+
+ if ( do_xen_hypercall(xc_handle, &hypercall) < 0 )
+ {
+ ERROR("Failure when submitting mmu updates");
+ err = 1;
+ }
+
+ mmu->idx = FIRST_MMU_UPDATE;
+
+ (void)munlock(mmu->updates, sizeof(mmu->updates));
+
+ out:
+ return err;
+}
+
+mmu_t *init_mmu_updates(int xc_handle, domid_t dom)
+{
+ mmu_t *mmu = malloc(sizeof(mmu_t));
+ if ( mmu == NULL )
+ return mmu;
+ mmu->idx = FIRST_MMU_UPDATE;
+ mmu->subject = dom;
+ return mmu;
+}
+
+int add_mmu_update(int xc_handle, mmu_t *mmu,
+ unsigned long ptr, unsigned long val)
+{
+ mmu->updates[mmu->idx].ptr = ptr;
+ mmu->updates[mmu->idx].val = val;
+ if ( ++mmu->idx == MAX_MMU_UPDATES )
+ return flush_mmu_updates(xc_handle, mmu);
+ return 0;
+}
+
+int finish_mmu_updates(int xc_handle, mmu_t *mmu)
+{
+ return flush_mmu_updates(xc_handle, mmu);
+}