diff options
author | Lv Zheng <lv.zheng@intel.com> | 2016-12-28 02:28:49 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2017-01-02 17:18:41 -0500 |
commit | 0fc5e8f4e4b33ddfa1d1d673fcd420d6e13eb076 (patch) | |
tree | 98882708adde1882b7aa110832c85df4b574a307 | |
parent | fcfb45531d7ef71a19caaa0a983611ca57ec04fe (diff) |
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>
-rw-r--r-- | drivers/acpi/acpica/hwesleep.c | 35 | ||||
-rw-r--r-- | drivers/acpi/acpica/hwsleep.c | 11 | ||||
-rw-r--r-- | drivers/acpi/osl.c | 27 | ||||
-rw-r--r-- | include/acpi/acexcep.h | 9 | ||||
-rw-r--r-- | include/acpi/acpiosxf.h | 4 | ||||
-rw-r--r-- | tools/power/acpi/os_specific/service_layers/osunixxf.c | 22 |
6 files changed, 76 insertions, 32 deletions
diff --git a/drivers/acpi/acpica/hwesleep.c b/drivers/acpi/acpica/hwesleep.c index 3f2fb4b31fdc..9023a1b87a54 100644 --- a/drivers/acpi/acpica/hwesleep.c +++ b/drivers/acpi/acpica/hwesleep.c | |||
@@ -43,7 +43,6 @@ | |||
43 | */ | 43 | */ |
44 | 44 | ||
45 | #include <acpi/acpi.h> | 45 | #include <acpi/acpi.h> |
46 | #include <linux/acpi.h> | ||
47 | #include "accommon.h" | 46 | #include "accommon.h" |
48 | 47 | ||
49 | #define _COMPONENT ACPI_HARDWARE | 48 | #define _COMPONENT ACPI_HARDWARE |
@@ -103,7 +102,7 @@ void acpi_hw_execute_sleep_method(char *method_pathname, u32 integer_argument) | |||
103 | acpi_status acpi_hw_extended_sleep(u8 sleep_state) | 102 | acpi_status acpi_hw_extended_sleep(u8 sleep_state) |
104 | { | 103 | { |
105 | acpi_status status; | 104 | acpi_status status; |
106 | u8 sleep_type_value; | 105 | u8 sleep_control; |
107 | u64 sleep_status; | 106 | u64 sleep_status; |
108 | 107 | ||
109 | ACPI_FUNCTION_TRACE(hw_extended_sleep); | 108 | ACPI_FUNCTION_TRACE(hw_extended_sleep); |
@@ -125,18 +124,6 @@ acpi_status acpi_hw_extended_sleep(u8 sleep_state) | |||
125 | 124 | ||
126 | acpi_gbl_system_awake_and_running = FALSE; | 125 | acpi_gbl_system_awake_and_running = FALSE; |
127 | 126 | ||
128 | /* Flush caches, as per ACPI specification */ | ||
129 | |||
130 | ACPI_FLUSH_CPU_CACHE(); | ||
131 | |||
132 | status = acpi_os_prepare_extended_sleep(sleep_state, | ||
133 | acpi_gbl_sleep_type_a, | ||
134 | acpi_gbl_sleep_type_b); | ||
135 | if (ACPI_SKIP(status)) | ||
136 | return_ACPI_STATUS(AE_OK); | ||
137 | if (ACPI_FAILURE(status)) | ||
138 | return_ACPI_STATUS(status); | ||
139 | |||
140 | /* | 127 | /* |
141 | * Set the SLP_TYP and SLP_EN bits. | 128 | * Set the SLP_TYP and SLP_EN bits. |
142 | * | 129 | * |
@@ -146,12 +133,22 @@ acpi_status acpi_hw_extended_sleep(u8 sleep_state) | |||
146 | ACPI_DEBUG_PRINT((ACPI_DB_INIT, | 133 | ACPI_DEBUG_PRINT((ACPI_DB_INIT, |
147 | "Entering sleep state [S%u]\n", sleep_state)); | 134 | "Entering sleep state [S%u]\n", sleep_state)); |
148 | 135 | ||
149 | sleep_type_value = | 136 | sleep_control = ((acpi_gbl_sleep_type_a << ACPI_X_SLEEP_TYPE_POSITION) & |
150 | ((acpi_gbl_sleep_type_a << ACPI_X_SLEEP_TYPE_POSITION) & | 137 | ACPI_X_SLEEP_TYPE_MASK) | ACPI_X_SLEEP_ENABLE; |
151 | ACPI_X_SLEEP_TYPE_MASK); | 138 | |
139 | /* Flush caches, as per ACPI specification */ | ||
140 | |||
141 | ACPI_FLUSH_CPU_CACHE(); | ||
142 | |||
143 | status = acpi_os_enter_sleep(sleep_state, sleep_control, 0); | ||
144 | if (status == AE_CTRL_TERMINATE) { | ||
145 | return_ACPI_STATUS(AE_OK); | ||
146 | } | ||
147 | if (ACPI_FAILURE(status)) { | ||
148 | return_ACPI_STATUS(status); | ||
149 | } | ||
152 | 150 | ||
153 | status = acpi_write((u64)(sleep_type_value | ACPI_X_SLEEP_ENABLE), | 151 | status = acpi_write((u64)sleep_control, &acpi_gbl_FADT.sleep_control); |
154 | &acpi_gbl_FADT.sleep_control); | ||
155 | if (ACPI_FAILURE(status)) { | 152 | if (ACPI_FAILURE(status)) { |
156 | return_ACPI_STATUS(status); | 153 | return_ACPI_STATUS(status); |
157 | } | 154 | } |
diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c index d00c9810845b..563c5d91663f 100644 --- a/drivers/acpi/acpica/hwsleep.c +++ b/drivers/acpi/acpica/hwsleep.c | |||
@@ -43,7 +43,6 @@ | |||
43 | */ | 43 | */ |
44 | 44 | ||
45 | #include <acpi/acpi.h> | 45 | #include <acpi/acpi.h> |
46 | #include <linux/acpi.h> | ||
47 | #include "accommon.h" | 46 | #include "accommon.h" |
48 | 47 | ||
49 | #define _COMPONENT ACPI_HARDWARE | 48 | #define _COMPONENT ACPI_HARDWARE |
@@ -152,12 +151,14 @@ acpi_status acpi_hw_legacy_sleep(u8 sleep_state) | |||
152 | 151 | ||
153 | ACPI_FLUSH_CPU_CACHE(); | 152 | ACPI_FLUSH_CPU_CACHE(); |
154 | 153 | ||
155 | status = acpi_os_prepare_sleep(sleep_state, pm1a_control, | 154 | status = acpi_os_enter_sleep(sleep_state, pm1a_control, pm1b_control); |
156 | pm1b_control); | 155 | if (status == AE_CTRL_TERMINATE) { |
157 | if (ACPI_SKIP(status)) | ||
158 | return_ACPI_STATUS(AE_OK); | 156 | return_ACPI_STATUS(AE_OK); |
159 | if (ACPI_FAILURE(status)) | 157 | } |
158 | if (ACPI_FAILURE(status)) { | ||
160 | return_ACPI_STATUS(status); | 159 | return_ACPI_STATUS(status); |
160 | } | ||
161 | |||
161 | /* Write #2: Write both SLP_TYP + SLP_EN */ | 162 | /* Write #2: Write both SLP_TYP + SLP_EN */ |
162 | 163 | ||
163 | status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control); | 164 | status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control); |
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 57fb5f468ac2..db78d353bab1 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
@@ -1686,7 +1686,7 @@ acpi_status acpi_os_prepare_sleep(u8 sleep_state, u32 pm1a_control, | |||
1686 | if (rc < 0) | 1686 | if (rc < 0) |
1687 | return AE_ERROR; | 1687 | return AE_ERROR; |
1688 | else if (rc > 0) | 1688 | else if (rc > 0) |
1689 | return AE_CTRL_SKIP; | 1689 | return AE_CTRL_TERMINATE; |
1690 | 1690 | ||
1691 | return AE_OK; | 1691 | return AE_OK; |
1692 | } | 1692 | } |
@@ -1697,6 +1697,7 @@ void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state, | |||
1697 | __acpi_os_prepare_sleep = func; | 1697 | __acpi_os_prepare_sleep = func; |
1698 | } | 1698 | } |
1699 | 1699 | ||
1700 | #if (ACPI_REDUCED_HARDWARE) | ||
1700 | acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state, u32 val_a, | 1701 | acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state, u32 val_a, |
1701 | u32 val_b) | 1702 | u32 val_b) |
1702 | { | 1703 | { |
@@ -1707,13 +1708,35 @@ acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state, u32 val_a, | |||
1707 | if (rc < 0) | 1708 | if (rc < 0) |
1708 | return AE_ERROR; | 1709 | return AE_ERROR; |
1709 | else if (rc > 0) | 1710 | else if (rc > 0) |
1710 | return AE_CTRL_SKIP; | 1711 | return AE_CTRL_TERMINATE; |
1711 | 1712 | ||
1712 | return AE_OK; | 1713 | return AE_OK; |
1713 | } | 1714 | } |
1715 | #else | ||
1716 | acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state, u32 val_a, | ||
1717 | u32 val_b) | ||
1718 | { | ||
1719 | return AE_OK; | ||
1720 | } | ||
1721 | #endif | ||
1714 | 1722 | ||
1715 | void acpi_os_set_prepare_extended_sleep(int (*func)(u8 sleep_state, | 1723 | void acpi_os_set_prepare_extended_sleep(int (*func)(u8 sleep_state, |
1716 | u32 val_a, u32 val_b)) | 1724 | u32 val_a, u32 val_b)) |
1717 | { | 1725 | { |
1718 | __acpi_os_prepare_extended_sleep = func; | 1726 | __acpi_os_prepare_extended_sleep = func; |
1719 | } | 1727 | } |
1728 | |||
1729 | acpi_status acpi_os_enter_sleep(u8 sleep_state, | ||
1730 | u32 reg_a_value, u32 reg_b_value) | ||
1731 | { | ||
1732 | acpi_status status; | ||
1733 | |||
1734 | if (acpi_gbl_reduced_hardware) | ||
1735 | status = acpi_os_prepare_extended_sleep(sleep_state, | ||
1736 | reg_a_value, | ||
1737 | reg_b_value); | ||
1738 | else | ||
1739 | status = acpi_os_prepare_sleep(sleep_state, | ||
1740 | reg_a_value, reg_b_value); | ||
1741 | return status; | ||
1742 | } | ||
diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h index 2c396344a7a2..1155002761a7 100644 --- a/include/acpi/acexcep.h +++ b/include/acpi/acexcep.h | |||
@@ -91,7 +91,6 @@ struct acpi_exception_info { | |||
91 | #define ACPI_SUCCESS(a) (!(a)) | 91 | #define ACPI_SUCCESS(a) (!(a)) |
92 | #define ACPI_FAILURE(a) (a) | 92 | #define ACPI_FAILURE(a) (a) |
93 | 93 | ||
94 | #define ACPI_SKIP(a) (a == AE_CTRL_SKIP) | ||
95 | #define AE_OK (acpi_status) 0x0000 | 94 | #define AE_OK (acpi_status) 0x0000 |
96 | 95 | ||
97 | /* | 96 | /* |
@@ -211,11 +210,10 @@ struct acpi_exception_info { | |||
211 | #define AE_CTRL_TRANSFER EXCEP_CTL (0x0008) | 210 | #define AE_CTRL_TRANSFER EXCEP_CTL (0x0008) |
212 | #define AE_CTRL_BREAK EXCEP_CTL (0x0009) | 211 | #define AE_CTRL_BREAK EXCEP_CTL (0x0009) |
213 | #define AE_CTRL_CONTINUE EXCEP_CTL (0x000A) | 212 | #define AE_CTRL_CONTINUE EXCEP_CTL (0x000A) |
214 | #define AE_CTRL_SKIP EXCEP_CTL (0x000B) | 213 | #define AE_CTRL_PARSE_CONTINUE EXCEP_CTL (0x000B) |
215 | #define AE_CTRL_PARSE_CONTINUE EXCEP_CTL (0x000C) | 214 | #define AE_CTRL_PARSE_PENDING EXCEP_CTL (0x000C) |
216 | #define AE_CTRL_PARSE_PENDING EXCEP_CTL (0x000D) | ||
217 | 215 | ||
218 | #define AE_CODE_CTRL_MAX 0x000D | 216 | #define AE_CODE_CTRL_MAX 0x000C |
219 | 217 | ||
220 | /* Exception strings for acpi_format_exception */ | 218 | /* Exception strings for acpi_format_exception */ |
221 | 219 | ||
@@ -378,7 +376,6 @@ static const struct acpi_exception_info acpi_gbl_exception_names_ctrl[] = { | |||
378 | EXCEP_TXT("AE_CTRL_TRANSFER", "Transfer control to called method"), | 376 | EXCEP_TXT("AE_CTRL_TRANSFER", "Transfer control to called method"), |
379 | EXCEP_TXT("AE_CTRL_BREAK", "A Break has been executed"), | 377 | EXCEP_TXT("AE_CTRL_BREAK", "A Break has been executed"), |
380 | EXCEP_TXT("AE_CTRL_CONTINUE", "A Continue has been executed"), | 378 | EXCEP_TXT("AE_CTRL_CONTINUE", "A Continue has been executed"), |
381 | EXCEP_TXT("AE_CTRL_SKIP", "Not currently used"), | ||
382 | EXCEP_TXT("AE_CTRL_PARSE_CONTINUE", "Used to skip over bad opcodes"), | 379 | EXCEP_TXT("AE_CTRL_PARSE_CONTINUE", "Used to skip over bad opcodes"), |
383 | EXCEP_TXT("AE_CTRL_PARSE_PENDING", "Used to implement AML While loops") | 380 | EXCEP_TXT("AE_CTRL_PARSE_PENDING", "Used to implement AML While loops") |
384 | }; | 381 | }; |
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h index 42ab9b37f33d..e166013b4712 100644 --- a/include/acpi/acpiosxf.h +++ b/include/acpi/acpiosxf.h | |||
@@ -333,6 +333,10 @@ u64 acpi_os_get_timer(void); | |||
333 | acpi_status acpi_os_signal(u32 function, void *info); | 333 | acpi_status acpi_os_signal(u32 function, void *info); |
334 | #endif | 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 | * Debug print routines | 341 | * Debug print routines |
338 | */ | 342 | */ |
diff --git a/tools/power/acpi/os_specific/service_layers/osunixxf.c b/tools/power/acpi/os_specific/service_layers/osunixxf.c index 10648aaf6164..e41c2644c347 100644 --- a/tools/power/acpi/os_specific/service_layers/osunixxf.c +++ b/tools/power/acpi/os_specific/service_layers/osunixxf.c | |||
@@ -318,6 +318,28 @@ acpi_os_physical_table_override(struct acpi_table_header *existing_table, | |||
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 | * FUNCTION: acpi_os_redirect_output | 343 | * FUNCTION: acpi_os_redirect_output |
322 | * | 344 | * |
323 | * PARAMETERS: destination - An open file handle/pointer | 345 | * PARAMETERS: destination - An open file handle/pointer |