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:

https://github.com/xen-project/xen/blob/95d9ab46143685f169f636cfdd7997e2fc630e86/tools/libs/ctrl/xc_domain.c

/**
 * 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;
}

🌱 Back to Garden