CONFIG_DEBUG_KMAP_LOCAL, which is selected by CONFIG_DEBUG_HIGHMEM is only
providing guard pages, but does not provide a mechanism to enforce the
usage of the kmap_local() infrastructure.

Provide CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP which forces the temporary
mapping even for lowmem pages. This needs to be a seperate config switch
because this only works on architectures which do not have cache aliasing
problems.

Suggested-by: Linus Torvalds <torva...@linux-foundation.org>
Signed-off-by: Thomas Gleixner <t...@linutronix.de>
---
V4: New patch
---
 lib/Kconfig.debug |   14 ++++++++++++++
 mm/highmem.c      |   12 +++++++++++-
 2 files changed, 25 insertions(+), 1 deletion(-)

--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -856,9 +856,23 @@ config DEBUG_KMAP_LOCAL
          This option enables additional error checking for the kmap_local
          infrastructure.  Disable for production use.
 
+config ARCH_SUPPORTS_KMAP_LOCAL_FORCE_MAP
+       bool
+
+config DEBUG_KMAP_LOCAL_FORCE_MAP
+       bool "Enforce kmap_local temporary mappings"
+       depends on DEBUG_KERNEL && ARCH_SUPPORTS_KMAP_LOCAL_FORCE_MAP
+       select KMAP_LOCAL
+       select DEBUG_KMAP_LOCAL
+       help
+         This option enforces temporary mappings through the kmap_local
+         mechanism for non-highmem pages and on non-highmem systems.
+         Disable this for production systems!
+
 config DEBUG_HIGHMEM
        bool "Highmem debugging"
        depends on DEBUG_KERNEL && HIGHMEM
+       select DEBUG_KMAP_LOCAL_FORCE_MAP if ARCH_SUPPORTS_KMAP_LOCAL_FORCE_MAP
        select DEBUG_KMAP_LOCAL
        help
          This option enables additional error checking for high memory
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -474,7 +474,12 @@ void *__kmap_local_page_prot(struct page
 {
        void *kmap;
 
-       if (!PageHighMem(page))
+       /*
+        * To broaden the usage of the actual kmap_local() machinery always map
+        * pages when debugging is enabled and the architecture has no problems
+        * with alias mappings.
+        */
+       if (!IS_ENABLED(CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP) && 
!PageHighMem(page))
                return page_address(page);
 
        /* Try kmap_high_get() if architecture has it enabled */
@@ -494,6 +499,11 @@ void kunmap_local_indexed(void *vaddr)
 
        if (addr < __fix_to_virt(FIX_KMAP_END) ||
            addr > __fix_to_virt(FIX_KMAP_BEGIN)) {
+               if (IS_ENABLED(CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP)) {
+                       /* This _should_ never happen! See above. */
+                       WARN_ON_ONCE(1);
+                       return;
+               }
                /*
                 * Handle mappings which were obtained by kmap_high_get()
                 * first as the virtual address of such mappings is below

Reply via email to