Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Renninger <trenn@suse.de>2011-09-20 18:09:04 +0200
committerThomas Renninger <trenn@suse.de>2011-09-20 18:09:04 +0200
commit34bb1954ece98383dfe96bb3792be85133212849 (patch)
treec0741ca9a02fe86087d5ffcd623b87828ab514e0
parent532c24ffdc1e085588774cecacdc52535bddc3a1 (diff)
- ACPI: Implement overriding of arbitrary ACPI tables via initrd
(none). - ACPICA: Fix wrongly mapped acpi table header when overriding via initrd (none). - ACPICA: Introduce acpi_os_phys_table_override function (none). - x86: allow NVS can be accessed by driver (none). - Update config files: CONFIG_ACPI_INITRD_TABLE_OVERRIDE=y on i386 and x86_64 flavors
-rw-r--r--config/i386/debug1
-rw-r--r--config/i386/default1
-rw-r--r--config/i386/desktop1
-rw-r--r--config/i386/pae1
-rw-r--r--config/i386/trace1
-rw-r--r--config/i386/xen1
-rw-r--r--config/ia64/debug1
-rw-r--r--config/ia64/default1
-rw-r--r--config/ia64/trace1
-rw-r--r--config/x86_64/debug1
-rw-r--r--config/x86_64/default1
-rw-r--r--config/x86_64/desktop1
-rw-r--r--config/x86_64/trace1
-rw-r--r--config/x86_64/xen1
-rw-r--r--patches.arch/acpi_implement_overriding_of_arbitrary_acpi_tables_via_initrd.patch455
-rw-r--r--patches.arch/acpica_fix_wrongly_mapped_acpi_table_header_when_overriding_via_initrd.patch45
-rw-r--r--patches.arch/acpica_introduce_acpi_os_phys_table_override_function.patch129
-rw-r--r--patches.drivers/apei_allow_drivers_access_nvs_ram.patch28
-rw-r--r--series.conf6
19 files changed, 677 insertions, 0 deletions
diff --git a/config/i386/debug b/config/i386/debug
index cbd066a15d..b9509f3d53 100644
--- a/config/i386/debug
+++ b/config/i386/debug
@@ -517,6 +517,7 @@ CONFIG_ACPI_THERMAL=m
CONFIG_ACPI_NUMA=y
CONFIG_ACPI_CUSTOM_DSDT_FILE=""
# CONFIG_ACPI_CUSTOM_DSDT is not set
+CONFIG_ACPI_INITRD_TABLE_OVERRIDE=y
CONFIG_ACPI_BLACKLIST_YEAR=0
CONFIG_ACPI_DEBUG=y
# CONFIG_ACPI_DEBUG_FUNC_TRACE is not set
diff --git a/config/i386/default b/config/i386/default
index 4dca0d9871..6e80470b46 100644
--- a/config/i386/default
+++ b/config/i386/default
@@ -501,6 +501,7 @@ CONFIG_ACPI_PROCESSOR_AGGREGATOR=m
CONFIG_ACPI_THERMAL=m
CONFIG_ACPI_CUSTOM_DSDT_FILE=""
# CONFIG_ACPI_CUSTOM_DSDT is not set
+CONFIG_ACPI_INITRD_TABLE_OVERRIDE=y
CONFIG_ACPI_BLACKLIST_YEAR=0
CONFIG_ACPI_DEBUG=y
# CONFIG_ACPI_DEBUG_FUNC_TRACE is not set
diff --git a/config/i386/desktop b/config/i386/desktop
index 050381ed6a..735f81ec51 100644
--- a/config/i386/desktop
+++ b/config/i386/desktop
@@ -520,6 +520,7 @@ CONFIG_ACPI_THERMAL=m
CONFIG_ACPI_NUMA=y
CONFIG_ACPI_CUSTOM_DSDT_FILE=""
# CONFIG_ACPI_CUSTOM_DSDT is not set
+CONFIG_ACPI_INITRD_TABLE_OVERRIDE=y
CONFIG_ACPI_BLACKLIST_YEAR=0
CONFIG_ACPI_DEBUG=y
# CONFIG_ACPI_DEBUG_FUNC_TRACE is not set
diff --git a/config/i386/pae b/config/i386/pae
index 235a67ec65..c559a0c0ac 100644
--- a/config/i386/pae
+++ b/config/i386/pae
@@ -518,6 +518,7 @@ CONFIG_ACPI_THERMAL=m
CONFIG_ACPI_NUMA=y
CONFIG_ACPI_CUSTOM_DSDT_FILE=""
# CONFIG_ACPI_CUSTOM_DSDT is not set
+CONFIG_ACPI_INITRD_TABLE_OVERRIDE=y
CONFIG_ACPI_BLACKLIST_YEAR=0
CONFIG_ACPI_DEBUG=y
# CONFIG_ACPI_DEBUG_FUNC_TRACE is not set
diff --git a/config/i386/trace b/config/i386/trace
index 5e1675562e..82adab26b6 100644
--- a/config/i386/trace
+++ b/config/i386/trace
@@ -518,6 +518,7 @@ CONFIG_ACPI_THERMAL=m
CONFIG_ACPI_NUMA=y
CONFIG_ACPI_CUSTOM_DSDT_FILE=""
# CONFIG_ACPI_CUSTOM_DSDT is not set
+CONFIG_ACPI_INITRD_TABLE_OVERRIDE=y
CONFIG_ACPI_BLACKLIST_YEAR=0
CONFIG_ACPI_DEBUG=y
# CONFIG_ACPI_DEBUG_FUNC_TRACE is not set
diff --git a/config/i386/xen b/config/i386/xen
index bd16925407..3bb347c7a6 100644
--- a/config/i386/xen
+++ b/config/i386/xen
@@ -424,6 +424,7 @@ CONFIG_ACPI_HOTPLUG_CPU=y
CONFIG_ACPI_THERMAL=m
CONFIG_ACPI_CUSTOM_DSDT_FILE=""
# CONFIG_ACPI_CUSTOM_DSDT is not set
+CONFIG_ACPI_INITRD_TABLE_OVERRIDE=y
CONFIG_ACPI_BLACKLIST_YEAR=0
CONFIG_ACPI_DEBUG=y
# CONFIG_ACPI_DEBUG_FUNC_TRACE is not set
diff --git a/config/ia64/debug b/config/ia64/debug
index acd69975c0..d679d59b8e 100644
--- a/config/ia64/debug
+++ b/config/ia64/debug
@@ -346,6 +346,7 @@ CONFIG_ACPI_THERMAL=m
CONFIG_ACPI_NUMA=y
CONFIG_ACPI_CUSTOM_DSDT_FILE=""
# CONFIG_ACPI_CUSTOM_DSDT is not set
+# CONFIG_ACPI_INITRD_TABLE_OVERRIDE is not set
CONFIG_ACPI_BLACKLIST_YEAR=0
CONFIG_ACPI_DEBUG=y
# CONFIG_ACPI_DEBUG_FUNC_TRACE is not set
diff --git a/config/ia64/default b/config/ia64/default
index dbdc00c1da..d1f3eb6dcb 100644
--- a/config/ia64/default
+++ b/config/ia64/default
@@ -346,6 +346,7 @@ CONFIG_ACPI_THERMAL=m
CONFIG_ACPI_NUMA=y
CONFIG_ACPI_CUSTOM_DSDT_FILE=""
# CONFIG_ACPI_CUSTOM_DSDT is not set
+# CONFIG_ACPI_INITRD_TABLE_OVERRIDE is not set
CONFIG_ACPI_BLACKLIST_YEAR=0
# CONFIG_ACPI_DEBUG is not set
CONFIG_ACPI_PCI_SLOT=m
diff --git a/config/ia64/trace b/config/ia64/trace
index 1c8406cd37..eccbb0b255 100644
--- a/config/ia64/trace
+++ b/config/ia64/trace
@@ -346,6 +346,7 @@ CONFIG_ACPI_THERMAL=m
CONFIG_ACPI_NUMA=y
CONFIG_ACPI_CUSTOM_DSDT_FILE=""
# CONFIG_ACPI_CUSTOM_DSDT is not set
+# CONFIG_ACPI_INITRD_TABLE_OVERRIDE is not set
CONFIG_ACPI_BLACKLIST_YEAR=0
# CONFIG_ACPI_DEBUG is not set
CONFIG_ACPI_PCI_SLOT=m
diff --git a/config/x86_64/debug b/config/x86_64/debug
index 99a05fc2ea..d838b9bafb 100644
--- a/config/x86_64/debug
+++ b/config/x86_64/debug
@@ -480,6 +480,7 @@ CONFIG_ACPI_THERMAL=m
CONFIG_ACPI_NUMA=y
CONFIG_ACPI_CUSTOM_DSDT_FILE=""
# CONFIG_ACPI_CUSTOM_DSDT is not set
+CONFIG_ACPI_INITRD_TABLE_OVERRIDE=y
CONFIG_ACPI_BLACKLIST_YEAR=0
CONFIG_ACPI_DEBUG=y
# CONFIG_ACPI_DEBUG_FUNC_TRACE is not set
diff --git a/config/x86_64/default b/config/x86_64/default
index bdd46be9d9..8d5e61e448 100644
--- a/config/x86_64/default
+++ b/config/x86_64/default
@@ -480,6 +480,7 @@ CONFIG_ACPI_THERMAL=m
CONFIG_ACPI_NUMA=y
CONFIG_ACPI_CUSTOM_DSDT_FILE=""
# CONFIG_ACPI_CUSTOM_DSDT is not set
+CONFIG_ACPI_INITRD_TABLE_OVERRIDE=y
CONFIG_ACPI_BLACKLIST_YEAR=0
CONFIG_ACPI_DEBUG=y
# CONFIG_ACPI_DEBUG_FUNC_TRACE is not set
diff --git a/config/x86_64/desktop b/config/x86_64/desktop
index 72cb6d33f1..3c7a121903 100644
--- a/config/x86_64/desktop
+++ b/config/x86_64/desktop
@@ -482,6 +482,7 @@ CONFIG_ACPI_THERMAL=m
CONFIG_ACPI_NUMA=y
CONFIG_ACPI_CUSTOM_DSDT_FILE=""
# CONFIG_ACPI_CUSTOM_DSDT is not set
+CONFIG_ACPI_INITRD_TABLE_OVERRIDE=y
CONFIG_ACPI_BLACKLIST_YEAR=0
CONFIG_ACPI_DEBUG=y
# CONFIG_ACPI_DEBUG_FUNC_TRACE is not set
diff --git a/config/x86_64/trace b/config/x86_64/trace
index 223a3d6164..8f6e37300b 100644
--- a/config/x86_64/trace
+++ b/config/x86_64/trace
@@ -480,6 +480,7 @@ CONFIG_ACPI_THERMAL=m
CONFIG_ACPI_NUMA=y
CONFIG_ACPI_CUSTOM_DSDT_FILE=""
# CONFIG_ACPI_CUSTOM_DSDT is not set
+CONFIG_ACPI_INITRD_TABLE_OVERRIDE=y
CONFIG_ACPI_BLACKLIST_YEAR=0
CONFIG_ACPI_DEBUG=y
# CONFIG_ACPI_DEBUG_FUNC_TRACE is not set
diff --git a/config/x86_64/xen b/config/x86_64/xen
index d78c344e6e..af731d40eb 100644
--- a/config/x86_64/xen
+++ b/config/x86_64/xen
@@ -394,6 +394,7 @@ CONFIG_ACPI_HOTPLUG_CPU=y
CONFIG_ACPI_THERMAL=m
CONFIG_ACPI_CUSTOM_DSDT_FILE=""
# CONFIG_ACPI_CUSTOM_DSDT is not set
+CONFIG_ACPI_INITRD_TABLE_OVERRIDE=y
CONFIG_ACPI_BLACKLIST_YEAR=0
CONFIG_ACPI_DEBUG=y
# CONFIG_ACPI_DEBUG_FUNC_TRACE is not set
diff --git a/patches.arch/acpi_implement_overriding_of_arbitrary_acpi_tables_via_initrd.patch b/patches.arch/acpi_implement_overriding_of_arbitrary_acpi_tables_via_initrd.patch
new file mode 100644
index 0000000000..0b1628444f
--- /dev/null
+++ b/patches.arch/acpi_implement_overriding_of_arbitrary_acpi_tables_via_initrd.patch
@@ -0,0 +1,455 @@
+Subject: ACPI: Implement overriding of arbitrary ACPI tables via initrd
+From: Thomas Renninger <trenn@suse.de>
+References: none
+Patch-Mainline: submitted, aiming for 3.2
+
+Details can be found in:
+Documentation/acpi/initrd_table_override.txt
+
+Additional dmesg output of a booted system with
+FACP (FADT), DSDT and SSDT (the 9th dynamically loaded one)
+tables overridden (with ### marked comments):
+
+### ACPI tables found glued to initrd
+DSDT ACPI table found in initrd - size: 16234
+FACP ACPI table found in initrd - size: 116
+SSDT ACPI table found in initrd - size: 334
+### Re-printed e820 map via e820_update() with additionally created
+### ACPI data section at 0xcff55000 where the ACPI tables passed via
+### initrd where copied to
+modified physical RAM map:
+...
+ ### New ACPI data section:
+ modified: 00000000cff55000 - 00000000cff5912c (ACPI data)
+ ### BIOS e820 provided ACPI data section:
+ modified: 00000000cff60000 - 00000000cff69000 (ACPI data)
+...
+### Total size of all ACPI tables glued to initrd
+### The address is initrd_start which gets updated to
+### initrd_start = initrd_start + "size of all ACPI tables glued to initrd"
+Found acpi tables of size: 16684 at 0xffff8800374c4000
+
+Disabling lock debugging due to kernel taint
+### initrd provided FACP and DSDT tables are used instead of BIOS provided ones
+ACPI: FACP @ 0x00000000cff68dd8 Phys table override, replaced with:
+ACPI: FACP 00000000cff58f6a 00074 (v01 INTEL TUMWATER 06040000 PTL 00000003)
+ACPI: DSDT @ 0x00000000cff649d4 Phys table override, replaced with:
+ACPI: DSDT 00000000cff55000 04404 (v01 Intel BLAKFORD 06040000 MSFT 0100000E)
+...
+### Much later, the 9th (/sys/firmware/acpi/table/dynamic/SSDT9) dynamically
+### loaded ACPI table matches and gets overridden:
+ACPI: SSDT @ 0x00000000cff64824 Phys table override, replaced with:
+ACPI: SSDT 00000000cff58fde 0014E (v01 PmRef Cpu7Ist 00003000 INTL 20110316)
+ACPI: Dynamic OEM Table Load:
+ACPI: SSDT (null) 0014E (v01 PmRef Cpu7Ist 00003000 INTL 20110316)
+...
+
+If the initrd does not start with a valid ACPI table signature or the ACPI
+table's checksum is wrong, there is no functional change.
+
+Signed-off-by: Thomas Renninger <trenn@suse.de>
+CC: linux-acpi@vger.kernel.org
+CC: lenb@kernel.org
+CC: linux-kernel@vger.kernel.org
+CC: x86@kernel.org
+---
+ Documentation/acpi/initrd_table_override.txt | 110 +++++++++++++++++++
+ arch/x86/kernel/setup.c | 18 ++-
+ arch/x86/mm/init.c | 6 +
+ drivers/acpi/Kconfig | 10 +
+ drivers/acpi/osl.c | 149 ++++++++++++++++++++++++++-
+ include/linux/acpi.h | 4
+ include/linux/initrd.h | 3
+ 7 files changed, 292 insertions(+), 8 deletions(-)
+ create mode 100644 Documentation/acpi/initrd_table_override.txt
+
+Index: linux-3.1-rc6-master/Documentation/acpi/initrd_table_override.txt
+===================================================================
+--- /dev/null
++++ linux-3.1-rc6-master/Documentation/acpi/initrd_table_override.txt
+@@ -0,0 +1,110 @@
++Overriding ACPI tables via initrd
++=================================
++
++1) Introduction (What is this about)
++2) What is this for
++3) How does it work
++4) References (Where to retrieve userspace tools)
++
++1) What is this about
++---------------------
++
++If ACPI_INITRD_TABLE_OVERRIDE compile option is true, it is possible to
++override nearly any ACPI table provided by the BIOS with an instrumented,
++modified one.
++
++Up to 10 arbitrary ACPI tables can be passed.
++For a full list of ACPI tables that can be overridden, take a look at
++the char *table_sigs[MAX_ACPI_SIGNATURE]; definition in drivers/acpi/osl.c
++All ACPI tables iasl (Intel's ACPI compiler and disassembler) knows should
++be overridable, except:
++ - ACPI_SIG_RSDP (has a signature of 6 bytes)
++ - ACPI_SIG_FACS (does not have an ordinary ACPI table header)
++Both could get implemented as well.
++
++
++2) What is this for
++-------------------
++
++Please keep in mind that this is a debug option.
++ACPI tables should not get overridden for productive use.
++If BIOS ACPI tables are overridden the kernel will get tainted with the
++TAINT_OVERRIDDEN_ACPI_TABLE flag.
++Complain to your platform/BIOS vendor if you find a bug which is that sever
++that a workaround is not accepted in the Linus kernel.
++
++Still, it can and should be enabled in any kernel, because:
++ - There is no functional change with not instrumented initrds
++ - It provides a powerful feature to easily debug and test ACPI BIOS table
++ compatibility with the Linux kernel.
++
++Until now it was only possible to override the DSDT by compiling it into
++the kernel. This is a nightmare when trying to work on ACPI related bugs
++and a lot bugs got stuck because of that.
++Even for people with enough kernel knowledge, building a kernel to try out
++things is very time consuming. Also people may have to browse and modify the
++ACPI interpreter code to find a possible BIOS bug. With this feature, people
++can correct the ACPI tables and try out quickly whether this is the root cause
++that needs to get addressed in the kernel.
++
++This could even ease up testing for BIOS providers who could flush their BIOS
++to test, but overriding table via initrd is much easier and quicker.
++For example one could prepare different initrds overriding NUMA tables with
++different affinity settings. Set up a script, let the machine reboot and
++run tests over night and one can get a picture how these settings influence
++the Linux kernel and which values are best.
++
++People can instrument the dynamic ACPI (ASL) code (for example with debug
++statements showing up in syslog when the ACPI code is processed, etc.),
++to better understand BIOS to OS interfaces, to hunt down ACPI BIOS code related
++bugs quickly or to easier develop ACPI based drivers.
++
++Intstrumenting ACPI code in SSDTs is now much easier. Before, one had to copy
++all SSDTs into the DSDT to compile it into the kernel for testing
++(because only DSDT could get overridden). That's what the acpi_no_auto_ssdt
++boot param is for: the BIOS provided SSDTs are ignored and all have to get
++copied into the DSDT, complicated and time consuming.
++
++Much more use cases, depending on which ACPI parts you are working on...
++
++
++3) How does it work
++-------------------
++
++# Extract the machine's ACPI tables:
++acpidump >acpidump
++acpixtract -a acpidump
++# Disassemble, modify and recompile them:
++iasl -d *.dat
++# For example add this statement into a _PRT (PCI Routing Table) function
++# of the DSDT:
++Store("Hello World", debug)
++iasl -sa *.dsl
++# glue them together with the initrd. ACPI tables go first, original initrd
++# goes on top:
++cat TBL1.dat >>instrumented_initrd
++cat TBL2.dat >>instrumented_initrd
++cat TBL3.dat >>instrumented_initrd
++cat /boot/initrd >>instrumented_initrd
++# reboot with increased acpi debug level, e.g. boot params:
++acpi.debug_level=0x2 acpi.debug_layer=0xFFFFFFFF
++# and check your syslog:
++[ 1.268089] ACPI: PCI Interrupt Routing Table [\_SB_.PCI0._PRT]
++[ 1.272091] [ACPI Debug] String [0x0B] "HELLO WORLD"
++
++iasl is able to disassemble and recompile quite a lot different,
++also static ACPI tables.
++
++4) Where to retrieve userspace tools
++------------------------------------
++
++iasl and acpixtract are part of Intel's ACPICA project:
++http://acpica.org/
++and should be packaged by distributions (for example in the acpica package
++on SUSE).
++
++acpidump can be found in Len Browns pmtools:
++ftp://kernel.org/pub/linux/kernel/people/lenb/acpi/utils/pmtools/acpidump
++This tool is also part of the acpica package on SUSE.
++Alternatively used ACPI tables can be retrieved via sysfs in latest kernels:
++/sys/firmware/acpi/tables
+Index: linux-3.1-rc6-master/arch/x86/kernel/setup.c
+===================================================================
+--- linux-3.1-rc6-master.orig/arch/x86/kernel/setup.c
++++ linux-3.1-rc6-master/arch/x86/kernel/setup.c
+@@ -411,12 +411,20 @@ static void __init reserve_initrd(void)
+ */
+ initrd_start = ramdisk_image + PAGE_OFFSET;
+ initrd_end = initrd_start + ramdisk_size;
+- return;
++ } else {
++ relocate_initrd();
++ memblock_x86_free_range(ramdisk_image, ramdisk_end);
+ }
+-
+- relocate_initrd();
+-
+- memblock_x86_free_range(ramdisk_image, ramdisk_end);
++#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
++ acpi_initrd_offset = acpi_initrd_table_override((void *)initrd_start,
++ (void *)initrd_end);
++ if (!acpi_initrd_offset)
++ return;
++ printk(KERN_INFO "Found acpi tables of size: %lu at 0x%lx\n",
++ acpi_initrd_offset, initrd_start);
++ initrd_start += acpi_initrd_offset;
++ return;
++#endif
+ }
+ #else
+ static void __init reserve_initrd(void)
+Index: linux-3.1-rc6-master/arch/x86/mm/init.c
+===================================================================
+--- linux-3.1-rc6-master.orig/arch/x86/mm/init.c
++++ linux-3.1-rc6-master/arch/x86/mm/init.c
+@@ -390,6 +390,12 @@ void free_initrd_mem(unsigned long start
+ * - relocate_initrd()
+ * So here We can do PAGE_ALIGN() safely to get partial page to be freed
+ */
++#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
++ if (acpi_initrd_offset)
++ free_init_pages("initrd memory", start - acpi_initrd_offset,
++ PAGE_ALIGN(end));
++ else
++#endif
+ free_init_pages("initrd memory", start, PAGE_ALIGN(end));
+ }
+ #endif
+Index: linux-3.1-rc6-master/drivers/acpi/Kconfig
+===================================================================
+--- linux-3.1-rc6-master.orig/drivers/acpi/Kconfig
++++ linux-3.1-rc6-master/drivers/acpi/Kconfig
+@@ -261,6 +261,16 @@ config ACPI_CUSTOM_DSDT
+ bool
+ default ACPI_CUSTOM_DSDT_FILE != ""
+
++config ACPI_INITRD_TABLE_OVERRIDE
++ bool
++ depends on X86
++ default y
++ help
++ This option provides functionality to override arbitrary ACPI tables
++ via initrd. No functional change if no ACPI tables are glued to the
++ initrd, therefore it's safe to say Y.
++ See Documentation/acpi/initrd_table_override.txt for details
++
+ config ACPI_BLACKLIST_YEAR
+ int "Disable ACPI for systems before Jan 1st this year" if X86_32
+ default 0
+Index: linux-3.1-rc6-master/drivers/acpi/osl.c
+===================================================================
+--- linux-3.1-rc6-master.orig/drivers/acpi/osl.c
++++ linux-3.1-rc6-master/drivers/acpi/osl.c
+@@ -44,9 +44,11 @@
+ #include <linux/list.h>
+ #include <linux/jiffies.h>
+ #include <linux/semaphore.h>
++#include <linux/memblock.h>
+
+ #include <asm/io.h>
+ #include <asm/uaccess.h>
++#include <asm/e820.h>
+
+ #include <acpi/acpi.h>
+ #include <acpi/acpi_bus.h>
+@@ -499,6 +501,107 @@ acpi_os_predefined_override(const struct
+ return AE_OK;
+ }
+
++#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
++#define ACPI_OVERRIDE_TABLES 10
++
++static unsigned long acpi_table_override_offset[ACPI_OVERRIDE_TABLES];
++static u64 acpi_tables_inram;
++
++unsigned long __initdata acpi_initrd_offset;
++
++/* Copied from acpica/tbutils.c:acpi_tb_checksum() */
++u8 __init acpi_table_checksum(u8 *buffer, u32 length)
++{
++ u8 sum = 0;
++ u8 *end = buffer + length;
++
++ while (buffer < end)
++ sum = (u8) (sum + *(buffer++));
++ return sum;
++}
++
++/* All but ACPI_SIG_RSDP and ACPI_SIG_FACS: */
++#define MAX_ACPI_SIGNATURE 35
++static const char *table_sigs[MAX_ACPI_SIGNATURE] = {
++ ACPI_SIG_BERT, ACPI_SIG_CPEP, ACPI_SIG_ECDT, ACPI_SIG_EINJ,
++ ACPI_SIG_ERST, ACPI_SIG_HEST, ACPI_SIG_MADT, ACPI_SIG_MSCT,
++ ACPI_SIG_SBST, ACPI_SIG_SLIT, ACPI_SIG_SRAT, ACPI_SIG_ASF,
++ ACPI_SIG_BOOT, ACPI_SIG_DBGP, ACPI_SIG_DMAR, ACPI_SIG_HPET,
++ 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_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT };
++
++int __init acpi_initrd_table_override(void *start_addr, void *end_addr)
++{
++ int table_nr, sig;
++ unsigned long offset = 0, max_len = end_addr - start_addr;
++ char *p;
++
++ for (table_nr = 0; table_nr < ACPI_OVERRIDE_TABLES; table_nr++) {
++ struct acpi_table_header *table;
++ if (max_len < offset + sizeof(struct acpi_table_header)) {
++ WARN_ON(1);
++ return 0;
++ }
++ table = start_addr + offset;
++
++ for (sig = 0; sig < MAX_ACPI_SIGNATURE; sig++)
++ if (!memcmp(table->signature, table_sigs[sig], 4))
++ break;
++
++ if (sig >= MAX_ACPI_SIGNATURE)
++ break;
++
++ if (max_len < offset + table->length) {
++ WARN_ON(1);
++ return 0;
++ }
++
++ if (acpi_table_checksum(start_addr + offset, table->length)) {
++ WARN(1, "%4.4s has invalid checksum\n",
++ table->signature);
++ continue;
++ }
++ printk(KERN_INFO "%4.4s ACPI table found in initrd"
++ " - size: %d\n", table->signature, table->length);
++
++ offset += table->length;
++ acpi_table_override_offset[table_nr] = offset;
++ }
++ if (!offset)
++ return 0;
++
++ acpi_tables_inram =
++ memblock_find_in_range(0, max_low_pfn_mapped << PAGE_SHIFT,
++ offset, PAGE_SIZE);
++ if (acpi_tables_inram == MEMBLOCK_ERROR)
++ panic("Cannot find place for ACPI override tables\n");
++
++ /*
++ * Only calling e820_add_reserve does not work and the
++ * tables are invalid (memory got used) later.
++ * memblock_x86_reserve_range works as expected and the tables
++ * won't get modified. But it's not enough because ioremap will
++ * complain later (used by acpi_os_map_memory) that the pages
++ * that should get mapped are not marked "reserved".
++ * Both memblock_x86_reserve_range and e820_add_region works fine.
++ */
++ memblock_x86_reserve_range(acpi_tables_inram,
++ acpi_tables_inram + offset,
++ "ACPI TABLE OVERRIDE");
++ e820_add_region(acpi_tables_inram, offset, E820_ACPI);
++ update_e820();
++
++ p = early_ioremap(acpi_tables_inram, offset);
++ memcpy(p, start_addr, offset);
++ early_iounmap(p, offset);
++ return offset;
++}
++
++#endif
++
+ acpi_status
+ acpi_os_table_override(struct acpi_table_header * existing_table,
+ struct acpi_table_header ** new_table)
+@@ -526,11 +629,51 @@ acpi_status
+ acpi_os_phys_table_override(struct acpi_table_header *existing_table,
+ acpi_physical_address *address, u32 *table_length)
+ {
+- if (!existing_table)
+- return AE_BAD_PARAMETER;
+
+- table_length = 0;
++#ifndef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
++ *table_length = 0;
++ *address = 0;
+ return AE_OK;
++#else
++ int table_nr = 0;
++ *table_length = 0;
++ *address = 0;
++ for (; table_nr < ACPI_OVERRIDE_TABLES &&
++ acpi_table_override_offset[table_nr]; table_nr++) {
++ int table_offset;
++ int table_len;
++ struct acpi_table_header *table;
++
++ if (table_nr == 0)
++ table_offset = 0;
++ else
++ table_offset = acpi_table_override_offset[table_nr - 1];
++
++ table_len = acpi_table_override_offset[table_nr] - table_offset;
++
++ table = acpi_os_map_memory(acpi_tables_inram + table_offset,
++ table_len);
++
++ if (memcmp(existing_table->signature, table->signature, 4)) {
++ acpi_os_unmap_memory(table, table_len);
++ continue;
++ }
++
++ /* Only override tables with matching oem id */
++ if (memcmp(table->oem_table_id, existing_table->oem_table_id,
++ ACPI_OEM_TABLE_ID_SIZE)) {
++ acpi_os_unmap_memory(table, table_len);
++ continue;
++ }
++
++ acpi_os_unmap_memory(table, table_len);
++ *address = acpi_tables_inram + table_offset;
++ *table_length = table_len;
++ add_taint(TAINT_OVERRIDDEN_ACPI_TABLE);
++ break;
++ }
++ return AE_OK;
++#endif
+ }
+
+ static irqreturn_t acpi_irq(int irq, void *dev_id)
+Index: linux-3.1-rc6-master/include/linux/acpi.h
+===================================================================
+--- linux-3.1-rc6-master.orig/include/linux/acpi.h
++++ linux-3.1-rc6-master/include/linux/acpi.h
+@@ -76,6 +76,10 @@ typedef int (*acpi_table_handler) (struc
+
+ typedef int (*acpi_table_entry_handler) (struct acpi_subtable_header *header, const unsigned long end);
+
++#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
++int __init acpi_initrd_table_override(void *start_addr, void *end_addr);
++#endif
++
+ char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
+ void __acpi_unmap_table(char *map, unsigned long size);
+ int early_acpi_boot_init(void);
+Index: linux-3.1-rc6-master/include/linux/initrd.h
+===================================================================
+--- linux-3.1-rc6-master.orig/include/linux/initrd.h
++++ linux-3.1-rc6-master/include/linux/initrd.h
+@@ -16,5 +16,8 @@ extern int initrd_below_start_ok;
+ /* free_initrd_mem always gets called with the next two as arguments.. */
+ extern unsigned long initrd_start, initrd_end;
+ extern void free_initrd_mem(unsigned long, unsigned long);
++#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
++extern unsigned long acpi_initrd_offset;
++#endif
+
+ extern unsigned int real_root_dev;
diff --git a/patches.arch/acpica_fix_wrongly_mapped_acpi_table_header_when_overriding_via_initrd.patch b/patches.arch/acpica_fix_wrongly_mapped_acpi_table_header_when_overriding_via_initrd.patch
new file mode 100644
index 0000000000..82610067e4
--- /dev/null
+++ b/patches.arch/acpica_fix_wrongly_mapped_acpi_table_header_when_overriding_via_initrd.patch
@@ -0,0 +1,45 @@
+Subject: ACPICA: Fix wrongly mapped acpi table header when overriding via initrd
+From: Michael Chang <mchang@suse.com>
+References: none
+Patch-Mainline: submitted, aiming for 3.2
+
+Fix the overriding ACPI table header do not override the existing ACPI
+header thus the existing one is still in use. This caused a discrepency
+of header and body, which would introdce a serios side effect that when
+overriding DSDT, system might have error with "Unable to load the System
+Description Tables" due to DSDT table verified failed.
+
+Most field in ACPI table is static, but the length field is dyamically
+changed and corresponds the new assembled *.aml size. We reserve the
+ACPI data region using the overridden table size but attemps to map it
+with existing ACPI table size introduced by above discrepency. It
+would lead to remap fail during verifying DSDT able if length difference
+cross a page boundary.
+
+Signed-off-by: Michael Chang <mchang@suse.com>
+---
+ drivers/acpi/acpica/tbutils.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c
+index df85afe..2e797d9 100644
+--- a/drivers/acpi/acpica/tbutils.c
++++ b/drivers/acpi/acpica/tbutils.c
+@@ -511,9 +511,9 @@ acpi_tb_install_table(acpi_physical_address address,
+ ACPI_CAST_PTR(void, address)));
+ acpi_os_unmap_memory(mapped_table,
+ sizeof(struct acpi_table_header));
++ address = tmp_addr;
+ mapped_table = acpi_os_map_memory(address,
+ sizeof(struct acpi_table_header));
+- address = tmp_addr;
+ }
+ flags = ACPI_TABLE_ORIGIN_MAPPED;
+ table_to_install = mapped_table;
+--
+1.7.3.4
+
+--
+To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
+the body of a message to majordomo@vger.kernel.org
+More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/patches.arch/acpica_introduce_acpi_os_phys_table_override_function.patch b/patches.arch/acpica_introduce_acpi_os_phys_table_override_function.patch
new file mode 100644
index 0000000000..4052a9b175
--- /dev/null
+++ b/patches.arch/acpica_introduce_acpi_os_phys_table_override_function.patch
@@ -0,0 +1,129 @@
+Subject: ACPICA: Introduce acpi_os_phys_table_override function
+From: Thomas Renninger <trenn@suse.de>
+References: none
+Patch-Mainline: submitted, aiming for 3.2
+
+Currently it's only possible to feed acpica with virtual
+address for table overriding.
+This patch introduces a function which allows the OS to
+pass physical addresses for table overriding.
+
+This is necessary to allow early table overridings of
+arbitrary ACPI tables.
+
+An extra flag like ACPI_TABLE_ORIGIN_OVERRIDE is not used,
+because physical address overriding is rather transparent
+(the same way acpica expects to get tables from reserved
+memory BIOS regions which is the normal way).
+
+Signed-off-by: Thomas Renninger <trenn@suse.de>
+CC: devel@acpica.org
+CC: linux-acpi@vger.kernel.org
+CC: lenb@kernel.org
+---
+ drivers/acpi/acpica/tbinstal.c | 15 +++++++++++++++
+ drivers/acpi/acpica/tbutils.c | 18 +++++++++++++++++-
+ drivers/acpi/osl.c | 11 +++++++++++
+ include/acpi/acpiosxf.h | 4 ++++
+ 4 files changed, 47 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c
+index 62365f6..b9b9d2a 100644
+--- a/drivers/acpi/acpica/tbinstal.c
++++ b/drivers/acpi/acpica/tbinstal.c
+@@ -242,6 +242,21 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
+ table_desc->pointer = override_table;
+ table_desc->length = override_table->length;
+ table_desc->flags = ACPI_TABLE_ORIGIN_OVERRIDE;
++ } else {
++ acpi_physical_address address = 0;
++ u32 table_len = 0;
++ status = acpi_os_phys_table_override(table_desc->pointer,
++ &address, &table_len);
++ if (ACPI_SUCCESS(status) && table_len && address) {
++ ACPI_INFO((AE_INFO, "%4.4s @ 0x%p "
++ "Phys table override, replaced with:",
++ table_desc->pointer->signature,
++ ACPI_CAST_PTR(void, table_desc->address)));
++ table_desc->address = address;
++ table_desc->pointer = acpi_os_map_memory(address,
++ table_len);
++ table_desc->length = table_len;
++ }
+ }
+
+ /* Add the table to the global root table list */
+diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c
+index 0f2d395..df85afe 100644
+--- a/drivers/acpi/acpica/tbutils.c
++++ b/drivers/acpi/acpica/tbutils.c
+@@ -499,8 +499,24 @@ acpi_tb_install_table(acpi_physical_address address,
+ table_to_install = override_table;
+ flags = ACPI_TABLE_ORIGIN_OVERRIDE;
+ } else {
+- table_to_install = mapped_table;
++ u32 table_len = 0;
++ acpi_physical_address tmp_addr = 0;
++
++ status = acpi_os_phys_table_override(mapped_table,
++ &tmp_addr, &table_len);
++ if (ACPI_SUCCESS(status) && table_len && tmp_addr) {
++ ACPI_INFO((AE_INFO, "%4.4s @ 0x%p "
++ "Phys table override, replaced with:",
++ mapped_table->signature,
++ ACPI_CAST_PTR(void, address)));
++ acpi_os_unmap_memory(mapped_table,
++ sizeof(struct acpi_table_header));
++ mapped_table = acpi_os_map_memory(address,
++ sizeof(struct acpi_table_header));
++ address = tmp_addr;
++ }
+ flags = ACPI_TABLE_ORIGIN_MAPPED;
++ table_to_install = mapped_table;
+ }
+
+ /* Initialize the table entry */
+diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
+index fa32f58..49b5fa6 100644
+--- a/drivers/acpi/osl.c
++++ b/drivers/acpi/osl.c
+@@ -522,6 +522,17 @@ acpi_os_table_override(struct acpi_table_header * existing_table,
+ return AE_OK;
+ }
+
++acpi_status
++acpi_os_phys_table_override(struct acpi_table_header *existing_table,
++ acpi_physical_address *address, u32 *table_length)
++{
++ if (!existing_table)
++ return AE_BAD_PARAMETER;
++
++ table_length = 0;
++ return AE_OK;
++}
++
+ static irqreturn_t acpi_irq(int irq, void *dev_id)
+ {
+ u32 handled;
+diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
+index 4543b6f..0bef969 100644
+--- a/include/acpi/acpiosxf.h
++++ b/include/acpi/acpiosxf.h
+@@ -95,6 +95,10 @@ acpi_status
+ acpi_os_table_override(struct acpi_table_header *existing_table,
+ struct acpi_table_header **new_table);
+
++acpi_status
++acpi_os_phys_table_override(struct acpi_table_header *existing_table,
++ acpi_physical_address *address, u32 *table_length);
++
+ /*
+ * Spinlock primitives
+ */
+--
+1.7.3.4
+
+--
+To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
+the body of a message to majordomo@vger.kernel.org
+More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/patches.drivers/apei_allow_drivers_access_nvs_ram.patch b/patches.drivers/apei_allow_drivers_access_nvs_ram.patch
new file mode 100644
index 0000000000..bc8760a606
--- /dev/null
+++ b/patches.drivers/apei_allow_drivers_access_nvs_ram.patch
@@ -0,0 +1,28 @@
+From: Yinghai Lu <yinghai@kernel.org>
+Subject: [PATCH] x86: allow NVS can be accessed by driver
+References: none
+Patch-Mainline: submitted, aiming for 3.2
+
+APEI related...
+
+Signed-off-by: Yinghai Lu <yinghai@kernel.org>
+Signed-off-by: Thomas Renninger <trenn@suse.de>
+
+---
+ arch/x86/kernel/e820.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+Index: linux-2.6/arch/x86/kernel/e820.c
+===================================================================
+--- linux-2.6.orig/arch/x86/kernel/e820.c
++++ linux-2.6/arch/x86/kernel/e820.c
+@@ -995,7 +995,8 @@ void __init e820_reserve_resources(void)
+ * pcibios_resource_survey()
+ */
+ if (e820.map[i].type != E820_RESERVED || res->start < (1ULL<<20)) {
+- res->flags |= IORESOURCE_BUSY;
++ if (e820.map[i].type != E820_NVS)
++ res->flags |= IORESOURCE_BUSY;
+ insert_resource(&iomem_resource, res);
+ }
+ res++;
diff --git a/series.conf b/series.conf
index 1ae603a539..25894158dc 100644
--- a/series.conf
+++ b/series.conf
@@ -215,6 +215,12 @@
# Queued for 2.6.36 -> just revert after some time
patches.fixes/acpi_ec_sys_access_user_space_with_get_user.patch
+ patches.drivers/apei_allow_drivers_access_nvs_ram.patch
+
+ patches.arch/acpica_introduce_acpi_os_phys_table_override_function.patch
+ patches.arch/acpica_fix_wrongly_mapped_acpi_table_header_when_overriding_via_initrd.patch
+ patches.arch/acpi_implement_overriding_of_arbitrary_acpi_tables_via_initrd.patch
+
########################################################
# CPUFREQ
########################################################