summaryrefslogtreecommitdiff
path: root/arch/arm/mm/tlb.c
blob: 42359793120b3d33dfbdbbe88cecb321feef6f27 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
// SPDX-License-Identifier: GPL-2.0-only
// Copyright 2024 Google LLC
// Author: Ard Biesheuvel <ardb@google.com>

#include <linux/types.h>
#include <asm/tlbflush.h>

#ifdef CONFIG_CPU_TLB_V4WT
void v4_flush_user_tlb_range(unsigned long, unsigned long, struct vm_area_struct *);
void v4_flush_kern_tlb_range(unsigned long, unsigned long);

struct cpu_tlb_fns v4_tlb_fns __initconst = {
	.flush_user_range	= v4_flush_user_tlb_range,
	.flush_kern_range	= v4_flush_kern_tlb_range,
	.tlb_flags		= v4_tlb_flags,
};
#endif

#ifdef CONFIG_CPU_TLB_V4WB
void v4wb_flush_user_tlb_range(unsigned long, unsigned long, struct vm_area_struct *);
void v4wb_flush_kern_tlb_range(unsigned long, unsigned long);

struct cpu_tlb_fns v4wb_tlb_fns __initconst = {
	.flush_user_range	= v4wb_flush_user_tlb_range,
	.flush_kern_range	= v4wb_flush_kern_tlb_range,
	.tlb_flags		= v4wb_tlb_flags,
};
#endif

#if defined(CONFIG_CPU_TLB_V4WBI) || defined(CONFIG_CPU_TLB_FEROCEON)
void v4wbi_flush_user_tlb_range(unsigned long, unsigned long, struct vm_area_struct *);
void v4wbi_flush_kern_tlb_range(unsigned long, unsigned long);

struct cpu_tlb_fns v4wbi_tlb_fns __initconst = {
	.flush_user_range	= v4wbi_flush_user_tlb_range,
	.flush_kern_range	= v4wbi_flush_kern_tlb_range,
	.tlb_flags		= v4wbi_tlb_flags,
};
#endif

#ifdef CONFIG_CPU_TLB_V6
void v6wbi_flush_user_tlb_range(unsigned long, unsigned long, struct vm_area_struct *);
void v6wbi_flush_kern_tlb_range(unsigned long, unsigned long);

struct cpu_tlb_fns v6wbi_tlb_fns __initconst = {
	.flush_user_range	= v6wbi_flush_user_tlb_range,
	.flush_kern_range	= v6wbi_flush_kern_tlb_range,
	.tlb_flags		= v6wbi_tlb_flags,
};
#endif

#ifdef CONFIG_CPU_TLB_V7
void v7wbi_flush_user_tlb_range(unsigned long, unsigned long, struct vm_area_struct *);
void v7wbi_flush_kern_tlb_range(unsigned long, unsigned long);

struct cpu_tlb_fns v7wbi_tlb_fns __initconst = {
	.flush_user_range	= v7wbi_flush_user_tlb_range,
	.flush_kern_range	= v7wbi_flush_kern_tlb_range,
	.tlb_flags		= IS_ENABLED(CONFIG_SMP) ? v7wbi_tlb_flags_smp
							 : v7wbi_tlb_flags_up,
};

#ifdef CONFIG_SMP_ON_UP
/* This will be run-time patched so the offset better be right */
static_assert(offsetof(struct cpu_tlb_fns, tlb_flags) == 8);

asm("	.pushsection	\".alt.smp.init\", \"a\"		\n" \
    "	.align		2					\n" \
    "	.long		v7wbi_tlb_fns + 8 - .			\n" \
    "	.long "  	__stringify(v7wbi_tlb_flags_up) "	\n" \
    "	.popsection						\n");
#endif
#endif

#ifdef CONFIG_CPU_TLB_FA
void fa_flush_user_tlb_range(unsigned long, unsigned long, struct vm_area_struct *);
void fa_flush_kern_tlb_range(unsigned long, unsigned long);

struct cpu_tlb_fns fa_tlb_fns __initconst = {
	.flush_user_range	= fa_flush_user_tlb_range,
	.flush_kern_range	= fa_flush_kern_tlb_range,
	.tlb_flags		= fa_tlb_flags,
};
#endif