x86, dom0: Allow get idle time stats by mask.
authorKeir Fraser <keir@xensource.com>
Wed, 24 Oct 2007 09:49:03 +0000 (10:49 +0100)
committerKeir Fraser <keir@xensource.com>
Wed, 24 Oct 2007 09:49:03 +0000 (10:49 +0100)
Signed-off-by: Kevin Tian <kevin.tian@intel.com>
xen/arch/x86/platform_hypercall.c
xen/include/public/platform.h

index b4ab7d4d2c905c9ba9ccd67d6ba7c36ce86dfa81..4d155b0a9871bd04f50628aec03cefc7435ffe01 100644 (file)
@@ -293,34 +293,44 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
 
     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;
index 16bf686d4aa093556ef8a8ceb1f971a98bd45c3d..3998989e6fefd7bc11060d0b5add6ac3337ade65 100644 (file)
@@ -174,13 +174,27 @@ struct xenpf_change_freq {
 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);