diff options
author | Laura Abbott <labbott@fedoraproject.org> | 2016-02-05 19:24:47 -0500 |
---|---|---|
committer | Catalin Marinas <catalin.marinas@arm.com> | 2016-02-16 10:40:30 -0500 |
commit | 83863f25e4b8214e994ef8b5647aad614d74b45d (patch) | |
tree | def928e193b847e4035a6d895efafc9f9b881896 /arch/arm64/mm/pageattr.c | |
parent | 132233a759580f5ce9b1bfaac9073e47d03c460d (diff) |
arm64: Add support for ARCH_SUPPORTS_DEBUG_PAGEALLOC
ARCH_SUPPORTS_DEBUG_PAGEALLOC provides a hook to map and unmap
pages for debugging purposes. This requires memory be mapped
with PAGE_SIZE mappings since breaking down larger mappings
at runtime will lead to TLB conflicts. Check if debug_pagealloc
is enabled at runtime and if so, map everyting with PAGE_SIZE
pages. Implement the functions to actually map/unmap the
pages at runtime.
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Laura Abbott <labbott@fedoraproject.org>
[catalin.marinas@arm.com: static annotation block_mappings_allowed() and #ifdef]
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Diffstat (limited to 'arch/arm64/mm/pageattr.c')
-rw-r--r-- | arch/arm64/mm/pageattr.c | 46 |
1 files changed, 36 insertions, 10 deletions
diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c index 0795c3a36d8f..ca6d268e3313 100644 --- a/arch/arm64/mm/pageattr.c +++ b/arch/arm64/mm/pageattr.c | |||
@@ -37,14 +37,31 @@ static int change_page_range(pte_t *ptep, pgtable_t token, unsigned long addr, | |||
37 | return 0; | 37 | return 0; |
38 | } | 38 | } |
39 | 39 | ||
40 | /* | ||
41 | * This function assumes that the range is mapped with PAGE_SIZE pages. | ||
42 | */ | ||
43 | static int __change_memory_common(unsigned long start, unsigned long size, | ||
44 | pgprot_t set_mask, pgprot_t clear_mask) | ||
45 | { | ||
46 | struct page_change_data data; | ||
47 | int ret; | ||
48 | |||
49 | data.set_mask = set_mask; | ||
50 | data.clear_mask = clear_mask; | ||
51 | |||
52 | ret = apply_to_page_range(&init_mm, start, size, change_page_range, | ||
53 | &data); | ||
54 | |||
55 | flush_tlb_kernel_range(start, start + size); | ||
56 | return ret; | ||
57 | } | ||
58 | |||
40 | static int change_memory_common(unsigned long addr, int numpages, | 59 | static int change_memory_common(unsigned long addr, int numpages, |
41 | pgprot_t set_mask, pgprot_t clear_mask) | 60 | pgprot_t set_mask, pgprot_t clear_mask) |
42 | { | 61 | { |
43 | unsigned long start = addr; | 62 | unsigned long start = addr; |
44 | unsigned long size = PAGE_SIZE*numpages; | 63 | unsigned long size = PAGE_SIZE*numpages; |
45 | unsigned long end = start + size; | 64 | unsigned long end = start + size; |
46 | int ret; | ||
47 | struct page_change_data data; | ||
48 | struct vm_struct *area; | 65 | struct vm_struct *area; |
49 | 66 | ||
50 | if (!PAGE_ALIGNED(addr)) { | 67 | if (!PAGE_ALIGNED(addr)) { |
@@ -75,14 +92,7 @@ static int change_memory_common(unsigned long addr, int numpages, | |||
75 | if (!numpages) | 92 | if (!numpages) |
76 | return 0; | 93 | return 0; |
77 | 94 | ||
78 | data.set_mask = set_mask; | 95 | return __change_memory_common(start, size, set_mask, clear_mask); |
79 | data.clear_mask = clear_mask; | ||
80 | |||
81 | ret = apply_to_page_range(&init_mm, start, size, change_page_range, | ||
82 | &data); | ||
83 | |||
84 | flush_tlb_kernel_range(start, end); | ||
85 | return ret; | ||
86 | } | 96 | } |
87 | 97 | ||
88 | int set_memory_ro(unsigned long addr, int numpages) | 98 | int set_memory_ro(unsigned long addr, int numpages) |
@@ -114,3 +124,19 @@ int set_memory_x(unsigned long addr, int numpages) | |||
114 | __pgprot(PTE_PXN)); | 124 | __pgprot(PTE_PXN)); |
115 | } | 125 | } |
116 | EXPORT_SYMBOL_GPL(set_memory_x); | 126 | EXPORT_SYMBOL_GPL(set_memory_x); |
127 | |||
128 | #ifdef CONFIG_DEBUG_PAGEALLOC | ||
129 | void __kernel_map_pages(struct page *page, int numpages, int enable) | ||
130 | { | ||
131 | unsigned long addr = (unsigned long) page_address(page); | ||
132 | |||
133 | if (enable) | ||
134 | __change_memory_common(addr, PAGE_SIZE * numpages, | ||
135 | __pgprot(PTE_VALID), | ||
136 | __pgprot(0)); | ||
137 | else | ||
138 | __change_memory_common(addr, PAGE_SIZE * numpages, | ||
139 | __pgprot(0), | ||
140 | __pgprot(PTE_VALID)); | ||
141 | } | ||
142 | #endif | ||