--- /dev/null
+From 1a1c130ab7575498eed5bcf7220037ae09cd1f8a Mon Sep 17 00:00:00 2001
+From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
+Date: Tue, 23 Mar 2021 20:26:52 +0100
+Subject: ACPI: tables: x86: Reserve memory occupied by ACPI tables
+
+From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+commit 1a1c130ab7575498eed5bcf7220037ae09cd1f8a upstream.
+
+The following problem has been reported by George Kennedy:
+
+ Since commit 7fef431be9c9 ("mm/page_alloc: place pages to tail
+ in __free_pages_core()") the following use after free occurs
+ intermittently when ACPI tables are accessed.
+
+ BUG: KASAN: use-after-free in ibft_init+0x134/0xc49
+ Read of size 4 at addr ffff8880be453004 by task swapper/0/1
+ CPU: 3 PID: 1 Comm: swapper/0 Not tainted 5.12.0-rc1-7a7fd0d #1
+ Call Trace:
+ dump_stack+0xf6/0x158
+ print_address_description.constprop.9+0x41/0x60
+ kasan_report.cold.14+0x7b/0xd4
+ __asan_report_load_n_noabort+0xf/0x20
+ ibft_init+0x134/0xc49
+ do_one_initcall+0xc4/0x3e0
+ kernel_init_freeable+0x5af/0x66b
+ kernel_init+0x16/0x1d0
+ ret_from_fork+0x22/0x30
+
+ ACPI tables mapped via kmap() do not have their mapped pages
+ reserved and the pages can be "stolen" by the buddy allocator.
+
+Apparently, on the affected system, the ACPI table in question is
+not located in "reserved" memory, like ACPI NVS or ACPI Data, that
+will not be used by the buddy allocator, so the memory occupied by
+that table has to be explicitly reserved to prevent the buddy
+allocator from using it.
+
+In order to address this problem, rearrange the initialization of the
+ACPI tables on x86 to locate the initial tables earlier and reserve
+the memory occupied by them.
+
+The other architectures using ACPI should not be affected by this
+change.
+
+Link: https://lore.kernel.org/linux-acpi/1614802160-29362-1-git-send-email-george.kennedy@oracle.com/
+Reported-by: George Kennedy <george.kennedy@oracle.com>
+Tested-by: George Kennedy <george.kennedy@oracle.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Reviewed-by: Mike Rapoport <rppt@linux.ibm.com>
+Cc: 5.10+ <stable@vger.kernel.org> # 5.10+
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/acpi/boot.c | 25 ++++++++++++-------------
+ arch/x86/kernel/setup.c | 8 +++-----
+ drivers/acpi/tables.c | 42 +++++++++++++++++++++++++++++++++++++++---
+ include/linux/acpi.h | 9 ++++++++-
+ 4 files changed, 62 insertions(+), 22 deletions(-)
+
+--- a/arch/x86/kernel/acpi/boot.c
++++ b/arch/x86/kernel/acpi/boot.c
+@@ -1565,10 +1565,18 @@ void __init acpi_boot_table_init(void)
+ /*
+ * Initialize the ACPI boot-time table parser.
+ */
+- if (acpi_table_init()) {
++ if (acpi_locate_initial_tables())
+ disable_acpi();
+- return;
+- }
++ else
++ acpi_reserve_initial_tables();
++}
++
++int __init early_acpi_boot_init(void)
++{
++ if (acpi_disabled)
++ return 1;
++
++ acpi_table_init_complete();
+
+ acpi_table_parse(ACPI_SIG_BOOT, acpi_parse_sbf);
+
+@@ -1581,18 +1589,9 @@ void __init acpi_boot_table_init(void)
+ } else {
+ printk(KERN_WARNING PREFIX "Disabling ACPI support\n");
+ disable_acpi();
+- return;
++ return 1;
+ }
+ }
+-}
+-
+-int __init early_acpi_boot_init(void)
+-{
+- /*
+- * If acpi_disabled, bail out
+- */
+- if (acpi_disabled)
+- return 1;
+
+ /*
+ * Process the Multiple APIC Description Table (MADT), if present
+--- a/arch/x86/kernel/setup.c
++++ b/arch/x86/kernel/setup.c
+@@ -1097,6 +1097,9 @@ void __init setup_arch(char **cmdline_p)
+
+ cleanup_highmap();
+
++ /* Look for ACPI tables and reserve memory occupied by them. */
++ acpi_boot_table_init();
++
+ memblock_set_current_limit(ISA_END_ADDRESS);
+ e820__memblock_setup();
+
+@@ -1183,11 +1186,6 @@ void __init setup_arch(char **cmdline_p)
+
+ early_platform_quirks();
+
+- /*
+- * Parse the ACPI tables for possible boot-time SMP configuration.
+- */
+- acpi_boot_table_init();
+-
+ early_acpi_boot_init();
+
+ initmem_init();
+--- a/drivers/acpi/tables.c
++++ b/drivers/acpi/tables.c
+@@ -732,7 +732,7 @@ acpi_os_table_override(struct acpi_table
+ }
+
+ /*
+- * acpi_table_init()
++ * acpi_locate_initial_tables()
+ *
+ * find RSDP, find and checksum SDT/XSDT.
+ * checksum all tables, print SDT/XSDT
+@@ -740,7 +740,7 @@ acpi_os_table_override(struct acpi_table
+ * result: sdt_entry[] is initialized
+ */
+
+-int __init acpi_table_init(void)
++int __init acpi_locate_initial_tables(void)
+ {
+ acpi_status status;
+
+@@ -755,9 +755,45 @@ int __init acpi_table_init(void)
+ status = acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0);
+ if (ACPI_FAILURE(status))
+ return -EINVAL;
+- acpi_table_initrd_scan();
+
++ return 0;
++}
++
++void __init acpi_reserve_initial_tables(void)
++{
++ int i;
++
++ for (i = 0; i < ACPI_MAX_TABLES; i++) {
++ struct acpi_table_desc *table_desc = &initial_tables[i];
++ u64 start = table_desc->address;
++ u64 size = table_desc->length;
++
++ if (!start || !size)
++ break;
++
++ pr_info("Reserving %4s table memory at [mem 0x%llx-0x%llx]\n",
++ table_desc->signature.ascii, start, start + size - 1);
++
++ memblock_reserve(start, size);
++ }
++}
++
++void __init acpi_table_init_complete(void)
++{
++ acpi_table_initrd_scan();
+ check_multiple_madt();
++}
++
++int __init acpi_table_init(void)
++{
++ int ret;
++
++ ret = acpi_locate_initial_tables();
++ if (ret)
++ return ret;
++
++ acpi_table_init_complete();
++
+ return 0;
+ }
+
+--- a/include/linux/acpi.h
++++ b/include/linux/acpi.h
+@@ -230,10 +230,14 @@ void __iomem *__acpi_map_table(unsigned
+ void __acpi_unmap_table(void __iomem *map, unsigned long size);
+ int early_acpi_boot_init(void);
+ int acpi_boot_init (void);
++void acpi_boot_table_prepare (void);
+ void acpi_boot_table_init (void);
+ int acpi_mps_check (void);
+ int acpi_numa_init (void);
+
++int acpi_locate_initial_tables (void);
++void acpi_reserve_initial_tables (void);
++void acpi_table_init_complete (void);
+ int acpi_table_init (void);
+ int acpi_table_parse(char *id, acpi_tbl_table_handler handler);
+ int __init acpi_table_parse_entries(char *id, unsigned long table_size,
+@@ -734,9 +738,12 @@ static inline int acpi_boot_init(void)
+ return 0;
+ }
+
++static inline void acpi_boot_table_prepare(void)
++{
++}
++
+ static inline void acpi_boot_table_init(void)
+ {
+- return;
+ }
+
+ static inline int acpi_mps_check(void)
--- /dev/null
+From 6998a8800d73116187aad542391ce3b2dd0f9e30 Mon Sep 17 00:00:00 2001
+From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
+Date: Tue, 13 Apr 2021 16:01:00 +0200
+Subject: ACPI: x86: Call acpi_boot_table_init() after acpi_table_upgrade()
+
+From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+commit 6998a8800d73116187aad542391ce3b2dd0f9e30 upstream.
+
+Commit 1a1c130ab757 ("ACPI: tables: x86: Reserve memory occupied by
+ACPI tables") attempted to address an issue with reserving the memory
+occupied by ACPI tables, but it broke the initrd-based table override
+mechanism relied on by multiple users.
+
+To restore the initrd-based ACPI table override functionality, move
+the acpi_boot_table_init() invocation in setup_arch() on x86 after
+the acpi_table_upgrade() one.
+
+Fixes: 1a1c130ab757 ("ACPI: tables: x86: Reserve memory occupied by ACPI tables")
+Reported-by: Hans de Goede <hdegoede@redhat.com>
+Tested-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Cc: George Kennedy <george.kennedy@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/setup.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+--- a/arch/x86/kernel/setup.c
++++ b/arch/x86/kernel/setup.c
+@@ -1097,9 +1097,6 @@ void __init setup_arch(char **cmdline_p)
+
+ cleanup_highmap();
+
+- /* Look for ACPI tables and reserve memory occupied by them. */
+- acpi_boot_table_init();
+-
+ memblock_set_current_limit(ISA_END_ADDRESS);
+ e820__memblock_setup();
+
+@@ -1179,6 +1176,8 @@ void __init setup_arch(char **cmdline_p)
+ reserve_initrd();
+
+ acpi_table_upgrade();
++ /* Look for ACPI tables and reserve memory occupied by them. */
++ acpi_boot_table_init();
+
+ vsmp_init();
+