summaryrefslogtreecommitdiff
path: root/mm/kasan
diff options
context:
space:
mode:
authorPeter Collingbourne <pcc@google.com>2021-06-02 16:52:29 -0700
committerWill Deacon <will@kernel.org>2021-06-04 19:32:21 +0100
commit013bb59dbb7cf876449df860946458a595a96d51 (patch)
tree2c086b293dc8c5d6e33881248aa49b0dbe698808 /mm/kasan
parent7a3b835371883558eb63e069d891bd87f562380d (diff)
arm64: mte: handle tags zeroing at page allocation time
Currently, on an anonymous page fault, the kernel allocates a zeroed page and maps it in user space. If the mapping is tagged (PROT_MTE), set_pte_at() additionally clears the tags. It is, however, more efficient to clear the tags at the same time as zeroing the data on allocation. To avoid clearing the tags on any page (which may not be mapped as tagged), only do this if the vma flags contain VM_MTE. This requires introducing a new GFP flag that is used to determine whether to clear the tags. The DC GZVA instruction with a 0 top byte (and 0 tag) requires top-byte-ignore. Set the TCR_EL1.{TBI1,TBID1} bits irrespective of whether KASAN_HW is enabled. Signed-off-by: Peter Collingbourne <pcc@google.com> Co-developed-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Link: https://linux-review.googlesource.com/id/Id46dc94e30fe11474f7e54f5d65e7658dbdddb26 Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> Reviewed-by: Andrey Konovalov <andreyknvl@gmail.com> Link: https://lore.kernel.org/r/20210602235230.3928842-4-pcc@google.com Signed-off-by: Will Deacon <will@kernel.org>
Diffstat (limited to 'mm/kasan')
-rw-r--r--mm/kasan/hw_tags.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/mm/kasan/hw_tags.c b/mm/kasan/hw_tags.c
index 9d0f6f934016..41fd5326ee0a 100644
--- a/mm/kasan/hw_tags.c
+++ b/mm/kasan/hw_tags.c
@@ -246,7 +246,14 @@ void kasan_alloc_pages(struct page *page, unsigned int order, gfp_t flags)
*/
bool init = !want_init_on_free() && want_init_on_alloc(flags);
- kasan_unpoison_pages(page, order, init);
+ if (flags & __GFP_ZEROTAGS) {
+ int i;
+
+ for (i = 0; i != 1 << order; ++i)
+ tag_clear_highpage(page + i);
+ } else {
+ kasan_unpoison_pages(page, order, init);
+ }
}
void kasan_free_pages(struct page *page, unsigned int order)