mirror of
https://github.com/xen-project/xen.git
synced 2026-10-30 03:00:05 +01:00
arm/vm_event: get/set registers
Add support for getting/setting registers through vm_event on ARM. Only TTB/CR/R0/R1, PC and CPSR are sent as part of a request and only PC is set as part of a response. The set of registers can be expanded in the future to include other registers as well if necessary. Signed-off-by: Tamas K Lengyel <tamas.lengyel@zentific.com> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com> Acked-by: Razvan Cojocaru <rcojocaru@bitdefender.com> Acked-by: Stefano Stabellini <sstabellini@kernel.org>
This commit is contained in:
1 parent
8a085e9d94
commit
a3fe74e434
6 files changed
+72
-17
No files matched your search
@@ -43,6 +43,7 @@ obj-y += traps.o
|
||||
obj-y += vgic.o
|
||||
obj-y += vgic-v2.o
|
||||
obj-$(CONFIG_ARM_64) += vgic-v3.o
|
||||
obj-y += vm_event.o
|
||||
obj-y += vtimer.o
|
||||
obj-y += vpsci.o
|
||||
obj-y += vuart.o
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* arch/arm/vm_event.c
|
||||
*
|
||||
* Architecture-specific vm_event handling routines
|
||||
*
|
||||
* Copyright (c) 2016 Tamas K Lengyel (tamas.lengyel@zentific.com)
|
||||
*
|
||||
* 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.pc = regs->pc;
|
||||
req->data.regs.arm.ttbcr = READ_SYSREG(TCR_EL1);
|
||||
req->data.regs.arm.ttbr0 = READ_SYSREG64(TTBR0_EL1);
|
||||
req->data.regs.arm.ttbr1 = READ_SYSREG64(TTBR1_EL1);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/* vCPU should be paused */
|
||||
ASSERT(atomic_read(&v->vm_event_pause_count));
|
||||
|
||||
regs->pc = rsp->data.regs.arm.pc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-file-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -45,15 +45,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__ */
|
||||
@@ -39,8 +39,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__ */
|
||||
@@ -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,19 @@ struct vm_event_regs_x86 {
|
||||
uint32_t _pad;
|
||||
};
|
||||
|
||||
/*
|
||||
* Only the register 'pc' can be set on a vm_event response using the
|
||||
* VM_EVENT_FLAG_SET_REGISTERS flag.
|
||||
*/
|
||||
struct vm_event_regs_arm {
|
||||
uint64_t ttbr0;
|
||||
uint64_t ttbr1;
|
||||
uint64_t ttbcr;
|
||||
uint64_t pc;
|
||||
uint32_t cpsr;
|
||||
uint32_t _pad;
|
||||
};
|
||||
|
||||
/*
|
||||
* mem_access flag definitions
|
||||
*
|
||||
@@ -275,6 +288,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;
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
/*
|
||||
|
||||