Commit 629ed3f7 authored by Thomas Gleixner's avatar Thomas Gleixner

xtensa/mm/highmem: Switch to generic kmap atomic

No reason having the same code in every architecture
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Cc: Chris Zankel <chris@zankel.net>
Cc: Max Filippov <jcmvbkbc@gmail.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Link: https://lore.kernel.org/r/20201103095858.311016780@linutronix.de
parent 3293efa9
...@@ -666,6 +666,7 @@ endchoice ...@@ -666,6 +666,7 @@ endchoice
config HIGHMEM config HIGHMEM
bool "High Memory Support" bool "High Memory Support"
depends on MMU depends on MMU
select KMAP_LOCAL
help help
Linux can use the full amount of RAM in the system by Linux can use the full amount of RAM in the system by
default. However, the default MMUv2 setup only maps the default. However, the default MMUv2 setup only maps the
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
#ifdef CONFIG_HIGHMEM #ifdef CONFIG_HIGHMEM
#include <linux/threads.h> #include <linux/threads.h>
#include <linux/pgtable.h> #include <linux/pgtable.h>
#include <asm/kmap_types.h> #include <asm/kmap_size.h>
#endif #endif
/* /*
...@@ -39,7 +39,7 @@ enum fixed_addresses { ...@@ -39,7 +39,7 @@ enum fixed_addresses {
/* reserved pte's for temporary kernel mappings */ /* reserved pte's for temporary kernel mappings */
FIX_KMAP_BEGIN, FIX_KMAP_BEGIN,
FIX_KMAP_END = 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 #endif
__end_of_fixed_addresses __end_of_fixed_addresses
}; };
......
...@@ -16,9 +16,8 @@ ...@@ -16,9 +16,8 @@
#include <linux/pgtable.h> #include <linux/pgtable.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/fixmap.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) (LAST_PKMAP + 1) * PAGE_SIZE) & PMD_MASK)
#define LAST_PKMAP (PTRS_PER_PTE * DCACHE_N_COLORS) #define LAST_PKMAP (PTRS_PER_PTE * DCACHE_N_COLORS)
#define LAST_PKMAP_MASK (LAST_PKMAP - 1) #define LAST_PKMAP_MASK (LAST_PKMAP - 1)
...@@ -68,6 +67,15 @@ static inline void flush_cache_kmaps(void) ...@@ -68,6 +67,15 @@ static inline void flush_cache_kmaps(void)
flush_cache_all(); 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); void kmap_init(void);
#endif #endif
...@@ -12,8 +12,6 @@ ...@@ -12,8 +12,6 @@
#include <linux/highmem.h> #include <linux/highmem.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
static pte_t *kmap_pte;
#if DCACHE_WAY_SIZE > PAGE_SIZE #if DCACHE_WAY_SIZE > PAGE_SIZE
unsigned int last_pkmap_nr_arr[DCACHE_N_COLORS]; unsigned int last_pkmap_nr_arr[DCACHE_N_COLORS];
wait_queue_head_t pkmap_map_wait_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(void) ...@@ -33,59 +31,25 @@ static inline void kmap_waitqueues_init(void)
static inline enum fixed_addresses kmap_idx(int type, unsigned long color) 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; 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; return kmap_idx(type, DCACHE_ALIAS(pfn << PAGE_SHIFT));
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;
} }
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 && return kmap_idx(type, DCACHE_ALIAS(addr));
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();
}
} }
EXPORT_SYMBOL(kunmap_atomic_high);
void __init kmap_init(void) void __init kmap_init(void)
{ {
unsigned long kmap_vstart;
/* Check if this memory layout is broken because PKMAP overlaps /* Check if this memory layout is broken because PKMAP overlaps
* page table. * page table.
*/ */
BUILD_BUG_ON(PKMAP_BASE < TLBTEMP_BASE_1 + TLBTEMP_SIZE); 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(); kmap_waitqueues_init();
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment