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

[Xen-devel] [PATCH v8 4/6] arm/vm_event: get/set registers



Add support for getting/setting registers through vm_event on ARM.
The set of registers can be expanded in the future to include other registers
as well if required. The set is limited to the GPRs, PC, CPSR and TTBR0/1 in
this patch.

Signed-off-by: Tamas K Lengyel <tamas.lengyel@xxxxxxxxxxxx>
Acked-by: Razvan Cojocaru <rcojocaru@xxxxxxxxxxxxxxx>
---
Cc: Stefano Stabellini <sstabellini@xxxxxxxxxx>
Cc: Julien Grall <julien.grall@xxxxxxx>
---
 xen/arch/arm/Makefile          |   1 +
 xen/arch/arm/vm_event.c        | 163 +++++++++++++++++++++++++++++++++++++++++
 xen/include/asm-arm/vm_event.h |  11 ---
 xen/include/asm-x86/vm_event.h |   4 -
 xen/include/public/vm_event.h  |  76 ++++++++++++++++++-
 xen/include/xen/vm_event.h     |   3 +
 6 files changed, 240 insertions(+), 18 deletions(-)
 create mode 100644 xen/arch/arm/vm_event.c

diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index ffb0e96..82ac34c 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -42,6 +42,7 @@ obj-y += processor.o
 obj-y += smc.o
 obj-$(CONFIG_LIVEPATCH) += livepatch.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..0e59fae
