[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v3 4/9] arm/vm_event: get/set registers



Add support for getting/setting registers through vm_event on ARM.

Signed-off-by: Tamas K Lengyel <tamas@xxxxxxxxxxxxx>
---
Cc: Stefano Stabellini <sstabellini@xxxxxxxxxx>
Cc: Julien Grall <julien.grall@xxxxxxx>
Cc: Razvan Cojocaru <rcojocaru@xxxxxxxxxxxxxxx>
---
 xen/arch/arm/Makefile          |   1 +
 xen/arch/arm/vm_event.c        | 141 +++++++++++++++++++++++++++++++++++++++++
 xen/include/asm-arm/vm_event.h |  13 ++--
 xen/include/public/vm_event.h  |  54 +++++++++++++++-
 4 files changed, 198 insertions(+), 11 deletions(-)
 create mode 100644 xen/arch/arm/vm_event.c

diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 6e3dcff..118be99 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -41,6 +41,7 @@ obj-y += decode.o
 obj-y += processor.o
 obj-y += smc.o
 obj-y += monitor.o
+obj-y += vm_event.o
 
 #obj-bin-y += ....o
 
diff --git a/xen/arch/arm/vm_event.c b/xen/arch/arm/vm_event.c
new file mode 100644
index 0000000..59962c7
--- /dev/null
+++ b/xen/arch/arm/vm_event.c
@@ -0,0 +1,141 @@
+/*
+ * arch/arm/vm_event.c
+ *
+ * Architecture-specific vm_event handling routines
+ *
+ * Copyright (c) 2016 Tamas K Lengyel (tamas@xxxxxxxxxxxxx)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License v2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <xen/sched.h>
+#include <asm/vm_event.h>
+
+void vm_event_fill_regs(vm_event_request_t *req,
+                        const struct cpu_user_regs *regs,
+                        struct domain *d)
+{
+    if ( is_32bit_domain(d) )
+    {
+        req->data.regs.arm32.r0_usr = regs->r0;
+        req->data.regs.arm32.r1_usr = regs->r1;
+        req->data.regs.arm32.r2_usr = regs->r2;
+        req->data.regs.arm32.r3_usr = regs->r3;
+        req->data.regs.arm32.r4_usr = regs->r4;
+        req->data.regs.arm32.r5_usr = regs->r5;
+        req->data.regs.arm32.r6_usr = regs->r6;
+        req->data.regs.arm32.r7_usr = regs->r7;
+        req->data.regs.arm32.r8_usr = regs->r8;
+        req->data.regs.arm32.r9_usr = regs->r9;
+        req->data.regs.arm32.r10_usr = regs->r10;
+        req->data.regs.arm32.r12_usr = regs->r12;
+        req->data.regs.arm32.pc = regs->pc32;
+        req->data.regs.arm32.sp_usr = regs->sp_usr;
+        req->data.regs.arm32.sp_svc = regs->sp_svc;
+        req->data.regs.arm32.fp = regs->fp;
+        req->data.regs.arm32.lr_usr = regs->lr_usr;
+        req->data.regs.arm32.cpsr = regs->cpsr;
+        req->data.regs.arm32.spsr_svc = regs->spsr_svc;
+        req->data.regs.arm32.ttbr0 = READ_SYSREG64(TTBR0_EL1);
+        req->data.regs.arm32.ttbr1 = READ_SYSREG64(TTBR1_EL1);
+    }
+#ifdef CONFIG_ARM_64
+    else
+    {
+        req->data.regs.arm64.x0 = regs->x0;
+        req->data.regs.arm64.x1 = regs->x1;
+        req->data.regs.arm64.x2 = regs->x2;
+        req->data.regs.arm64.x3 = regs->x3;
+        req->data.regs.arm64.x4 = regs->x4;
+        req->data.regs.arm64.x5 = regs->x5;
+        req->data.regs.arm64.x6 = regs->x6;
+        req->data.regs.arm64.x7 = regs->x7;
+        req->data.regs.arm64.x8 = regs->x8;
+        req->data.regs.arm64.x9 = regs->x9;
+        req->data.regs.arm64.x10 = regs->x10;
+        req->data.regs.arm64.x16 = regs->x16;
+        req->data.regs.arm64.pc = regs->pc;
+        req->data.regs.arm64.sp_el0 = regs->sp_el0;
+        req->data.regs.arm64.sp_el1 = regs->sp_el1;
+        req->data.regs.arm64.fp = regs->fp;
+        req->data.regs.arm64.lr = regs->lr;
+        req->data.regs.arm64.cpsr = regs->cpsr;
+        req->data.regs.arm64.spsr_el1 = regs->spsr_svc;
+        req->data.regs.arm64.ttbr0 = READ_SYSREG64(TTBR0_EL1);
+        req->data.regs.arm64.ttbr1 = READ_SYSREG64(TTBR1_EL1);
+    }
+#endif
+}
+
+void vm_event_set_registers(struct vcpu *v, vm_event_response_t *rsp)
+{
+    struct cpu_user_regs *regs = &v->arch.cpu_info->guest_cpu_user_regs;
+
+    if ( is_32bit_domain(v->domain) )
+    {
+        regs->r0 = rsp->data.regs.arm32.r0_usr;
+        regs->r1 = rsp->data.regs.arm32.r1_usr;
+        regs->r2 = rsp->data.regs.arm32.r2_usr;
+        regs->r3 = rsp->data.regs.arm32.r3_usr;
+        regs->r4 = rsp->data.regs.arm32.r4_usr;
+        regs->r5 = rsp->data.regs.arm32.r5_usr;
+        regs->r6 = rsp->data.regs.arm32.r6_usr;
+        regs->r7 = rsp->data.regs.arm32.r7_usr;
+        regs->r8 = rsp->data.regs.arm32.r8_usr;
+        regs->r9 = rsp->data.regs.arm32.r9_usr;
+        regs->r10 = rsp->data.regs.arm32.r10_usr;
+        regs->r12 = rsp->data.regs.arm32.r12_usr;
+        regs->pc32 = rsp->data.regs.arm32.pc;
+        regs->sp_usr = rsp->data.regs.arm32.sp_usr;
+        regs->sp_svc = rsp->data.regs.arm32.sp_svc;
+        regs->fp = rsp->data.regs.arm32.fp;
+        regs->lr_usr = rsp->data.regs.arm32.lr_usr;
+        regs->cpsr = rsp->data.regs.arm32.cpsr;
+        v->arch.ttbr0 = rsp->data.regs.arm32.ttbr0;
+        v->arch.ttbr1 = rsp->data.regs.arm32.ttbr1;
+    }
+#ifdef CONFIG_ARM_64
+    else
+    {
+        regs->x0 = rsp->data.regs.arm64.x0;
+        regs->x1 = rsp->data.regs.arm64.x1;
+        regs->x2 = rsp->data.regs.arm64.x2;
+        regs->x3 = rsp->data.regs.arm64.x3;
+        regs->x4 = rsp->data.regs.arm64.x4;
+        regs->x5 = rsp->data.regs.arm64.x5;
+        regs->x6 = rsp->data.regs.arm64.x6;
+        regs->x7 = rsp->data.regs.arm64.x7;
+        regs->x8 = rsp->data.regs.arm64.x8;
+        regs->x9 = rsp->data.regs.arm64.x9;
+        regs->x10 = rsp->data.regs.arm64.x10;
+        regs->x16 = rsp->data.regs.arm64.x16;
+        regs->pc = rsp->data.regs.arm64.pc;
+        regs->sp_el0 = rsp->data.regs.arm64.sp_el0;
+        regs->sp_el1 = rsp->data.regs.arm64.sp_el1;
+        regs->fp = rsp->data.regs.arm64.fp;
+        regs->lr = rsp->data.regs.arm64.lr;
+        regs->cpsr = rsp->data.regs.arm64.cpsr;
+        v->arch.ttbr0 = rsp->data.regs.arm64.ttbr0;
+        v->arch.ttbr1 = rsp->data.regs.arm64.ttbr1;
+    }
+#endif
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-arm/vm_event.h b/xen/include/asm-arm/vm_event.h
index a3fc4ce..814d0da 100644
--- a/xen/include/asm-arm/vm_event.h
+++ b/xen/include/asm-arm/vm_event.h
@@ -48,15 +48,10 @@ void vm_event_register_write_resume(struct vcpu *v, 
vm_event_response_t *rsp)
     /* Not supported on ARM. */
 }
 
