OSDN Git Service

mm/highmem: Provide CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP
authorThomas Gleixner <tglx@linutronix.de>
Wed, 18 Nov 2020 19:48:40 +0000 (20:48 +0100)
committerThomas Gleixner <tglx@linutronix.de>
Tue, 24 Nov 2020 13:42:08 +0000 (14:42 +0100)
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 <torvalds@linux-foundation.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/r/20201118204007.028261233@linutronix.de
lib/Kconfig.debug
mm/highmem.c

index f24fa15..e952f89 100644 (file)
@@ -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
index fab128d..39aaca1 100644 (file)
@@ -474,7 +474,12 @@ void *__kmap_local_page_prot(struct page *page, pgprot_t prot)
 {
        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