1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151#include <linux/init.h>
152#include <linux/module.h>
153#include <linux/list.h>
154#include <linux/hash.h>
155#include <linux/sched.h>
156#include <linux/seq_file.h>
157
158#include <asm/cache.h>
159#include <asm/setup.h>
160
161#include <asm/xen/page.h>
162#include <asm/xen/hypercall.h>
163#include <asm/xen/hypervisor.h>
164#include <xen/grant_table.h>
165
166#include "multicalls.h"
167#include "xen-ops.h"
168
169static void __init m2p_override_init(void);
170
171unsigned long xen_max_p2m_pfn __read_mostly;
172
173#define P2M_PER_PAGE (PAGE_SIZE / sizeof(unsigned long))
174#define P2M_MID_PER_PAGE (PAGE_SIZE / sizeof(unsigned long *))
175#define P2M_TOP_PER_PAGE (PAGE_SIZE / sizeof(unsigned long **))
176
177#define MAX_P2M_PFN (P2M_TOP_PER_PAGE * P2M_MID_PER_PAGE * P2M_PER_PAGE)
178
179
180static RESERVE_BRK_ARRAY(unsigned long, p2m_missing, P2M_PER_PAGE);
181static RESERVE_BRK_ARRAY(unsigned long *, p2m_mid_missing, P2M_MID_PER_PAGE);
182static RESERVE_BRK_ARRAY(unsigned long, p2m_mid_missing_mfn, P2M_MID_PER_PAGE);
183
184static RESERVE_BRK_ARRAY(unsigned long **, p2m_top, P2M_TOP_PER_PAGE);
185static RESERVE_BRK_ARRAY(unsigned long, p2m_top_mfn, P2M_TOP_PER_PAGE);
186static RESERVE_BRK_ARRAY(unsigned long *, p2m_top_mfn_p, P2M_TOP_PER_PAGE);
187
188static RESERVE_BRK_ARRAY(unsigned long, p2m_identity, P2M_PER_PAGE);
189
190RESERVE_BRK(p2m_mid, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE)));
191RESERVE_BRK(p2m_mid_mfn, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE)));
192
193
194
195RESERVE_BRK(p2m_mid_identity, PAGE_SIZE * 2 * 3);
196
197
198
199
200
201
202RESERVE_BRK(p2m_populated, PAGE_SIZE * 3);
203
204static inline unsigned p2m_top_index(unsigned long pfn)
205{
206 BUG_ON(pfn >= MAX_P2M_PFN);
207 return pfn / (P2M_MID_PER_PAGE * P2M_PER_PAGE);
208}
209
210static inline unsigned p2m_mid_index(unsigned long pfn)
211{
212 return (pfn / P2M_PER_PAGE) % P2M_MID_PER_PAGE;
213}
214
215static inline unsigned p2m_index(unsigned long pfn)
216{
217 return pfn % P2M_PER_PAGE;
218}
219
220static void p2m_top_init(unsigned long ***top)
221{
222 unsigned i;
223
224 for (i = 0; i < P2M_TOP_PER_PAGE; i++)
225 top[i] = p2m_mid_missing;
226}
227
228static void p2m_top_mfn_init(unsigned long *top)
229{
230 unsigned i;
231
232 for (i = 0; i < P2M_TOP_PER_PAGE; i++)
233 top[i] = virt_to_mfn(p2m_mid_missing_mfn);
234}
235
236static void p2m_top_mfn_p_init(unsigned long **top)
237{
238 unsigned i;
239
240 for (i = 0; i < P2M_TOP_PER_PAGE; i++)
241 top[i] = p2m_mid_missing_mfn;
242}
243
244static void p2m_mid_init(unsigned long **mid)
245{
246 unsigned i;
247
248 for (i = 0; i < P2M_MID_PER_PAGE; i++)
249 mid[i] = p2m_missing;
250}
251
252static void p2m_mid_mfn_init(unsigned long *mid)
253{
254 unsigned i;
255
256 for (i = 0; i < P2M_MID_PER_PAGE; i++)
257 mid[i] = virt_to_mfn(p2m_missing);
258}
259
260static void p2m_init(unsigned long *p2m)
261{
262 unsigned i;
263
264 for (i = 0; i < P2M_MID_PER_PAGE; i++)
265 p2m[i] = INVALID_P2M_ENTRY;
266}
267
268
269
270
271
272
273
274
275
276
277
278void __ref xen_build_mfn_list_list(void)
279{
280 unsigned long pfn;
281
282
283 if (p2m_top_mfn == NULL) {
284 p2m_mid_missing_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE);
285 p2m_mid_mfn_init(p2m_mid_missing_mfn);
286
287 p2m_top_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
288 p2m_top_mfn_p_init(p2m_top_mfn_p);
289
290 p2m_top_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE);
291 p2m_top_mfn_init(p2m_top_mfn);
292 } else {
293
294 p2m_mid_mfn_init(p2m_mid_missing_mfn);
295 }
296
297 for (pfn = 0; pfn < xen_max_p2m_pfn; pfn += P2M_PER_PAGE) {
298 unsigned topidx = p2m_top_index(pfn);
299 unsigned mididx = p2m_mid_index(pfn);
300 unsigned long **mid;
301 unsigned long *mid_mfn_p;
302
303 mid = p2m_top[topidx];
304 mid_mfn_p = p2m_top_mfn_p[topidx];
305
306
307
308
309
310 if (mid == p2m_mid_missing) {
311 BUG_ON(mididx);
312 BUG_ON(mid_mfn_p != p2m_mid_missing_mfn);
313 p2m_top_mfn[topidx] = virt_to_mfn(p2m_mid_missing_mfn);
314 pfn += (P2M_MID_PER_PAGE - 1) * P2M_PER_PAGE;
315 continue;
316 }
317
318 if (mid_mfn_p == p2m_mid_missing_mfn) {
319
320
321
322
323
324
325 mid_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
326 p2m_mid_mfn_init(mid_mfn_p);
327
328 p2m_top_mfn_p[topidx] = mid_mfn_p;
329 }
330
331 p2m_top_mfn[topidx] = virt_to_mfn(mid_mfn_p);
332 mid_mfn_p[mididx] = virt_to_mfn(mid[mididx]);
333 }
334}
335
336void xen_setup_mfn_list_list(void)
337{
338 BUG_ON(HYPERVISOR_shared_info == &xen_dummy_shared_info);
339
340 HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
341 virt_to_mfn(p2m_top_mfn);
342 HYPERVISOR_shared_info->arch.max_pfn = xen_max_p2m_pfn;
343}
344
345
346void __init xen_build_dynamic_phys_to_machine(void)
347{
348 unsigned long *mfn_list = (unsigned long *)xen_start_info->mfn_list;
349 unsigned long max_pfn = min(MAX_DOMAIN_PAGES, xen_start_info->nr_pages);
350 unsigned long pfn;
351
352 xen_max_p2m_pfn = max_pfn;
353
354 p2m_missing = extend_brk(PAGE_SIZE, PAGE_SIZE);
355 p2m_init(p2m_missing);
356
357 p2m_mid_missing = extend_brk(PAGE_SIZE, PAGE_SIZE);
358 p2m_mid_init(p2m_mid_missing);
359
360 p2m_top = extend_brk(PAGE_SIZE, PAGE_SIZE);
361 p2m_top_init(p2m_top);
362
363 p2m_identity = extend_brk(PAGE_SIZE, PAGE_SIZE);
364 p2m_init(p2m_identity);
365
366
367
368
369
370
371 for (pfn = 0; pfn < max_pfn; pfn += P2M_PER_PAGE) {
372 unsigned topidx = p2m_top_index(pfn);
373 unsigned mididx = p2m_mid_index(pfn);
374
375 if (p2m_top[topidx] == p2m_mid_missing) {
376 unsigned long **mid = extend_brk(PAGE_SIZE, PAGE_SIZE);
377 p2m_mid_init(mid);
378
379 p2m_top[topidx] = mid;
380 }
381
382
383
384
385
386
387 if (unlikely(pfn + P2M_PER_PAGE > max_pfn)) {
388 unsigned long p2midx;
389
390 p2midx = max_pfn % P2M_PER_PAGE;
391 for ( ; p2midx < P2M_PER_PAGE; p2midx++)
392 mfn_list[pfn + p2midx] = INVALID_P2M_ENTRY;
393 }
394 p2m_top[topidx][mididx] = &mfn_list[pfn];
395 }
396
397 m2p_override_init();
398}
399#ifdef CONFIG_X86_64
400#include <linux/bootmem.h>
401unsigned long __init xen_revector_p2m_tree(void)
402{
403 unsigned long va_start;
404 unsigned long va_end;
405 unsigned long pfn;
406 unsigned long pfn_free = 0;
407 unsigned long *mfn_list = NULL;
408 unsigned long size;
409
410 va_start = xen_start_info->mfn_list;
411
412
413 size = PAGE_ALIGN(xen_start_info->nr_pages * sizeof(unsigned long));
414 va_end = va_start + size;
415
416
417 if (va_start <= __START_KERNEL_map && va_start >= __PAGE_OFFSET)
418 return 0;
419
420 mfn_list = alloc_bootmem_align(size, PAGE_SIZE);
421 if (!mfn_list) {
422 pr_warn("Could not allocate space for a new P2M tree!\n");
423 return xen_start_info->mfn_list;
424 }
425
426 memset(mfn_list, 0xFF, size);
427
428 for (pfn = 0; pfn < ALIGN(MAX_DOMAIN_PAGES, P2M_PER_PAGE); pfn += P2M_PER_PAGE) {
429 unsigned topidx = p2m_top_index(pfn);
430 unsigned mididx;
431 unsigned long *mid_p;
432
433 if (!p2m_top[topidx])
434 continue;
435
436 if (p2m_top[topidx] == p2m_mid_missing)
437 continue;
438
439 mididx = p2m_mid_index(pfn);
440 mid_p = p2m_top[topidx][mididx];
441 if (!mid_p)
442 continue;
443 if ((mid_p == p2m_missing) || (mid_p == p2m_identity))
444 continue;
445
446 if ((unsigned long)mid_p == INVALID_P2M_ENTRY)
447 continue;
448
449
450 if (mid_p >= (unsigned long *)va_start && mid_p <= (unsigned long *)va_end) {
451 unsigned long *new;
452
453 if (pfn_free > (size / sizeof(unsigned long))) {
454 WARN(1, "Only allocated for %ld pages, but we want %ld!\n",
455 size / sizeof(unsigned long), pfn_free);
456 return 0;
457 }
458 new = &mfn_list[pfn_free];
459
460 copy_page(new, mid_p);
461 p2m_top[topidx][mididx] = &mfn_list[pfn_free];
462 p2m_top_mfn_p[topidx][mididx] = virt_to_mfn(&mfn_list[pfn_free]);
463
464 pfn_free += P2M_PER_PAGE;
465
466 }
467
468 }
469 return (unsigned long)mfn_list;
470
471}
472#else
473unsigned long __init xen_revector_p2m_tree(void)
474{
475 return 0;
476}
477#endif
478unsigned long get_phys_to_machine(unsigned long pfn)
479{
480 unsigned topidx, mididx, idx;
481
482 if (unlikely(pfn >= MAX_P2M_PFN))
483 return INVALID_P2M_ENTRY;
484
485 topidx = p2m_top_index(pfn);
486 mididx = p2m_mid_index(pfn);
487 idx = p2m_index(pfn);
488
489
490
491
492
493
494 if (p2m_top[topidx][mididx] == p2m_identity)
495 return IDENTITY_FRAME(pfn);
496
497 return p2m_top[topidx][mididx][idx];
498}
499EXPORT_SYMBOL_GPL(get_phys_to_machine);
500
501static void *alloc_p2m_page(void)
502{
503 return (void *)__get_free_page(GFP_KERNEL | __GFP_REPEAT);
504}
505
506static void free_p2m_page(void *p)
507{
508 free_page((unsigned long)p);
509}
510
511
512
513
514
515
516
517
518static bool alloc_p2m(unsigned long pfn)
519{
520 unsigned topidx, mididx;
521 unsigned long ***top_p, **mid;
522 unsigned long *top_mfn_p, *mid_mfn;
523
524 topidx = p2m_top_index(pfn);
525 mididx = p2m_mid_index(pfn);
526
527 top_p = &p2m_top[topidx];
528 mid = *top_p;
529
530 if (mid == p2m_mid_missing) {
531
532 mid = alloc_p2m_page();
533 if (!mid)
534 return false;
535
536 p2m_mid_init(mid);
537
538 if (cmpxchg(top_p, p2m_mid_missing, mid) != p2m_mid_missing)
539 free_p2m_page(mid);
540 }
541
542 top_mfn_p = &p2m_top_mfn[topidx];
543 mid_mfn = p2m_top_mfn_p[topidx];
544
545 BUG_ON(virt_to_mfn(mid_mfn) != *top_mfn_p);
546
547 if (mid_mfn == p2m_mid_missing_mfn) {
548
549 unsigned long missing_mfn;
550 unsigned long mid_mfn_mfn;
551
552 mid_mfn = alloc_p2m_page();
553 if (!mid_mfn)
554 return false;
555
556 p2m_mid_mfn_init(mid_mfn);
557
558 missing_mfn = virt_to_mfn(p2m_mid_missing_mfn);
559 mid_mfn_mfn = virt_to_mfn(mid_mfn);
560 if (cmpxchg(top_mfn_p, missing_mfn, mid_mfn_mfn) != missing_mfn)
561 free_p2m_page(mid_mfn);
562 else
563 p2m_top_mfn_p[topidx] = mid_mfn;
564 }
565
566 if (p2m_top[topidx][mididx] == p2m_identity ||
567 p2m_top[topidx][mididx] == p2m_missing) {
568
569 unsigned long *p2m;
570 unsigned long *p2m_orig = p2m_top[topidx][mididx];
571
572 p2m = alloc_p2m_page();
573 if (!p2m)
574 return false;
575
576 p2m_init(p2m);
577
578 if (cmpxchg(&mid[mididx], p2m_orig, p2m) != p2m_orig)
579 free_p2m_page(p2m);
580 else
581 mid_mfn[mididx] = virt_to_mfn(p2m);
582 }
583
584 return true;
585}
586
587static bool __init early_alloc_p2m_middle(unsigned long pfn, bool check_boundary)
588{
589 unsigned topidx, mididx, idx;
590 unsigned long *p2m;
591 unsigned long *mid_mfn_p;
592
593 topidx = p2m_top_index(pfn);
594 mididx = p2m_mid_index(pfn);
595 idx = p2m_index(pfn);
596
597
598 if (!idx && check_boundary)
599 return false;
600
601 WARN(p2m_top[topidx][mididx] == p2m_identity,
602 "P2M[%d][%d] == IDENTITY, should be MISSING (or alloced)!\n",
603 topidx, mididx);
604
605
606
607
608 if (p2m_top[topidx][mididx] != p2m_missing)
609 return false;
610
611
612 p2m = extend_brk(PAGE_SIZE, PAGE_SIZE);
613
614 p2m_init(p2m);
615
616 p2m_top[topidx][mididx] = p2m;
617
618
619
620 mid_mfn_p = p2m_top_mfn_p[topidx];
621 WARN(mid_mfn_p[mididx] != virt_to_mfn(p2m_missing),
622 "P2M_TOP_P[%d][%d] != MFN of p2m_missing!\n",
623 topidx, mididx);
624 mid_mfn_p[mididx] = virt_to_mfn(p2m);
625
626 return true;
627}
628
629static bool __init early_alloc_p2m(unsigned long pfn)
630{
631 unsigned topidx = p2m_top_index(pfn);
632 unsigned long *mid_mfn_p;
633 unsigned long **mid;
634
635 mid = p2m_top[topidx];
636 mid_mfn_p = p2m_top_mfn_p[topidx];
637 if (mid == p2m_mid_missing) {
638 mid = extend_brk(PAGE_SIZE, PAGE_SIZE);
639
640 p2m_mid_init(mid);
641
642 p2m_top[topidx] = mid;
643
644 BUG_ON(mid_mfn_p != p2m_mid_missing_mfn);
645 }
646
647 if (mid_mfn_p == p2m_mid_missing_mfn) {
648 mid_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
649 p2m_mid_mfn_init(mid_mfn_p);
650
651 p2m_top_mfn_p[topidx] = mid_mfn_p;
652 p2m_top_mfn[topidx] = virt_to_mfn(mid_mfn_p);
653
654
655 }
656 return true;
657}
658
659
660
661
662
663
664
665bool __init early_can_reuse_p2m_middle(unsigned long set_pfn, unsigned long set_mfn)
666{
667 unsigned topidx;
668 unsigned mididx;
669 unsigned ident_pfns;
670 unsigned inv_pfns;
671 unsigned long *p2m;
672 unsigned long *mid_mfn_p;
673 unsigned idx;
674 unsigned long pfn;
675
676
677 if (p2m_index(set_pfn))
678 return false;
679
680 for (pfn = 0; pfn < MAX_DOMAIN_PAGES; pfn += P2M_PER_PAGE) {
681 topidx = p2m_top_index(pfn);
682
683 if (!p2m_top[topidx])
684 continue;
685
686 if (p2m_top[topidx] == p2m_mid_missing)
687 continue;
688
689 mididx = p2m_mid_index(pfn);
690 p2m = p2m_top[topidx][mididx];
691 if (!p2m)
692 continue;
693
694 if ((p2m == p2m_missing) || (p2m == p2m_identity))
695 continue;
696
697 if ((unsigned long)p2m == INVALID_P2M_ENTRY)
698 continue;
699
700 ident_pfns = 0;
701 inv_pfns = 0;
702 for (idx = 0; idx < P2M_PER_PAGE; idx++) {
703
704 if (p2m[idx] == IDENTITY_FRAME(pfn + idx))
705 ident_pfns++;
706 else if (p2m[idx] == INVALID_P2M_ENTRY)
707 inv_pfns++;
708 else
709 break;
710 }
711 if ((ident_pfns == P2M_PER_PAGE) || (inv_pfns == P2M_PER_PAGE))
712 goto found;
713 }
714 return false;
715found:
716
717 p2m_top[topidx][mididx] = (ident_pfns ? p2m_identity : p2m_missing);
718
719 mid_mfn_p = p2m_top_mfn_p[topidx];
720
721
722 mid_mfn_p[mididx] = virt_to_mfn(p2m_missing);
723
724
725 topidx = p2m_top_index(set_pfn);
726 mididx = p2m_mid_index(set_pfn);
727
728
729 if (WARN_ON(p2m_top[topidx] == p2m_mid_missing))
730 early_alloc_p2m(set_pfn);
731
732 if (WARN_ON(p2m_top[topidx][mididx] != p2m_missing))
733 return false;
734
735 p2m_init(p2m);
736 p2m_top[topidx][mididx] = p2m;
737 mid_mfn_p = p2m_top_mfn_p[topidx];
738 mid_mfn_p[mididx] = virt_to_mfn(p2m);
739
740 return true;
741}
742bool __init early_set_phys_to_machine(unsigned long pfn, unsigned long mfn)
743{
744 if (unlikely(!__set_phys_to_machine(pfn, mfn))) {
745 if (!early_alloc_p2m(pfn))
746 return false;
747
748 if (early_can_reuse_p2m_middle(pfn, mfn))
749 return __set_phys_to_machine(pfn, mfn);
750
751 if (!early_alloc_p2m_middle(pfn, false ))
752 return false;
753
754 if (!__set_phys_to_machine(pfn, mfn))
755 return false;
756 }
757
758 return true;
759}
760unsigned long __init set_phys_range_identity(unsigned long pfn_s,
761 unsigned long pfn_e)
762{
763 unsigned long pfn;
764
765 if (unlikely(pfn_s >= MAX_P2M_PFN || pfn_e >= MAX_P2M_PFN))
766 return 0;
767
768 if (unlikely(xen_feature(XENFEAT_auto_translated_physmap)))
769 return pfn_e - pfn_s;
770
771 if (pfn_s > pfn_e)
772 return 0;
773
774 for (pfn = (pfn_s & ~(P2M_MID_PER_PAGE * P2M_PER_PAGE - 1));
775 pfn < ALIGN(pfn_e, (P2M_MID_PER_PAGE * P2M_PER_PAGE));
776 pfn += P2M_MID_PER_PAGE * P2M_PER_PAGE)
777 {
778 WARN_ON(!early_alloc_p2m(pfn));
779 }
780
781 early_alloc_p2m_middle(pfn_s, true);
782 early_alloc_p2m_middle(pfn_e, true);
783
784 for (pfn = pfn_s; pfn < pfn_e; pfn++)
785 if (!__set_phys_to_machine(pfn, IDENTITY_FRAME(pfn)))
786 break;
787
788 if (!WARN((pfn - pfn_s) != (pfn_e - pfn_s),
789 "Identity mapping failed. We are %ld short of 1-1 mappings!\n",
790 (pfn_e - pfn_s) - (pfn - pfn_s)))
791 printk(KERN_DEBUG "1-1 mapping on %lx->%lx\n", pfn_s, pfn);
792
793 return pfn - pfn_s;
794}
795
796
797bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
798{
799 unsigned topidx, mididx, idx;
800
801 if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) {
802 BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
803 return true;
804 }
805 if (unlikely(pfn >= MAX_P2M_PFN)) {
806 BUG_ON(mfn != INVALID_P2M_ENTRY);
807 return true;
808 }
809
810 topidx = p2m_top_index(pfn);
811 mididx = p2m_mid_index(pfn);
812 idx = p2m_index(pfn);
813
814
815
816
817 if (mfn != INVALID_P2M_ENTRY && (mfn & IDENTITY_FRAME_BIT)) {
818 if (p2m_top[topidx][mididx] == p2m_identity)
819 return true;
820
821
822 if (p2m_top[topidx][mididx] == p2m_missing) {
823 WARN_ON(cmpxchg(&p2m_top[topidx][mididx], p2m_missing,
824 p2m_identity) != p2m_missing);
825 return true;
826 }
827 }
828
829 if (p2m_top[topidx][mididx] == p2m_missing)
830 return mfn == INVALID_P2M_ENTRY;
831
832 p2m_top[topidx][mididx][idx] = mfn;
833
834 return true;
835}
836
837bool set_phys_to_machine(unsigned long pfn, unsigned long mfn)
838{
839 if (unlikely(!__set_phys_to_machine(pfn, mfn))) {
840 if (!alloc_p2m(pfn))
841 return false;
842
843 if (!__set_phys_to_machine(pfn, mfn))
844 return false;
845 }
846
847 return true;
848}
849
850#define M2P_OVERRIDE_HASH_SHIFT 10
851#define M2P_OVERRIDE_HASH (1 << M2P_OVERRIDE_HASH_SHIFT)
852
853static RESERVE_BRK_ARRAY(struct list_head, m2p_overrides, M2P_OVERRIDE_HASH);
854static DEFINE_SPINLOCK(m2p_override_lock);
855
856static void __init m2p_override_init(void)
857{
858 unsigned i;
859
860 m2p_overrides = extend_brk(sizeof(*m2p_overrides) * M2P_OVERRIDE_HASH,
861 sizeof(unsigned long));
862
863 for (i = 0; i < M2P_OVERRIDE_HASH; i++)
864 INIT_LIST_HEAD(&m2p_overrides[i]);
865}
866
867static unsigned long mfn_hash(unsigned long mfn)
868{
869 return hash_long(mfn, M2P_OVERRIDE_HASH_SHIFT);
870}
871
872
873int m2p_add_override(unsigned long mfn, struct page *page,
874 struct gnttab_map_grant_ref *kmap_op)
875{
876 unsigned long flags;
877 unsigned long pfn;
878 unsigned long uninitialized_var(address);
879 unsigned level;
880 pte_t *ptep = NULL;
881 int ret = 0;
882
883 pfn = page_to_pfn(page);
884 if (!PageHighMem(page)) {
885 address = (unsigned long)__va(pfn << PAGE_SHIFT);
886 ptep = lookup_address(address, &level);
887 if (WARN(ptep == NULL || level != PG_LEVEL_4K,
888 "m2p_add_override: pfn %lx not mapped", pfn))
889 return -EINVAL;
890 }
891 WARN_ON(PagePrivate(page));
892 SetPagePrivate(page);
893 set_page_private(page, mfn);
894 page->index = pfn_to_mfn(pfn);
895
896 if (unlikely(!set_phys_to_machine(pfn, FOREIGN_FRAME(mfn))))
897 return -ENOMEM;
898
899 if (kmap_op != NULL) {
900 if (!PageHighMem(page)) {
901 struct multicall_space mcs =
902 xen_mc_entry(sizeof(*kmap_op));
903
904 MULTI_grant_table_op(mcs.mc,
905 GNTTABOP_map_grant_ref, kmap_op, 1);
906
907 xen_mc_issue(PARAVIRT_LAZY_MMU);
908 }
909 }
910 spin_lock_irqsave(&m2p_override_lock, flags);
911 list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]);
912 spin_unlock_irqrestore(&m2p_override_lock, flags);
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928 ret = __get_user(pfn, &machine_to_phys_mapping[mfn]);
929 if (ret == 0 && get_phys_to_machine(pfn) == mfn)
930 set_phys_to_machine(pfn, FOREIGN_FRAME(mfn));
931
932 return 0;
933}
934EXPORT_SYMBOL_GPL(m2p_add_override);
935int m2p_remove_override(struct page *page,
936 struct gnttab_map_grant_ref *kmap_op)
937{
938 unsigned long flags;
939 unsigned long mfn;
940 unsigned long pfn;
941 unsigned long uninitialized_var(address);
942 unsigned level;
943 pte_t *ptep = NULL;
944 int ret = 0;
945
946 pfn = page_to_pfn(page);
947 mfn = get_phys_to_machine(pfn);
948 if (mfn == INVALID_P2M_ENTRY || !(mfn & FOREIGN_FRAME_BIT))
949 return -EINVAL;
950
951 if (!PageHighMem(page)) {
952 address = (unsigned long)__va(pfn << PAGE_SHIFT);
953 ptep = lookup_address(address, &level);
954
955 if (WARN(ptep == NULL || level != PG_LEVEL_4K,
956 "m2p_remove_override: pfn %lx not mapped", pfn))
957 return -EINVAL;
958 }
959
960 spin_lock_irqsave(&m2p_override_lock, flags);
961 list_del(&page->lru);
962 spin_unlock_irqrestore(&m2p_override_lock, flags);
963 WARN_ON(!PagePrivate(page));
964 ClearPagePrivate(page);
965
966 set_phys_to_machine(pfn, page->index);
967 if (kmap_op != NULL) {
968 if (!PageHighMem(page)) {
969 struct multicall_space mcs;
970 struct gnttab_unmap_grant_ref *unmap_op;
971
972
973
974
975
976
977
978
979 if (kmap_op->handle == -1)
980 xen_mc_flush();
981
982
983
984
985 if (kmap_op->handle == GNTST_general_error) {
986 printk(KERN_WARNING "m2p_remove_override: "
987 "pfn %lx mfn %lx, failed to modify kernel mappings",
988 pfn, mfn);
989 return -1;
990 }
991
992 mcs = xen_mc_entry(
993 sizeof(struct gnttab_unmap_grant_ref));
994 unmap_op = mcs.args;
995 unmap_op->host_addr = kmap_op->host_addr;
996 unmap_op->handle = kmap_op->handle;
997 unmap_op->dev_bus_addr = 0;
998
999 MULTI_grant_table_op(mcs.mc,
1000 GNTTABOP_unmap_grant_ref, unmap_op, 1);
1001
1002 xen_mc_issue(PARAVIRT_LAZY_MMU);
1003
1004 set_pte_at(&init_mm, address, ptep,
1005 pfn_pte(pfn, PAGE_KERNEL));
1006 __flush_tlb_single(address);
1007 kmap_op->host_addr = 0;
1008 }
1009 }
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021 mfn &= ~FOREIGN_FRAME_BIT;
1022 ret = __get_user(pfn, &machine_to_phys_mapping[mfn]);
1023 if (ret == 0 && get_phys_to_machine(pfn) == FOREIGN_FRAME(mfn) &&
1024 m2p_find_override(mfn) == NULL)
1025 set_phys_to_machine(pfn, mfn);
1026
1027 return 0;
1028}
1029EXPORT_SYMBOL_GPL(m2p_remove_override);
1030
1031struct page *m2p_find_override(unsigned long mfn)
1032{
1033 unsigned long flags;
1034 struct list_head *bucket = &m2p_overrides[mfn_hash(mfn)];
1035 struct page *p, *ret;
1036
1037 ret = NULL;
1038
1039 spin_lock_irqsave(&m2p_override_lock, flags);
1040
1041 list_for_each_entry(p, bucket, lru) {
1042 if (page_private(p) == mfn) {
1043 ret = p;
1044 break;
1045 }
1046 }
1047
1048 spin_unlock_irqrestore(&m2p_override_lock, flags);
1049
1050 return ret;
1051}
1052
1053unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn)
1054{
1055 struct page *p = m2p_find_override(mfn);
1056 unsigned long ret = pfn;
1057
1058 if (p)
1059 ret = page_to_pfn(p);
1060
1061 return ret;
1062}
1063EXPORT_SYMBOL_GPL(m2p_find_override_pfn);
1064
1065#ifdef CONFIG_XEN_DEBUG_FS
1066#include <linux/debugfs.h>
1067#include "debugfs.h"
1068static int p2m_dump_show(struct seq_file *m, void *v)
1069{
1070 static const char * const level_name[] = { "top", "middle",
1071 "entry", "abnormal", "error"};
1072#define TYPE_IDENTITY 0
1073#define TYPE_MISSING 1
1074#define TYPE_PFN 2
1075#define TYPE_UNKNOWN 3
1076 static const char * const type_name[] = {
1077 [TYPE_IDENTITY] = "identity",
1078 [TYPE_MISSING] = "missing",
1079 [TYPE_PFN] = "pfn",
1080 [TYPE_UNKNOWN] = "abnormal"};
1081 unsigned long pfn, prev_pfn_type = 0, prev_pfn_level = 0;
1082 unsigned int uninitialized_var(prev_level);
1083 unsigned int uninitialized_var(prev_type);
1084
1085 if (!p2m_top)
1086 return 0;
1087
1088 for (pfn = 0; pfn < MAX_DOMAIN_PAGES; pfn++) {
1089 unsigned topidx = p2m_top_index(pfn);
1090 unsigned mididx = p2m_mid_index(pfn);
1091 unsigned idx = p2m_index(pfn);
1092 unsigned lvl, type;
1093
1094 lvl = 4;
1095 type = TYPE_UNKNOWN;
1096 if (p2m_top[topidx] == p2m_mid_missing) {
1097 lvl = 0; type = TYPE_MISSING;
1098 } else if (p2m_top[topidx] == NULL) {
1099 lvl = 0; type = TYPE_UNKNOWN;
1100 } else if (p2m_top[topidx][mididx] == NULL) {
1101 lvl = 1; type = TYPE_UNKNOWN;
1102 } else if (p2m_top[topidx][mididx] == p2m_identity) {
1103 lvl = 1; type = TYPE_IDENTITY;
1104 } else if (p2m_top[topidx][mididx] == p2m_missing) {
1105 lvl = 1; type = TYPE_MISSING;
1106 } else if (p2m_top[topidx][mididx][idx] == 0) {
1107 lvl = 2; type = TYPE_UNKNOWN;
1108 } else if (p2m_top[topidx][mididx][idx] == IDENTITY_FRAME(pfn)) {
1109 lvl = 2; type = TYPE_IDENTITY;
1110 } else if (p2m_top[topidx][mididx][idx] == INVALID_P2M_ENTRY) {
1111 lvl = 2; type = TYPE_MISSING;
1112 } else if (p2m_top[topidx][mididx][idx] == pfn) {
1113 lvl = 2; type = TYPE_PFN;
1114 } else if (p2m_top[topidx][mididx][idx] != pfn) {
1115 lvl = 2; type = TYPE_PFN;
1116 }
1117 if (pfn == 0) {
1118 prev_level = lvl;
1119 prev_type = type;
1120 }
1121 if (pfn == MAX_DOMAIN_PAGES-1) {
1122 lvl = 3;
1123 type = TYPE_UNKNOWN;
1124 }
1125 if (prev_type != type) {
1126 seq_printf(m, " [0x%lx->0x%lx] %s\n",
1127 prev_pfn_type, pfn, type_name[prev_type]);
1128 prev_pfn_type = pfn;
1129 prev_type = type;
1130 }
1131 if (prev_level != lvl) {
1132 seq_printf(m, " [0x%lx->0x%lx] level %s\n",
1133 prev_pfn_level, pfn, level_name[prev_level]);
1134 prev_pfn_level = pfn;
1135 prev_level = lvl;
1136 }
1137 }
1138 return 0;
1139#undef TYPE_IDENTITY
1140#undef TYPE_MISSING
1141#undef TYPE_PFN
1142#undef TYPE_UNKNOWN
1143}
1144
1145static int p2m_dump_open(struct inode *inode, struct file *filp)
1146{
1147 return single_open(filp, p2m_dump_show, NULL);
1148}
1149
1150static const struct file_operations p2m_dump_fops = {
1151 .open = p2m_dump_open,
1152 .read = seq_read,
1153 .llseek = seq_lseek,
1154 .release = single_release,
1155};
1156
1157static struct dentry *d_mmu_debug;
1158
1159static int __init xen_p2m_debugfs(void)
1160{
1161 struct dentry *d_xen = xen_init_debugfs();
1162
1163 if (d_xen == NULL)
1164 return -ENOMEM;
1165
1166 d_mmu_debug = debugfs_create_dir("mmu", d_xen);
1167
1168 debugfs_create_file("p2m", 0600, d_mmu_debug, NULL, &p2m_dump_fops);
1169 return 0;
1170}
1171fs_initcall(xen_p2m_debugfs);
1172#endif
1173