-static inline
-void vm_event_set_registers(struct vcpu *v, vm_event_response_t *rsp)
-{
-    /* Not supported on ARM. */
-}
+void vm_event_set_registers(struct vcpu *v, vm_event_response_t *rsp);
 
-static inline void vm_event_fill_regs(vm_event_request_t *req)
-{
-    /* Not supported on ARM. */
-}
+void vm_event_fill_regs(vm_event_request_t *req,
+                        const struct cpu_user_regs *regs,
+                        struct domain *d);
 
 #endif /* __ASM_ARM_VM_EVENT_H__ */
diff --git a/xen/include/public/vm_event.h b/xen/include/public/vm_event.h
index 3acf217..fabeee8 100644
--- a/xen/include/public/vm_event.h
+++ b/xen/include/public/vm_event.h
@@ -129,8 +129,8 @@
 #define VM_EVENT_X86_XCR0   3
 
 /*
- * Using a custom struct (not hvm_hw_cpu) so as to not fill
- * the vm_event ring buffer too quickly.
+ * Using custom vCPU structs (i.e. not hvm_hw_cpu) for both x86 and ARM
+ * so as to not fill the vm_event ring buffer too quickly.
  */
 struct vm_event_regs_x86 {
     uint64_t rax;
@@ -168,6 +168,54 @@ struct vm_event_regs_x86 {
     uint32_t _pad;
 };
 
+struct vm_event_regs_arm32 {
+    uint32_t r0_usr;
+    uint32_t r1_usr;
+    uint32_t r2_usr;
+    uint32_t r3_usr;
+    uint32_t r4_usr;
+    uint32_t r5_usr;
+    uint32_t r6_usr;
+    uint32_t r7_usr;
+    uint32_t r8_usr;
+    uint32_t r9_usr;
+    uint32_t r10_usr;
+    uint32_t r12_usr;
+    uint32_t lr_usr;
+    uint32_t sp_usr;
+    uint32_t sp_svc;
+    uint32_t spsr_svc;
+    uint32_t fp;
+    uint32_t pc;
+    uint32_t cpsr;
+    uint32_t ttbr0;
+    uint32_t ttbr1;
+};
+
+struct vm_event_regs_arm64 {
+    uint64_t x0;
+    uint64_t x1;
+    uint64_t x2;
+    uint64_t x3;
+    uint64_t x4;
+    uint64_t x5;
+    uint64_t x6;
+    uint64_t x7;
+    uint64_t x8;
+    uint64_t x9;
+    uint64_t x10;
+    uint64_t x16;
+    uint64_t lr;
+    uint64_t sp_el0;
+    uint64_t sp_el1;
+    uint32_t spsr_el1;
+    uint64_t fp;
+    uint64_t pc;
+    uint32_t cpsr;
+    uint64_t ttbr0;
+    uint64_t ttbr1;
+};
+
 /*
  * mem_access flag definitions
  *
@@ -256,6 +304,8 @@ typedef struct vm_event_st {
     union {
         union {
             struct vm_event_regs_x86 x86;
+            struct vm_event_regs_arm32 arm32;
+            struct vm_event_regs_arm64 arm64;
         } regs;
 
         struct vm_event_emul_read_data emul_read_data;
-- 
2.8.1


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.