case XENPF_getidletime:
{
- uint32_t i, nr_cpus;
- uint64_t idletime;
+ uint32_t cpu;
+ uint64_t idletime, now = NOW();
struct vcpu *v;
+ struct xenctl_cpumap ctlmap;
+ cpumask_t cpumap;
XEN_GUEST_HANDLE(uint64_t) idletimes;
ret = -ENOSYS;
if ( cpufreq_controller != FREQCTL_dom0_kernel )
break;
+ memset(&ctlmap, 0, sizeof(ctlmap));
+ ctlmap.nr_cpus = op->u.getidletime.cpumap_nr_cpus;
+ ctlmap.bitmap.p = op->u.getidletime.cpumap_bitmap.p;
+ xenctl_cpumap_to_cpumask(&cpumap, &ctlmap);
guest_from_compat_handle(idletimes, op->u.getidletime.idletime);
- nr_cpus = min_t(uint32_t, op->u.getidletime.max_cpus, NR_CPUS);
- for ( i = 0; i < nr_cpus; i++ )
+ for_each_cpu_mask ( cpu, cpumap )
{
- /* Assume no holes in idle-vcpu map. */
- if ( (v = idle_vcpu[i]) == NULL )
- break;
-
- idletime = v->runstate.time[RUNSTATE_running];
- if ( v->is_running )
- idletime += NOW() - v->runstate.state_entry_time;
+ if ( (v = idle_vcpu[cpu]) != NULL )
+ {
+ idletime = v->runstate.time[RUNSTATE_running];
+ if ( v->is_running )
+ idletime += now - v->runstate.state_entry_time;
+ }
+ else
+ {
+ idletime = 0;
+ cpu_clear(cpu, cpumap);
+ }
ret = -EFAULT;
- if ( copy_to_guest_offset(idletimes, i, &idletime, 1) )
+ if ( copy_to_guest_offset(idletimes, cpu, &idletime, 1) )
goto out;
}
- op->u.getidletime.nr_cpus = i;
+ op->u.getidletime.now = now;
+ cpumask_to_xenctl_cpumap(&ctlmap, &cpumap);
ret = copy_to_guest(u_xenpf_op, op, 1) ? -EFAULT : 0;
}
break;
typedef struct xenpf_change_freq xenpf_change_freq_t;
DEFINE_XEN_GUEST_HANDLE(xenpf_change_freq_t);
+/*
+ * Get idle times (nanoseconds since boot) for physical CPUs specified in the
+ * @cpumap_bitmap with range [0..@cpumap_nr_cpus-1]. The @idletime array is
+ * indexed by CPU number; only entries with the corresponding @cpumap_bitmap
+ * bit set are written to. On return, @cpumap_bitmap is modified so that any
+ * non-existent CPUs are cleared. Such CPUs have their @idletime array entry
+ * cleared.
+ */
#define XENPF_getidletime 53
struct xenpf_getidletime {
- /* IN variables. */
- uint32_t max_cpus;
+ /* IN/OUT variables */
+ /* IN: CPUs to interrogate; OUT: subset of IN which are present */
+ XEN_GUEST_HANDLE(uint8_t) cpumap_bitmap;
+ /* IN variables */
+ /* Size of cpumap bitmap. */
+ uint32_t cpumap_nr_cpus;
+ /* Must be indexable for every cpu in cpumap_bitmap. */
XEN_GUEST_HANDLE(uint64_t) idletime;
- /* OUT variables. */
- uint32_t nr_cpus;
+ /* OUT variables */
+ /* System time when the idletime snapshots were taken. */
+ uint64_t now;
};
typedef struct xenpf_getidletime xenpf_getidletime_t;
DEFINE_XEN_GUEST_HANDLE(xenpf_getidletime_t);