[PATCH 2/4] ACPICA: Introduce new acpi_os_physical_table_add OS callback
by Thomas Renninger
This one allows OS to add arbitrary ACPI tables.
ToDo: It should get checked whether a table with the same signature already
exists and if this is the case, adding should not happen.
Signed-off-by: Thomas Renninger <trenn(a)suse.de>
CC: hpa(a)zytor.com
CC: tglx(a)linutronix.de
CC: ck(a)conrad-kostecki.de
CC: linux-kernel(a)vger.kernel.org
CC: x86(a)kernel.org
CC: mingo(a)redhat.com
CC: rjw(a)rjwysocki.net
CC: devel(a)acpica.org
---
drivers/acpi/acpica/tbutils.c | 36 ++++++++++++++++++++++++++++++++++++
include/acpi/acpiosxf.h | 6 ++++++
2 files changed, 42 insertions(+), 0 deletions(-)
diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c
index 6412d3c..a819d198 100644
--- a/drivers/acpi/acpica/tbutils.c
+++ b/drivers/acpi/acpica/tbutils.c
@@ -453,6 +453,8 @@ static acpi_status acpi_tb_validate_xsdt(acpi_physical_address xsdt_address)
*
******************************************************************************/
+#define ACPI_MAX_TABLE_ADD 64
+
acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
{
struct acpi_table_rsdp *rsdp;
@@ -623,5 +625,39 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
}
}
+ /*
+ * ACPI Table Add:
+ * Allow the OS to add additional tables to the global root table list
+ */
+ for (i = 0; i < ACPI_MAX_TABLE_ADD; i++) {
+ int tmp, k;
+ table_entry_size = 0;
+ address = 0;
+ status = acpi_os_physical_table_add(&address,
+ &table_entry_size);
+ if (status == AE_OK && table_entry_size && address) {
+ table = acpi_os_map_memory(address, table_entry_size);
+ for (k = 2; k < acpi_gbl_root_table_list.current_table_count; k++) {
+ /*
+ Always add SSDTs. Only allow adding of other
+ tables if none of such a signature already
+ exists. Use the override interface instead
+ in such a case.
+ */
+ if (ACPI_COMPARE_NAME("SSDT", table->signature) &&
+ !ACPI_COMPARE_NAME(&acpi_gbl_root_table_list.tables[i].signature, table->signature)) {
+ ACPI_INFO((AE_INFO, "OS table not added, signature already exists:"));
+ acpi_tb_print_table_header(address, table);
+ acpi_os_unmap_memory(table, table_entry_size);
+ } else {
+ ACPI_INFO((AE_INFO, "Add OS provided table:"));
+ acpi_tb_print_table_header(address, table);
+ status = acpi_tb_store_table(address, table, table_entry_size,
+ ACPI_TABLE_ORIGIN_MAPPED, &tmp);
+ }
+ }
+ } else
+ break;
+ }
return_ACPI_STATUS(AE_OK);
}
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
index 01e6c6d..70c00ed 100644
--- a/include/acpi/acpiosxf.h
+++ b/include/acpi/acpiosxf.h
@@ -111,6 +111,12 @@ acpi_os_physical_table_override(struct acpi_table_header *existing_table,
u32 *new_table_length);
#endif
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_physical_table_add
+acpi_status
+acpi_os_physical_table_add(acpi_physical_address * new_address,
+ u32 *new_table_length);
+#endif
+
/*
* Spinlock primitives
*/
--
1.7.6.1
8 years, 3 months
[PATCH 1/4] ACPI: Provide support for ACPI table adding via OS
by Thomas Renninger
This is done the same way as the previous ACPI physical table override
mechanism.
How to override or add tables via initrd, please look up:
Documentation/acpi/initrd_table_override.txt
SSDTs can only be overridden, not added.
Overriding only happens if the OEM id of the table header matches the one
with the BIOS provided one.
All table types (SSDTs are an exception), must only show up once.
So either you:
- Add a fresh new table for adding of which type (signature) none exists
in the BIOS -> OS ACPI table adding happens.
or
- Add a table which already exists in BIOS, but the OEM id must match the
one of the table of the same type (signature) that exists in BIOS already
-> OS ACPI table overriding happens
Typically one copies away the original ACPI table, disassembles,
modifies (for example adding debug strings), compiles it and provides
the table via initrd for overriding (will have the same OEM id).
But this is not necessary, one could also come up with a selfmade
table for overriding, by taking care that the signature and OEM id is
the same as the one provided by BIOS
In ACPI table overriding case you see in dmesg:
ACPI: Override [DSDT- BXDSDT], this is unsafe: tainting kernel
Disabling lock debugging due to kernel taint
In ACPI table adding case you see in dmesg (BGRT table got added):
ACPI: Add [BGRT-SLIC-WKS], this is unsafe: tainting kernel
ACPI: BGRT 000000007fffd1ba 000038 (v00 HPQOEM SLIC-WKS 01072009
INTL 20130823)
Signed-off-by: Thomas Renninger <trenn(a)suse.de>
CC: hpa(a)zytor.com
CC: tglx(a)linutronix.de
CC: ck(a)conrad-kostecki.de
CC: linux-kernel(a)vger.kernel.org
CC: x86(a)kernel.org
CC: mingo(a)redhat.com
CC: rjw(a)rjwysocki.net
CC: devel(a)acpica.org
---
drivers/acpi/osl.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 90 insertions(+), 1 deletions(-)
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index fc1aa79..7f9a865 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -566,6 +566,8 @@ static const char * const table_sigs[] = {
#define ACPI_OVERRIDE_TABLES 64
static struct cpio_data __initdata acpi_initrd_files[ACPI_OVERRIDE_TABLES];
+/* Remember physical address of overriden or added tables */
+static acpi_physical_address acpi_table_overridden[ACPI_OVERRIDE_TABLES];
#define MAP_CHUNK_SIZE (NR_FIX_BTMAPS << PAGE_SHIFT)
@@ -715,7 +717,7 @@ acpi_os_physical_table_override(struct acpi_table_header *existing_table,
*address = 0;
return AE_OK;
#else
- int table_offset = 0;
+ int no, table_offset = 0;
struct acpi_table_header *table;
*table_length = 0;
@@ -759,6 +761,12 @@ acpi_os_physical_table_override(struct acpi_table_header *existing_table,
*table_length = table->length;
acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
*address = acpi_tables_addr + table_offset;
+ for (no = 0; no < ACPI_OVERRIDE_TABLES; no++) {
+ if (acpi_table_overridden[no] == 0) {
+ acpi_table_overridden[no] = *address;
+ break;
+ }
+ }
break;
} while (table_offset + ACPI_HEADER_SIZE < all_tables_size);
@@ -768,6 +776,87 @@ acpi_os_physical_table_override(struct acpi_table_header *existing_table,
#endif
}
+acpi_status
+acpi_os_physical_table_add(acpi_physical_address *address,
+ u32 *table_length)
+{
+#ifndef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
+ *table_length = 0;
+ *address = 0;
+ return AE_OK;
+#else
+ int no, table_offset = 0;
+ struct acpi_table_header *table;
+
+ *table_length = 0;
+ *address = 0;
+
+ if (!acpi_tables_addr)
+ return AE_OK;
+
+ do {
+ if (table_offset + ACPI_HEADER_SIZE > all_tables_size) {
+ WARN_ON(1);
+ return AE_OK;
+ }
+
+ table = acpi_os_map_memory(acpi_tables_addr + table_offset,
+ ACPI_HEADER_SIZE);
+
+ if (table_offset + table->length > all_tables_size) {
+ acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
+ WARN_ON(1);
+ return AE_OK;
+ }
+
+ table_offset += table->length;
+
+ /* Do not add SSDTs, only if acpi_no_auto_ssdt boot parameter
+ got set.
+ */
+ if (acpi_gbl_disable_ssdt_table_load == FALSE &&
+ !memcmp("SSDT", table->signature, 4)) {
+ pr_info("Will not add SSDT [%8.8s], use acpi_no_auto_ssdt to force\n", table->oem_table_id);
+ acpi_os_unmap_memory(table,
+ ACPI_HEADER_SIZE);
+ continue;
+ }
+
+ /* Only add tables that have not been overridden already */
+ for (no = 0; no < ACPI_OVERRIDE_TABLES; no++) {
+ if (acpi_table_overridden[no] == 0)
+ break;
+ if (acpi_table_overridden[no] ==
+ acpi_tables_addr + table_offset - table->length)
+ break;
+ }
+ /* All tables have been added or overridden */
+ if (acpi_table_overridden[no] != 0) {
+ acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
+ continue;
+ }
+ /* Max table override/add limit reached */
+ if (no == ACPI_OVERRIDE_TABLES) {
+ acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
+ return AE_ERROR;
+ }
+
+ table_offset -= table->length;
+ *table_length = table->length;
+ *address = acpi_tables_addr + table_offset;
+ /* do not add this table again */
+ acpi_table_overridden[no] = *address;
+ pr_warn(PREFIX
+ "Add [%4.4s-%8.8s], this is unsafe: tainting kernel\n",
+ table->signature, table->oem_table_id);
+ add_taint(TAINT_OVERRIDDEN_ACPI_TABLE, LOCKDEP_NOW_UNRELIABLE);
+ acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
+ return AE_OK;
+ } while (table_offset + ACPI_HEADER_SIZE < all_tables_size);
+ return AE_OK;
+#endif
+}
+
static irqreturn_t acpi_irq(int irq, void *dev_id)
{
u32 handled;
--
1.7.6.1
8 years, 4 months
[PATCH 4/4] ACPI: Add new table signatures that can be overridden/added.
by Thomas Renninger
Signed-off-by: Thomas Renninger <trenn(a)suse.de>
CC: hpa(a)zytor.com
CC: tglx(a)linutronix.de
CC: ck(a)conrad-kostecki.de
CC: linux-kernel(a)vger.kernel.org
CC: x86(a)kernel.org
CC: mingo(a)redhat.com
CC: rjw(a)rjwysocki.net
CC: devel(a)acpica.org
---
drivers/acpi/osl.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 7f9a865..23ce5b1 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -38,6 +38,7 @@
#include <linux/delay.h>
#include <linux/workqueue.h>
#include <linux/nmi.h>
+# define ACPI_UNDEFINED_TABLES 1
#include <linux/acpi.h>
#include <linux/efi.h>
#include <linux/ioport.h>
@@ -559,7 +560,8 @@ static const char * const table_sigs[] = {
ACPI_SIG_IBFT, ACPI_SIG_IVRS, ACPI_SIG_MCFG, ACPI_SIG_MCHI,
ACPI_SIG_SLIC, ACPI_SIG_SPCR, ACPI_SIG_SPMI, ACPI_SIG_TCPA,
ACPI_SIG_UEFI, ACPI_SIG_WAET, ACPI_SIG_WDAT, ACPI_SIG_WDDT,
- ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT, ACPI_SIG_PSDT,
+ ACPI_SIG_WDRT, ACPI_SIG_BGRT, ACPI_SIG_ATKG, ACPI_SIG_GSCI,
+ ACPI_SIG_IEIT, ACPI_SIG_DSDT, ACPI_SIG_FADT, ACPI_SIG_PSDT,
ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, NULL };
#define ACPI_HEADER_SIZE sizeof(struct acpi_table_header)
--
1.7.6.1
8 years, 4 months
[PATCH 3/4] ACPICA: Add BGRT signature to known signatures
by Thomas Renninger
In Linux there even exists a driver already making use of this table:
drivers/acpi/bgrt.c:MODULE_DESCRIPTION("BGRT boot graphic support");
Signed-off-by: Thomas Renninger <trenn(a)suse.de>
CC: hpa(a)zytor.com
CC: tglx(a)linutronix.de
CC: ck(a)conrad-kostecki.de
CC: linux-kernel(a)vger.kernel.org
CC: x86(a)kernel.org
CC: mingo(a)redhat.com
CC: rjw(a)rjwysocki.net
CC: devel(a)acpica.org
---
include/acpi/actbl2.h | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h
index 094a906..9ed1c20 100644
--- a/include/acpi/actbl2.h
+++ b/include/acpi/actbl2.h
@@ -83,6 +83,7 @@
#define ACPI_SIG_WDAT "WDAT" /* Watchdog Action Table */
#define ACPI_SIG_WDDT "WDDT" /* Watchdog Timer Description Table */
#define ACPI_SIG_WDRT "WDRT" /* Watchdog Resource Table */
+#define ACPI_SIG_BGRT "BGRT" /* Boot Graphic Support */
#ifdef ACPI_UNDEFINED_TABLES
/*
--
1.7.6.1
8 years, 4 months
[PATCH] minor correction for big endian machines
by Al Stone
When using the ASL files in the misc tests directory, I found a
case where a warning message printed out the table signature in
the wrong order on big endian machines. The patch below fixes
the message so it works on little- or big-endian.
Signed-off-by: Al Stone <ahs3(a)redhat.com>
diff -urN acpica-unix2-20140214/source/compiler/asllookup.c
acpica-unix2-20140214-patch/source/compiler/asllookup.c
--- acpica-unix2-20140214/source/compiler/asllookup.c 2014-02-14
16:23:33.000000000 -0700
+++ acpica-unix2-20140214-patch/source/compiler/asllookup.c 2014-02-27
11:50:52.168659866 -0700
@@ -120,6 +120,7 @@
{
ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR
(ACPI_NAMESPACE_NODE, ObjHandle);
ACPI_NAMESPACE_NODE *Next;
+ ACPI_NAME_UNION tmp;
/* Referenced flag is set during the namespace xref */
@@ -163,8 +164,9 @@
* Issue a remark even if it is a reserved name (starts
* with an underscore).
*/
+ ACPI_MOVE_32_TO_32(&tmp.Ascii, Next->Name.Ascii);
sprintf (MsgBuffer, "Name is within method [%4.4s]",
- Next->Name.Ascii);
+ tmp.Ascii);
AslError (ASL_REMARK, ASL_MSG_NOT_REFERENCED,
LkGetNameOp (Node->Op), MsgBuffer);
return (AE_OK);
--
ciao,
al
-----------------------------------
Al Stone
Software Engineer
Red Hat, Inc.
ahs3(a)redhat.com
-----------------------------------
8 years, 4 months
Re: [Devel] [PATCH 1/4] ACPI: Provide support for ACPI table adding via OS
by Thomas Renninger
On Tuesday, February 18, 2014 10:27:23 AM H. Peter Anvin wrote:
> Why can't you add SSDTs? It would be particularly useful.
There are 2 ways how ACPI tables get added:
- Via pointer from a root table (XSDT or RSDT iirc)
- Via load statement inside of ACPI context when ACPI BIOS
code gets executed (iirc the physical address is passed).
The latter is only for SSDTs.
The problem is that you if you add an SSDT early, it might
have been intended for overriding when an SSDT gets dynamically
loaded later when the system is up which is particular useful as
well if you want to debug this specific BIOS table.
This could be workarounded via a boot param:
acpi=allow_ssdt_adding
But this is not nice. Maybe someone has a more elegant idea.
Something could still be added if someone is really needing this.
Thomas
8 years, 4 months
Re: [Devel] [PATCH 1/4] ACPI: Provide support for ACPI table adding via OS
by Thomas Renninger
On Tuesday, February 18, 2014 12:51:07 PM H. Peter Anvin wrote:
> On 02/18/2014 10:44 AM, Thomas Renninger wrote:
> > On Tuesday, February 18, 2014 10:27:23 AM H. Peter Anvin wrote:
> >> Why can't you add SSDTs? It would be particularly useful.
> >
> > There are 2 ways how ACPI tables get added:
> > - Via pointer from a root table (XSDT or RSDT iirc)
> > - Via load statement inside of ACPI context when ACPI BIOS
> >
> > code gets executed (iirc the physical address is passed).
> >
> > The latter is only for SSDTs.
> > The problem is that you if you add an SSDT early, it might
> > have been intended for overriding when an SSDT gets dynamically
> > loaded later when the system is up which is particular useful as
> > well if you want to debug this specific BIOS table.
> >
> > This could be workarounded via a boot param:
> > acpi=allow_ssdt_adding
> > But this is not nice. Maybe someone has a more elegant idea.
> > Something could still be added if someone is really needing this.
>
> Since adding SSDTs is one of the things I really can imagine one would
> do, I think we need to figure out how to do that. I would think that
> overriding would be the exception case.
You can always paste new code into the DSDT. It is effectively the same
than adding a new SSDT table.
The other way around, modifying or deleting broken code in a BIOS
provided SSDT needs overriding.
So in fact adding SSDTs is not necessary at all.
It would be a nice add-on, but it's not even worth introducing
an extra boot param or whatever confusion.
A hint in Documentation that adding additional ASL (ACPI Source Language)
code to the DSDT would be the same than creating and adding a new
SSDT table which is not possible should be enough.
The whole thing will always taint the kernel and is meant for
debugging only anyway.
Thomas
8 years, 4 months
Re: [Devel] 6 second boot delay if processing SSDT tables
by Zheng, Lv
Hi,
I created a bug entry here:
https://bugzilla.kernel.org/show_bug.cgi?id=70891
Possibly this is a known issue.
We have a series to cleanup table related code where Linux specific logics are embedded.
In that series, there are several issues detected.
Could you please first upload an acpidump output there to let me check if there is a known fix matching this bug?
Thanks and best regards
-Lv
> From: linux-acpi-owner(a)vger.kernel.org [mailto:[email protected]] On Behalf Of Stanislaw Gruszka
> Sent: Tuesday, February 18, 2014 4:39 PM
>
> Hi,
>
> On bugzilla https://bugzilla.redhat.com/show_bug.cgi?id=1055228 ,
> Gareth reported 6 second boot delay on 3.12 kernel. Delay does not
> happen if acpi_no_auto_ssdt option is used, nor if kernel is compiled
> with various debug facilities like LOCKDEP (fedora kernel-debug
> variant). We tried to compile kernel with just CONFIG_ACPI_DEBUG=y, on
> that kernel issue was reproducible, but after enable printing messages,
> again issue disappeared (we tried acpi.debug_layer=0xffffffff together
> with acip.debug_level=0x0307ff4f and acip.debug_level=0x03000000,
> links to logs are provided in bugzilla).
>
> On affected kernels interesting dmesg part looks like below:
>
> [ 0.212035] [Firmware Bug]: ACPI: BIOS _OSI(Linux) query ignored
> [ 0.217930] ACPI: SSDT 0000000092e6ac18 003D3 (v01 PmRef Cpu0Cst 00003001 INTL 20121220)
> [ 0.218512] ACPI: Dynamic OEM Table Load:
> [ 0.218514] ACPI: SSDT (null) 003D3 (v01 PmRef Cpu0Cst 00003001 INTL 20121220)
> [ 0.222109] ACPI: SSDT 0000000092e6a618 005AA (v01 PmRef ApIst 00003000 INTL 20121220)
> [ 0.222792] ACPI: Dynamic OEM Table Load:
> [ 0.222799] ACPI: SSDT (null) 005AA (v01 PmRef ApIst 00003000 INTL 20121220)
> [ 0.226920] ACPI: SSDT 0000000092e69d98 00119 (v01 PmRef ApCst 00003000 INTL 20121220)
> [ 0.227495] ACPI: Dynamic OEM Table Load:
> [ 0.227497] ACPI: SSDT (null) 00119 (v01 PmRef ApCst 00003000 INTL 20121220)
> [ 6.812869] ACPI: Interpreter enabled
>
> With acpi_no_auto_ssdt option interesting part looks like this:
>
> [ 0.203230] [Firmware Bug]: ACPI: BIOS _OSI(Linux) query ignored
> [ 0.203595] ACPI Error: [SGMD] Namespace lookup failure, AE_NOT_FOUND (20130725/psargs-359)
> [ 0.203601] ACPI Error: Method parse/execution failed [\_SB_._OSC] (Node ffff880253859438), AE_NOT_FOUND (20130725/psparse-
> 536)
> [ 0.206093] ACPI Error: [\_PR_.CPU0._PPC] Namespace lookup failure, AE_NOT_FOUND (20130725/psargs-359)
> [ 0.206102] ACPI Error: Method parse/execution failed [\_SB_.PCI0.LPCB.EC0_.SASU] (Node ffff8802538570a0), AE_NOT_FOUND
> (20130725/psparse-536)
> [ 0.206108] ACPI Error: Method parse/execution failed [\_SB_.PCI0.LPCB.EC0_.ECMI] (Node ffff880253857078), AE_NOT_FOUND
> (20130725/psparse-536)
> [ 0.206113] ACPI Error: Method parse/execution failed [\_SB_.PCI0.LPCB.EC0_._REG] (Node ffff880253856910), AE_NOT_FOUND
> (20130725/psparse-536)
> [ 0.206122] Fail in evaluating the _REG object of EC device. Broken bios is suspected.
> [ 0.206127] ACPI: Interpreter enabled
>
> Any help to solving this bug would be appreciate. I'm CCing Gareth, he
> can provide more informations if needed.
>
> Thanks
> Stanislaw
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to majordomo(a)vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
8 years, 4 months
ACPI: Also allow ACPI table adding via initrd not only overriding
by Thomas Renninger
The ACPICA patches have to go into separate acpica repository first.
It should also be checked in acpica whether the table signature the OS likes
to add already exists (from BIOS). In this case the table must not be added.
Worked here by trying to override a DSDT and addind a BGRT table.
Thomas
8 years, 4 months
Re: [Devel] [PATCH] x86: HPET force enable for Soekris net6501
by Thomas Renninger
On Monday, February 17, 2014 10:47:50 AM H. Peter Anvin wrote:
> On 02/17/2014 10:23 AM, Thomas Renninger wrote:
> > Easiest I can think of instead of trying to modify RSDP or similar, is
> > to still pass the tables via unzipped, glued cpio which the kernel
> > can access early. The same way it is done for current ACPI table
> > overriding
> > and early microcode passing.
>
> We shouldn't *need* an RSDP and RSDT/XSDT, though, since all they are
> are pointers to the actual tables. Rather than hacking around it we
> should probably just fix the fundamental problem.
That is what I described.
If something similar what I wrote gets implemented, you can simply
add ACPI tables to initrd as described here:
Documentation/acpi/initrd_table_override.txt
and if BIOS already provides them they get overridden, otherwise
they get added.
Thomas
8 years, 4 months