There is a hidden logic for AcpiTbInstallStandardTable():
1. When it is invoked from the OS boot stage, ACPICA mutex may not be
available, and thus no AcpiUtAcquireMutex()/AcpiUtReleaseMutex() are
invoked in these code paths:
AcpiInitializeTables
AcpiTbParseRootTable
AcpiTbInstallStandardTable (4 invocations)
AcpiInstallTable
AcpiTbInstallStandardTable
2. When it is invoked during the runtime, ACPICA mutex is correctly used:
AcpiExLoadOp
AcpiTbInstallAndLoadTable
Lock(TABLES)
AcpiTbInstallStandardTable
UnLock(TABLES)
AcpiLoadTable
AcpiTbInstallAndLoadTable
Lock(TABLES)
AcpiTbInstallStandardTable
UnLock(TABLES)
So the hidden logic is: AcpiTbInstallStandardTable() tries not to hold
mutexes to handle the difference of the boot stage and the runtime, but
leaves the mutexes held from some calling runtime APIs.
This introduces another problem in AcpiTbInstallStandardTable() where
AcpiGbl_TableHandler is invoked from and the lock contexts are thus not
consistent for the table handlers. Linux registers such a handler to track
the table installation and the handler is actually invoked from both
contexts. Since the handler also invokes AcpiGetTable(), when the following
commit corrected AcpiGetTable() to make it start to hold the table lock,
a regression is then triggered.
Commit: cac6790954d4d752a083e6122220b8a22febcd07
Subject: Tables: Back port acpi_get_table_with_size() and early_acpi_os_unmap_memory() from Linux kernel
The regression is noticed by LKP as new errors reported by ACPICA mutex
debugging facility.
[ 2.043693] ACPI Error: Mutex [ACPI_MTX_Tables] already acquired by this thread [497483776] (20160930/utmutex-254)
[ 2.054084] ACPI Error: Mutex [0x2] is not acquired, cannot release (20160930/utmutex-326)
And it triggers a dead lock:
[ 247.066214] INFO: task swapper/0:1 blocked for more than 120 seconds.
...
[ 247.091271] Call Trace:
...
[ 247.121523] down_timeout+0x47/0x50
[ 247.125065] acpi_os_wait_semaphore+0x47/0x62
[ 247.129475] acpi_ut_acquire_mutex+0x43/0x81
[ 247.133798] acpi_get_table+0x2d/0x84
[ 247.137513] acpi_table_attr_init+0xcd/0x100
[ 247.146590] acpi_sysfs_table_handler+0x5d/0xb8
[ 247.151174] acpi_bus_table_handler+0x23/0x2a
[ 247.155583] acpi_tb_install_standard_table+0xe0/0x213
[ 247.164489] acpi_tb_install_and_load_table+0x3a/0x82
[ 247.169592] acpi_ex_load_op+0x194/0x201
...
[ 247.200108] acpi_ns_evaluate+0x1bb/0x247
[ 247.204170] acpi_evaluate_object+0x178/0x274
[ 247.213249] acpi_processor_set_pdc+0x154/0x17b
...
The table mutex held in AcpiTbInstallAndLoadTable() is re-visited by
AcpiGetTable().
Noticing that the early mutex requirement actually belongs to the OSL layer
and has already been handled in Linux
acpi_os_wait_semaphore()/acpi_os_signal_semaphore(). This patch then can
fix the regression by removing this hidden logic from ACPICA core and
leaving it to OSPMs.
Tested-by: Tomi Sarvela <tomi.p.sarvela@intel.com>
Tested-by: Ye Xiaolong <xiaolong.ye@intel.com>
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
To avoid caller to trigger unexpected warning messages (Link #1):
ACPI Warning: Table ffffffffbb461d20, Validation count is zero before decrement
Which is reported from AcpiTbPutTable(). When the table is validated, the
pointer must be non-zero. Thus the message is not suitable for invalidated
tables. This patch fixes the callee side based on this fact. Reported by
Cristian Aravena Romero, Fixed by Lv Zheng.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=191221 [#1]
Reported-by: Cristian Aravena Romero <caravena@gmail.com>
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
On linux, 2 ioremap() mechanisms are implemented for 2 stages:
1. During early boot, before memory manager is fully initialized.
2. For late boot and runtime, after memory manager is fully
initialized.
Maps mapped in the early stage cannot be used by late stage.
So for early stage, linux invokes AcpiGetTable()/AcpiPutTable() APIs to
free table mappings (means there is no imbalance), and for late stage,
linux mostly only invokes AcpiGetTable() table API (means there are
imbalances, and balances and imbalances co-exist).
The original mechanism is designed to allow:
1. early stage balances;
2. late stage co-existence of balances/imbalances.
But for the latter, it has a limitation, it doesn't allow balances to be
implemented for users who can easily increment ValidationCount to its
maximum value.
Considering this case:
1. A program opens a sysfs table file 65535 times, it can increase
ValidationCount and first increment causes the table to be mapped:
ValidationCount = 65535
2. AML execution causes "Load" to be executed on the same
table, this time it cannot increase ValidationCount, so
ValidationCount remains:
ValidationCount = 65535
3. The program closes sysfs table file 65535 times, it can decrease
ValidationCount and the last decrement cause the table to be
unmapped:
ValidationCount = 0
4. AML code still accessing the loaded table, kernel crash can be
observed.
This is because the original mechanism is only prepared for late stage
users that won't invoke AcpiPutTable() so often (means can only handle
co-existence of balanced non-frequent AcpiPutTable() invocations and
imbalanced AcpiGetTable() invocations), and cannot handle the
co-existence of balanced frequent AcpiPutTable() invocations and
imbalanced AcpiGetTable() invocations.
To prevent that from happening, add a ValidationCount threashold. When it
is reached, the ValidationCount can no longer be incremented/decremented to
invalidate the table descriptor (means preventing table unmappings). Now
the improved mechanism can handle co-existence of any balances/imbalances.
Note that code added in AcpiTbPutTable() is actually a no-op but changes
the warning message into a "warn once" one. Since all warning messages can
only appear once for one table descriptor, it is safe now to add them back
without worrying about log flooding. Lv Zheng.
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
On linux, 2 ioremap() mechanisms are implemented for 2 stages:
1. During early boot, before memory manager is fully initialized.
2. For late boot and runtime, after memory manager is fully
initialized.
Maps mapped in the early stage can not be used by late stage.
So for early stage, linux implements get/put like table APIs to free table
mappings, and for late stage, linux only invokes get table APIs.
We merged 2 implementations into single style API set:
AcpiGetTable() and AcpiPutTable(). During early stage, we want the
"ValidationCount" based mechanism to fully work to release table mappings,
while for late stages, if get/put invocations are balanced, we can free
mappings, but if not (we'll reach the warnings in
AcpiTbGetTable()/AcpiTbPutTable()), we should stop unmapping tables.
The design should work but unfortunately, "return_ACPI_STAUS(AE_LIMIT)"
prevents AcpiGetTable() from returning mapped table pointer to the
callers and the error message can flood kernel logs.
Thus this patch removes the error value returned by AcpiTbGetTable()
in that case along with the accompanying error message to fix the
issue.
Reported-by: Anush Seetharaman <anush.seetharaman@intel.com>
Reported-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
acpisrc now has capability to convert both the followings:
1. Form 1:
typedef struct/union foo { struct/union foo {
.... --> ...
} FOO; }
2. Form 2:
typedef struct/union foo FOO; --> typedef struct/union foo foo;
It becomes unable to handle the following:
3. Form3:
typedef struct/union foo { /* comment */
...
} FOO;
-->
strut/union foo { /* comment */
...
};
As:
1. The purpose of acpisrc is to convert formatted code (ACPICA coding
style) into linux coding style,
2. acpisrc is a very simple tool that doesn't fully handle C language.
This commit changes the definitions side in order not to regress and we
shall make "no comments in struct/union line" as a new ACPICA coding style
rule. Lv Zheng.
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Some projects use compiler plugins that support automatic
layout randomization of structures that are entirely function
pointers. To support this, static initializers need to use designated
initialization rather than ordered initialization. This provides a macro,
ACPI_STRUCT_INIT, to handle both cases, keeping ordered initialization
for builds using compilers that do not support designated initialization.
Signed-off-by: Kees Cook <keescook@google.com>
This change allows compilation of code like the following:
DefinitionBlock (...)
{
External (ABCD.EFGH)
Device (ABCD)
{
Name (IJLK,0)
}
}
but does not allow compilation of code like the following:
DefinitionBlock (...)
{
External (ABCD)
Device (ABCD)
{
Name (EFGH,0)
}
}
Signed-off-by: Erik Schmauss <erik.schmauss@intel.com>
IORT revision C has been published with a number of new SMMU
implementation identifiers; define them.
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Fix some confusion between "parse op" and "parse node".
Adds a new file, aslparseop.c
Consistently use "parse op" to describe the elements of the
parse tree data structure.
An "Op" is the primary data structure element, even though
it sounds odd.
Reversing the order of defintion block declarations exposed an
issue in the compiler namespace loading. This issue has been fixed
and this change exercises the code involved in the bug fix.
Signed-off-by: Erik Schmauss <erik.schmauss@intel.com>
This change allows the compilation of an external declaration that refers
to a field unit in a separate table.
Signed-off-by: Erik Schmauss <erik.schmauss@intel.com>
The assignment to Length is redundant as the stored value is
overwritten again before it is read. Issue detected by
CoverityScan CID#163885 ("Unused Value")
Signed-off-by: Colin Ian King <colin.king@canonical.com>