In MPU system, we implement map_domain_page()/unmap_domain_page()
through mapping the domain page with a transient MPU region on demand.
Signed-off-by: Penny Zheng <penny.zheng@arm.com>
Signed-off-by: Wei Chen <wei.chen@arm.com>
---
v3:
- new patch
---
xen/arch/arm/Makefile | 4 ++
xen/arch/arm/include/asm/mpu/mm.h | 1 +
xen/arch/arm/mpu/domain_page.c | 68 +++++++++++++++++++++++++++++++
xen/arch/arm/mpu/mm.c | 17 ++++++++
4 files changed, 90 insertions(+)
create mode 100644 xen/arch/arm/mpu/domain_page.c
diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 5f6ee817ad..feb49640a0 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -17,7 +17,11 @@ obj-y += device.o
obj-$(CONFIG_IOREQ_SERVER) += dm.o
obj-y += domain.o
obj-y += domain_build.init.o
+ifneq ($(CONFIG_HAS_MPU),y)
obj-$(CONFIG_ARCH_MAP_DOMAIN_PAGE) += domain_page.o
+else
+obj-$(CONFIG_ARCH_MAP_DOMAIN_PAGE) += mpu/domain_page.o
+endif
obj-y += domctl.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-y += efi/
diff --git a/xen/arch/arm/include/asm/mpu/mm.h b/xen/arch/arm/include/asm/mpu/mm.h
index 452fe20c5f..a83519ad13 100644
--- a/xen/arch/arm/include/asm/mpu/mm.h
+++ b/xen/arch/arm/include/asm/mpu/mm.h
@@ -10,6 +10,7 @@ extern void setup_staticheap_mappings(void);
extern uint8_t is_mm_range_mapped(paddr_t pa, paddr_t len);
extern void *map_mm_range(paddr_t pa, size_t len, unsigned int attributes);
extern void unmap_mm_range(paddr_t pa);
+extern bool is_mm_range_mapped_transient(paddr_t pa, paddr_t len);
#endif /* __ARCH_ARM_MM_MPU__ */
diff --git a/xen/arch/arm/mpu/domain_page.c b/xen/arch/arm/mpu/domain_page.c
new file mode 100644
index 0000000000..da408bb9e0
--- /dev/null
+++ b/xen/arch/arm/mpu/domain_page.c
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#include <xen/mm.h>
+#include <asm/arm64/mpu.h>
+
+/* Override macros from asm/mm.h to make them work with mfn_t */
+#undef mfn_to_virt
+#define mfn_to_virt(mfn) __mfn_to_virt(mfn_x(mfn))
+
+void *map_domain_page_global(mfn_t mfn)
+{
+ /* TODO: map shared domain page globally */
+ printk(XENLOG_ERR
+ "mpu: mapping shared domain page not SUPPORTED right now!\n");
+ return NULL;
+}
+
+void unmap_domain_page_global(const void *va)
+{
+ /* TODO: map shared domain page globally */
+ printk(XENLOG_ERR
+ "mpu: mapping shared domain page not SUPPORTED right now!\n");
+ return;
+}
+
+/* Map a page of domain memory */
+void *map_domain_page(mfn_t mfn)
+{
+ uint8_t idx;
+ paddr_t pa = mfn_to_maddr(mfn);
+
+ idx = is_mm_range_mapped(pa, PAGE_SIZE);
+ if ( idx != INVALID_REGION_IDX )
+ /* Already mapped */
+ return mfn_to_virt(mfn);
+ else
+ /*
+ * Map it temporarily with a transient MPU region.
+ * And it is caller's responsibity to unmap it
+ * through unmap_domain_page.
+ */
+ return map_mm_range(pa, PAGE_SIZE, PAGE_HYPERVISOR_RW);
+}
+
+/* Release a mapping taken with map_domain_page() */
+void unmap_domain_page(const void *va)
+{
+ paddr_t pa = (paddr_t)(unsigned long)(va);
+
+ /* Only unmap transient page */
+ if ( is_mm_range_mapped_transient(pa, PAGE_SIZE) )
+ unmap_mm_range(pa);
+}
+
+mfn_t domain_page_map_to_mfn(const void *ptr)
+{
+ printk(XENLOG_ERR
+ "mpu: domain_page_map_to_mfn() not SUPPORTED right now!\n");
+ return INVALID_MFN;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/mpu/mm.c b/xen/arch/arm/mpu/mm.c
index 21276d6de9..b2419f0603 100644
--- a/xen/arch/arm/mpu/mm.c
+++ b/xen/arch/arm/mpu/mm.c
@@ -809,6 +809,23 @@ void iounmap(void __iomem *va)
unmap_mm_range(virt_to_maddr(va));
}
+bool is_mm_range_mapped_transient(paddr_t pa, paddr_t len)
+{
+ uint8_t idx;
+
+ idx = is_mm_range_mapped(pa, len);
+ if ( idx != INVALID_REGION_IDX )
+ {
+ pr_t *region;
+
+ region = &xen_mpumap[idx];
+ if ( region_is_transient(region) )
+ return true;
+ }
+
+ return false;
+}
+
/*
* Local variables:
* mode: C
--
2.25.1