linux/include/xen/page.h
<<
>>
Prefs
   1#ifndef __XEN_PAGE_H
   2#define __XEN_PAGE_H
   3
   4#include <linux/pfn.h>
   5
   6#include <asm/uaccess.h>
   7#include <asm/pgtable.h>
   8
   9#include <xen/features.h>
  10
  11#ifdef CONFIG_X86_PAE
  12/* Xen machine address */
  13typedef struct xmaddr {
  14        unsigned long long maddr;
  15} xmaddr_t;
  16
  17/* Xen pseudo-physical address */
  18typedef struct xpaddr {
  19        unsigned long long paddr;
  20} xpaddr_t;
  21#else
  22/* Xen machine address */
  23typedef struct xmaddr {
  24        unsigned long maddr;
  25} xmaddr_t;
  26
  27/* Xen pseudo-physical address */
  28typedef struct xpaddr {
  29        unsigned long paddr;
  30} xpaddr_t;
  31#endif
  32
  33#define XMADDR(x)       ((xmaddr_t) { .maddr = (x) })
  34#define XPADDR(x)       ((xpaddr_t) { .paddr = (x) })
  35
  36/**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/
  37#define INVALID_P2M_ENTRY       (~0UL)
  38#define FOREIGN_FRAME_BIT       (1UL<<31)
  39#define FOREIGN_FRAME(m)        ((m) | FOREIGN_FRAME_BIT)
  40
  41extern unsigned long *phys_to_machine_mapping;
  42
  43static inline unsigned long pfn_to_mfn(unsigned long pfn)
  44{
  45        if (xen_feature(XENFEAT_auto_translated_physmap))
  46                return pfn;
  47
  48        return phys_to_machine_mapping[(unsigned int)(pfn)] &
  49                ~FOREIGN_FRAME_BIT;
  50}
  51
  52static inline int phys_to_machine_mapping_valid(unsigned long pfn)
  53{
  54        if (xen_feature(XENFEAT_auto_translated_physmap))
  55                return 1;
  56
  57        return (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY);
  58}
  59
  60static inline unsigned long mfn_to_pfn(unsigned long mfn)
  61{
  62        unsigned long pfn;
  63
  64        if (xen_feature(XENFEAT_auto_translated_physmap))
  65                return mfn;
  66
  67#if 0
  68        if (unlikely((mfn >> machine_to_phys_order) != 0))
  69                return max_mapnr;
  70#endif
  71
  72        pfn = 0;
  73        /*
  74         * The array access can fail (e.g., device space beyond end of RAM).
  75         * In such cases it doesn't matter what we return (we return garbage),
  76         * but we must handle the fault without crashing!
  77         */
  78        __get_user(pfn, &machine_to_phys_mapping[mfn]);
  79
  80        return pfn;
  81}
  82
  83static inline xmaddr_t phys_to_machine(xpaddr_t phys)
  84{
  85        unsigned offset = phys.paddr & ~PAGE_MASK;
  86        return XMADDR(PFN_PHYS((u64)pfn_to_mfn(PFN_DOWN(phys.paddr))) | offset);
  87}
  88
  89static inline xpaddr_t machine_to_phys(xmaddr_t machine)
  90{
  91        unsigned offset = machine.maddr & ~PAGE_MASK;
  92        return XPADDR(PFN_PHYS((u64)mfn_to_pfn(PFN_DOWN(machine.maddr))) | offset);
  93}
  94
  95/*
  96 * We detect special mappings in one of two ways:
  97 *  1. If the MFN is an I/O page then Xen will set the m2p entry
  98 *     to be outside our maximum possible pseudophys range.
  99 *  2. If the MFN belongs to a different domain then we will certainly
 100 *     not have MFN in our p2m table. Conversely, if the page is ours,
 101 *     then we'll have p2m(m2p(MFN))==MFN.
 102 * If we detect a special mapping then it doesn't have a 'struct page'.
 103 * We force !pfn_valid() by returning an out-of-range pointer.
 104 *
 105 * NB. These checks require that, for any MFN that is not in our reservation,
 106 * there is no PFN such that p2m(PFN) == MFN. Otherwise we can get confused if
 107 * we are foreign-mapping the MFN, and the other domain as m2p(MFN) == PFN.
 108 * Yikes! Various places must poke in INVALID_P2M_ENTRY for safety.
 109 *
 110 * NB2. When deliberately mapping foreign pages into the p2m table, you *must*
 111 *      use FOREIGN_FRAME(). This will cause pte_pfn() to choke on it, as we
 112 *      require. In all the cases we care about, the FOREIGN_FRAME bit is
 113 *      masked (e.g., pfn_to_mfn()) so behaviour there is correct.
 114 */
 115static inline unsigned long mfn_to_local_pfn(unsigned long mfn)
 116{
 117        extern unsigned long max_mapnr;
 118        unsigned long pfn = mfn_to_pfn(mfn);
 119        if ((pfn < max_mapnr)
 120            && !xen_feature(XENFEAT_auto_translated_physmap)
 121            && (phys_to_machine_mapping[pfn] != mfn))
 122                return max_mapnr; /* force !pfn_valid() */
 123        return pfn;
 124}
 125
 126static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 127{
 128        if (xen_feature(XENFEAT_auto_translated_physmap)) {
 129                BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
 130                return;
 131        }
 132        phys_to_machine_mapping[pfn] = mfn;
 133}
 134
 135/* VIRT <-> MACHINE conversion */
 136#define virt_to_machine(v)      (phys_to_machine(XPADDR(__pa(v))))
 137#define virt_to_mfn(v)          (pfn_to_mfn(PFN_DOWN(__pa(v))))
 138#define mfn_to_virt(m)          (__va(mfn_to_pfn(m) << PAGE_SHIFT))
 139
 140#ifdef CONFIG_X86_PAE
 141#define pte_mfn(_pte) (((_pte).pte_low >> PAGE_SHIFT) |                 \
 142                       (((_pte).pte_high & 0xfff) << (32-PAGE_SHIFT)))
 143
 144static inline pte_t mfn_pte(unsigned long page_nr, pgprot_t pgprot)
 145{
 146        pte_t pte;
 147
 148        pte.pte_high = (page_nr >> (32 - PAGE_SHIFT)) |
 149                (pgprot_val(pgprot) >> 32);
 150        pte.pte_high &= (__supported_pte_mask >> 32);
 151        pte.pte_low = ((page_nr << PAGE_SHIFT) | pgprot_val(pgprot));
 152        pte.pte_low &= __supported_pte_mask;
 153
 154        return pte;
 155}
 156
 157static inline unsigned long long pte_val_ma(pte_t x)
 158{
 159        return ((unsigned long long)x.pte_high << 32) | x.pte_low;
 160}
 161#define pmd_val_ma(v) ((v).pmd)
 162#define pud_val_ma(v) ((v).pgd.pgd)
 163#define __pte_ma(x)     ((pte_t) { .pte_low = (x), .pte_high = (x)>>32 } )
 164#define __pmd_ma(x)     ((pmd_t) { (x) } )
 165#else  /* !X86_PAE */
 166#define pte_mfn(_pte) ((_pte).pte_low >> PAGE_SHIFT)
 167#define mfn_pte(pfn, prot)      __pte_ma(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
 168#define pte_val_ma(x)   ((x).pte_low)
 169#define pmd_val_ma(v)   ((v).pud.pgd.pgd)
 170#define __pte_ma(x)     ((pte_t) { (x) } )
 171#endif  /* CONFIG_X86_PAE */
 172
 173#define pgd_val_ma(x)   ((x).pgd)
 174
 175
 176xmaddr_t arbitrary_virt_to_machine(unsigned long address);
 177void make_lowmem_page_readonly(void *vaddr);
 178void make_lowmem_page_readwrite(void *vaddr);
 179
 180#endif /* __XEN_PAGE_H */
 181