Skip to content

Commit

Permalink
Merge branches 'pm-sleep' and 'powercap'
Browse files Browse the repository at this point in the history
* pm-sleep:
  PM / sleep: Print active wakeup sources when blocking on wakeup_count reads
  x86/suspend: fix false positive KASAN warning on suspend/resume
  PM / sleep / ACPI: Use the ACPI_FADT_LOW_POWER_S0 flag
  PM / sleep: System sleep state selection interface rework
  PM / hibernate: Verify the consistent of e820 memory map by md5 digest

* powercap:
  powercap / RAPL: Add Knights Mill CPUID
  powercap/intel_rapl: fix and tidy up error handling
  powercap/intel_rapl: Track active CPUs internally
  powercap/intel_rapl: Cleanup duplicated init code
  powercap/intel rapl: Convert to hotplug state machine
  powercap/intel_rapl: Propagate error code when registration fails
  powercap/intel_rapl: Add missing domain data update on hotplug
  • Loading branch information
Rafael J. Wysocki committed Dec 12, 2016
3 parents b19ad3b + 9320f95 + bd90891 commit 631ddab
Show file tree
Hide file tree
Showing 13 changed files with 454 additions and 346 deletions.
45 changes: 25 additions & 20 deletions Documentation/ABI/testing/sysfs-power
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,35 @@ Description:
subsystem.

What: /sys/power/state
Date: May 2014
Date: November 2016
Contact: Rafael J. Wysocki <rjw@rjwysocki.net>
Description:
The /sys/power/state file controls system sleep states.
Reading from this file returns the available sleep state
labels, which may be "mem", "standby", "freeze" and "disk"
(hibernation). The meanings of the first three labels depend on
the relative_sleep_states command line argument as follows:
1) relative_sleep_states = 1
"mem", "standby", "freeze" represent non-hibernation sleep
states from the deepest ("mem", always present) to the
shallowest ("freeze"). "standby" and "freeze" may or may
not be present depending on the capabilities of the
platform. "freeze" can only be present if "standby" is
present.
2) relative_sleep_states = 0 (default)
"mem" - "suspend-to-RAM", present if supported.
"standby" - "power-on suspend", present if supported.
"freeze" - "suspend-to-idle", always present.

Writing to this file one of these strings causes the system to
transition into the corresponding state, if available. See
Documentation/power/states.txt for a description of what
"suspend-to-RAM", "power-on suspend" and "suspend-to-idle" mean.
labels, which may be "mem" (suspend), "standby" (power-on
suspend), "freeze" (suspend-to-idle) and "disk" (hibernation).

Writing one of the above strings to this file causes the system
to transition into the corresponding state, if available.

See Documentation/power/states.txt for more information.

What: /sys/power/mem_sleep
Date: November 2016
Contact: Rafael J. Wysocki <rjw@rjwysocki.net>
Description:
The /sys/power/mem_sleep file controls the operating mode of
system suspend. Reading from it returns the available modes
as "s2idle" (always present), "shallow" and "deep" (present if
supported). The mode that will be used on subsequent attempts
to suspend the system (by writing "mem" to the /sys/power/state
file described above) is enclosed in square brackets.

Writing one of the above strings to this file causes the mode
represented by it to be used on subsequent attempts to suspend
the system.

See Documentation/power/states.txt for more information.

What: /sys/power/disk
Date: September 2006
Expand Down
13 changes: 6 additions & 7 deletions Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2334,6 +2334,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
memory contents and reserves bad memory
regions that are detected.

mem_sleep_default= [SUSPEND] Default system suspend mode:
s2idle - Suspend-To-Idle
shallow - Power-On Suspend or equivalent (if supported)
deep - Suspend-To-RAM or equivalent (if supported)
See Documentation/power/states.txt.

meye.*= [HW] Set MotionEye Camera parameters
See Documentation/video4linux/meye.txt.

Expand Down Expand Up @@ -3677,13 +3683,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
[KNL, SMP] Set scheduler's default relax_domain_level.
See Documentation/cgroup-v1/cpusets.txt.

relative_sleep_states=
[SUSPEND] Use sleep state labeling where the deepest
state available other than hibernation is always "mem".
Format: { "0" | "1" }
0 -- Traditional sleep state labels.
1 -- Relative sleep state labels.

reserve= [KNL,BUGS] Force the kernel to ignore some iomem area

reservetop= [X86-32]
Expand Down
62 changes: 40 additions & 22 deletions Documentation/power/states.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,43 @@ for each state.

The states are represented by strings that can be read or written to the
/sys/power/state file. Those strings may be "mem", "standby", "freeze" and
"disk", where the last one always represents hibernation (Suspend-To-Disk) and
the meaning of the remaining ones depends on the relative_sleep_states command
line argument.

