linux/arch/x86/mm/physaddr.c
<<
>>
Prefs
   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
  14unsigned 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}
  32EXPORT_SYMBOL(__phys_addr);
  33
  34unsigned 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}
  43EXPORT_SYMBOL(__phys_addr_symbol);
  44#endif
  45
  46bool __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}
  66EXPORT_SYMBOL(__virt_addr_valid);
  67
  68#else
  69
  70#ifdef CONFIG_DEBUG_VIRTUAL
  71unsigned 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}
  84EXPORT_SYMBOL(__phys_addr);
  85#endif
  86
  87bool __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}
  97EXPORT_SYMBOL(__virt_addr_valid);
  98
  99#endif  /* CONFIG_X86_64 */
 100