--- /dev/null
+++ b/xen/arch/arm/vm_event.c
@@ -0,0 +1,163 @@
+/*
+ * 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 = guest_cpu_user_regs();
+
+    req->data.regs.arm.cpsr = regs->cpsr;
+    req->data.regs.arm.ttbr0 = READ_SYSREG64(TTBR0_EL1);
+    req->data.regs.arm.ttbr1 = READ_SYSREG64(TTBR1_EL1);
+
+    if ( psr_mode_is_32bit(regs->cpsr) )
+    {
+        req->data.regs.arm.arch.arm32.r0 = regs->r0;
+        req->data.regs.arm.arch.arm32.r1 = regs->r1;
+        req->data.regs.arm.arch.arm32.r2 = regs->r2;
+        req->data.regs.arm.arch.arm32.r3 = regs->r3;
+        req->data.regs.arm.arch.arm32.r4 = regs->r4;
+        req->data.regs.arm.arch.arm32.r5 = regs->r5;
+        req->data.regs.arm.arch.arm32.r6 = regs->r6;
+        req->data.regs.arm.arch.arm32.r7 = regs->r7;
+        req->data.regs.arm.arch.arm32.r8 = regs->r8;
+        req->data.regs.arm.arch.arm32.r9 = regs->r9;
+        req->data.regs.arm.arch.arm32.r10 = regs->r10;
+        req->data.regs.arm.arch.arm32.r11 = regs->fp;
+        req->data.regs.arm.arch.arm32.r12 = regs->r12;
+        req->data.regs.arm.arch.arm32.r13 = regs->sp;
+        req->data.regs.arm.arch.arm32.r14 = regs->lr;
+        req->data.regs.arm.arch.arm32.pc = regs->pc32;
+    }
+#ifdef CONFIG_ARM_64
+    else
+    {
+        req->data.regs.arm.arch.arm64.x0 = regs->x0;
+        req->data.regs.arm.arch.arm64.x1 = regs->x1;
+        req->data.regs.arm.arch.arm64.x2 = regs->x2;
+        req->data.regs.arm.arch.arm64.x3 = regs->x3;
+        req->data.regs.arm.arch.arm64.x4 = regs->x4;
+        req->data.regs.arm.arch.arm64.x5 = regs->x5;
+        req->data.regs.arm.arch.arm64.x6 = regs->x6;
+        req->data.regs.arm.arch.arm64.x7 = regs->x7;
+        req->data.regs.arm.arch.arm64.x8 = regs->x8;
+        req->data.regs.arm.arch.arm64.x9 = regs->x9;
+        req->data.regs.arm.arch.arm64.x10 = regs->x10;
+        req->data.regs.arm.arch.arm64.x11 = regs->x11;
+        req->data.regs.arm.arch.arm64.x12 = regs->x12;
+        req->data.regs.arm.arch.arm64.x13 = regs->x13;
+        req->data.regs.arm.arch.arm64.x14 = regs->x14;
+        req->data.regs.arm.arch.arm64.x15 = regs->x15;
+        req->data.regs.arm.arch.arm64.x16 = regs->x16;
+        req->data.regs.arm.arch.arm64.x17 = regs->x17;
+        req->data.regs.arm.arch.arm64.x18 = regs->x18;
+        req->data.regs.arm.arch.arm64.x19 = regs->x19;
+        req->data.regs.arm.arch.arm64.x20 = regs->x20;
+        req->data.regs.arm.arch.arm64.x21 = regs->x21;
+        req->data.regs.arm.arch.arm64.x22 = regs->x22;
+        req->data.regs.arm.arch.arm64.x23 = regs->x23;
+        req->data.regs.arm.arch.arm64.x24 = regs->x24;
+        req->data.regs.arm.arch.arm64.x25 = regs->x25;
+        req->data.regs.arm.arch.arm64.x26 = regs->x26;
+        req->data.regs.arm.arch.arm64.x27 = regs->x27;
+        req->data.regs.arm.arch.arm64.x28 = regs->x28;
+        req->data.regs.arm.arch.arm64.x29 = regs->fp;
+        req->data.regs.arm.arch.arm64.x30 = regs->lr;
+        req->data.regs.arm.arch.arm64.pc = regs->pc;
+    }
+#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;
+
+    regs->cpsr = rsp->data.regs.arm.cpsr;
+    v->arch.ttbr0 = rsp->data.regs.arm.ttbr0;
+    v->arch.ttbr1 = rsp->data.regs.arm.ttbr1;
+
+    if ( psr_mode_is_32bit(regs->cpsr) )
+    {
+        regs->r0 = rsp->data.regs.arm.arch.arm32.r0;
+        regs->r1 = rsp->data.regs.arm.arch.arm32.r1;
+        regs->r2 = rsp->data.regs.arm.arch.arm32.r2;
+        regs->r3 = rsp->data.regs.arm.arch.arm32.r3;
+        regs->r4 = rsp->data.regs.arm.arch.arm32.r4;
+        regs->r5 = rsp->data.regs.arm.arch.arm32.r5;
+        regs->r6 = rsp->data.regs.arm.arch.arm32.r6;
+        regs->r7 = rsp->data.regs.arm.arch.arm32.r7;
+        regs->r8 = rsp->data.regs.arm.arch.arm32.r8;
+        regs->r9 = rsp->data.regs.arm.arch.arm32.r9;
+        regs->r10 = rsp->data.regs.arm.arch.arm32.r10;
+        regs->fp = rsp->data.regs.arm.arch.arm32.r11;
+        regs->r12 = rsp->data.regs.arm.arch.arm32.r12;
+        regs->sp = rsp->data.regs.arm.arch.arm32.r13;
+        regs->lr = rsp->data.regs.arm.arch.arm32.r14;
+        regs->pc32 = rsp->data.regs.arm.arch.arm32.pc;
+    }
+#ifdef CONFIG_ARM_64
+    else
+    {
+        regs->x0 = rsp->data.regs.arm.arch.arm64.x0;
+        regs->x1 = rsp->data.regs.arm.arch.arm64.x1;
+        regs->x2 = rsp->data.regs.arm.arch.arm64.x2;
+        regs->x3 = rsp->data.regs.arm.arch.arm64.x3;
+        regs->x4 = rsp->data.regs.arm.arch.arm64.x4;
+        regs->x5 = rsp->data.regs.arm.arch.arm64.x5;
+        regs->x6 = rsp->data.regs.arm.arch.arm64.x6;
+        regs->x7 = rsp->data.regs.arm.arch.arm64.x7;
+        regs->x8 = rsp->data.regs.arm.arch.arm64.x8;
+        regs->x9 = rsp->data.regs.arm.arch.arm64.x9;
+        regs->x10 = rsp->data.regs.arm.arch.arm64.x10;
+        regs->x11 = rsp->data.regs.arm.arch.arm64.x11;
+        regs->x12 = rsp->data.regs.arm.arch.arm64.x12;
+        regs->x13 = rsp->data.regs.arm.arch.arm64.x13;
+        regs->x14 = rsp->data.regs.arm.arch.arm64.x14;
+        regs->x15 = rsp->data.regs.arm.arch.arm64.x15;
+        regs->x16 = rsp->data.regs.arm.arch.arm64.x16;
+        regs->x17 = rsp->data.regs.arm.arch.arm64.x17;
+        regs->x18 = rsp->data.regs.arm.arch.arm64.x18;
+        regs->x19 = rsp->data.regs.arm.arch.arm64.x19;
+        regs->x20 = rsp->data.regs.arm.arch.arm64.x20;
+        regs->x21 = rsp->data.regs.arm.arch.arm64.x21;
+        regs->x22 = rsp->data.regs.arm.arch.arm64.x22;
+        regs->x23 = rsp->data.regs.arm.arch.arm64.x23;
+        regs->x24 = rsp->data.regs.arm.arch.arm64.x24;
+        regs->x25 = rsp->data.regs.arm.arch.arm64.x25;
+        regs->x26 = rsp->data.regs.arm.arch.arm64.x26;
+        regs->x27 = rsp->data.regs.arm.arch.arm64.x27;
+        regs->x28 = rsp->data.regs.arm.arch.arm64.x28;
+        regs->fp = rsp->data.regs.arm.arch.arm64.x29;
+        regs->lr = rsp->data.regs.arm.arch.arm64.x30;
+        regs->pc = rsp->data.regs.arm.arch.arm64.pc;
+    }
+#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..a4922b3 100644
--- a/xen/include/asm-arm/vm_event.h
+++ b/xen/include/asm-arm/vm_event.h
@@ -48,15 +48,4 @@ 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. */
-}
-
-static inline void vm_event_fill_regs(vm_event_request_t *req)
-{
-    /* Not supported on ARM. */
-}
-
 #endif /* __ASM_ARM_VM_EVENT_H__ */