For relative_sleep_states=1, the strings "mem", "standby" and "freeze" label the
available non-hibernation sleep states from the deepest to the shallowest,
respectively. In that case, "mem" is always present in /sys/power/state,
because there is at least one non-hibernation sleep state in every system. If
the given system supports two non-hibernation sleep states, "standby" is present
in /sys/power/state in addition to "mem". If the system supports three
non-hibernation sleep states, "freeze" will be present in /sys/power/state in
addition to "mem" and "standby".

For relative_sleep_states=0, which is the default, the following descriptions
apply.

state: Suspend-To-Idle
"disk", where the last three always represent Power-On Suspend (if supported),
Suspend-To-Idle and hibernation (Suspend-To-Disk), respectively.

The meaning of the "mem" string is controlled by the /sys/power/mem_sleep file.
It contains strings representing the available modes of system suspend that may
be triggered by writing "mem" to /sys/power/state. These modes are "s2idle"
(Suspend-To-Idle), "shallow" (Power-On Suspend) and "deep" (Suspend-To-RAM).
The "s2idle" mode is always available, while the other ones are only available
if supported by the platform (if not supported, the strings representing them
are not present in /sys/power/mem_sleep). The string representing the suspend
mode to be used subsequently is enclosed in square brackets. Writing one of
the other strings present in /sys/power/mem_sleep to it causes the suspend mode
to be used subsequently to change to the one represented by that string.

Consequently, there are two ways to cause the system to go into the
Suspend-To-Idle sleep state. The first one is to write "freeze" directly to
/sys/power/state. The second one is to write "s2idle" to /sys/power/mem_sleep
and then to wrtie "mem" to /sys/power/state. Similarly, there are two ways
to cause the system to go into the Power-On Suspend sleep state (the strings to
write to the control files in that case are "standby" or "shallow" and "mem",
respectively) if that state is supported by the platform. In turn, there is
only one way to cause the system to go into the Suspend-To-RAM state (write
"deep" into /sys/power/mem_sleep and "mem" into /sys/power/state).

The default suspend mode (ie. the one to be used without writing anything into
/sys/power/mem_sleep) is either "deep" (if Suspend-To-RAM is supported) or
"s2idle", but it can be overridden by the value of the "mem_sleep_default"
parameter in the kernel command line. On some ACPI-based systems, depending on
the information in the FADT, the default may be "s2idle" even if Suspend-To-RAM
is supported.

The properties of all of the sleep states are described below.


State: Suspend-To-Idle
ACPI state: S0
Label: "freeze"
Label: "s2idle" ("freeze")

This state is a generic, pure software, light-weight, system sleep state.
It allows more energy to be saved relative to runtime idle by freezing user
Expand All @@ -35,13 +53,13 @@ lower-power than available at run time), such that the processors can
spend more time in their idle states.

This state can be used for platforms without Power-On Suspend/Suspend-to-RAM
support, or it can be used in addition to Suspend-to-RAM (memory sleep)
to provide reduced resume latency. It is always supported.
support, or it can be used in addition to Suspend-to-RAM to provide reduced
resume latency. It is always supported.


State: Standby / Power-On Suspend
ACPI State: S1
Label: "standby"
Label: "shallow" ("standby")

This state, if supported, offers moderate, though real, power savings, while
providing a relatively low-latency transition back to a working system. No
Expand All @@ -58,7 +76,7 @@ state.

State: Suspend-to-RAM
ACPI State: S3
Label: "mem"
Label: "deep"

This state, if supported, offers significant power savings as everything in the
system is put into a low-power state, except for memory, which should be placed
Expand Down
9 changes: 9 additions & 0 deletions arch/x86/kernel/acpi/wakeup_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,15 @@ ENTRY(do_suspend_lowlevel)
movq pt_regs_r14(%rax), %r14
movq pt_regs_r15(%rax), %r15

#ifdef CONFIG_KASAN
/*
* The suspend path may have poisoned some areas deeper in the stack,
* which we now need to unpoison.
*/
movq %rsp, %rdi
call kasan_unpoison_task_stack_below
#endif

xorl %eax, %eax
addq $8, %rsp
FRAME_END
Expand Down
94 changes: 92 additions & 2 deletions arch/x86/power/hibernate_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
#include <linux/gfp.h>
#include <linux/smp.h>
#include <linux/suspend.h>
#include <linux/scatterlist.h>
#include <linux/kdebug.h>

#include <crypto/hash.h>

#include <asm/init.h>
#include <asm/proto.h>
Expand Down Expand Up @@ -177,14 +181,86 @@ int pfn_is_nosave(unsigned long pfn)
return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn);
}

#define MD5_DIGEST_SIZE 16

struct restore_data_record {
unsigned long jump_address;
unsigned long jump_address_phys;
unsigned long cr3;
unsigned long magic;
u8 e820_digest[MD5_DIGEST_SIZE];
};

#define RESTORE_MAGIC 0x123456789ABCDEF0UL
#define RESTORE_MAGIC 0x23456789ABCDEF01UL

