xref: /openbmc/linux/arch/x86/mm/physaddr.c (revision 186525bd)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
257c8a661SMike Rapoport #include <linux/memblock.h>
378c86e5eSJeremy Fitzhardinge #include <linux/mmdebug.h>
44b599fedSPaul Gortmaker #include <linux/export.h>
578c86e5eSJeremy Fitzhardinge #include <linux/mm.h>
678c86e5eSJeremy Fitzhardinge 
778c86e5eSJeremy Fitzhardinge #include <asm/page.h>
8186525bdSIngo Molnar #include <linux/vmalloc.h>
978c86e5eSJeremy Fitzhardinge 
1078c86e5eSJeremy Fitzhardinge #include "physaddr.h"
1178c86e5eSJeremy Fitzhardinge 
1278c86e5eSJeremy Fitzhardinge #ifdef CONFIG_X86_64
1378c86e5eSJeremy Fitzhardinge 
140bdf525fSAlexander Duyck #ifdef CONFIG_DEBUG_VIRTUAL
__phys_addr(unsigned long x)1578c86e5eSJeremy Fitzhardinge unsigned long __phys_addr(unsigned long x)
1678c86e5eSJeremy Fitzhardinge {
170bdf525fSAlexander Duyck 	unsigned long y = x - __START_KERNEL_map;
180bdf525fSAlexander Duyck 
190bdf525fSAlexander Duyck 	/* use the carry flag to determine if x was < __START_KERNEL_map */
200bdf525fSAlexander Duyck 	if (unlikely(x > y)) {
210bdf525fSAlexander Duyck 		x = y + phys_base;
220bdf525fSAlexander Duyck 
230bdf525fSAlexander Duyck 		VIRTUAL_BUG_ON(y >= KERNEL_IMAGE_SIZE);
2478c86e5eSJeremy Fitzhardinge 	} else {
250bdf525fSAlexander Duyck 		x = y + (__START_KERNEL_map - PAGE_OFFSET);
260bdf525fSAlexander Duyck 
270bdf525fSAlexander Duyck 		/* carry flag will be set if starting x was >= PAGE_OFFSET */
280bdf525fSAlexander Duyck 		VIRTUAL_BUG_ON((x > y) || !phys_addr_valid(x));
2978c86e5eSJeremy Fitzhardinge 	}
300bdf525fSAlexander Duyck 
3178c86e5eSJeremy Fitzhardinge 	return x;
3278c86e5eSJeremy Fitzhardinge }
3378c86e5eSJeremy Fitzhardinge EXPORT_SYMBOL(__phys_addr);
347d74275dSAlexander Duyck 
__phys_addr_symbol(unsigned long x)357d74275dSAlexander Duyck unsigned long __phys_addr_symbol(unsigned long x)
367d74275dSAlexander Duyck {
377d74275dSAlexander Duyck 	unsigned long y = x - __START_KERNEL_map;
387d74275dSAlexander Duyck 
397d74275dSAlexander Duyck 	/* only check upper bounds since lower bounds will trigger carry */
407d74275dSAlexander Duyck 	VIRTUAL_BUG_ON(y >= KERNEL_IMAGE_SIZE);
417d74275dSAlexander Duyck 
427d74275dSAlexander Duyck 	return y + phys_base;
437d74275dSAlexander Duyck }
447d74275dSAlexander Duyck EXPORT_SYMBOL(__phys_addr_symbol);
450bdf525fSAlexander Duyck #endif
4678c86e5eSJeremy Fitzhardinge 
__virt_addr_valid(unsigned long x)4778c86e5eSJeremy Fitzhardinge bool __virt_addr_valid(unsigned long x)
4878c86e5eSJeremy Fitzhardinge {
490bdf525fSAlexander Duyck 	unsigned long y = x - __START_KERNEL_map;
500bdf525fSAlexander Duyck 
510bdf525fSAlexander Duyck 	/* use the carry flag to determine if x was < __START_KERNEL_map */
520bdf525fSAlexander Duyck 	if (unlikely(x > y)) {
530bdf525fSAlexander Duyck 		x = y + phys_base;
540bdf525fSAlexander Duyck 
550bdf525fSAlexander Duyck 		if (y >= KERNEL_IMAGE_SIZE)
5678c86e5eSJeremy Fitzhardinge 			return false;
5778c86e5eSJeremy Fitzhardinge 	} else {
580bdf525fSAlexander Duyck 		x = y + (__START_KERNEL_map - PAGE_OFFSET);
590bdf525fSAlexander Duyck 
600bdf525fSAlexander Duyck 		/* carry flag will be set if starting x was >= PAGE_OFFSET */
610bdf525fSAlexander Duyck 		if ((x > y) || !phys_addr_valid(x))
6278c86e5eSJeremy Fitzhardinge 			return false;
6378c86e5eSJeremy Fitzhardinge 	}
6478c86e5eSJeremy Fitzhardinge 
6578c86e5eSJeremy Fitzhardinge 	return pfn_valid(x >> PAGE_SHIFT);
6678c86e5eSJeremy Fitzhardinge }
6778c86e5eSJeremy Fitzhardinge EXPORT_SYMBOL(__virt_addr_valid);
6878c86e5eSJeremy Fitzhardinge 
6978c86e5eSJeremy Fitzhardinge #else
7078c86e5eSJeremy Fitzhardinge 
7178c86e5eSJeremy Fitzhardinge #ifdef CONFIG_DEBUG_VIRTUAL
__phys_addr(unsigned long x)7278c86e5eSJeremy Fitzhardinge unsigned long __phys_addr(unsigned long x)
7378c86e5eSJeremy Fitzhardinge {
74a25b9316SDave Hansen 	unsigned long phys_addr = x - PAGE_OFFSET;
7578c86e5eSJeremy Fitzhardinge 	/* VMALLOC_* aren't constants  */
7678c86e5eSJeremy Fitzhardinge 	VIRTUAL_BUG_ON(x < PAGE_OFFSET);
7778c86e5eSJeremy Fitzhardinge 	VIRTUAL_BUG_ON(__vmalloc_start_set && is_vmalloc_addr((void *) x));
78a25b9316SDave Hansen 	/* max_low_pfn is set early, but not _that_ early */
79a25b9316SDave Hansen 	if (max_low_pfn) {
80a25b9316SDave Hansen 		VIRTUAL_BUG_ON((phys_addr >> PAGE_SHIFT) > max_low_pfn);
81a25b9316SDave Hansen 		BUG_ON(slow_virt_to_phys((void *)x) != phys_addr);
82a25b9316SDave Hansen 	}
83a25b9316SDave Hansen 	return phys_addr;
8478c86e5eSJeremy Fitzhardinge }
8578c86e5eSJeremy Fitzhardinge EXPORT_SYMBOL(__phys_addr);
8678c86e5eSJeremy Fitzhardinge #endif
8778c86e5eSJeremy Fitzhardinge 
__virt_addr_valid(unsigned long x)8878c86e5eSJeremy Fitzhardinge bool __virt_addr_valid(unsigned long x)
8978c86e5eSJeremy Fitzhardinge {
9078c86e5eSJeremy Fitzhardinge 	if (x < PAGE_OFFSET)
9178c86e5eSJeremy Fitzhardinge 		return false;
9278c86e5eSJeremy Fitzhardinge 	if (__vmalloc_start_set && is_vmalloc_addr((void *) x))
9378c86e5eSJeremy Fitzhardinge 		return false;
9478c86e5eSJeremy Fitzhardinge 	if (x >= FIXADDR_START)
9578c86e5eSJeremy Fitzhardinge 		return false;
9678c86e5eSJeremy Fitzhardinge 	return pfn_valid((x - PAGE_OFFSET) >> PAGE_SHIFT);
9778c86e5eSJeremy Fitzhardinge }
9878c86e5eSJeremy Fitzhardinge EXPORT_SYMBOL(__virt_addr_valid);
9978c86e5eSJeremy Fitzhardinge 
10078c86e5eSJeremy Fitzhardinge #endif	/* CONFIG_X86_64 */
101