debuggers.hg

view xen/arch/x86/mm/p2m.c @ 16765:f17b34df974f

amd hvm (svm): Print warning if NPT constraints on PAE are hit.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Jan 16 15:55:57 2008 +0000 (2008-01-16)
parents db9f62d8f7f4
children 98c2665056ea
line source
1 /******************************************************************************
2 * arch/x86/mm/p2m.c
3 *
4 * physical-to-machine mappings for automatically-translated domains.
5 *
6 * Parts of this code are Copyright (c) 2007 by Advanced Micro Devices.
7 * Parts of this code are Copyright (c) 2006-2007 by XenSource Inc.
8 * Parts of this code are Copyright (c) 2006 by Michael A Fetterman
9 * Parts based on earlier work by Michael A Fetterman, Ian Pratt et al.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
26 #include <asm/domain.h>
27 #include <asm/page.h>
28 #include <asm/paging.h>
29 #include <asm/p2m.h>
30 #include <asm/iommu.h>
32 /* Debugging and auditing of the P2M code? */
33 #define P2M_AUDIT 0
34 #define P2M_DEBUGGING 0
36 /*
37 * The P2M lock. This protects all updates to the p2m table.
38 * Updates are expected to be safe against concurrent reads,
39 * which do *not* require the lock.
40 *
41 * Locking discipline: always acquire this lock before the shadow or HAP one
42 */
44 #define p2m_lock_init(_d) \
45 do { \
46 spin_lock_init(&(_d)->arch.p2m.lock); \
47 (_d)->arch.p2m.locker = -1; \
48 (_d)->arch.p2m.locker_function = "nobody"; \
49 } while (0)
51 #define p2m_lock(_d) \
52 do { \
53 if ( unlikely((_d)->arch.p2m.locker == current->processor) )\
54 { \
55 printk("Error: p2m lock held by %s\n", \
56 (_d)->arch.p2m.locker_function); \
57 BUG(); \
58 } \
59 spin_lock(&(_d)->arch.p2m.lock); \
60 ASSERT((_d)->arch.p2m.locker == -1); \
61 (_d)->arch.p2m.locker = current->processor; \
62 (_d)->arch.p2m.locker_function = __func__; \
63 } while (0)
65 #define p2m_unlock(_d) \
66 do { \
67 ASSERT((_d)->arch.p2m.locker == current->processor); \
68 (_d)->arch.p2m.locker = -1; \
69 (_d)->arch.p2m.locker_function = "nobody"; \
70 spin_unlock(&(_d)->arch.p2m.lock); \
71 } while (0)
75 /* Printouts */
76 #define P2M_PRINTK(_f, _a...) \
77 debugtrace_printk("p2m: %s(): " _f, __func__, ##_a)
78 #define P2M_ERROR(_f, _a...) \
79 printk("pg error: %s(): " _f, __func__, ##_a)
80 #if P2M_DEBUGGING
81 #define P2M_DEBUG(_f, _a...) \
82 debugtrace_printk("p2mdebug: %s(): " _f, __func__, ##_a)
83 #else
84 #define P2M_DEBUG(_f, _a...) do { (void)(_f); } while(0)
85 #endif
88 /* Override macros from asm/page.h to make them work with mfn_t */
89 #undef mfn_to_page
90 #define mfn_to_page(_m) (frame_table + mfn_x(_m))
91 #undef mfn_valid
92 #define mfn_valid(_mfn) (mfn_x(_mfn) < max_page)
93 #undef page_to_mfn
94 #define page_to_mfn(_pg) (_mfn((_pg) - frame_table))
97 /* PTE flags for the various types of p2m entry */
98 #define P2M_BASE_FLAGS \
99 (_PAGE_PRESENT | _PAGE_USER | _PAGE_DIRTY | _PAGE_ACCESSED)
101 static unsigned long p2m_type_to_flags(p2m_type_t t)
102 {
103 unsigned long flags = (t & 0x7UL) << 9;
104 switch(t)
105 {
106 case p2m_invalid:
107 default:
108 return flags;
109 case p2m_ram_rw:
110 return flags | P2M_BASE_FLAGS | _PAGE_RW;
111 case p2m_ram_logdirty:
112 return flags | P2M_BASE_FLAGS;
113 case p2m_ram_ro:
114 return flags | P2M_BASE_FLAGS;
115 case p2m_mmio_dm:
116 return flags;
117 case p2m_mmio_direct:
118 return flags | P2M_BASE_FLAGS | _PAGE_RW | _PAGE_PCD;
119 }
120 }
123 // Find the next level's P2M entry, checking for out-of-range gfn's...
124 // Returns NULL on error.
125 //
126 static l1_pgentry_t *
127 p2m_find_entry(void *table, unsigned long *gfn_remainder,
128 unsigned long gfn, u32 shift, u32 max)
129 {
130 u32 index;
132 index = *gfn_remainder >> shift;
133 if ( index >= max )
134 {
135 P2M_DEBUG("gfn=0x%lx out of range "
136 "(gfn_remainder=0x%lx shift=%d index=0x%x max=0x%x)\n",
137 gfn, *gfn_remainder, shift, index, max);
138 return NULL;
139 }
140 *gfn_remainder &= (1 << shift) - 1;
141 return (l1_pgentry_t *)table + index;
142 }
144 // Walk one level of the P2M table, allocating a new table if required.
145 // Returns 0 on error.
146 //
147 static int
148 p2m_next_level(struct domain *d, mfn_t *table_mfn, void **table,
149 unsigned long *gfn_remainder, unsigned long gfn, u32 shift,
150 u32 max, unsigned long type)
151 {
152 l1_pgentry_t *p2m_entry;
153 l1_pgentry_t new_entry;
154 void *next;
155 ASSERT(d->arch.p2m.alloc_page);
157 if ( !(p2m_entry = p2m_find_entry(*table, gfn_remainder, gfn,
158 shift, max)) )
159 return 0;
161 if ( !(l1e_get_flags(*p2m_entry) & _PAGE_PRESENT) )
162 {
163 struct page_info *pg = d->arch.p2m.alloc_page(d);
164 if ( pg == NULL )
165 return 0;
166 list_add_tail(&pg->list, &d->arch.p2m.pages);
167 pg->u.inuse.type_info = type | 1 | PGT_validated;
168 pg->count_info = 1;
170 new_entry = l1e_from_pfn(mfn_x(page_to_mfn(pg)),
171 __PAGE_HYPERVISOR|_PAGE_USER);
173 switch ( type ) {
174 case PGT_l3_page_table:
175 paging_write_p2m_entry(d, gfn,
176 p2m_entry, *table_mfn, new_entry, 4);
177 break;
178 case PGT_l2_page_table:
179 #if CONFIG_PAGING_LEVELS == 3
180 /* for PAE mode, PDPE only has PCD/PWT/P bits available */
181 new_entry = l1e_from_pfn(mfn_x(page_to_mfn(pg)), _PAGE_PRESENT);
182 #endif
183 paging_write_p2m_entry(d, gfn,
184 p2m_entry, *table_mfn, new_entry, 3);
185 break;
186 case PGT_l1_page_table:
187 paging_write_p2m_entry(d, gfn,
188 p2m_entry, *table_mfn, new_entry, 2);
189 break;
190 default:
191 BUG();
192 break;
193 }
194 }
195 *table_mfn = _mfn(l1e_get_pfn(*p2m_entry));
196 next = map_domain_page(mfn_x(*table_mfn));
197 unmap_domain_page(*table);
198 *table = next;
200 return 1;
201 }
203 // Returns 0 on error (out of memory)
204 static int
205 set_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn, p2m_type_t p2mt)
206 {
207 // XXX -- this might be able to be faster iff current->domain == d
208 mfn_t table_mfn = pagetable_get_mfn(d->arch.phys_table);
209 void *table =map_domain_page(mfn_x(table_mfn));
210 unsigned long gfn_remainder = gfn;
211 l1_pgentry_t *p2m_entry;
212 l1_pgentry_t entry_content;
213 int rv=0;
215 #if CONFIG_PAGING_LEVELS >= 4
216 if ( !p2m_next_level(d, &table_mfn, &table, &gfn_remainder, gfn,
217 L4_PAGETABLE_SHIFT - PAGE_SHIFT,
218 L4_PAGETABLE_ENTRIES, PGT_l3_page_table) )
219 goto out;
220 #endif
221 #if CONFIG_PAGING_LEVELS >= 3
222 /*
223 * When using PAE Xen, we only allow 33 bits of pseudo-physical
224 * address in translated guests (i.e. 8 GBytes). This restriction
225 * comes from wanting to map the P2M table into the 16MB RO_MPT hole
226 * in Xen's address space for translated PV guests.
227 * When using AMD's NPT on PAE Xen, we are restricted to 4GB.
228 */
229 if ( !p2m_next_level(d, &table_mfn, &table, &gfn_remainder, gfn,
230 L3_PAGETABLE_SHIFT - PAGE_SHIFT,
231 ((CONFIG_PAGING_LEVELS == 3)
232 ? (hvm_funcs.hap_supported ? 4 : 8)
233 : L3_PAGETABLE_ENTRIES),
234 PGT_l2_page_table) )
235 goto out;
236 #endif
237 if ( !p2m_next_level(d, &table_mfn, &table, &gfn_remainder, gfn,
238 L2_PAGETABLE_SHIFT - PAGE_SHIFT,
239 L2_PAGETABLE_ENTRIES, PGT_l1_page_table) )
240 goto out;
242 p2m_entry = p2m_find_entry(table, &gfn_remainder, gfn,
243 0, L1_PAGETABLE_ENTRIES);
244 ASSERT(p2m_entry);
246 /* Track the highest gfn for which we have ever had a valid mapping */
247 if ( mfn_valid(mfn) && (gfn > d->arch.p2m.max_mapped_pfn) )
248 d->arch.p2m.max_mapped_pfn = gfn;
250 if ( mfn_valid(mfn) || (p2mt == p2m_mmio_direct) )
251 entry_content = l1e_from_pfn(mfn_x(mfn), p2m_type_to_flags(p2mt));
252 else
253 entry_content = l1e_empty();
255 /* level 1 entry */
256 paging_write_p2m_entry(d, gfn, p2m_entry, table_mfn, entry_content, 1);
258 if ( vtd_enabled && (p2mt == p2m_mmio_direct) && is_hvm_domain(d) )
259 iommu_flush(d, gfn, (u64*)p2m_entry);
261 /* Success */
262 rv = 1;
264 out:
265 unmap_domain_page(table);
266 return rv;
267 }
270 /* Init the datastructures for later use by the p2m code */
271 void p2m_init(struct domain *d)
272 {
273 p2m_lock_init(d);
274 INIT_LIST_HEAD(&d->arch.p2m.pages);
275 }
278 // Allocate a new p2m table for a domain.
279 //
280 // The structure of the p2m table is that of a pagetable for xen (i.e. it is
281 // controlled by CONFIG_PAGING_LEVELS).
282 //
283 // The alloc_page and free_page functions will be used to get memory to
284 // build the p2m, and to release it again at the end of day.
285 //
286 // Returns 0 for success or -errno.
287 //
288 int p2m_alloc_table(struct domain *d,
289 struct page_info * (*alloc_page)(struct domain *d),
290 void (*free_page)(struct domain *d, struct page_info *pg))
292 {
293 mfn_t mfn = _mfn(INVALID_MFN);
294 struct list_head *entry;
295 struct page_info *page, *p2m_top;
296 unsigned int page_count = 0;
297 unsigned long gfn = -1UL;
299 p2m_lock(d);
301 if ( pagetable_get_pfn(d->arch.phys_table) != 0 )
302 {
303 P2M_ERROR("p2m already allocated for this domain\n");
304 p2m_unlock(d);
305 return -EINVAL;
306 }
308 P2M_PRINTK("allocating p2m table\n");
310 d->arch.p2m.alloc_page = alloc_page;
311 d->arch.p2m.free_page = free_page;
313 p2m_top = d->arch.p2m.alloc_page(d);
314 if ( p2m_top == NULL )
315 {
316 p2m_unlock(d);
317 return -ENOMEM;
318 }
319 list_add_tail(&p2m_top->list, &d->arch.p2m.pages);
321 p2m_top->count_info = 1;
322 p2m_top->u.inuse.type_info =
323 #if CONFIG_PAGING_LEVELS == 4
324 PGT_l4_page_table
325 #elif CONFIG_PAGING_LEVELS == 3
326 PGT_l3_page_table
327 #elif CONFIG_PAGING_LEVELS == 2
328 PGT_l2_page_table
329 #endif
330 | 1 | PGT_validated;
332 d->arch.phys_table = pagetable_from_mfn(page_to_mfn(p2m_top));
334 P2M_PRINTK("populating p2m table\n");
336 /* Initialise physmap tables for slot zero. Other code assumes this. */
337 if ( !set_p2m_entry(d, 0, _mfn(INVALID_MFN), p2m_invalid) )
338 goto error;
340 /* Copy all existing mappings from the page list and m2p */
341 for ( entry = d->page_list.next;
342 entry != &d->page_list;
343 entry = entry->next )
344 {
345 page = list_entry(entry, struct page_info, list);
346 mfn = page_to_mfn(page);
347 gfn = get_gpfn_from_mfn(mfn_x(mfn));
348 page_count++;
349 if (
350 #ifdef __x86_64__
351 (gfn != 0x5555555555555555L)
352 #else
353 (gfn != 0x55555555L)
354 #endif
355 && gfn != INVALID_M2P_ENTRY
356 && !set_p2m_entry(d, gfn, mfn, p2m_ram_rw) )
357 goto error;
358 }
360 #if CONFIG_PAGING_LEVELS >= 3
361 if (vtd_enabled && is_hvm_domain(d))
362 iommu_set_pgd(d);
363 #endif
365 P2M_PRINTK("p2m table initialised (%u pages)\n", page_count);
366 p2m_unlock(d);
367 return 0;
369 error:
370 P2M_PRINTK("failed to initialize p2m table, gfn=%05lx, mfn=%"
371 PRI_mfn "\n", gfn, mfn_x(mfn));
372 p2m_unlock(d);
373 return -ENOMEM;
374 }
376 void p2m_teardown(struct domain *d)
377 /* Return all the p2m pages to Xen.
378 * We know we don't have any extra mappings to these pages */
379 {
380 struct list_head *entry, *n;
381 struct page_info *pg;
383 p2m_lock(d);
384 d->arch.phys_table = pagetable_null();
386 list_for_each_safe(entry, n, &d->arch.p2m.pages)
387 {
388 pg = list_entry(entry, struct page_info, list);
389 list_del(entry);
390 d->arch.p2m.free_page(d, pg);
391 }
392 p2m_unlock(d);
393 }
395 mfn_t
396 gfn_to_mfn_foreign(struct domain *d, unsigned long gfn, p2m_type_t *t)
397 /* Read another domain's p2m entries */
398 {
399 mfn_t mfn;
400 paddr_t addr = ((paddr_t)gfn) << PAGE_SHIFT;
401 l2_pgentry_t *l2e;
402 l1_pgentry_t *l1e;
404 ASSERT(paging_mode_translate(d));
406 /* XXX This is for compatibility with the old model, where anything not
407 * XXX marked as RAM was considered to be emulated MMIO space.
408 * XXX Once we start explicitly registering MMIO regions in the p2m
409 * XXX we will return p2m_invalid for unmapped gfns */
410 *t = p2m_mmio_dm;
412 mfn = pagetable_get_mfn(d->arch.phys_table);
414 if ( gfn > d->arch.p2m.max_mapped_pfn )
415 /* This pfn is higher than the highest the p2m map currently holds */
416 return _mfn(INVALID_MFN);
418 #if CONFIG_PAGING_LEVELS >= 4
419 {
420 l4_pgentry_t *l4e = map_domain_page(mfn_x(mfn));
421 l4e += l4_table_offset(addr);
422 if ( (l4e_get_flags(*l4e) & _PAGE_PRESENT) == 0 )
423 {
424 unmap_domain_page(l4e);
425 return _mfn(INVALID_MFN);
426 }
427 mfn = _mfn(l4e_get_pfn(*l4e));
428 unmap_domain_page(l4e);
429 }
430 #endif
431 #if CONFIG_PAGING_LEVELS >= 3
432 {
433 l3_pgentry_t *l3e = map_domain_page(mfn_x(mfn));
434 #if CONFIG_PAGING_LEVELS == 3
435 /* On PAE hosts the p2m has eight l3 entries, not four (see
436 * shadow_set_p2m_entry()) so we can't use l3_table_offset.
437 * Instead, just count the number of l3es from zero. It's safe
438 * to do this because we already checked that the gfn is within
439 * the bounds of the p2m. */
440 l3e += (addr >> L3_PAGETABLE_SHIFT);
441 #else
442 l3e += l3_table_offset(addr);
443 #endif
444 if ( (l3e_get_flags(*l3e) & _PAGE_PRESENT) == 0 )
445 {
446 unmap_domain_page(l3e);
447 return _mfn(INVALID_MFN);
448 }
449 mfn = _mfn(l3e_get_pfn(*l3e));
450 unmap_domain_page(l3e);
451 }
452 #endif
454 l2e = map_domain_page(mfn_x(mfn));
455 l2e += l2_table_offset(addr);
456 if ( (l2e_get_flags(*l2e) & _PAGE_PRESENT) == 0 )
457 {
458 unmap_domain_page(l2e);
459 return _mfn(INVALID_MFN);
460 }
461 mfn = _mfn(l2e_get_pfn(*l2e));
462 unmap_domain_page(l2e);
464 l1e = map_domain_page(mfn_x(mfn));
465 l1e += l1_table_offset(addr);
466 if ( (l1e_get_flags(*l1e) & _PAGE_PRESENT) == 0 )
467 {
468 unmap_domain_page(l1e);
469 return _mfn(INVALID_MFN);
470 }
471 mfn = _mfn(l1e_get_pfn(*l1e));
472 *t = p2m_flags_to_type(l1e_get_flags(*l1e));
473 unmap_domain_page(l1e);
475 ASSERT(mfn_valid(mfn) || !p2m_is_ram(*t));
476 return (p2m_is_valid(*t)) ? mfn : _mfn(INVALID_MFN);
477 }
479 #if P2M_AUDIT
480 static void audit_p2m(struct domain *d)
481 {
482 struct list_head *entry;
483 struct page_info *page;
484 struct domain *od;
485 unsigned long mfn, gfn, m2pfn, lp2mfn = 0;
486 mfn_t p2mfn;
487 unsigned long orphans_d = 0, orphans_i = 0, mpbad = 0, pmbad = 0;
488 int test_linear;
490 if ( !paging_mode_translate(d) )
491 return;
493 //P2M_PRINTK("p2m audit starts\n");
495 test_linear = ( (d == current->domain)
496 && !pagetable_is_null(current->arch.monitor_table) );
497 if ( test_linear )
498 flush_tlb_local();
500 /* Audit part one: walk the domain's page allocation list, checking
501 * the m2p entries. */
502 for ( entry = d->page_list.next;
503 entry != &d->page_list;
504 entry = entry->next )
505 {
506 page = list_entry(entry, struct page_info, list);
507 mfn = mfn_x(page_to_mfn(page));
509 // P2M_PRINTK("auditing guest page, mfn=%#lx\n", mfn);
511 od = page_get_owner(page);
513 if ( od != d )
514 {
515 P2M_PRINTK("wrong owner %#lx -> %p(%u) != %p(%u)\n",
516 mfn, od, (od?od->domain_id:-1), d, d->domain_id);
517 continue;
518 }
520 gfn = get_gpfn_from_mfn(mfn);
521 if ( gfn == INVALID_M2P_ENTRY )
522 {
523 orphans_i++;
524 //P2M_PRINTK("orphaned guest page: mfn=%#lx has invalid gfn\n",
525 // mfn);
526 continue;
527 }
529 if ( gfn == 0x55555555 )
530 {
531 orphans_d++;
532 //P2M_PRINTK("orphaned guest page: mfn=%#lx has debug gfn\n",
533 // mfn);
534 continue;
535 }
537 p2mfn = gfn_to_mfn_foreign(d, gfn);
538 if ( mfn_x(p2mfn) != mfn )
539 {
540 mpbad++;
541 P2M_PRINTK("map mismatch mfn %#lx -> gfn %#lx -> mfn %#lx"
542 " (-> gfn %#lx)\n",
543 mfn, gfn, mfn_x(p2mfn),
544 (mfn_valid(p2mfn)
545 ? get_gpfn_from_mfn(mfn_x(p2mfn))
546 : -1u));
547 /* This m2p entry is stale: the domain has another frame in
548 * this physical slot. No great disaster, but for neatness,
549 * blow away the m2p entry. */
550 set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY, __PAGE_HYPERVISOR|_PAGE_USER);
551 }
553 if ( test_linear && (gfn <= d->arch.p2m.max_mapped_pfn) )
554 {
555 lp2mfn = mfn_x(gfn_to_mfn_current(gfn));
556 if ( lp2mfn != mfn_x(p2mfn) )
557 {
558 P2M_PRINTK("linear mismatch gfn %#lx -> mfn %#lx "
559 "(!= mfn %#lx)\n", gfn, lp2mfn, mfn_x(p2mfn));
560 }
561 }
563 // P2M_PRINTK("OK: mfn=%#lx, gfn=%#lx, p2mfn=%#lx, lp2mfn=%#lx\n",
564 // mfn, gfn, p2mfn, lp2mfn);
565 }
567 /* Audit part two: walk the domain's p2m table, checking the entries. */
568 if ( pagetable_get_pfn(d->arch.phys_table) != 0 )
569 {
570 l2_pgentry_t *l2e;
571 l1_pgentry_t *l1e;
572 int i1, i2;
574 #if CONFIG_PAGING_LEVELS == 4
575 l4_pgentry_t *l4e;
576 l3_pgentry_t *l3e;
577 int i3, i4;
578 l4e = map_domain_page(mfn_x(pagetable_get_mfn(d->arch.phys_table)));
579 #elif CONFIG_PAGING_LEVELS == 3
580 l3_pgentry_t *l3e;
581 int i3;
582 l3e = map_domain_page(mfn_x(pagetable_get_mfn(d->arch.phys_table)));
583 #else /* CONFIG_PAGING_LEVELS == 2 */
584 l2e = map_domain_page(mfn_x(pagetable_get_mfn(d->arch.phys_table)));
585 #endif
587 gfn = 0;
588 #if CONFIG_PAGING_LEVELS >= 3
589 #if CONFIG_PAGING_LEVELS >= 4
590 for ( i4 = 0; i4 < L4_PAGETABLE_ENTRIES; i4++ )
591 {
592 if ( !(l4e_get_flags(l4e[i4]) & _PAGE_PRESENT) )
593 {
594 gfn += 1 << (L4_PAGETABLE_SHIFT - PAGE_SHIFT);
595 continue;
596 }
597 l3e = map_domain_page(mfn_x(_mfn(l4e_get_pfn(l4e[i4]))));
598 #endif /* now at levels 3 or 4... */
599 for ( i3 = 0;
600 i3 < ((CONFIG_PAGING_LEVELS==4) ? L3_PAGETABLE_ENTRIES : 8);
601 i3++ )
602 {
603 if ( !(l3e_get_flags(l3e[i3]) & _PAGE_PRESENT) )
604 {
605 gfn += 1 << (L3_PAGETABLE_SHIFT - PAGE_SHIFT);
606 continue;
607 }
608 l2e = map_domain_page(mfn_x(_mfn(l3e_get_pfn(l3e[i3]))));
609 #endif /* all levels... */
610 for ( i2 = 0; i2 < L2_PAGETABLE_ENTRIES; i2++ )
611 {
612 if ( !(l2e_get_flags(l2e[i2]) & _PAGE_PRESENT) )
613 {
614 gfn += 1 << (L2_PAGETABLE_SHIFT - PAGE_SHIFT);
615 continue;
616 }
617 l1e = map_domain_page(mfn_x(_mfn(l2e_get_pfn(l2e[i2]))));
619 for ( i1 = 0; i1 < L1_PAGETABLE_ENTRIES; i1++, gfn++ )
620 {
621 if ( !(l1e_get_flags(l1e[i1]) & _PAGE_PRESENT) )
622 continue;
623 mfn = l1e_get_pfn(l1e[i1]);
624 ASSERT(mfn_valid(_mfn(mfn)));
625 m2pfn = get_gpfn_from_mfn(mfn);
626 if ( m2pfn != gfn )
627 {
628 pmbad++;
629 P2M_PRINTK("mismatch: gfn %#lx -> mfn %#lx"
630 " -> gfn %#lx\n", gfn, mfn, m2pfn);
631 BUG();
632 }
633 }
634 unmap_domain_page(l1e);
635 }
636 #if CONFIG_PAGING_LEVELS >= 3
637 unmap_domain_page(l2e);
638 }
639 #if CONFIG_PAGING_LEVELS >= 4
640 unmap_domain_page(l3e);
641 }
642 #endif
643 #endif
645 #if CONFIG_PAGING_LEVELS == 4
646 unmap_domain_page(l4e);
647 #elif CONFIG_PAGING_LEVELS == 3
648 unmap_domain_page(l3e);
649 #else /* CONFIG_PAGING_LEVELS == 2 */
650 unmap_domain_page(l2e);
651 #endif
653 }
655 //P2M_PRINTK("p2m audit complete\n");
656 //if ( orphans_i | orphans_d | mpbad | pmbad )
657 // P2M_PRINTK("p2m audit found %lu orphans (%lu inval %lu debug)\n",
658 // orphans_i + orphans_d, orphans_i, orphans_d,
659 if ( mpbad | pmbad )
660 P2M_PRINTK("p2m audit found %lu odd p2m, %lu bad m2p entries\n",
661 pmbad, mpbad);
662 }
663 #else
664 #define audit_p2m(_d) do { (void)(_d); } while(0)
665 #endif /* P2M_AUDIT */
669 static void
670 p2m_remove_page(struct domain *d, unsigned long gfn, unsigned long mfn)
671 {
672 if ( !paging_mode_translate(d) )
673 return;
674 P2M_DEBUG("removing gfn=%#lx mfn=%#lx\n", gfn, mfn);
676 set_p2m_entry(d, gfn, _mfn(INVALID_MFN), p2m_invalid);
677 set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY);
678 }
680 void
681 guest_physmap_remove_page(struct domain *d, unsigned long gfn,
682 unsigned long mfn)
683 {
684 p2m_lock(d);
685 audit_p2m(d);
686 p2m_remove_page(d, gfn, mfn);
687 audit_p2m(d);
688 p2m_unlock(d);
689 }
691 int
692 guest_physmap_add_entry(struct domain *d, unsigned long gfn,
693 unsigned long mfn, p2m_type_t t)
694 {
695 unsigned long ogfn;
696 p2m_type_t ot;
697 mfn_t omfn;
698 int rc = 0;
700 if ( !paging_mode_translate(d) )
701 return -EINVAL;
703 #if CONFIG_PAGING_LEVELS == 3
704 /*
705 * 32bit PAE nested paging does not support over 4GB guest due to
706 * hardware translation limit. This limitation is checked by comparing
707 * gfn with 0xfffffUL.
708 */
709 if ( paging_mode_hap(d) && (gfn > 0xfffffUL) )
710 {
711 if ( !test_and_set_bool(d->arch.hvm_domain.amd_npt_4gb_warning) )
712 dprintk(XENLOG_WARNING, "Dom%d failed to populate memory beyond"
713 " 4GB: remove 'hap' Xen boot parameter.\n",
714 d->domain_id);
715 return -EINVAL;
716 }
717 #endif
719 p2m_lock(d);
720 audit_p2m(d);
722 P2M_DEBUG("adding gfn=%#lx mfn=%#lx\n", gfn, mfn);
724 omfn = gfn_to_mfn(d, gfn, &ot);
725 if ( p2m_is_ram(ot) )
726 {
727 ASSERT(mfn_valid(omfn));
728 set_gpfn_from_mfn(mfn_x(omfn), INVALID_M2P_ENTRY);
729 }
731 ogfn = mfn_to_gfn(d, _mfn(mfn));
732 if (
733 #ifdef __x86_64__
734 (ogfn != 0x5555555555555555L)
735 #else
736 (ogfn != 0x55555555L)
737 #endif
738 && (ogfn != INVALID_M2P_ENTRY)
739 && (ogfn != gfn) )
740 {
741 /* This machine frame is already mapped at another physical address */
742 P2M_DEBUG("aliased! mfn=%#lx, old gfn=%#lx, new gfn=%#lx\n",
743 mfn, ogfn, gfn);
744 omfn = gfn_to_mfn(d, ogfn, &ot);
745 if ( p2m_is_ram(ot) )
746 {
747 ASSERT(mfn_valid(omfn));
748 P2M_DEBUG("old gfn=%#lx -> mfn %#lx\n",
749 ogfn , mfn_x(omfn));
750 if ( mfn_x(omfn) == mfn )
751 p2m_remove_page(d, ogfn, mfn);
752 }
753 }
755 if ( mfn_valid(_mfn(mfn)) )
756 {
757 if ( !set_p2m_entry(d, gfn, _mfn(mfn), t) )
758 rc = -EINVAL;
759 set_gpfn_from_mfn(mfn, gfn);
760 }
761 else
762 {
763 gdprintk(XENLOG_WARNING, "Adding bad mfn to p2m map (%#lx -> %#lx)\n",
764 gfn, mfn);
765 if ( !set_p2m_entry(d, gfn, _mfn(INVALID_MFN), p2m_invalid) )
766 rc = -EINVAL;
767 }
769 audit_p2m(d);
770 p2m_unlock(d);
772 return rc;
773 }
775 /* Walk the whole p2m table, changing any entries of the old type
776 * to the new type. This is used in hardware-assisted paging to
777 * quickly enable or diable log-dirty tracking */
778 void p2m_change_type_global(struct domain *d, p2m_type_t ot, p2m_type_t nt)
779 {
780 unsigned long mfn, gfn, flags;
781 l1_pgentry_t l1e_content;
782 l1_pgentry_t *l1e;
783 l2_pgentry_t *l2e;
784 mfn_t l1mfn;
785 int i1, i2;
786 #if CONFIG_PAGING_LEVELS >= 3
787 l3_pgentry_t *l3e;
788 int i3;
789 #if CONFIG_PAGING_LEVELS == 4
790 l4_pgentry_t *l4e;
791 int i4;
792 #endif /* CONFIG_PAGING_LEVELS == 4 */
793 #endif /* CONFIG_PAGING_LEVELS >= 3 */
795 if ( !paging_mode_translate(d) )
796 return;
798 if ( pagetable_get_pfn(d->arch.phys_table) == 0 )
799 return;
801 p2m_lock(d);
803 #if CONFIG_PAGING_LEVELS == 4
804 l4e = map_domain_page(mfn_x(pagetable_get_mfn(d->arch.phys_table)));
805 #elif CONFIG_PAGING_LEVELS == 3
806 l3e = map_domain_page(mfn_x(pagetable_get_mfn(d->arch.phys_table)));
807 #else /* CONFIG_PAGING_LEVELS == 2 */
808 l2e = map_domain_page(mfn_x(pagetable_get_mfn(d->arch.phys_table)));
809 #endif
811 #if CONFIG_PAGING_LEVELS >= 3
812 #if CONFIG_PAGING_LEVELS >= 4
813 for ( i4 = 0; i4 < L4_PAGETABLE_ENTRIES; i4++ )
814 {
815 if ( !(l4e_get_flags(l4e[i4]) & _PAGE_PRESENT) )
816 {
817 continue;
818 }
819 l3e = map_domain_page(l4e_get_pfn(l4e[i4]));
820 #endif /* now at levels 3 or 4... */
821 for ( i3 = 0;
822 i3 < ((CONFIG_PAGING_LEVELS==4) ? L3_PAGETABLE_ENTRIES : 8);
823 i3++ )
824 {
825 if ( !(l3e_get_flags(l3e[i3]) & _PAGE_PRESENT) )
826 {
827 continue;
828 }
829 l2e = map_domain_page(l3e_get_pfn(l3e[i3]));
830 #endif /* all levels... */
831 for ( i2 = 0; i2 < L2_PAGETABLE_ENTRIES; i2++ )
832 {
833 if ( !(l2e_get_flags(l2e[i2]) & _PAGE_PRESENT) )
834 {
835 continue;
836 }
838 l1mfn = _mfn(l2e_get_pfn(l2e[i2]));
839 l1e = map_domain_page(mfn_x(l1mfn));
841 for ( i1 = 0; i1 < L1_PAGETABLE_ENTRIES; i1++, gfn++ )
842 {
843 flags = l1e_get_flags(l1e[i1]);
844 if ( p2m_flags_to_type(flags) != ot )
845 continue;
846 mfn = l1e_get_pfn(l1e[i1]);
847 gfn = get_gpfn_from_mfn(mfn);
848 /* create a new 1le entry with the new type */
849 flags = p2m_flags_to_type(nt);
850 l1e_content = l1e_from_pfn(mfn, flags);
851 paging_write_p2m_entry(d, gfn, &l1e[i1],
852 l1mfn, l1e_content, 1);
853 }
854 unmap_domain_page(l1e);
855 }
856 #if CONFIG_PAGING_LEVELS >= 3
857 unmap_domain_page(l2e);
858 }
859 #if CONFIG_PAGING_LEVELS >= 4
860 unmap_domain_page(l3e);
861 }
862 #endif
863 #endif
865 #if CONFIG_PAGING_LEVELS == 4
866 unmap_domain_page(l4e);
867 #elif CONFIG_PAGING_LEVELS == 3
868 unmap_domain_page(l3e);
869 #else /* CONFIG_PAGING_LEVELS == 2 */
870 unmap_domain_page(l2e);
871 #endif
873 p2m_unlock(d);
874 }
876 /* Modify the p2m type of a single gfn from ot to nt, returning the
877 * entry's previous type */
878 p2m_type_t p2m_change_type(struct domain *d, unsigned long gfn,
879 p2m_type_t ot, p2m_type_t nt)
880 {
881 p2m_type_t pt;
882 mfn_t mfn;
884 p2m_lock(d);
886 mfn = gfn_to_mfn(d, gfn, &pt);
887 if ( pt == ot )
888 set_p2m_entry(d, gfn, mfn, nt);
890 p2m_unlock(d);
892 return pt;
893 }
895 int
896 set_mmio_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn)
897 {
898 int rc = 0;
899 p2m_type_t ot;
900 mfn_t omfn;
902 if ( !paging_mode_translate(d) )
903 return 0;
905 omfn = gfn_to_mfn(d, gfn, &ot);
906 if ( p2m_is_ram(ot) )
907 {
908 ASSERT(mfn_valid(omfn));
909 set_gpfn_from_mfn(mfn_x(omfn), INVALID_M2P_ENTRY);
910 }
912 rc = set_p2m_entry(d, gfn, mfn, p2m_mmio_direct);
913 if ( 0 == rc )
914 gdprintk(XENLOG_ERR,
915 "set_mmio_p2m_entry: set_p2m_entry failed! mfn=%08lx\n",
916 gmfn_to_mfn(d, gfn));
917 return rc;
918 }
920 int
921 clear_mmio_p2m_entry(struct domain *d, unsigned long gfn)
922 {
923 int rc = 0;
924 unsigned long mfn;
926 if ( !paging_mode_translate(d) )
927 return 0;
929 mfn = gmfn_to_mfn(d, gfn);
930 if ( INVALID_MFN == mfn )
931 {
932 gdprintk(XENLOG_ERR,
933 "clear_mmio_p2m_entry: gfn_to_mfn failed! gfn=%08lx\n", gfn);
934 return 0;
935 }
936 rc = set_p2m_entry(d, gfn, _mfn(INVALID_MFN), 0);
938 return rc;
939 }
941 /*
942 * Local variables:
943 * mode: C
944 * c-set-style: "BSD"
945 * c-basic-offset: 4
946 * indent-tabs-mode: nil
947 * End:
948 */