|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v1 2/6] xen/riscv: implement copy_to_guest_phys()
Introduce copy_to_guest_phys() for RISC-V, based on the Arm implementation.
Add a generic copy_guest() helper for copying to and from guest physical
(and potentially virtual addresses in the future), and implement
translate_get_page() to translate a guest physical address into a struct
page_info via the domain p2m.
Compared to the Arm code:
- Drop COPY_flush_dcache(), as no such use cases exist on RISC-V.
- Do not implement the linear mapping case, which is currently unused.
- Use PAGE_OFFSET() to initialize the local offset variable in copy_guest().
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@xxxxxxxxx>
---
xen/arch/riscv/Makefile | 1 +
xen/arch/riscv/guestcopy.c | 112 ++++++++++++++++++++++
xen/arch/riscv/include/asm/guest_access.h | 7 ++
3 files changed, 120 insertions(+)
create mode 100644 xen/arch/riscv/guestcopy.c
diff --git a/xen/arch/riscv/Makefile b/xen/arch/riscv/Makefile
index 7439d029cc45..90210799e038 100644
--- a/xen/arch/riscv/Makefile
+++ b/xen/arch/riscv/Makefile
@@ -3,6 +3,7 @@ obj-y += cpufeature.o
obj-y += domain.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-y += entry.o
+obj-y += guestcopy.o
obj-y += imsic.o
obj-y += intc.o
obj-y += irq.o
diff --git a/xen/arch/riscv/guestcopy.c b/xen/arch/riscv/guestcopy.c
new file mode 100644
index 000000000000..19b681c30b1b
--- /dev/null
+++ b/xen/arch/riscv/guestcopy.c
@@ -0,0 +1,112 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <xen/domain_page.h>
+#include <xen/page-size.h>
+#include <xen/sched.h>
+#include <xen/string.h>
+
+#include <asm/guest_access.h>
+
+#define COPY_from_guest (0U << 0)
+#define COPY_to_guest (1U << 0)
+#define COPY_ipa (0U << 1)
+#define COPY_linear (1U << 1)
+
+typedef union
+{
+ struct
+ {
+ struct vcpu *v;
+ } gva;
+
+ struct
+ {
+ struct domain *d;
+ } gpa;
+} copy_info_t;
+
+#define GVA_INFO(vcpu) ((copy_info_t) { .gva = { vcpu } })
+#define GPA_INFO(domain) ((copy_info_t) { .gpa = { domain } })
+
+static struct page_info *translate_get_page(copy_info_t info, uint64_t addr,
+ bool linear, bool write)
+{
+ p2m_type_t p2mt;
+ struct page_info *page;
+
+ if ( linear )
+ BUG_ON("unimplemeted\n");
+
+ page = get_page_from_gfn(info.gpa.d, paddr_to_pfn(addr), &p2mt, P2M_ALLOC);
+
+ if ( !page )
+ return NULL;
+
+ if ( !p2m_is_ram(p2mt) )
+ {
+ put_page(page);
+ return NULL;
+ }
+
+ return page;
+}
+
+static unsigned long copy_guest(void *buf, uint64_t addr, unsigned int len,
+ copy_info_t info, unsigned int flags)
+{
+ unsigned int offset = PAGE_OFFSET(addr);
+
+ BUILD_BUG_ON((sizeof(addr)) < sizeof(vaddr_t));
+ BUILD_BUG_ON((sizeof(addr)) < sizeof(paddr_t));
+
+ while ( len )
+ {
+ void *p;
+ unsigned int size = min(len, (unsigned int)PAGE_SIZE - offset);
+ struct page_info *page;
+
+ page = translate_get_page(info, addr, flags & COPY_linear,
+ flags & COPY_to_guest);
+ if ( page == NULL )
+ return len;
+
+ p = __map_domain_page(page);
+ p += offset;
+ if ( flags & COPY_to_guest )
+ {
+ /*
+ * buf will be NULL when the caller request to zero the
+ * guest memory.
+ */
+ if ( buf )
+ memcpy(p, buf, size);
+ else
+ memset(p, 0, size);
+ }
+ else
+ memcpy(buf, p, size);
+
+ unmap_domain_page(p - offset);
+ put_page(page);
+ len -= size;
+ buf += size;
+ addr += size;
+
+ /*
+ * After the first iteration, guest virtual address is correctly
+ * aligned to PAGE_SIZE.
+ */
+ offset = 0;
+ }
+
+ return 0;
+}
+
+unsigned long copy_to_guest_phys(struct domain *d,
+ paddr_t gpa,
+ void *buf,
+ unsigned int len)
+{
+ return copy_guest(buf, gpa, len, GPA_INFO(d),
+ COPY_to_guest | COPY_ipa);
+}
diff --git a/xen/arch/riscv/include/asm/guest_access.h
b/xen/arch/riscv/include/asm/guest_access.h
index 7cd51fbbdead..024e29b4c9f9 100644
--- a/xen/arch/riscv/include/asm/guest_access.h
+++ b/xen/arch/riscv/include/asm/guest_access.h
@@ -2,6 +2,10 @@
#ifndef ASM__RISCV__GUEST_ACCESS_H
#define ASM__RISCV__GUEST_ACCESS_H
+#include <xen/types.h>
+
+struct domain;
+
unsigned long raw_copy_to_guest(void *to, const void *from, unsigned len);
unsigned long raw_copy_from_guest(void *to, const void *from, unsigned len);
unsigned long raw_clear_guest(void *to, unsigned int len);
@@ -18,6 +22,9 @@ unsigned long raw_clear_guest(void *to, unsigned int len);
#define guest_handle_okay(hnd, nr) (1)
#define guest_handle_subrange_okay(hnd, first, last) (1)
+unsigned long copy_to_guest_phys(struct domain *d, paddr_t gpa, void *buf,
+ unsigned int len);
+
#endif /* ASM__RISCV__GUEST_ACCESS_H */
/*
* Local variables:
--
2.52.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |