Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * sleep.c - x86-specific ACPI sleep support.
0004  *
0005  *  Copyright (C) 2001-2003 Patrick Mochel
0006  *  Copyright (C) 2001-2003 Pavel Machek <pavel@ucw.cz>
0007  */
0008 
0009 #include <linux/acpi.h>
0010 #include <linux/memblock.h>
0011 #include <linux/dmi.h>
0012 #include <linux/cpumask.h>
0013 #include <linux/pgtable.h>
0014 #include <asm/segment.h>
0015 #include <asm/desc.h>
0016 #include <asm/cacheflush.h>
0017 #include <asm/realmode.h>
0018 #include <asm/hypervisor.h>
0019 
0020 #include <linux/ftrace.h>
0021 #include "../../realmode/rm/wakeup.h"
0022 #include "sleep.h"
0023 
0024 unsigned long acpi_realmode_flags;
0025 
0026 #if defined(CONFIG_SMP) && defined(CONFIG_64BIT)
0027 static char temp_stack[4096];
0028 #endif
0029 
0030 /**
0031  * acpi_get_wakeup_address - provide physical address for S3 wakeup
0032  *
0033  * Returns the physical address where the kernel should be resumed after the
0034  * system awakes from S3, e.g. for programming into the firmware waking vector.
0035  */
0036 unsigned long acpi_get_wakeup_address(void)
0037 {
0038     return ((unsigned long)(real_mode_header->wakeup_start));
0039 }
0040 
0041 /**
0042  * x86_acpi_enter_sleep_state - enter sleep state
0043  * @state: Sleep state to enter.
0044  *
0045  * Wrapper around acpi_enter_sleep_state() to be called by assembly.
0046  */
0047 asmlinkage acpi_status __visible x86_acpi_enter_sleep_state(u8 state)
0048 {
0049     return acpi_enter_sleep_state(state);
0050 }
0051 
0052 /**
0053  * x86_acpi_suspend_lowlevel - save kernel state
0054  *
0055  * Create an identity mapped page table and copy the wakeup routine to
0056  * low memory.
0057  */
0058 int x86_acpi_suspend_lowlevel(void)
0059 {
0060     struct wakeup_header *header =
0061         (struct wakeup_header *) __va(real_mode_header->wakeup_header);
0062 
0063     if (header->signature != WAKEUP_HEADER_SIGNATURE) {
0064         printk(KERN_ERR "wakeup header does not match\n");
0065         return -EINVAL;
0066     }
0067 
0068     header->video_mode = saved_video_mode;
0069 
0070     header->pmode_behavior = 0;
0071 
0072 #ifndef CONFIG_64BIT
0073     native_store_gdt((struct desc_ptr *)&header->pmode_gdt);
0074 
0075     /*
0076      * We have to check that we can write back the value, and not
0077      * just read it.  At least on 90 nm Pentium M (Family 6, Model
0078      * 13), reading an invalid MSR is not guaranteed to trap, see
0079      * Erratum X4 in "Intel Pentium M Processor on 90 nm Process
0080      * with 2-MB L2 Cache and IntelĀ® Processor A100 and A110 on 90
0081      * nm process with 512-KB L2 Cache Specification Update".
0082      */
0083     if (!rdmsr_safe(MSR_EFER,
0084             &header->pmode_efer_low,
0085             &header->pmode_efer_high) &&
0086         !wrmsr_safe(MSR_EFER,
0087             header->pmode_efer_low,
0088             header->pmode_efer_high))
0089         header->pmode_behavior |= (1 << WAKEUP_BEHAVIOR_RESTORE_EFER);
0090 #endif /* !CONFIG_64BIT */
0091 
0092     header->pmode_cr0 = read_cr0();
0093     if (__this_cpu_read(cpu_info.cpuid_level) >= 0) {
0094         header->pmode_cr4 = __read_cr4();
0095         header->pmode_behavior |= (1 << WAKEUP_BEHAVIOR_RESTORE_CR4);
0096     }
0097     if (!rdmsr_safe(MSR_IA32_MISC_ENABLE,
0098             &header->pmode_misc_en_low,
0099             &header->pmode_misc_en_high) &&
0100         !wrmsr_safe(MSR_IA32_MISC_ENABLE,
0101             header->pmode_misc_en_low,
0102             header->pmode_misc_en_high))
0103         header->pmode_behavior |=
0104             (1 << WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE);
0105     header->realmode_flags = acpi_realmode_flags;
0106     header->real_magic = 0x12345678;
0107 
0108 #ifndef CONFIG_64BIT
0109     header->pmode_entry = (u32)&wakeup_pmode_return;
0110     header->pmode_cr3 = (u32)__pa_symbol(initial_page_table);
0111     saved_magic = 0x12345678;
0112 #else /* CONFIG_64BIT */
0113 #ifdef CONFIG_SMP
0114     initial_stack = (unsigned long)temp_stack + sizeof(temp_stack);
0115     early_gdt_descr.address =
0116             (unsigned long)get_cpu_gdt_rw(smp_processor_id());
0117     initial_gs = per_cpu_offset(smp_processor_id());
0118 #endif
0119     initial_code = (unsigned long)wakeup_long64;
0120        saved_magic = 0x123456789abcdef0L;
0121 #endif /* CONFIG_64BIT */
0122 
0123     /*
0124      * Pause/unpause graph tracing around do_suspend_lowlevel as it has
0125      * inconsistent call/return info after it jumps to the wakeup vector.
0126      */
0127     pause_graph_tracing();
0128     do_suspend_lowlevel();
0129     unpause_graph_tracing();
0130     return 0;
0131 }
0132 
0133 static int __init acpi_sleep_setup(char *str)
0134 {
0135     while ((str != NULL) && (*str != '\0')) {
0136         if (strncmp(str, "s3_bios", 7) == 0)
0137             acpi_realmode_flags |= 1;
0138         if (strncmp(str, "s3_mode", 7) == 0)
0139             acpi_realmode_flags |= 2;
0140         if (strncmp(str, "s3_beep", 7) == 0)
0141             acpi_realmode_flags |= 4;
0142 #ifdef CONFIG_HIBERNATION
0143         if (strncmp(str, "s4_hwsig", 8) == 0)
0144             acpi_check_s4_hw_signature = 1;
0145         if (strncmp(str, "s4_nohwsig", 10) == 0)
0146             acpi_check_s4_hw_signature = 0;
0147 #endif
0148         if (strncmp(str, "nonvs", 5) == 0)
0149             acpi_nvs_nosave();
0150         if (strncmp(str, "nonvs_s3", 8) == 0)
0151             acpi_nvs_nosave_s3();
0152         if (strncmp(str, "old_ordering", 12) == 0)
0153             acpi_old_suspend_ordering();
0154         if (strncmp(str, "nobl", 4) == 0)
0155             acpi_sleep_no_blacklist();
0156         str = strchr(str, ',');
0157         if (str != NULL)
0158             str += strspn(str, ", \t");
0159     }
0160     return 1;
0161 }
0162 
0163 __setup("acpi_sleep=", acpi_sleep_setup);
0164 
0165 #if defined(CONFIG_HIBERNATION) && defined(CONFIG_HYPERVISOR_GUEST)
0166 static int __init init_s4_sigcheck(void)
0167 {
0168     /*
0169      * If running on a hypervisor, honour the ACPI specification
0170      * by default and trigger a clean reboot when the hardware
0171      * signature in FACS is changed after hibernation.
0172      */
0173     if (acpi_check_s4_hw_signature == -1 &&
0174         !hypervisor_is_type(X86_HYPER_NATIVE))
0175         acpi_check_s4_hw_signature = 1;
0176 
0177     return 0;
0178 }
0179 /* This must happen before acpi_init() which is a subsys initcall */
0180 arch_initcall(init_s4_sigcheck);
0181 #endif