* [patch V3 17/37] xtensa/mm/highmem: Switch to generic kmap atomic
From: Thomas Gleixner @ 2020-11-03 9:27 UTC (permalink / raw)
To: LKML
Cc: Juri Lelli, linux-aio, Peter Zijlstra, Sebastian Andrzej Siewior,
Joonas Lahtinen, dri-devel, virtualization, Ben Segall,
Chris Mason, Huang Rui, Paul Mackerras, Gerd Hoffmann,
Daniel Bristot de Oliveira, sparclinux, Vincent Chen,
Christoph Hellwig, Vincent Guittot, Arnd Bergmann, Max Filippov,
x86, Russell King, linux-csky, Ingo Molnar, David Airlie,
VMware Graphics, Mel Gorman, nouveau, Dave Airlie, linux-snps-arc,
Ben Skeggs, linux-xtensa, Paul McKenney, intel-gfx,
Roland Scheidegger, Josef Bacik, Steven Rostedt, Linus Torvalds,
Alexander Viro, spice-devel, David Sterba, Rodrigo Vivi,
Dietmar Eggemann, linux-arm-kernel, Jani Nikula, Chris Zankel,
Michal Simek, Thomas Bogendoerfer, Nick Hu, linux-mm,
Vineet Gupta, linux-mips, Christian Koenig, Benjamin LaHaise,
Daniel Vetter, linux-fsdevel, Andrew Morton, linuxppc-dev,
David S. Miller, linux-btrfs, Greentime Hu
In-Reply-To: <20201103092712.714480842@linutronix.de>
No reason having the same code in every architecture
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Chris Zankel <chris@zankel.net>
Cc: Max Filippov <jcmvbkbc@gmail.com>
Cc: linux-xtensa@linux-xtensa.org
---
V3: Remove the kmap types cruft
---
arch/xtensa/Kconfig | 1
arch/xtensa/include/asm/fixmap.h | 4 +--
arch/xtensa/include/asm/highmem.h | 12 ++++++++-
arch/xtensa/mm/highmem.c | 46 ++++----------------------------------
4 files changed, 18 insertions(+), 45 deletions(-)
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -666,6 +666,7 @@ endchoice
config HIGHMEM
bool "High Memory Support"
depends on MMU
+ select KMAP_LOCAL
help
Linux can use the full amount of RAM in the system by
default. However, the default MMUv2 setup only maps the
--- a/arch/xtensa/include/asm/fixmap.h
+++ b/arch/xtensa/include/asm/fixmap.h
@@ -16,7 +16,7 @@
#ifdef CONFIG_HIGHMEM
#include <linux/threads.h>
#include <linux/pgtable.h>
-#include <asm/kmap_types.h>
+#include <asm/kmap_size.h>
#endif
/*
@@ -39,7 +39,7 @@ enum fixed_addresses {
/* reserved pte's for temporary kernel mappings */
FIX_KMAP_BEGIN,
FIX_KMAP_END = FIX_KMAP_BEGIN +
- (KM_TYPE_NR * NR_CPUS * DCACHE_N_COLORS) - 1,
+ (KM_MAX_IDX * NR_CPUS * DCACHE_N_COLORS) - 1,
#endif
__end_of_fixed_addresses
};
--- a/arch/xtensa/include/asm/highmem.h
+++ b/arch/xtensa/include/asm/highmem.h
@@ -16,9 +16,8 @@
#include <linux/pgtable.h>
#include <asm/cacheflush.h>
#include <asm/fixmap.h>
-#include <asm/kmap_types.h>
-#define PKMAP_BASE ((FIXADDR_START - \
+#define PKMAP_BASE ((FIXADDR_START - \
(LAST_PKMAP + 1) * PAGE_SIZE) & PMD_MASK)
#define LAST_PKMAP (PTRS_PER_PTE * DCACHE_N_COLORS)
#define LAST_PKMAP_MASK (LAST_PKMAP - 1)
@@ -68,6 +67,15 @@ static inline void flush_cache_kmaps(voi
flush_cache_all();
}
+enum fixed_addresses kmap_local_map_idx(int type, unsigned long pfn);
+#define arch_kmap_local_map_idx kmap_local_map_idx
+
+enum fixed_addresses kmap_local_unmap_idx(int type, unsigned long addr);
+#define arch_kmap_local_unmap_idx kmap_local_unmap_idx
+
+#define arch_kmap_local_post_unmap(vaddr) \
+ local_flush_tlb_kernel_range(vaddr, vaddr + PAGE_SIZE)
+
void kmap_init(void);
#endif
--- a/arch/xtensa/mm/highmem.c
+++ b/arch/xtensa/mm/highmem.c
@@ -12,8 +12,6 @@
#include <linux/highmem.h>
#include <asm/tlbflush.h>
-static pte_t *kmap_pte;
-
#if DCACHE_WAY_SIZE > PAGE_SIZE
unsigned int last_pkmap_nr_arr[DCACHE_N_COLORS];
wait_queue_head_t pkmap_map_wait_arr[DCACHE_N_COLORS];
@@ -33,59 +31,25 @@ static inline void kmap_waitqueues_init(
static inline enum fixed_addresses kmap_idx(int type, unsigned long color)
{
- return (type + KM_TYPE_NR * smp_processor_id()) * DCACHE_N_COLORS +
+ return (type + KM_MAX_IDX * smp_processor_id()) * DCACHE_N_COLORS +
color;
}
-void *kmap_atomic_high_prot(struct page *page, pgprot_t prot)
+enum fixed_addresses kmap_local_map_idx(int type, unsigned long pfn)
{
- enum fixed_addresses idx;
- unsigned long vaddr;
-
- idx = kmap_idx(kmap_atomic_idx_push(),
- DCACHE_ALIAS(page_to_phys(page)));
- vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
-#ifdef CONFIG_DEBUG_HIGHMEM
- BUG_ON(!pte_none(*(kmap_pte + idx)));
-#endif
- set_pte(kmap_pte + idx, mk_pte(page, prot));
-
- return (void *)vaddr;
+ return kmap_idx(type, DCACHE_ALIAS(pfn << PAGE_SHIFT));
}
-EXPORT_SYMBOL(kmap_atomic_high_prot);
-void kunmap_atomic_high(void *kvaddr)
+enum fixed_addresses kmap_local_unmap_idx(int type, unsigned long addr)
{
- if (kvaddr >= (void *)FIXADDR_START &&
- kvaddr < (void *)FIXADDR_TOP) {
- int idx = kmap_idx(kmap_atomic_idx(),
- DCACHE_ALIAS((unsigned long)kvaddr));
-
- /*
- * Force other mappings to Oops if they'll try to access this
- * pte without first remap it. Keeping stale mappings around
- * is a bad idea also, in case the page changes cacheability
- * attributes or becomes a protected page in a hypervisor.
- */
- pte_clear(&init_mm, kvaddr, kmap_pte + idx);
- local_flush_tlb_kernel_range((unsigned long)kvaddr,
- (unsigned long)kvaddr + PAGE_SIZE);
-
- kmap_atomic_idx_pop();
- }
+ return kmap_idx(type, DCACHE_ALIAS(addr));
}
-EXPORT_SYMBOL(kunmap_atomic_high);
void __init kmap_init(void)
{
- unsigned long kmap_vstart;
-
/* Check if this memory layout is broken because PKMAP overlaps
* page table.
*/
BUILD_BUG_ON(PKMAP_BASE < TLBTEMP_BASE_1 + TLBTEMP_SIZE);
- /* cache the first kmap pte */
- kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
- kmap_pte = virt_to_kpte(kmap_vstart);
kmap_waitqueues_init();
}
^ permalink raw reply
* [patch V3 13/37] mips/mm/highmem: Switch to generic kmap atomic
From: Thomas Gleixner @ 2020-11-03 9:27 UTC (permalink / raw)
To: LKML
Cc: Juri Lelli, linux-aio, Peter Zijlstra, Sebastian Andrzej Siewior,
Joonas Lahtinen, dri-devel, virtualization, Ben Segall,
Chris Mason, Huang Rui, Paul Mackerras, Gerd Hoffmann,
Daniel Bristot de Oliveira, sparclinux, Vincent Chen,
Christoph Hellwig, Vincent Guittot, Paul McKenney, Max Filippov,
x86, Russell King, linux-csky, Ingo Molnar, David Airlie,
VMware Graphics, Mel Gorman, nouveau, Dave Airlie, linux-snps-arc,
Ben Skeggs, linux-xtensa, Arnd Bergmann, intel-gfx,
Roland Scheidegger, Josef Bacik, Steven Rostedt, Linus Torvalds,
Alexander Viro, spice-devel, David Sterba, Rodrigo Vivi,
Dietmar Eggemann, linux-arm-kernel, Jani Nikula, Chris Zankel,
Michal Simek, Thomas Bogendoerfer, Nick Hu, linux-mm,
Vineet Gupta, linux-mips, Christian Koenig, Benjamin LaHaise,
Daniel Vetter, linux-fsdevel, Andrew Morton, linuxppc-dev,
David S. Miller, linux-btrfs, Greentime Hu
In-Reply-To: <20201103092712.714480842@linutronix.de>
No reason having the same code in every architecture
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: linux-mips@vger.kernel.org
---
V3: Remove the kmap types cruft
---
arch/mips/Kconfig | 1
arch/mips/include/asm/fixmap.h | 4 -
arch/mips/include/asm/highmem.h | 6 +-
arch/mips/include/asm/kmap_types.h | 13 ------
arch/mips/mm/highmem.c | 77 -------------------------------------
arch/mips/mm/init.c | 4 -
6 files changed, 6 insertions(+), 99 deletions(-)
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -2719,6 +2719,7 @@ config WAR_MIPS34K_MISSED_ITLB
config HIGHMEM
bool "High Memory Support"
depends on 32BIT && CPU_SUPPORTS_HIGHMEM && SYS_SUPPORTS_HIGHMEM && !CPU_MIPS32_3_5_EVA
+ select KMAP_LOCAL
config CPU_SUPPORTS_HIGHMEM
bool
--- a/arch/mips/include/asm/fixmap.h
+++ b/arch/mips/include/asm/fixmap.h
@@ -17,7 +17,7 @@
#include <spaces.h>
#ifdef CONFIG_HIGHMEM
#include <linux/threads.h>
-#include <asm/kmap_types.h>
+#include <asm/kmap_size.h>
#endif
/*
@@ -52,7 +52,7 @@ enum fixed_addresses {
#ifdef CONFIG_HIGHMEM
/* reserved pte's for temporary kernel mappings */
FIX_KMAP_BEGIN = FIX_CMAP_END + 1,
- FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
+ FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_MAX_IDX * NR_CPUS) - 1,
#endif
__end_of_fixed_addresses
};
--- a/arch/mips/include/asm/highmem.h
+++ b/arch/mips/include/asm/highmem.h
@@ -24,7 +24,7 @@
#include <linux/interrupt.h>
#include <linux/uaccess.h>
#include <asm/cpu-features.h>
-#include <asm/kmap_types.h>
+#include <asm/kmap_size.h>
/* declarations for highmem.c */
extern unsigned long highstart_pfn, highend_pfn;
@@ -48,11 +48,11 @@ extern pte_t *pkmap_page_table;
#define ARCH_HAS_KMAP_FLUSH_TLB
extern void kmap_flush_tlb(unsigned long addr);
-extern void *kmap_atomic_pfn(unsigned long pfn);
#define flush_cache_kmaps() BUG_ON(cpu_has_dc_aliases)
-extern void kmap_init(void);
+#define arch_kmap_local_post_map(vaddr, pteval) local_flush_tlb_one(vaddr)
+#define arch_kmap_local_post_unmap(vaddr) local_flush_tlb_one(vaddr)
#endif /* __KERNEL__ */
--- a/arch/mips/include/asm/kmap_types.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_KMAP_TYPES_H
-#define _ASM_KMAP_TYPES_H
-
-#ifdef CONFIG_DEBUG_HIGHMEM
-#define __WITH_KM_FENCE
-#endif
-
-#include <asm-generic/kmap_types.h>
-
-#undef __WITH_KM_FENCE
-
-#endif
--- a/arch/mips/mm/highmem.c
+++ b/arch/mips/mm/highmem.c
@@ -8,8 +8,6 @@
#include <asm/fixmap.h>
#include <asm/tlbflush.h>
-static pte_t *kmap_pte;
-
unsigned long highstart_pfn, highend_pfn;
void kmap_flush_tlb(unsigned long addr)
@@ -17,78 +15,3 @@ void kmap_flush_tlb(unsigned long addr)
flush_tlb_one(addr);
}
EXPORT_SYMBOL(kmap_flush_tlb);
-
-void *kmap_atomic_high_prot(struct page *page, pgprot_t prot)
-{
- unsigned long vaddr;
- int idx, type;
-
- type = kmap_atomic_idx_push();
- idx = type + KM_TYPE_NR*smp_processor_id();
- vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
-#ifdef CONFIG_DEBUG_HIGHMEM
- BUG_ON(!pte_none(*(kmap_pte - idx)));
-#endif
- set_pte(kmap_pte-idx, mk_pte(page, prot));
- local_flush_tlb_one((unsigned long)vaddr);
-
- return (void*) vaddr;
-}
-EXPORT_SYMBOL(kmap_atomic_high_prot);
-
-void kunmap_atomic_high(void *kvaddr)
-{
- unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
- int type __maybe_unused;
-
- if (vaddr < FIXADDR_START)
- return;
-
- type = kmap_atomic_idx();
-#ifdef CONFIG_DEBUG_HIGHMEM
- {
- int idx = type + KM_TYPE_NR * smp_processor_id();
-
- BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
-
- /*
- * force other mappings to Oops if they'll try to access
- * this pte without first remap it
- */
- pte_clear(&init_mm, vaddr, kmap_pte-idx);
- local_flush_tlb_one(vaddr);
- }
-#endif
- kmap_atomic_idx_pop();
-}
-EXPORT_SYMBOL(kunmap_atomic_high);
-
-/*
- * This is the same as kmap_atomic() but can map memory that doesn't
- * have a struct page associated with it.
- */
-void *kmap_atomic_pfn(unsigned long pfn)
-{
- unsigned long vaddr;
- int idx, type;
-
- preempt_disable();
- pagefault_disable();
-
- type = kmap_atomic_idx_push();
- idx = type + KM_TYPE_NR*smp_processor_id();
- vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
- set_pte(kmap_pte-idx, pfn_pte(pfn, PAGE_KERNEL));
- flush_tlb_one(vaddr);
-
- return (void*) vaddr;
-}
-
-void __init kmap_init(void)
-{
- unsigned long kmap_vstart;
-
- /* cache the first kmap pte */
- kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
- kmap_pte = virt_to_kpte(kmap_vstart);
-}
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -36,7 +36,6 @@
#include <asm/cachectl.h>
#include <asm/cpu.h>
#include <asm/dma.h>
-#include <asm/kmap_types.h>
#include <asm/maar.h>
#include <asm/mmu_context.h>
#include <asm/sections.h>
@@ -402,9 +401,6 @@ void __init paging_init(void)
pagetable_init();
-#ifdef CONFIG_HIGHMEM
- kmap_init();
-#endif
#ifdef CONFIG_ZONE_DMA
max_zone_pfns[ZONE_DMA] = MAX_DMA_PFN;
#endif
^ permalink raw reply
* [patch V3 11/37] csky/mm/highmem: Switch to generic kmap atomic
From: Thomas Gleixner @ 2020-11-03 9:27 UTC (permalink / raw)
To: LKML
Cc: Juri Lelli, linux-aio, Peter Zijlstra, Sebastian Andrzej Siewior,
Joonas Lahtinen, dri-devel, virtualization, Ben Segall,
Chris Mason, Huang Rui, Paul Mackerras, Gerd Hoffmann,
Daniel Bristot de Oliveira, sparclinux, Vincent Chen,
Christoph Hellwig, Vincent Guittot, Paul McKenney, Max Filippov,
x86, Russell King, linux-csky, Ingo Molnar, David Airlie,
VMware Graphics, Mel Gorman, nouveau, Dave Airlie, linux-snps-arc,
Ben Skeggs, linux-xtensa, Arnd Bergmann, intel-gfx,
Roland Scheidegger, Josef Bacik, Steven Rostedt, Linus Torvalds,
Alexander Viro, spice-devel, David Sterba, Rodrigo Vivi,
Dietmar Eggemann, linux-arm-kernel, Jani Nikula, Chris Zankel,
Michal Simek, Thomas Bogendoerfer, Nick Hu, linux-mm,
Vineet Gupta, linux-mips, Christian Koenig, Benjamin LaHaise,
Daniel Vetter, linux-fsdevel, Andrew Morton, linuxppc-dev,
David S. Miller, linux-btrfs, Greentime Hu
In-Reply-To: <20201103092712.714480842@linutronix.de>
No reason having the same code in every architecture.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-csky@vger.kernel.org
---
V3: Does not compile with gcc 10
---
arch/csky/Kconfig | 1
arch/csky/include/asm/fixmap.h | 4 +-
arch/csky/include/asm/highmem.h | 6 ++-
arch/csky/mm/highmem.c | 75 ----------------------------------------
4 files changed, 8 insertions(+), 78 deletions(-)
--- a/arch/csky/Kconfig
+++ b/arch/csky/Kconfig
@@ -286,6 +286,7 @@ config NR_CPUS
config HIGHMEM
bool "High Memory Support"
depends on !CPU_CK610
+ select KMAP_LOCAL
default y
config FORCE_MAX_ZONEORDER
--- a/arch/csky/include/asm/fixmap.h
+++ b/arch/csky/include/asm/fixmap.h
@@ -8,7 +8,7 @@
#include <asm/memory.h>
#ifdef CONFIG_HIGHMEM
#include <linux/threads.h>
-#include <asm/kmap_types.h>
+#include <asm/kmap_size.h>
#endif
enum fixed_addresses {
@@ -17,7 +17,7 @@ enum fixed_addresses {
#endif
#ifdef CONFIG_HIGHMEM
FIX_KMAP_BEGIN,
- FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_TYPE_NR * NR_CPUS) - 1,
+ FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_MAX_IDX * NR_CPUS) - 1,
#endif
__end_of_fixed_addresses
};
--- a/arch/csky/include/asm/highmem.h
+++ b/arch/csky/include/asm/highmem.h
@@ -9,7 +9,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/uaccess.h>
-#include <asm/kmap_types.h>
+#include <asm/kmap_size.h>
#include <asm/cache.h>
/* undef for production */
@@ -32,10 +32,12 @@ extern pte_t *pkmap_page_table;
#define ARCH_HAS_KMAP_FLUSH_TLB
extern void kmap_flush_tlb(unsigned long addr);
-extern void *kmap_atomic_pfn(unsigned long pfn);
#define flush_cache_kmaps() do {} while (0)
+#define arch_kmap_local_post_map(vaddr, pteval) kmap_flush_tlb(vaddr)
+#define arch_kmap_local_post_unmap(vaddr) kmap_flush_tlb(vaddr)
+
extern void kmap_init(void);
#endif /* __KERNEL__ */
--- a/arch/csky/mm/highmem.c
+++ b/arch/csky/mm/highmem.c
@@ -9,8 +9,6 @@
#include <asm/tlbflush.h>
#include <asm/cacheflush.h>
-static pte_t *kmap_pte;
-
unsigned long highstart_pfn, highend_pfn;
void kmap_flush_tlb(unsigned long addr)
@@ -19,67 +17,7 @@ void kmap_flush_tlb(unsigned long addr)
}
EXPORT_SYMBOL(kmap_flush_tlb);
-void *kmap_atomic_high_prot(struct page *page, pgprot_t prot)
-{
- unsigned long vaddr;
- int idx, type;
-
- type = kmap_atomic_idx_push();
- idx = type + KM_TYPE_NR*smp_processor_id();
- vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
-#ifdef CONFIG_DEBUG_HIGHMEM
- BUG_ON(!pte_none(*(kmap_pte - idx)));
-#endif
- set_pte(kmap_pte-idx, mk_pte(page, prot));
- flush_tlb_one((unsigned long)vaddr);
-
- return (void *)vaddr;
-}
-EXPORT_SYMBOL(kmap_atomic_high_prot);
-
-void kunmap_atomic_high(void *kvaddr)
-{
- unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
- int idx;
-
- if (vaddr < FIXADDR_START)
- return;
-
-#ifdef CONFIG_DEBUG_HIGHMEM
- idx = KM_TYPE_NR*smp_processor_id() + kmap_atomic_idx();
-
- BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
-
- pte_clear(&init_mm, vaddr, kmap_pte - idx);
- flush_tlb_one(vaddr);
-#else
- (void) idx; /* to kill a warning */
-#endif
- kmap_atomic_idx_pop();
-}
-EXPORT_SYMBOL(kunmap_atomic_high);
-
-/*
- * This is the same as kmap_atomic() but can map memory that doesn't
- * have a struct page associated with it.
- */
-void *kmap_atomic_pfn(unsigned long pfn)
-{
- unsigned long vaddr;
- int idx, type;
-
- pagefault_disable();
-
- type = kmap_atomic_idx_push();
- idx = type + KM_TYPE_NR*smp_processor_id();
- vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
- set_pte(kmap_pte-idx, pfn_pte(pfn, PAGE_KERNEL));
- flush_tlb_one(vaddr);
-
- return (void *) vaddr;
-}
-
-static void __init kmap_pages_init(void)
+void __init kmap_init(void)
{
unsigned long vaddr;
pgd_t *pgd;
@@ -96,14 +34,3 @@ static void __init kmap_pages_init(void)
pte = pte_offset_kernel(pmd, vaddr);
pkmap_page_table = pte;
}
-
-void __init kmap_init(void)
-{
- unsigned long vaddr;
-
- kmap_pages_init();
-
- vaddr = __fix_to_virt(FIX_KMAP_BEGIN);
-
- kmap_pte = pte_offset_kernel((pmd_t *)pgd_offset_k(vaddr), vaddr);
-}
^ permalink raw reply
* [patch V3 10/37] ARM: highmem: Switch to generic kmap atomic
From: Thomas Gleixner @ 2020-11-03 9:27 UTC (permalink / raw)
To: LKML
Cc: Juri Lelli, linux-aio, Peter Zijlstra, Sebastian Andrzej Siewior,
Joonas Lahtinen, dri-devel, virtualization, Ben Segall,
Chris Mason, Huang Rui, Paul Mackerras, Gerd Hoffmann,
Daniel Bristot de Oliveira, sparclinux, Vincent Chen,
Christoph Hellwig, Vincent Guittot, Paul McKenney, Max Filippov,
x86, Russell King, linux-csky, Ingo Molnar, David Airlie,
VMware Graphics, Mel Gorman, nouveau, Dave Airlie, linux-snps-arc,
Ben Skeggs, linux-xtensa, Arnd Bergmann, intel-gfx,
Roland Scheidegger, Josef Bacik, Steven Rostedt, Linus Torvalds,
Alexander Viro, spice-devel, David Sterba, Rodrigo Vivi,
Dietmar Eggemann, linux-arm-kernel, Jani Nikula, Chris Zankel,
Michal Simek, Thomas Bogendoerfer, Nick Hu, linux-mm,
Vineet Gupta, linux-mips, Christian Koenig, Benjamin LaHaise,
Daniel Vetter, linux-fsdevel, Andrew Morton, linuxppc-dev,
David S. Miller, linux-btrfs, Greentime Hu
In-Reply-To: <20201103092712.714480842@linutronix.de>
No reason having the same code in every architecture.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Russell King <linux@armlinux.org.uk>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: linux-arm-kernel@lists.infradead.org
---
V3: Remove the kmap types cruft
---
arch/arm/Kconfig | 1
arch/arm/include/asm/fixmap.h | 4 -
arch/arm/include/asm/highmem.h | 33 +++++++---
arch/arm/include/asm/kmap_types.h | 10 ---
arch/arm/mm/Makefile | 1
arch/arm/mm/highmem.c | 121 --------------------------------------
6 files changed, 26 insertions(+), 144 deletions(-)
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1498,6 +1498,7 @@ config HAVE_ARCH_PFN_VALID
config HIGHMEM
bool "High Memory Support"
depends on MMU
+ select KMAP_LOCAL
help
The address space of ARM processors is only 4 Gigabytes large
and it has to accommodate user address space, kernel address
--- a/arch/arm/include/asm/fixmap.h
+++ b/arch/arm/include/asm/fixmap.h
@@ -7,14 +7,14 @@
#define FIXADDR_TOP (FIXADDR_END - PAGE_SIZE)
#include <linux/pgtable.h>
-#include <asm/kmap_types.h>
+#include <asm/kmap_size.h>
enum fixed_addresses {
FIX_EARLYCON_MEM_BASE,
__end_of_permanent_fixed_addresses,
FIX_KMAP_BEGIN = __end_of_permanent_fixed_addresses,
- FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_TYPE_NR * NR_CPUS) - 1,
+ FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_MAX_IDX * NR_CPUS) - 1,
/* Support writing RO kernel text via kprobes, jump labels, etc. */
FIX_TEXT_POKE0,
--- a/arch/arm/include/asm/highmem.h
+++ b/arch/arm/include/asm/highmem.h
@@ -2,7 +2,7 @@
#ifndef _ASM_HIGHMEM_H
#define _ASM_HIGHMEM_H
-#include <asm/kmap_types.h>
+#include <asm/kmap_size.h>
#define PKMAP_BASE (PAGE_OFFSET - PMD_SIZE)
#define LAST_PKMAP PTRS_PER_PTE
@@ -46,19 +46,32 @@ extern pte_t *pkmap_page_table;
#ifdef ARCH_NEEDS_KMAP_HIGH_GET
extern void *kmap_high_get(struct page *page);
-#else
+
+static inline void *arch_kmap_local_high_get(struct page *page)
+{
+ if (IS_ENABLED(CONFIG_DEBUG_HIGHMEM) && !cache_is_vivt())
+ return NULL;
+ return kmap_high_get(page);
+}
+#define arch_kmap_local_high_get arch_kmap_local_high_get
+
+#else /* ARCH_NEEDS_KMAP_HIGH_GET */
static inline void *kmap_high_get(struct page *page)
{
return NULL;
}
-#endif
+#endif /* !ARCH_NEEDS_KMAP_HIGH_GET */
-/*
- * The following functions are already defined by <linux/highmem.h>
- * when CONFIG_HIGHMEM is not set.
- */
-#ifdef CONFIG_HIGHMEM
-extern void *kmap_atomic_pfn(unsigned long pfn);
-#endif
+#define arch_kmap_local_post_map(vaddr, pteval) \
+ local_flush_tlb_kernel_page(vaddr)
+
+#define arch_kmap_local_pre_unmap(vaddr) \
+do { \
+ if (cache_is_vivt()) \
+ __cpuc_flush_dcache_area((void *)vaddr, PAGE_SIZE); \
+} while (0)
+
+#define arch_kmap_local_post_unmap(vaddr) \
+ local_flush_tlb_kernel_page(vaddr)
#endif
--- a/arch/arm/include/asm/kmap_types.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __ARM_KMAP_TYPES_H
-#define __ARM_KMAP_TYPES_H
-
-/*
- * This is the "bare minimum". AIO seems to require this.
- */
-#define KM_TYPE_NR 16
-
-#endif
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -19,7 +19,6 @@ obj-$(CONFIG_MODULES) += proc-syms.o
obj-$(CONFIG_DEBUG_VIRTUAL) += physaddr.o
obj-$(CONFIG_ALIGNMENT_TRAP) += alignment.o
-obj-$(CONFIG_HIGHMEM) += highmem.o
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
obj-$(CONFIG_ARM_PV_FIXUP) += pv-fixup-asm.o
--- a/arch/arm/mm/highmem.c
+++ /dev/null
@@ -1,121 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mm/highmem.c -- ARM highmem support
- *
- * Author: Nicolas Pitre
- * Created: september 8, 2008
- * Copyright: Marvell Semiconductors Inc.
- */
-
-#include <linux/module.h>
-#include <linux/highmem.h>
-#include <linux/interrupt.h>
-#include <asm/fixmap.h>
-#include <asm/cacheflush.h>
-#include <asm/tlbflush.h>
-#include "mm.h"
-
-static inline void set_fixmap_pte(int idx, pte_t pte)
-{
- unsigned long vaddr = __fix_to_virt(idx);
- pte_t *ptep = virt_to_kpte(vaddr);
-
- set_pte_ext(ptep, pte, 0);
- local_flush_tlb_kernel_page(vaddr);
-}
-
-static inline pte_t get_fixmap_pte(unsigned long vaddr)
-{
- pte_t *ptep = virt_to_kpte(vaddr);
-
- return *ptep;
-}
-
-void *kmap_atomic_high_prot(struct page *page, pgprot_t prot)
-{
- unsigned int idx;
- unsigned long vaddr;
- void *kmap;
- int type;
-
-#ifdef CONFIG_DEBUG_HIGHMEM
- /*
- * There is no cache coherency issue when non VIVT, so force the
- * dedicated kmap usage for better debugging purposes in that case.
- */
- if (!cache_is_vivt())
- kmap = NULL;
- else
-#endif
- kmap = kmap_high_get(page);
- if (kmap)
- return kmap;
-
- type = kmap_atomic_idx_push();
-
- idx = FIX_KMAP_BEGIN + type + KM_TYPE_NR * smp_processor_id();
- vaddr = __fix_to_virt(idx);
-#ifdef CONFIG_DEBUG_HIGHMEM
- /*
- * With debugging enabled, kunmap_atomic forces that entry to 0.
- * Make sure it was indeed properly unmapped.
- */
- BUG_ON(!pte_none(get_fixmap_pte(vaddr)));
-#endif
- /*
- * When debugging is off, kunmap_atomic leaves the previous mapping
- * in place, so the contained TLB flush ensures the TLB is updated
- * with the new mapping.
- */
- set_fixmap_pte(idx, mk_pte(page, prot));
-
- return (void *)vaddr;
-}
-EXPORT_SYMBOL(kmap_atomic_high_prot);
-
-void kunmap_atomic_high(void *kvaddr)
-{
- unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
- int idx, type;
-
- if (kvaddr >= (void *)FIXADDR_START) {
- type = kmap_atomic_idx();
- idx = FIX_KMAP_BEGIN + type + KM_TYPE_NR * smp_processor_id();
-
- if (cache_is_vivt())
- __cpuc_flush_dcache_area((void *)vaddr, PAGE_SIZE);
-#ifdef CONFIG_DEBUG_HIGHMEM
- BUG_ON(vaddr != __fix_to_virt(idx));
- set_fixmap_pte(idx, __pte(0));
-#else
- (void) idx; /* to kill a warning */
-#endif
- kmap_atomic_idx_pop();
- } else if (vaddr >= PKMAP_ADDR(0) && vaddr < PKMAP_ADDR(LAST_PKMAP)) {
- /* this address was obtained through kmap_high_get() */
- kunmap_high(pte_page(pkmap_page_table[PKMAP_NR(vaddr)]));
- }
-}
-EXPORT_SYMBOL(kunmap_atomic_high);
-
-void *kmap_atomic_pfn(unsigned long pfn)
-{
- unsigned long vaddr;
- int idx, type;
- struct page *page = pfn_to_page(pfn);
-
- preempt_disable();
- pagefault_disable();
- if (!PageHighMem(page))
- return page_address(page);
-
- type = kmap_atomic_idx_push();
- idx = FIX_KMAP_BEGIN + type + KM_TYPE_NR * smp_processor_id();
- vaddr = __fix_to_virt(idx);
-#ifdef CONFIG_DEBUG_HIGHMEM
- BUG_ON(!pte_none(get_fixmap_pte(vaddr)));
-#endif
- set_fixmap_pte(idx, pfn_pte(pfn, kmap_prot));
-
- return (void *)vaddr;
-}
^ permalink raw reply
* [patch V3 12/37] microblaze/mm/highmem: Switch to generic kmap atomic
From: Thomas Gleixner @ 2020-11-03 9:27 UTC (permalink / raw)
To: LKML
Cc: Juri Lelli, linux-aio, Peter Zijlstra, Sebastian Andrzej Siewior,
Joonas Lahtinen, dri-devel, virtualization, Ben Segall,
Chris Mason, Huang Rui, Paul Mackerras, Gerd Hoffmann,
Daniel Bristot de Oliveira, sparclinux, Vincent Chen,
Christoph Hellwig, Vincent Guittot, Paul McKenney, Max Filippov,
x86, Russell King, linux-csky, Ingo Molnar, David Airlie,
VMware Graphics, Mel Gorman, nouveau, Dave Airlie, linux-snps-arc,
Ben Skeggs, linux-xtensa, Arnd Bergmann, intel-gfx,
Roland Scheidegger, Josef Bacik, Steven Rostedt, Linus Torvalds,
Alexander Viro, spice-devel, David Sterba, Rodrigo Vivi,
Dietmar Eggemann, linux-arm-kernel, Jani Nikula, Chris Zankel,
Michal Simek, Thomas Bogendoerfer, Nick Hu, linux-mm,
Vineet Gupta, linux-mips, Christian Koenig, Benjamin LaHaise,
Daniel Vetter, linux-fsdevel, Andrew Morton, linuxppc-dev,
David S. Miller, linux-btrfs, Greentime Hu
In-Reply-To: <20201103092712.714480842@linutronix.de>
No reason having the same code in every architecture.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Michal Simek <monstr@monstr.eu>
---
V3: Remove the kmap types cruft
---
arch/microblaze/Kconfig | 1
arch/microblaze/include/asm/fixmap.h | 4 -
arch/microblaze/include/asm/highmem.h | 6 ++
arch/microblaze/mm/Makefile | 1
arch/microblaze/mm/highmem.c | 78 ----------------------------------
arch/microblaze/mm/init.c | 6 --
6 files changed, 8 insertions(+), 88 deletions(-)
--- a/arch/microblaze/Kconfig
+++ b/arch/microblaze/Kconfig
@@ -155,6 +155,7 @@ config XILINX_UNCACHED_SHADOW
config HIGHMEM
bool "High memory support"
depends on MMU
+ select KMAP_LOCAL
help
The address space of Microblaze processors is only 4 Gigabytes large
and it has to accommodate user address space, kernel address
--- a/arch/microblaze/include/asm/fixmap.h
+++ b/arch/microblaze/include/asm/fixmap.h
@@ -20,7 +20,7 @@
#include <asm/page.h>
#ifdef CONFIG_HIGHMEM
#include <linux/threads.h>
-#include <asm/kmap_types.h>
+#include <asm/kmap_size.h>
#endif
#define FIXADDR_TOP ((unsigned long)(-PAGE_SIZE))
@@ -47,7 +47,7 @@ enum fixed_addresses {
FIX_HOLE,
#ifdef CONFIG_HIGHMEM
FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */
- FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_TYPE_NR * num_possible_cpus()) - 1,
+ FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_MAX_IDX * num_possible_cpus()) - 1,
#endif
__end_of_fixed_addresses
};
--- a/arch/microblaze/include/asm/highmem.h
+++ b/arch/microblaze/include/asm/highmem.h
@@ -25,7 +25,6 @@
#include <linux/uaccess.h>
#include <asm/fixmap.h>
-extern pte_t *kmap_pte;
extern pte_t *pkmap_page_table;
/*
@@ -52,6 +51,11 @@ extern pte_t *pkmap_page_table;
#define flush_cache_kmaps() { flush_icache(); flush_dcache(); }
+#define arch_kmap_local_post_map(vaddr, pteval) \
+ local_flush_tlb_page(NULL, vaddr);
+#define arch_kmap_local_post_unmap(vaddr) \
+ local_flush_tlb_page(NULL, vaddr);
+
#endif /* __KERNEL__ */
#endif /* _ASM_HIGHMEM_H */
--- a/arch/microblaze/mm/Makefile
+++ b/arch/microblaze/mm/Makefile
@@ -6,4 +6,3 @@
obj-y := consistent.o init.o
obj-$(CONFIG_MMU) += pgtable.o mmu_context.o fault.o
-obj-$(CONFIG_HIGHMEM) += highmem.o
--- a/arch/microblaze/mm/highmem.c
+++ /dev/null
@@ -1,78 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * highmem.c: virtual kernel memory mappings for high memory
- *
- * PowerPC version, stolen from the i386 version.
- *
- * Used in CONFIG_HIGHMEM systems for memory pages which
- * are not addressable by direct kernel virtual addresses.
- *
- * Copyright (C) 1999 Gerhard Wichert, Siemens AG
- * Gerhard.Wichert@pdb.siemens.de
- *
- *
- * Redesigned the x86 32-bit VM architecture to deal with
- * up to 16 Terrabyte physical memory. With current x86 CPUs
- * we now support up to 64 Gigabytes physical RAM.
- *
- * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
- *
- * Reworked for PowerPC by various contributors. Moved from
- * highmem.h by Benjamin Herrenschmidt (c) 2009 IBM Corp.
- */
-
-#include <linux/export.h>
-#include <linux/highmem.h>
-
-/*
- * The use of kmap_atomic/kunmap_atomic is discouraged - kmap/kunmap
- * gives a more generic (and caching) interface. But kmap_atomic can
- * be used in IRQ contexts, so in some (very limited) cases we need
- * it.
- */
-#include <asm/tlbflush.h>
-
-void *kmap_atomic_high_prot(struct page *page, pgprot_t prot)
-{
-
- unsigned long vaddr;
- int idx, type;
-
- type = kmap_atomic_idx_push();
- idx = type + KM_TYPE_NR*smp_processor_id();
- vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
-#ifdef CONFIG_DEBUG_HIGHMEM
- BUG_ON(!pte_none(*(kmap_pte-idx)));
-#endif
- set_pte_at(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot));
- local_flush_tlb_page(NULL, vaddr);
-
- return (void *) vaddr;
-}
-EXPORT_SYMBOL(kmap_atomic_high_prot);
-
-void kunmap_atomic_high(void *kvaddr)
-{
- unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
- int type;
- unsigned int idx;
-
- if (vaddr < __fix_to_virt(FIX_KMAP_END))
- return;
-
- type = kmap_atomic_idx();
-
- idx = type + KM_TYPE_NR * smp_processor_id();
-#ifdef CONFIG_DEBUG_HIGHMEM
- BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
-#endif
- /*
- * force other mappings to Oops if they'll try to access
- * this pte without first remap it
- */
- pte_clear(&init_mm, vaddr, kmap_pte-idx);
- local_flush_tlb_page(NULL, vaddr);
-
- kmap_atomic_idx_pop();
-}
-EXPORT_SYMBOL(kunmap_atomic_high);
--- a/arch/microblaze/mm/init.c
+++ b/arch/microblaze/mm/init.c
@@ -49,17 +49,11 @@ unsigned long lowmem_size;
EXPORT_SYMBOL(min_low_pfn);
EXPORT_SYMBOL(max_low_pfn);
-#ifdef CONFIG_HIGHMEM
-pte_t *kmap_pte;
-EXPORT_SYMBOL(kmap_pte);
-
static void __init highmem_init(void)
{
pr_debug("%x\n", (u32)PKMAP_BASE);
map_page(PKMAP_BASE, 0, 0); /* XXX gross */
pkmap_page_table = virt_to_kpte(PKMAP_BASE);
-
- kmap_pte = virt_to_kpte(__fix_to_virt(FIX_KMAP_BEGIN));
}
static void highmem_setup(void)
^ permalink raw reply
* [patch V3 15/37] powerpc/mm/highmem: Switch to generic kmap atomic
From: Thomas Gleixner @ 2020-11-03 9:27 UTC (permalink / raw)
To: LKML
Cc: Juri Lelli, linux-aio, Peter Zijlstra, Sebastian Andrzej Siewior,
Joonas Lahtinen, dri-devel, virtualization, Ben Segall,
Chris Mason, Huang Rui, Paul Mackerras, Gerd Hoffmann,
Daniel Bristot de Oliveira, sparclinux, Vincent Chen,
Christoph Hellwig, Vincent Guittot, Arnd Bergmann, Max Filippov,
x86, Russell King, linux-csky, Ingo Molnar, David Airlie,
VMware Graphics, Mel Gorman, nouveau, Dave Airlie, linux-snps-arc,
Ben Skeggs, linux-xtensa, Paul McKenney, intel-gfx,
Roland Scheidegger, Josef Bacik, Steven Rostedt, Linus Torvalds,
Alexander Viro, spice-devel, David Sterba, Rodrigo Vivi,
Dietmar Eggemann, linux-arm-kernel, Jani Nikula, Chris Zankel,
Michal Simek, Thomas Bogendoerfer, Nick Hu, linux-mm,
Vineet Gupta, linux-mips, Christian Koenig, Benjamin LaHaise,
Daniel Vetter, linux-fsdevel, Andrew Morton, linuxppc-dev,
David S. Miller, linux-btrfs, Greentime Hu
In-Reply-To: <20201103092712.714480842@linutronix.de>
No reason having the same code in every architecture
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: linuxppc-dev@lists.ozlabs.org
---
V3: Remove the kmap types cruft
---
arch/powerpc/Kconfig | 1
arch/powerpc/include/asm/fixmap.h | 4 +-
arch/powerpc/include/asm/highmem.h | 7 ++-
arch/powerpc/include/asm/kmap_types.h | 13 ------
arch/powerpc/mm/Makefile | 1
arch/powerpc/mm/highmem.c | 67 ----------------------------------
arch/powerpc/mm/mem.c | 7 ---
7 files changed, 8 insertions(+), 92 deletions(-)
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -409,6 +409,7 @@ menu "Kernel options"
config HIGHMEM
bool "High memory support"
depends on PPC32
+ select KMAP_LOCAL
source "kernel/Kconfig.hz"
--- a/arch/powerpc/include/asm/fixmap.h
+++ b/arch/powerpc/include/asm/fixmap.h
@@ -20,7 +20,7 @@
#include <asm/page.h>
#ifdef CONFIG_HIGHMEM
#include <linux/threads.h>
-#include <asm/kmap_types.h>
+#include <asm/kmap_size.h>
#endif
#ifdef CONFIG_KASAN
@@ -55,7 +55,7 @@ enum fixed_addresses {
FIX_EARLY_DEBUG_BASE = FIX_EARLY_DEBUG_TOP+(ALIGN(SZ_128K, PAGE_SIZE)/PAGE_SIZE)-1,
#ifdef CONFIG_HIGHMEM
FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */
- FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
+ FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_MAX_IDX * NR_CPUS) - 1,
#endif
#ifdef CONFIG_PPC_8xx
/* For IMMR we need an aligned 512K area */
--- a/arch/powerpc/include/asm/highmem.h
+++ b/arch/powerpc/include/asm/highmem.h
@@ -24,12 +24,10 @@
#ifdef __KERNEL__
#include <linux/interrupt.h>
-#include <asm/kmap_types.h>
#include <asm/cacheflush.h>
#include <asm/page.h>
#include <asm/fixmap.h>
-extern pte_t *kmap_pte;
extern pte_t *pkmap_page_table;
/*
@@ -60,6 +58,11 @@ extern pte_t *pkmap_page_table;
#define flush_cache_kmaps() flush_cache_all()
+#define arch_kmap_local_post_map(vaddr, pteval) \
+ local_flush_tlb_page(NULL, vaddr)
+#define arch_kmap_local_post_unmap(vaddr) \
+ local_flush_tlb_page(NULL, vaddr)
+
#endif /* __KERNEL__ */
#endif /* _ASM_HIGHMEM_H */
--- a/arch/powerpc/include/asm/kmap_types.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-#ifndef _ASM_POWERPC_KMAP_TYPES_H
-#define _ASM_POWERPC_KMAP_TYPES_H
-
-#ifdef __KERNEL__
-
-/*
- */
-
-#define KM_TYPE_NR 16
-
-#endif /* __KERNEL__ */
-#endif /* _ASM_POWERPC_KMAP_TYPES_H */
--- a/arch/powerpc/mm/Makefile
+++ b/arch/powerpc/mm/Makefile
@@ -16,7 +16,6 @@ obj-$(CONFIG_NEED_MULTIPLE_NODES) += num
obj-$(CONFIG_PPC_MM_SLICES) += slice.o
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-noncoherent.o
-obj-$(CONFIG_HIGHMEM) += highmem.o
obj-$(CONFIG_PPC_COPRO_BASE) += copro_fault.o
obj-$(CONFIG_PPC_PTDUMP) += ptdump/
obj-$(CONFIG_KASAN) += kasan/
--- a/arch/powerpc/mm/highmem.c
+++ /dev/null
@@ -1,67 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * highmem.c: virtual kernel memory mappings for high memory
- *
- * PowerPC version, stolen from the i386 version.
- *
- * Used in CONFIG_HIGHMEM systems for memory pages which
- * are not addressable by direct kernel virtual addresses.
- *
- * Copyright (C) 1999 Gerhard Wichert, Siemens AG
- * Gerhard.Wichert@pdb.siemens.de
- *
- *
- * Redesigned the x86 32-bit VM architecture to deal with
- * up to 16 Terrabyte physical memory. With current x86 CPUs
- * we now support up to 64 Gigabytes physical RAM.
- *
- * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
- *
- * Reworked for PowerPC by various contributors. Moved from
- * highmem.h by Benjamin Herrenschmidt (c) 2009 IBM Corp.
- */
-
-#include <linux/highmem.h>
-#include <linux/module.h>
-
-void *kmap_atomic_high_prot(struct page *page, pgprot_t prot)
-{
- unsigned long vaddr;
- int idx, type;
-
- type = kmap_atomic_idx_push();
- idx = type + KM_TYPE_NR*smp_processor_id();
- vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
- WARN_ON(IS_ENABLED(CONFIG_DEBUG_HIGHMEM) && !pte_none(*(kmap_pte - idx)));
- __set_pte_at(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot), 1);
- local_flush_tlb_page(NULL, vaddr);
-
- return (void*) vaddr;
-}
-EXPORT_SYMBOL(kmap_atomic_high_prot);
-
-void kunmap_atomic_high(void *kvaddr)
-{
- unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
-
- if (vaddr < __fix_to_virt(FIX_KMAP_END))
- return;
-
- if (IS_ENABLED(CONFIG_DEBUG_HIGHMEM)) {
- int type = kmap_atomic_idx();
- unsigned int idx;
-
- idx = type + KM_TYPE_NR * smp_processor_id();
- WARN_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
-
- /*
- * force other mappings to Oops if they'll try to access
- * this pte without first remap it
- */
- pte_clear(&init_mm, vaddr, kmap_pte-idx);
- local_flush_tlb_page(NULL, vaddr);
- }
-
- kmap_atomic_idx_pop();
-}
-EXPORT_SYMBOL(kunmap_atomic_high);
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -61,11 +61,6 @@
unsigned long long memory_limit;
bool init_mem_is_free;
-#ifdef CONFIG_HIGHMEM
-pte_t *kmap_pte;
-EXPORT_SYMBOL(kmap_pte);
-#endif
-
pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
unsigned long size, pgprot_t vma_prot)
{
@@ -235,8 +230,6 @@ void __init paging_init(void)
map_kernel_page(PKMAP_BASE, 0, __pgprot(0)); /* XXX gross */
pkmap_page_table = virt_to_kpte(PKMAP_BASE);
-
- kmap_pte = virt_to_kpte(__fix_to_virt(FIX_KMAP_BEGIN));
#endif /* CONFIG_HIGHMEM */
printk(KERN_DEBUG "Top of RAM: 0x%llx, Total RAM: 0x%llx\n",
^ permalink raw reply
* [patch V3 16/37] sparc/mm/highmem: Switch to generic kmap atomic
From: Thomas Gleixner @ 2020-11-03 9:27 UTC (permalink / raw)
To: LKML
Cc: Juri Lelli, linux-aio, Peter Zijlstra, Sebastian Andrzej Siewior,
Joonas Lahtinen, dri-devel, virtualization, Ben Segall,
Chris Mason, Huang Rui, Paul Mackerras, Gerd Hoffmann,
Daniel Bristot de Oliveira, sparclinux, Vincent Chen,
Christoph Hellwig, Vincent Guittot, Paul McKenney, Max Filippov,
x86, Russell King, linux-csky, Ingo Molnar, David Airlie,
VMware Graphics, Mel Gorman, nouveau, Dave Airlie, linux-snps-arc,
Ben Skeggs, linux-xtensa, Arnd Bergmann, intel-gfx,
Roland Scheidegger, Josef Bacik, Steven Rostedt, Linus Torvalds,
Alexander Viro, spice-devel, David Sterba, Rodrigo Vivi,
Dietmar Eggemann, linux-arm-kernel, Jani Nikula, Chris Zankel,
Michal Simek, Thomas Bogendoerfer, Nick Hu, linux-mm,
Vineet Gupta, linux-mips, Christian Koenig, Benjamin LaHaise,
Daniel Vetter, linux-fsdevel, Andrew Morton, linuxppc-dev,
David S. Miller, linux-btrfs, Greentime Hu
In-Reply-To: <20201103092712.714480842@linutronix.de>
No reason having the same code in every architecture
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: sparclinux@vger.kernel.org
---
V3: Remove the kmap types cruft
---
arch/sparc/Kconfig | 1
arch/sparc/include/asm/highmem.h | 8 +-
arch/sparc/include/asm/kmap_types.h | 11 ---
arch/sparc/include/asm/vaddrs.h | 4 -
arch/sparc/mm/Makefile | 3
arch/sparc/mm/highmem.c | 115 ------------------------------------
arch/sparc/mm/srmmu.c | 2
7 files changed, 8 insertions(+), 136 deletions(-)
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -139,6 +139,7 @@ config MMU
config HIGHMEM
bool
default y if SPARC32
+ select KMAP_LOCAL
config ZONE_DMA
bool
--- a/arch/sparc/include/asm/highmem.h
+++ b/arch/sparc/include/asm/highmem.h
@@ -24,7 +24,6 @@
#include <linux/interrupt.h>
#include <linux/pgtable.h>
#include <asm/vaddrs.h>
-#include <asm/kmap_types.h>
#include <asm/pgtsrmmu.h>
/* declarations for highmem.c */
@@ -33,8 +32,6 @@ extern unsigned long highstart_pfn, high
#define kmap_prot __pgprot(SRMMU_ET_PTE | SRMMU_PRIV | SRMMU_CACHE)
extern pte_t *pkmap_page_table;
-void kmap_init(void) __init;
-
/*
* Right now we initialize only a single pte table. It can be extended
* easily, subsequent pte tables have to be allocated in one physical
@@ -53,6 +50,11 @@ void kmap_init(void) __init;
#define flush_cache_kmaps() flush_cache_all()
+/* FIXME: Use __flush_tlb_one(vaddr) instead of flush_cache_all() -- Anton */
+#define arch_kmap_local_post_map(vaddr, pteval) flush_cache_all()
+#define arch_kmap_local_post_unmap(vaddr) flush_cache_all()
+
+
#endif /* __KERNEL__ */
#endif /* _ASM_HIGHMEM_H */
--- a/arch/sparc/include/asm/kmap_types.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_KMAP_TYPES_H
-#define _ASM_KMAP_TYPES_H
-
-/* Dummy header just to define km_type. None of this
- * is actually used on sparc. -DaveM
- */
-
-#include <asm-generic/kmap_types.h>
-
-#endif
--- a/arch/sparc/include/asm/vaddrs.h
+++ b/arch/sparc/include/asm/vaddrs.h
@@ -32,13 +32,13 @@
#define SRMMU_NOCACHE_ALCRATIO 64 /* 256 pages per 64MB of system RAM */
#ifndef __ASSEMBLY__
-#include <asm/kmap_types.h>
+#include <asm/kmap_size.h>
enum fixed_addresses {
FIX_HOLE,
#ifdef CONFIG_HIGHMEM
FIX_KMAP_BEGIN,
- FIX_KMAP_END = (KM_TYPE_NR * NR_CPUS),
+ FIX_KMAP_END = (KM_MAX_IDX * NR_CPUS),
#endif
__end_of_fixed_addresses
};
--- a/arch/sparc/mm/Makefile
+++ b/arch/sparc/mm/Makefile
@@ -15,6 +15,3 @@ obj-$(CONFIG_SPARC32) += leon_mm.o
# Only used by sparc64
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
-
-# Only used by sparc32
-obj-$(CONFIG_HIGHMEM) += highmem.o
--- a/arch/sparc/mm/highmem.c
+++ /dev/null
@@ -1,115 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * highmem.c: virtual kernel memory mappings for high memory
- *
- * Provides kernel-static versions of atomic kmap functions originally
- * found as inlines in include/asm-sparc/highmem.h. These became
- * needed as kmap_atomic() and kunmap_atomic() started getting
- * called from within modules.
- * -- Tomas Szepe <szepe@pinerecords.com>, September 2002
- *
- * But kmap_atomic() and kunmap_atomic() cannot be inlined in
- * modules because they are loaded with btfixup-ped functions.
- */
-
-/*
- * The use of kmap_atomic/kunmap_atomic is discouraged - kmap/kunmap
- * gives a more generic (and caching) interface. But kmap_atomic can
- * be used in IRQ contexts, so in some (very limited) cases we need it.
- *
- * XXX This is an old text. Actually, it's good to use atomic kmaps,
- * provided you remember that they are atomic and not try to sleep
- * with a kmap taken, much like a spinlock. Non-atomic kmaps are
- * shared by CPUs, and so precious, and establishing them requires IPI.
- * Atomic kmaps are lightweight and we may have NCPUS more of them.
- */
-#include <linux/highmem.h>
-#include <linux/export.h>
-#include <linux/mm.h>
-
-#include <asm/cacheflush.h>
-#include <asm/tlbflush.h>
-#include <asm/vaddrs.h>
-
-static pte_t *kmap_pte;
-
-void __init kmap_init(void)
-{
- unsigned long address = __fix_to_virt(FIX_KMAP_BEGIN);
-
- /* cache the first kmap pte */
- kmap_pte = virt_to_kpte(address);
-}
-
-void *kmap_atomic_high_prot(struct page *page, pgprot_t prot)
-{
- unsigned long vaddr;
- long idx, type;
-
- type = kmap_atomic_idx_push();
- idx = type + KM_TYPE_NR*smp_processor_id();
- vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
-
-/* XXX Fix - Anton */
-#if 0
- __flush_cache_one(vaddr);
-#else
- flush_cache_all();
-#endif
-
-#ifdef CONFIG_DEBUG_HIGHMEM
- BUG_ON(!pte_none(*(kmap_pte-idx)));
-#endif
- set_pte(kmap_pte-idx, mk_pte(page, prot));
-/* XXX Fix - Anton */
-#if 0
- __flush_tlb_one(vaddr);
-#else
- flush_tlb_all();
-#endif
-
- return (void*) vaddr;
-}
-EXPORT_SYMBOL(kmap_atomic_high_prot);
-
-void kunmap_atomic_high(void *kvaddr)
-{
- unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
- int type;
-
- if (vaddr < FIXADDR_START)
- return;
-
- type = kmap_atomic_idx();
-
-#ifdef CONFIG_DEBUG_HIGHMEM
- {
- unsigned long idx;
-
- idx = type + KM_TYPE_NR * smp_processor_id();
- BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx));
-
- /* XXX Fix - Anton */
-#if 0
- __flush_cache_one(vaddr);
-#else
- flush_cache_all();
-#endif
-
- /*
- * force other mappings to Oops if they'll try to access
- * this pte without first remap it
- */
- pte_clear(&init_mm, vaddr, kmap_pte-idx);
- /* XXX Fix - Anton */
-#if 0
- __flush_tlb_one(vaddr);
-#else
- flush_tlb_all();
-#endif
- }
-#endif
-
- kmap_atomic_idx_pop();
-}
-EXPORT_SYMBOL(kunmap_atomic_high);
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -971,8 +971,6 @@ void __init srmmu_paging_init(void)
sparc_context_init(num_contexts);
- kmap_init();
-
{
unsigned long max_zone_pfn[MAX_NR_ZONES] = { 0 };
^ permalink raw reply
* [patch V3 14/37] nds32/mm/highmem: Switch to generic kmap atomic
From: Thomas Gleixner @ 2020-11-03 9:27 UTC (permalink / raw)
To: LKML
Cc: Juri Lelli, linux-aio, Peter Zijlstra, Sebastian Andrzej Siewior,
Joonas Lahtinen, dri-devel, virtualization, Ben Segall,
Chris Mason, Huang Rui, Paul Mackerras, Gerd Hoffmann,
Daniel Bristot de Oliveira, sparclinux, Vincent Chen,
Christoph Hellwig, Vincent Guittot, Arnd Bergmann, Max Filippov,
x86, Russell King, linux-csky, Ingo Molnar, David Airlie,
VMware Graphics, Mel Gorman, nouveau, Dave Airlie, linux-snps-arc,
Ben Skeggs, linux-xtensa, Paul McKenney, intel-gfx,
Roland Scheidegger, Josef Bacik, Steven Rostedt, Linus Torvalds,
Greentime Hu, spice-devel, David Sterba, Rodrigo Vivi,
Dietmar Eggemann, linux-arm-kernel, Jani Nikula, Chris Zankel,
Michal Simek, Thomas Bogendoerfer, Nick Hu, linux-mm,
Vineet Gupta, linux-mips, Christian Koenig, Benjamin LaHaise,
Daniel Vetter, linux-fsdevel, Andrew Morton, linuxppc-dev,
David S. Miller, linux-btrfs, Alexander Viro
In-Reply-To: <20201103092712.714480842@linutronix.de>
The mapping code is odd and looks broken. See FIXME in the comment.
Also fix the harmless off by one in the FIX_KMAP_END define.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Nick Hu <nickhu@andestech.com>
Cc: Greentime Hu <green.hu@gmail.com>
Cc: Vincent Chen <deanbo422@gmail.com>
---
V3: Remove the kmap types cruft
---
arch/nds32/Kconfig.cpu | 1
arch/nds32/include/asm/fixmap.h | 4 +--
arch/nds32/include/asm/highmem.h | 22 +++++++++++++----
arch/nds32/mm/Makefile | 1
arch/nds32/mm/highmem.c | 48 ---------------------------------------
5 files changed, 19 insertions(+), 57 deletions(-)
--- a/arch/nds32/Kconfig.cpu
+++ b/arch/nds32/Kconfig.cpu
@@ -157,6 +157,7 @@ config HW_SUPPORT_UNALIGNMENT_ACCESS
config HIGHMEM
bool "High Memory Support"
depends on MMU && !CPU_CACHE_ALIASING
+ select KMAP_LOCAL
help
The address space of Andes processors is only 4 Gigabytes large
and it has to accommodate user address space, kernel address
--- a/arch/nds32/include/asm/fixmap.h
+++ b/arch/nds32/include/asm/fixmap.h
@@ -6,7 +6,7 @@
#ifdef CONFIG_HIGHMEM
#include <linux/threads.h>
-#include <asm/kmap_types.h>
+#include <asm/kmap_size.h>
#endif
enum fixed_addresses {
@@ -14,7 +14,7 @@ enum fixed_addresses {
FIX_KMAP_RESERVED,
FIX_KMAP_BEGIN,
#ifdef CONFIG_HIGHMEM
- FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_TYPE_NR * NR_CPUS),
+ FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_MAX_IDX * NR_CPUS) - 1,
#endif
FIX_EARLYCON_MEM_BASE,
__end_of_fixed_addresses
--- a/arch/nds32/include/asm/highmem.h
+++ b/arch/nds32/include/asm/highmem.h
@@ -5,7 +5,6 @@
#define _ASM_HIGHMEM_H
#include <asm/proc-fns.h>
-#include <asm/kmap_types.h>
#include <asm/fixmap.h>
/*
@@ -45,11 +44,22 @@ extern pte_t *pkmap_page_table;
extern void kmap_init(void);
/*
- * The following functions are already defined by <linux/highmem.h>
- * when CONFIG_HIGHMEM is not set.
+ * FIXME: The below looks broken vs. a kmap_atomic() in task context which
+ * is interupted and another kmap_atomic() happens in interrupt context.
+ * But what do I know about nds32. -- tglx
*/
-#ifdef CONFIG_HIGHMEM
-extern void *kmap_atomic_pfn(unsigned long pfn);
-#endif
+#define arch_kmap_local_post_map(vaddr, pteval) \
+ do { \
+ __nds32__tlbop_inv(vaddr); \
+ __nds32__mtsr_dsb(vaddr, NDS32_SR_TLB_VPN); \
+ __nds32__tlbop_rwr(pteval); \
+ __nds32__isb(); \
+ } while (0)
+
+#define arch_kmap_local_pre_unmap(vaddr) \
+ do { \
+ __nds32__tlbop_inv(vaddr); \
+ __nds32__isb(); \
+ } while (0)
#endif
--- a/arch/nds32/mm/Makefile
+++ b/arch/nds32/mm/Makefile
@@ -3,7 +3,6 @@ obj-y := extable.o tlb.o fault.o init
mm-nds32.o cacheflush.o proc.o
obj-$(CONFIG_ALIGNMENT_TRAP) += alignment.o
-obj-$(CONFIG_HIGHMEM) += highmem.o
ifdef CONFIG_FUNCTION_TRACER
CFLAGS_REMOVE_proc.o = $(CC_FLAGS_FTRACE)
--- a/arch/nds32/mm/highmem.c
+++ /dev/null
@@ -1,48 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-// Copyright (C) 2005-2017 Andes Technology Corporation
-
-#include <linux/export.h>
-#include <linux/highmem.h>
-#include <linux/sched.h>
-#include <linux/smp.h>
-#include <linux/interrupt.h>
-#include <linux/memblock.h>
-#include <asm/fixmap.h>
-#include <asm/tlbflush.h>
-
-void *kmap_atomic_high_prot(struct page *page, pgprot_t prot)
-{
- unsigned int idx;
- unsigned long vaddr, pte;
- int type;
- pte_t *ptep;
-
- type = kmap_atomic_idx_push();
-
- idx = type + KM_TYPE_NR * smp_processor_id();
- vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
- pte = (page_to_pfn(page) << PAGE_SHIFT) | prot;
- ptep = pte_offset_kernel(pmd_off_k(vaddr), vaddr);
- set_pte(ptep, pte);
-
- __nds32__tlbop_inv(vaddr);
- __nds32__mtsr_dsb(vaddr, NDS32_SR_TLB_VPN);
- __nds32__tlbop_rwr(pte);
- __nds32__isb();
- return (void *)vaddr;
-}
-EXPORT_SYMBOL(kmap_atomic_high_prot);
-
-void kunmap_atomic_high(void *kvaddr)
-{
- if (kvaddr >= (void *)FIXADDR_START) {
- unsigned long vaddr = (unsigned long)kvaddr;
- pte_t *ptep;
- kmap_atomic_idx_pop();
- __nds32__tlbop_inv(vaddr);
- __nds32__isb();
- ptep = pte_offset_kernel(pmd_off_k(vaddr), vaddr);
- set_pte(ptep, 0);
- }
-}
-EXPORT_SYMBOL(kunmap_atomic_high);
^ permalink raw reply
* [patch V3 09/37] arc/mm/highmem: Use generic kmap atomic implementation
From: Thomas Gleixner @ 2020-11-03 9:27 UTC (permalink / raw)
To: LKML
Cc: Juri Lelli, linux-aio, Peter Zijlstra, Sebastian Andrzej Siewior,
Joonas Lahtinen, dri-devel, virtualization, Ben Segall,
Chris Mason, Huang Rui, Paul Mackerras, Gerd Hoffmann,
Daniel Bristot de Oliveira, sparclinux, Vincent Chen,
Christoph Hellwig, Vincent Guittot, Paul McKenney, Max Filippov,
x86, Russell King, linux-csky, Ingo Molnar, David Airlie,
VMware Graphics, Mel Gorman, nouveau, Dave Airlie, linux-snps-arc,
Ben Skeggs, linux-xtensa, Arnd Bergmann, intel-gfx,
Roland Scheidegger, Josef Bacik, Steven Rostedt, Linus Torvalds,
Alexander Viro, spice-devel, David Sterba, Rodrigo Vivi,
Dietmar Eggemann, linux-arm-kernel, Jani Nikula, Chris Zankel,
Michal Simek, Thomas Bogendoerfer, Nick Hu, linux-mm,
Vineet Gupta, linux-mips, Christian Koenig, Benjamin LaHaise,
Daniel Vetter, linux-fsdevel, Andrew Morton, linuxppc-dev,
David S. Miller, linux-btrfs, Greentime Hu
In-Reply-To: <20201103092712.714480842@linutronix.de>
Adopt the map ordering to match the other architectures and the generic
code. Also make the maximum entries limited and not dependend on the number
of CPUs. With the original implementation did the following calculation:
nr_slots = mapsize >> PAGE_SHIFT;
The results in either 512 or 1024 total slots depending on
configuration. The total slots have to be divided by the number of CPUs to
get the number of slots per CPU (former KM_TYPE_NR). ARC supports up to 4k
CPUs, so this just falls apart in random ways depending on the number of
CPUs and the actual kmap (atomic) nesting. The comment in highmem.c:
* - fixmap anyhow needs a limited number of mappings. So 2M kvaddr == 256 PTE
* slots across NR_CPUS would be more than sufficient (generic code defines
* KM_TYPE_NR as 20).
is just wrong. KM_TYPE_NR (now KM_MAX_IDX) is the number of slots per CPU
because kmap_local/atomic() needs to support nested mappings (thread,
softirq, interrupt). While KM_MAX_IDX might be overestimated, the above
reasoning is just wrong and clearly the highmem code was never tested with
any system with more than a few CPUs.
Use the default number of slots and fail the build when it does not
fit. Randomly failing at runtime is not a really good option.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Vineet Gupta <vgupta@synopsys.com>
Cc: linux-snps-arc@lists.infradead.org
---
V3: Make it actually more correct.
---
arch/arc/Kconfig | 1
arch/arc/include/asm/highmem.h | 26 ++++++++++++++----
arch/arc/include/asm/kmap_types.h | 14 ---------
arch/arc/mm/highmem.c | 54 +++-----------------------------------
4 files changed, 26 insertions(+), 69 deletions(-)
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -507,6 +507,7 @@ config LINUX_RAM_BASE
config HIGHMEM
bool "High Memory Support"
select ARCH_DISCONTIGMEM_ENABLE
+ select KMAP_LOCAL
help
With ARC 2G:2G address split, only upper 2G is directly addressable by
kernel. Enable this to potentially allow access to rest of 2G and PAE
--- a/arch/arc/include/asm/highmem.h
+++ b/arch/arc/include/asm/highmem.h
@@ -9,17 +9,29 @@
#ifdef CONFIG_HIGHMEM
#include <uapi/asm/page.h>
-#include <asm/kmap_types.h>
+#include <asm/kmap_size.h>
+
+#define FIXMAP_SIZE PGDIR_SIZE
+#define PKMAP_SIZE PGDIR_SIZE
/* start after vmalloc area */
#define FIXMAP_BASE (PAGE_OFFSET - FIXMAP_SIZE - PKMAP_SIZE)
-#define FIXMAP_SIZE PGDIR_SIZE /* only 1 PGD worth */
-#define KM_TYPE_NR ((FIXMAP_SIZE >> PAGE_SHIFT)/NR_CPUS)
-#define FIXMAP_ADDR(nr) (FIXMAP_BASE + ((nr) << PAGE_SHIFT))
+
+#define FIX_KMAP_SLOTS (KM_MAX_IDX * NR_CPUS)
+#define FIX_KMAP_BEGIN (0UL)
+#define FIX_KMAP_END ((FIX_KMAP_BEGIN + FIX_KMAP_SLOTS) - 1)
+
+#define FIXADDR_TOP (FIXMAP_BASE + (FIX_KMAP_END << PAGE_SHIFT))
+
+/*
+ * This should be converted to the asm-generic version, but of course this
+ * is needlessly different from all other architectures. Sigh - tglx
+ */
+#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
+#define __virt_to_fix(x) (((FIXADDR_TOP - ((x) & PAGE_MASK))) >> PAGE_SHIFT)
/* start after fixmap area */
#define PKMAP_BASE (FIXMAP_BASE + FIXMAP_SIZE)
-#define PKMAP_SIZE PGDIR_SIZE
#define LAST_PKMAP (PKMAP_SIZE >> PAGE_SHIFT)
#define LAST_PKMAP_MASK (LAST_PKMAP - 1)
#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT))
@@ -29,11 +41,13 @@
extern void kmap_init(void);
+#define arch_kmap_local_post_unmap(vaddr) \
+ local_flush_tlb_kernel_range(vaddr, vaddr + PAGE_SIZE)
+
static inline void flush_cache_kmaps(void)
{
flush_cache_all();
}
-
#endif
#endif
--- a/arch/arc/include/asm/kmap_types.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) 2015 Synopsys, Inc. (www.synopsys.com)
- */
-
-#ifndef _ASM_KMAP_TYPES_H
-#define _ASM_KMAP_TYPES_H
-
-/*
- * We primarily need to define KM_TYPE_NR here but that in turn
- * is a function of PGDIR_SIZE etc.
- * To avoid circular deps issue, put everything in asm/highmem.h
- */
-#endif
--- a/arch/arc/mm/highmem.c
+++ b/arch/arc/mm/highmem.c
@@ -36,9 +36,8 @@
* This means each only has 1 PGDIR_SIZE worth of kvaddr mappings, which means
* 2M of kvaddr space for typical config (8K page and 11:8:13 traversal split)
*
- * - fixmap anyhow needs a limited number of mappings. So 2M kvaddr == 256 PTE
- * slots across NR_CPUS would be more than sufficient (generic code defines
- * KM_TYPE_NR as 20).
+ * - The fixed KMAP slots for kmap_local/atomic() require KM_MAX_IDX slots per
+ * CPU. So the number of CPUs sharing a single PTE page is limited.
*
* - pkmap being preemptible, in theory could do with more than 256 concurrent
* mappings. However, generic pkmap code: map_new_virtual(), doesn't traverse
@@ -47,48 +46,6 @@
*/
extern pte_t * pkmap_page_table;
-static pte_t * fixmap_page_table;
-
-void *kmap_atomic_high_prot(struct page *page, pgprot_t prot)
-{
- int idx, cpu_idx;
- unsigned long vaddr;
-
- cpu_idx = kmap_atomic_idx_push();
- idx = cpu_idx + KM_TYPE_NR * smp_processor_id();
- vaddr = FIXMAP_ADDR(idx);
-
- set_pte_at(&init_mm, vaddr, fixmap_page_table + idx,
- mk_pte(page, prot));
-
- return (void *)vaddr;
-}
-EXPORT_SYMBOL(kmap_atomic_high_prot);
-
-void kunmap_atomic_high(void *kv)
-{
- unsigned long kvaddr = (unsigned long)kv;
-
- if (kvaddr >= FIXMAP_BASE && kvaddr < (FIXMAP_BASE + FIXMAP_SIZE)) {
-
- /*
- * Because preemption is disabled, this vaddr can be associated
- * with the current allocated index.
- * But in case of multiple live kmap_atomic(), it still relies on
- * callers to unmap in right order.
- */
- int cpu_idx = kmap_atomic_idx();
- int idx = cpu_idx + KM_TYPE_NR * smp_processor_id();
-
- WARN_ON(kvaddr != FIXMAP_ADDR(idx));
-
- pte_clear(&init_mm, kvaddr, fixmap_page_table + idx);
- local_flush_tlb_kernel_range(kvaddr, kvaddr + PAGE_SIZE);
-
- kmap_atomic_idx_pop();
- }
-}
-EXPORT_SYMBOL(kunmap_atomic_high);
static noinline pte_t * __init alloc_kmap_pgtable(unsigned long kvaddr)
{
@@ -108,10 +65,9 @@ void __init kmap_init(void)
{
/* Due to recursive include hell, we can't do this in processor.h */
BUILD_BUG_ON(PAGE_OFFSET < (VMALLOC_END + FIXMAP_SIZE + PKMAP_SIZE));
+ BUILD_BUG_ON(LAST_PKMAP > PTRS_PER_PTE);
+ BUILD_BUG_ON(FIX_KMAP_SLOTS > PTRS_PER_PTE);
- BUILD_BUG_ON(KM_TYPE_NR > PTRS_PER_PTE);
pkmap_page_table = alloc_kmap_pgtable(PKMAP_BASE);
-
- BUILD_BUG_ON(LAST_PKMAP > PTRS_PER_PTE);
- fixmap_page_table = alloc_kmap_pgtable(FIXMAP_BASE);
+ alloc_kmap_pgtable(FIXMAP_BASE);
}
^ permalink raw reply
* [patch V3 08/37] x86/mm/highmem: Use generic kmap atomic implementation
From: Thomas Gleixner @ 2020-11-03 9:27 UTC (permalink / raw)
To: LKML
Cc: Juri Lelli, linux-aio, Peter Zijlstra, Sebastian Andrzej Siewior,
Joonas Lahtinen, dri-devel, virtualization, Ben Segall,
Chris Mason, Huang Rui, Paul Mackerras, Gerd Hoffmann,
Daniel Bristot de Oliveira, sparclinux, Vincent Chen,
Christoph Hellwig, Vincent Guittot, Paul McKenney, Max Filippov,
x86, Russell King, linux-csky, Ingo Molnar, David Airlie,
VMware Graphics, Mel Gorman, nouveau, Dave Airlie, linux-snps-arc,
Ben Skeggs, linux-xtensa, Arnd Bergmann, intel-gfx,
Roland Scheidegger, Josef Bacik, Steven Rostedt, Linus Torvalds,
Alexander Viro, spice-devel, David Sterba, Rodrigo Vivi,
Dietmar Eggemann, linux-arm-kernel, Jani Nikula, Chris Zankel,
Michal Simek, Thomas Bogendoerfer, Nick Hu, linux-mm,
Vineet Gupta, linux-mips, Christian Koenig, Benjamin LaHaise,
Daniel Vetter, linux-fsdevel, Andrew Morton, linuxppc-dev,
David S. Miller, linux-btrfs, Greentime Hu
In-Reply-To: <20201103092712.714480842@linutronix.de>
Convert X86 to the generic kmap atomic implementation and make the
iomap_atomic() naming convention consistent while at it.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: x86@kernel.org
---
V3: Remove the kmap_types cruft
---
arch/x86/Kconfig | 3 +
arch/x86/include/asm/fixmap.h | 5 +-
arch/x86/include/asm/highmem.h | 13 +++++--
arch/x86/include/asm/iomap.h | 18 +++++-----
arch/x86/include/asm/kmap_types.h | 13 -------
arch/x86/include/asm/paravirt_types.h | 1
arch/x86/mm/highmem_32.c | 59 ----------------------------------
arch/x86/mm/init_32.c | 15 --------
arch/x86/mm/iomap_32.c | 59 ++--------------------------------
include/linux/highmem.h | 2 -
include/linux/io-mapping.h | 2 -
mm/highmem.c | 2 -
12 files changed, 31 insertions(+), 161 deletions(-)
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -14,10 +14,11 @@ config X86_32
select ARCH_WANT_IPC_PARSE_VERSION
select CLKSRC_I8253
select CLONE_BACKWARDS
+ select GENERIC_VDSO_32
select HAVE_DEBUG_STACKOVERFLOW
+ select KMAP_LOCAL
select MODULES_USE_ELF_REL
select OLD_SIGACTION
- select GENERIC_VDSO_32
config X86_64
def_bool y
--- a/arch/x86/include/asm/fixmap.h
+++ b/arch/x86/include/asm/fixmap.h
@@ -31,7 +31,7 @@
#include <asm/pgtable_types.h>
#ifdef CONFIG_X86_32
#include <linux/threads.h>
-#include <asm/kmap_types.h>
+#include <asm/kmap_size.h>
#else
#include <uapi/asm/vsyscall.h>
#endif
@@ -94,7 +94,7 @@ enum fixed_addresses {
#endif
#ifdef CONFIG_X86_32
FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */
- FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
+ FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_MAX_IDX * NR_CPUS) - 1,
#ifdef CONFIG_PCI_MMCONFIG
FIX_PCIE_MCFG,
#endif
@@ -151,7 +151,6 @@ extern void reserve_top_address(unsigned
extern int fixmaps_set;
-extern pte_t *kmap_pte;
extern pte_t *pkmap_page_table;
void __native_set_fixmap(enum fixed_addresses idx, pte_t pte);
--- a/arch/x86/include/asm/highmem.h
+++ b/arch/x86/include/asm/highmem.h
@@ -23,7 +23,6 @@
#include <linux/interrupt.h>
#include <linux/threads.h>
-#include <asm/kmap_types.h>
#include <asm/tlbflush.h>
#include <asm/paravirt.h>
#include <asm/fixmap.h>
@@ -58,11 +57,17 @@ extern unsigned long highstart_pfn, high
#define PKMAP_NR(virt) ((virt-PKMAP_BASE) >> PAGE_SHIFT)
#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT))
-void *kmap_atomic_pfn(unsigned long pfn);
-void *kmap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot);
-
#define flush_cache_kmaps() do { } while (0)
+#define arch_kmap_local_post_map(vaddr, pteval) \
+ arch_flush_lazy_mmu_mode()
+
+#define arch_kmap_local_post_unmap(vaddr) \
+ do { \
+ flush_tlb_one_kernel((vaddr)); \
+ arch_flush_lazy_mmu_mode(); \
+ } while (0)
+
extern void add_highpages_with_active_regions(int nid, unsigned long start_pfn,
unsigned long end_pfn);
--- a/arch/x86/include/asm/iomap.h
+++ b/arch/x86/include/asm/iomap.h
@@ -9,19 +9,21 @@
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/uaccess.h>
+#include <linux/highmem.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
-void __iomem *
-iomap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot);
+void __iomem *iomap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot);
-void
-iounmap_atomic(void __iomem *kvaddr);
+static inline void iounmap_atomic(void __iomem *vaddr)
+{
+ kunmap_local_indexed((void __force *)vaddr);
+ pagefault_enable();
+ preempt_enable();
+}
-int
-iomap_create_wc(resource_size_t base, unsigned long size, pgprot_t *prot);
+int iomap_create_wc(resource_size_t base, unsigned long size, pgprot_t *prot);
-void
-iomap_free(resource_size_t base, unsigned long size);
+void iomap_free(resource_size_t base, unsigned long size);
#endif /* _ASM_X86_IOMAP_H */
--- a/arch/x86/include/asm/kmap_types.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_X86_KMAP_TYPES_H
-#define _ASM_X86_KMAP_TYPES_H
-
-#if defined(CONFIG_X86_32) && defined(CONFIG_DEBUG_HIGHMEM)
-#define __WITH_KM_FENCE
-#endif
-
-#include <asm-generic/kmap_types.h>
-
-#undef __WITH_KM_FENCE
-
-#endif /* _ASM_X86_KMAP_TYPES_H */
--- a/arch/x86/include/asm/paravirt_types.h
+++ b/arch/x86/include/asm/paravirt_types.h
@@ -41,7 +41,6 @@
#ifndef __ASSEMBLY__
#include <asm/desc_defs.h>
-#include <asm/kmap_types.h>
#include <asm/pgtable_types.h>
#include <asm/nospec-branch.h>
--- a/arch/x86/mm/highmem_32.c
+++ b/arch/x86/mm/highmem_32.c
@@ -4,65 +4,6 @@
#include <linux/swap.h> /* for totalram_pages */
#include <linux/memblock.h>
-void *kmap_atomic_high_prot(struct page *page, pgprot_t prot)
-{
- unsigned long vaddr;
- int idx, type;
-
- type = kmap_atomic_idx_push();
- idx = type + KM_TYPE_NR*smp_processor_id();
- vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
- BUG_ON(!pte_none(*(kmap_pte-idx)));
- set_pte(kmap_pte-idx, mk_pte(page, prot));
- arch_flush_lazy_mmu_mode();
-
- return (void *)vaddr;
-}
-EXPORT_SYMBOL(kmap_atomic_high_prot);
-
-/*
- * This is the same as kmap_atomic() but can map memory that doesn't
- * have a struct page associated with it.
- */
-void *kmap_atomic_pfn(unsigned long pfn)
-{
- return kmap_atomic_prot_pfn(pfn, kmap_prot);
-}
-EXPORT_SYMBOL_GPL(kmap_atomic_pfn);
-
-void kunmap_atomic_high(void *kvaddr)
-{
- unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
-
- if (vaddr >= __fix_to_virt(FIX_KMAP_END) &&
- vaddr <= __fix_to_virt(FIX_KMAP_BEGIN)) {
- int idx, type;
-
- type = kmap_atomic_idx();
- idx = type + KM_TYPE_NR * smp_processor_id();
-
-#ifdef CONFIG_DEBUG_HIGHMEM
- WARN_ON_ONCE(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
-#endif
- /*
- * Force other mappings to Oops if they'll try to access this
- * pte without first remap it. Keeping stale mappings around
- * is a bad idea also, in case the page changes cacheability
- * attributes or becomes a protected page in a hypervisor.
- */
- kpte_clear_flush(kmap_pte-idx, vaddr);
- kmap_atomic_idx_pop();
- arch_flush_lazy_mmu_mode();
- }
-#ifdef CONFIG_DEBUG_HIGHMEM
- else {
- BUG_ON(vaddr < PAGE_OFFSET);
- BUG_ON(vaddr >= (unsigned long)high_memory);
- }
-#endif
-}
-EXPORT_SYMBOL(kunmap_atomic_high);
-
void __init set_highmem_pages_init(void)
{
struct zone *zone;
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -394,19 +394,6 @@ kernel_physical_mapping_init(unsigned lo
return last_map_addr;
}
-pte_t *kmap_pte;
-
-static void __init kmap_init(void)
-{
- unsigned long kmap_vstart;
-
- /*
- * Cache the first kmap pte:
- */
- kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
- kmap_pte = virt_to_kpte(kmap_vstart);
-}
-
#ifdef CONFIG_HIGHMEM
static void __init permanent_kmaps_init(pgd_t *pgd_base)
{
@@ -712,8 +699,6 @@ void __init paging_init(void)
__flush_tlb_all();
- kmap_init();
-
/*
* NOTE: at this point the bootmem allocator is fully available.
*/
--- a/arch/x86/mm/iomap_32.c
+++ b/arch/x86/mm/iomap_32.c
@@ -44,28 +44,7 @@ void iomap_free(resource_size_t base, un
}
EXPORT_SYMBOL_GPL(iomap_free);
-void *kmap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot)
-{
- unsigned long vaddr;
- int idx, type;
-
- preempt_disable();
- pagefault_disable();
-
- type = kmap_atomic_idx_push();
- idx = type + KM_TYPE_NR * smp_processor_id();
- vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
- set_pte(kmap_pte - idx, pfn_pte(pfn, prot));
- arch_flush_lazy_mmu_mode();
-
- return (void *)vaddr;
-}
-
-/*
- * Map 'pfn' using protections 'prot'
- */
-void __iomem *
-iomap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot)
+void __iomem *iomap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot)
{
/*
* For non-PAT systems, translate non-WB request to UC- just in
@@ -81,36 +60,8 @@ iomap_atomic_prot_pfn(unsigned long pfn,
/* Filter out unsupported __PAGE_KERNEL* bits: */
pgprot_val(prot) &= __default_kernel_pte_mask;
- return (void __force __iomem *) kmap_atomic_prot_pfn(pfn, prot);
-}
-EXPORT_SYMBOL_GPL(iomap_atomic_prot_pfn);
-
-void
-iounmap_atomic(void __iomem *kvaddr)
-{
- unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
-
- if (vaddr >= __fix_to_virt(FIX_KMAP_END) &&
- vaddr <= __fix_to_virt(FIX_KMAP_BEGIN)) {
- int idx, type;
-
- type = kmap_atomic_idx();
- idx = type + KM_TYPE_NR * smp_processor_id();
-
-#ifdef CONFIG_DEBUG_HIGHMEM
- WARN_ON_ONCE(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
-#endif
- /*
- * Force other mappings to Oops if they'll try to access this
- * pte without first remap it. Keeping stale mappings around
- * is a bad idea also, in case the page changes cacheability
- * attributes or becomes a protected page in a hypervisor.
- */
- kpte_clear_flush(kmap_pte-idx, vaddr);
- kmap_atomic_idx_pop();
- }
-
- pagefault_enable();
- preempt_enable();
+ preempt_disable();
+ pagefault_disable();
+ return (void __force __iomem *)__kmap_local_pfn_prot(pfn, prot);
}
-EXPORT_SYMBOL_GPL(iounmap_atomic);
+EXPORT_SYMBOL_GPL(iomap_atomic_pfn_prot);
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -217,7 +217,7 @@ static inline void __kunmap_atomic(void
#endif /* CONFIG_HIGHMEM */
#if !defined(CONFIG_KMAP_LOCAL)
-#if defined(CONFIG_HIGHMEM) || defined(CONFIG_X86_32)
+#if defined(CONFIG_HIGHMEM)
DECLARE_PER_CPU(int, __kmap_atomic_idx);
--- a/include/linux/io-mapping.h
+++ b/include/linux/io-mapping.h
@@ -69,7 +69,7 @@ io_mapping_map_atomic_wc(struct io_mappi
BUG_ON(offset >= mapping->size);
phys_addr = mapping->base + offset;
- return iomap_atomic_prot_pfn(PHYS_PFN(phys_addr), mapping->prot);
+ return iomap_atomic_pfn_prot(PHYS_PFN(phys_addr), mapping->prot);
}
static inline void
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -32,7 +32,7 @@
#include <linux/vmalloc.h>
#ifndef CONFIG_KMAP_LOCAL
-#if defined(CONFIG_HIGHMEM) || defined(CONFIG_X86_32)
+#ifdef CONFIG_HIGHMEM
DEFINE_PER_CPU(int, __kmap_atomic_idx);
#endif
#endif
^ permalink raw reply
* [patch V3 07/37] highmem: Make DEBUG_HIGHMEM functional
From: Thomas Gleixner @ 2020-11-03 9:27 UTC (permalink / raw)
To: LKML
Cc: Juri Lelli, linux-aio, Peter Zijlstra, Sebastian Andrzej Siewior,
Joonas Lahtinen, dri-devel, virtualization, Ben Segall,
Chris Mason, Huang Rui, Paul Mackerras, Gerd Hoffmann,
Daniel Bristot de Oliveira, sparclinux, Vincent Chen,
Christoph Hellwig, Vincent Guittot, Paul McKenney, Max Filippov,
x86, Russell King, linux-csky, Ingo Molnar, David Airlie,
VMware Graphics, Mel Gorman, nouveau, Dave Airlie, linux-snps-arc,
Ben Skeggs, linux-xtensa, Arnd Bergmann, intel-gfx,
Roland Scheidegger, Josef Bacik, Steven Rostedt, Linus Torvalds,
Alexander Viro, spice-devel, David Sterba, Rodrigo Vivi,
Dietmar Eggemann, linux-arm-kernel, Jani Nikula, Chris Zankel,
Michal Simek, Thomas Bogendoerfer, Nick Hu, linux-mm,
Vineet Gupta, linux-mips, Christian Koenig, Benjamin LaHaise,
Daniel Vetter, linux-fsdevel, Andrew Morton, linuxppc-dev,
David S. Miller, linux-btrfs, Greentime Hu
In-Reply-To: <20201103092712.714480842@linutronix.de>
For some obscure reason when CONFIG_DEBUG_HIGHMEM is enabled the stack
depth is increased from 20 to 41. But the only thing DEBUG_HIGHMEM does is
to enable a few BUG_ON()'s in the mapping code.
That's a leftover from the historical mapping code which had fixed entries
for various purposes. DEBUG_HIGHMEM inserted guard mappings between the map
types. But that got all ditched when kmap_atomic() switched to a stack
based map management. Though the WITH_KM_FENCE magic survived without being
functional. All the thing does today is to increase the stack depth.
Add a working implementation to the generic kmap_local* implementation.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
V3: New patch
---
mm/highmem.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -374,9 +374,19 @@ EXPORT_SYMBOL(kunmap_high);
static DEFINE_PER_CPU(int, __kmap_local_idx);
+/*
+ * With DEBUG_HIGHMEM the stack depth is doubled and every second
+ * slot is unused which acts as a guard page
+ */
+#ifdef CONFIG_DEBUG_HIGHMEM
+# define KM_INCR 2
+#else
+# define KM_INCR 1
+#endif
+
static inline int kmap_local_idx_push(void)
{
- int idx = __this_cpu_inc_return(__kmap_local_idx) - 1;
+ int idx = __this_cpu_add_return(__kmap_local_idx, KM_INCR) - 1;
WARN_ON_ONCE(in_irq() && !irqs_disabled());
BUG_ON(idx >= KM_MAX_IDX);
@@ -390,7 +400,7 @@ static inline int kmap_local_idx(void)
static inline void kmap_local_idx_pop(void)
{
- int idx = __this_cpu_dec_return(__kmap_local_idx);
+ int idx = __this_cpu_sub_return(__kmap_local_idx, KM_INCR);
BUG_ON(idx < 0);
}
^ permalink raw reply
* [patch V3 06/37] highmem: Provide generic variant of kmap_atomic*
From: Thomas Gleixner @ 2020-11-03 9:27 UTC (permalink / raw)
To: LKML
Cc: Juri Lelli, linux-aio, Peter Zijlstra, Sebastian Andrzej Siewior,
Joonas Lahtinen, dri-devel, virtualization, Ben Segall,
Chris Mason, Huang Rui, Paul Mackerras, Gerd Hoffmann,
Daniel Bristot de Oliveira, sparclinux, Vincent Chen,
Christoph Hellwig, Vincent Guittot, Paul McKenney, Max Filippov,
x86, Russell King, linux-csky, Ingo Molnar, David Airlie,
VMware Graphics, Mel Gorman, nouveau, Dave Airlie, linux-snps-arc,
Ben Skeggs, linux-xtensa, Arnd Bergmann, intel-gfx,
Roland Scheidegger, Josef Bacik, Steven Rostedt, Linus Torvalds,
Alexander Viro, spice-devel, David Sterba, Rodrigo Vivi,
Dietmar Eggemann, linux-arm-kernel, Jani Nikula, Chris Zankel,
Michal Simek, Thomas Bogendoerfer, Nick Hu, linux-mm,
Vineet Gupta, linux-mips, Christian Koenig, Benjamin LaHaise,
Daniel Vetter, linux-fsdevel, Andrew Morton, linuxppc-dev,
David S. Miller, linux-btrfs, Greentime Hu
In-Reply-To: <20201103092712.714480842@linutronix.de>
The kmap_atomic* interfaces in all architectures are pretty much the same
except for post map operations (flush) and pre- and post unmap operations.
Provide a generic variant for that.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: linux-mm@kvack.org
---
V3: Do not reuse the kmap_atomic_idx pile and use kmap_size.h right away
V2: Address review comments from Christoph (style and EXPORT variant)
---
include/linux/highmem.h | 82 ++++++++++++++++++++++-----
mm/Kconfig | 3 +
mm/highmem.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 211 insertions(+), 18 deletions(-)
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -31,9 +31,16 @@ static inline void invalidate_kernel_vma
#include <asm/kmap_types.h>
+/*
+ * Outside of CONFIG_HIGHMEM to support X86 32bit iomap_atomic() cruft.
+ */
+#ifdef CONFIG_KMAP_LOCAL
+void *__kmap_local_pfn_prot(unsigned long pfn, pgprot_t prot);
+void *__kmap_local_page_prot(struct page *page, pgprot_t prot);
+void kunmap_local_indexed(void *vaddr);
+#endif
+
#ifdef CONFIG_HIGHMEM
-extern void *kmap_atomic_high_prot(struct page *page, pgprot_t prot);
-extern void kunmap_atomic_high(void *kvaddr);
#include <asm/highmem.h>
#ifndef ARCH_HAS_KMAP_FLUSH_TLB
@@ -81,6 +88,11 @@ static inline void kunmap(struct page *p
* be used in IRQ contexts, so in some (very limited) cases we need
* it.
*/
+
+#ifndef CONFIG_KMAP_LOCAL
+void *kmap_atomic_high_prot(struct page *page, pgprot_t prot);
+void kunmap_atomic_high(void *kvaddr);
+
static inline void *kmap_atomic_prot(struct page *page, pgprot_t prot)
{
preempt_disable();
@@ -89,7 +101,38 @@ static inline void *kmap_atomic_prot(str
return page_address(page);
return kmap_atomic_high_prot(page, prot);
}
-#define kmap_atomic(page) kmap_atomic_prot(page, kmap_prot)
+
+static inline void __kunmap_atomic(void *vaddr)
+{
+ kunmap_atomic_high(vaddr);
+}
+#else /* !CONFIG_KMAP_LOCAL */
+
+static inline void *kmap_atomic_prot(struct page *page, pgprot_t prot)
+{
+ preempt_disable();
+ pagefault_disable();
+ return __kmap_local_page_prot(page, prot);
+}
+
+static inline void *kmap_atomic_pfn(unsigned long pfn)
+{
+ preempt_disable();
+ pagefault_disable();
+ return __kmap_local_pfn_prot(pfn, kmap_prot);
+}
+
+static inline void __kunmap_atomic(void *addr)
+{
+ kunmap_local_indexed(addr);
+}
+
+#endif /* CONFIG_KMAP_LOCAL */
+
+static inline void *kmap_atomic(struct page *page)
+{
+ return kmap_atomic_prot(page, kmap_prot);
+}
/* declarations for linux/mm/highmem.c */
unsigned int nr_free_highpages(void);
@@ -147,25 +190,33 @@ static inline void *kmap_atomic(struct p
pagefault_disable();
return page_address(page);
}
-#define kmap_atomic_prot(page, prot) kmap_atomic(page)
-static inline void kunmap_atomic_high(void *addr)
+static inline void *kmap_atomic_prot(struct page *page, pgprot_t prot)
+{
+ return kmap_atomic(page);
+}
+
+static inline void *kmap_atomic_pfn(unsigned long pfn)
+{
+ return kmap_atomic(pfn_to_page(pfn));
+}
+
+static inline void __kunmap_atomic(void *addr)
{
/*
* Mostly nothing to do in the CONFIG_HIGHMEM=n case as kunmap_atomic()
- * handles re-enabling faults + preemption
+ * handles re-enabling faults and preemption
*/
#ifdef ARCH_HAS_FLUSH_ON_KUNMAP
kunmap_flush_on_unmap(addr);
#endif
}
-#define kmap_atomic_pfn(pfn) kmap_atomic(pfn_to_page(pfn))
-
#define kmap_flush_unused() do {} while(0)
#endif /* CONFIG_HIGHMEM */
+#if !defined(CONFIG_KMAP_LOCAL)
#if defined(CONFIG_HIGHMEM) || defined(CONFIG_X86_32)
DECLARE_PER_CPU(int, __kmap_atomic_idx);
@@ -196,22 +247,21 @@ static inline void kmap_atomic_idx_pop(v
__this_cpu_dec(__kmap_atomic_idx);
#endif
}
-
+#endif
#endif
/*
* Prevent people trying to call kunmap_atomic() as if it were kunmap()
* kunmap_atomic() should get the return value of kmap_atomic, not the page.
*/
-#define kunmap_atomic(addr) \
-do { \
- BUILD_BUG_ON(__same_type((addr), struct page *)); \
- kunmap_atomic_high(addr); \
- pagefault_enable(); \
- preempt_enable(); \
+#define kunmap_atomic(__addr) \
+do { \
+ BUILD_BUG_ON(__same_type((__addr), struct page *)); \
+ __kunmap_atomic(__addr); \
+ pagefault_enable(); \
+ preempt_enable(); \
} while (0)
-
/* when CONFIG_HIGHMEM is not set these will be plain clear/copy_page */
#ifndef clear_user_highpage
static inline void clear_user_highpage(struct page *page, unsigned long vaddr)
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -872,4 +872,7 @@ config ARCH_HAS_HUGEPD
config MAPPING_DIRTY_HELPERS
bool
+config KMAP_LOCAL
+ bool
+
endmenu
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -31,9 +31,11 @@
#include <asm/tlbflush.h>
#include <linux/vmalloc.h>
+#ifndef CONFIG_KMAP_LOCAL
#if defined(CONFIG_HIGHMEM) || defined(CONFIG_X86_32)
DEFINE_PER_CPU(int, __kmap_atomic_idx);
#endif
+#endif
/*
* Virtual_count is not a pure "count".
@@ -365,9 +367,147 @@ void kunmap_high(struct page *page)
if (need_wakeup)
wake_up(pkmap_map_wait);
}
-
EXPORT_SYMBOL(kunmap_high);
-#endif /* CONFIG_HIGHMEM */
+#endif /* CONFIG_HIGHMEM */
+
+#ifdef CONFIG_KMAP_LOCAL
+
+#include <asm/kmap_size.h>
+
+static DEFINE_PER_CPU(int, __kmap_local_idx);
+
+static inline int kmap_local_idx_push(void)
+{
+ int idx = __this_cpu_inc_return(__kmap_local_idx) - 1;
+
+ WARN_ON_ONCE(in_irq() && !irqs_disabled());
+ BUG_ON(idx >= KM_MAX_IDX);
+ return idx;
+}
+
+static inline int kmap_local_idx(void)
+{
+ return __this_cpu_read(__kmap_local_idx) - 1;
+}
+
+static inline void kmap_local_idx_pop(void)
+{
+ int idx = __this_cpu_dec_return(__kmap_local_idx);
+
+ BUG_ON(idx < 0);
+}
+
+#ifndef arch_kmap_local_post_map
+# define arch_kmap_local_post_map(vaddr, pteval) do { } while (0)
+#endif
+#ifndef arch_kmap_local_pre_unmap
+# define arch_kmap_local_pre_unmap(vaddr) do { } while (0)
+#endif
+
+#ifndef arch_kmap_local_post_unmap
+# define arch_kmap_local_post_unmap(vaddr) do { } while (0)
+#endif
+
+#ifndef arch_kmap_local_map_idx
+#define arch_kmap_local_map_idx(idx, pfn) kmap_local_calc_idx(idx)
+#endif
+
+#ifndef arch_kmap_local_unmap_idx
+#define arch_kmap_local_unmap_idx(idx, vaddr) kmap_local_calc_idx(idx)
+#endif
+
+#ifndef arch_kmap_local_high_get
+static inline void *arch_kmap_local_high_get(struct page *page)
+{
+ return NULL;
+}
+#endif
+
+/* Unmap a local mapping which was obtained by kmap_high_get() */
+static inline void kmap_high_unmap_local(unsigned long vaddr)
+{
+#ifdef ARCH_NEEDS_KMAP_HIGH_GET
+ if (vaddr >= PKMAP_ADDR(0) && vaddr < PKMAP_ADDR(LAST_PKMAP))
+ kunmap_high(pte_page(pkmap_page_table[PKMAP_NR(vaddr)]));
+#endif
+}
+
+static inline int kmap_local_calc_idx(int idx)
+{
+ return idx + KM_MAX_IDX * smp_processor_id();
+}
+
+static pte_t *__kmap_pte;
+
+static pte_t *kmap_get_pte(void)
+{
+ if (!__kmap_pte)
+ __kmap_pte = virt_to_kpte(__fix_to_virt(FIX_KMAP_BEGIN));
+ return __kmap_pte;
+}
+
+void *__kmap_local_pfn_prot(unsigned long pfn, pgprot_t prot)
+{
+ pte_t pteval, *kmap_pte = kmap_get_pte();
+ unsigned long vaddr;
+ int idx;
+
+ preempt_disable();
+ idx = arch_kmap_local_map_idx(kmap_local_idx_push(), pfn);
+ vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+ BUG_ON(!pte_none(*(kmap_pte - idx)));
+ pteval = pfn_pte(pfn, prot);
+ set_pte_at(&init_mm, vaddr, kmap_pte - idx, pteval);
+ arch_kmap_local_post_map(vaddr, pteval);
+ preempt_enable();
+
+ return (void *)vaddr;
+}
+EXPORT_SYMBOL_GPL(__kmap_local_pfn_prot);
+
+void *__kmap_local_page_prot(struct page *page, pgprot_t prot)
+{
+ void *kmap;
+
+ if (!PageHighMem(page))
+ return page_address(page);
+
+ /* Try kmap_high_get() if architecture has it enabled */
+ kmap = arch_kmap_local_high_get(page);
+ if (kmap)
+ return kmap;
+
+ return __kmap_local_pfn_prot(page_to_pfn(page), prot);
+}
+EXPORT_SYMBOL(__kmap_local_page_prot);
+
+void kunmap_local_indexed(void *vaddr)
+{
+ unsigned long addr = (unsigned long) vaddr & PAGE_MASK;
+ pte_t *kmap_pte = kmap_get_pte();
+ int idx;
+
+ if (addr < __fix_to_virt(FIX_KMAP_END) ||
+ addr > __fix_to_virt(FIX_KMAP_BEGIN)) {
+ WARN_ON_ONCE(addr < PAGE_OFFSET);
+
+ /* Handle mappings which were obtained by kmap_high_get() */
+ kmap_high_unmap_local(addr);
+ return;
+ }
+
+ preempt_disable();
+ idx = arch_kmap_local_unmap_idx(kmap_local_idx(), addr);
+ WARN_ON_ONCE(addr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
+
+ arch_kmap_local_pre_unmap(addr);
+ pte_clear(&init_mm, addr, kmap_pte - idx);
+ arch_kmap_local_post_unmap(addr);
+ kmap_local_idx_pop();
+ preempt_enable();
+}
+EXPORT_SYMBOL(kunmap_local_indexed);
+#endif
#if defined(HASHED_PAGE_VIRTUAL)
^ permalink raw reply
* [patch V3 05/37] asm-generic: Provide kmap_size.h
From: Thomas Gleixner @ 2020-11-03 9:27 UTC (permalink / raw)
To: LKML
Cc: Juri Lelli, linux-aio, Peter Zijlstra, Sebastian Andrzej Siewior,
Joonas Lahtinen, dri-devel, virtualization, Ben Segall,
Chris Mason, Huang Rui, Paul Mackerras, Gerd Hoffmann,
Daniel Bristot de Oliveira, sparclinux, Vincent Chen,
Christoph Hellwig, Vincent Guittot, Paul McKenney, Max Filippov,
x86, Russell King, linux-csky, Ingo Molnar, David Airlie,
VMware Graphics, Mel Gorman, nouveau, Dave Airlie, linux-snps-arc,
Ben Skeggs, linux-xtensa, Arnd Bergmann, intel-gfx,
Roland Scheidegger, Josef Bacik, Steven Rostedt, Linus Torvalds,
Alexander Viro, spice-devel, David Sterba, Rodrigo Vivi,
Dietmar Eggemann, linux-arm-kernel, Jani Nikula, Chris Zankel,
Michal Simek, Thomas Bogendoerfer, Nick Hu, linux-mm,
Vineet Gupta, linux-mips, Christian Koenig, Benjamin LaHaise,
Daniel Vetter, linux-fsdevel, Andrew Morton, linuxppc-dev,
David S. Miller, linux-btrfs, Greentime Hu
In-Reply-To: <20201103092712.714480842@linutronix.de>
kmap_types.h is a misnomer because the old atomic MAP based array does not
exist anymore and the whole indirection of architectures including
kmap_types.h is inconinstent and does not allow to provide guard page
debugging for this misfeature.
Add a common header file which defines the mapping stack size for all
architectures. Will be used when converting architectures over to a
generic kmap_local/atomic implementation.
The array size is chosen with the following constraints in mind:
- The deepest nest level in one context is 3 according to code
inspection.
- The worst case nesting for the upcoming reemptible version would be:
2 maps in task context and a fault inside
2 maps in the fault handler
3 maps in softirq
2 maps in interrupt
So a total of 16 is sufficient and probably overestimated.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
V3: New patch
---
include/asm-generic/Kbuild | 1 +
include/asm-generic/kmap_size.h | 12 ++++++++++++
2 files changed, 13 insertions(+)
--- a/include/asm-generic/Kbuild
+++ b/include/asm-generic/Kbuild
@@ -31,6 +31,7 @@ mandatory-y += irq_regs.h
mandatory-y += irq_work.h
mandatory-y += kdebug.h
mandatory-y += kmap_types.h
+mandatory-y += kmap_size.h
mandatory-y += kprobes.h
mandatory-y += linkage.h
mandatory-y += local.h
--- /dev/null
+++ b/include/asm-generic/kmap_size.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_GENERIC_KMAP_SIZE_H
+#define _ASM_GENERIC_KMAP_SIZE_H
+
+/* For debug this provides guard pages between the maps */
+#ifdef CONFIG_DEBUG_HIGHMEM
+# define KM_MAX_IDX 33
+#else
+# define KM_MAX_IDX 16
+#endif
+
+#endif
^ permalink raw reply
* [patch V3 04/37] sh/highmem: Remove all traces of unused cruft
From: Thomas Gleixner @ 2020-11-03 9:27 UTC (permalink / raw)
To: LKML
Cc: Juri Lelli, linux-aio, Peter Zijlstra, Sebastian Andrzej Siewior,
Joonas Lahtinen, dri-devel, virtualization, Ben Segall,
Chris Mason, Huang Rui, Paul Mackerras, Gerd Hoffmann,
Daniel Bristot de Oliveira, sparclinux, Vincent Chen,
Christoph Hellwig, Vincent Guittot, Paul McKenney, Max Filippov,
x86, Russell King, linux-csky, Ingo Molnar, David Airlie,
VMware Graphics, Mel Gorman, nouveau, Dave Airlie, linux-snps-arc,
Ben Skeggs, linux-xtensa, Arnd Bergmann, intel-gfx,
Roland Scheidegger, Josef Bacik, Steven Rostedt, Linus Torvalds,
Alexander Viro, spice-devel, David Sterba, Rodrigo Vivi,
Dietmar Eggemann, linux-arm-kernel, Jani Nikula, Chris Zankel,
Michal Simek, Thomas Bogendoerfer, Nick Hu, linux-mm,
Vineet Gupta, linux-mips, Christian Koenig, Benjamin LaHaise,
Daniel Vetter, linux-fsdevel, Andrew Morton, linuxppc-dev,
David S. Miller, linux-btrfs, Greentime Hu
In-Reply-To: <20201103092712.714480842@linutronix.de>
For whatever reasons SH has highmem bits all over the place but does
not enable it via Kconfig. Remove the bitrot.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
arch/sh/include/asm/fixmap.h | 8 --------
arch/sh/include/asm/kmap_types.h | 15 ---------------
arch/sh/mm/init.c | 8 --------
3 files changed, 31 deletions(-)
--- a/arch/sh/include/asm/fixmap.h
+++ b/arch/sh/include/asm/fixmap.h
@@ -13,9 +13,6 @@
#include <linux/kernel.h>
#include <linux/threads.h>
#include <asm/page.h>
-#ifdef CONFIG_HIGHMEM
-#include <asm/kmap_types.h>
-#endif
/*
* Here we define all the compile-time 'special' virtual
@@ -53,11 +50,6 @@ enum fixed_addresses {
FIX_CMAP_BEGIN,
FIX_CMAP_END = FIX_CMAP_BEGIN + (FIX_N_COLOURS * NR_CPUS) - 1,
-#ifdef CONFIG_HIGHMEM
- FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */
- FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_TYPE_NR * NR_CPUS) - 1,
-#endif
-
#ifdef CONFIG_IOREMAP_FIXED
/*
* FIX_IOREMAP entries are useful for mapping physical address
--- a/arch/sh/include/asm/kmap_types.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __SH_KMAP_TYPES_H
-#define __SH_KMAP_TYPES_H
-
-/* Dummy header just to define km_type. */
-
-#ifdef CONFIG_DEBUG_HIGHMEM
-#define __WITH_KM_FENCE
-#endif
-
-#include <asm-generic/kmap_types.h>
-
-#undef __WITH_KM_FENCE
-
-#endif
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -362,9 +362,6 @@ void __init mem_init(void)
mem_init_print_info(NULL);
pr_info("virtual kernel memory layout:\n"
" fixmap : 0x%08lx - 0x%08lx (%4ld kB)\n"
-#ifdef CONFIG_HIGHMEM
- " pkmap : 0x%08lx - 0x%08lx (%4ld kB)\n"
-#endif
" vmalloc : 0x%08lx - 0x%08lx (%4ld MB)\n"
" lowmem : 0x%08lx - 0x%08lx (%4ld MB) (cached)\n"
#ifdef CONFIG_UNCACHED_MAPPING
@@ -376,11 +373,6 @@ void __init mem_init(void)
FIXADDR_START, FIXADDR_TOP,
(FIXADDR_TOP - FIXADDR_START) >> 10,
-#ifdef CONFIG_HIGHMEM
- PKMAP_BASE, PKMAP_BASE+LAST_PKMAP*PAGE_SIZE,
- (LAST_PKMAP*PAGE_SIZE) >> 10,
-#endif
-
(unsigned long)VMALLOC_START, VMALLOC_END,
(VMALLOC_END - VMALLOC_START) >> 20,
^ permalink raw reply
* [patch V3 00/37] mm/highmem: Preemptible variant of kmap_atomic & friends
From: Thomas Gleixner @ 2020-11-03 9:27 UTC (permalink / raw)
To: LKML
Cc: Juri Lelli, linux-aio, Peter Zijlstra, Sebastian Andrzej Siewior,
Joonas Lahtinen, dri-devel, virtualization, Ben Segall,
Chris Mason, Huang Rui, Paul Mackerras, Gerd Hoffmann,
Daniel Bristot de Oliveira, sparclinux, Vincent Chen,
Christoph Hellwig, Vincent Guittot, Paul McKenney, Max Filippov,
x86, Russell King, linux-csky, Ingo Molnar, David Airlie,
VMware Graphics, Mel Gorman, nouveau, Dave Airlie, linux-snps-arc,
Ben Skeggs, linux-xtensa, Arnd Bergmann, intel-gfx,
Roland Scheidegger, Josef Bacik, Steven Rostedt, Linus Torvalds,
Alexander Viro, spice-devel, David Sterba, Rodrigo Vivi,
Dietmar Eggemann, linux-arm-kernel, Jani Nikula, Chris Zankel,
Michal Simek, Thomas Bogendoerfer, Nick Hu, linux-mm,
Vineet Gupta, linux-mips, Christian Koenig, Benjamin LaHaise,
Daniel Vetter, linux-fsdevel, Andrew Morton, linuxppc-dev,
David S. Miller, linux-btrfs, Greentime Hu
Following up to the discussion in:
https://lore.kernel.org/r/20200914204209.256266093@linutronix.de
and the second version of this:
https://lore.kernel.org/r/20201029221806.189523375@linutronix.de
this series provides a preemptible variant of kmap_atomic & related
interfaces.
This is achieved by:
- Removing the RT dependency from migrate_disable/enable()
- Consolidating all kmap atomic implementations in generic code including
a useful version of the CONFIG_DEBUG_HIGHMEM which provides guard pages
between the individual maps instead of just increasing the map size.
- Switching from per CPU storage of the kmap index to a per task storage
- Adding a pteval array to the per task storage which contains the ptevals
of the currently active temporary kmaps
- Adding context switch code which checks whether the outgoing or the
incoming task has active temporary kmaps. If so, the outgoing task's
kmaps are removed and the incoming task's kmaps are restored.
- Adding new interfaces k[un]map_local*() which are not disabling
preemption and can be called from any context (except NMI).
Contrary to kmap() which provides preemptible and "persistant" mappings,
these interfaces are meant to replace the temporary mappings provided by
kmap_atomic*() today.
This allows to get rid of conditional mapping choices and allows to have
preemptible short term mappings on 64bit which are today enforced to be
non-preemptible due to the highmem constraints. It clearly puts overhead on
the highmem users, but highmem is slow anyway.
This is not a wholesale conversion which makes kmap_atomic magically
preemptible because there might be usage sites which rely on the implicit
preempt disable. So this needs to be done on a case by case basis and the
call sites converted to kmap_local().
Note, that this is only tested on X86 and completely untested on all other
architectures (at least it compiles except on csky which does not compile
with the newest cross tools from kernel.org independent of this change).
The lot is available from
git://git.kernel.org/pub/scm/linux/kernel/git/tglx/devel.git highmem
It is based on Peter Zijlstras migrate disable branch which is close to be
merged into the tip tree, but still not finalized:
git://git.kernel.org/pub/scm/linux/kernel/git/peterz/queue.git sched/migrate-disable
The series has the following parts:
Patches 1 - 22: Consolidation work which is independent of the scheduler
changes
79 files changed, 595 insertions(+), 1296 deletions(-)
Patch 23: Needs to be folded back into the sched/migrate-disable
Patches 24 - 26: The preemptible kmap_local() implementation
9 files changed, 283 insertions(+), 57 deletions(-)
Patches 27 - 37: Cleanup of the less common kmap/io_map_atomic users
19 files changed, 114 insertions(+), 256 deletions(-)
Vs. merging this pile:
If everyone agrees, I'd like to take the first part (1-22) through tip so
that the preemptible implementation can be sorted in tip once the scheduler
prerequisites are there. The initial cleanups (27-37) might have to wait if
there are conflicts vs. the drm/gpu tree. We'll see.
>From what I can tell kmap_atomic() can be removed all together and
completly replaced by kmap_local(). Most of the usage sites are trivial and
just doing memcpy(), memset() or trivial operations on the temporarily
mapped page. The interesting ones are those which do either conditional
stuff or have copy_.*_user_inatomic() inside. As shown with the crash and
drm/gpu cleanups this allows to simplify the code quite a bit.
Changes vs. V2:
- Remove the migrate disable from kmap_local and only issue that when the
there is an actual highmem mapping. (Linus)
- Reordered the series so the consolidation is upfront
- Get rid of kmap_types.h and the associated cruft
- Fixup documentation and add function documentation for kmap_*
- Splitout the internal implementation into a seperate header
- More cleanups - removal of unused functions
- Replace a few of the less frequently used kmap_atomic and
io_mapping_map_atomic variants and remove those interfaces.
Thanks,
tglx
---
arch/alpha/include/asm/kmap_types.h | 15
arch/arc/include/asm/kmap_types.h | 14
arch/arm/include/asm/kmap_types.h | 10
arch/arm/mm/highmem.c | 121 -------
arch/ia64/include/asm/kmap_types.h | 13
arch/microblaze/mm/highmem.c | 78 ----
arch/mips/include/asm/kmap_types.h | 13
arch/nds32/mm/highmem.c | 48 --
arch/parisc/include/asm/kmap_types.h | 13
arch/powerpc/include/asm/kmap_types.h | 13
arch/powerpc/mm/highmem.c | 67 ----
arch/sh/include/asm/kmap_types.h | 15
arch/sparc/include/asm/kmap_types.h | 11
arch/sparc/mm/highmem.c | 115 -------
arch/um/include/asm/kmap_types.h | 13
arch/x86/include/asm/kmap_types.h | 13
b/Documentation/driver-api/io-mapping.rst | 92 ++---
b/arch/arc/Kconfig | 1
b/arch/arc/include/asm/highmem.h | 26 +
b/arch/arc/mm/highmem.c | 54 ---
b/arch/arm/Kconfig | 1
b/arch/arm/include/asm/fixmap.h | 4
b/arch/arm/include/asm/highmem.h | 33 +-
b/arch/arm/mm/Makefile | 1
b/arch/arm/mm/cache-feroceon-l2.c | 6
b/arch/arm/mm/cache-xsc3l2.c | 4
b/arch/csky/Kconfig | 1
b/arch/csky/include/asm/fixmap.h | 4
b/arch/csky/include/asm/highmem.h | 6
b/arch/csky/mm/highmem.c | 75 ----
b/arch/microblaze/Kconfig | 1
b/arch/microblaze/include/asm/fixmap.h | 4
b/arch/microblaze/include/asm/highmem.h | 6
b/arch/microblaze/mm/Makefile | 1
b/arch/microblaze/mm/init.c | 6
b/arch/mips/Kconfig | 1
b/arch/mips/include/asm/fixmap.h | 4
b/arch/mips/include/asm/highmem.h | 6
b/arch/mips/kernel/crash_dump.c | 42 --
b/arch/mips/mm/highmem.c | 77 ----
b/arch/mips/mm/init.c | 4
b/arch/nds32/Kconfig.cpu | 1
b/arch/nds32/include/asm/fixmap.h | 4
b/arch/nds32/include/asm/highmem.h | 22 -
b/arch/nds32/mm/Makefile | 1
b/arch/openrisc/mm/init.c | 1
b/arch/openrisc/mm/ioremap.c | 1
b/arch/powerpc/Kconfig | 1
b/arch/powerpc/include/asm/fixmap.h | 4
b/arch/powerpc/include/asm/highmem.h | 7
b/arch/powerpc/mm/Makefile | 1
b/arch/powerpc/mm/mem.c | 7
b/arch/sh/include/asm/fixmap.h | 8
b/arch/sh/mm/init.c | 8
b/arch/sparc/Kconfig | 1
b/arch/sparc/include/asm/highmem.h | 8
b/arch/sparc/include/asm/vaddrs.h | 4
b/arch/sparc/mm/Makefile | 3
b/arch/sparc/mm/srmmu.c | 2
b/arch/um/include/asm/fixmap.h | 1
b/arch/x86/Kconfig | 3
b/arch/x86/include/asm/fixmap.h | 5
b/arch/x86/include/asm/highmem.h | 13
b/arch/x86/include/asm/iomap.h | 13
b/arch/x86/include/asm/paravirt_types.h | 1
b/arch/x86/kernel/crash_dump_32.c | 48 --
b/arch/x86/mm/highmem_32.c | 59 ---
b/arch/x86/mm/init_32.c | 15
b/arch/x86/mm/iomap_32.c | 57 ---
b/arch/xtensa/Kconfig | 1
b/arch/xtensa/include/asm/fixmap.h | 4
b/arch/xtensa/include/asm/highmem.h | 12
b/arch/xtensa/mm/highmem.c | 46 --
b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 7
b/drivers/gpu/drm/i915/i915_gem.c | 40 --
b/drivers/gpu/drm/i915/selftests/i915_gem.c | 4
b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 8
b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/fbmem.h | 8
b/drivers/gpu/drm/qxl/qxl_image.c | 18 -
b/drivers/gpu/drm/qxl/qxl_ioctl.c | 27 -
b/drivers/gpu/drm/qxl/qxl_object.c | 12
b/drivers/gpu/drm/qxl/qxl_object.h | 4
b/drivers/gpu/drm/qxl/qxl_release.c | 4
b/drivers/gpu/drm/ttm/ttm_bo_util.c | 20 -
b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c | 30 -
b/fs/aio.c | 1
b/fs/btrfs/ctree.h | 1
b/include/asm-generic/Kbuild | 2
b/include/asm-generic/kmap_size.h | 12
b/include/linux/highmem-internal.h | 210 ++++++++++++
b/include/linux/highmem.h | 294 ++++++------------
b/include/linux/io-mapping.h | 28 -
b/include/linux/kernel.h | 21 -
b/include/linux/preempt.h | 38 --
b/include/linux/sched.h | 11
b/kernel/entry/common.c | 2
b/kernel/fork.c | 1
b/kernel/sched/core.c | 63 +++
b/kernel/sched/sched.h | 4
b/lib/smp_processor_id.c | 2
b/mm/Kconfig | 3
b/mm/highmem.c | 255 ++++++++++++++-
include/asm-generic/kmap_types.h | 11
103 files changed, 959 insertions(+), 1576 deletions(-)
^ permalink raw reply
* [patch V3 03/37] fs: Remove asm/kmap_types.h includes
From: Thomas Gleixner @ 2020-11-03 9:27 UTC (permalink / raw)
To: LKML
Cc: Juri Lelli, linux-aio, Peter Zijlstra, Sebastian Andrzej Siewior,
Joonas Lahtinen, dri-devel, virtualization, Ben Segall, linux-mm,
Huang Rui, Paul Mackerras, Gerd Hoffmann,
Daniel Bristot de Oliveira, sparclinux, Vincent Chen,
Christoph Hellwig, Vincent Guittot, Paul McKenney, Max Filippov,
x86, Russell King, linux-csky, Ingo Molnar, David Airlie,
VMware Graphics, Mel Gorman, nouveau, Dave Airlie, linux-snps-arc,
Ben Skeggs, linux-xtensa, Arnd Bergmann, intel-gfx,
Roland Scheidegger, Josef Bacik, Steven Rostedt, Linus Torvalds,
Alexander Viro, spice-devel, David Sterba, Rodrigo Vivi,
Dietmar Eggemann, linux-arm-kernel, Jani Nikula, Chris Zankel,
Michal Simek, Thomas Bogendoerfer, Nick Hu, Chris Mason,
Vineet Gupta, linux-mips, Christian Koenig, Benjamin LaHaise,
Daniel Vetter, linux-fsdevel, Andrew Morton, linuxppc-dev,
David S. Miller, linux-btrfs, Greentime Hu
In-Reply-To: <20201103092712.714480842@linutronix.de>
Historical leftovers from the time where kmap() had fixed slots.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Benjamin LaHaise <bcrl@kvack.org>
Cc: linux-fsdevel@vger.kernel.org
Cc: linux-aio@kvack.org
Cc: Chris Mason <clm@fb.com>
Cc: Josef Bacik <josef@toxicpanda.com>
Cc: David Sterba <dsterba@suse.com>
Cc: linux-btrfs@vger.kernel.org
---
fs/aio.c | 1 -
fs/btrfs/ctree.h | 1 -
2 files changed, 2 deletions(-)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -43,7 +43,6 @@
#include <linux/mount.h>
#include <linux/pseudo_fs.h>
-#include <asm/kmap_types.h>
#include <linux/uaccess.h>
#include <linux/nospec.h>
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -17,7 +17,6 @@
#include <linux/wait.h>
#include <linux/slab.h>
#include <trace/events/btrfs.h>
-#include <asm/kmap_types.h>
#include <asm/unaligned.h>
#include <linux/pagemap.h>
#include <linux/btrfs.h>
^ permalink raw reply
* [patch V3 01/37] mm/highmem: Un-EXPORT __kmap_atomic_idx()
From: Thomas Gleixner @ 2020-11-03 9:27 UTC (permalink / raw)
To: LKML
Cc: Juri Lelli, linux-aio, Peter Zijlstra, Sebastian Andrzej Siewior,
Joonas Lahtinen, dri-devel, virtualization, Ben Segall,
Chris Mason, Huang Rui, Paul Mackerras, Gerd Hoffmann,
Daniel Bristot de Oliveira, sparclinux, Vincent Chen,
Christoph Hellwig, Vincent Guittot, Paul McKenney, Max Filippov,
x86, Russell King, linux-csky, Ingo Molnar, David Airlie,
VMware Graphics, Mel Gorman, nouveau, Dave Airlie, linux-snps-arc,
Ben Skeggs, linux-xtensa, Arnd Bergmann, intel-gfx,
Roland Scheidegger, Josef Bacik, Steven Rostedt, Linus Torvalds,
Alexander Viro, spice-devel, David Sterba, Rodrigo Vivi,
Dietmar Eggemann, linux-arm-kernel, Jani Nikula, Chris Zankel,
Michal Simek, Thomas Bogendoerfer, Nick Hu, linux-mm,
Vineet Gupta, linux-mips, Christian Koenig, Benjamin LaHaise,
Daniel Vetter, linux-fsdevel, Andrew Morton, linuxppc-dev,
David S. Miller, linux-btrfs, Greentime Hu
In-Reply-To: <20201103092712.714480842@linutronix.de>
Nothing in modules can use that.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: linux-mm@kvack.org
---
mm/highmem.c | 2 --
1 file changed, 2 deletions(-)
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -108,8 +108,6 @@ static inline wait_queue_head_t *get_pkm
atomic_long_t _totalhigh_pages __read_mostly;
EXPORT_SYMBOL(_totalhigh_pages);
-EXPORT_PER_CPU_SYMBOL(__kmap_atomic_idx);
-
unsigned int nr_free_highpages (void)
{
struct zone *zone;
^ permalink raw reply
* [patch V3 02/37] highmem: Remove unused functions
From: Thomas Gleixner @ 2020-11-03 9:27 UTC (permalink / raw)
To: LKML
Cc: Juri Lelli, linux-aio, Peter Zijlstra, Sebastian Andrzej Siewior,
Joonas Lahtinen, dri-devel, virtualization, Ben Segall,
Chris Mason, Huang Rui, Paul Mackerras, Gerd Hoffmann,
Daniel Bristot de Oliveira, sparclinux, Vincent Chen,
Christoph Hellwig, Vincent Guittot, Paul McKenney, Max Filippov,
x86, Russell King, linux-csky, Ingo Molnar, David Airlie,
VMware Graphics, Mel Gorman, nouveau, Dave Airlie, linux-snps-arc,
Ben Skeggs, linux-xtensa, Arnd Bergmann, intel-gfx,
Roland Scheidegger, Josef Bacik, Steven Rostedt, Linus Torvalds,
Alexander Viro, spice-devel, David Sterba, Rodrigo Vivi,
Dietmar Eggemann, linux-arm-kernel, Jani Nikula, Chris Zankel,
Michal Simek, Thomas Bogendoerfer, Nick Hu, linux-mm,
Vineet Gupta, linux-mips, Christian Koenig, Benjamin LaHaise,
Daniel Vetter, linux-fsdevel, Andrew Morton, linuxppc-dev,
David S. Miller, linux-btrfs, Greentime Hu
In-Reply-To: <20201103092712.714480842@linutronix.de>
Nothing uses totalhigh_pages_dec() and totalhigh_pages_set().
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
V3: New patch
---
include/linux/highmem.h | 10 ----------
1 file changed, 10 deletions(-)
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -104,21 +104,11 @@ static inline void totalhigh_pages_inc(v
atomic_long_inc(&_totalhigh_pages);
}
-static inline void totalhigh_pages_dec(void)
-{
- atomic_long_dec(&_totalhigh_pages);
-}
-
static inline void totalhigh_pages_add(long count)
{
atomic_long_add(count, &_totalhigh_pages);
}
-static inline void totalhigh_pages_set(long val)
-{
- atomic_long_set(&_totalhigh_pages, val);
-}
-
void kmap_flush_unused(void);
struct page *kmap_to_page(void *addr);
^ permalink raw reply
* Re: [PATCH 11/11 v2] ftrace: Add recording of functions that caused recursion
From: Petr Mladek @ 2020-11-03 10:40 UTC (permalink / raw)
To: Steven Rostedt
Cc: Anton Vorontsov, linux-doc, Peter Zijlstra,
Sebastian Andrzej Siewior, Kamalesh Babulal, James E.J. Bottomley,
Guo Ren, H. Peter Anvin, live-patching, Miroslav Benes,
Ingo Molnar, linux-s390, Joe Lawrence, Jonathan Corbet,
Mauro Carvalho Chehab, Helge Deller, x86, linux-csky,
Christian Borntraeger, Kees Cook, Vasily Gorbik, Heiko Carstens,
Jiri Kosina, Borislav Petkov, Josh Poimboeuf, Thomas Gleixner,
Tony Luck, linux-parisc, linux-kernel, Masami Hiramatsu,
Colin Cross, Paul Mackerras, Andrew Morton, linuxppc-dev
In-Reply-To: <20201102120907.457ad2f7@gandalf.local.home>
On Mon 2020-11-02 12:09:07, Steven Rostedt wrote:
> On Mon, 2 Nov 2020 17:41:47 +0100
> Petr Mladek <pmladek@suse.com> wrote:
>
> > On Fri 2020-10-30 17:31:53, Steven Rostedt wrote:
> > > From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>
> > >
> > > This adds CONFIG_FTRACE_RECORD_RECURSION that will record to a file
> > > "recursed_functions" all the functions that caused recursion while a
> > > callback to the function tracer was running.
> > >
> >
> > > --- /dev/null
> > > +++ b/kernel/trace/trace_recursion_record.c
> > > + if (index >= CONFIG_FTRACE_RECORD_RECURSION_SIZE)
> > > + return;
> > > +
> > > + for (i = index - 1; i >= 0; i--) {
> > > + if (recursed_functions[i].ip == ip) {
> > > + cached_function = ip;
> > > + return;
> > > + }
> > > + }
> > > +
> > > + cached_function = ip;
> > > +
> > > + /*
> > > + * We only want to add a function if it hasn't been added before.
> > > + * Add to the current location before incrementing the count.
> > > + * If it fails to add, then increment the index (save in i)
> > > + * and try again.
> > > + */
> > > + old = cmpxchg(&recursed_functions[index].ip, 0, ip);
> > > + if (old != 0) {
> > > + /* Did something else already added this for us? */
> > > + if (old == ip)
> > > + return;
> > > + /* Try the next location (use i for the next index) */
> > > + i = index + 1;
> >
> > What about
> >
> > index++;
> >
> > We basically want to run the code again with index + 1 limit.
>
> But something else could update nr_records, and we want to use that if
> nr_records is greater than i.
>
> Now, we could swap the use case, and have
>
> int index = 0;
>
> [..]
> i = atomic_read(&nr_records);
> if (i > index)
> index = i;
>
> [..]
>
> index++;
> goto again;
>
>
> >
> > Maybe, it even does not make sense to check the array again
> > and we should just try to store the value into the next slot.
>
> We do this dance to prevent duplicates.
I see.
My code was wrong. It reserved slot for the new "ip" by cmpxchg
on nr_records. The "ip" was stored later so that any parallel
call need not see that it is a dumplicate.
Your code reserves the slot by cmpxchg of "ip".
Any parallel call would fail to take the slot and see
the "ip" in the next iteration.
Best Regards,
Petr
^ permalink raw reply
* Re: [RESEND PATCH] kernel/watchdog: Fix watchdog_allowed_mask not used warning
From: Petr Mladek @ 2020-11-03 10:15 UTC (permalink / raw)
To: Santosh Sivaraj
Cc: Linux Kernel, bala24, Thomas Gleixner, linuxppc-dev,
Andrew Morton
In-Reply-To: <214be993-96ec-82b0-b841-c80f7e7faefb@csgroup.eu>
On Tue 2020-11-03 10:55:11, Christophe Leroy wrote:
>
>
> Le 03/11/2020 à 10:32, Santosh Sivaraj a écrit :
> > Define watchdog_allowed_mask only when SOFTLOCKUP_DETECTOR is enabled.
> >
> > Signed-off-by: Santosh Sivaraj <santosh@fossix.org>
>
> I think maybe you should add a Fixes: tag (Towards https://github.com/linuxppc/linux/commit/7feeb9cd ?)
>
> And copy Thomas (tglx)
And also Andrew that usually take patches in this area.
Finally, you should add my Reviewed-by that I provided for the first
resend. Sigh, I have missed that the important people were not in CC.
Best Regards,
Petr
> Christophe
>
> > ---
> >
> > Original patch is here:
> > https://lore.kernel.org/lkml/20190807014417.9418-1-santosh@fossix.org/
> >
> > A similar patch was also sent by Balamuruhan and reviewed by Petr.
> > https://lkml.org/lkml/2020/8/20/1030
> >
> > kernel/watchdog.c | 4 ++--
> > 1 file changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/kernel/watchdog.c b/kernel/watchdog.c
> > index 5abb5b22ad13..71109065bd8e 100644
> > --- a/kernel/watchdog.c
> > +++ b/kernel/watchdog.c
> > @@ -44,8 +44,6 @@ int __read_mostly soft_watchdog_user_enabled = 1;
> > int __read_mostly watchdog_thresh = 10;
> > static int __read_mostly nmi_watchdog_available;
> > -static struct cpumask watchdog_allowed_mask __read_mostly;
> > -
> > struct cpumask watchdog_cpumask __read_mostly;
> > unsigned long *watchdog_cpumask_bits = cpumask_bits(&watchdog_cpumask);
> > @@ -162,6 +160,8 @@ static void lockup_detector_update_enable(void)
> > int __read_mostly sysctl_softlockup_all_cpu_backtrace;
> > #endif
> > +static struct cpumask watchdog_allowed_mask __read_mostly;
> > +
> > /* Global variables, exported for sysctl */
> > unsigned int __read_mostly softlockup_panic =
> > CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE;
> >
^ permalink raw reply
* Re: [RESEND PATCH] kernel/watchdog: Fix watchdog_allowed_mask not used warning
From: Christophe Leroy @ 2020-11-03 9:55 UTC (permalink / raw)
To: Santosh Sivaraj, Linux Kernel, Michael Ellerman, linuxppc-dev
Cc: pmladek, Thomas Gleixner, bala24
In-Reply-To: <20201103093235.655665-1-santosh@fossix.org>
Le 03/11/2020 à 10:32, Santosh Sivaraj a écrit :
> Define watchdog_allowed_mask only when SOFTLOCKUP_DETECTOR is enabled.
>
> Signed-off-by: Santosh Sivaraj <santosh@fossix.org>
I think maybe you should add a Fixes: tag (Towards https://github.com/linuxppc/linux/commit/7feeb9cd ?)
And copy Thomas (tglx)
Christophe
> ---
>
> Original patch is here:
> https://lore.kernel.org/lkml/20190807014417.9418-1-santosh@fossix.org/
>
> A similar patch was also sent by Balamuruhan and reviewed by Petr.
> https://lkml.org/lkml/2020/8/20/1030
>
> kernel/watchdog.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/kernel/watchdog.c b/kernel/watchdog.c
> index 5abb5b22ad13..71109065bd8e 100644
> --- a/kernel/watchdog.c
> +++ b/kernel/watchdog.c
> @@ -44,8 +44,6 @@ int __read_mostly soft_watchdog_user_enabled = 1;
> int __read_mostly watchdog_thresh = 10;
> static int __read_mostly nmi_watchdog_available;
>
> -static struct cpumask watchdog_allowed_mask __read_mostly;
> -
> struct cpumask watchdog_cpumask __read_mostly;
> unsigned long *watchdog_cpumask_bits = cpumask_bits(&watchdog_cpumask);
>
> @@ -162,6 +160,8 @@ static void lockup_detector_update_enable(void)
> int __read_mostly sysctl_softlockup_all_cpu_backtrace;
> #endif
>
> +static struct cpumask watchdog_allowed_mask __read_mostly;
> +
> /* Global variables, exported for sysctl */
> unsigned int __read_mostly softlockup_panic =
> CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE;
>
^ permalink raw reply
* [RESEND PATCH] kernel/watchdog: Fix watchdog_allowed_mask not used warning
From: Santosh Sivaraj @ 2020-11-03 9:32 UTC (permalink / raw)
To: Linux Kernel, Michael Ellerman, linuxppc-dev
Cc: pmladek, Santosh Sivaraj, bala24
Define watchdog_allowed_mask only when SOFTLOCKUP_DETECTOR is enabled.
Signed-off-by: Santosh Sivaraj <santosh@fossix.org>
---
Original patch is here:
https://lore.kernel.org/lkml/20190807014417.9418-1-santosh@fossix.org/
A similar patch was also sent by Balamuruhan and reviewed by Petr.
https://lkml.org/lkml/2020/8/20/1030
kernel/watchdog.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index 5abb5b22ad13..71109065bd8e 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -44,8 +44,6 @@ int __read_mostly soft_watchdog_user_enabled = 1;
int __read_mostly watchdog_thresh = 10;
static int __read_mostly nmi_watchdog_available;
-static struct cpumask watchdog_allowed_mask __read_mostly;
-
struct cpumask watchdog_cpumask __read_mostly;
unsigned long *watchdog_cpumask_bits = cpumask_bits(&watchdog_cpumask);
@@ -162,6 +160,8 @@ static void lockup_detector_update_enable(void)
int __read_mostly sysctl_softlockup_all_cpu_backtrace;
#endif
+static struct cpumask watchdog_allowed_mask __read_mostly;
+
/* Global variables, exported for sysctl */
unsigned int __read_mostly softlockup_panic =
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE;
--
2.26.2
^ permalink raw reply related
* Re: [PATCH v1 4/4] powernv/memtrace: don't abuse memory hot(un)plug infrastructure for memory allocations
From: David Hildenbrand @ 2020-11-03 9:29 UTC (permalink / raw)
To: Michal Hocko
Cc: Wei Yang, linux-kernel, linux-mm, Paul Mackerras, Rashmica Gupta,
linuxppc-dev, Andrew Morton, Mike Rapoport, Oscar Salvador
In-Reply-To: <20201103092309.GD21990@dhcp22.suse.cz>
On 03.11.20 10:23, Michal Hocko wrote:
> On Thu 29-10-20 17:27:18, David Hildenbrand wrote:
>> Let's use alloc_contig_pages() for allocating memory and remove the
>> linear mapping manually via arch_remove_linear_mapping(). Mark all pages
>> PG_offline, such that they will definitely not get touched - e.g.,
>> when hibernating. When freeing memory, try to revert what we did.
>>
>> The original idea was discussed in:
>> https://lkml.kernel.org/r/48340e96-7e6b-736f-9e23-d3111b915b6e@redhat.com
>>
>> This is similar to CONFIG_DEBUG_PAGEALLOC handling on other
>> architectures, whereby only single pages are unmapped from the linear
>> mapping. Let's mimic what memory hot(un)plug would do with the linear
>> mapping.
>>
>> We now need MEMORY_HOTPLUG and CONTIG_ALLOC as dependencies.
>>
>> Simple test under QEMU TCG (10GB RAM, single NUMA node):
>>
>> sh-5.0# mount -t debugfs none /sys/kernel/debug/
>> sh-5.0# cat /sys/devices/system/memory/block_size_bytes
>> 40000000
>> sh-5.0# echo 0x40000000 > /sys/kernel/debug/powerpc/memtrace/enable
>> [ 71.052836][ T356] memtrace: Allocated trace memory on node 0 at 0x0000000080000000
>> sh-5.0# echo 0x80000000 > /sys/kernel/debug/powerpc/memtrace/enable
>> [ 75.424302][ T356] radix-mmu: Mapped 0x0000000080000000-0x00000000c0000000 with 64.0 KiB pages
>> [ 75.430549][ T356] memtrace: Freed trace memory back on node 0
>> [ 75.604520][ T356] memtrace: Allocated trace memory on node 0 at 0x0000000080000000
>> sh-5.0# echo 0x100000000 > /sys/kernel/debug/powerpc/memtrace/enable
>> [ 80.418835][ T356] radix-mmu: Mapped 0x0000000080000000-0x0000000100000000 with 64.0 KiB pages
>> [ 80.430493][ T356] memtrace: Freed trace memory back on node 0
>> [ 80.433882][ T356] memtrace: Failed to allocate trace memory on node 0
>> sh-5.0# echo 0x40000000 > /sys/kernel/debug/powerpc/memtrace/enable
>> [ 91.920158][ T356] memtrace: Allocated trace memory on node 0 at 0x0000000080000000
>>
>> Note 1: We currently won't be allocating from ZONE_MOVABLE - because our
>> pages are not movable. However, as we don't run with any memory
>> hot(un)plug mechanism around, we could make an exception to
>> increase the chance of allocations succeeding.
>>
>> Note 2: PG_reserved isn't sufficient. E.g., kernel_page_present() used
>> along PG_reserved in hibernation code will always return "true"
>> on powerpc, resulting in the pages getting touched. It's too
>> generic - e.g., indicates boot allocations.
>>
>> Note 3: For now, we keep using memory_block_size_bytes() as minimum
>> granularity. I'm not able to come up with a better guess (most
>> probably, doing it on a section basis could be possible).
>>
>> Suggested-by: Michal Hocko <mhocko@kernel.org>
>> Cc: Michael Ellerman <mpe@ellerman.id.au>
>> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>> Cc: Paul Mackerras <paulus@samba.org>
>> Cc: Rashmica Gupta <rashmica.g@gmail.com>
>> Cc: Andrew Morton <akpm@linux-foundation.org>
>> Cc: Mike Rapoport <rppt@kernel.org>
>> Cc: Michal Hocko <mhocko@suse.com>
>> Cc: Oscar Salvador <osalvador@suse.de>
>> Cc: Wei Yang <richard.weiyang@linux.alibaba.com>
>> Signed-off-by: David Hildenbrand <david@redhat.com>
>
> Thanks! This looks like a move into the right direction. I cannot really
> judge implementation details because I am not familiar with the code.
> I have only one tiny concern:
> [...]
>> -/* called with device_hotplug_lock held */
>> -static bool memtrace_offline_pages(u32 nid, u64 start_pfn, u64 nr_pages)
>> +static u64 memtrace_alloc_node(u32 nid, u64 size)
>> {
>> - const unsigned long start = PFN_PHYS(start_pfn);
>> - const unsigned long size = PFN_PHYS(nr_pages);
>> + const unsigned long nr_pages = PHYS_PFN(size);
>> + unsigned long pfn, start_pfn;
>> + struct page *page;
>>
>> - if (walk_memory_blocks(start, size, NULL, check_memblock_online))
>> - return false;
>> -
>> - walk_memory_blocks(start, size, (void *)MEM_GOING_OFFLINE,
>> - change_memblock_state);
>> -
>> - if (offline_pages(start_pfn, nr_pages)) {
>> - walk_memory_blocks(start, size, (void *)MEM_ONLINE,
>> - change_memblock_state);
>> - return false;
>> - }
>> + /*
>> + * Trace memory needs to be aligned to the size, which is guaranteed
>> + * by alloc_contig_pages().
>> + */
>> + page = alloc_contig_pages(nr_pages, __GFP_THISNODE | __GFP_NOWARN,
>> + nid, NULL);
>
> __GFP_THISNODE without other modifiers looks suspicious. I suspect you
> want to enfore node locality and exclude movable zones by this. While
> this works it is an antipattern. I would rather use GFP_KERNEL |
> __GFP_THISNODE | __GFP_NOWARN to be more in line with other gfp usage.
Agreed GFP_KERNEL should be the right thing to do here.
>
> If for no other reasons we want to be able to work inside a normal
> compaction context (comparing to effectively GFP_NOIO which the above
> implies). Also this looks like a sleepable context.
>
Yes it is. Thanks!
--
Thanks,
David / dhildenb
^ permalink raw reply
* Re: [PATCH v1 4/4] powernv/memtrace: don't abuse memory hot(un)plug infrastructure for memory allocations
From: Michal Hocko @ 2020-11-03 9:23 UTC (permalink / raw)
To: David Hildenbrand
Cc: Wei Yang, linux-kernel, linux-mm, Paul Mackerras, Rashmica Gupta,
linuxppc-dev, Andrew Morton, Mike Rapoport, Oscar Salvador
In-Reply-To: <20201029162718.29910-5-david@redhat.com>
On Thu 29-10-20 17:27:18, David Hildenbrand wrote:
> Let's use alloc_contig_pages() for allocating memory and remove the
> linear mapping manually via arch_remove_linear_mapping(). Mark all pages
> PG_offline, such that they will definitely not get touched - e.g.,
> when hibernating. When freeing memory, try to revert what we did.
>
> The original idea was discussed in:
> https://lkml.kernel.org/r/48340e96-7e6b-736f-9e23-d3111b915b6e@redhat.com
>
> This is similar to CONFIG_DEBUG_PAGEALLOC handling on other
> architectures, whereby only single pages are unmapped from the linear
> mapping. Let's mimic what memory hot(un)plug would do with the linear
> mapping.
>
> We now need MEMORY_HOTPLUG and CONTIG_ALLOC as dependencies.
>
> Simple test under QEMU TCG (10GB RAM, single NUMA node):
>
> sh-5.0# mount -t debugfs none /sys/kernel/debug/
> sh-5.0# cat /sys/devices/system/memory/block_size_bytes
> 40000000
> sh-5.0# echo 0x40000000 > /sys/kernel/debug/powerpc/memtrace/enable
> [ 71.052836][ T356] memtrace: Allocated trace memory on node 0 at 0x0000000080000000
> sh-5.0# echo 0x80000000 > /sys/kernel/debug/powerpc/memtrace/enable
> [ 75.424302][ T356] radix-mmu: Mapped 0x0000000080000000-0x00000000c0000000 with 64.0 KiB pages
> [ 75.430549][ T356] memtrace: Freed trace memory back on node 0
> [ 75.604520][ T356] memtrace: Allocated trace memory on node 0 at 0x0000000080000000
> sh-5.0# echo 0x100000000 > /sys/kernel/debug/powerpc/memtrace/enable
> [ 80.418835][ T356] radix-mmu: Mapped 0x0000000080000000-0x0000000100000000 with 64.0 KiB pages
> [ 80.430493][ T356] memtrace: Freed trace memory back on node 0
> [ 80.433882][ T356] memtrace: Failed to allocate trace memory on node 0
> sh-5.0# echo 0x40000000 > /sys/kernel/debug/powerpc/memtrace/enable
> [ 91.920158][ T356] memtrace: Allocated trace memory on node 0 at 0x0000000080000000
>
> Note 1: We currently won't be allocating from ZONE_MOVABLE - because our
> pages are not movable. However, as we don't run with any memory
> hot(un)plug mechanism around, we could make an exception to
> increase the chance of allocations succeeding.
>
> Note 2: PG_reserved isn't sufficient. E.g., kernel_page_present() used
> along PG_reserved in hibernation code will always return "true"
> on powerpc, resulting in the pages getting touched. It's too
> generic - e.g., indicates boot allocations.
>
> Note 3: For now, we keep using memory_block_size_bytes() as minimum
> granularity. I'm not able to come up with a better guess (most
> probably, doing it on a section basis could be possible).
>
> Suggested-by: Michal Hocko <mhocko@kernel.org>
> Cc: Michael Ellerman <mpe@ellerman.id.au>
> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Cc: Paul Mackerras <paulus@samba.org>
> Cc: Rashmica Gupta <rashmica.g@gmail.com>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Cc: Mike Rapoport <rppt@kernel.org>
> Cc: Michal Hocko <mhocko@suse.com>
> Cc: Oscar Salvador <osalvador@suse.de>
> Cc: Wei Yang <richard.weiyang@linux.alibaba.com>
> Signed-off-by: David Hildenbrand <david@redhat.com>
Thanks! This looks like a move into the right direction. I cannot really
judge implementation details because I am not familiar with the code.
I have only one tiny concern:
[...]
> -/* called with device_hotplug_lock held */
> -static bool memtrace_offline_pages(u32 nid, u64 start_pfn, u64 nr_pages)
> +static u64 memtrace_alloc_node(u32 nid, u64 size)
> {
> - const unsigned long start = PFN_PHYS(start_pfn);
> - const unsigned long size = PFN_PHYS(nr_pages);
> + const unsigned long nr_pages = PHYS_PFN(size);
> + unsigned long pfn, start_pfn;
> + struct page *page;
>
> - if (walk_memory_blocks(start, size, NULL, check_memblock_online))
> - return false;
> -
> - walk_memory_blocks(start, size, (void *)MEM_GOING_OFFLINE,
> - change_memblock_state);
> -
> - if (offline_pages(start_pfn, nr_pages)) {
> - walk_memory_blocks(start, size, (void *)MEM_ONLINE,
> - change_memblock_state);
> - return false;
> - }
> + /*
> + * Trace memory needs to be aligned to the size, which is guaranteed
> + * by alloc_contig_pages().
> + */
> + page = alloc_contig_pages(nr_pages, __GFP_THISNODE | __GFP_NOWARN,
> + nid, NULL);
__GFP_THISNODE without other modifiers looks suspicious. I suspect you
want to enfore node locality and exclude movable zones by this. While
this works it is an antipattern. I would rather use GFP_KERNEL |
__GFP_THISNODE | __GFP_NOWARN to be more in line with other gfp usage.
If for no other reasons we want to be able to work inside a normal
compaction context (comparing to effectively GFP_NOIO which the above
implies). Also this looks like a sleepable context.
--
Michal Hocko
SUSE Labs
^ permalink raw reply
* Re: [PATCH] powerpc/32s: Setup the early hash table at all time.
From: Andreas Schwab @ 2020-11-03 8:56 UTC (permalink / raw)
To: Christophe Leroy; +Cc: Paul Mackerras, linuxppc-dev, linux-kernel
In-Reply-To: <1f8494cd-36db-e3a2-8ea4-28fb976468e7@csgroup.eu>
On Nov 03 2020, Christophe Leroy wrote:
> Would you mind checking that with that patch reverted, you are able to
> boot a kernel built with CONFIG_KASAN ?
That doesn't exist.
Andreas.
--
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510 2552 DF73 E780 A9DA AEC1
"And now for something completely different."
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox