static inline status_t
driver_get_vcpureg(
vmi_instance_t vmi,
uint64_t *value,
reg_t reg,
unsigned long vcpu)
{
#ifdef ENABLE_SAFETY_CHECKS
if (!vmi->driver.initialized || !vmi->driver.get_vcpureg_ptr) {
dbprint(VMI_DEBUG_DRIVER, "WARNING: driver_get_vcpureg function not implemented.\n");
return VMI_FAILURE;
}
#endif
return vmi->driver.get_vcpureg_ptr(vmi, value, reg, vcpu);
}driver.get_vcpureg_ptr = &xen_get_vcpureg;status_t
xen_get_vcpureg(
vmi_instance_t vmi,
uint64_t *value,
reg_t reg,
unsigned long vcpu)
{
#if defined(ARM32) || defined(ARM64)
return xen_get_vcpureg_arm(vmi, value, reg, vcpu);
#elif defined(I386) || defined (X86_64)
if (vmi->vm_type == HVM)
return xen_get_vcpureg_hvm (vmi, value, reg, vcpu);
else {
if (vmi->vm_type == PV64)
return xen_get_vcpureg_pv64(vmi, value, reg, vcpu);
else if (vmi->vm_type == PV32)
return xen_get_vcpureg_pv32(vmi, value, reg, vcpu);
}
return VMI_FAILURE;
#endif
}#if defined(ARM32) || defined(ARM64)
static status_t
xen_get_vcpureg_arm(
vmi_instance_t vmi,
uint64_t *value,
reg_t reg,
unsigned long vcpu)
{
vcpu_guest_context_any_t ctx;
xen_instance_t *xen = xen_get_instance(vmi);
if (xen->libxcw.xc_vcpu_getcontext(xen->xchandle, xen->domainid, vcpu, &ctx)) {
errprint("Failed to get context information (ARM domain).\n");
return VMI_FAILURE;
}
/* Xen overlays 64-bit registers to the 32-bit ones */
switch (reg) {
case SCTLR:
*value = ctx.c.sctlr;
break;
case TTBCR:
*value = ctx.c.ttbcr;
break;
case TTBR0:
*value = ctx.c.ttbr0;
break;
case TTBR1:
*value = ctx.c.ttbr1;
break;
case CPSR:
*value = ctx.c.user_regs.cpsr;
break;
case R0:
*value = ctx.c.user_regs.r0_usr;
break;
case R1:
*value = ctx.c.user_regs.r1_usr;
break;
case R2:
*value = ctx.c.user_regs.r2_usr;
break;
case R3:
*value = ctx.c.user_regs.r3_usr;
break;
case R4:
*value = ctx.c.user_regs.r4_usr;
break;
case R5:
*value = ctx.c.user_regs.r5_usr;
break;
case R6:
*value = ctx.c.user_regs.r6_usr;
break;
case R7:
*value = ctx.c.user_regs.r7_usr;
break;
case R8:
*value = ctx.c.user_regs.r8_usr;
break;
case R9:
*value = ctx.c.user_regs.r9_usr;
break;
case R10:
*value = ctx.c.user_regs.r10_usr;
break;
case R11:
*value = ctx.c.user_regs.r11_usr;
break;
case R12:
*value = ctx.c.user_regs.r12_usr;
break;
case SP_USR:
*value = ctx.c.user_regs.sp_usr;
break;
case LR_USR:
*value = ctx.c.user_regs.lr_usr;
break;
case LR_IRQ:
*value = ctx.c.user_regs.lr_irq;
break;
case SP_IRQ:
*value = ctx.c.user_regs.sp_irq;
break;
case LR_SVC:
*value = ctx.c.user_regs.lr_svc;
break;
case SP_SVC:
*value = ctx.c.user_regs.sp_svc;
break;
case LR_ABT:
*value = ctx.c.user_regs.lr_abt;
break;
case SP_ABT:
*value = ctx.c.user_regs.sp_abt;
break;
case LR_UND:
*value = ctx.c.user_regs.lr_und;
break;
case SP_UND:
*value = ctx.c.user_regs.sp_und;
break;
case R8_FIQ:
*value = ctx.c.user_regs.r8_fiq;
break;
case R9_FIQ:
*value = ctx.c.user_regs.r9_fiq;
break;
case R10_FIQ:
*value = ctx.c.user_regs.r10_fiq;
break;
case R11_FIQ:
*value = ctx.c.user_regs.r11_fiq;
break;
case R12_FIQ:
*value = ctx.c.user_regs.r12_fiq;
break;
case SP_FIQ:
*value = ctx.c.user_regs.sp_fiq;
break;
case LR_FIQ:
*value = ctx.c.user_regs.lr_fiq;
break;
case PC:
*value = ctx.c.user_regs.pc32;
break;
case SPSR_SVC:
*value = ctx.c.user_regs.spsr_svc;
break;
case SPSR_FIQ:
*value = ctx.c.user_regs.spsr_fiq;
break;
case SPSR_IRQ:
*value = ctx.c.user_regs.spsr_irq;
break;
case SPSR_UND:
*value = ctx.c.user_regs.spsr_und;
break;
case SPSR_ABT:
*value = ctx.c.user_regs.spsr_abt;
break;
case SP_EL0:
*value = ctx.c.user_regs.sp_el0;
break;
case SP_EL1:
*value = ctx.c.user_regs.sp_el1;
break;
case ELR_EL1:
*value = ctx.c.user_regs.elr_el1;
break;
default:
return VMI_FAILURE;
}
return VMI_SUCCESS;
}wrapper->xc_vcpu_getcontext = dlsym(wrapper->handle, "xc_vcpu_getcontext");From:
/**
* This function returns information about the execution context of a
* particular vcpu of a domain.
*
* @parm xch a handle to an open hypervisor interface
* @parm domid the domain to get information from
* @parm vcpu the vcpu number
* @parm ctxt a pointer to a structure to store the execution context of the
* domain
* @return 0 on success, -1 on failure
*/
int xc_vcpu_getcontext(xc_interface *xch,
uint32_t domid,
uint32_t vcpu,
vcpu_guest_context_any_t *ctxt)
{
int rc;
DECLARE_DOMCTL;
DECLARE_HYPERCALL_BOUNCE(ctxt, sizeof(vcpu_guest_context_any_t), XC_HYPERCALL_BUFFER_BOUNCE_OUT);
if ( xc_hypercall_bounce_pre(xch, ctxt) )
return -1;
domctl.cmd = XEN_DOMCTL_getvcpucontext;
domctl.domain = domid;
domctl.u.vcpucontext.vcpu = (uint16_t)vcpu;
set_xen_guest_handle(domctl.u.vcpucontext.ctxt, ctxt);
rc = do_domctl(xch, &domctl);
xc_hypercall_bounce_post(xch, ctxt);
return rc;
}