debuggers.hg

view xen/include/asm-x86/mm.h @ 3726:88957a238191

bitkeeper revision 1.1159.1.544 (4207248crq3YxiyLWjUehtHv_Yd3tg)

Merge tempest.cl.cam.ac.uk:/auto/groups/xeno-xenod/BK/xeno.bk
into tempest.cl.cam.ac.uk:/local/scratch/smh22/xen-unstable.bk
author smh22@tempest.cl.cam.ac.uk
date Mon Feb 07 08:19:24 2005 +0000 (2005-02-07)
parents bbe8541361dd 253e8e10e986
children f5f2757b3aa2
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>
17 #include <public/xen.h>
19 /*
20 * Per-page-frame information.
21 *
22 * Every architecture must ensure the following:
23 * 1. 'struct pfn_info' contains a 'struct list_head list'.
24 * 2. Provide a PFN_ORDER() macro for accessing the order of a free page.
25 */
26 #define PFN_ORDER(_pfn) ((_pfn)->u.free.order)
28 struct pfn_info
29 {
30 /* Each frame can be threaded onto a doubly-linked list. */
31 struct list_head list;
33 /* Timestamp from 'TLB clock', used to reduce need for safety flushes. */
34 u32 tlbflush_timestamp;
36 /* Reference count and various PGC_xxx flags and fields. */
37 u32 count_info;
39 /* Context-dependent fields follow... */
40 union {
42 /* Page is in use: ((count_info & PGC_count_mask) != 0). */
43 struct {
44 /* Owner of this page (NULL if page is anonymous). */
45 u32 _domain; /* pickled format */
46 /* Type reference count and various PGT_xxx flags and fields. */
47 u32 type_info;
48 } PACKED inuse;
50 /* Page is on a free list: ((count_info & PGC_count_mask) == 0). */
51 struct {
52 /* Mask of possibly-tainted TLBs. */
53 u32 cpu_mask;
54 /* Order-size of the free chunk this page is the head of. */
55 u8 order;
56 } PACKED free;
58 } PACKED u;
60 } PACKED;
62 /* The following page types are MUTUALLY EXCLUSIVE. */
63 #define PGT_none (0<<29) /* no special uses of this page */
64 #define PGT_l1_page_table (1<<29) /* using this page as an L1 page table? */
65 #define PGT_l2_page_table (2<<29) /* using this page as an L2 page table? */
66 #define PGT_l3_page_table (3<<29) /* using this page as an L3 page table? */
67 #define PGT_l4_page_table (4<<29) /* using this page as an L4 page table? */
68 #define PGT_gdt_page (5<<29) /* using this page in a GDT? */
69 #define PGT_ldt_page (6<<29) /* using this page in an LDT? */
70 #define PGT_writable_page (7<<29) /* has writable mappings of this page? */
71 #define PGT_type_mask (7<<29) /* Bits 29-31. */
72 /* Has this page been validated for use as its current type? */
73 #define _PGT_validated 28
74 #define PGT_validated (1U<<_PGT_validated)
75 /* Owning guest has pinned this page to its current type? */
76 #define _PGT_pinned 27
77 #define PGT_pinned (1U<<_PGT_pinned)
78 /* The 10 most significant bits of virt address if this is a page table. */
79 #define PGT_va_shift 17
80 #define PGT_va_mask (((1U<<10)-1)<<PGT_va_shift)
81 /* Is the back pointer still mutable (i.e. not fixed yet)? */
82 #define PGT_va_mutable (((1U<<10)-1)<<PGT_va_shift)
83 /* Is the back pointer unknown (e.g., p.t. is mapped at multiple VAs)? */
84 #define PGT_va_unknown (((1U<<10)-2)<<PGT_va_shift)
85 /* 17-bit count of uses of this frame as its current type. */
86 #define PGT_count_mask ((1U<<17)-1)
88 /* Cleared when the owning guest 'frees' this page. */
89 #define _PGC_allocated 31
90 #define PGC_allocated (1U<<_PGC_allocated)
91 /* 31-bit count of references to this frame. */
92 #define PGC_count_mask ((1U<<31)-1)
94 /* We trust the slab allocator in slab.c, and our use of it. */
95 #define PageSlab(page) (1)
96 #define PageSetSlab(page) ((void)0)
97 #define PageClearSlab(page) ((void)0)
99 #define IS_XEN_HEAP_FRAME(_pfn) (page_to_phys(_pfn) < xenheap_phys_end)
101 #if defined(__i386__)
103 #define pickle_domptr(_d) ((u32)(unsigned long)(_d))
104 #define unpickle_domptr(_d) ((struct domain *)(unsigned long)(_d))
106 #elif defined(__x86_64__)
107 static inline struct domain *unpickle_domptr(u32 _domain)
108 { return (_domain == 0) ? NULL : __va(_domain); }
109 static inline u32 pickle_domptr(struct domain *domain)
110 { return (domain == NULL) ? 0 : (u32)__pa(domain); }
112 #endif
114 #define page_get_owner(_p) (unpickle_domptr((_p)->u.inuse._domain))
115 #define page_set_owner(_p,_d) ((_p)->u.inuse._domain = pickle_domptr(_d))
117 #define SHARE_PFN_WITH_DOMAIN(_pfn, _dom) \
118 do { \
119 page_set_owner((_pfn), (_dom)); \
120 /* The incremented type count is intended to pin to 'writable'. */ \
121 (_pfn)->u.inuse.type_info = PGT_writable_page | PGT_validated | 1; \
122 wmb(); /* install valid domain ptr before updating refcnt. */ \
123 spin_lock(&(_dom)->page_alloc_lock); \
124 /* _dom holds an allocation reference */ \
125 ASSERT((_pfn)->count_info == 0); \
126 (_pfn)->count_info |= PGC_allocated | 1; \
127 if ( unlikely((_dom)->xenheap_pages++ == 0) ) \
128 get_knownalive_domain(_dom); \
129 list_add_tail(&(_pfn)->list, &(_dom)->xenpage_list); \
130 spin_unlock(&(_dom)->page_alloc_lock); \
131 } while ( 0 )
133 #define INVALID_P2M_ENTRY (~0UL)
135 extern struct pfn_info *frame_table;
136 extern unsigned long frame_table_size;
137 extern unsigned long max_page;
138 void init_frametable(void);
140 int alloc_page_type(struct pfn_info *page, unsigned int type);
141 void free_page_type(struct pfn_info *page, unsigned int type);
143 static inline void put_page(struct pfn_info *page)
144 {
145 u32 nx, x, y = page->count_info;
147 do {
148 x = y;
149 nx = x - 1;
150 }
151 while ( unlikely((y = cmpxchg(&page->count_info, x, nx)) != x) );
153 if ( unlikely((nx & PGC_count_mask) == 0) )
154 free_domheap_page(page);
155 }
158 static inline int get_page(struct pfn_info *page,
159 struct domain *domain)
160 {
161 u32 x, nx, y = page->count_info;
162 u32 d, nd = page->u.inuse._domain;
163 u32 _domain = pickle_domptr(domain);
165 do {
166 x = y;
167 nx = x + 1;
168 d = nd;
169 if ( unlikely((x & PGC_count_mask) == 0) || /* Not allocated? */
170 unlikely((nx & PGC_count_mask) == 0) || /* Count overflow? */
171 unlikely(d != _domain) ) /* Wrong owner? */
172 {
173 DPRINTK("Error pfn %08lx: ed=%p, sd=%p, caf=%08x, taf=%08x\n",
174 page_to_pfn(page), domain, unpickle_domptr(d),
175 x, page->u.inuse.type_info);
176 return 0;
177 }
178 __asm__ __volatile__(
179 LOCK_PREFIX "cmpxchg8b %3"
180 : "=d" (nd), "=a" (y), "=c" (d),
181 "=m" (*(volatile u64 *)(&page->count_info))
182 : "0" (d), "1" (x), "c" (d), "b" (nx) );
183 }
184 while ( unlikely(nd != d) || unlikely(y != x) );
186 return 1;
187 }
189 void put_page_type(struct pfn_info *page);
190 int get_page_type(struct pfn_info *page, u32 type);
192 static inline void put_page_and_type(struct pfn_info *page)
193 {
194 put_page_type(page);
195 put_page(page);
196 }
199 static inline int get_page_and_type(struct pfn_info *page,
200 struct domain *domain,
201 u32 type)
202 {
203 int rc = get_page(page, domain);
205 if ( likely(rc) && unlikely(!get_page_type(page, type)) )
206 {
207 put_page(page);
208 rc = 0;
209 }
211 return rc;
212 }
214 #define ASSERT_PAGE_IS_TYPE(_p, _t) \
215 ASSERT(((_p)->u.inuse.type_info & PGT_type_mask) == (_t)); \
216 ASSERT(((_p)->u.inuse.type_info & PGT_count_mask) != 0)
217 #define ASSERT_PAGE_IS_DOMAIN(_p, _d) \
218 ASSERT(((_p)->count_info & PGC_count_mask) != 0); \
219 ASSERT(page_get_owner(_p) == (_d))
221 int check_descriptor(unsigned long *d);
223 /*
224 * Use currently-executing domain's pagetables on the specified CPUs.
225 * i.e., stop borrowing someone else's tables if you are the idle domain.
226 */
227 void synchronise_pagetables(unsigned long cpu_mask);
229 /*
230 * The MPT (machine->physical mapping table) is an array of word-sized
231 * values, indexed on machine frame number. It is expected that guest OSes
232 * will use it to store a "physical" frame number to give the appearance of
233 * contiguous (or near contiguous) physical memory.
234 */
235 #undef machine_to_phys_mapping
237 /*
238 * The phys_to_machine_mapping is the reversed mapping of MPT for full
239 * virtualization.
240 */
241 #undef phys_to_machine_mapping
243 #define machine_to_phys_mapping ((unsigned long *)RDWR_MPT_VIRT_START)
244 #define phys_to_machine_mapping ((unsigned long *)PERDOMAIN_VIRT_START)
246 #define set_machinetophys(_mfn, _pfn) machine_to_phys_mapping[(_mfn)] = (_pfn)
248 #define DEFAULT_GDT_ENTRIES (LAST_RESERVED_GDT_ENTRY+1)
249 #define DEFAULT_GDT_ADDRESS ((unsigned long)gdt_table)
251 #ifdef MEMORY_GUARD
252 void *memguard_init(void *heap_start);
253 void memguard_guard_stack(void *p);
254 void memguard_guard_range(void *p, unsigned long l);
255 void memguard_unguard_range(void *p, unsigned long l);
256 #else
257 #define memguard_init(_s) (_s)
258 #define memguard_guard_stack(_p) ((void)0)
259 #define memguard_guard_range(_p,_l) ((void)0)
260 #define memguard_unguard_range(_p,_l) ((void)0)
261 #endif
264 typedef struct {
265 void (*enable)(struct domain *);
266 void (*disable)(struct domain *);
267 } vm_assist_info_t;
268 extern vm_assist_info_t vm_assist_info[];
271 /* Writable Pagetables */
272 typedef struct {
273 /* Linear address where the guest is updating the p.t. page. */
274 unsigned long l1va;
275 /* Copy of the p.t. page, taken before guest is given write access. */
276 l1_pgentry_t *page;
277 /* A temporary Xen mapping of the actual p.t. page. */
278 l1_pgentry_t *pl1e;
279 /* Index in L2 page table where this L1 p.t. is always hooked. */
280 unsigned int l2_idx; /* NB. Only used for PTWR_PT_ACTIVE. */
281 } ptwr_ptinfo_t;
283 typedef struct {
284 ptwr_ptinfo_t ptinfo[2];
285 } __cacheline_aligned ptwr_info_t;
287 extern ptwr_info_t ptwr_info[];
289 #define PTWR_PT_ACTIVE 0
290 #define PTWR_PT_INACTIVE 1
292 #define PTWR_CLEANUP_ACTIVE 1
293 #define PTWR_CLEANUP_INACTIVE 2
295 void ptwr_flush(const int);
296 int ptwr_do_page_fault(unsigned long);
298 int new_guest_cr3(unsigned long pfn);
300 #define __cleanup_writable_pagetable(_what) \
301 do { \
302 int cpu = smp_processor_id(); \
303 if ((_what) & PTWR_CLEANUP_ACTIVE) \
304 if (ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].l1va) \
305 ptwr_flush(PTWR_PT_ACTIVE); \
306 if ((_what) & PTWR_CLEANUP_INACTIVE) \
307 if (ptwr_info[cpu].ptinfo[PTWR_PT_INACTIVE].l1va) \
308 ptwr_flush(PTWR_PT_INACTIVE); \
309 } while ( 0 )
311 #define cleanup_writable_pagetable(_d) \
312 do { \
313 if ( unlikely(VM_ASSIST((_d), VMASST_TYPE_writable_pagetables)) ) \
314 __cleanup_writable_pagetable(PTWR_CLEANUP_ACTIVE | \
315 PTWR_CLEANUP_INACTIVE); \
316 } while ( 0 )
318 #ifndef NDEBUG
319 void audit_domain(struct domain *d);
320 void audit_domains(void);
321 #else
322 #define audit_domain(_d) ((void)0)
323 #define audit_domains() ((void)0)
324 #endif
326 void propagate_page_fault(unsigned long addr, u16 error_code);
328 #endif /* __ASM_X86_MM_H__ */