debuggers.hg

annotate xen/include/asm-x86/mm.h @ 3632:fec8b1778268

bitkeeper revision 1.1159.212.60 (41febc4bKKSkh9u-Zes9v2CmBuLZxA)

More bootstrap fixes for x86/64. Next thing to do is sort out the IDT and
get traps.c working; then we can get rid of a bunch of dummy labels from
end of boot/x86_64.S. We're also going to need some kind of entry.S before
we can safely enable interrupts. Also bear in mind that not all of physical
RAM may be mapped (only first 1GB) and no m2p table is yet allocated or
mapped. Plenty to be done!
author kaf24@viper.(none)
date Mon Jan 31 23:16:27 2005 +0000 (2005-01-31)
parents eef1949801b8
children d55d523078f7
rev   line source
djm@1747 1
djm@1747 2 #ifndef __ASM_X86_MM_H__
djm@1747 3 #define __ASM_X86_MM_H__
djm@1747 4
djm@1747 5 #include <xen/config.h>
djm@1747 6 #include <xen/list.h>
djm@1747 7 #include <xen/spinlock.h>
djm@1747 8 #include <xen/perfc.h>
djm@1747 9 #include <xen/sched.h>
djm@1747 10
djm@1747 11 #include <asm/processor.h>
djm@1747 12 #include <asm/atomic.h>
djm@1747 13 #include <asm/desc.h>
djm@1747 14 #include <asm/flushtlb.h>
djm@1747 15 #include <asm/io.h>
djm@1747 16
kaf24@2827 17 #include <public/xen.h>
djm@1747 18
djm@1747 19 /*
djm@1747 20 * Per-page-frame information.
kaf24@1970 21 *
kaf24@1970 22 * Every architecture must ensure the following:
kaf24@1970 23 * 1. 'struct pfn_info' contains a 'struct list_head list'.
kaf24@1970 24 * 2. Provide a PFN_ORDER() macro for accessing the order of a free page.
djm@1747 25 */
kaf24@1970 26 #define PFN_ORDER(_pfn) ((_pfn)->u.free.order)
djm@1747 27
djm@1747 28 struct pfn_info
djm@1747 29 {
djm@1747 30 /* Each frame can be threaded onto a doubly-linked list. */
djm@1747 31 struct list_head list;
kaf24@1970 32
kaf24@2384 33 /* Reference count and various PGC_xxx flags and fields. */
kaf24@2384 34 u32 count_info;
kaf24@2384 35
kaf24@1970 36 /* Context-dependent fields follow... */
djm@1747 37 union {
kaf24@1970 38
kaf24@2384 39 /* Page is in use: ((count_info & PGC_count_mask) != 0). */
kaf24@1970 40 struct {
kaf24@2384 41 /* Owner of this page (NULL if page is anonymous). */
kaf24@1970 42 struct domain *domain;
kaf24@1970 43 /* Type reference count and various PGT_xxx flags and fields. */
kaf24@1970 44 u32 type_info;
kaf24@1970 45 } inuse;
kaf24@1970 46
kaf24@2384 47 /* Page is on a free list: ((count_info & PGC_count_mask) == 0). */
kaf24@1970 48 struct {
kaf24@1970 49 /* Mask of possibly-tainted TLBs. */
kaf24@1970 50 unsigned long cpu_mask;
kaf24@1970 51 /* Order-size of the free chunk this page is the head of. */
kaf24@1970 52 u8 order;
kaf24@1970 53 } free;
kaf24@1970 54
djm@1747 55 } u;
kaf24@1970 56
djm@1747 57 /* Timestamp from 'TLB clock', used to reduce need for safety flushes. */
djm@1747 58 u32 tlbflush_timestamp;
djm@1747 59 };
djm@1747 60
djm@1747 61 /* The following page types are MUTUALLY EXCLUSIVE. */
djm@1747 62 #define PGT_none (0<<29) /* no special uses of this page */
djm@1747 63 #define PGT_l1_page_table (1<<29) /* using this page as an L1 page table? */
djm@1747 64 #define PGT_l2_page_table (2<<29) /* using this page as an L2 page table? */
djm@1747 65 #define PGT_l3_page_table (3<<29) /* using this page as an L3 page table? */
djm@1747 66 #define PGT_l4_page_table (4<<29) /* using this page as an L4 page table? */
djm@1747 67 #define PGT_gdt_page (5<<29) /* using this page in a GDT? */
djm@1747 68 #define PGT_ldt_page (6<<29) /* using this page in an LDT? */
kaf24@2375 69 #define PGT_writable_page (7<<29) /* has writable mappings of this page? */
djm@1747 70 #define PGT_type_mask (7<<29) /* Bits 29-31. */
djm@1747 71 /* Has this page been validated for use as its current type? */
djm@1747 72 #define _PGT_validated 28
kaf24@2655 73 #define PGT_validated (1U<<_PGT_validated)
kaf24@2466 74 /* Owning guest has pinned this page to its current type? */
kaf24@2466 75 #define _PGT_pinned 27
kaf24@2655 76 #define PGT_pinned (1U<<_PGT_pinned)
kaf24@2466 77 /* The 10 most significant bits of virt address if this is a page table. */
kaf24@2466 78 #define PGT_va_shift 17
kaf24@2655 79 #define PGT_va_mask (((1U<<10)-1)<<PGT_va_shift)
kaf24@2506 80 /* Is the back pointer still mutable (i.e. not fixed yet)? */
kaf24@2655 81 #define PGT_va_mutable (((1U<<10)-1)<<PGT_va_shift)
kaf24@2506 82 /* Is the back pointer unknown (e.g., p.t. is mapped at multiple VAs)? */
kaf24@2655 83 #define PGT_va_unknown (((1U<<10)-2)<<PGT_va_shift)
kaf24@2466 84 /* 17-bit count of uses of this frame as its current type. */
kaf24@2655 85 #define PGT_count_mask ((1U<<17)-1)
djm@1747 86
djm@1747 87 /* Cleared when the owning guest 'frees' this page. */
kaf24@2655 88 #define _PGC_allocated 31
kaf24@2655 89 #define PGC_allocated (1U<<_PGC_allocated)
kaf24@2655 90 /* 31-bit count of references to this frame. */
kaf24@2655 91 #define PGC_count_mask ((1U<<31)-1)
djm@1747 92
djm@1747 93 /* We trust the slab allocator in slab.c, and our use of it. */
kaf24@2655 94 #define PageSlab(page) (1)
kaf24@2655 95 #define PageSetSlab(page) ((void)0)
kaf24@2655 96 #define PageClearSlab(page) ((void)0)
djm@1747 97
djm@1747 98 #define IS_XEN_HEAP_FRAME(_pfn) (page_to_phys(_pfn) < xenheap_phys_end)
djm@1747 99
djm@1747 100 #define SHARE_PFN_WITH_DOMAIN(_pfn, _dom) \
djm@1747 101 do { \
kaf24@1974 102 (_pfn)->u.inuse.domain = (_dom); \
kaf24@2375 103 /* The incremented type count is intended to pin to 'writable'. */ \
kaf24@2498 104 (_pfn)->u.inuse.type_info = PGT_writable_page | PGT_validated | 1; \
djm@1747 105 wmb(); /* install valid domain ptr before updating refcnt. */ \
djm@1747 106 spin_lock(&(_dom)->page_alloc_lock); \
djm@1747 107 /* _dom holds an allocation reference */ \
kaf24@2655 108 ASSERT((_pfn)->count_info == 0); \
kaf24@2384 109 (_pfn)->count_info |= PGC_allocated | 1; \
djm@1747 110 if ( unlikely((_dom)->xenheap_pages++ == 0) ) \
kaf24@2336 111 get_knownalive_domain(_dom); \
kaf24@2360 112 list_add_tail(&(_pfn)->list, &(_dom)->xenpage_list); \
djm@1747 113 spin_unlock(&(_dom)->page_alloc_lock); \
djm@1747 114 } while ( 0 )
djm@1747 115
iap10@2561 116 #define INVALID_P2M_ENTRY (~0UL)
iap10@2561 117
djm@1747 118 extern struct pfn_info *frame_table;
djm@1747 119 extern unsigned long frame_table_size;
djm@1747 120 extern unsigned long max_page;
kaf24@3392 121 void init_frametable(void);
djm@1747 122
djm@1747 123 int alloc_page_type(struct pfn_info *page, unsigned int type);
djm@1747 124 void free_page_type(struct pfn_info *page, unsigned int type);
djm@1747 125
djm@1747 126 static inline void put_page(struct pfn_info *page)
djm@1747 127 {
kaf24@2384 128 u32 nx, x, y = page->count_info;
djm@1747 129
djm@1747 130 do {
djm@1747 131 x = y;
djm@1747 132 nx = x - 1;
djm@1747 133 }
kaf24@2384 134 while ( unlikely((y = cmpxchg(&page->count_info, x, nx)) != x) );
djm@1747 135
djm@1747 136 if ( unlikely((nx & PGC_count_mask) == 0) )
kaf24@1979 137 free_domheap_page(page);
djm@1747 138 }
djm@1747 139
djm@1747 140
djm@1747 141 static inline int get_page(struct pfn_info *page,
djm@1747 142 struct domain *domain)
djm@1747 143 {
kaf24@2384 144 u32 x, nx, y = page->count_info;
kaf24@2498 145 struct domain *d, *nd = page->u.inuse.domain;
djm@1747 146
djm@1747 147 do {
djm@1747 148 x = y;
djm@1747 149 nx = x + 1;
kaf24@2498 150 d = nd;
djm@1747 151 if ( unlikely((x & PGC_count_mask) == 0) || /* Not allocated? */
djm@1747 152 unlikely((nx & PGC_count_mask) == 0) || /* Count overflow? */
kaf24@2498 153 unlikely(d != domain) ) /* Wrong owner? */
djm@1747 154 {
kaf24@2382 155 DPRINTK("Error pfn %08lx: ed=%p, sd=%p, caf=%08x, taf=%08x\n",
kaf24@2498 156 page_to_pfn(page), domain, d,
kaf24@1970 157 x, page->u.inuse.type_info);
djm@1747 158 return 0;
djm@1747 159 }
djm@1747 160 __asm__ __volatile__(
djm@1747 161 LOCK_PREFIX "cmpxchg8b %3"
kaf24@2498 162 : "=d" (nd), "=a" (y), "=c" (d),
kaf24@2384 163 "=m" (*(volatile u64 *)(&page->count_info))
kaf24@2498 164 : "0" (d), "1" (x), "c" (d), "b" (nx) );
djm@1747 165 }
kaf24@2498 166 while ( unlikely(nd != d) || unlikely(y != x) );
djm@1747 167
djm@1747 168 return 1;
djm@1747 169 }
djm@1747 170
kaf24@2498 171 void put_page_type(struct pfn_info *page);
kaf24@2498 172 int get_page_type(struct pfn_info *page, u32 type);
djm@1747 173
djm@1747 174 static inline void put_page_and_type(struct pfn_info *page)
djm@1747 175 {
djm@1747 176 put_page_type(page);
djm@1747 177 put_page(page);
djm@1747 178 }
djm@1747 179
djm@1747 180
djm@1747 181 static inline int get_page_and_type(struct pfn_info *page,
djm@1747 182 struct domain *domain,
djm@1747 183 u32 type)
djm@1747 184 {
djm@1747 185 int rc = get_page(page, domain);
djm@1747 186
djm@1747 187 if ( likely(rc) && unlikely(!get_page_type(page, type)) )
djm@1747 188 {
djm@1747 189 put_page(page);
djm@1747 190 rc = 0;
djm@1747 191 }
djm@1747 192
djm@1747 193 return rc;
djm@1747 194 }
djm@1747 195
kaf24@1974 196 #define ASSERT_PAGE_IS_TYPE(_p, _t) \
kaf24@1974 197 ASSERT(((_p)->u.inuse.type_info & PGT_type_mask) == (_t)); \
kaf24@1970 198 ASSERT(((_p)->u.inuse.type_info & PGT_count_mask) != 0)
kaf24@1974 199 #define ASSERT_PAGE_IS_DOMAIN(_p, _d) \
kaf24@2384 200 ASSERT(((_p)->count_info & PGC_count_mask) != 0); \
kaf24@1970 201 ASSERT((_p)->u.inuse.domain == (_d))
djm@1747 202
kaf24@1854 203 int check_descriptor(unsigned long *d);
djm@1747 204
djm@1747 205 /*
kaf24@1806 206 * Use currently-executing domain's pagetables on the specified CPUs.
kaf24@1806 207 * i.e., stop borrowing someone else's tables if you are the idle domain.
kaf24@1806 208 */
kaf24@1806 209 void synchronise_pagetables(unsigned long cpu_mask);
kaf24@1806 210
kaf24@1806 211 /*
djm@1747 212 * The MPT (machine->physical mapping table) is an array of word-sized
djm@1747 213 * values, indexed on machine frame number. It is expected that guest OSes
djm@1747 214 * will use it to store a "physical" frame number to give the appearance of
djm@1747 215 * contiguous (or near contiguous) physical memory.
djm@1747 216 */
djm@1747 217 #undef machine_to_phys_mapping
kaf24@3333 218
iap10@3328 219 /*
iap10@3328 220 * The phys_to_machine_mapping is the reversed mapping of MPT for full
iap10@3328 221 * virtualization.
iap10@3328 222 */
iap10@3328 223 #undef phys_to_machine_mapping
iap10@3328 224
sos22@3478 225 /* Don't call virt_to_phys on this: it isn't direct mapped. Using
sos22@3478 226 m2p_start_mfn instead. */
djm@1747 227 #define machine_to_phys_mapping ((unsigned long *)RDWR_MPT_VIRT_START)
sos22@3478 228 extern unsigned long m2p_start_mfn;
iap10@3328 229 #define phys_to_machine_mapping ((unsigned long *)PERDOMAIN_VIRT_START)
djm@1747 230
kaf24@3515 231 #define set_machinetophys(_mfn, _pfn) machine_to_phys_mapping[(_mfn)] = (_pfn)
kaf24@3515 232
kaf24@1854 233 #define DEFAULT_GDT_ENTRIES (LAST_RESERVED_GDT_ENTRY+1)
djm@1747 234 #define DEFAULT_GDT_ADDRESS ((unsigned long)gdt_table)
djm@1747 235
djm@1747 236 #ifdef MEMORY_GUARD
djm@1747 237 void *memguard_init(void *heap_start);
djm@1747 238 void memguard_guard_range(void *p, unsigned long l);
djm@1747 239 void memguard_unguard_range(void *p, unsigned long l);
djm@1747 240 #else
djm@1747 241 #define memguard_init(_s) (_s)
djm@1747 242 #define memguard_guard_range(_p,_l) ((void)0)
djm@1747 243 #define memguard_unguard_range(_p,_l) ((void)0)
djm@1747 244 #endif
djm@1747 245
cl349@2093 246
cl349@2227 247 typedef struct {
cl349@2486 248 void (*enable)(struct domain *);
cl349@2486 249 void (*disable)(struct domain *);
cl349@2227 250 } vm_assist_info_t;
cl349@2227 251 extern vm_assist_info_t vm_assist_info[];
cl349@2227 252
cl349@2227 253
cl349@2093 254 /* Writable Pagetables */
cl349@2093 255 typedef struct {
kaf24@2663 256 /* Linear address where the guest is updating the p.t. page. */
cl349@2512 257 unsigned long l1va;
kaf24@2663 258 /* Copy of the p.t. page, taken before guest is given write access. */
cl349@2512 259 l1_pgentry_t *page;
kaf24@2663 260 /* A temporary Xen mapping of the actual p.t. page. */
cl349@2512 261 l1_pgentry_t *pl1e;
kaf24@2663 262 /* Index in L2 page table where this L1 p.t. is always hooked. */
kaf24@2663 263 unsigned int l2_idx; /* NB. Only used for PTWR_PT_ACTIVE. */
cl349@2512 264 } ptwr_ptinfo_t;
cl349@2512 265
cl349@2512 266 typedef struct {
cl349@2512 267 ptwr_ptinfo_t ptinfo[2];
cl349@2093 268 } __cacheline_aligned ptwr_info_t;
cl349@2093 269
cl349@2093 270 extern ptwr_info_t ptwr_info[];
cl349@2093 271
cl349@2512 272 #define PTWR_PT_ACTIVE 0
cl349@2512 273 #define PTWR_PT_INACTIVE 1
cl349@2093 274
cl349@2512 275 #define PTWR_CLEANUP_ACTIVE 1
cl349@2512 276 #define PTWR_CLEANUP_INACTIVE 2
cl349@2512 277
cl349@2512 278 void ptwr_flush(const int);
cl349@1879 279 int ptwr_do_page_fault(unsigned long);
cl349@1879 280
kaf24@3443 281 int new_guest_cr3(unsigned long pfn);
kaf24@3443 282
cl349@2495 283 #define __cleanup_writable_pagetable(_what) \
cl349@2495 284 do { \
cl349@2495 285 int cpu = smp_processor_id(); \
cl349@2495 286 if ((_what) & PTWR_CLEANUP_ACTIVE) \
cl349@2512 287 if (ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].l1va) \
cl349@2512 288 ptwr_flush(PTWR_PT_ACTIVE); \
cl349@2495 289 if ((_what) & PTWR_CLEANUP_INACTIVE) \
cl349@2512 290 if (ptwr_info[cpu].ptinfo[PTWR_PT_INACTIVE].l1va) \
cl349@2512 291 ptwr_flush(PTWR_PT_INACTIVE); \
kaf24@2382 292 } while ( 0 )
cl349@1894 293
kaf24@3515 294 #define cleanup_writable_pagetable(_d) \
kaf24@2382 295 do { \
kaf24@2382 296 if ( unlikely(VM_ASSIST((_d), VMASST_TYPE_writable_pagetables)) ) \
kaf24@3515 297 __cleanup_writable_pagetable(PTWR_CLEANUP_ACTIVE | \
kaf24@3515 298 PTWR_CLEANUP_INACTIVE); \
kaf24@2382 299 } while ( 0 )
kaf24@2375 300
kaf24@2637 301 #ifndef NDEBUG
kaf24@2637 302 void audit_domain(struct domain *d);
kaf24@2637 303 void audit_domains(void);
kaf24@2637 304 #else
kaf24@2637 305 #define audit_domain(_d) ((void)0)
kaf24@2637 306 #define audit_domains() ((void)0)
kaf24@2637 307 #endif
kaf24@2637 308
kaf24@3462 309 void propagate_page_fault(unsigned long addr, u16 error_code);
kaf24@3462 310
djm@1747 311 #endif /* __ASM_X86_MM_H__ */