174cc7187e6f ACPICA: Tables: Back port acpi_get_table_with_size() and early_acpi_os_unmap_memory() from Linux kernel

Message ID CAJZ5v0gEyaqRvYA79bFrkCcw3Yto3WHbh=AdeG3s22_AjkR5iA@mail.gmail.com
State New
Headers show

Commit Message

Rafael J. Wysocki Jan. 11, 2017, 3:42 a.m.
On Tue, Jan 10, 2017 at 10:41 AM, Borislav Petkov <bp@alien8.de> wrote:
> On Tue, Jan 10, 2017 at 02:27:16AM +0100, Rafael J. Wysocki wrote:

>> Well, if the https://patchwork.kernel.org/patch/9504277/ patch from Lv

>> worked, the attached one should work too (please test), but it can be

>> justified in a slightly more convincing way.

>

> No workie:

>

> diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c

> index 57fb5f4..acb6118 100644

> --- a/drivers/acpi/osl.c

> +++ b/drivers/acpi/osl.c

> @@ -378,7 +378,11 @@ static void acpi_os_drop_map_ref(struct acpi_ioremap *map)

>  static void acpi_os_map_cleanup(struct acpi_ioremap *map)

>  {

>         if (!map->refcount) {

> -               synchronize_rcu_expedited();

> +               if (acpi_os_initialized) {

> +                       pr_err("%s: acpi_os_initialized\n", __func__);

> +                       synchronize_rcu_expedited();

> +               }

> +

>                 acpi_unmap(map->phys, map->virt);

>                 kfree(map);

>         }

>

> The pr_err() gets issued before the box hangs.

>

> Lv's version which set the bool in acpi_os_map_generic_address() did

> work though.


Well, it would if nothing mapped by acpi_os_map_generic_address() was
in the memory address space, for example, but then it would never use
the RCU synchronization as well (not good).

Basically, we need to find a point during the initialization such that
acpi_os_read/write_memory() is not invoked earlier and set a flag in
there.

Let's try the attached one.

BTW, I'm going to travel to the LCA starting tomorrow, so I guess I
will be a bit unresponsive during the next few days.

Thanks,
Rafael

Comments

Borislav Petkov Jan. 11, 2017, 9:42 a.m. | #1
On Wed, Jan 11, 2017 at 04:42:16AM +0100, Rafael J. Wysocki wrote:
> Let's try the attached one.


Works, thanks. Lemme give you the tags :)

Reported-and-tested-by: Borislav Petkov <bp@suse.de>
Fixes: 174cc7187e6f ("ACPICA: Tables: Back port acpi_get_table_with_size() and early_acpi_os_unmap_memory() from Linux kernel")
Link: https://lkml.kernel.org/r/4034dde8-ffc1-18e2-f40c-00cf37471793@intel.com

> BTW, I'm going to travel to the LCA starting tomorrow, so I guess I

> will be a bit unresponsive during the next few days.


Sure, we have time. Have a safe trip!

-- 
Regards/Gruss,
    Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.
--
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

Patch hide | download patch | download mbox

---
 drivers/acpi/bus.c     |    6 ++++++
 drivers/acpi/osl.c     |    9 ++++++++-
 include/acpi/acpi_io.h |    1 +
 3 files changed, 15 insertions(+), 1 deletion(-)

Index: linux-pm/drivers/acpi/bus.c
===================================================================
--- linux-pm.orig/drivers/acpi/bus.c
+++ linux-pm/drivers/acpi/bus.c
@@ -1191,6 +1191,12 @@  static int __init acpi_init(void)
 		acpi_kobj = NULL;
 	}
 
+	/*
+	 * acpi_os_read_memory()/acpi_os_write_memory() should not be invoked
+	 * before this point.
+	 */
+	acpi_sync_memory_unmap = true;
+
 	init_acpi_device_notify();
 	result = acpi_bus_init();
 	if (result) {
Index: linux-pm/drivers/acpi/osl.c
===================================================================
--- linux-pm.orig/drivers/acpi/osl.c
+++ linux-pm/drivers/acpi/osl.c
@@ -77,6 +77,7 @@  static struct workqueue_struct *kacpi_ho
 static bool acpi_os_initialized;
 unsigned int acpi_sci_irq = INVALID_ACPI_IRQ;
 bool acpi_permanent_mmap = false;
+bool acpi_sync_memory_unmap;
 
 /*
  * This list of permanent mappings is for memory that may be accessed from
@@ -378,7 +379,9 @@  static void acpi_os_drop_map_ref(struct
 static void acpi_os_map_cleanup(struct acpi_ioremap *map)
 {
 	if (!map->refcount) {
-		synchronize_rcu_expedited();
+		if (acpi_sync_memory_unmap)
+			synchronize_rcu_expedited();
+
 		acpi_unmap(map->phys, map->virt);
 		kfree(map);
 	}
@@ -671,6 +674,8 @@  acpi_os_read_memory(acpi_physical_addres
 	bool unmap = false;
 	u64 dummy;
 
+	WARN_ON_ONCE(!acpi_sync_memory_unmap);
+
 	rcu_read_lock();
 	virt_addr = acpi_map_vaddr_lookup(phys_addr, size);
 	if (!virt_addr) {
@@ -716,6 +721,8 @@  acpi_os_write_memory(acpi_physical_addre
 	unsigned int size = width / 8;
 	bool unmap = false;
 
+	WARN_ON_ONCE(!acpi_sync_memory_unmap);
+
 	rcu_read_lock();
 	virt_addr = acpi_map_vaddr_lookup(phys_addr, size);
 	if (!virt_addr) {
Index: linux-pm/include/acpi/acpi_io.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_io.h
+++ linux-pm/include/acpi/acpi_io.h
@@ -14,6 +14,7 @@  static inline void __iomem *acpi_os_iore
 #endif
 
 extern bool acpi_permanent_mmap;
+extern bool acpi_sync_memory_unmap;
 
 void __iomem *__ref
 acpi_os_map_iomem(acpi_physical_address phys, acpi_size size);