ppc64_runlatch_on();
 }
 
+static inline u64 read_this_idle_purr(void)
+{
+       /*
+        * If we are reading from an idle context, update the
+        * idle-purr cycles corresponding to the last idle period.
+        * Since the idle context is not yet over, take a fresh
+        * snapshot of the idle-purr.
+        */
+       if (unlikely(get_lppaca()->idle == 1)) {
+               update_idle_purr_accounting();
+               snapshot_purr_idle_entry();
+       }
+
+       return be64_to_cpu(get_lppaca()->wait_state_cycles);
+}
+
+static inline u64 read_this_idle_spurr(void)
+{
+       /*
+        * If we are reading from an idle context, update the
+        * idle-spurr cycles corresponding to the last idle period.
+        * Since the idle context is not yet over, take a fresh
+        * snapshot of the idle-spurr.
+        */
+       if (get_lppaca()->idle == 1) {
+               update_idle_spurr_accounting();
+               snapshot_spurr_idle_entry();
+       }
+
+       return *this_cpu_ptr(&idle_spurr_cycles);
+}
+
 #endif /* CONFIG_PPC_PSERIES */
 #endif
 
 #include <asm/smp.h>
 #include <asm/pmc.h>
 #include <asm/firmware.h>
+#include <asm/idle.h>
 #include <asm/svm.h>
 
 #include "cacheinfo.h"
 }
 #endif /* CONFIG_PPC_SVM */
 
+#ifdef CONFIG_PPC_PSERIES
+static void read_idle_purr(void *val)
+{
+       u64 *ret = val;
+
+       *ret = read_this_idle_purr();
+}
+
+static ssize_t idle_purr_show(struct device *dev,
+                             struct device_attribute *attr, char *buf)
+{
+       struct cpu *cpu = container_of(dev, struct cpu, dev);
+       u64 val;
+
+       smp_call_function_single(cpu->dev.id, read_idle_purr, &val, 1);
+       return sprintf(buf, "%llx\n", val);
+}
+static DEVICE_ATTR(idle_purr, 0400, idle_purr_show, NULL);
+
+static void create_idle_purr_file(struct device *s)
+{
+       if (firmware_has_feature(FW_FEATURE_LPAR))
+               device_create_file(s, &dev_attr_idle_purr);
+}
+
+static void remove_idle_purr_file(struct device *s)
+{
+       if (firmware_has_feature(FW_FEATURE_LPAR))
+               device_remove_file(s, &dev_attr_idle_purr);
+}
+
+static void read_idle_spurr(void *val)
+{
+       u64 *ret = val;
+
+       *ret = read_this_idle_spurr();
+}
+
+static ssize_t idle_spurr_show(struct device *dev,
+                              struct device_attribute *attr, char *buf)
+{
+       struct cpu *cpu = container_of(dev, struct cpu, dev);
+       u64 val;
+
+       smp_call_function_single(cpu->dev.id, read_idle_spurr, &val, 1);
+       return sprintf(buf, "%llx\n", val);
+}
+static DEVICE_ATTR(idle_spurr, 0400, idle_spurr_show, NULL);
+
+static void create_idle_spurr_file(struct device *s)
+{
+       if (firmware_has_feature(FW_FEATURE_LPAR))
+               device_create_file(s, &dev_attr_idle_spurr);
+}
+
+static void remove_idle_spurr_file(struct device *s)
+{
+       if (firmware_has_feature(FW_FEATURE_LPAR))
+               device_remove_file(s, &dev_attr_idle_spurr);
+}
+
+#else /* CONFIG_PPC_PSERIES */
+#define create_idle_purr_file(s)
+#define remove_idle_purr_file(s)
+#define create_idle_spurr_file(s)
+#define remove_idle_spurr_file(s)
+#endif /* CONFIG_PPC_PSERIES */
+
 static int register_cpu_online(unsigned int cpu)
 {
        struct cpu *c = &per_cpu(cpu_devices, cpu);
                if (!firmware_has_feature(FW_FEATURE_LPAR))
                        add_write_permission_dev_attr(&dev_attr_purr);
                device_create_file(s, &dev_attr_purr);
+               create_idle_purr_file(s);
        }
 
-       if (cpu_has_feature(CPU_FTR_SPURR))
+       if (cpu_has_feature(CPU_FTR_SPURR)) {
                device_create_file(s, &dev_attr_spurr);
+               create_idle_spurr_file(s);
+       }
 
        if (cpu_has_feature(CPU_FTR_DSCR))
                device_create_file(s, &dev_attr_dscr);
                device_remove_file(s, &dev_attr_mmcra);
 #endif /* CONFIG_PMU_SYSFS */
 
-       if (cpu_has_feature(CPU_FTR_PURR))
+       if (cpu_has_feature(CPU_FTR_PURR)) {
                device_remove_file(s, &dev_attr_purr);
+               remove_idle_purr_file(s);
+       }
 
-       if (cpu_has_feature(CPU_FTR_SPURR))
+       if (cpu_has_feature(CPU_FTR_SPURR)) {
                device_remove_file(s, &dev_attr_spurr);
+               remove_idle_spurr_file(s);
+       }
 
        if (cpu_has_feature(CPU_FTR_DSCR))
                device_remove_file(s, &dev_attr_dscr);