lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Fri, 26 Jun 2020 19:31:16 +0200
From:   "Rafael J. Wysocki" <rjw@...ysocki.net>
To:     Dan Williams <dan.j.williams@...el.com>,
        Erik Kaneda <erik.kaneda@...el.com>
Cc:     rafael.j.wysocki@...el.com, Len Brown <lenb@...nel.org>,
        Borislav Petkov <bp@...en8.de>,
        Ira Weiny <ira.weiny@...el.com>,
        James Morse <james.morse@....com>,
        Myron Stowe <myron.stowe@...hat.com>,
        Andy Shevchenko <andriy.shevchenko@...ux.intel.com>,
        linux-kernel@...r.kernel.org, linux-acpi@...r.kernel.org,
        linux-nvdimm@...ts.01.org, Bob Moore <robert.moore@...el.com>
Subject: [RFT][PATCH v3 1/4] ACPICA: Take deferred unmapping of memory into account

From: "Rafael J. Wysocki" <rafael.j.wysocki@...el.com>

The ACPI OS layer in Linux uses RCU to protect the walkers of the
list of ACPI memory mappings from seeing an inconsistent state
while it is being updated.  Among other situations, that list can
be walked in (NMI and non-NMI) interrupt context, so using a
sleeping lock to protect it is not an option.

However, performance issues related to the RCU usage in there
appear, as described by Dan Williams:

"Recently a performance problem was reported for a process invoking
a non-trival ASL program. The method call in this case ends up
repetitively triggering a call path like:

    acpi_ex_store
    acpi_ex_store_object_to_node
    acpi_ex_write_data_to_field
    acpi_ex_insert_into_field
    acpi_ex_write_with_update_rule
    acpi_ex_field_datum_io
    acpi_ex_access_region
    acpi_ev_address_space_dispatch
    acpi_ex_system_memory_space_handler
    acpi_os_map_cleanup.part.14
    _synchronize_rcu_expedited.constprop.89
    schedule

The end result of frequent synchronize_rcu_expedited() invocation is
tiny sub-millisecond spurts of execution where the scheduler freely
migrates this apparently sleepy task. The overhead of frequent
scheduler invocation multiplies the execution time by a factor
of 2-3X."

The source of this is that acpi_ex_system_memory_space_handler()
unmaps the memory mapping currently cached by it at the access time
if that mapping doesn't cover the memory area being accessed.
Consequently, if there is a memory opregion with two fields
separated from each other by an unused chunk of address space that
is large enough for not being covered by a single mapping, and they
happen to be used in an alternating pattern, the unmapping will
occur on every acpi_ex_system_memory_space_handler() invocation for
that memory opregion and that will lead to significant overhead.

To address that, acpi_os_unmap_memory() provided by Linux can be
modified so as to avoid unmapping the memory region matching the
address range at hand right away and queue it up for later removal.

However, that requires the deferred unmapping of unused memory
regions to be carried out at least occasionally, so modify
ACPICA to do that by invoking a new OS layer function,
acpi_os_release_unused_mappings(), for this purpose every time
the AML interpreter is exited.

For completeness, also call that function from
acpi_db_test_all_objects() after all of the fields have been
tested.

Reported-by: Dan Williams <dan.j.williams@...el.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@...el.com>
---
 drivers/acpi/acpica/dbtest.c  | 4 ++++
 drivers/acpi/acpica/exutils.c | 2 ++
 include/acpi/acpiosxf.h       | 4 ++++
 3 files changed, 10 insertions(+)

diff --git a/drivers/acpi/acpica/dbtest.c b/drivers/acpi/acpica/dbtest.c
index 6db44a5ac786..55931daa1779 100644
--- a/drivers/acpi/acpica/dbtest.c
+++ b/drivers/acpi/acpica/dbtest.c
@@ -220,6 +220,10 @@ static void acpi_db_test_all_objects(void)
 	(void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
 				  ACPI_UINT32_MAX, acpi_db_test_one_object,
 				  NULL, NULL, NULL);
+
+	/* Release memory mappings that are not needed any more. */
+
+	acpi_os_release_unused_mappings();
 }
 
 /*******************************************************************************
diff --git a/drivers/acpi/acpica/exutils.c b/drivers/acpi/acpica/exutils.c
index 8fefa6feac2f..ae2030095b63 100644
--- a/drivers/acpi/acpica/exutils.c
+++ b/drivers/acpi/acpica/exutils.c
@@ -106,6 +106,8 @@ void acpi_ex_exit_interpreter(void)
 			    "Could not release AML Interpreter mutex"));
 	}
 
+	acpi_os_release_unused_mappings();
+
 	return_VOID;
 }
 
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
index 33bb8c9a089d..0efe2d1725e2 100644
--- a/include/acpi/acpiosxf.h
+++ b/include/acpi/acpiosxf.h
@@ -187,6 +187,10 @@ void *acpi_os_map_memory(acpi_physical_address where, acpi_size length);
 void acpi_os_unmap_memory(void *logical_address, acpi_size size);
 #endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_release_unused_mappings
+#define acpi_os_release_unused_mappings()	do { } while (FALSE)
+#endif
+
 #ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_physical_address
 acpi_status
 acpi_os_get_physical_address(void *logical_address,
-- 
2.26.2




Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