#if IS_BUILTIN(CONFIG_CRYPTO_MD5)
/**
* get_e820_md5 - calculate md5 according to given e820 map
*
* @map: the e820 map to be calculated
* @buf: the md5 result to be stored to
*/
static int get_e820_md5(struct e820map *map, void *buf)
{
struct scatterlist sg;
struct crypto_ahash *tfm;
int size;
int ret = 0;

tfm = crypto_alloc_ahash("md5", 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(tfm))
return -ENOMEM;

{
AHASH_REQUEST_ON_STACK(req, tfm);
size = offsetof(struct e820map, map)
+ sizeof(struct e820entry) * map->nr_map;
ahash_request_set_tfm(req, tfm);
sg_init_one(&sg, (u8 *)map, size);
ahash_request_set_callback(req, 0, NULL, NULL);
ahash_request_set_crypt(req, &sg, buf, size);

if (crypto_ahash_digest(req))
ret = -EINVAL;
ahash_request_zero(req);
}
crypto_free_ahash(tfm);

return ret;
}

static void hibernation_e820_save(void *buf)
{
get_e820_md5(e820_saved, buf);
}

static bool hibernation_e820_mismatch(void *buf)
{
int ret;
u8 result[MD5_DIGEST_SIZE];

memset(result, 0, MD5_DIGEST_SIZE);
/* If there is no digest in suspend kernel, let it go. */
if (!memcmp(result, buf, MD5_DIGEST_SIZE))
return false;

ret = get_e820_md5(e820_saved, result);
if (ret)
return true;

return memcmp(result, buf, MD5_DIGEST_SIZE) ? true : false;
}
#else
static void hibernation_e820_save(void *buf)
{
}

static bool hibernation_e820_mismatch(void *buf)
{
/* If md5 is not builtin for restore kernel, let it go. */
return false;
}
#endif

/**
* arch_hibernation_header_save - populate the architecture specific part
Expand All @@ -201,6 +277,9 @@ int arch_hibernation_header_save(void *addr, unsigned int max_size)
rdr->jump_address_phys = __pa_symbol(&restore_registers);
rdr->cr3 = restore_cr3;
rdr->magic = RESTORE_MAGIC;

hibernation_e820_save(rdr->e820_digest);

return 0;
}

Expand All @@ -216,5 +295,16 @@ int arch_hibernation_header_restore(void *addr)
restore_jump_address = rdr->jump_address;
jump_address_phys = rdr->jump_address_phys;
restore_cr3 = rdr->cr3;
return (rdr->magic == RESTORE_MAGIC) ? 0 : -EINVAL;

if (rdr->magic != RESTORE_MAGIC) {
pr_crit("Unrecognized hibernate image header format!\n");
return -EINVAL;
}

if (hibernation_e820_mismatch(rdr->e820_digest)) {
pr_crit("Hibernate inconsistent memory map detected!\n");
return -ENODEV;
}

return 0;
}
8 changes: 8 additions & 0 deletions drivers/acpi/sleep.c
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,14 @@ static void acpi_sleep_suspend_setup(void)
if (acpi_sleep_state_supported(i))
sleep_states[i] = 1;

/*
* Use suspend-to-idle by default if ACPI_FADT_LOW_POWER_S0 is set and
* the default suspend mode was not selected from the command line.
*/
if (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0 &&
mem_sleep_default > PM_SUSPEND_MEM)
mem_sleep_default = PM_SUSPEND_FREEZE;

suspend_set_ops(old_suspend_ordering ?
&acpi_suspend_ops_old : &acpi_suspend_ops);
freeze_set_ops(&acpi_freeze_ops);
Expand Down
6 changes: 3 additions & 3 deletions drivers/base/power/wakeup.c
Original file line number Diff line number Diff line change
Expand Up @@ -811,7 +811,7 @@ void pm_print_active_wakeup_sources(void)
rcu_read_lock();
list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
if (ws->active) {
pr_info("active wakeup source: %s\n", ws->name);
pr_debug("active wakeup source: %s\n", ws->name);
active = 1;
} else if (!active &&
(!last_activity_ws ||
Expand All @@ -822,7 +822,7 @@ void pm_print_active_wakeup_sources(void)
}

if (!active && last_activity_ws)
pr_info("last active wakeup source: %s\n",
pr_debug("last active wakeup source: %s\n",
last_activity_ws->name);
rcu_read_unlock();
}
Expand Down Expand Up @@ -905,7 +905,7 @@ bool pm_get_wakeup_count(unsigned int *count, bool block)
split_counters(&cnt, &inpr);
if (inpr == 0 || signal_pending(current))
break;

pm_print_active_wakeup_sources();
schedule();
}
finish_wait(&wakeup_count_wait_queue, &wait);
Expand Down
Loading

0 comments on commit 631ddab

Please sign in to comment.