@@ -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__ */
@@ -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;
@@ -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