Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1400508 > unrolled thread
| Started by | Lv Zheng <lv.zheng@intel.com> |
|---|---|
| First post | 2016-05-13 07:40 +0200 |
| Last post | 2016-05-20 03:00 +0200 |
| Articles | 6 — 3 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
[PATCH v2 0/4] ACPI 2.0: Enable TermList interpretion for table loading Lv Zheng <lv.zheng@intel.com> - 2016-05-13 07:40 +0200
[PATCH v2 3/4] ACPI 2.0 / AML: Enable correct ACPI subsystem initialization order for new table loading mode Lv Zheng <lv.zheng@intel.com> - 2016-05-13 07:40 +0200
[PATCH v2 2/4] ACPICA: ACPI 2.0, Interpreter: Fix MLC issues by switching to new TermList grammar for table loading Lv Zheng <lv.zheng@intel.com> - 2016-05-13 07:40 +0200
RE: [PATCH v2 0/4] ACPI 2.0: Enable TermList interpretion for table loading "Zheng, Lv" <lv.zheng@intel.com> - 2016-05-17 02:30 +0200
Re: [PATCH v2 0/4] ACPI 2.0: Enable TermList interpretion for table loading "Rafael J. Wysocki" <rafael@kernel.org> - 2016-05-18 01:30 +0200
RE: [PATCH v2 0/4] ACPI 2.0: Enable TermList interpretion for table loading "Zheng, Lv" <lv.zheng@intel.com> - 2016-05-20 03:00 +0200
| From | Lv Zheng <lv.zheng@intel.com> |
|---|---|
| Date | 2016-05-13 07:40 +0200 |
| Subject | [PATCH v2 0/4] ACPI 2.0: Enable TermList interpretion for table loading |
| Message-ID | <rydZo-52M-7@gated-at.bofh.it> |
MLC (module level code) is an ACPICA terminology describing the AML code
out of any control method, currently only Type1Opcode (If/Else/While)
wrapped MLC code blocks are executed by the AML interpreter after the table
loading. But the issue which is fixed by this patchset is:
Not only Type1Opcode, but also Type2Opcode will be executed as MLC and
MLC is not executed after loading the table, but is executed right in
place.
The following AML code is assembled into a static loading SSDT, and used
as an instrumentation to pry into the de-facto standard AML interpreter
behaviors:
Name (ECOK, Zero)
Scope (\)
{
DBUG ("TermList 1")
If (LEqual (ECOK, Zero))
{
DBUG ("TermList 2")
Device (MDEV)
{
DEBUG (TermList 3")
If (CondRefOf (MDEV))
{
DBUG ("MDEV exists")
}
If (CondRefOf (MDEV._STA))
{
DBUG ("MDEV._STA exists")
}
If (CondRefOf (\_SB.PCI0.EC))
{
DBUG ("\\_SB.PCI0.EC exists")
}
Name (_HID, EisaId ("PNP9999"))
Method (_STA, 0, Serialized)
{
DEBUG ("\\_SB.MDEV._STA")
Return (0x0F)
}
}
DBUG ("TermList 4")
}
Method (_INI, 0, Serialized)
{
DBUG ("\\_SB._INI")
}
}
Scope (_SB.PCI0)
{
Device (EC)
{
...
}
}
The DBUG function is a function to write the debugging messages into a
SystemIo debug port.
Running Windows with the BIOS providing this SSDT via RSDT, the following
messages are obtained from the debug port:
TermList 1
TermList 2
TermList 3
\_SB.MDEV exists
TermList 4
\_SB._INI
...
This test reveals the de-facto grammar for the AMLCode to us:
1. During the table loading, MLC will be executed by the interpreter, this
is partially supported by the current ACPICA;
2. For SystemIo, not only after the _REG(1, 1) is evaluated (current ACPICA
interpreter limitation), but when the table is being loaded, the
SystemIo (the debugging port) is accessible, this is recently fixed in
the upstream, now all early operation regions are accessible during the
table loading;
3. Not only Type1Opcode, but also Type2Opcode will be executed as MLC and
MLC is not executed after loading the table, but is executed right in
place, the Linux upstream is not compliant to this behavior.
The last compliance issue has already been clarified in ACPI 2.0
specification, so the compliance issue is not that Linux is not compliant
to the de-facto standard OS, but that Linux is not compliant to ACPI 2.0.
Definition block tables in fact is defined by the spec as TermList, which
has no difference than the control methods, thus the interpretion of the
table should be no difference that the control method evaluation:
AMLCode := DefBlockHeader TermList
DefMethod := MethodOp PkgLength NameString MethodFlags TermList
Why ACPICA interpreter is acting so differently from this definition? This
is because, there are many software entropies preventing this from being
enabled, such entropies need to be cleaned up first in order not to trigger
regressions for specific platforms. These entropies include:
1. ECDT support is broken. In fact, the original EC driver was correct, but
devlopers started to use the namespace EC instead of ECDT just because
several broken ECDT tables were reported on the bugzilla. They trusted
the namespace EC settings rather than the ECDT ones, this led to the
evaluation of _REG/_GPE/_CRS and namespace walk before executing the
module level AML opcodes. And the fixes in fact finally disable early EC
usages (used during table loading and early device enumeration
processes).
2. _REG evaluations are wrong. ACPICA provides APIs for OSPMs to register
operation region handlers. But for the early operation region accesses,
ACPI spec declares that the evaluations of _REG are not required, but
the ACPICA APIs do not avoid running _REG to meet this early
requirements. Code to fix this is partially upstreamed during previous
ACPICA release cycle.
3. _REG associations are wrong. ACPICA associates _REG control method to
all operation region objects before executing the _REG control method.
This can happen even when a control method is evaluated and operation
regions defined in the method is initialized
(acpi_ev_initialize_region). As a part of the ACPICA internal _REG
evaluation state machine, it requires the namespace walk, and all
namespace walk should be ensured to happen only "AFTER THE NAMESPACE IS
INITIALIZED". But when this logic happens during the table loading, it
may fail in finding the _REG method since the _REG method may not be
created by the interpreter just because _REG is defined after the
operation region object's declaration.
4. _REG(CONNECT)/_REG(DISCONNECT) executions are not balanced, this can
lead to wrong table loading/unloading results. Since _REG evaluations
require the releasing of all interpreter/namespace locks in order to
allow another evaluation to happen, and ACPICA operand object
destruction code can be invoked from different locking environment, this
becomes difficult for the developers to provide one single function to
make _REG(CONNECT)/_REG(DISCONNECT) balanced.
5. \_SB._INI is not the first control method evaluated by the interpreter.
Many platforms put initialization code in \_SB._INI in order to have
named objects initialized very early during the device enumeration
process. Without this order strictly ensured, early operation region
access enabling could break these platforms.
6. Linux initialization order is wrong, it is now:
a. load namespace without executing root scope If/Else/While module
level code blocks;
b. probe ECDT and instal EmbeddedControl operation region handler with
_REG evaluated;
c. install SystemMemory, SystemIo, PciConfig operation region handlers
without evaluating _REG;
d. run _REG for SystemMemory, SystemIo, PciConfig operation regions;
e. execute root scope If/Else/While module level code blocks;
f. enable GPE and namespace EC.
While the correct order should be:
a. probe ECDT and install EmbeddedControl operation region handler
without evaluating _REG;
b. install SystemMemory, SystemIo, PciConfig operation region handlers
without evaluating _REG;
c. load namespace, in the meanshile, execute all module level AML
opcodes;
d. run _REG for SystemMemory, SystemIo, PciConfig operation regions;
e. enable GPE and namespace EC which results in _REG evaluation for EC.
Until now we've upstreamed most of the entropy fixes into the Linux kernel,
tested the grammar switch in the ACPICA upstream using ASLTS and no
significant regressions can be seen while we need more tests before it is
merged:
https://github.com/acpica/acpica/pull/134
This is the ASLTS running result after applying the grammar switch, the
test cases include new "module" case for which ACPICA interpreter cannot
pass without this grammar switch applied:
============================================================
Test cases specified for running:
arithmetic
bfield
constant
control
descriptor
logic
manipulation
name
reference
region
synchronization
table
misc
provoke
oarg
oconst
olocal
onamedloc
onamedglob
opackageel
oreftonamed
oreftopackageel
oreturn
rstore
roptional
rcopyobject
rindecrement
rexplicitconv
badasl
namespace
exc
exc_ref
exc_operand2
exc_result2
exc_tbl
mt_mutex
extra
extra_aslts
bdemo
bdemof
condbranches
TOTAL: (32-bit norm mode)
PASS : 0
FAIL : 0
BLOCKED : 0
SKIPPED : 0
Tests : 0
Test Cases : 40 (of 47)
Test Collections : 7 (of 8)
Outstanding allocations after execution : 0
Outstanding allocations (ACPI Error) : 0
Large Reference Count (ACPI Error) : 0
Memory consumption total : 0 Kb
TOTAL: (64-bit norm mode)
PASS : 0
FAIL : 0
BLOCKED : 0
SKIPPED : 0
Tests : 0
Test Cases : 40 (of 47)
Test Collections : 7 (of 8)
Outstanding allocations after execution : 0
Outstanding allocations (ACPI Error) : 0
Large Reference Count (ACPI Error) : 0
Memory consumption total : 0 Kb
TOTAL: (32-bit slack mode)
PASS : 0
FAIL : 0
BLOCKED : 0
SKIPPED : 0
Tests : 0
Test Cases : 40 (of 47)
Test Collections : 7 (of 8)
Outstanding allocations after execution : 0
Outstanding allocations (ACPI Error) : 0
Large Reference Count (ACPI Error) : 0
Memory consumption total : 0 Kb
TOTAL: (64-bit slack mode)
PASS : 0
FAIL : 0
BLOCKED : 0
SKIPPED : 0
Tests : 0
Test Cases : 40 (of 47)
Test Collections : 7 (of 8)
Outstanding allocations after execution : 0
Outstanding allocations (ACPI Error) : 0
Large Reference Count (ACPI Error) : 0
Memory consumption total : 0 Kb
============================================================
Since we need more tests from the real users, we could make the grammar
switch released from the Linux upstream. It's safe to do so because we have
implemented regression protection (acpi_gbl_parse_table_as_term_list) in
the fixes. The earlier the fix is tested by more real users, the better
quality can be achieved by knowing the unknown cases (if any).
Lv Zheng (4):
ACPICA: Dispatcher: Fix an issue that the opregions created by the
linked MLC were not tracked
ACPICA: ACPI 2.0, Interpreter: Fix MLC issues by switching to new
TermList grammar for table loading
ACPI 2.0 / AML: Enable correct ACPI subsystem initialization order
for new table loading mode
ACPI 2.0 / AML: Fix module level execution by correctly parsing table
as TermList
drivers/acpi/acpica/acnamesp.h | 3 +
drivers/acpi/acpica/acparser.h | 2 +
drivers/acpi/acpica/dsopcode.c | 6 ++
drivers/acpi/acpica/evrgnini.c | 3 +-
drivers/acpi/acpica/exconfig.c | 6 +-
drivers/acpi/acpica/nsload.c | 3 +-
drivers/acpi/acpica/nsparse.c | 163 ++++++++++++++++++++++++++++++++--------
drivers/acpi/acpica/psparse.c | 4 +-
drivers/acpi/acpica/psxface.c | 73 ++++++++++++++++++
drivers/acpi/acpica/tbxfload.c | 3 +-
drivers/acpi/acpica/utxfinit.c | 3 +-
drivers/acpi/bus.c | 6 +-
include/acpi/acpixf.h | 6 ++
13 files changed, 241 insertions(+), 40 deletions(-)
--
1.7.10
[toc] | [next] | [standalone]
| From | Lv Zheng <lv.zheng@intel.com> |
|---|---|
| Date | 2016-05-13 07:40 +0200 |
| Subject | [PATCH v2 3/4] ACPI 2.0 / AML: Enable correct ACPI subsystem initialization order for new table loading mode |
| Message-ID | <rydZp-52M-27@gated-at.bofh.it> |
| In reply to | #1400508 |
This patch enables the following initialization order for the new table
loading mode (which is enabled by setting
acpi_gbl_parse_table_as_term_list to TRUE):
1. Install default region handlers (SystemMemory, SystemIo, PciConfig,
EmbeddedControl via ECDT) without evaluating _REG;
2. Load the table and execute the module level AML opcodes instantly.
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
---
drivers/acpi/bus.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 31e8da6..d177649 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -925,7 +925,8 @@ void __init acpi_early_init(void)
goto error0;
}
- if (acpi_gbl_group_module_level_code) {
+ if (!acpi_gbl_parse_table_as_term_list &&
+ acpi_gbl_group_module_level_code) {
status = acpi_load_tables();
if (ACPI_FAILURE(status)) {
printk(KERN_ERR PREFIX
@@ -1008,7 +1009,8 @@ static int __init acpi_bus_init(void)
status = acpi_ec_ecdt_probe();
/* Ignore result. Not having an ECDT is not fatal. */
- if (!acpi_gbl_group_module_level_code) {
+ if (acpi_gbl_parse_table_as_term_list ||
+ !acpi_gbl_group_module_level_code) {
status = acpi_load_tables();
if (ACPI_FAILURE(status)) {
printk(KERN_ERR PREFIX
--
1.7.10
[toc] | [prev] | [next] | [standalone]
| From | Lv Zheng <lv.zheng@intel.com> |
|---|---|
| Date | 2016-05-13 07:40 +0200 |
| Subject | [PATCH v2 2/4] ACPICA: ACPI 2.0, Interpreter: Fix MLC issues by switching to new TermList grammar for table loading |
| Message-ID | <rydZp-52M-31@gated-at.bofh.it> |
| In reply to | #1400508 |
The MLC (Module Level Code) is an ACPICA terminology describing the AML
code out of any control method, its support is the main contention of the
interpreter behavior during the table loading.
The original implementation of MLC in ACPICA had several issues:
1. Out of any control method, besides of the object creating opcodes, only
the code blocks wrapped by "If/Else/While" opcodes were supported.
2. The supported MLC code blocks were executed after loading the table
rather than being executed right in place.
============================================================
The demo of this order issue is as follows:
Name (OBJ1, 1)
If (CND1 == 1)
{
Name (OBJ2, 2)
}
Name (OBJ3, 3)
The original MLC support created OBJ2 after OBJ3's creation.
============================================================
Other than these limitations, MLC support in ACPICA looks correct. And
supporting this should be easy/natural for ACPICA, but enabling of this was
blocked by some ACPICA internal and OSPM specific initialization order
issues we've fixed recently. The wrong support started from the following
false bug fixing commit:
Commit: 80d7951177315f70b5ffd8663985fbf725d07799
Subject: Add support for module-level executable AML code.
We can confirm Windows interpreter behavior via reverse engineering means.
It can be proven that not only If/Else/While wrapped code blocks, all
opcodes can be executed at the module level, including operation region
accesses. And it can be proven that the MLC should be executed right in
place, not in such a deferred way executed after loading the table.
And the above facts indeed reflect the spec words around ACPI definition
block tables (DSDT/SSDT/...), the entire table and the Scope object is
defined by the AML specification in BNF style as:
AMLCode := DefBlockHeader TermList
DefScope := ScopeOp PkgLength NameString TermList
The bodies of the scope opening terms (AMLCode/Scope) are all TermList,
thus the table loading should be no difference than the control method
evaluations as the body of the Method is also defined by the AML
specification as TermList:
DefMethod := MethodOp PkgLength NameString MethodFlags TermList
The only difference is: after evaluating control method, created named
objects may be freed due to no reference, while named objects created by
the table loading should only be freed after unloading the table.
So this patch follows the spec and the de-facto standard behavior, enables
the new grammar (TermList) for the table loading.
By doing so, beyond the fixes to the above issues, we can see additional
differences comparing to the old grammar based table loading:
1. Originally, beyond the scope opening terms (AMLCode/Scope),
If/Else/While wrapped code blocks under the scope creating terms
(Device/PowerResource/Processor/ThermalZone) are also supported as
deferred MLC, which violates the spec defined grammar where ObjectList
is enforced. With MLC support improved as non-deferred, the interpreter
parses such scope creating terms as TermList rather ObjectList like the
scope opening terms.
After probing the Windows behavior and proving that it also parses these
terms as TermList, we submitted an ECR (Engineering Change Request) to
the ASWG (ACPI Specification Working Group) to clarify this. The ECR is
titled as "ASL Grammar Clarification for Executable AML Opcodes" and has
been accepted by the ASWG. The new grammar will appear in ACPI
specification 6.2.
2. Originally, Buffer/Package/OperationRegion/CreateXXXField/BankField
arguments are evaluated in a deferred way after loading the table. With
MLC support improved, they are also parsed right in place during the
table loading.
This is also Windows compliant and the only difference is the removal
of the debugging messages implemented before acpi_ds_execute_arguments(),
see Link 1 for the details. A previous commit should have ensured that
acpi_check_address_range() won't regress.
Note that enabling this feature may cause regressions due to long term
Linux ACPI support on top of the wrong grammar. So this patch also prepares
a global option to be used to roll back to the old grammar during the
period between a regression is reported and the regression is
root-cause-fixed. ACPICA BZ 963, fixed by Lv Zheng.
Link 1: https://bugzilla.kernel.org/show_bug.cgi?id=112911
Link 2: https://bugs.acpica.org/show_bug.cgi?id=963
Tested-by: Chris Bainbridge <chris.bainbridge@gmail.com>
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
---
drivers/acpi/acpica/acnamesp.h | 3 +
drivers/acpi/acpica/acparser.h | 2 +
drivers/acpi/acpica/evrgnini.c | 3 +-
drivers/acpi/acpica/exconfig.c | 6 +-
drivers/acpi/acpica/nsload.c | 3 +-
drivers/acpi/acpica/nsparse.c | 163 ++++++++++++++++++++++++++++++++--------
drivers/acpi/acpica/psparse.c | 4 +-
drivers/acpi/acpica/psxface.c | 73 ++++++++++++++++++
drivers/acpi/acpica/tbxfload.c | 3 +-
drivers/acpi/acpica/utxfinit.c | 3 +-
include/acpi/acpixf.h | 6 ++
11 files changed, 231 insertions(+), 38 deletions(-)
diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h
index f33a4ba..829672a 100644
--- a/drivers/acpi/acpica/acnamesp.h
+++ b/drivers/acpi/acpica/acnamesp.h
@@ -130,6 +130,9 @@ acpi_status
acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node);
acpi_status
+acpi_ns_execute_table(u32 table_index, struct acpi_namespace_node *start_node);
+
+acpi_status
acpi_ns_one_complete_parse(u32 pass_number,
u32 table_index,
struct acpi_namespace_node *start_node);
diff --git a/drivers/acpi/acpica/acparser.h b/drivers/acpi/acpica/acparser.h
index fc30577..939d411 100644
--- a/drivers/acpi/acpica/acparser.h
+++ b/drivers/acpi/acpica/acparser.h
@@ -78,6 +78,8 @@ extern const u8 acpi_gbl_long_op_index[];
*/
acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info);
+acpi_status acpi_ps_execute_table(struct acpi_evaluate_info *info);
+
/*
* psargs - Parse AML opcode arguments
*/
diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c
index b6ea9c0..3843f1f 100644
--- a/drivers/acpi/acpica/evrgnini.c
+++ b/drivers/acpi/acpica/evrgnini.c
@@ -553,7 +553,8 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj,
*
* See acpi_ns_exec_module_code
*/
- if (obj_desc->method.
+ if (!acpi_gbl_parse_table_as_term_list &&
+ obj_desc->method.
info_flags & ACPI_METHOD_MODULE_LEVEL) {
handler_obj =
obj_desc->method.dispatch.handler;
diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c
index a1d177d..3918c33 100644
--- a/drivers/acpi/acpica/exconfig.c
+++ b/drivers/acpi/acpica/exconfig.c
@@ -108,8 +108,10 @@ acpi_ex_add_table(u32 table_index,
/* Add the table to the namespace */
+ acpi_ex_exit_interpreter();
status = acpi_ns_load_table(table_index, parent_node);
if (ACPI_FAILURE(status)) {
+ acpi_ex_enter_interpreter();
acpi_ut_remove_reference(obj_desc);
*ddb_handle = NULL;
return_ACPI_STATUS(status);
@@ -117,8 +119,8 @@ acpi_ex_add_table(u32 table_index,
/* Execute any module-level code that was found in the table */
- acpi_ex_exit_interpreter();
- if (acpi_gbl_group_module_level_code) {
+ if (!acpi_gbl_parse_table_as_term_list
+ && acpi_gbl_group_module_level_code) {
acpi_ns_exec_module_code_list();
}
acpi_ex_enter_interpreter();
diff --git a/drivers/acpi/acpica/nsload.c b/drivers/acpi/acpica/nsload.c
index b5e2b0a..2daa9a09 100644
--- a/drivers/acpi/acpica/nsload.c
+++ b/drivers/acpi/acpica/nsload.c
@@ -162,7 +162,8 @@ unlock:
* other ACPI implementations. Optionally, the execution can be deferred
* until later, see acpi_initialize_objects.
*/
- if (!acpi_gbl_group_module_level_code) {
+ if (!acpi_gbl_parse_table_as_term_list
+ && !acpi_gbl_group_module_level_code) {
acpi_ns_exec_module_code_list();
}
diff --git a/drivers/acpi/acpica/nsparse.c b/drivers/acpi/acpica/nsparse.c
index f631a47..2452bf3 100644
--- a/drivers/acpi/acpica/nsparse.c
+++ b/drivers/acpi/acpica/nsparse.c
@@ -47,12 +47,103 @@
#include "acparser.h"
#include "acdispat.h"
#include "actables.h"
+#include "acinterp.h"
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nsparse")
/*******************************************************************************
*
+ * FUNCTION: ns_execute_table
+ *
+ * PARAMETERS: table_desc - An ACPI table descriptor for table to parse
+ * start_node - Where to enter the table into the namespace
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Load ACPI/AML table by executing the entire table as a
+ * term_list.
+ *
+ ******************************************************************************/
+acpi_status
+acpi_ns_execute_table(u32 table_index, struct acpi_namespace_node *start_node)
+{
+ acpi_status status;
+ struct acpi_table_header *table;
+ acpi_owner_id owner_id;
+ struct acpi_evaluate_info *info = NULL;
+ u32 aml_length;
+ u8 *aml_start;
+ union acpi_operand_object *method_obj = NULL;
+
+ ACPI_FUNCTION_TRACE(ns_execute_table);
+
+ status = acpi_get_table_by_index(table_index, &table);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ /* Table must consist of at least a complete header */
+
+ if (table->length < sizeof(struct acpi_table_header)) {
+ return_ACPI_STATUS(AE_BAD_HEADER);
+ }
+
+ aml_start = (u8 *)table + sizeof(struct acpi_table_header);
+ aml_length = table->length - sizeof(struct acpi_table_header);
+
+ status = acpi_tb_get_owner_id(table_index, &owner_id);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ /* Create, initialize, and link a new temporary method object */
+
+ method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD);
+ if (!method_obj) {
+ return_ACPI_STATUS(AE_NO_MEMORY);
+ }
+
+ /* Allocate the evaluation information block */
+
+ info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
+ if (!info) {
+ status = AE_NO_MEMORY;
+ goto cleanup;
+ }
+
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "Create table code block: %p\n", method_obj));
+
+ method_obj->method.aml_start = aml_start;
+ method_obj->method.aml_length = aml_length;
+ method_obj->method.owner_id = owner_id;
+ method_obj->method.info_flags |= ACPI_METHOD_MODULE_LEVEL;
+
+ info->pass_number = ACPI_IMODE_EXECUTE;
+ info->node = start_node;
+ info->obj_desc = method_obj;
+ info->node_flags = info->node->flags;
+ info->full_pathname = acpi_ns_get_normalized_pathname(info->node, TRUE);
+ if (!info->full_pathname) {
+ status = AE_NO_MEMORY;
+ goto cleanup;
+ }
+
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ status = acpi_ps_execute_table(info);
+ (void)acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+
+cleanup:
+ acpi_ut_remove_reference(method_obj);
+ ACPI_FREE(info->full_pathname);
+ info->full_pathname = NULL;
+ ACPI_FREE(info);
+ return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
* FUNCTION: ns_one_complete_parse
*
* PARAMETERS: pass_number - 1 or 2
@@ -63,6 +154,7 @@ ACPI_MODULE_NAME("nsparse")
* DESCRIPTION: Perform one complete parse of an ACPI/AML table.
*
******************************************************************************/
+
acpi_status
acpi_ns_one_complete_parse(u32 pass_number,
u32 table_index,
@@ -170,38 +262,47 @@ acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node)
ACPI_FUNCTION_TRACE(ns_parse_table);
- /*
- * AML Parse, pass 1
- *
- * In this pass, we load most of the namespace. Control methods
- * are not parsed until later. A parse tree is not created. Instead,
- * each Parser Op subtree is deleted when it is finished. This saves
- * a great deal of memory, and allows a small cache of parse objects
- * to service the entire parse. The second pass of the parse then
- * performs another complete parse of the AML.
- */
- ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 1\n"));
-
- status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS1,
- table_index, start_node);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
+ if (acpi_gbl_parse_table_as_term_list) {
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start load pass\n"));
- /*
- * AML Parse, pass 2
- *
- * In this pass, we resolve forward references and other things
- * that could not be completed during the first pass.
- * Another complete parse of the AML is performed, but the
- * overhead of this is compensated for by the fact that the
- * parse objects are all cached.
- */
- ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 2\n"));
- status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS2,
- table_index, start_node);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
+ status = acpi_ns_execute_table(table_index, start_node);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+ } else {
+ /*
+ * AML Parse, pass 1
+ *
+ * In this pass, we load most of the namespace. Control methods
+ * are not parsed until later. A parse tree is not created.
+ * Instead, each Parser Op subtree is deleted when it is finished.
+ * This saves a great deal of memory, and allows a small cache of
+ * parse objects to service the entire parse. The second pass of
+ * the parse then performs another complete parse of the AML.
+ */
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 1\n"));
+
+ status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS1,
+ table_index, start_node);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ /*
+ * AML Parse, pass 2
+ *
+ * In this pass, we resolve forward references and other things
+ * that could not be completed during the first pass.
+ * Another complete parse of the AML is performed, but the
+ * overhead of this is compensated for by the fact that the
+ * parse objects are all cached.
+ */
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 2\n"));
+ status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS2,
+ table_index, start_node);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
}
return_ACPI_STATUS(status);
diff --git a/drivers/acpi/acpica/psparse.c b/drivers/acpi/acpica/psparse.c
index 0a23897..3aa9162 100644
--- a/drivers/acpi/acpica/psparse.c
+++ b/drivers/acpi/acpica/psparse.c
@@ -571,7 +571,9 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
* cleanup to do
*/
if (((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) ==
- ACPI_PARSE_EXECUTE) || (ACPI_FAILURE(status))) {
+ ACPI_PARSE_EXECUTE &&
+ !(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) ||
+ (ACPI_FAILURE(status))) {
acpi_ds_terminate_control_method(walk_state->
method_desc,
walk_state);
diff --git a/drivers/acpi/acpica/psxface.c b/drivers/acpi/acpica/psxface.c
index cf30cd82..0f0500d 100644
--- a/drivers/acpi/acpica/psxface.c
+++ b/drivers/acpi/acpica/psxface.c
@@ -252,6 +252,79 @@ cleanup:
/*******************************************************************************
*
+ * FUNCTION: acpi_ps_execute_table
+ *
+ * PARAMETERS: info - Method info block, contains:
+ * node - Node to where the is entered into the
+ * namespace
+ * obj_desc - Pseudo method object describing the AML
+ * code of the entire table
+ * pass_number - Parse or execute pass
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Execute a table
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ps_execute_table(struct acpi_evaluate_info *info)
+{
+ acpi_status status;
+ union acpi_parse_object *op = NULL;
+ struct acpi_walk_state *walk_state = NULL;
+
+ ACPI_FUNCTION_TRACE(ps_execute_table);
+
+ /* Create and init a Root Node */
+
+ op = acpi_ps_create_scope_op(info->obj_desc->method.aml_start);
+ if (!op) {
+ status = AE_NO_MEMORY;
+ goto cleanup;
+ }
+
+ /* Create and initialize a new walk state */
+
+ walk_state =
+ acpi_ds_create_walk_state(info->obj_desc->method.owner_id, NULL,
+ NULL, NULL);
+ if (!walk_state) {
+ status = AE_NO_MEMORY;
+ goto cleanup;
+ }
+
+ status = acpi_ds_init_aml_walk(walk_state, op, info->node,
+ info->obj_desc->method.aml_start,
+ info->obj_desc->method.aml_length, info,
+ info->pass_number);
+ if (ACPI_FAILURE(status)) {
+ goto cleanup;
+ }
+
+ if (info->obj_desc->method.info_flags & ACPI_METHOD_MODULE_LEVEL) {
+ walk_state->parse_flags |= ACPI_PARSE_MODULE_LEVEL;
+ }
+
+ /*
+ * Parse the AML, walk_state will be deleted by parse_aml
+ */
+ acpi_ex_enter_interpreter();
+ status = acpi_ps_parse_aml(walk_state);
+ walk_state = NULL;
+ acpi_ex_exit_interpreter();
+
+cleanup:
+ if (op) {
+ acpi_ps_delete_parse_tree(op);
+ }
+ if (walk_state) {
+ acpi_ds_delete_walk_state(walk_state);
+ }
+ return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_ps_update_parameter_list
*
* PARAMETERS: info - See struct acpi_evaluate_info
diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c
index ac71abc..2b9e87f 100644
--- a/drivers/acpi/acpica/tbxfload.c
+++ b/drivers/acpi/acpica/tbxfload.c
@@ -103,7 +103,8 @@ acpi_status __init acpi_load_tables(void)
"While loading namespace from ACPI tables"));
}
- if (!acpi_gbl_group_module_level_code) {
+ if (acpi_gbl_parse_table_as_term_list
+ || !acpi_gbl_group_module_level_code) {
/*
* Initialize the objects that remain uninitialized. This
* runs the executable AML that may be part of the
diff --git a/drivers/acpi/acpica/utxfinit.c b/drivers/acpi/acpica/utxfinit.c
index 75b5f27..e41424a 100644
--- a/drivers/acpi/acpica/utxfinit.c
+++ b/drivers/acpi/acpica/utxfinit.c
@@ -265,7 +265,8 @@ acpi_status __init acpi_initialize_objects(u32 flags)
* all of the tables have been loaded. It is a legacy option and is
* not compatible with other ACPI implementations. See acpi_ns_load_table.
*/
- if (acpi_gbl_group_module_level_code) {
+ if (!acpi_gbl_parse_table_as_term_list
+ && acpi_gbl_group_module_level_code) {
acpi_ns_exec_module_code_list();
/*
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index 4e4c214..22b0397 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -195,6 +195,12 @@ ACPI_INIT_GLOBAL(u8, acpi_gbl_do_not_use_xsdt, FALSE);
ACPI_INIT_GLOBAL(u8, acpi_gbl_group_module_level_code, FALSE);
/*
+ * Optionally support module level code by parsing the entire table as
+ * a term_list. Default is FALSE, do not execute entire table.
+ */
+ACPI_INIT_GLOBAL(u8, acpi_gbl_parse_table_as_term_list, FALSE);
+
+/*
* Optionally use 32-bit FADT addresses if and when there is a conflict
* (address mismatch) between the 32-bit and 64-bit versions of the
* address. Although ACPICA adheres to the ACPI specification which
--
1.7.10
[toc] | [prev] | [next] | [standalone]
| From | "Zheng, Lv" <lv.zheng@intel.com> |
|---|---|
| Date | 2016-05-17 02:30 +0200 |
| Subject | RE: [PATCH v2 0/4] ACPI 2.0: Enable TermList interpretion for table loading |
| Message-ID | <rzB3z-5GZ-9@gated-at.bofh.it> |
| In reply to | #1400508 |
Hi, Rafael
Can we queue this up in linux-next?
ASLTS recursive tests are done in ACPICA upstream and no regressions can be seen.
We need more tests around this experimental change from the real users to have the chances to learn the unknown cases.
If they reported regressions, we could stop the regressions by reverting [PATCH 4/4].
So it should be safe to do such experiments in the Linux upstream.
Thanks in advance.
Best regards
-Lv
> From: Zheng, Lv
> Subject: [PATCH v2 0/4] ACPI 2.0: Enable TermList interpretion for table loading
>
> MLC (module level code) is an ACPICA terminology describing the AML code
> out of any control method, currently only Type1Opcode (If/Else/While)
> wrapped MLC code blocks are executed by the AML interpreter after the table
> loading. But the issue which is fixed by this patchset is:
> Not only Type1Opcode, but also Type2Opcode will be executed as MLC and
> MLC is not executed after loading the table, but is executed right in
> place.
>
> The following AML code is assembled into a static loading SSDT, and used
> as an instrumentation to pry into the de-facto standard AML interpreter
> behaviors:
> Name (ECOK, Zero)
> Scope (\)
> {
> DBUG ("TermList 1")
> If (LEqual (ECOK, Zero))
> {
> DBUG ("TermList 2")
> Device (MDEV)
> {
> DEBUG (TermList 3")
> If (CondRefOf (MDEV))
> {
> DBUG ("MDEV exists")
> }
> If (CondRefOf (MDEV._STA))
> {
> DBUG ("MDEV._STA exists")
> }
> If (CondRefOf (\_SB.PCI0.EC))
> {
> DBUG ("\\_SB.PCI0.EC exists")
> }
> Name (_HID, EisaId ("PNP9999"))
> Method (_STA, 0, Serialized)
> {
> DEBUG ("\\_SB.MDEV._STA")
> Return (0x0F)
> }
> }
> DBUG ("TermList 4")
> }
> Method (_INI, 0, Serialized)
> {
> DBUG ("\\_SB._INI")
> }
> }
> Scope (_SB.PCI0)
> {
> Device (EC)
> {
> ...
> }
> }
> The DBUG function is a function to write the debugging messages into a
> SystemIo debug port.
> Running Windows with the BIOS providing this SSDT via RSDT, the following
> messages are obtained from the debug port:
> TermList 1
> TermList 2
> TermList 3
> \_SB.MDEV exists
> TermList 4
> \_SB._INI
> ...
>
> This test reveals the de-facto grammar for the AMLCode to us:
> 1. During the table loading, MLC will be executed by the interpreter, this
> is partially supported by the current ACPICA;
> 2. For SystemIo, not only after the _REG(1, 1) is evaluated (current ACPICA
> interpreter limitation), but when the table is being loaded, the
> SystemIo (the debugging port) is accessible, this is recently fixed in
> the upstream, now all early operation regions are accessible during the
> table loading;
> 3. Not only Type1Opcode, but also Type2Opcode will be executed as MLC and
> MLC is not executed after loading the table, but is executed right in
> place, the Linux upstream is not compliant to this behavior.
>
> The last compliance issue has already been clarified in ACPI 2.0
> specification, so the compliance issue is not that Linux is not compliant
> to the de-facto standard OS, but that Linux is not compliant to ACPI 2.0.
> Definition block tables in fact is defined by the spec as TermList, which
> has no difference than the control methods, thus the interpretion of the
> table should be no difference that the control method evaluation:
> AMLCode := DefBlockHeader TermList
> DefMethod := MethodOp PkgLength NameString MethodFlags TermList
>
> Why ACPICA interpreter is acting so differently from this definition? This
> is because, there are many software entropies preventing this from being
> enabled, such entropies need to be cleaned up first in order not to trigger
> regressions for specific platforms. These entropies include:
> 1. ECDT support is broken. In fact, the original EC driver was correct, but
> devlopers started to use the namespace EC instead of ECDT just because
> several broken ECDT tables were reported on the bugzilla. They trusted
> the namespace EC settings rather than the ECDT ones, this led to the
> evaluation of _REG/_GPE/_CRS and namespace walk before executing the
> module level AML opcodes. And the fixes in fact finally disable early EC
> usages (used during table loading and early device enumeration
> processes).
> 2. _REG evaluations are wrong. ACPICA provides APIs for OSPMs to register
> operation region handlers. But for the early operation region accesses,
> ACPI spec declares that the evaluations of _REG are not required, but
> the ACPICA APIs do not avoid running _REG to meet this early
> requirements. Code to fix this is partially upstreamed during previous
> ACPICA release cycle.
> 3. _REG associations are wrong. ACPICA associates _REG control method to
> all operation region objects before executing the _REG control method.
> This can happen even when a control method is evaluated and operation
> regions defined in the method is initialized
> (acpi_ev_initialize_region). As a part of the ACPICA internal _REG
> evaluation state machine, it requires the namespace walk, and all
> namespace walk should be ensured to happen only "AFTER THE NAMESPACE
> IS
> INITIALIZED". But when this logic happens during the table loading, it
> may fail in finding the _REG method since the _REG method may not be
> created by the interpreter just because _REG is defined after the
> operation region object's declaration.
> 4. _REG(CONNECT)/_REG(DISCONNECT) executions are not balanced, this can
> lead to wrong table loading/unloading results. Since _REG evaluations
> require the releasing of all interpreter/namespace locks in order to
> allow another evaluation to happen, and ACPICA operand object
> destruction code can be invoked from different locking environment, this
> becomes difficult for the developers to provide one single function to
> make _REG(CONNECT)/_REG(DISCONNECT) balanced.
> 5. \_SB._INI is not the first control method evaluated by the interpreter.
> Many platforms put initialization code in \_SB._INI in order to have
> named objects initialized very early during the device enumeration
> process. Without this order strictly ensured, early operation region
> access enabling could break these platforms.
> 6. Linux initialization order is wrong, it is now:
> a. load namespace without executing root scope If/Else/While module
> level code blocks;
> b. probe ECDT and instal EmbeddedControl operation region handler with
> _REG evaluated;
> c. install SystemMemory, SystemIo, PciConfig operation region handlers
> without evaluating _REG;
> d. run _REG for SystemMemory, SystemIo, PciConfig operation regions;
> e. execute root scope If/Else/While module level code blocks;
> f. enable GPE and namespace EC.
> While the correct order should be:
> a. probe ECDT and install EmbeddedControl operation region handler
> without evaluating _REG;
> b. install SystemMemory, SystemIo, PciConfig operation region handlers
> without evaluating _REG;
> c. load namespace, in the meanshile, execute all module level AML
> opcodes;
> d. run _REG for SystemMemory, SystemIo, PciConfig operation regions;
> e. enable GPE and namespace EC which results in _REG evaluation for EC.
>
> Until now we've upstreamed most of the entropy fixes into the Linux kernel,
> tested the grammar switch in the ACPICA upstream using ASLTS and no
> significant regressions can be seen while we need more tests before it is
> merged:
> https://github.com/acpica/acpica/pull/134
> This is the ASLTS running result after applying the grammar switch, the
> test cases include new "module" case for which ACPICA interpreter cannot
> pass without this grammar switch applied:
> ============================================================
> Test cases specified for running:
> arithmetic
> bfield
> constant
> control
> descriptor
> logic
> manipulation
> name
> reference
> region
> synchronization
> table
> misc
> provoke
> oarg
> oconst
> olocal
> onamedloc
> onamedglob
> opackageel
> oreftonamed
> oreftopackageel
> oreturn
> rstore
> roptional
> rcopyobject
> rindecrement
> rexplicitconv
> badasl
> namespace
> exc
> exc_ref
> exc_operand2
> exc_result2
> exc_tbl
> mt_mutex
> extra
> extra_aslts
> bdemo
> bdemof
> condbranches
> TOTAL: (32-bit norm mode)
> PASS : 0
> FAIL : 0
> BLOCKED : 0
> SKIPPED : 0
> Tests : 0
> Test Cases : 40 (of 47)
> Test Collections : 7 (of 8)
> Outstanding allocations after execution : 0
> Outstanding allocations (ACPI Error) : 0
> Large Reference Count (ACPI Error) : 0
> Memory consumption total : 0 Kb
> TOTAL: (64-bit norm mode)
> PASS : 0
> FAIL : 0
> BLOCKED : 0
> SKIPPED : 0
> Tests : 0
> Test Cases : 40 (of 47)
> Test Collections : 7 (of 8)
> Outstanding allocations after execution : 0
> Outstanding allocations (ACPI Error) : 0
> Large Reference Count (ACPI Error) : 0
> Memory consumption total : 0 Kb
> TOTAL: (32-bit slack mode)
> PASS : 0
> FAIL : 0
> BLOCKED : 0
> SKIPPED : 0
> Tests : 0
> Test Cases : 40 (of 47)
> Test Collections : 7 (of 8)
> Outstanding allocations after execution : 0
> Outstanding allocations (ACPI Error) : 0
> Large Reference Count (ACPI Error) : 0
> Memory consumption total : 0 Kb
> TOTAL: (64-bit slack mode)
> PASS : 0
> FAIL : 0
> BLOCKED : 0
> SKIPPED : 0
> Tests : 0
> Test Cases : 40 (of 47)
> Test Collections : 7 (of 8)
> Outstanding allocations after execution : 0
> Outstanding allocations (ACPI Error) : 0
> Large Reference Count (ACPI Error) : 0
> Memory consumption total : 0 Kb
> ============================================================
>
> Since we need more tests from the real users, we could make the grammar
> switch released from the Linux upstream. It's safe to do so because we have
> implemented regression protection (acpi_gbl_parse_table_as_term_list) in
> the fixes. The earlier the fix is tested by more real users, the better
> quality can be achieved by knowing the unknown cases (if any).
>
> Lv Zheng (4):
> ACPICA: Dispatcher: Fix an issue that the opregions created by the
> linked MLC were not tracked
> ACPICA: ACPI 2.0, Interpreter: Fix MLC issues by switching to new
> TermList grammar for table loading
> ACPI 2.0 / AML: Enable correct ACPI subsystem initialization order
> for new table loading mode
> ACPI 2.0 / AML: Fix module level execution by correctly parsing table
> as TermList
>
> drivers/acpi/acpica/acnamesp.h | 3 +
> drivers/acpi/acpica/acparser.h | 2 +
> drivers/acpi/acpica/dsopcode.c | 6 ++
> drivers/acpi/acpica/evrgnini.c | 3 +-
> drivers/acpi/acpica/exconfig.c | 6 +-
> drivers/acpi/acpica/nsload.c | 3 +-
> drivers/acpi/acpica/nsparse.c | 163 ++++++++++++++++++++++++++++++++--
> ------
> drivers/acpi/acpica/psparse.c | 4 +-
> drivers/acpi/acpica/psxface.c | 73 ++++++++++++++++++
> drivers/acpi/acpica/tbxfload.c | 3 +-
> drivers/acpi/acpica/utxfinit.c | 3 +-
> drivers/acpi/bus.c | 6 +-
> include/acpi/acpixf.h | 6 ++
> 13 files changed, 241 insertions(+), 40 deletions(-)
>
> --
> 1.7.10
[toc] | [prev] | [next] | [standalone]
| From | "Rafael J. Wysocki" <rafael@kernel.org> |
|---|---|
| Date | 2016-05-18 01:30 +0200 |
| Message-ID | <rzWB4-2Ab-13@gated-at.bofh.it> |
| In reply to | #1401827 |
On Tue, May 17, 2016 at 2:29 AM, Zheng, Lv <lv.zheng@intel.com> wrote: > Hi, Rafael > > Can we queue this up in linux-next? > ASLTS recursive tests are done in ACPICA upstream and no regressions can be seen. > We need more tests around this experimental change from the real users to have the chances to learn the unknown cases. > If they reported regressions, we could stop the regressions by reverting [PATCH 4/4]. > So it should be safe to do such experiments in the Linux upstream. > Thanks in advance. There is a rule that during a merge window linux-next should only contain material for that merge window. That is, currently linux-next should only contain material targeted at v4.7. For this reason, I can't put the series into linux-next right now, but I'll do that as soon as 4.7-rc1 is released.
[toc] | [prev] | [next] | [standalone]
| From | "Zheng, Lv" <lv.zheng@intel.com> |
|---|---|
| Date | 2016-05-20 03:00 +0200 |
| Subject | RE: [PATCH v2 0/4] ACPI 2.0: Enable TermList interpretion for table loading |
| Message-ID | <rAGXf-728-5@gated-at.bofh.it> |
| In reply to | #1402652 |
Hi, Rafael > From: rjwysocki@gmail.com [mailto:rjwysocki@gmail.com] On Behalf Of > Rafael J. Wysocki > Subject: Re: [PATCH v2 0/4] ACPI 2.0: Enable TermList interpretion for table > loading > > On Tue, May 17, 2016 at 2:29 AM, Zheng, Lv <lv.zheng@intel.com> wrote: > > Hi, Rafael > > > > Can we queue this up in linux-next? > > ASLTS recursive tests are done in ACPICA upstream and no regressions can be > seen. > > We need more tests around this experimental change from the real users to > have the chances to learn the unknown cases. > > If they reported regressions, we could stop the regressions by reverting > [PATCH 4/4]. > > So it should be safe to do such experiments in the Linux upstream. > > Thanks in advance. > > There is a rule that during a merge window linux-next should only > contain material for that merge window. That is, currently linux-next > should only contain material targeted at v4.7. > > For this reason, I can't put the series into linux-next right now, but > I'll do that as soon as 4.7-rc1 is released. [Lv Zheng] Great! Thanks for the information. Best regards -Lv
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web