debuggers.hg

view xen/include/asm-x86/mm.h @ 3746:9e80fc0dcac5

bitkeeper revision 1.1159.212.121 (42081031Gcfd1G5fgexBl7vd4XfmLQ)

Use 1:1 pagetables used for guest physical mode emulation for doing
phys_to_machine_mapping as well.

Signed-off-by: Arun Sharma <arun.sharma@intel.com>
Signed-off-by: ian@xensource.com
author iap10@labyrinth.cl.cam.ac.uk
date Tue Feb 08 01:04:49 2005 +0000 (2005-02-08)
parents ef5e5cd10778
children 23e7cf28ddb3
line source
2 #ifndef __ASM_X86_MM_H__
3 #define __ASM_X86_MM_H__
5 #include <xen/config.h>
6 #include <xen/list.h>
7 #include <xen/spinlock.h>
8 #include <xen/perfc.h>
9 #include <xen/sched.h>
11 #include <asm/processor.h>
12 #include <asm/atomic.h>
13 #include <asm/desc.h>
14 #include <asm/flushtlb.h>
15 #include <asm/io.h>
16 #include <asm/uaccess.h>
18 #include <public/xen.h>
20 /*
21 * Per-page-frame information.
22 *
23 * Every architecture must ensure the following:
24 * 1. 'struct pfn_info' contains a 'struct list_head list'.
25 * 2. Provide a PFN_ORDER() macro for accessing the order of a free page.
26 */
27 #define PFN_ORDER(_pfn) ((_pfn)->u.free.order)
29 struct pfn_info
30 {
31 /* Each frame can be threaded onto a doubly-linked list. */
32 struct list_head list;
34 /* Timestamp from 'TLB clock', used to reduce need for safety flushes. */
35 u32 tlbflush_timestamp;
37 /* Reference count and various PGC_xxx flags and fields. */
38 u32 count_info;
40 /* Context-dependent fields follow... */
41 union {
43 /* Page is in use: ((count_info & PGC_count_mask) != 0). */
44 struct {
45 /* Owner of this page (NULL if page is anonymous). */
46 u32 _domain; /* pickled format */
47 /* Type reference count and various PGT_xxx flags and fields. */
48 u32 type_info;
49 } PACKED inuse;
51 /* Page is on a free list: ((count_info & PGC_count_mask) == 0). */
52 struct {
53 /* Mask of possibly-tainted TLBs. */
54 u32 cpu_mask;
55 /* Order-size of the free chunk this page is the head of. */
56 u8 order;
57 } PACKED free;
59 } PACKED u;
61 } PACKED;
63 /* The following page types are MUTUALLY EXCLUSIVE. */
64 #define PGT_none (0<<29) /* no special uses of this page */
65 #define PGT_l1_page_table (1<<29) /* using this page as an L1 page table? */
66 #define PGT_l2_page_table (2<<29) /* using this page as an L2 page table? */
67 #define PGT_l3_page_table (3<<29) /* using this page as an L3 page table? */
68 #define PGT_l4_page_table (4<<29) /* using this page as an L4 page table? */
69 #define PGT_gdt_page (5<<29) /* using this page in a GDT? */
70 #define PGT_ldt_page (6<<29) /* using this page in an LDT? */
71 #define PGT_writable_page (7<<29) /* has writable mappings of this page? */
72 #define PGT_type_mask (7<<29) /* Bits 29-31. */
73 /* Has this page been validated for use as its current type? */
74 #define _PGT_validated 28
75 #define PGT_validated (1U<<_PGT_validated)
76 /* Owning guest has pinned this page to its current type? */
77 #define _PGT_pinned 27
78 #define PGT_pinned (1U<<_PGT_pinned)
79 /* The 10 most significant bits of virt address if this is a page table. */
80 #define PGT_va_shift 17
81 #define PGT_va_mask (((1U<<10)-1)<<PGT_va_shift)
82 /* Is the back pointer still mutable (i.e. not fixed yet)? */
83 #define PGT_va_mutable (((1U<<10)-1)<<PGT_va_shift)
84 /* Is the back pointer unknown (e.g., p.t. is mapped at multiple VAs)? */
85 #define PGT_va_unknown (((1U<<10)-2)<<PGT_va_shift)
86 /* 17-bit count of uses of this frame as its current type. */
87 #define PGT_count_mask ((1U<<17)-1)
89 /* Cleared when the owning guest 'frees' this page. */
90 #define _PGC_allocated 31
91 #define PGC_allocated (1U<<_PGC_allocated)
92 /* 31-bit count of references to this frame. */
93 #define PGC_count_mask ((1U<<31)-1)
95 /* We trust the slab allocator in slab.c, and our use of it. */
96 #define PageSlab(page) (1)
97 #define PageSetSlab(page) ((void)0)
98 #define PageClearSlab(page) ((void)0)
100 #define IS_XEN_HEAP_FRAME(_pfn) (page_to_phys(_pfn) < xenheap_phys_end)
102 #if defined(__i386__)
104 #define pickle_domptr(_d) ((u32)(unsigned long)(_d))
105 #define unpickle_domptr(_d) ((struct domain *)(unsigned long)(_d))
107 #elif defined(__x86_64__)
108 static inline struct domain *unpickle_domptr(u32 _domain)
109 { return (_domain == 0) ? NULL : __va(_domain); }
110 static inline u32 pickle_domptr(struct domain *domain)
111 { return (domain == NULL) ? 0 : (u32)__pa(domain); }
113 #endif
115 #define page_get_owner(_p) (unpickle_domptr((_p)->u.inuse._domain))
116 #define page_set_owner(_p,_d) ((_p)->u.inuse._domain = pickle_domptr(_d))
118 #define SHARE_PFN_WITH_DOMAIN(_pfn, _dom) \
119 do { \
120 page_set_owner((_pfn), (_dom)); \
121 /* The incremented type count is intended to pin to 'writable'. */ \
122 (_pfn)->u.inuse.type_info = PGT_writable_page | PGT_validated | 1; \
123 wmb(); /* install valid domain ptr before updating refcnt. */ \
124 spin_lock(&(_dom)->page_alloc_lock); \
125 /* _dom holds an allocation reference */ \
126 ASSERT((_pfn)->count_info == 0); \
127 (_pfn)->count_info |= PGC_allocated | 1; \
128 if ( unlikely((_dom)->xenheap_pages++ == 0) ) \
129 get_knownalive_domain(_dom); \
130 list_add_tail(&(_pfn)->list, &(_dom)->xenpage_list); \
131 spin_unlock(&(_dom)->page_alloc_lock); \
132 } while ( 0 )
134 #define INVALID_P2M_ENTRY (~0UL)
136 extern struct pfn_info *frame_table;
137 extern unsigned long frame_table_size;
138 extern unsigned long max_page;
139 void init_frametable(void);
141 int alloc_page_type(struct pfn_info *page, unsigned int type);
142 void free_page_type(struct pfn_info *page, unsigned int type);
144 static inline void put_page(struct pfn_info *page)
145 {
146 u32 nx, x, y = page->count_info;
148 do {
149 x = y;
150 nx = x - 1;
151 }
152 while ( unlikely((y = cmpxchg(&page->count_info, x, nx)) != x) );
154 if ( unlikely((nx & PGC_count_mask) == 0) )
155 free_domheap_page(page);
156 }
159 static inline int get_page(struct pfn_info *page,
160 struct domain *domain)
161 {
162 u32 x, nx, y = page->count_info;
163 u32 d, nd = page->u.inuse._domain;
164 u32 _domain = pickle_domptr(domain);
166 do {
167 x = y;
168 nx = x + 1;
169 d = nd;
170 if ( unlikely((x & PGC_count_mask) == 0) || /* Not allocated? */
171 unlikely((nx & PGC_count_mask) == 0) || /* Count overflow? */
172 unlikely(d != _domain) ) /* Wrong owner? */
173 {
174 DPRINTK("Error pfn %08lx: ed=%p, sd=%p, caf=%08x, taf=%08x\n",
175 page_to_pfn(page), domain, unpickle_domptr(d),
176 x, page->u.inuse.type_info);
177 return 0;
178 }
179 __asm__ __volatile__(
180 LOCK_PREFIX "cmpxchg8b %3"
181 : "=d" (nd), "=a" (y), "=c" (d),
182 "=m" (*(volatile u64 *)(&page->count_info))
183 : "0" (d), "1" (x), "c" (d), "b" (nx) );
184 }
185 while ( unlikely(nd != d) || unlikely(y != x) );
187 return 1;
188 }
190 void put_page_type(struct pfn_info *page);
191 int get_page_type(struct pfn_info *page, u32 type);
193 static inline void put_page_and_type(struct pfn_info *page)
194 {
195 put_page_type(page);
196 put_page(page);
197 }
200 static inline int get_page_and_type(struct pfn_info *page,
201 struct domain *domain,
202 u32 type)
203 {
204 int rc = get_page(page, domain);
206 if ( likely(rc) && unlikely(!get_page_type(page, type)) )
207 {
208 put_page(page);
209 rc = 0;
210 }
212 return rc;
213 }
215 #define ASSERT_PAGE_IS_TYPE(_p, _t) \
216 ASSERT(((_p)->u.inuse.type_info & PGT_type_mask) == (_t)); \
217 ASSERT(((_p)->u.inuse.type_info & PGT_count_mask) != 0)
218 #define ASSERT_PAGE_IS_DOMAIN(_p, _d) \
219 ASSERT(((_p)->count_info & PGC_count_mask) != 0); \
220 ASSERT(page_get_owner(_p) == (_d))
222 int check_descriptor(unsigned long *d);
224 /*
225 * Use currently-executing domain's pagetables on the specified CPUs.
226 * i.e., stop borrowing someone else's tables if you are the idle domain.
227 */
228 void synchronise_pagetables(unsigned long cpu_mask);
230 /*
231 * The MPT (machine->physical mapping table) is an array of word-sized
232 * values, indexed on machine frame number. It is expected that guest OSes
233 * will use it to store a "physical" frame number to give the appearance of
234 * contiguous (or near contiguous) physical memory.
235 */
236 #undef machine_to_phys_mapping
238 /*
239 * The phys_to_machine_mapping is the reversed mapping of MPT for full
240 * virtualization.
241 */
242 #undef phys_to_machine_mapping
244 #define machine_to_phys_mapping ((unsigned long *)RDWR_MPT_VIRT_START)
245 #define __phys_to_machine_mapping ((unsigned long *)PERDOMAIN_VIRT_START)
246 /* Returns the machine physical */
247 static inline unsigned long phys_to_machine_mapping(unsigned long pfn)
248 {
249 unsigned long mfn;
250 l1_pgentry_t pte;
252 if (__get_user(l1_pgentry_val(pte), (__phys_to_machine_mapping + pfn))) {
253 return 0;
254 }
256 mfn = l1_pgentry_to_phys(pte) >> PAGE_SHIFT;
257 return mfn;
258 }
259 #define set_machinetophys(_mfn, _pfn) machine_to_phys_mapping[(_mfn)] = (_pfn)
261 #define DEFAULT_GDT_ENTRIES (LAST_RESERVED_GDT_ENTRY+1)
262 #define DEFAULT_GDT_ADDRESS ((unsigned long)gdt_table)
264 #ifdef MEMORY_GUARD
265 void *memguard_init(void *heap_start);
266 void memguard_guard_stack(void *p);
267 void memguard_guard_range(void *p, unsigned long l);
268 void memguard_unguard_range(void *p, unsigned long l);
269 #else
270 #define memguard_init(_s) (_s)
271 #define memguard_guard_stack(_p) ((void)0)
272 #define memguard_guard_range(_p,_l) ((void)0)
273 #define memguard_unguard_range(_p,_l) ((void)0)
274 #endif
277 typedef struct {
278 void (*enable)(struct domain *);
279 void (*disable)(struct domain *);
280 } vm_assist_info_t;
281 extern vm_assist_info_t vm_assist_info[];
284 /* Writable Pagetables */
285 typedef struct {
286 /* Linear address where the guest is updating the p.t. page. */
287 unsigned long l1va;
288 /* Copy of the p.t. page, taken before guest is given write access. */
289 l1_pgentry_t *page;
290 /* A temporary Xen mapping of the actual p.t. page. */
291 l1_pgentry_t *pl1e;
292 /* Index in L2 page table where this L1 p.t. is always hooked. */
293 unsigned int l2_idx; /* NB. Only used for PTWR_PT_ACTIVE. */
294 } ptwr_ptinfo_t;
296 typedef struct {
297 ptwr_ptinfo_t ptinfo[2];
298 } __cacheline_aligned ptwr_info_t;
300 extern ptwr_info_t ptwr_info[];
302 #define PTWR_PT_ACTIVE 0
303 #define PTWR_PT_INACTIVE 1
305 #define PTWR_CLEANUP_ACTIVE 1
306 #define PTWR_CLEANUP_INACTIVE 2
308 void ptwr_flush(const int);
309 int ptwr_do_page_fault(unsigned long);
311 int new_guest_cr3(unsigned long pfn);
313 #define __cleanup_writable_pagetable(_what) \
314 do { \
315 int cpu = smp_processor_id(); \
316 if ((_what) & PTWR_CLEANUP_ACTIVE) \
317 if (ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].l1va) \
318 ptwr_flush(PTWR_PT_ACTIVE); \
319 if ((_what) & PTWR_CLEANUP_INACTIVE) \
320 if (ptwr_info[cpu].ptinfo[PTWR_PT_INACTIVE].l1va) \
321 ptwr_flush(PTWR_PT_INACTIVE); \
322 } while ( 0 )
324 #define cleanup_writable_pagetable(_d) \
325 do { \
326 if ( unlikely(VM_ASSIST((_d), VMASST_TYPE_writable_pagetables)) ) \
327 __cleanup_writable_pagetable(PTWR_CLEANUP_ACTIVE | \
328 PTWR_CLEANUP_INACTIVE); \
329 } while ( 0 )
331 #ifndef NDEBUG
332 void audit_domain(struct domain *d);
333 void audit_domains(void);
334 #else
335 #define audit_domain(_d) ((void)0)
336 #define audit_domains() ((void)0)
337 #endif
339 void propagate_page_fault(unsigned long addr, u16 error_code);
341 #endif /* __ASM_X86_MM_H__ */