xref: /openbmc/linux/arch/x86/include/asm/kmsan.h (revision 4ca8cc8d)
1*4ca8cc8dSAlexander Potapenko /* SPDX-License-Identifier: GPL-2.0 */
2*4ca8cc8dSAlexander Potapenko /*
3*4ca8cc8dSAlexander Potapenko  * x86 KMSAN support.
4*4ca8cc8dSAlexander Potapenko  *
5*4ca8cc8dSAlexander Potapenko  * Copyright (C) 2022, Google LLC
6*4ca8cc8dSAlexander Potapenko  * Author: Alexander Potapenko <glider@google.com>
7*4ca8cc8dSAlexander Potapenko  */
8*4ca8cc8dSAlexander Potapenko 
9*4ca8cc8dSAlexander Potapenko #ifndef _ASM_X86_KMSAN_H
10*4ca8cc8dSAlexander Potapenko #define _ASM_X86_KMSAN_H
11*4ca8cc8dSAlexander Potapenko 
12*4ca8cc8dSAlexander Potapenko #ifndef MODULE
13*4ca8cc8dSAlexander Potapenko 
14*4ca8cc8dSAlexander Potapenko #include <asm/processor.h>
15*4ca8cc8dSAlexander Potapenko #include <linux/mmzone.h>
16*4ca8cc8dSAlexander Potapenko 
17*4ca8cc8dSAlexander Potapenko /*
18*4ca8cc8dSAlexander Potapenko  * Taken from arch/x86/mm/physaddr.h to avoid using an instrumented version.
19*4ca8cc8dSAlexander Potapenko  */
20*4ca8cc8dSAlexander Potapenko static inline bool kmsan_phys_addr_valid(unsigned long addr)
21*4ca8cc8dSAlexander Potapenko {
22*4ca8cc8dSAlexander Potapenko 	if (IS_ENABLED(CONFIG_PHYS_ADDR_T_64BIT))
23*4ca8cc8dSAlexander Potapenko 		return !(addr >> boot_cpu_data.x86_phys_bits);
24*4ca8cc8dSAlexander Potapenko 	else
25*4ca8cc8dSAlexander Potapenko 		return true;
26*4ca8cc8dSAlexander Potapenko }
27*4ca8cc8dSAlexander Potapenko 
28*4ca8cc8dSAlexander Potapenko /*
29*4ca8cc8dSAlexander Potapenko  * Taken from arch/x86/mm/physaddr.c to avoid using an instrumented version.
30*4ca8cc8dSAlexander Potapenko  */
31*4ca8cc8dSAlexander Potapenko static inline bool kmsan_virt_addr_valid(void *addr)
32*4ca8cc8dSAlexander Potapenko {
33*4ca8cc8dSAlexander Potapenko 	unsigned long x = (unsigned long)addr;
34*4ca8cc8dSAlexander Potapenko 	unsigned long y = x - __START_KERNEL_map;
35*4ca8cc8dSAlexander Potapenko 
36*4ca8cc8dSAlexander Potapenko 	/* use the carry flag to determine if x was < __START_KERNEL_map */
37*4ca8cc8dSAlexander Potapenko 	if (unlikely(x > y)) {
38*4ca8cc8dSAlexander Potapenko 		x = y + phys_base;
39*4ca8cc8dSAlexander Potapenko 
40*4ca8cc8dSAlexander Potapenko 		if (y >= KERNEL_IMAGE_SIZE)
41*4ca8cc8dSAlexander Potapenko 			return false;
42*4ca8cc8dSAlexander Potapenko 	} else {
43*4ca8cc8dSAlexander Potapenko 		x = y + (__START_KERNEL_map - PAGE_OFFSET);
44*4ca8cc8dSAlexander Potapenko 
45*4ca8cc8dSAlexander Potapenko 		/* carry flag will be set if starting x was >= PAGE_OFFSET */
46*4ca8cc8dSAlexander Potapenko 		if ((x > y) || !kmsan_phys_addr_valid(x))
47*4ca8cc8dSAlexander Potapenko 			return false;
48*4ca8cc8dSAlexander Potapenko 	}
49*4ca8cc8dSAlexander Potapenko 
50*4ca8cc8dSAlexander Potapenko 	return pfn_valid(x >> PAGE_SHIFT);
51*4ca8cc8dSAlexander Potapenko }
52*4ca8cc8dSAlexander Potapenko 
53*4ca8cc8dSAlexander Potapenko #endif /* !MODULE */
54*4ca8cc8dSAlexander Potapenko 
55*4ca8cc8dSAlexander Potapenko #endif /* _ASM_X86_KMSAN_H */
56