diff --git a/xen/include/asm-x86/vm_event.h b/xen/include/asm-x86/vm_event.h
index 026f42e..cf2077c 100644
--- a/xen/include/asm-x86/vm_event.h
+++ b/xen/include/asm-x86/vm_event.h
@@ -40,8 +40,4 @@ void vm_event_toggle_singlestep(struct domain *d, struct vcpu 
*v);
 
 void vm_event_register_write_resume(struct vcpu *v, vm_event_response_t *rsp);
 
-void vm_event_set_registers(struct vcpu *v, vm_event_response_t *rsp);
-
-void vm_event_fill_regs(vm_event_request_t *req);
-
 #endif /* __ASM_X86_VM_EVENT_H__ */
diff --git a/xen/include/public/vm_event.h b/xen/include/public/vm_event.h
index 66e27b7..d3b0c4d 100644
--- a/xen/include/public/vm_event.h
+++ b/xen/include/public/vm_event.h
@@ -132,8 +132,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;
@@ -171,6 +171,71 @@ struct vm_event_regs_x86 {
     uint32_t _pad;
 };
 
+struct vm_event_regs_arm32 {
+    uint32_t r0;
+    uint32_t r1;
+    uint32_t r2;
+    uint32_t r3;
+    uint32_t r4;
+    uint32_t r5;
+    uint32_t r6;
+    uint32_t r7;
+    uint32_t r8;
+    uint32_t r9;
+    uint32_t r10;
+    uint32_t r11;
+    uint32_t r12;
+    uint32_t r13;
+    uint32_t r14;
+    uint32_t pc;
+};
+
+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 x11;
+    uint64_t x12;
+    uint64_t x13;
+    uint64_t x14;
+    uint64_t x15;
+    uint64_t x16;
+    uint64_t x17;
+    uint64_t x18;
+    uint64_t x19;
+    uint64_t x20;
+    uint64_t x21;
+    uint64_t x22;
+    uint64_t x23;
+    uint64_t x24;
+    uint64_t x25;
+    uint64_t x26;
+    uint64_t x27;
+    uint64_t x28;
+    uint64_t x29;
+    uint64_t x30;
+    uint64_t pc;
+};
+
+struct vm_event_regs_arm {
+    uint32_t cpsr; /* PSR_MODE_BIT is set iff arm32 is used below */
+    uint32_t _pad;
+    uint64_t ttbr0;
+    uint64_t ttbr1;
+    union {
+        struct vm_event_regs_arm32 arm32;
+        struct vm_event_regs_arm64 arm64;
+    } arch;
+};
+
 /*
  * mem_access flag definitions
  *
@@ -246,10 +311,14 @@ struct vm_event_sharing {
     uint32_t _pad;
 };
 
+#define VM_EVENT_MAX_DATA_SIZE \
+    (sizeof(struct vm_event_regs_x86) > sizeof(struct vm_event_regs_arm) ? \
+        sizeof(struct vm_event_regs_x86) : sizeof(struct vm_event_regs_arm))
+
 struct vm_event_emul_read_data {
     uint32_t size;
     /* The struct is used in a union with vm_event_regs_x86. */
-    uint8_t  data[sizeof(struct vm_event_regs_x86) - sizeof(uint32_t)];
+    uint8_t  data[VM_EVENT_MAX_DATA_SIZE - sizeof(uint32_t)];
 };
 
 typedef struct vm_event_st {
@@ -275,6 +344,7 @@ typedef struct vm_event_st {
     union {
         union {
             struct vm_event_regs_x86 x86;
+            struct vm_event_regs_arm arm;
         } regs;
 
         struct vm_event_emul_read_data emul_read_data;
diff --git a/xen/include/xen/vm_event.h b/xen/include/xen/vm_event.h
index 42bd9f6..95420f8 100644
--- a/xen/include/xen/vm_event.h
+++ b/xen/include/xen/vm_event.h
@@ -75,6 +75,9 @@ int vm_event_domctl(struct domain *d, 
xen_domctl_vm_event_op_t *vec,
 void vm_event_vcpu_pause(struct vcpu *v);
 void vm_event_vcpu_unpause(struct vcpu *v);
 
+void vm_event_fill_regs(vm_event_request_t *req);
+void vm_event_set_registers(struct vcpu *v, vm_event_response_t *rsp);
+
 #endif /* __VM_EVENT_H__ */
 
 
-- 
2.8.1


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

 


Rackspace

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