Skip to content

Commit 39cac19

Browse files
committed
arc/mm/highmem: Use generic kmap atomic implementation
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 <[email protected]> Cc: Vineet Gupta <[email protected]> Cc: Arnd Bergmann <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 157e118 commit 39cac19

File tree

4 files changed

+26
-69
lines changed

4 files changed

+26
-69
lines changed

arch/arc/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,7 @@ config LINUX_RAM_BASE
507507
config HIGHMEM
508508
bool "High Memory Support"
509509
select ARCH_DISCONTIGMEM_ENABLE
510+
select KMAP_LOCAL
510511
help
511512
With ARC 2G:2G address split, only upper 2G is directly addressable by
512513
kernel. Enable this to potentially allow access to rest of 2G and PAE

arch/arc/include/asm/highmem.h

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,29 @@
99
#ifdef CONFIG_HIGHMEM
1010

1111
#include <uapi/asm/page.h>
12-
#include <asm/kmap_types.h>
12+
#include <asm/kmap_size.h>
13+
14+
#define FIXMAP_SIZE PGDIR_SIZE
15+
#define PKMAP_SIZE PGDIR_SIZE
1316

1417
/* start after vmalloc area */
1518
#define FIXMAP_BASE (PAGE_OFFSET - FIXMAP_SIZE - PKMAP_SIZE)
16-
#define FIXMAP_SIZE PGDIR_SIZE /* only 1 PGD worth */
17-
#define KM_TYPE_NR ((FIXMAP_SIZE >> PAGE_SHIFT)/NR_CPUS)
18-
#define FIXMAP_ADDR(nr) (FIXMAP_BASE + ((nr) << PAGE_SHIFT))
19+
20+
#define FIX_KMAP_SLOTS (KM_MAX_IDX * NR_CPUS)
21+
#define FIX_KMAP_BEGIN (0UL)
22+
#define FIX_KMAP_END ((FIX_KMAP_BEGIN + FIX_KMAP_SLOTS) - 1)
23+
24+
#define FIXADDR_TOP (FIXMAP_BASE + (FIX_KMAP_END << PAGE_SHIFT))
25+
26+
/*
27+
* This should be converted to the asm-generic version, but of course this
28+
* is needlessly different from all other architectures. Sigh - tglx
29+
*/
30+
#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
31+
#define __virt_to_fix(x) (((FIXADDR_TOP - ((x) & PAGE_MASK))) >> PAGE_SHIFT)
1932

2033
/* start after fixmap area */
2134
#define PKMAP_BASE (FIXMAP_BASE + FIXMAP_SIZE)
22-
#define PKMAP_SIZE PGDIR_SIZE
2335
#define LAST_PKMAP (PKMAP_SIZE >> PAGE_SHIFT)
2436
#define LAST_PKMAP_MASK (LAST_PKMAP - 1)
2537
#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT))
@@ -29,11 +41,13 @@
2941

3042
extern void kmap_init(void);
3143

44+
#define arch_kmap_local_post_unmap(vaddr) \
45+
local_flush_tlb_kernel_range(vaddr, vaddr + PAGE_SIZE)
46+
3247
static inline void flush_cache_kmaps(void)
3348
{
3449
flush_cache_all();
3550
}
36-
3751
#endif
3852

3953
#endif

arch/arc/include/asm/kmap_types.h

Lines changed: 0 additions & 14 deletions
This file was deleted.

arch/arc/mm/highmem.c

Lines changed: 5 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,8 @@
3636
* This means each only has 1 PGDIR_SIZE worth of kvaddr mappings, which means
3737
* 2M of kvaddr space for typical config (8K page and 11:8:13 traversal split)
3838
*
39-
* - fixmap anyhow needs a limited number of mappings. So 2M kvaddr == 256 PTE
40-
* slots across NR_CPUS would be more than sufficient (generic code defines
41-
* KM_TYPE_NR as 20).
39+
* - The fixed KMAP slots for kmap_local/atomic() require KM_MAX_IDX slots per
40+
* CPU. So the number of CPUs sharing a single PTE page is limited.
4241
*
4342
* - pkmap being preemptible, in theory could do with more than 256 concurrent
4443
* mappings. However, generic pkmap code: map_new_virtual(), doesn't traverse
@@ -47,48 +46,6 @@
4746
*/
4847

4948
extern pte_t * pkmap_page_table;
50-
static pte_t * fixmap_page_table;
51-
52-
void *kmap_atomic_high_prot(struct page *page, pgprot_t prot)
53-
{
54-
int idx, cpu_idx;
55-
unsigned long vaddr;
56-
57-
cpu_idx = kmap_atomic_idx_push();
58-
idx = cpu_idx + KM_TYPE_NR * smp_processor_id();
59-
vaddr = FIXMAP_ADDR(idx);
60-
61-
set_pte_at(&init_mm, vaddr, fixmap_page_table + idx,
62-
mk_pte(page, prot));
63-
64-
return (void *)vaddr;
65-
}
66-
EXPORT_SYMBOL(kmap_atomic_high_prot);
67-
68-
void kunmap_atomic_high(void *kv)
69-
{
70-
unsigned long kvaddr = (unsigned long)kv;
71-
72-
if (kvaddr >= FIXMAP_BASE && kvaddr < (FIXMAP_BASE + FIXMAP_SIZE)) {
73-
74-
/*
75-
* Because preemption is disabled, this vaddr can be associated
76-
* with the current allocated index.
77-
* But in case of multiple live kmap_atomic(), it still relies on
78-
* callers to unmap in right order.
79-
*/
80-
int cpu_idx = kmap_atomic_idx();
81-
int idx = cpu_idx + KM_TYPE_NR * smp_processor_id();
82-
83-
WARN_ON(kvaddr != FIXMAP_ADDR(idx));
84-
85-
pte_clear(&init_mm, kvaddr, fixmap_page_table + idx);
86-
local_flush_tlb_kernel_range(kvaddr, kvaddr + PAGE_SIZE);
87-
88-
kmap_atomic_idx_pop();
89-
}
90-
}
91-
EXPORT_SYMBOL(kunmap_atomic_high);
9249

9350
static noinline pte_t * __init alloc_kmap_pgtable(unsigned long kvaddr)
9451
{
@@ -108,10 +65,9 @@ void __init kmap_init(void)
10865
{
10966
/* Due to recursive include hell, we can't do this in processor.h */
11067
BUILD_BUG_ON(PAGE_OFFSET < (VMALLOC_END + FIXMAP_SIZE + PKMAP_SIZE));
68+
BUILD_BUG_ON(LAST_PKMAP > PTRS_PER_PTE);
69+
BUILD_BUG_ON(FIX_KMAP_SLOTS > PTRS_PER_PTE);
11170

112-
BUILD_BUG_ON(KM_TYPE_NR > PTRS_PER_PTE);
11371
pkmap_page_table = alloc_kmap_pgtable(PKMAP_BASE);
114-
115-
BUILD_BUG_ON(LAST_PKMAP > PTRS_PER_PTE);
116-
fixmap_page_table = alloc_kmap_pgtable(FIXMAP_BASE);
72+
alloc_kmap_pgtable(FIXMAP_BASE);
11773
}

0 commit comments

Comments
 (0)