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