ia64/xen-unstable

view xen/include/asm-ia64/mm.h @ 19128:77393d4de777

[IA64] No need for cmpxchg on page_info structure.

Updates and checks on count_info and page owner can safely be
non-atomic.
This is ia64 counter part of 19088:055c589f4791.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author Isaku Yamahata <yamahata@valinux.co.jp>
date Fri Jan 30 11:12:29 2009 +0900 (2009-01-30)
parents 7029eb0930b4
children 971d2d5cb5cb
line source
1 /*
2 * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
3 * VA Linux Systems Japan K.K.
4 * dom0 vp model support
5 */
6 #ifndef __ASM_IA64_MM_H__
7 #define __ASM_IA64_MM_H__
9 #include <xen/config.h>
10 #ifdef LINUX_2_6
11 #include <linux/gfp.h>
12 #endif
13 #include <xen/list.h>
14 #include <xen/spinlock.h>
15 #include <xen/perfc.h>
16 #include <xen/sched.h>
18 #include <asm/processor.h>
19 #include <asm/atomic.h>
20 #include <asm/tlbflush.h>
21 #include <asm/flushtlb.h>
22 #include <asm/io.h>
24 #include <public/xen.h>
26 /*
27 * The following is for page_alloc.c.
28 */
30 typedef unsigned long page_flags_t;
32 /*
33 * Per-page-frame information.
34 *
35 * Every architecture must ensure the following:
36 * 1. 'struct page_info' contains a 'struct list_head list'.
37 * 2. Provide a PFN_ORDER() macro for accessing the order of a free page.
38 */
39 #define PFN_ORDER(_pfn) ((_pfn)->u.free.order)
41 #define PRtype_info "016lx"
43 struct page_info
44 {
45 /* Each frame can be threaded onto a doubly-linked list. */
46 struct list_head list;
48 /* Reference count and various PGC_xxx flags and fields. */
49 u32 count_info;
51 /* Context-dependent fields follow... */
52 union {
54 /* Page is in use: ((count_info & PGC_count_mask) != 0). */
55 struct {
56 /* Owner of this page (NULL if page is anonymous). */
57 u32 _domain; /* pickled format */
58 /* Type reference count and various PGT_xxx flags and fields. */
59 unsigned long type_info;
60 } __attribute__ ((packed)) inuse;
62 /* Page is on a free list: ((count_info & PGC_count_mask) == 0). */
63 struct {
64 /* Order-size of the free chunk this page is the head of. */
65 u32 order;
66 /* Mask of possibly-tainted TLBs. */
67 cpumask_t cpumask;
68 } __attribute__ ((packed)) free;
70 } u;
72 /* Timestamp from 'TLB clock', used to reduce need for safety flushes. */
73 u32 tlbflush_timestamp;
75 #if 0
76 // following added for Linux compiling
77 page_flags_t flags;
78 atomic_t _count;
79 struct list_head lru; // is this the same as above "list"?
80 #endif
81 };
83 #define set_page_count(p,v) atomic_set(&(p)->_count, v - 1)
85 /*
86 * Still small set of flags defined by far on IA-64.
87 * IA-64 should make it a definition same as x86_64.
88 */
89 /* The following page types are MUTUALLY EXCLUSIVE. */
90 #define PGT_none (0UL<<29) /* no special uses of this page */
91 #define PGT_l1_page_table (1UL<<29) /* using this page as an L1 page table? */
92 #define PGT_l2_page_table (2UL<<29) /* using this page as an L2 page table? */
93 #define PGT_l3_page_table (3UL<<29) /* using this page as an L3 page table? */
94 #define PGT_l4_page_table (4UL<<29) /* using this page as an L4 page table? */
95 /* Value 5 reserved. See asm-x86/mm.h */
96 /* Value 6 reserved. See asm-x86/mm.h */
97 #define PGT_writable_page (7UL<<29) /* has writable mappings of this page? */
98 #define PGT_type_mask (7UL<<29) /* Bits 29-31. */
100 /* Has this page been validated for use as its current type? */
101 #define _PGT_validated 28
102 #define PGT_validated (1UL<<_PGT_validated)
103 /* Owning guest has pinned this page to its current type? */
104 #define _PGT_pinned 27
105 #define PGT_pinned (1UL<<_PGT_pinned)
107 /* 16-bit count of uses of this frame as its current type. */
108 #define PGT_count_mask ((1UL<<16)-1)
110 /* Cleared when the owning guest 'frees' this page. */
111 #define _PGC_allocated 31
112 #define PGC_allocated (1UL<<_PGC_allocated)
113 /* Bit 30 reserved. See asm-x86/mm.h */
114 /* Bit 29 reserved. See asm-x86/mm.h */
115 /* 29-bit count of references to this frame. */
116 #define PGC_count_mask ((1UL<<29)-1)
118 #define is_xen_heap_mfn(mfn) (((mfn) < paddr_to_pfn(xenheap_phys_end)) \
119 && ((mfn) >= paddr_to_pfn(xen_pstart)))
120 #define is_xen_heap_page(page) is_xen_heap_mfn(page_to_mfn(page))
122 extern void* xen_pickle_offset;
123 #define __pickle(a) ((unsigned long)a - (unsigned long)xen_pickle_offset)
124 #define __unpickle(a) (void *)(a + xen_pickle_offset)
126 static inline struct domain *unpickle_domptr(u64 _d)
127 { return (_d == 0) ? NULL : __unpickle(_d); }
128 static inline u32 pickle_domptr(struct domain *_d)
129 { return (_d == NULL) ? 0 : (u32)__pickle(_d); }
131 #define page_get_owner(_p) (unpickle_domptr((_p)->u.inuse._domain))
132 #define page_set_owner(_p, _d) ((_p)->u.inuse._domain = pickle_domptr(_d))
134 #define XENSHARE_writable 0
135 #define XENSHARE_readonly 1
136 void share_xen_page_with_guest(struct page_info *page,
137 struct domain *d, int readonly);
138 void share_xen_page_with_privileged_guests(struct page_info *page,
139 int readonly);
141 extern unsigned long frametable_pg_dir[];
142 extern struct page_info *frame_table;
143 extern unsigned long frame_table_size;
144 extern struct list_head free_list;
145 extern spinlock_t free_list_lock;
146 extern unsigned int free_pfns;
147 extern unsigned long max_page;
149 extern void __init init_frametable(void);
150 void add_to_domain_alloc_list(unsigned long ps, unsigned long pe);
152 static inline void put_page(struct page_info *page)
153 {
154 u32 nx, x, y = page->count_info;
156 do {
157 x = y;
158 nx = x - 1;
159 }
160 while (unlikely((y = cmpxchg_rel(&page->count_info, x, nx)) != x));
162 if (unlikely((nx & PGC_count_mask) == 0))
163 free_domheap_page(page);
164 }
166 /* count_info and ownership are checked atomically. */
167 static inline int get_page(struct page_info *page,
168 struct domain *domain)
169 {
170 u32 x, y = page->count_info;
172 do {
173 x = y;
174 if (unlikely((x & PGC_count_mask) == 0) || /* Not allocated? */
175 unlikely(((x + 1) & PGC_count_mask) == 0) ) {/* Count overflow? */
176 goto fail;
177 }
178 y = cmpxchg_acq(&page->count_info, x, x + 1);
179 } while (unlikely(y != x));
181 if (likely(page_get_owner(page) == domain))
182 return 1;
184 put_page(page);
185 fail:
186 /* if (!domain->is_dying) */ /* XXX: header inclusion hell */
187 gdprintk(XENLOG_INFO,
188 "Error pfn %lx: rd=%p, od=%p, caf=%016x, taf=%" PRtype_info "\n",
189 page_to_mfn(page), domain,
190 page_get_owner(page), y, page->u.inuse.type_info);
191 return 0;
192 }
194 int is_iomem_page(unsigned long mfn);
196 extern void put_page_type(struct page_info *page);
197 extern int get_page_type(struct page_info *page, u32 type);
199 static inline void put_page_and_type(struct page_info *page)
200 {
201 put_page_type(page);
202 put_page(page);
203 }
206 static inline int get_page_and_type(struct page_info *page,
207 struct domain *domain,
208 u32 type)
209 {
210 int rc = get_page(page, domain);
212 if ( likely(rc) && unlikely(!get_page_type(page, type)) )
213 {
214 put_page(page);
215 rc = 0;
216 }
218 return rc;
219 }
221 #define set_machinetophys(_mfn, _pfn) do { } while(0);
223 #ifdef MEMORY_GUARD
224 void *memguard_init(void *heap_start);
225 void memguard_guard_stack(void *p);
226 void memguard_guard_range(void *p, unsigned long l);
227 void memguard_unguard_range(void *p, unsigned long l);
228 #else
229 #define memguard_init(_s) (_s)
230 #define memguard_guard_stack(_p) ((void)0)
231 #define memguard_guard_range(_p,_l) ((void)0)
232 #define memguard_unguard_range(_p,_l) ((void)0)
233 #endif
235 // prototype of misc memory stuff
236 //unsigned long __get_free_pages(unsigned int mask, unsigned int order);
237 //void __free_pages(struct page_info *page, unsigned int order);
238 void *pgtable_quicklist_alloc(void);
239 void pgtable_quicklist_free(void *pgtable_entry);
241 // FOLLOWING FROM linux-2.6.7/include/mm.h
243 /*
244 * This struct defines a memory VMM memory area. There is one of these
245 * per VM-area/task. A VM area is any part of the process virtual memory
246 * space that has a special rule for the page-fault handlers (ie a shared
247 * library, the executable area etc).
248 */
249 struct vm_area_struct {
250 struct mm_struct * vm_mm; /* The address space we belong to. */
251 unsigned long vm_start; /* Our start address within vm_mm. */
252 unsigned long vm_end; /* The first byte after our end address
253 within vm_mm. */
255 /* linked list of VM areas per task, sorted by address */
256 struct vm_area_struct *vm_next;
258 pgprot_t vm_page_prot; /* Access permissions of this VMA. */
259 unsigned long vm_flags; /* Flags, listed below. */
261 #ifndef XEN
262 struct rb_node vm_rb;
264 // XEN doesn't need all the backing store stuff
265 /*
266 * For areas with an address space and backing store,
267 * linkage into the address_space->i_mmap prio tree, or
268 * linkage to the list of like vmas hanging off its node, or
269 * linkage of vma in the address_space->i_mmap_nonlinear list.
270 */
271 union {
272 struct {
273 struct list_head list;
274 void *parent; /* aligns with prio_tree_node parent */
275 struct vm_area_struct *head;
276 } vm_set;
278 struct prio_tree_node prio_tree_node;
279 } shared;
281 /*
282 * A file's MAP_PRIVATE vma can be in both i_mmap tree and anon_vma
283 * list, after a COW of one of the file pages. A MAP_SHARED vma
284 * can only be in the i_mmap tree. An anonymous MAP_PRIVATE, stack
285 * or brk vma (with NULL file) can only be in an anon_vma list.
286 */
287 struct list_head anon_vma_node; /* Serialized by anon_vma->lock */
288 struct anon_vma *anon_vma; /* Serialized by page_table_lock */
290 /* Function pointers to deal with this struct. */
291 struct vm_operations_struct * vm_ops;
293 /* Information about our backing store: */
294 unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE
295 units, *not* PAGE_CACHE_SIZE */
296 struct file * vm_file; /* File we map to (can be NULL). */
297 void * vm_private_data; /* was vm_pte (shared mem) */
299 #ifdef CONFIG_NUMA
300 struct mempolicy *vm_policy; /* NUMA policy for the VMA */
301 #endif
302 #endif
303 };
304 /*
305 * vm_flags..
306 */
307 #define VM_READ 0x00000001 /* currently active flags */
308 #define VM_WRITE 0x00000002
309 #define VM_EXEC 0x00000004
310 #define VM_SHARED 0x00000008
312 #define VM_MAYREAD 0x00000010 /* limits for mprotect() etc */
313 #define VM_MAYWRITE 0x00000020
314 #define VM_MAYEXEC 0x00000040
315 #define VM_MAYSHARE 0x00000080
317 #define VM_GROWSDOWN 0x00000100 /* general info on the segment */
318 #define VM_GROWSUP 0x00000200
319 #define VM_SHM 0x00000400 /* shared memory area, don't swap out */
320 #define VM_DENYWRITE 0x00000800 /* ETXTBSY on write attempts.. */
322 #define VM_EXECUTABLE 0x00001000
323 #define VM_LOCKED 0x00002000
324 #define VM_IO 0x00004000 /* Memory mapped I/O or similar */
326 /* Used by sys_madvise() */
327 #define VM_SEQ_READ 0x00008000 /* App will access data sequentially */
328 #define VM_RAND_READ 0x00010000 /* App will not benefit from clustered reads */
330 #define VM_DONTCOPY 0x00020000 /* Do not copy this vma on fork */
331 #define VM_DONTEXPAND 0x00040000 /* Cannot expand with mremap() */
332 #define VM_RESERVED 0x00080000 /* Don't unmap it from swap_out */
333 #define VM_ACCOUNT 0x00100000 /* Is a VM accounted object */
334 #define VM_HUGETLB 0x00400000 /* Huge TLB Page VM */
335 #define VM_NONLINEAR 0x00800000 /* Is non-linear (remap_file_pages) */
337 #ifndef VM_STACK_DEFAULT_FLAGS /* arch can override this */
338 #define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS
339 #endif
341 #ifdef CONFIG_STACK_GROWSUP
342 #define VM_STACK_FLAGS (VM_GROWSUP | VM_STACK_DEFAULT_FLAGS | VM_ACCOUNT)
343 #else
344 #define VM_STACK_FLAGS (VM_GROWSDOWN | VM_STACK_DEFAULT_FLAGS | VM_ACCOUNT)
345 #endif
347 #if 0 /* removed when rebasing to 2.6.13 */
348 /*
349 * The zone field is never updated after free_area_init_core()
350 * sets it, so none of the operations on it need to be atomic.
351 * We'll have up to (MAX_NUMNODES * MAX_NR_ZONES) zones total,
352 * so we use (MAX_NODES_SHIFT + MAX_ZONES_SHIFT) here to get enough bits.
353 */
354 #define NODEZONE_SHIFT (sizeof(page_flags_t)*8 - MAX_NODES_SHIFT - MAX_ZONES_SHIFT)
355 #define NODEZONE(node, zone) ((node << ZONES_SHIFT) | zone)
357 static inline unsigned long page_zonenum(struct page_info *page)
358 {
359 return (page->flags >> NODEZONE_SHIFT) & (~(~0UL << ZONES_SHIFT));
360 }
361 static inline unsigned long page_to_nid(struct page_info *page)
362 {
363 return (page->flags >> (NODEZONE_SHIFT + ZONES_SHIFT));
364 }
366 struct zone;
367 extern struct zone *zone_table[];
369 static inline struct zone *page_zone(struct page_info *page)
370 {
371 return zone_table[page->flags >> NODEZONE_SHIFT];
372 }
374 static inline void set_page_zone(struct page_info *page, unsigned long nodezone_num)
375 {
376 page->flags &= ~(~0UL << NODEZONE_SHIFT);
377 page->flags |= nodezone_num << NODEZONE_SHIFT;
378 }
379 #endif
381 #ifndef CONFIG_DISCONTIGMEM /* Don't use mapnrs, do it properly */
382 extern unsigned long max_mapnr;
383 #endif
385 static inline void *lowmem_page_address(struct page_info *page)
386 {
387 return __va(page_to_mfn(page) << PAGE_SHIFT);
388 }
390 #if defined(CONFIG_HIGHMEM) && !defined(WANT_PAGE_VIRTUAL)
391 #define HASHED_PAGE_VIRTUAL
392 #endif
394 #if defined(WANT_PAGE_VIRTUAL)
395 #define page_address(page) ((page)->virtual)
396 #define set_page_address(page, address) \
397 do { \
398 (page)->virtual = (address); \
399 } while(0)
400 #define page_address_init() do { } while(0)
401 #endif
403 #if defined(HASHED_PAGE_VIRTUAL)
404 void *page_address(struct page_info *page);
405 void set_page_address(struct page_info *page, void *virtual);
406 void page_address_init(void);
407 #endif
409 #if !defined(HASHED_PAGE_VIRTUAL) && !defined(WANT_PAGE_VIRTUAL)
410 #define page_address(page) lowmem_page_address(page)
411 #define set_page_address(page, address) do { } while(0)
412 #define page_address_init() do { } while(0)
413 #endif
416 #ifndef CONFIG_DEBUG_PAGEALLOC
417 static inline void
418 kernel_map_pages(struct page_info *page, int numpages, int enable)
419 {
420 }
421 #endif
423 extern unsigned long num_physpages;
424 extern unsigned long totalram_pages;
425 extern int nr_swap_pages;
427 extern void alloc_dom_xen_and_dom_io(void);
428 extern int mm_teardown(struct domain* d);
429 extern void mm_final_teardown(struct domain* d);
430 extern struct page_info * assign_new_domain_page(struct domain *d, unsigned long mpaddr);
431 extern void assign_new_domain0_page(struct domain *d, unsigned long mpaddr);
432 extern int __assign_domain_page(struct domain *d, unsigned long mpaddr, unsigned long physaddr, unsigned long flags);
433 extern void assign_domain_page(struct domain *d, unsigned long mpaddr, unsigned long physaddr);
434 extern void assign_domain_io_page(struct domain *d, unsigned long mpaddr, unsigned long flags);
435 extern int deassign_domain_mmio_page(struct domain *d, unsigned long mpaddr,
436 unsigned long phys_addr, unsigned long size);
437 struct p2m_entry;
438 extern unsigned long lookup_domain_mpa(struct domain *d, unsigned long mpaddr, struct p2m_entry* entry);
439 extern void *domain_mpa_to_imva(struct domain *d, unsigned long mpaddr);
440 extern volatile pte_t *lookup_noalloc_domain_pte(struct domain* d, unsigned long mpaddr);
441 extern unsigned long assign_domain_mmio_page(struct domain *d, unsigned long mpaddr, unsigned long phys_addr, unsigned long size, unsigned long flags);
442 extern unsigned long assign_domain_mach_page(struct domain *d, unsigned long mpaddr, unsigned long size, unsigned long flags);
443 int domain_page_mapped(struct domain *d, unsigned long mpaddr);
444 int efi_mmio(unsigned long physaddr, unsigned long size);
445 extern unsigned long ____lookup_domain_mpa(struct domain *d, unsigned long mpaddr);
446 extern unsigned long do_dom0vp_op(unsigned long cmd, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3);
447 extern unsigned long dom0vp_zap_physmap(struct domain *d, unsigned long gpfn, unsigned int extent_order);
448 extern unsigned long dom0vp_add_physmap(struct domain* d, unsigned long gpfn, unsigned long mfn, unsigned long flags, domid_t domid);
449 extern unsigned long dom0vp_add_physmap_with_gmfn(struct domain* d, unsigned long gpfn, unsigned long gmfn, unsigned long flags, domid_t domid);
450 #ifdef CONFIG_XEN_IA64_EXPOSE_P2M
451 extern void expose_p2m_init(void);
452 extern unsigned long dom0vp_expose_p2m(struct domain* d, unsigned long conv_start_gpfn, unsigned long assign_start_gpfn, unsigned long expose_size, unsigned long granule_pfn);
453 extern void foreign_p2m_init(struct domain* d);
454 extern void foreign_p2m_destroy(struct domain* d);
455 extern unsigned long dom0vp_expose_foreign_p2m(struct domain* dest_dom, unsigned long dest_gpfn, domid_t domid, XEN_GUEST_HANDLE(char) buffer, unsigned long flags);
456 extern unsigned long dom0vp_unexpose_foreign_p2m(struct domain* dest_dom, unsigned long dest_gpfn, domid_t domid);
457 extern unsigned long dom0vp_get_memmap(domid_t domid, XEN_GUEST_HANDLE(char) buffer);
458 #else
459 #define expose_p2m_init() do { } while (0)
460 #define dom0vp_expose_p2m(d, conv_start_gpfn, assign_start_gpfn, expose_size, granule_pfn) (-ENOSYS)
461 #define foreign_p2m_init(d) do { } while (0)
462 #define foreign_p2m_destroy(d) do { } while (0)
463 #define dom0vp_expose_foreign_p2m(dest_dom, dest_gpfn, domid, buffer, flags) (-ENOSYS)
464 #define dom0vp_unexpose_foreign_p2m(dest_dom, dest_gpfn, domid) (-ENOSYS)
465 #define __dom0vp_add_memdesc(d, memmap_info, memdesc) (-ENOSYS)
466 #define dom0vp_get_memmap(domid, buffer) (-ENOSYS)
467 #endif
469 int
470 p2m_pod_decrease_reservation(struct domain *d,
471 xen_pfn_t gpfn, unsigned int order);
472 int guest_physmap_mark_populate_on_demand(struct domain *d, unsigned long gfn,
473 unsigned int order);
475 extern volatile unsigned long *mpt_table;
476 extern unsigned long gmfn_to_mfn_foreign(struct domain *d, unsigned long gpfn);
477 extern u64 translate_domain_pte(u64 pteval, u64 address, u64 itir__,
478 u64* itir, struct p2m_entry* entry);
479 #define machine_to_phys_mapping mpt_table
481 #define INVALID_M2P_ENTRY (~0UL)
482 #define VALID_M2P(_e) (!((_e) & (1UL<<63)))
484 #define set_gpfn_from_mfn(mfn, pfn) (machine_to_phys_mapping[(mfn)] = (pfn))
485 #define get_gpfn_from_mfn(mfn) (machine_to_phys_mapping[(mfn)])
487 /* If pmt table is provided by control pannel later, we need __get_user
488 * here. However if it's allocated by HV, we should access it directly
489 */
491 #define mfn_to_gmfn(_d, mfn) \
492 get_gpfn_from_mfn(mfn)
494 #define gmfn_to_mfn(_d, gpfn) \
495 gmfn_to_mfn_foreign((_d), (gpfn))
497 #define __gpfn_invalid(_d, gpfn) \
498 (lookup_domain_mpa((_d), ((gpfn)<<PAGE_SHIFT), NULL) == INVALID_MFN)
500 #define __gmfn_valid(_d, gpfn) !__gpfn_invalid(_d, gpfn)
502 #define __gpa_to_mpa(_d, gpa) \
503 ((gmfn_to_mfn((_d),(gpa)>>PAGE_SHIFT)<<PAGE_SHIFT)|((gpa)&~PAGE_MASK))
505 #define __mpa_to_gpa(madr) \
506 ((get_gpfn_from_mfn((madr) >> PAGE_SHIFT) << PAGE_SHIFT) | \
507 ((madr) & ~PAGE_MASK))
509 /* Internal use only: returns 0 in case of bad address. */
510 extern unsigned long paddr_to_maddr(unsigned long paddr);
512 /* Arch-specific portion of memory_op hypercall. */
513 long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg);
515 int steal_page(
516 struct domain *d, struct page_info *page, unsigned int memflags);
518 #define domain_clamp_alloc_bitsize(d, b) (b)
520 unsigned long domain_get_maximum_gpfn(struct domain *d);
522 extern struct domain *dom_xen, *dom_io; /* for vmcoreinfo */
524 #endif /* __ASM_IA64_MM_H__ */