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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Jan 10, 2017 at 10:41 AM, Borislav Petkov <bp@xxxxxxxxx> 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
---
 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);

[Index of Archives]     [Linux IBM ACPI]     [Linux Power Management]     [Linux Kernel]     [Linux Laptop]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux