source: trunk/packages/xen-common/xen-common/xen/include/asm-x86/page.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: 14.9 KB
Line 
1
2#ifndef __X86_PAGE_H__
3#define __X86_PAGE_H__
4
5/*
6 * It is important that the masks are signed quantities. This ensures that
7 * the compiler sign-extends a 32-bit mask to 64 bits if that is required.
8 */
9#ifndef __ASSEMBLY__
10#define PAGE_SIZE           (1L << PAGE_SHIFT)
11#else
12#define PAGE_SIZE           (1 << PAGE_SHIFT)
13#endif
14#define PAGE_MASK           (~(PAGE_SIZE-1))
15#define PAGE_FLAG_MASK      (~0)
16
17#ifndef __ASSEMBLY__
18# include <asm/types.h>
19# include <xen/lib.h>
20#endif
21
22#if defined(__i386__)
23# include <asm/x86_32/page.h>
24#elif defined(__x86_64__)
25# include <asm/x86_64/page.h>
26#endif
27
28/* Read a pte atomically from memory. */
29#define l1e_read_atomic(l1ep) \
30    l1e_from_intpte(pte_read_atomic(&l1e_get_intpte(*(l1ep))))
31#define l2e_read_atomic(l2ep) \
32    l2e_from_intpte(pte_read_atomic(&l2e_get_intpte(*(l2ep))))
33#define l3e_read_atomic(l3ep) \
34    l3e_from_intpte(pte_read_atomic(&l3e_get_intpte(*(l3ep))))
35#define l4e_read_atomic(l4ep) \
36    l4e_from_intpte(pte_read_atomic(&l4e_get_intpte(*(l4ep))))
37
38/* Write a pte atomically to memory. */
39#define l1e_write_atomic(l1ep, l1e) \
40    pte_write_atomic(&l1e_get_intpte(*(l1ep)), l1e_get_intpte(l1e))
41#define l2e_write_atomic(l2ep, l2e) \
42    pte_write_atomic(&l2e_get_intpte(*(l2ep)), l2e_get_intpte(l2e))
43#define l3e_write_atomic(l3ep, l3e) \
44    pte_write_atomic(&l3e_get_intpte(*(l3ep)), l3e_get_intpte(l3e))
45#define l4e_write_atomic(l4ep, l4e) \
46    pte_write_atomic(&l4e_get_intpte(*(l4ep)), l4e_get_intpte(l4e))
47
48/*
49 * Write a pte safely but non-atomically to memory.
50 * The PTE may become temporarily not-present during the update.
51 */
52#define l1e_write(l1ep, l1e) \
53    pte_write(&l1e_get_intpte(*(l1ep)), l1e_get_intpte(l1e))
54#define l2e_write(l2ep, l2e) \
55    pte_write(&l2e_get_intpte(*(l2ep)), l2e_get_intpte(l2e))
56#define l3e_write(l3ep, l3e) \
57    pte_write(&l3e_get_intpte(*(l3ep)), l3e_get_intpte(l3e))
58#define l4e_write(l4ep, l4e) \
59    pte_write(&l4e_get_intpte(*(l4ep)), l4e_get_intpte(l4e))
60
61/* Get direct integer representation of a pte's contents (intpte_t). */
62#define l1e_get_intpte(x)          ((x).l1)
63#define l2e_get_intpte(x)          ((x).l2)
64#define l3e_get_intpte(x)          ((x).l3)
65#define l4e_get_intpte(x)          ((x).l4)
66
67/* Get pfn mapped by pte (unsigned long). */
68#define l1e_get_pfn(x)             \
69    ((unsigned long)(((x).l1 & (PADDR_MASK&PAGE_MASK)) >> PAGE_SHIFT))
70#define l2e_get_pfn(x)             \
71    ((unsigned long)(((x).l2 & (PADDR_MASK&PAGE_MASK)) >> PAGE_SHIFT))
72#define l3e_get_pfn(x)             \
73    ((unsigned long)(((x).l3 & (PADDR_MASK&PAGE_MASK)) >> PAGE_SHIFT))
74#define l4e_get_pfn(x)             \
75    ((unsigned long)(((x).l4 & (PADDR_MASK&PAGE_MASK)) >> PAGE_SHIFT))
76
77/* Get physical address of page mapped by pte (paddr_t). */
78#define l1e_get_paddr(x)           \
79    ((paddr_t)(((x).l1 & (PADDR_MASK&PAGE_MASK))))
80#define l2e_get_paddr(x)           \
81    ((paddr_t)(((x).l2 & (PADDR_MASK&PAGE_MASK))))
82#define l3e_get_paddr(x)           \
83    ((paddr_t)(((x).l3 & (PADDR_MASK&PAGE_MASK))))
84#define l4e_get_paddr(x)           \
85    ((paddr_t)(((x).l4 & (PADDR_MASK&PAGE_MASK))))
86
87/* Get pointer to info structure of page mapped by pte (struct page_info *). */
88#define l1e_get_page(x)           (mfn_to_page(l1e_get_pfn(x)))
89#define l2e_get_page(x)           (mfn_to_page(l2e_get_pfn(x)))
90#define l3e_get_page(x)           (mfn_to_page(l3e_get_pfn(x)))
91#define l4e_get_page(x)           (mfn_to_page(l4e_get_pfn(x)))
92
93/* Get pte access flags (unsigned int). */
94#define l1e_get_flags(x)           (get_pte_flags((x).l1))
95#define l2e_get_flags(x)           (get_pte_flags((x).l2))
96#define l3e_get_flags(x)           (get_pte_flags((x).l3))
97#define l4e_get_flags(x)           (get_pte_flags((x).l4))
98
99/* Construct an empty pte. */
100#define l1e_empty()                ((l1_pgentry_t) { 0 })
101#define l2e_empty()                ((l2_pgentry_t) { 0 })
102#define l3e_empty()                ((l3_pgentry_t) { 0 })
103#define l4e_empty()                ((l4_pgentry_t) { 0 })
104
105/* Construct a pte from a pfn and access flags. */
106#define l1e_from_pfn(pfn, flags)   \
107    ((l1_pgentry_t) { ((intpte_t)(pfn) << PAGE_SHIFT) | put_pte_flags(flags) })
108#define l2e_from_pfn(pfn, flags)   \
109    ((l2_pgentry_t) { ((intpte_t)(pfn) << PAGE_SHIFT) | put_pte_flags(flags) })
110#define l3e_from_pfn(pfn, flags)   \
111    ((l3_pgentry_t) { ((intpte_t)(pfn) << PAGE_SHIFT) | put_pte_flags(flags) })
112#define l4e_from_pfn(pfn, flags)   \
113    ((l4_pgentry_t) { ((intpte_t)(pfn) << PAGE_SHIFT) | put_pte_flags(flags) })
114
115/* Construct a pte from a physical address and access flags. */
116#ifndef __ASSEMBLY__
117static inline l1_pgentry_t l1e_from_paddr(paddr_t pa, unsigned int flags)
118{
119    ASSERT((pa & ~(PADDR_MASK & PAGE_MASK)) == 0);
120    return (l1_pgentry_t) { pa | put_pte_flags(flags) };
121}
122static inline l2_pgentry_t l2e_from_paddr(paddr_t pa, unsigned int flags)
123{
124    ASSERT((pa & ~(PADDR_MASK & PAGE_MASK)) == 0);
125    return (l2_pgentry_t) { pa | put_pte_flags(flags) };
126}
127#if CONFIG_PAGING_LEVELS >= 3
128static inline l3_pgentry_t l3e_from_paddr(paddr_t pa, unsigned int flags)
129{
130    ASSERT((pa & ~(PADDR_MASK & PAGE_MASK)) == 0);
131    return (l3_pgentry_t) { pa | put_pte_flags(flags) };
132}
133#endif
134#if CONFIG_PAGING_LEVELS >= 4
135static inline l4_pgentry_t l4e_from_paddr(paddr_t pa, unsigned int flags)
136{
137    ASSERT((pa & ~(PADDR_MASK & PAGE_MASK)) == 0);
138    return (l4_pgentry_t) { pa | put_pte_flags(flags) };
139}
140#endif
141#endif /* !__ASSEMBLY__ */
142
143/* Construct a pte from its direct integer representation. */
144#define l1e_from_intpte(intpte)    ((l1_pgentry_t) { (intpte_t)(intpte) })
145#define l2e_from_intpte(intpte)    ((l2_pgentry_t) { (intpte_t)(intpte) })
146#define l3e_from_intpte(intpte)    ((l3_pgentry_t) { (intpte_t)(intpte) })
147#define l4e_from_intpte(intpte)    ((l4_pgentry_t) { (intpte_t)(intpte) })
148
149/* Construct a pte from a page pointer and access flags. */
150#define l1e_from_page(page, flags) (l1e_from_pfn(page_to_mfn(page),(flags)))
151#define l2e_from_page(page, flags) (l2e_from_pfn(page_to_mfn(page),(flags)))
152#define l3e_from_page(page, flags) (l3e_from_pfn(page_to_mfn(page),(flags)))
153#define l4e_from_page(page, flags) (l4e_from_pfn(page_to_mfn(page),(flags)))
154
155/* Add extra flags to an existing pte. */
156#define l1e_add_flags(x, flags)    ((x).l1 |= put_pte_flags(flags))
157#define l2e_add_flags(x, flags)    ((x).l2 |= put_pte_flags(flags))
158#define l3e_add_flags(x, flags)    ((x).l3 |= put_pte_flags(flags))
159#define l4e_add_flags(x, flags)    ((x).l4 |= put_pte_flags(flags))
160
161/* Remove flags from an existing pte. */
162#define l1e_remove_flags(x, flags) ((x).l1 &= ~put_pte_flags(flags))
163#define l2e_remove_flags(x, flags) ((x).l2 &= ~put_pte_flags(flags))
164#define l3e_remove_flags(x, flags) ((x).l3 &= ~put_pte_flags(flags))
165#define l4e_remove_flags(x, flags) ((x).l4 &= ~put_pte_flags(flags))
166
167/* Check if a pte's page mapping or significant access flags have changed. */
168#define l1e_has_changed(x,y,flags) \
169    ( !!(((x).l1 ^ (y).l1) & ((PADDR_MASK&PAGE_MASK)|put_pte_flags(flags))) )
170#define l2e_has_changed(x,y,flags) \
171    ( !!(((x).l2 ^ (y).l2) & ((PADDR_MASK&PAGE_MASK)|put_pte_flags(flags))) )
172#define l3e_has_changed(x,y,flags) \
173    ( !!(((x).l3 ^ (y).l3) & ((PADDR_MASK&PAGE_MASK)|put_pte_flags(flags))) )
174#define l4e_has_changed(x,y,flags) \
175    ( !!(((x).l4 ^ (y).l4) & ((PADDR_MASK&PAGE_MASK)|put_pte_flags(flags))) )
176
177/* Pagetable walking. */
178#define l2e_to_l1e(x)              ((l1_pgentry_t *)__va(l2e_get_paddr(x)))
179#define l3e_to_l2e(x)              ((l2_pgentry_t *)__va(l3e_get_paddr(x)))
180#define l4e_to_l3e(x)              ((l3_pgentry_t *)__va(l4e_get_paddr(x)))
181
182/* Given a virtual address, get an entry offset into a page table. */
183#define l1_table_offset(a)         \
184    (((a) >> L1_PAGETABLE_SHIFT) & (L1_PAGETABLE_ENTRIES - 1))
185#define l2_table_offset(a)         \
186    (((a) >> L2_PAGETABLE_SHIFT) & (L2_PAGETABLE_ENTRIES - 1))
187#define l3_table_offset(a)         \
188    (((a) >> L3_PAGETABLE_SHIFT) & (L3_PAGETABLE_ENTRIES - 1))
189#define l4_table_offset(a)         \
190    (((a) >> L4_PAGETABLE_SHIFT) & (L4_PAGETABLE_ENTRIES - 1))
191
192/* Convert a pointer to a page-table entry into pagetable slot index. */
193#define pgentry_ptr_to_slot(_p)    \
194    (((unsigned long)(_p) & ~PAGE_MASK) / sizeof(*(_p)))
195
196/* Page-table type. */
197#ifndef __ASSEMBLY__
198#if CONFIG_PAGING_LEVELS == 2
199/* x86_32 default */
200typedef struct { u32 pfn; } pagetable_t;
201#elif CONFIG_PAGING_LEVELS == 3
202/* x86_32 PAE */
203typedef struct { u32 pfn; } pagetable_t;
204#elif CONFIG_PAGING_LEVELS == 4
205/* x86_64 */
206typedef struct { u64 pfn; } pagetable_t;
207#endif
208#define pagetable_get_paddr(x)  ((paddr_t)(x).pfn << PAGE_SHIFT)
209#define pagetable_get_page(x)   mfn_to_page((x).pfn)
210#define pagetable_get_pfn(x)    ((x).pfn)
211#define pagetable_get_mfn(x)    _mfn(((x).pfn))
212#define pagetable_is_null(x)    ((x).pfn == 0)
213#define pagetable_from_pfn(pfn) ((pagetable_t) { (pfn) })
214#define pagetable_from_mfn(mfn) ((pagetable_t) { mfn_x(mfn) })
215#define pagetable_from_page(pg) pagetable_from_pfn(page_to_mfn(pg))
216#define pagetable_from_paddr(p) pagetable_from_pfn((p)>>PAGE_SHIFT)
217#define pagetable_null()        pagetable_from_pfn(0)
218#endif
219
220#define clear_page(_p)      memset((void *)(_p), 0, PAGE_SIZE)
221#define copy_page(_t,_f)    memcpy((void *)(_t), (void *)(_f), PAGE_SIZE)
222
223#define mfn_valid(mfn)      ((mfn) < max_page)
224
225/* Convert between Xen-heap virtual addresses and machine addresses. */
226#define PAGE_OFFSET         ((unsigned long)__PAGE_OFFSET)
227#define virt_to_maddr(va)   ((unsigned long)(va)-PAGE_OFFSET)
228#define maddr_to_virt(ma)   ((void *)((unsigned long)(ma)+PAGE_OFFSET))
229/* Shorthand versions of the above functions. */
230#define __pa(x)             (virt_to_maddr(x))
231#define __va(x)             (maddr_to_virt(x))
232
233/* Convert between Xen-heap virtual addresses and machine frame numbers. */
234#define virt_to_mfn(va)     (virt_to_maddr(va) >> PAGE_SHIFT)
235#define mfn_to_virt(mfn)    (maddr_to_virt(mfn << PAGE_SHIFT))
236
237/* Convert between machine frame numbers and page-info structures. */
238#define mfn_to_page(mfn)    (frame_table + (mfn))
239#define page_to_mfn(pg)     ((unsigned long)((pg) - frame_table))
240
241/* Convert between machine addresses and page-info structures. */
242#define maddr_to_page(ma)   (frame_table + ((ma) >> PAGE_SHIFT))
243#define page_to_maddr(pg)   ((paddr_t)((pg) - frame_table) << PAGE_SHIFT)
244
245/* Convert between Xen-heap virtual addresses and page-info structures. */
246#define virt_to_page(va)    (frame_table + (__pa(va) >> PAGE_SHIFT))
247#define page_to_virt(pg)    (maddr_to_virt(page_to_maddr(pg)))
248
249/* Convert between frame number and address formats.  */
250#define pfn_to_paddr(pfn)   ((paddr_t)(pfn) << PAGE_SHIFT)
251#define paddr_to_pfn(pa)    ((unsigned long)((pa) >> PAGE_SHIFT))
252
253/* High table entries are reserved by the hypervisor. */
254#if defined(CONFIG_X86_32) && !defined(CONFIG_X86_PAE)
255#define DOMAIN_ENTRIES_PER_L2_PAGETABLE     \
256  (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT)
257#define HYPERVISOR_ENTRIES_PER_L2_PAGETABLE \
258  (L2_PAGETABLE_ENTRIES - DOMAIN_ENTRIES_PER_L2_PAGETABLE)
259#else
260#define DOMAIN_ENTRIES_PER_L2_PAGETABLE     0
261#define HYPERVISOR_ENTRIES_PER_L2_PAGETABLE 0
262
263#define DOMAIN_ENTRIES_PER_L4_PAGETABLE     \
264    (l4_table_offset(HYPERVISOR_VIRT_START))
265#define GUEST_ENTRIES_PER_L4_PAGETABLE     \
266    (l4_table_offset(HYPERVISOR_VIRT_END))
267#define HYPERVISOR_ENTRIES_PER_L4_PAGETABLE \
268    (L4_PAGETABLE_ENTRIES - GUEST_ENTRIES_PER_L4_PAGETABLE  \
269     + DOMAIN_ENTRIES_PER_L4_PAGETABLE)
270#endif
271
272/* Where to find each level of the linear mapping */
273#define __linear_l1_table ((l1_pgentry_t *)(LINEAR_PT_VIRT_START))
274#define __linear_l2_table \
275 ((l2_pgentry_t *)(__linear_l1_table + l1_linear_offset(LINEAR_PT_VIRT_START)))
276#define __linear_l3_table \
277 ((l3_pgentry_t *)(__linear_l2_table + l2_linear_offset(LINEAR_PT_VIRT_START)))
278#define __linear_l4_table \
279 ((l4_pgentry_t *)(__linear_l3_table + l3_linear_offset(LINEAR_PT_VIRT_START)))
280
281
282#ifndef __ASSEMBLY__
283#if CONFIG_PAGING_LEVELS == 3
284extern root_pgentry_t idle_pg_table[ROOT_PAGETABLE_ENTRIES];
285extern l3_pgentry_t   idle_pg_table_l3[ROOT_PAGETABLE_ENTRIES];
286extern l2_pgentry_t   idle_pg_table_l2[ROOT_PAGETABLE_ENTRIES*L2_PAGETABLE_ENTRIES];
287#else
288extern root_pgentry_t idle_pg_table[ROOT_PAGETABLE_ENTRIES];
289extern l2_pgentry_t   idle_pg_table_l2[ROOT_PAGETABLE_ENTRIES];
290#ifdef CONFIG_COMPAT
291extern l2_pgentry_t  *compat_idle_pg_table_l2;
292extern unsigned int   m2p_compat_vstart;
293#endif
294#endif
295void paging_init(void);
296void setup_idle_pagetable(void);
297#endif
298
299#define __pge_off()                                                     \
300    do {                                                                \
301        __asm__ __volatile__(                                           \
302            "mov %0, %%cr4;  # turn off PGE     "                       \
303            : : "r" (mmu_cr4_features & ~X86_CR4_PGE) );                \
304        } while ( 0 )
305
306#define __pge_on()                                                      \
307    do {                                                                \
308        __asm__ __volatile__(                                           \
309            "mov %0, %%cr4;  # turn off PGE     "                       \
310            : : "r" (mmu_cr4_features) );                               \
311    } while ( 0 )
312
313#define _PAGE_PRESENT  0x001U
314#define _PAGE_RW       0x002U
315#define _PAGE_USER     0x004U
316#define _PAGE_PWT      0x008U
317#define _PAGE_PCD      0x010U
318#define _PAGE_ACCESSED 0x020U
319#define _PAGE_DIRTY    0x040U
320#define _PAGE_PAT      0x080U
321#define _PAGE_PSE      0x080U
322#define _PAGE_GLOBAL   0x100U
323#define _PAGE_AVAIL0   0x200U
324#define _PAGE_AVAIL1   0x400U
325#define _PAGE_AVAIL2   0x800U
326#define _PAGE_AVAIL    0xE00U
327#define _PAGE_PSE_PAT 0x1000U
328
329/*
330 * Debug option: Ensure that granted mappings are not implicitly unmapped.
331 * WARNING: This will need to be disabled to run OSes that use the spare PTE
332 * bits themselves (e.g., *BSD).
333 */
334#ifndef NDEBUG
335#define _PAGE_GNTTAB   _PAGE_AVAIL2
336#else
337#define _PAGE_GNTTAB   0
338#endif
339
340#define __PAGE_HYPERVISOR \
341    (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
342#define __PAGE_HYPERVISOR_NOCACHE \
343    (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_PCD | _PAGE_ACCESSED)
344
345#ifndef __ASSEMBLY__
346
347static inline int get_order_from_bytes(paddr_t size)
348{
349    int order;
350    size = (size-1) >> PAGE_SHIFT;
351    for ( order = 0; size; order++ )
352        size >>= 1;
353    return order;
354}
355
356static inline int get_order_from_pages(unsigned long nr_pages)
357{
358    int order;
359    nr_pages--;
360    for ( order = 0; nr_pages; order++ )
361        nr_pages >>= 1;
362    return order;
363}
364
365/* Allocator functions for Xen pagetables. */
366void *alloc_xen_pagetable(void);
367void free_xen_pagetable(void *v);
368l2_pgentry_t *virt_to_xen_l2e(unsigned long v);
369
370/* Map machine page range in Xen virtual address space. */
371#define MAP_SMALL_PAGES (1UL<<16) /* don't use superpages for the mapping */
372int
373map_pages_to_xen(
374    unsigned long virt,
375    unsigned long mfn,
376    unsigned long nr_mfns,
377    unsigned long flags);
378
379#endif /* !__ASSEMBLY__ */
380
381#define PFN_DOWN(x)   ((x) >> PAGE_SHIFT)
382#define PFN_UP(x)     (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
383
384#endif /* __X86_PAGE_H__ */
385
386/*
387 * Local variables:
388 * mode: C
389 * c-set-style: "BSD"
390 * c-basic-offset: 4
391 * tab-width: 4
392 * indent-tabs-mode: nil
393 * End:
394 */
Note: See TracBrowser for help on using the repository browser.