1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/bootmem.h> 3 #include <linux/mmdebug.h> 4 #include <linux/export.h> 5 #include <linux/mm.h> 6 7 #include <asm/page.h> 8 9 #include "physaddr.h" 10 11 #ifdef CONFIG_X86_64 12 13 #ifdef CONFIG_DEBUG_VIRTUAL 14 unsigned long __phys_addr(unsigned long x) 15 { 16 unsigned long y = x - __START_KERNEL_map; 17 18 /* use the carry flag to determine if x was < __START_KERNEL_map */ 19 if (unlikely(x > y)) { 20 x = y + phys_base; 21 22 VIRTUAL_BUG_ON(y >= KERNEL_IMAGE_SIZE); 23 } else { 24 x = y + (__START_KERNEL_map - PAGE_OFFSET); 25 26 /* carry flag will be set if starting x was >= PAGE_OFFSET */ 27 VIRTUAL_BUG_ON((x > y) || !phys_addr_valid(x)); 28 } 29 30 return x; 31 } 32 EXPORT_SYMBOL(__phys_addr); 33 34 unsigned long __phys_addr_symbol(unsigned long x) 35 { 36 unsigned long y = x - __START_KERNEL_map; 37 38 /* only check upper bounds since lower bounds will trigger carry */ 39 VIRTUAL_BUG_ON(y >= KERNEL_IMAGE_SIZE); 40 41 return y + phys_base; 42 } 43 EXPORT_SYMBOL(__phys_addr_symbol); 44 #endif 45 46 bool __virt_addr_valid(unsigned long x) 47 { 48 unsigned long y = x - __START_KERNEL_map; 49 50 /* use the carry flag to determine if x was < __START_KERNEL_map */ 51 if (unlikely(x > y)) { 52 x = y + phys_base; 53 54 if (y >= KERNEL_IMAGE_SIZE) 55 return false; 56 } else { 57 x = y + (__START_KERNEL_map - PAGE_OFFSET); 58 59 /* carry flag will be set if starting x was >= PAGE_OFFSET */ 60 if ((x > y) || !phys_addr_valid(x)) 61 return false; 62 } 63 64 return pfn_valid(x >> PAGE_SHIFT); 65 } 66 EXPORT_SYMBOL(__virt_addr_valid); 67 68 #else 69 70 #ifdef CONFIG_DEBUG_VIRTUAL 71 unsigned long __phys_addr(unsigned long x) 72 { 73 unsigned long phys_addr = x - PAGE_OFFSET; 74 /* VMALLOC_* aren't constants */ 75 VIRTUAL_BUG_ON(x < PAGE_OFFSET); 76 VIRTUAL_BUG_ON(__vmalloc_start_set && is_vmalloc_addr((void *) x)); 77 /* max_low_pfn is set early, but not _that_ early */ 78 if (max_low_pfn) { 79 VIRTUAL_BUG_ON((phys_addr >> PAGE_SHIFT) > max_low_pfn); 80 BUG_ON(slow_virt_to_phys((void *)x) != phys_addr); 81 } 82 return phys_addr; 83 } 84 EXPORT_SYMBOL(__phys_addr); 85 #endif 86 87 bool __virt_addr_valid(unsigned long x) 88 { 89 if (x < PAGE_OFFSET) 90 return false; 91 if (__vmalloc_start_set && is_vmalloc_addr((void *) x)) 92 return false; 93 if (x >= FIXADDR_START) 94 return false; 95 return pfn_valid((x - PAGE_OFFSET) >> PAGE_SHIFT); 96 } 97 EXPORT_SYMBOL(__virt_addr_valid); 98 99 #endif /* CONFIG_X86_64 */ 100