source: trunk/packages/xen-common/xen-common/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/maddr.h @ 34

Last change on this file since 34 was 34, checked in by hartmans, 17 years ago

Add xen and xen-common

File size: 5.7 KB
Line 
1#ifndef _I386_MADDR_H
2#define _I386_MADDR_H
3
4#include <xen/features.h>
5#include <xen/interface/xen.h>
6
7/**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/
8#define INVALID_P2M_ENTRY       (~0UL)
9#define FOREIGN_FRAME_BIT       (1UL<<31)
10#define FOREIGN_FRAME(m)        ((m) | FOREIGN_FRAME_BIT)
11
12/* Definitions for machine and pseudophysical addresses. */
13#ifdef CONFIG_X86_PAE
14typedef unsigned long long paddr_t;
15typedef unsigned long long maddr_t;
16#else
17typedef unsigned long paddr_t;
18typedef unsigned long maddr_t;
19#endif
20
21#ifdef CONFIG_XEN
22
23extern unsigned long *phys_to_machine_mapping;
24extern unsigned long  max_mapnr;
25
26#undef machine_to_phys_mapping
27extern unsigned long *machine_to_phys_mapping;
28extern unsigned int   machine_to_phys_order;
29
30static inline unsigned long pfn_to_mfn(unsigned long pfn)
31{
32        if (xen_feature(XENFEAT_auto_translated_physmap))
33                return pfn;
34        BUG_ON(max_mapnr && pfn >= max_mapnr);
35        return phys_to_machine_mapping[pfn] & ~FOREIGN_FRAME_BIT;
36}
37
38static inline int phys_to_machine_mapping_valid(unsigned long pfn)
39{
40        if (xen_feature(XENFEAT_auto_translated_physmap))
41                return 1;
42        BUG_ON(max_mapnr && pfn >= max_mapnr);
43        return (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY);
44}
45
46static inline unsigned long mfn_to_pfn(unsigned long mfn)
47{
48        unsigned long pfn;
49
50        if (xen_feature(XENFEAT_auto_translated_physmap))
51                return mfn;
52
53        if (unlikely((mfn >> machine_to_phys_order) != 0))
54                return max_mapnr;
55
56        /* The array access can fail (e.g., device space beyond end of RAM). */
57        asm (
58                "1:     movl %1,%0\n"
59                "2:\n"
60                ".section .fixup,\"ax\"\n"
61                "3:     movl %2,%0\n"
62                "       jmp  2b\n"
63                ".previous\n"
64                ".section __ex_table,\"a\"\n"
65                "       .align 4\n"
66                "       .long 1b,3b\n"
67                ".previous"
68                : "=r" (pfn)
69                : "m" (machine_to_phys_mapping[mfn]), "m" (max_mapnr) );
70
71        return pfn;
72}
73
74/*
75 * We detect special mappings in one of two ways:
76 *  1. If the MFN is an I/O page then Xen will set the m2p entry
77 *     to be outside our maximum possible pseudophys range.
78 *  2. If the MFN belongs to a different domain then we will certainly
79 *     not have MFN in our p2m table. Conversely, if the page is ours,
80 *     then we'll have p2m(m2p(MFN))==MFN.
81 * If we detect a special mapping then it doesn't have a 'struct page'.
82 * We force !pfn_valid() by returning an out-of-range pointer.
83 *
84 * NB. These checks require that, for any MFN that is not in our reservation,
85 * there is no PFN such that p2m(PFN) == MFN. Otherwise we can get confused if
86 * we are foreign-mapping the MFN, and the other domain as m2p(MFN) == PFN.
87 * Yikes! Various places must poke in INVALID_P2M_ENTRY for safety.
88 *
89 * NB2. When deliberately mapping foreign pages into the p2m table, you *must*
90 *      use FOREIGN_FRAME(). This will cause pte_pfn() to choke on it, as we
91 *      require. In all the cases we care about, the FOREIGN_FRAME bit is
92 *      masked (e.g., pfn_to_mfn()) so behaviour there is correct.
93 */
94static inline unsigned long mfn_to_local_pfn(unsigned long mfn)
95{
96        unsigned long pfn = mfn_to_pfn(mfn);
97        if ((pfn < max_mapnr)
98            && !xen_feature(XENFEAT_auto_translated_physmap)
99            && (phys_to_machine_mapping[pfn] != mfn))
100                return max_mapnr; /* force !pfn_valid() */
101        return pfn;
102}
103
104static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
105{
106        BUG_ON(max_mapnr && pfn >= max_mapnr);
107        if (xen_feature(XENFEAT_auto_translated_physmap)) {
108                BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
109                return;
110        }
111        phys_to_machine_mapping[pfn] = mfn;
112}
113
114static inline maddr_t phys_to_machine(paddr_t phys)
115{
116        maddr_t machine = pfn_to_mfn(phys >> PAGE_SHIFT);
117        machine = (machine << PAGE_SHIFT) | (phys & ~PAGE_MASK);
118        return machine;
119}
120
121static inline paddr_t machine_to_phys(maddr_t machine)
122{
123        paddr_t phys = mfn_to_pfn(machine >> PAGE_SHIFT);
124        phys = (phys << PAGE_SHIFT) | (machine & ~PAGE_MASK);
125        return phys;
126}
127
128#ifdef CONFIG_X86_PAE
129static inline paddr_t pte_phys_to_machine(paddr_t phys)
130{
131        /*
132         * In PAE mode, the NX bit needs to be dealt with in the value
133         * passed to pfn_to_mfn(). On x86_64, we need to mask it off,
134         * but for i386 the conversion to ulong for the argument will
135         * clip it off.
136         */
137        maddr_t machine = pfn_to_mfn(phys >> PAGE_SHIFT);
138        machine = (machine << PAGE_SHIFT) | (phys & ~PHYSICAL_PAGE_MASK);
139        return machine;
140}
141
142static inline paddr_t pte_machine_to_phys(maddr_t machine)
143{
144        /*
145         * In PAE mode, the NX bit needs to be dealt with in the value
146         * passed to mfn_to_pfn(). On x86_64, we need to mask it off,
147         * but for i386 the conversion to ulong for the argument will
148         * clip it off.
149         */
150        paddr_t phys = mfn_to_pfn(machine >> PAGE_SHIFT);
151        phys = (phys << PAGE_SHIFT) | (machine & ~PHYSICAL_PAGE_MASK);
152        return phys;
153}
154#endif
155
156#ifdef CONFIG_X86_PAE
157static inline pte_t pfn_pte_ma(unsigned long page_nr, pgprot_t pgprot)
158{
159        pte_t pte;
160
161        pte.pte_high = (page_nr >> (32 - PAGE_SHIFT)) | \
162                                        (pgprot_val(pgprot) >> 32);
163        pte.pte_high &= (__supported_pte_mask >> 32);
164        pte.pte_low = ((page_nr << PAGE_SHIFT) | pgprot_val(pgprot)) & \
165                                                        __supported_pte_mask;
166        return pte;
167}
168#else
169#define pfn_pte_ma(pfn, prot)   __pte_ma(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
170#endif
171
172#define __pte_ma(x)     ((pte_t) { (x) } )
173
174#else /* !CONFIG_XEN */
175
176#define pfn_to_mfn(pfn) (pfn)
177#define mfn_to_pfn(mfn) (mfn)
178#define mfn_to_local_pfn(mfn) (mfn)
179#define set_phys_to_machine(pfn, mfn) ((void)0)
180#define phys_to_machine_mapping_valid(pfn) (1)
181#define phys_to_machine(phys) ((maddr_t)(phys))
182#define machine_to_phys(mach) ((paddr_t)(mach))
183#define pfn_pte_ma(pfn, prot) pfn_pte(pfn, prot)
184#define __pte_ma(x) __pte(x)
185
186#endif /* !CONFIG_XEN */
187
188/* VIRT <-> MACHINE conversion */
189#define virt_to_machine(v)      (phys_to_machine(__pa(v)))
190#define virt_to_mfn(v)          (pfn_to_mfn(__pa(v) >> PAGE_SHIFT))
191#define mfn_to_virt(m)          (__va(mfn_to_pfn(m) << PAGE_SHIFT))
192
193#endif /* _I386_MADDR_H */
Note: See TracBrowser for help on using the repository browser.