diff mbox series

[v3,37/52] xen/mpu: implement MPU version of copy_from_paddr

Message ID 20230626033443.2943270-38-Penny.Zheng@arm.com (mailing list archive)
State New, archived
Headers show
Series xen/arm: Add Armv8-R64 MPU support to Xen - Part#1 | expand

Commit Message

Penny Zheng June 26, 2023, 3:34 a.m. UTC
When implementing MPU version of copy_from_paddr, if source physical address
is not accessible, we shall map it temporarily with a transient MPU
memory region for copying and pasting.

Signed-off-by: Penny Zheng <penny.zheng@arm.com>
Signed-off-by: Wei Chen <wei.chen@arm.com>
---
v3:
- new patch
---
 xen/arch/arm/include/asm/mpu/mm.h |  3 +++
 xen/arch/arm/mpu/mm.c             |  6 +++---
 xen/arch/arm/mpu/setup.c          | 32 +++++++++++++++++++++++++++++++
 3 files changed, 38 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/xen/arch/arm/include/asm/mpu/mm.h b/xen/arch/arm/include/asm/mpu/mm.h
index 98f6df65b8..452fe20c5f 100644
--- a/xen/arch/arm/include/asm/mpu/mm.h
+++ b/xen/arch/arm/include/asm/mpu/mm.h
@@ -7,6 +7,9 @@  extern unsigned long frametable_pdx_end;
 
 extern int xen_mpumap_update(paddr_t base, paddr_t limit, unsigned int flags);
 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);
 
 #endif /* __ARCH_ARM_MM_MPU__ */
 
diff --git a/xen/arch/arm/mpu/mm.c b/xen/arch/arm/mpu/mm.c
index 3bb1a5c7c4..21276d6de9 100644
--- a/xen/arch/arm/mpu/mm.c
+++ b/xen/arch/arm/mpu/mm.c
@@ -631,7 +631,7 @@  int __init unmap_staticmem_pages_to_xen(paddr_t start, paddr_t end)
  * If it is mapped, the associated index will be returned.
  * If it is not mapped, INVALID_REGION_IDX will be returned.
  */
-static uint8_t is_mm_range_mapped(paddr_t pa, paddr_t len)
+uint8_t is_mm_range_mapped(paddr_t pa, paddr_t len)
 {
     int rc;
     uint8_t idx;
@@ -705,7 +705,7 @@  static int is_mm_range_mapped_with_attr(paddr_t pa, paddr_t len,
  * map_mm_range shall work with unmap_mm_range to map a chunk
  * of memory with a transient MPU memory region for a period of short time.
  */
-static void *map_mm_range(paddr_t pa, size_t len, unsigned int attributes)
+void *map_mm_range(paddr_t pa, size_t len, unsigned int attributes)
 {
     if ( xen_mpumap_update(pa, pa + len, attributes | _PAGE_TRANSIENT) )
         printk(XENLOG_ERR "Failed to map_mm_range 0x%"PRIpaddr"-0x%"PRIpaddr"\n",
@@ -714,7 +714,7 @@  static void *map_mm_range(paddr_t pa, size_t len, unsigned int attributes)
     return maddr_to_virt(pa);
 }
 
-static void unmap_mm_range(paddr_t pa)
+void unmap_mm_range(paddr_t pa)
 {
     uint8_t idx;
 
diff --git a/xen/arch/arm/mpu/setup.c b/xen/arch/arm/mpu/setup.c
index 31f412957c..9963975b4e 100644
--- a/xen/arch/arm/mpu/setup.c
+++ b/xen/arch/arm/mpu/setup.c
@@ -22,6 +22,7 @@ 
 #include <xen/init.h>
 #include <xen/mm.h>
 #include <xen/pfn.h>
+#include <asm/arm64/mpu.h>
 #include <asm/mpu/mm.h>
 #include <asm/page.h>
 #include <asm/setup.h>
@@ -60,6 +61,37 @@  void __init setup_mm(void)
     init_staticmem_pages();
 }
 
+/*
+ * copy_from_paddr - copy data from a physical address
+ * @dst: destination virtual address
+ * @paddr: source physical address
+ * @len: length to copy
+ */
+void __init copy_from_paddr(void *dst, paddr_t paddr, unsigned long len)
+{
+    void *src, *rc = NULL;
+    uint8_t idx;
+
+    idx = is_mm_range_mapped(round_pgdown(paddr), round_pgup(len));
+    if ( idx == INVALID_REGION_IDX )
+    {
+        /*
+         * If source physical address is not accessible, we shall map it
+         * temporarily for copying and pasting
+         */
+        rc = map_mm_range(round_pgdown(paddr), round_pgup(len),
+                          PAGE_HYPERVISOR_WC);
+        if ( !rc )
+            return;
+    }
+
+    src = maddr_to_virt(paddr);
+    memcpy(dst, src, len);
+
+    if ( rc )
+        unmap_mm_range(round_pgdown(paddr));
+}
+
 /*
  * Local variables:
  * mode: C