/* This is called just after a mm has been created, but it has not been used yet. We need to make sure that its pagetable is all read-only, and can be pinned. */ void xen_pgd_pin(pgd_t *pgd) { struct multicall_space mcs; struct mmuext_op *op; xen_mc_batch(); if (pgd_walk(pgd, pin_page, TASK_SIZE)) { /* re-enable interrupts for kmap_flush_unused */ xen_mc_issue(0); kmap_flush_unused(); xen_mc_batch(); } mcs = __xen_mc_entry(sizeof(*op)); op = mcs.args; #ifdef CONFIG_X86_PAE op->cmd = MMUEXT_PIN_L3_TABLE; #else op->cmd = MMUEXT_PIN_L2_TABLE; #endif op->arg1.mfn = pfn_to_mfn(PFN_DOWN(__pa(pgd))); MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF); xen_mc_issue(0); }
static void xen_set_ldt(const void *addr, unsigned entries) { struct mmuext_op *op; struct multicall_space mcs = xen_mc_entry(sizeof(*op)); op = mcs.args; op->cmd = MMUEXT_SET_LDT; op->arg1.linear_addr = (unsigned long)addr; op->arg2.nr_ents = entries; MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF); xen_mc_issue(PARAVIRT_LAZY_CPU); }
static void xen_extend_mmuext_op(const struct mmuext_op *op) { struct multicall_space mcs; struct mmuext_op *u; mcs = xen_mc_extend_args(__HYPERVISOR_mmuext_op, sizeof(*u)); if (mcs.mc != NULL) { mcs.mc->args[1]++; } else { mcs = __xen_mc_entry(sizeof(*u)); MULTI_mmuext_op(mcs.mc, mcs.args, 1, NULL, DOMID_SELF); } u = mcs.args; *u = *op; }
/* Release a pagetables pages back as normal RW */ static void xen_pgd_unpin(pgd_t *pgd) { struct mmuext_op *op; struct multicall_space mcs; xen_mc_batch(); mcs = __xen_mc_entry(sizeof(*op)); op = mcs.args; op->cmd = MMUEXT_UNPIN_TABLE; op->arg1.mfn = pfn_to_mfn(PFN_DOWN(__pa(pgd))); MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF); pgd_walk(pgd, unpin_page, TASK_SIZE); xen_mc_issue(0); }