Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ACPICA: Hardware: Add sleep register hooks

ACPICA commit ba665dc8e20d9f7730466a659564dd6c557a6cbc

In Linux, para-virtualization implmentation hooks critical register
writes to prevent real hardware operations. This increases divergences
when the sleep registers are cracked in Linux resident ACPICA.

This patch tries to introduce a single OSL to reduce the divergences.

Link: https://github.com/acpica/acpica/commit/ba665dc8
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Lv Zheng and committed by
Rafael J. Wysocki
0fc5e8f4 fcfb4553

+76 -32
+16 -19
drivers/acpi/acpica/hwesleep.c
··· 43 43 */ 44 44 45 45 #include <acpi/acpi.h> 46 - #include <linux/acpi.h> 47 46 #include "accommon.h" 48 47 49 48 #define _COMPONENT ACPI_HARDWARE ··· 102 103 acpi_status acpi_hw_extended_sleep(u8 sleep_state) 103 104 { 104 105 acpi_status status; 105 - u8 sleep_type_value; 106 + u8 sleep_control; 106 107 u64 sleep_status; 107 108 108 109 ACPI_FUNCTION_TRACE(hw_extended_sleep); ··· 124 125 125 126 acpi_gbl_system_awake_and_running = FALSE; 126 127 127 - /* Flush caches, as per ACPI specification */ 128 - 129 - ACPI_FLUSH_CPU_CACHE(); 130 - 131 - status = acpi_os_prepare_extended_sleep(sleep_state, 132 - acpi_gbl_sleep_type_a, 133 - acpi_gbl_sleep_type_b); 134 - if (ACPI_SKIP(status)) 135 - return_ACPI_STATUS(AE_OK); 136 - if (ACPI_FAILURE(status)) 137 - return_ACPI_STATUS(status); 138 - 139 128 /* 140 129 * Set the SLP_TYP and SLP_EN bits. 141 130 * ··· 133 146 ACPI_DEBUG_PRINT((ACPI_DB_INIT, 134 147 "Entering sleep state [S%u]\n", sleep_state)); 135 148 136 - sleep_type_value = 137 - ((acpi_gbl_sleep_type_a << ACPI_X_SLEEP_TYPE_POSITION) & 138 - ACPI_X_SLEEP_TYPE_MASK); 149 + sleep_control = ((acpi_gbl_sleep_type_a << ACPI_X_SLEEP_TYPE_POSITION) & 150 + ACPI_X_SLEEP_TYPE_MASK) | ACPI_X_SLEEP_ENABLE; 139 151 140 - status = acpi_write((u64)(sleep_type_value | ACPI_X_SLEEP_ENABLE), 141 - &acpi_gbl_FADT.sleep_control); 152 + /* Flush caches, as per ACPI specification */ 153 + 154 + ACPI_FLUSH_CPU_CACHE(); 155 + 156 + status = acpi_os_enter_sleep(sleep_state, sleep_control, 0); 157 + if (status == AE_CTRL_TERMINATE) { 158 + return_ACPI_STATUS(AE_OK); 159 + } 160 + if (ACPI_FAILURE(status)) { 161 + return_ACPI_STATUS(status); 162 + } 163 + 164 + status = acpi_write((u64)sleep_control, &acpi_gbl_FADT.sleep_control); 142 165 if (ACPI_FAILURE(status)) { 143 166 return_ACPI_STATUS(status); 144 167 }
+6 -5
drivers/acpi/acpica/hwsleep.c
··· 43 43 */ 44 44 45 45 #include <acpi/acpi.h> 46 - #include <linux/acpi.h> 47 46 #include "accommon.h" 48 47 49 48 #define _COMPONENT ACPI_HARDWARE ··· 151 152 152 153 ACPI_FLUSH_CPU_CACHE(); 153 154 154 - status = acpi_os_prepare_sleep(sleep_state, pm1a_control, 155 - pm1b_control); 156 - if (ACPI_SKIP(status)) 155 + status = acpi_os_enter_sleep(sleep_state, pm1a_control, pm1b_control); 156 + if (status == AE_CTRL_TERMINATE) { 157 157 return_ACPI_STATUS(AE_OK); 158 - if (ACPI_FAILURE(status)) 158 + } 159 + if (ACPI_FAILURE(status)) { 159 160 return_ACPI_STATUS(status); 161 + } 162 + 160 163 /* Write #2: Write both SLP_TYP + SLP_EN */ 161 164 162 165 status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control);
+25 -2
drivers/acpi/osl.c
··· 1686 1686 if (rc < 0) 1687 1687 return AE_ERROR; 1688 1688 else if (rc > 0) 1689 - return AE_CTRL_SKIP; 1689 + return AE_CTRL_TERMINATE; 1690 1690 1691 1691 return AE_OK; 1692 1692 } ··· 1697 1697 __acpi_os_prepare_sleep = func; 1698 1698 } 1699 1699 1700 + #if (ACPI_REDUCED_HARDWARE) 1700 1701 acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state, u32 val_a, 1701 1702 u32 val_b) 1702 1703 { ··· 1708 1707 if (rc < 0) 1709 1708 return AE_ERROR; 1710 1709 else if (rc > 0) 1711 - return AE_CTRL_SKIP; 1710 + return AE_CTRL_TERMINATE; 1712 1711 1713 1712 return AE_OK; 1714 1713 } 1714 + #else 1715 + acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state, u32 val_a, 1716 + u32 val_b) 1717 + { 1718 + return AE_OK; 1719 + } 1720 + #endif 1715 1721 1716 1722 void acpi_os_set_prepare_extended_sleep(int (*func)(u8 sleep_state, 1717 1723 u32 val_a, u32 val_b)) 1718 1724 { 1719 1725 __acpi_os_prepare_extended_sleep = func; 1726 + } 1727 + 1728 + acpi_status acpi_os_enter_sleep(u8 sleep_state, 1729 + u32 reg_a_value, u32 reg_b_value) 1730 + { 1731 + acpi_status status; 1732 + 1733 + if (acpi_gbl_reduced_hardware) 1734 + status = acpi_os_prepare_extended_sleep(sleep_state, 1735 + reg_a_value, 1736 + reg_b_value); 1737 + else 1738 + status = acpi_os_prepare_sleep(sleep_state, 1739 + reg_a_value, reg_b_value); 1740 + return status; 1720 1741 }
+3 -6
include/acpi/acexcep.h
··· 91 91 #define ACPI_SUCCESS(a) (!(a)) 92 92 #define ACPI_FAILURE(a) (a) 93 93 94 - #define ACPI_SKIP(a) (a == AE_CTRL_SKIP) 95 94 #define AE_OK (acpi_status) 0x0000 96 95 97 96 /* ··· 210 211 #define AE_CTRL_TRANSFER EXCEP_CTL (0x0008) 211 212 #define AE_CTRL_BREAK EXCEP_CTL (0x0009) 212 213 #define AE_CTRL_CONTINUE EXCEP_CTL (0x000A) 213 - #define AE_CTRL_SKIP EXCEP_CTL (0x000B) 214 - #define AE_CTRL_PARSE_CONTINUE EXCEP_CTL (0x000C) 215 - #define AE_CTRL_PARSE_PENDING EXCEP_CTL (0x000D) 214 + #define AE_CTRL_PARSE_CONTINUE EXCEP_CTL (0x000B) 215 + #define AE_CTRL_PARSE_PENDING EXCEP_CTL (0x000C) 216 216 217 - #define AE_CODE_CTRL_MAX 0x000D 217 + #define AE_CODE_CTRL_MAX 0x000C 218 218 219 219 /* Exception strings for acpi_format_exception */ 220 220 ··· 376 378 EXCEP_TXT("AE_CTRL_TRANSFER", "Transfer control to called method"), 377 379 EXCEP_TXT("AE_CTRL_BREAK", "A Break has been executed"), 378 380 EXCEP_TXT("AE_CTRL_CONTINUE", "A Continue has been executed"), 379 - EXCEP_TXT("AE_CTRL_SKIP", "Not currently used"), 380 381 EXCEP_TXT("AE_CTRL_PARSE_CONTINUE", "Used to skip over bad opcodes"), 381 382 EXCEP_TXT("AE_CTRL_PARSE_PENDING", "Used to implement AML While loops") 382 383 };
+4
include/acpi/acpiosxf.h
··· 333 333 acpi_status acpi_os_signal(u32 function, void *info); 334 334 #endif 335 335 336 + #ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_enter_sleep 337 + acpi_status acpi_os_enter_sleep(u8 sleep_state, u32 rega_value, u32 regb_value); 338 + #endif 339 + 336 340 /* 337 341 * Debug print routines 338 342 */
+22
tools/power/acpi/os_specific/service_layers/osunixxf.c
··· 318 318 319 319 /****************************************************************************** 320 320 * 321 + * FUNCTION: acpi_os_enter_sleep 322 + * 323 + * PARAMETERS: sleep_state - Which sleep state to enter 324 + * rega_value - Register A value 325 + * regb_value - Register B value 326 + * 327 + * RETURN: Status 328 + * 329 + * DESCRIPTION: A hook before writing sleep registers to enter the sleep 330 + * state. Return AE_CTRL_TERMINATE to skip further sleep register 331 + * writes. 332 + * 333 + *****************************************************************************/ 334 + 335 + acpi_status acpi_os_enter_sleep(u8 sleep_state, u32 rega_value, u32 regb_value) 336 + { 337 + 338 + return (AE_OK); 339 + } 340 + 341 + /****************************************************************************** 342 + * 321 343 * FUNCTION: acpi_os_redirect_output 322 344 * 323 345 * PARAMETERS: destination - An open file handle/pointer