Beispiel #1
0
int xc_psr_get_hw_info(xc_interface *xch, uint32_t socket,
                       xc_psr_feat_type type, xc_psr_hw_info *hw_info)
{
    int rc = -1;
    DECLARE_SYSCTL;

    if ( !hw_info )
    {
        errno = EINVAL;
        return rc;
    }

    sysctl.cmd = XEN_SYSCTL_psr_alloc;
    sysctl.u.psr_alloc.target = socket;

    switch ( type )
    {
    case XC_PSR_CAT_L2:
    case XC_PSR_CAT_L3:
        sysctl.u.psr_alloc.cmd = (type == XC_PSR_CAT_L2) ?
                                 XEN_SYSCTL_PSR_get_l2_info :
                                 XEN_SYSCTL_PSR_get_l3_info;

        rc = xc_sysctl(xch, &sysctl);
        if ( rc )
            break;

        hw_info->cat.cos_max = sysctl.u.psr_alloc.u.cat_info.cos_max;
        hw_info->cat.cbm_len = sysctl.u.psr_alloc.u.cat_info.cbm_len;
        hw_info->cat.cdp_enabled = (type == XC_PSR_CAT_L2) ?
                                   false :
                                   (sysctl.u.psr_alloc.u.cat_info.flags &
                                    XEN_SYSCTL_PSR_CAT_L3_CDP);

        break;
    case XC_PSR_MBA:
        sysctl.u.psr_alloc.cmd = XEN_SYSCTL_PSR_get_mba_info;
        rc = xc_sysctl(xch, &sysctl);
        if ( rc )
            break;

        hw_info->mba.cos_max = sysctl.u.psr_alloc.u.mba_info.cos_max;
        hw_info->mba.thrtl_max = sysctl.u.psr_alloc.u.mba_info.thrtl_max;
        hw_info->mba.linear = sysctl.u.psr_alloc.u.mba_info.flags &
                              XEN_SYSCTL_PSR_MBA_LINEAR;

        break;
    default:
        errno = EOPNOTSUPP;
        break;
    }

    return rc;
}
Beispiel #2
0
int main(int argc, char * argv[])
{
    struct xen_sysctl sysctl;
    int ret;

    xc_interface *xc_handle = xc_interface_open(0,0,0);
    sysctl.cmd = XEN_SYSCTL_tbuf_op;
    sysctl.interface_version = XEN_SYSCTL_INTERFACE_VERSION;
    sysctl.u.tbuf_op.cmd  = XEN_SYSCTL_TBUFOP_get_info;
    ret = xc_sysctl(xc_handle, &sysctl);
    if ( ret != 0 )
    {
        perror("Failure to get event mask from Xen");
        exit(1);
    }
    else
    {
        printf("Current event mask: 0x%.8x\n", sysctl.u.tbuf_op.evt_mask);
    }

    sysctl.cmd = XEN_SYSCTL_tbuf_op;
    sysctl.interface_version = XEN_SYSCTL_INTERFACE_VERSION;
    sysctl.u.tbuf_op.cmd  = XEN_SYSCTL_TBUFOP_set_evt_mask;
    sysctl.u.tbuf_op.evt_mask = XENMON;

    ret = xc_sysctl(xc_handle, &sysctl);
    printf("Setting mask to 0x%.8x\n", sysctl.u.tbuf_op.evt_mask);
    if ( ret != 0 )
    {
        perror("Failure to get scheduler ID from Xen");
        exit(1);
    }

    sysctl.cmd = XEN_SYSCTL_tbuf_op;
    sysctl.interface_version = XEN_SYSCTL_INTERFACE_VERSION;
    sysctl.u.tbuf_op.cmd  = XEN_SYSCTL_TBUFOP_get_info;
    ret = xc_sysctl(xc_handle, &sysctl);
    if ( ret != 0 )
    {
        perror("Failure to get event mask from Xen");
        exit(1);
    }
    else
    {
        printf("Current event mask: 0x%.8x\n", sysctl.u.tbuf_op.evt_mask);
    }
    xc_interface_close(xc_handle);
    return 0;
}
Beispiel #3
0
int xc_domain_getinfolist(xc_interface *xch,
                          uint32_t first_domain,
                          unsigned int max_domains,
                          xc_domaininfo_t *info)
{
    int ret = 0;
    DECLARE_SYSCTL;
    DECLARE_HYPERCALL_BOUNCE(info, max_domains*sizeof(*info), XC_HYPERCALL_BUFFER_BOUNCE_OUT);

    if ( xc_hypercall_bounce_pre(xch, info) )
        return -1;

    sysctl.cmd = XEN_SYSCTL_getdomaininfolist;
    sysctl.u.getdomaininfolist.first_domain = first_domain;
    sysctl.u.getdomaininfolist.max_domains  = max_domains;
    set_xen_guest_handle(sysctl.u.getdomaininfolist.buffer, info);

    if ( xc_sysctl(xch, &sysctl) < 0 )
        ret = -1;
    else
        ret = sysctl.u.getdomaininfolist.num_domains;

    xc_hypercall_bounce_post(xch, info);

    return ret;
}
Beispiel #4
0
int xc_tbuf_get_size(int xc_handle, unsigned long *size)
{
    struct t_info *t_info;
    int rc;
    DECLARE_SYSCTL;

    sysctl.cmd = XEN_SYSCTL_tbuf_op;
    sysctl.interface_version = XEN_SYSCTL_INTERFACE_VERSION;
    sysctl.u.tbuf_op.cmd  = XEN_SYSCTL_TBUFOP_get_info;

    rc = xc_sysctl(xc_handle, &sysctl);
    if ( rc != 0 )
        return rc;

    t_info = xc_map_foreign_range(xc_handle, DOMID_XEN,
                    sysctl.u.tbuf_op.size, PROT_READ | PROT_WRITE,
                    sysctl.u.tbuf_op.buffer_mfn);

    if ( t_info == NULL || t_info->tbuf_size == 0 )
        return -1;

    *size = t_info->tbuf_size;

    return 0;
}
Beispiel #5
0
int xc_psr_cmt_get_l3_cache_size(xc_interface *xch, uint32_t cpu,
                                 uint32_t *l3_cache_size)
{
    static int val = 0;
    int rc;
    DECLARE_SYSCTL;

    if ( val )
    {
        *l3_cache_size = val;
        return 0;
    }

    sysctl.cmd = XEN_SYSCTL_psr_cmt_op;
    sysctl.u.psr_cmt_op.cmd =
        XEN_SYSCTL_PSR_CMT_get_l3_cache_size;
    sysctl.u.psr_cmt_op.flags = 0;
    sysctl.u.psr_cmt_op.u.l3_cache.cpu = cpu;

    rc = xc_sysctl(xch, &sysctl);
    if ( !rc )
        val = *l3_cache_size= sysctl.u.psr_cmt_op.u.data;

    return rc;
}
Beispiel #6
0
int xc_domain_getinfolist(int xc_handle,
                          uint32_t first_domain,
                          unsigned int max_domains,
                          xc_domaininfo_t *info)
{
    int ret = 0;
    DECLARE_SYSCTL;

    if ( lock_pages(info, max_domains*sizeof(xc_domaininfo_t)) != 0 )
        return -1;

    sysctl.cmd = XEN_SYSCTL_getdomaininfolist;
    sysctl.u.getdomaininfolist.first_domain = first_domain;
    sysctl.u.getdomaininfolist.max_domains  = max_domains;
    set_xen_guest_handle(sysctl.u.getdomaininfolist.buffer, info);

    if ( xc_sysctl(xc_handle, &sysctl) < 0 )
        ret = -1;
    else
        ret = sysctl.u.getdomaininfolist.num_domains;

    unlock_pages(info, max_domains*sizeof(xc_domaininfo_t));

    return ret;
}
Beispiel #7
0
int xc_tbuf_enable(xc_interface *xch, unsigned long pages, unsigned long *mfn,
                   unsigned long *size)
{
    DECLARE_SYSCTL;
    int rc;

    /*
     * Ignore errors (at least for now) as we get an error if size is already
     * set (since trace buffers cannot be reallocated). If we really have no
     * buffers at all then tbuf_enable() will fail, so this is safe.
     */
    (void)xc_tbuf_set_size(xch, pages);

    if ( tbuf_enable(xch, 1) != 0 )
        return -1;

    sysctl.cmd = XEN_SYSCTL_tbuf_op;
    sysctl.interface_version = XEN_SYSCTL_INTERFACE_VERSION;
    sysctl.u.tbuf_op.cmd  = XEN_SYSCTL_TBUFOP_get_info;

    rc = xc_sysctl(xch, &sysctl);
    if ( rc == 0 )
    {
        *size = sysctl.u.tbuf_op.size;
        *mfn = sysctl.u.tbuf_op.buffer_mfn;
    }

    return 0;
}
Beispiel #8
0
int xc_tbuf_get_size(xc_interface *xch, unsigned long *size)
{
    struct t_info *t_info;
    int rc;
    DECLARE_SYSCTL;

    sysctl.cmd = XEN_SYSCTL_tbuf_op;
    sysctl.interface_version = XEN_SYSCTL_INTERFACE_VERSION;
    sysctl.u.tbuf_op.cmd  = XEN_SYSCTL_TBUFOP_get_info;

    rc = xc_sysctl(xch, &sysctl);
    if ( rc != 0 )
        return rc;

    t_info = xc_map_foreign_range(xch, DOMID_XEN,
                    sysctl.u.tbuf_op.size, PROT_READ | PROT_WRITE,
                    sysctl.u.tbuf_op.buffer_mfn);

    if ( t_info == NULL || t_info->tbuf_size == 0 )
        rc = -1;
    else
	*size = t_info->tbuf_size;

    xenforeignmemory_unmap(xch->fmem, t_info, sysctl.u.tbuf_op.size);

    return rc;
}
Beispiel #9
0
Datei: xc_pm.c Projekt: CPFL/xen
int xc_pm_get_cxstat(xc_interface *xch, int cpuid, struct xc_cx_stat *cxpt)
{
    DECLARE_SYSCTL;
    DECLARE_NAMED_HYPERCALL_BOUNCE(triggers, cxpt->triggers,
                                   cxpt->nr * sizeof(*cxpt->triggers),
                                   XC_HYPERCALL_BUFFER_BOUNCE_OUT);
    DECLARE_NAMED_HYPERCALL_BOUNCE(residencies, cxpt->residencies,
                                   cxpt->nr * sizeof(*cxpt->residencies),
                                   XC_HYPERCALL_BUFFER_BOUNCE_OUT);
    DECLARE_NAMED_HYPERCALL_BOUNCE(pc, cxpt->pc,
                                   cxpt->nr_pc * sizeof(*cxpt->pc),
                                   XC_HYPERCALL_BUFFER_BOUNCE_OUT);
    DECLARE_NAMED_HYPERCALL_BOUNCE(cc, cxpt->cc,
                                   cxpt->nr_cc * sizeof(*cxpt->cc),
                                   XC_HYPERCALL_BUFFER_BOUNCE_OUT);
    int ret = -1;

    if ( xc_hypercall_bounce_pre(xch, triggers) )
        goto unlock_0;
    if ( xc_hypercall_bounce_pre(xch, residencies) )
        goto unlock_1;
    if ( xc_hypercall_bounce_pre(xch, pc) )
        goto unlock_2;
    if ( xc_hypercall_bounce_pre(xch, cc) )
        goto unlock_3;

    sysctl.cmd = XEN_SYSCTL_get_pmstat;
    sysctl.u.get_pmstat.type = PMSTAT_get_cxstat;
    sysctl.u.get_pmstat.cpuid = cpuid;
    sysctl.u.get_pmstat.u.getcx.nr = cxpt->nr;
    sysctl.u.get_pmstat.u.getcx.nr_pc = cxpt->nr_pc;
    sysctl.u.get_pmstat.u.getcx.nr_cc = cxpt->nr_cc;
    set_xen_guest_handle(sysctl.u.get_pmstat.u.getcx.triggers, triggers);
    set_xen_guest_handle(sysctl.u.get_pmstat.u.getcx.residencies, residencies);
    set_xen_guest_handle(sysctl.u.get_pmstat.u.getcx.pc, pc);
    set_xen_guest_handle(sysctl.u.get_pmstat.u.getcx.cc, cc);

    if ( (ret = xc_sysctl(xch, &sysctl)) )
        goto unlock_4;

    cxpt->nr = sysctl.u.get_pmstat.u.getcx.nr;
    cxpt->last = sysctl.u.get_pmstat.u.getcx.last;
    cxpt->idle_time = sysctl.u.get_pmstat.u.getcx.idle_time;
    cxpt->nr_pc = sysctl.u.get_pmstat.u.getcx.nr_pc;
    cxpt->nr_cc = sysctl.u.get_pmstat.u.getcx.nr_cc;

unlock_4:
    xc_hypercall_bounce_post(xch, cc);
unlock_3:
    xc_hypercall_bounce_post(xch, pc);
unlock_2:
    xc_hypercall_bounce_post(xch, residencies);
unlock_1:
    xc_hypercall_bounce_post(xch, triggers);
unlock_0:
    return ret;
}
Beispiel #10
0
Datei: xc_pm.c Projekt: CPFL/xen
int xc_pm_reset_pxstat(xc_interface *xch, int cpuid)
{
    DECLARE_SYSCTL;

    sysctl.cmd = XEN_SYSCTL_get_pmstat;
    sysctl.u.get_pmstat.type = PMSTAT_reset_pxstat;
    sysctl.u.get_pmstat.cpuid = cpuid;

    return xc_sysctl(xch, &sysctl);
}
Beispiel #11
0
Datei: xc_pm.c Projekt: CPFL/xen
int xc_pm_get_pxstat(xc_interface *xch, int cpuid, struct xc_px_stat *pxpt)
{
    DECLARE_SYSCTL;
    /* Sizes unknown until xc_pm_get_max_px */
    DECLARE_NAMED_HYPERCALL_BOUNCE(trans, pxpt->trans_pt, 0, XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
    DECLARE_NAMED_HYPERCALL_BOUNCE(pt, pxpt->pt, 0, XC_HYPERCALL_BUFFER_BOUNCE_BOTH);

    int max_px, ret;

    if ( !pxpt->trans_pt || !pxpt->pt )
    {
        errno = EINVAL;
        return -1;
    }
    if ( (ret = xc_pm_get_max_px(xch, cpuid, &max_px)) != 0)
        return ret;

    HYPERCALL_BOUNCE_SET_SIZE(trans, max_px * max_px * sizeof(uint64_t));
    HYPERCALL_BOUNCE_SET_SIZE(pt, max_px * sizeof(struct xc_px_val));

    if ( xc_hypercall_bounce_pre(xch, trans) )
        return ret;

    if ( xc_hypercall_bounce_pre(xch, pt) )
    {
        xc_hypercall_bounce_post(xch, trans);
        return ret;
    }

    sysctl.cmd = XEN_SYSCTL_get_pmstat;
    sysctl.u.get_pmstat.type = PMSTAT_get_pxstat;
    sysctl.u.get_pmstat.cpuid = cpuid;
    sysctl.u.get_pmstat.u.getpx.total = max_px;
    set_xen_guest_handle(sysctl.u.get_pmstat.u.getpx.trans_pt, trans);
    set_xen_guest_handle(sysctl.u.get_pmstat.u.getpx.pt, pt);

    ret = xc_sysctl(xch, &sysctl);
    if ( ret )
    {
	xc_hypercall_bounce_post(xch, trans);
	xc_hypercall_bounce_post(xch, pt);
        return ret;
    }

    pxpt->total = sysctl.u.get_pmstat.u.getpx.total;
    pxpt->usable = sysctl.u.get_pmstat.u.getpx.usable;
    pxpt->last = sysctl.u.get_pmstat.u.getpx.last;
    pxpt->cur = sysctl.u.get_pmstat.u.getpx.cur;

    xc_hypercall_bounce_post(xch, trans);
    xc_hypercall_bounce_post(xch, pt);

    return ret;
}
Beispiel #12
0
int xc_tbuf_set_size(xc_interface *xch, unsigned long size)
{
    DECLARE_SYSCTL;

    sysctl.cmd = XEN_SYSCTL_tbuf_op;
    sysctl.interface_version = XEN_SYSCTL_INTERFACE_VERSION;
    sysctl.u.tbuf_op.cmd  = XEN_SYSCTL_TBUFOP_set_size;
    sysctl.u.tbuf_op.size = size;

    return xc_sysctl(xch, &sysctl);
}
Beispiel #13
0
static int tbuf_enable(xc_interface *xch, int enable)
{
    DECLARE_SYSCTL;

    sysctl.cmd = XEN_SYSCTL_tbuf_op;
    sysctl.interface_version = XEN_SYSCTL_INTERFACE_VERSION;
    if ( enable )
        sysctl.u.tbuf_op.cmd  = XEN_SYSCTL_TBUFOP_enable;
    else
        sysctl.u.tbuf_op.cmd  = XEN_SYSCTL_TBUFOP_disable;

    return xc_sysctl(xch, &sysctl);
}
Beispiel #14
0
Datei: xc_pm.c Projekt: CPFL/xen
int xc_pm_get_max_cx(xc_interface *xch, int cpuid, int *max_cx)
{
    DECLARE_SYSCTL;
    int ret = 0;

    sysctl.cmd = XEN_SYSCTL_get_pmstat;
    sysctl.u.get_pmstat.type = PMSTAT_get_max_cx;
    sysctl.u.get_pmstat.cpuid = cpuid;
    if ( (ret = xc_sysctl(xch, &sysctl)) != 0 )
        return ret;

    *max_cx = sysctl.u.get_pmstat.u.getcx.nr;
    return ret;
}
Beispiel #15
0
int gcov_sysctl(int op, struct xen_sysctl *sysctl,
                struct xc_hypercall_buffer *buf, uint32_t buf_size)
{
    DECLARE_HYPERCALL_BUFFER_ARGUMENT(buf);

    memset(sysctl, 0, sizeof(*sysctl));
    sysctl->cmd = XEN_SYSCTL_gcov_op;

    sysctl->u.gcov_op.cmd = op;
    sysctl->u.gcov_op.size = buf_size;
    set_xen_guest_handle(sysctl->u.gcov_op.buffer, buf);

    return xc_sysctl(xch, sysctl);
}
Beispiel #16
0
Datei: xc_pm.c Projekt: CPFL/xen
/*
 * Get PM statistic info
 */
int xc_pm_get_max_px(xc_interface *xch, int cpuid, int *max_px)
{
    DECLARE_SYSCTL;
    int ret;

    sysctl.cmd = XEN_SYSCTL_get_pmstat;
    sysctl.u.get_pmstat.type = PMSTAT_get_max_px;
    sysctl.u.get_pmstat.cpuid = cpuid;
    ret = xc_sysctl(xch, &sysctl);
    if ( ret )
        return ret;

    *max_px = sysctl.u.get_pmstat.u.getpx.total;
    return ret;
}
Beispiel #17
0
int xc_psr_cmt_get_l3_event_mask(xc_interface *xch, uint32_t *event_mask)
{
    int rc;
    DECLARE_SYSCTL;

    sysctl.cmd = XEN_SYSCTL_psr_cmt_op;
    sysctl.u.psr_cmt_op.cmd =
        XEN_SYSCTL_PSR_CMT_get_l3_event_mask;
    sysctl.u.psr_cmt_op.flags = 0;

    rc = xc_sysctl(xch, &sysctl);
    if ( !rc )
        *event_mask = sysctl.u.psr_cmt_op.u.data;

    return rc;
}
Beispiel #18
0
Datei: xc_pm.c Projekt: CPFL/xen
int xc_set_cpufreq_para(xc_interface *xch, int cpuid, 
                        int ctrl_type, int ctrl_value)
{
    DECLARE_SYSCTL;

    if ( !xch )
    {
        errno = EINVAL;
        return -1;
    }
    sysctl.cmd = XEN_SYSCTL_pm_op;
    sysctl.u.pm_op.cmd = SET_CPUFREQ_PARA;
    sysctl.u.pm_op.cpuid = cpuid;
    sysctl.u.pm_op.u.set_para.ctrl_type = ctrl_type;
    sysctl.u.pm_op.u.set_para.ctrl_value = ctrl_value;

    return xc_sysctl(xch, &sysctl);
}
Beispiel #19
0
Datei: xc_pm.c Projekt: CPFL/xen
int xc_set_cpufreq_gov(xc_interface *xch, int cpuid, char *govname)
{
    DECLARE_SYSCTL;
    char *scaling_governor = sysctl.u.pm_op.u.set_gov.scaling_governor;

    if ( !xch || !govname )
    {
        errno = EINVAL;
        return -1;
    }
    sysctl.cmd = XEN_SYSCTL_pm_op;
    sysctl.u.pm_op.cmd = SET_CPUFREQ_GOV;
    sysctl.u.pm_op.cpuid = cpuid;
    strncpy(scaling_governor, govname, CPUFREQ_NAME_LEN);
    scaling_governor[CPUFREQ_NAME_LEN - 1] = '\0';

    return xc_sysctl(xch, &sysctl);
}
Beispiel #20
0
Datei: xc_pm.c Projekt: CPFL/xen
int xc_get_cpufreq_avgfreq(xc_interface *xch, int cpuid, int *avg_freq)
{
    int ret = 0;
    DECLARE_SYSCTL;

    if ( !xch || !avg_freq )
    {
        errno = EINVAL;
        return -1;
    }
    sysctl.cmd = XEN_SYSCTL_pm_op;
    sysctl.u.pm_op.cmd = GET_CPUFREQ_AVGFREQ;
    sysctl.u.pm_op.cpuid = cpuid;
    ret = xc_sysctl(xch, &sysctl);

    *avg_freq = sysctl.u.pm_op.u.get_avgfreq;

    return ret;
}
Beispiel #21
0
int xc_availheap(int xc_handle,
                 int min_width,
                 int max_width,
                 int node,
                 uint64_t *bytes)
{
    DECLARE_SYSCTL;
    int rc;

    sysctl.cmd = XEN_SYSCTL_availheap;
    sysctl.u.availheap.min_bitwidth = min_width;
    sysctl.u.availheap.max_bitwidth = max_width;
    sysctl.u.availheap.node = node;

    rc = xc_sysctl(xc_handle, &sysctl);

    *bytes = sysctl.u.availheap.avail_bytes;

    return rc;
}
Beispiel #22
0
int xc_psr_cmt_get_total_rmid(xc_interface *xch, uint32_t *total_rmid)
{
    static int val = 0;
    int rc;
    DECLARE_SYSCTL;

    if ( val )
    {
        *total_rmid = val;
        return 0;
    }

    sysctl.cmd = XEN_SYSCTL_psr_cmt_op;
    sysctl.u.psr_cmt_op.cmd = XEN_SYSCTL_PSR_CMT_get_total_rmid;
    sysctl.u.psr_cmt_op.flags = 0;

    rc = xc_sysctl(xch, &sysctl);
    if ( !rc )
        val = *total_rmid = sysctl.u.psr_cmt_op.u.data;

    return rc;
}
Beispiel #23
0
int xc_psr_cmt_get_l3_upscaling_factor(xc_interface *xch,
                                       uint32_t *upscaling_factor)
{
    static int val = 0;
    int rc;
    DECLARE_SYSCTL;

    if ( val )
    {
        *upscaling_factor = val;
        return 0;
    }

    sysctl.cmd = XEN_SYSCTL_psr_cmt_op;
    sysctl.u.psr_cmt_op.cmd =
        XEN_SYSCTL_PSR_CMT_get_l3_upscaling_factor;
    sysctl.u.psr_cmt_op.flags = 0;

    rc = xc_sysctl(xch, &sysctl);
    if ( !rc )
        val = *upscaling_factor = sysctl.u.psr_cmt_op.u.data;

    return rc;
}
Beispiel #24
0
Datei: xc_pm.c Projekt: CPFL/xen
/*
 * 1. Get PM parameter
 * 2. Provide user PM control
 */
int xc_get_cpufreq_para(xc_interface *xch, int cpuid,
                        struct xc_get_cpufreq_para *user_para)
{
    DECLARE_SYSCTL;
    int ret = 0;
    struct xen_get_cpufreq_para *sys_para = &sysctl.u.pm_op.u.get_para;
    DECLARE_NAMED_HYPERCALL_BOUNCE(affected_cpus,
			 user_para->affected_cpus,
			 user_para->cpu_num * sizeof(uint32_t), XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
    DECLARE_NAMED_HYPERCALL_BOUNCE(scaling_available_frequencies,
			 user_para->scaling_available_frequencies,
			 user_para->freq_num * sizeof(uint32_t), XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
    DECLARE_NAMED_HYPERCALL_BOUNCE(scaling_available_governors,
			 user_para->scaling_available_governors,
			 user_para->gov_num * CPUFREQ_NAME_LEN * sizeof(char), XC_HYPERCALL_BUFFER_BOUNCE_BOTH);

    bool has_num = user_para->cpu_num &&
                     user_para->freq_num &&
                     user_para->gov_num;

    if ( has_num )
    {
        if ( (!user_para->affected_cpus)                    ||
             (!user_para->scaling_available_frequencies)    ||
             (!user_para->scaling_available_governors) )
        {
            errno = EINVAL;
            return -1;
        }
        if ( xc_hypercall_bounce_pre(xch, affected_cpus) )
            goto unlock_1;
        if ( xc_hypercall_bounce_pre(xch, scaling_available_frequencies) )
            goto unlock_2;
        if ( xc_hypercall_bounce_pre(xch, scaling_available_governors) )
            goto unlock_3;

        set_xen_guest_handle(sys_para->affected_cpus, affected_cpus);
        set_xen_guest_handle(sys_para->scaling_available_frequencies, scaling_available_frequencies);
        set_xen_guest_handle(sys_para->scaling_available_governors, scaling_available_governors);
    }

    sysctl.cmd = XEN_SYSCTL_pm_op;
    sysctl.u.pm_op.cmd = GET_CPUFREQ_PARA;
    sysctl.u.pm_op.cpuid = cpuid;
    sys_para->cpu_num  = user_para->cpu_num;
    sys_para->freq_num = user_para->freq_num;
    sys_para->gov_num  = user_para->gov_num;

    ret = xc_sysctl(xch, &sysctl);
    if ( ret )
    {
        if ( errno == EAGAIN )
        {
            user_para->cpu_num  = sys_para->cpu_num;
            user_para->freq_num = sys_para->freq_num;
            user_para->gov_num  = sys_para->gov_num;
            ret = -errno;
        }

        if ( has_num )
            goto unlock_4;
        goto unlock_1;
    }
    else
    {
        user_para->cpuinfo_cur_freq = sys_para->cpuinfo_cur_freq;
        user_para->cpuinfo_max_freq = sys_para->cpuinfo_max_freq;
        user_para->cpuinfo_min_freq = sys_para->cpuinfo_min_freq;
        user_para->scaling_cur_freq = sys_para->scaling_cur_freq;
        user_para->scaling_max_freq = sys_para->scaling_max_freq;
        user_para->scaling_min_freq = sys_para->scaling_min_freq;
        user_para->turbo_enabled    = sys_para->turbo_enabled;

        memcpy(user_para->scaling_driver,
                sys_para->scaling_driver, CPUFREQ_NAME_LEN);
        memcpy(user_para->scaling_governor,
                sys_para->scaling_governor, CPUFREQ_NAME_LEN);

        /* copy to user_para no matter what cpufreq governor */
        XC_BUILD_BUG_ON(sizeof(((struct xc_get_cpufreq_para *)0)->u) !=
                        sizeof(((struct xen_get_cpufreq_para *)0)->u));

        memcpy(&user_para->u, &sys_para->u, sizeof(sys_para->u));
    }

unlock_4:
    xc_hypercall_bounce_post(xch, scaling_available_governors);
unlock_3:
    xc_hypercall_bounce_post(xch, scaling_available_frequencies);
unlock_2:
    xc_hypercall_bounce_post(xch, affected_cpus);
unlock_1:
    return ret;
}