Contributors: 26
Author |
Tokens |
Token Proportion |
Commits |
Commit Proportion |
Pavel Machek |
164 |
26.93% |
4 |
8.16% |
Andi Kleen |
121 |
19.87% |
3 |
6.12% |
H. Peter Anvin |
78 |
12.81% |
7 |
14.29% |
Rafael J. Wysocki |
68 |
11.17% |
6 |
12.24% |
Kees Cook |
32 |
5.25% |
1 |
2.04% |
Sean Christopherson |
22 |
3.61% |
1 |
2.04% |
Shaohua Li |
22 |
3.61% |
2 |
4.08% |
Kristen Carlson Accardi |
16 |
2.63% |
1 |
2.04% |
Lv Zheng |
14 |
2.30% |
1 |
2.04% |
Jarkko Sakkinen |
12 |
1.97% |
3 |
6.12% |
Marcin Ślusarz |
10 |
1.64% |
1 |
2.04% |
Todd E Brandt |
10 |
1.64% |
1 |
2.04% |
Tejun Heo |
8 |
1.31% |
2 |
4.08% |
Ingo Molnar |
6 |
0.99% |
2 |
4.08% |
Borislav Petkov |
5 |
0.82% |
1 |
2.04% |
Matt Mackall |
5 |
0.82% |
2 |
4.08% |
Mike Rapoport |
3 |
0.49% |
1 |
2.04% |
Yinghai Lu |
3 |
0.49% |
1 |
2.04% |
Konrad Rzeszutek Wilk |
3 |
0.49% |
2 |
4.08% |
Alexey Dobriyan |
1 |
0.16% |
1 |
2.04% |
Jaswinder Singh Rajput |
1 |
0.16% |
1 |
2.04% |
Greg Kroah-Hartman |
1 |
0.16% |
1 |
2.04% |
Alexander Duyck |
1 |
0.16% |
1 |
2.04% |
Thomas Garnier |
1 |
0.16% |
1 |
2.04% |
Andrew Lutomirski |
1 |
0.16% |
1 |
2.04% |
Josh Poimboeuf |
1 |
0.16% |
1 |
2.04% |
Total |
609 |
|
49 |
|
// SPDX-License-Identifier: GPL-2.0
/*
* sleep.c - x86-specific ACPI sleep support.
*
* Copyright (C) 2001-2003 Patrick Mochel
* Copyright (C) 2001-2003 Pavel Machek <pavel@ucw.cz>
*/
#include <linux/acpi.h>
#include <linux/memblock.h>
#include <linux/dmi.h>
#include <linux/cpumask.h>
#include <linux/pgtable.h>
#include <asm/segment.h>
#include <asm/desc.h>
#include <asm/cacheflush.h>
#include <asm/realmode.h>
#include <linux/ftrace.h>
#include "../../realmode/rm/wakeup.h"
#include "sleep.h"
unsigned long acpi_realmode_flags;
#if defined(CONFIG_SMP) && defined(CONFIG_64BIT)
static char temp_stack[4096];
#endif
/**
* acpi_get_wakeup_address - provide physical address for S3 wakeup
*
* Returns the physical address where the kernel should be resumed after the
* system awakes from S3, e.g. for programming into the firmware waking vector.
*/
unsigned long acpi_get_wakeup_address(void)
{
return ((unsigned long)(real_mode_header->wakeup_start));
}
/**
* x86_acpi_enter_sleep_state - enter sleep state
* @state: Sleep state to enter.
*
* Wrapper around acpi_enter_sleep_state() to be called by assembly.
*/
asmlinkage acpi_status __visible x86_acpi_enter_sleep_state(u8 state)
{
return acpi_enter_sleep_state(state);
}
/**
* x86_acpi_suspend_lowlevel - save kernel state
*
* Create an identity mapped page table and copy the wakeup routine to
* low memory.
*/
int x86_acpi_suspend_lowlevel(void)
{
struct wakeup_header *header =
(struct wakeup_header *) __va(real_mode_header->wakeup_header);
if (header->signature != WAKEUP_HEADER_SIGNATURE) {
printk(KERN_ERR "wakeup header does not match\n");
return -EINVAL;
}
header->video_mode = saved_video_mode;
header->pmode_behavior = 0;
#ifndef CONFIG_64BIT
native_store_gdt((struct desc_ptr *)&header->pmode_gdt);
/*
* We have to check that we can write back the value, and not
* just read it. At least on 90 nm Pentium M (Family 6, Model
* 13), reading an invalid MSR is not guaranteed to trap, see
* Erratum X4 in "Intel Pentium M Processor on 90 nm Process
* with 2-MB L2 Cache and Intel® Processor A100 and A110 on 90
* nm process with 512-KB L2 Cache Specification Update".
*/
if (!rdmsr_safe(MSR_EFER,
&header->pmode_efer_low,
&header->pmode_efer_high) &&
!wrmsr_safe(MSR_EFER,
header->pmode_efer_low,
header->pmode_efer_high))
header->pmode_behavior |= (1 << WAKEUP_BEHAVIOR_RESTORE_EFER);
#endif /* !CONFIG_64BIT */
header->pmode_cr0 = read_cr0();
if (__this_cpu_read(cpu_info.cpuid_level) >= 0) {
header->pmode_cr4 = __read_cr4();
header->pmode_behavior |= (1 << WAKEUP_BEHAVIOR_RESTORE_CR4);
}
if (!rdmsr_safe(MSR_IA32_MISC_ENABLE,
&header->pmode_misc_en_low,
&header->pmode_misc_en_high) &&
!wrmsr_safe(MSR_IA32_MISC_ENABLE,
header->pmode_misc_en_low,
header->pmode_misc_en_high))
header->pmode_behavior |=
(1 << WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE);
header->realmode_flags = acpi_realmode_flags;
header->real_magic = 0x12345678;
#ifndef CONFIG_64BIT
header->pmode_entry = (u32)&wakeup_pmode_return;
header->pmode_cr3 = (u32)__pa_symbol(initial_page_table);
saved_magic = 0x12345678;
#else /* CONFIG_64BIT */
#ifdef CONFIG_SMP
initial_stack = (unsigned long)temp_stack + sizeof(temp_stack);
early_gdt_descr.address =
(unsigned long)get_cpu_gdt_rw(smp_processor_id());
initial_gs = per_cpu_offset(smp_processor_id());
#endif
initial_code = (unsigned long)wakeup_long64;
saved_magic = 0x123456789abcdef0L;
#endif /* CONFIG_64BIT */
/*
* Pause/unpause graph tracing around do_suspend_lowlevel as it has
* inconsistent call/return info after it jumps to the wakeup vector.
*/
pause_graph_tracing();
do_suspend_lowlevel();
unpause_graph_tracing();
return 0;
}
static int __init acpi_sleep_setup(char *str)
{
while ((str != NULL) && (*str != '\0')) {
if (strncmp(str, "s3_bios", 7) == 0)
acpi_realmode_flags |= 1;
if (strncmp(str, "s3_mode", 7) == 0)
acpi_realmode_flags |= 2;
if (strncmp(str, "s3_beep", 7) == 0)
acpi_realmode_flags |= 4;
#ifdef CONFIG_HIBERNATION
if (strncmp(str, "s4_nohwsig", 10) == 0)
acpi_no_s4_hw_signature();
#endif
if (strncmp(str, "nonvs", 5) == 0)
acpi_nvs_nosave();
if (strncmp(str, "nonvs_s3", 8) == 0)
acpi_nvs_nosave_s3();
if (strncmp(str, "old_ordering", 12) == 0)
acpi_old_suspend_ordering();
if (strncmp(str, "nobl", 4) == 0)
acpi_sleep_no_blacklist();
str = strchr(str, ',');
if (str != NULL)
str += strspn(str, ", \t");
}
return 1;
}
__setup("acpi_sleep=", acpi_sleep_setup);