Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
57c8a661 | 2 | #include <linux/memblock.h> |
78c86e5e | 3 | #include <linux/mmdebug.h> |
4b599fed | 4 | #include <linux/export.h> |
78c86e5e JF |
5 | #include <linux/mm.h> |
6 | ||
7 | #include <asm/page.h> | |
8 | ||
9 | #include "physaddr.h" | |
10 | ||
11 | #ifdef CONFIG_X86_64 | |
12 | ||
0bdf525f | 13 | #ifdef CONFIG_DEBUG_VIRTUAL |
78c86e5e JF |
14 | unsigned long __phys_addr(unsigned long x) |
15 | { | |
0bdf525f AD |
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); | |
78c86e5e | 23 | } else { |
0bdf525f AD |
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)); | |
78c86e5e | 28 | } |
0bdf525f | 29 | |
78c86e5e JF |
30 | return x; |
31 | } | |
32 | EXPORT_SYMBOL(__phys_addr); | |
7d74275d AD |
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); | |
0bdf525f | 44 | #endif |
78c86e5e JF |
45 | |
46 | bool __virt_addr_valid(unsigned long x) | |
47 | { | |
0bdf525f AD |
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) | |
78c86e5e | 55 | return false; |
78c86e5e | 56 | } else { |
0bdf525f AD |
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)) | |
78c86e5e JF |
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 | { | |
a25b9316 | 73 | unsigned long phys_addr = x - PAGE_OFFSET; |
78c86e5e JF |
74 | /* VMALLOC_* aren't constants */ |
75 | VIRTUAL_BUG_ON(x < PAGE_OFFSET); | |
76 | VIRTUAL_BUG_ON(__vmalloc_start_set && is_vmalloc_addr((void *) x)); | |
a25b9316 DH |
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; | |
78c86e5e JF |
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 */ |