Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/x86/include/asm/cacheflush.h
10821 views
1
#ifndef _ASM_X86_CACHEFLUSH_H
2
#define _ASM_X86_CACHEFLUSH_H
3
4
/* Caches aren't brain-dead on the intel. */
5
#include <asm-generic/cacheflush.h>
6
7
#ifdef CONFIG_X86_PAT
8
/*
9
* X86 PAT uses page flags WC and Uncached together to keep track of
10
* memory type of pages that have backing page struct. X86 PAT supports 3
11
* different memory types, _PAGE_CACHE_WB, _PAGE_CACHE_WC and
12
* _PAGE_CACHE_UC_MINUS and fourth state where page's memory type has not
13
* been changed from its default (value of -1 used to denote this).
14
* Note we do not support _PAGE_CACHE_UC here.
15
*/
16
17
#define _PGMT_DEFAULT 0
18
#define _PGMT_WC (1UL << PG_arch_1)
19
#define _PGMT_UC_MINUS (1UL << PG_uncached)
20
#define _PGMT_WB (1UL << PG_uncached | 1UL << PG_arch_1)
21
#define _PGMT_MASK (1UL << PG_uncached | 1UL << PG_arch_1)
22
#define _PGMT_CLEAR_MASK (~_PGMT_MASK)
23
24
static inline unsigned long get_page_memtype(struct page *pg)
25
{
26
unsigned long pg_flags = pg->flags & _PGMT_MASK;
27
28
if (pg_flags == _PGMT_DEFAULT)
29
return -1;
30
else if (pg_flags == _PGMT_WC)
31
return _PAGE_CACHE_WC;
32
else if (pg_flags == _PGMT_UC_MINUS)
33
return _PAGE_CACHE_UC_MINUS;
34
else
35
return _PAGE_CACHE_WB;
36
}
37
38
static inline void set_page_memtype(struct page *pg, unsigned long memtype)
39
{
40
unsigned long memtype_flags = _PGMT_DEFAULT;
41
unsigned long old_flags;
42
unsigned long new_flags;
43
44
switch (memtype) {
45
case _PAGE_CACHE_WC:
46
memtype_flags = _PGMT_WC;
47
break;
48
case _PAGE_CACHE_UC_MINUS:
49
memtype_flags = _PGMT_UC_MINUS;
50
break;
51
case _PAGE_CACHE_WB:
52
memtype_flags = _PGMT_WB;
53
break;
54
}
55
56
do {
57
old_flags = pg->flags;
58
new_flags = (old_flags & _PGMT_CLEAR_MASK) | memtype_flags;
59
} while (cmpxchg(&pg->flags, old_flags, new_flags) != old_flags);
60
}
61
#else
62
static inline unsigned long get_page_memtype(struct page *pg) { return -1; }
63
static inline void set_page_memtype(struct page *pg, unsigned long memtype) { }
64
#endif
65
66
/*
67
* The set_memory_* API can be used to change various attributes of a virtual
68
* address range. The attributes include:
69
* Cachability : UnCached, WriteCombining, WriteBack
70
* Executability : eXeutable, NoteXecutable
71
* Read/Write : ReadOnly, ReadWrite
72
* Presence : NotPresent
73
*
74
* Within a category, the attributes are mutually exclusive.
75
*
76
* The implementation of this API will take care of various aspects that
77
* are associated with changing such attributes, such as:
78
* - Flushing TLBs
79
* - Flushing CPU caches
80
* - Making sure aliases of the memory behind the mapping don't violate
81
* coherency rules as defined by the CPU in the system.
82
*
83
* What this API does not do:
84
* - Provide exclusion between various callers - including callers that
85
* operation on other mappings of the same physical page
86
* - Restore default attributes when a page is freed
87
* - Guarantee that mappings other than the requested one are
88
* in any state, other than that these do not violate rules for
89
* the CPU you have. Do not depend on any effects on other mappings,
90
* CPUs other than the one you have may have more relaxed rules.
91
* The caller is required to take care of these.
92
*/
93
94
int _set_memory_uc(unsigned long addr, int numpages);
95
int _set_memory_wc(unsigned long addr, int numpages);
96
int _set_memory_wb(unsigned long addr, int numpages);
97
int set_memory_uc(unsigned long addr, int numpages);
98
int set_memory_wc(unsigned long addr, int numpages);
99
int set_memory_wb(unsigned long addr, int numpages);
100
int set_memory_x(unsigned long addr, int numpages);
101
int set_memory_nx(unsigned long addr, int numpages);
102
int set_memory_ro(unsigned long addr, int numpages);
103
int set_memory_rw(unsigned long addr, int numpages);
104
int set_memory_np(unsigned long addr, int numpages);
105
int set_memory_4k(unsigned long addr, int numpages);
106
107
int set_memory_array_uc(unsigned long *addr, int addrinarray);
108
int set_memory_array_wc(unsigned long *addr, int addrinarray);
109
int set_memory_array_wb(unsigned long *addr, int addrinarray);
110
111
int set_pages_array_uc(struct page **pages, int addrinarray);
112
int set_pages_array_wc(struct page **pages, int addrinarray);
113
int set_pages_array_wb(struct page **pages, int addrinarray);
114
115
/*
116
* For legacy compatibility with the old APIs, a few functions
117
* are provided that work on a "struct page".
118
* These functions operate ONLY on the 1:1 kernel mapping of the
119
* memory that the struct page represents, and internally just
120
* call the set_memory_* function. See the description of the
121
* set_memory_* function for more details on conventions.
122
*
123
* These APIs should be considered *deprecated* and are likely going to
124
* be removed in the future.
125
* The reason for this is the implicit operation on the 1:1 mapping only,
126
* making this not a generally useful API.
127
*
128
* Specifically, many users of the old APIs had a virtual address,
129
* called virt_to_page() or vmalloc_to_page() on that address to
130
* get a struct page* that the old API required.
131
* To convert these cases, use set_memory_*() on the original
132
* virtual address, do not use these functions.
133
*/
134
135
int set_pages_uc(struct page *page, int numpages);
136
int set_pages_wb(struct page *page, int numpages);
137
int set_pages_x(struct page *page, int numpages);
138
int set_pages_nx(struct page *page, int numpages);
139
int set_pages_ro(struct page *page, int numpages);
140
int set_pages_rw(struct page *page, int numpages);
141
142
143
void clflush_cache_range(void *addr, unsigned int size);
144
145
#ifdef CONFIG_DEBUG_RODATA
146
void mark_rodata_ro(void);
147
extern const int rodata_test_data;
148
extern int kernel_set_to_readonly;
149
void set_kernel_text_rw(void);
150
void set_kernel_text_ro(void);
151
#else
152
static inline void set_kernel_text_rw(void) { }
153
static inline void set_kernel_text_ro(void) { }
154
#endif
155
156
#ifdef CONFIG_DEBUG_RODATA_TEST
157
int rodata_test(void);
158
#else
159
static inline int rodata_test(void)
160
{
161
return 0;
162
}
163
#endif
164
165
#endif /* _ASM_X86_CACHEFLUSH_H */
166
167