Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

kasan, page_alloc: allow skipping memory init for HW_TAGS

Add a new GFP flag __GFP_SKIP_ZERO that allows to skip memory
initialization. The flag is only effective with HW_TAGS KASAN.

This flag will be used by vmalloc code for page_alloc allocations backing
vmalloc() mappings in a following patch. The reason to skip memory
initialization for these pages in page_alloc is because vmalloc code will
be initializing them instead.

With the current implementation, when __GFP_SKIP_ZERO is provided,
__GFP_ZEROTAGS is ignored. This doesn't matter, as these two flags are
never provided at the same time. However, if this is changed in the
future, this particular implementation detail can be changed as well.

Link: https://lkml.kernel.org/r/0d53efeff345de7d708e0baa0d8829167772521e.1643047180.git.andreyknvl@google.com
Signed-off-by: Andrey Konovalov <andreyknvl@google.com>
Acked-by: Marco Elver <elver@google.com>
Cc: Alexander Potapenko <glider@google.com>
Cc: Andrey Ryabinin <ryabinin.a.a@gmail.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: Evgenii Stepanov <eugenis@google.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Collingbourne <pcc@google.com>
Cc: Vincenzo Frascino <vincenzo.frascino@arm.com>
Cc: Will Deacon <will@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Andrey Konovalov and committed by
Linus Torvalds
9353ffa6 53ae233c

+24 -8
+11 -7
include/linux/gfp.h
··· 55 55 #define ___GFP_ACCOUNT 0x400000u 56 56 #define ___GFP_ZEROTAGS 0x800000u 57 57 #ifdef CONFIG_KASAN_HW_TAGS 58 - #define ___GFP_SKIP_KASAN_UNPOISON 0x1000000u 59 - #define ___GFP_SKIP_KASAN_POISON 0x2000000u 58 + #define ___GFP_SKIP_ZERO 0x1000000u 59 + #define ___GFP_SKIP_KASAN_UNPOISON 0x2000000u 60 + #define ___GFP_SKIP_KASAN_POISON 0x4000000u 60 61 #else 62 + #define ___GFP_SKIP_ZERO 0 61 63 #define ___GFP_SKIP_KASAN_UNPOISON 0 62 64 #define ___GFP_SKIP_KASAN_POISON 0 63 65 #endif 64 66 #ifdef CONFIG_LOCKDEP 65 - #define ___GFP_NOLOCKDEP 0x4000000u 67 + #define ___GFP_NOLOCKDEP 0x8000000u 66 68 #else 67 69 #define ___GFP_NOLOCKDEP 0 68 70 #endif ··· 241 239 * %__GFP_ZERO returns a zeroed page on success. 242 240 * 243 241 * %__GFP_ZEROTAGS zeroes memory tags at allocation time if the memory itself 244 - * is being zeroed (either via __GFP_ZERO or via init_on_alloc). This flag is 245 - * intended for optimization: setting memory tags at the same time as zeroing 246 - * memory has minimal additional performace impact. 242 + * is being zeroed (either via __GFP_ZERO or via init_on_alloc, provided that 243 + * __GFP_SKIP_ZERO is not set). This flag is intended for optimization: setting 244 + * memory tags at the same time as zeroing memory has minimal additional 245 + * performace impact. 247 246 * 248 247 * %__GFP_SKIP_KASAN_UNPOISON makes KASAN skip unpoisoning on page allocation. 249 248 * Only effective in HW_TAGS mode. ··· 256 253 #define __GFP_COMP ((__force gfp_t)___GFP_COMP) 257 254 #define __GFP_ZERO ((__force gfp_t)___GFP_ZERO) 258 255 #define __GFP_ZEROTAGS ((__force gfp_t)___GFP_ZEROTAGS) 256 + #define __GFP_SKIP_ZERO ((__force gfp_t)___GFP_SKIP_ZERO) 259 257 #define __GFP_SKIP_KASAN_UNPOISON ((__force gfp_t)___GFP_SKIP_KASAN_UNPOISON) 260 258 #define __GFP_SKIP_KASAN_POISON ((__force gfp_t)___GFP_SKIP_KASAN_POISON) 261 259 ··· 265 261 266 262 /* Room for N __GFP_FOO bits */ 267 263 #define __GFP_BITS_SHIFT (24 + \ 268 - 2 * IS_ENABLED(CONFIG_KASAN_HW_TAGS) + \ 264 + 3 * IS_ENABLED(CONFIG_KASAN_HW_TAGS) + \ 269 265 IS_ENABLED(CONFIG_LOCKDEP)) 270 266 #define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1)) 271 267
+1
include/trace/events/mmflags.h
··· 53 53 54 54 #ifdef CONFIG_KASAN_HW_TAGS 55 55 #define __def_gfpflag_names_kasan , \ 56 + {(unsigned long)__GFP_SKIP_ZERO, "__GFP_SKIP_ZERO"}, \ 56 57 {(unsigned long)__GFP_SKIP_KASAN_POISON, "__GFP_SKIP_KASAN_POISON"}, \ 57 58 {(unsigned long)__GFP_SKIP_KASAN_UNPOISON, "__GFP_SKIP_KASAN_UNPOISON"} 58 59 #else
+12 -1
mm/page_alloc.c
··· 2363 2363 return init_tags || (flags & __GFP_SKIP_KASAN_UNPOISON); 2364 2364 } 2365 2365 2366 + static inline bool should_skip_init(gfp_t flags) 2367 + { 2368 + /* Don't skip, if hardware tag-based KASAN is not enabled. */ 2369 + if (!kasan_hw_tags_enabled()) 2370 + return false; 2371 + 2372 + /* For hardware tag-based KASAN, skip if requested. */ 2373 + return (flags & __GFP_SKIP_ZERO); 2374 + } 2375 + 2366 2376 inline void post_alloc_hook(struct page *page, unsigned int order, 2367 2377 gfp_t gfp_flags) 2368 2378 { 2369 - bool init = !want_init_on_free() && want_init_on_alloc(gfp_flags); 2379 + bool init = !want_init_on_free() && want_init_on_alloc(gfp_flags) && 2380 + !should_skip_init(gfp_flags); 2370 2381 bool init_tags = init && (gfp_flags & __GFP_ZEROTAGS); 2371 2382 2372 2383 set_page_private(page, 0);