2013-01-23 01:24:30 +04:00
# include <linux/bootmem.h>
2009-09-10 21:09:38 +04:00
# include <linux/mmdebug.h>
# include <linux/module.h>
# include <linux/mm.h>
# include <asm/page.h>
# include "physaddr.h"
# ifdef CONFIG_X86_64
2012-11-17 01:53:51 +04:00
# ifdef CONFIG_DEBUG_VIRTUAL
2009-09-10 21:09:38 +04:00
unsigned long __phys_addr ( unsigned long x )
{
2012-11-17 01:53:51 +04:00
unsigned long y = x - __START_KERNEL_map ;
/* use the carry flag to determine if x was < __START_KERNEL_map */
if ( unlikely ( x > y ) ) {
x = y + phys_base ;
VIRTUAL_BUG_ON ( y > = KERNEL_IMAGE_SIZE ) ;
2009-09-10 21:09:38 +04:00
} else {
2012-11-17 01:53:51 +04:00
x = y + ( __START_KERNEL_map - PAGE_OFFSET ) ;
/* carry flag will be set if starting x was >= PAGE_OFFSET */
VIRTUAL_BUG_ON ( ( x > y ) | | ! phys_addr_valid ( x ) ) ;
2009-09-10 21:09:38 +04:00
}
2012-11-17 01:53:51 +04:00
2009-09-10 21:09:38 +04:00
return x ;
}
EXPORT_SYMBOL ( __phys_addr ) ;
2012-11-17 01:55:46 +04:00
unsigned long __phys_addr_symbol ( unsigned long x )
{
unsigned long y = x - __START_KERNEL_map ;
/* only check upper bounds since lower bounds will trigger carry */
VIRTUAL_BUG_ON ( y > = KERNEL_IMAGE_SIZE ) ;
return y + phys_base ;
}
EXPORT_SYMBOL ( __phys_addr_symbol ) ;
2012-11-17 01:53:51 +04:00
# endif
2009-09-10 21:09:38 +04:00
bool __virt_addr_valid ( unsigned long x )
{
2012-11-17 01:53:51 +04:00
unsigned long y = x - __START_KERNEL_map ;
/* use the carry flag to determine if x was < __START_KERNEL_map */
if ( unlikely ( x > y ) ) {
x = y + phys_base ;
if ( y > = KERNEL_IMAGE_SIZE )
2009-09-10 21:09:38 +04:00
return false ;
} else {
2012-11-17 01:53:51 +04:00
x = y + ( __START_KERNEL_map - PAGE_OFFSET ) ;
/* carry flag will be set if starting x was >= PAGE_OFFSET */
if ( ( x > y ) | | ! phys_addr_valid ( x ) )
2009-09-10 21:09:38 +04:00
return false ;
}
return pfn_valid ( x > > PAGE_SHIFT ) ;
}
EXPORT_SYMBOL ( __virt_addr_valid ) ;
# else
# ifdef CONFIG_DEBUG_VIRTUAL
unsigned long __phys_addr ( unsigned long x )
{
2013-01-23 01:24:30 +04:00
unsigned long phys_addr = x - PAGE_OFFSET ;
2009-09-10 21:09:38 +04:00
/* VMALLOC_* aren't constants */
VIRTUAL_BUG_ON ( x < PAGE_OFFSET ) ;
VIRTUAL_BUG_ON ( __vmalloc_start_set & & is_vmalloc_addr ( ( void * ) x ) ) ;
2013-01-23 01:24:30 +04:00
/* max_low_pfn is set early, but not _that_ early */
if ( max_low_pfn ) {
VIRTUAL_BUG_ON ( ( phys_addr > > PAGE_SHIFT ) > max_low_pfn ) ;
BUG_ON ( slow_virt_to_phys ( ( void * ) x ) ! = phys_addr ) ;
}
return phys_addr ;
2009-09-10 21:09:38 +04:00
}
EXPORT_SYMBOL ( __phys_addr ) ;
# endif
bool __virt_addr_valid ( unsigned long x )
{
if ( x < PAGE_OFFSET )
return false ;
if ( __vmalloc_start_set & & is_vmalloc_addr ( ( void * ) x ) )
return false ;
if ( x > = FIXADDR_START )
return false ;
return pfn_valid ( ( x - PAGE_OFFSET ) > > PAGE_SHIFT ) ;
}
EXPORT_SYMBOL ( __virt_addr_valid ) ;
# endif /* CONFIG_X86_64 */