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