aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xen/common/compat/memory.c14
-rw-r--r--xen/common/memory.c37
-rw-r--r--xen/include/asm-ia64/mm.h1
-rw-r--r--xen/include/public/memory.h16
-rw-r--r--xen/include/xlat.lst1
-rw-r--r--xen/include/xsm/xsm.h6
-rw-r--r--xen/xsm/dummy.c6
-rw-r--r--xen/xsm/flask/hooks.c6
8 files changed, 87 insertions, 0 deletions
diff --git a/xen/common/compat/memory.c b/xen/common/compat/memory.c
index 2402984f1e..e7257cc53e 100644
--- a/xen/common/compat/memory.c
+++ b/xen/common/compat/memory.c
@@ -25,6 +25,7 @@ int compat_memory_op(unsigned int cmd, XEN_GUEST_HANDLE(void) compat)
XEN_GUEST_HANDLE(void) hnd;
struct xen_memory_reservation *rsrv;
struct xen_memory_exchange *xchg;
+ struct xen_remove_from_physmap *xrfp;
} nat;
union {
struct compat_memory_reservation rsrv;
@@ -179,6 +180,18 @@ int compat_memory_op(unsigned int cmd, XEN_GUEST_HANDLE(void) compat)
nat.hnd = compat;
break;
+ case XENMEM_remove_from_physmap:
+ {
+ struct compat_remove_from_physmap cmp;
+
+ if ( copy_from_guest(&cmp, compat, 1) )
+ return -EFAULT;
+
+ XLAT_remove_from_physmap(nat.xrfp, &cmp);
+
+ break;
+ }
+
default:
return compat_arch_memory_op(cmd, compat);
}
@@ -284,6 +297,7 @@ int compat_memory_op(unsigned int cmd, XEN_GUEST_HANDLE(void) compat)
case XENMEM_current_reservation:
case XENMEM_maximum_reservation:
case XENMEM_maximum_gpfn:
+ case XENMEM_remove_from_physmap:
break;
default:
diff --git a/xen/common/memory.c b/xen/common/memory.c
index 8d45439745..53886cea3b 100644
--- a/xen/common/memory.c
+++ b/xen/common/memory.c
@@ -659,6 +659,43 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE(void) arg)
break;
+ case XENMEM_remove_from_physmap:
+ {
+ struct xen_remove_from_physmap xrfp;
+ unsigned long mfn;
+ struct domain *d;
+
+ if ( copy_from_guest(&xrfp, arg, 1) )
+ return -EFAULT;
+
+ rc = rcu_lock_target_domain_by_id(xrfp.domid, &d);
+ if ( rc != 0 )
+ return rc;
+
+ if ( xsm_remove_from_physmap(current->domain, d) )
+ {
+ rcu_unlock_domain(d);
+ return -EPERM;
+ }
+
+ domain_lock(d);
+
+ mfn = get_gfn_untyped(d, xrfp.gpfn);
+
+ if ( mfn_valid(mfn) )
+ guest_physmap_remove_page(d, xrfp.gpfn, mfn, PAGE_ORDER_4K);
+ else
+ rc = -ENOENT;
+
+ put_gfn(d, xrfp.gpfn);
+
+ domain_unlock(d);
+
+ rcu_unlock_domain(d);
+
+ break;
+ }
+
default:
rc = arch_memory_op(op, arg);
break;
diff --git a/xen/include/asm-ia64/mm.h b/xen/include/asm-ia64/mm.h
index d09c363df3..a2bfc026e6 100644
--- a/xen/include/asm-ia64/mm.h
+++ b/xen/include/asm-ia64/mm.h
@@ -550,6 +550,7 @@ extern u64 translate_domain_pte(u64 pteval, u64 address, u64 itir__,
#define gmfn_to_mfn(_d, gpfn) \
gmfn_to_mfn_foreign((_d), (gpfn))
+#define get_gfn_untyped(d, gpfn) gmfn_to_mfn(d, gpfn)
#define put_gfn(d, g) ((void)0)
#define __gpfn_invalid(_d, gpfn) \
diff --git a/xen/include/public/memory.h b/xen/include/public/memory.h
index 3bc2f25cdc..9d9aabcfdb 100644
--- a/xen/include/public/memory.h
+++ b/xen/include/public/memory.h
@@ -229,6 +229,22 @@ struct xen_add_to_physmap {
typedef struct xen_add_to_physmap xen_add_to_physmap_t;
DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_t);
+/*
+ * Unmaps the page appearing at a particular GPFN from the specified guest's
+ * pseudophysical address space.
+ * arg == addr of xen_remove_from_physmap_t.
+ */
+#define XENMEM_remove_from_physmap 15
+struct xen_remove_from_physmap {
+ /* Which domain to change the mapping for. */
+ domid_t domid;
+
+ /* GPFN of the current mapping of the page. */
+ xen_pfn_t gpfn;
+};
+typedef struct xen_remove_from_physmap xen_remove_from_physmap_t;
+DEFINE_XEN_GUEST_HANDLE(xen_remove_from_physmap_t);
+
/*** REMOVED ***/
/*#define XENMEM_translate_gpfn_list 8*/
diff --git a/xen/include/xlat.lst b/xen/include/xlat.lst
index f6021550df..3d4f1e328f 100644
--- a/xen/include/xlat.lst
+++ b/xen/include/xlat.lst
@@ -60,6 +60,7 @@
! memory_map memory.h
! memory_reservation memory.h
! pod_target memory.h
+! remove_from_physmap memory.h
? physdev_eoi physdev.h
? physdev_get_free_pirq physdev.h
? physdev_irq physdev.h
diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h
index df6cec22f3..566c8080f7 100644
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -169,6 +169,7 @@ struct xsm_operations {
int (*update_va_mapping) (struct domain *d, struct domain *f,
l1_pgentry_t pte);
int (*add_to_physmap) (struct domain *d1, struct domain *d2);
+ int (*remove_from_physmap) (struct domain *d1, struct domain *d2);
int (*sendtrigger) (struct domain *d);
int (*bind_pt_irq) (struct domain *d, struct xen_domctl_bind_pt_irq *bind);
int (*unbind_pt_irq) (struct domain *d);
@@ -738,6 +739,11 @@ static inline int xsm_add_to_physmap(struct domain *d1, struct domain *d2)
return xsm_call(add_to_physmap(d1, d2));
}
+static inline int xsm_remove_from_physmap(struct domain *d1, struct domain *d2)
+{
+ return xsm_call(remove_from_physmap(d1, d2));
+}
+
static inline int xsm_sendtrigger(struct domain *d)
{
return xsm_call(sendtrigger(d));
diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c
index 4bbfbffb14..65daa4e775 100644
--- a/xen/xsm/dummy.c
+++ b/xen/xsm/dummy.c
@@ -529,6 +529,11 @@ static int dummy_add_to_physmap (struct domain *d1, struct domain *d2)
return 0;
}
+static int dummy_remove_from_physmap (struct domain *d1, struct domain *d2)
+{
+ return 0;
+}
+
static int dummy_sendtrigger (struct domain *d)
{
return 0;
@@ -690,6 +695,7 @@ void xsm_fixup_ops (struct xsm_operations *ops)
set_to_dummy_if_null(ops, mmu_machphys_update);
set_to_dummy_if_null(ops, update_va_mapping);
set_to_dummy_if_null(ops, add_to_physmap);
+ set_to_dummy_if_null(ops, remove_from_physmap);
set_to_dummy_if_null(ops, sendtrigger);
set_to_dummy_if_null(ops, bind_pt_irq);
set_to_dummy_if_null(ops, pin_mem_cacheattr);
diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
index 0d35767821..a2020a9f60 100644
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -1283,6 +1283,11 @@ static int flask_add_to_physmap(struct domain *d1, struct domain *d2)
return domain_has_perm(d1, d2, SECCLASS_MMU, MMU__PHYSMAP);
}
+static int flask_remove_from_physmap(struct domain *d1, struct domain *d2)
+{
+ return domain_has_perm(d1, d2, SECCLASS_MMU, MMU__PHYSMAP);
+}
+
static int flask_sendtrigger(struct domain *d)
{
return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, DOMAIN__TRIGGER);
@@ -1550,6 +1555,7 @@ static struct xsm_operations flask_ops = {
.mmu_machphys_update = flask_mmu_machphys_update,
.update_va_mapping = flask_update_va_mapping,
.add_to_physmap = flask_add_to_physmap,
+ .remove_from_physmap = flask_remove_from_physmap,
.sendtrigger = flask_sendtrigger,
.get_device_group = flask_get_device_group,
.test_assign_device = flask_test_assign_device,