[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v5 6/9] 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@xxxxxxxxxxxxx> Acked-by: Razvan Cojocaru <rcojocaru@xxxxxxxxxxxxxxx> --- Cc: Stefano Stabellini <sstabellini@xxxxxxxxxx> Cc: Julien Grall <julien.grall@xxxxxxx> v5: Use x29/x30 as names instead of the Xen internal names on 64-bit Transmit all GPRs on 64-bit v4: Use psr mode to determine whether to full 32-bit or 64-bit structs --- xen/arch/arm/Makefile | 1 + xen/arch/arm/vm_event.c | 159 +++++++++++++++++++++++++++++++++++++++++ xen/include/asm-arm/vm_event.h | 11 --- xen/include/asm-x86/vm_event.h | 4 -- xen/include/public/vm_event.h | 74 ++++++++++++++++++- xen/include/xen/vm_event.h | 3 + 6 files changed, 234 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 344d3ad..7d2641c 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_XSPLICE) += xsplice.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..6e92f8b --- /dev/null +++ b/xen/arch/arm/vm_event.c @@ -0,0 +1,159 @@ +/* + * 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.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->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 7976080..31801b2 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,69 @@ 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 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 * @@ -236,10 +299,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 { @@ -264,6 +331,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 89e6243..a5767ab 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); + /* * Monitor vm-events */ -- 2.8.1 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |