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