| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: x86_xpmap.c,v 1.63 2016/11/01 12:16:10 maxv Exp $ */ | | 1 | /* $NetBSD: x86_xpmap.c,v 1.64 2016/11/11 11:12:42 maxv Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2006 Mathieu Ropert <mro@adviseo.fr> | | 4 | * Copyright (c) 2006 Mathieu Ropert <mro@adviseo.fr> |
5 | * | | 5 | * |
6 | * Permission to use, copy, modify, and distribute this software for any | | 6 | * Permission to use, copy, modify, and distribute this software for any |
7 | * purpose with or without fee is hereby granted, provided that the above | | 7 | * purpose with or without fee is hereby granted, provided that the above |
8 | * copyright notice and this permission notice appear in all copies. | | 8 | * copyright notice and this permission notice appear in all copies. |
9 | * | | 9 | * |
10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | | 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | | 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | | 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | | 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | | 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
| @@ -32,123 +32,128 @@ | | | @@ -32,123 +32,128 @@ |
32 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 32 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
33 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 33 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
34 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | | 34 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
35 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | | 35 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
36 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 36 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
37 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | | 37 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
38 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 38 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
39 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | | 39 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
40 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 40 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
41 | * | | 41 | * |
42 | */ | | 42 | */ |
43 | | | 43 | |
44 | /* | | 44 | /* |
45 | * | | | |
46 | * Copyright (c) 2004 Christian Limpach. | | 45 | * Copyright (c) 2004 Christian Limpach. |
47 | * All rights reserved. | | 46 | * All rights reserved. |
48 | * | | 47 | * |
49 | * Redistribution and use in source and binary forms, with or without | | 48 | * Redistribution and use in source and binary forms, with or without |
50 | * modification, are permitted provided that the following conditions | | 49 | * modification, are permitted provided that the following conditions |
51 | * are met: | | 50 | * are met: |
52 | * 1. Redistributions of source code must retain the above copyright | | 51 | * 1. Redistributions of source code must retain the above copyright |
53 | * notice, this list of conditions and the following disclaimer. | | 52 | * notice, this list of conditions and the following disclaimer. |
54 | * 2. Redistributions in binary form must reproduce the above copyright | | 53 | * 2. Redistributions in binary form must reproduce the above copyright |
55 | * notice, this list of conditions and the following disclaimer in the | | 54 | * notice, this list of conditions and the following disclaimer in the |
56 | * documentation and/or other materials provided with the distribution. | | 55 | * documentation and/or other materials provided with the distribution. |
57 | * | | 56 | * |
58 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | | 57 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
59 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 58 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
60 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 59 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
61 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | | 60 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
62 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | | 61 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
63 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 62 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
64 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | | 63 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
65 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 64 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
66 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | | 65 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
67 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 66 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
68 | */ | | 67 | */ |
69 | | | 68 | |
70 | | | 69 | |
71 | #include <sys/cdefs.h> | | 70 | #include <sys/cdefs.h> |
72 | __KERNEL_RCSID(0, "$NetBSD: x86_xpmap.c,v 1.63 2016/11/01 12:16:10 maxv Exp $"); | | 71 | __KERNEL_RCSID(0, "$NetBSD: x86_xpmap.c,v 1.64 2016/11/11 11:12:42 maxv Exp $"); |
73 | | | 72 | |
74 | #include "opt_xen.h" | | 73 | #include "opt_xen.h" |
75 | #include "opt_ddb.h" | | 74 | #include "opt_ddb.h" |
76 | #include "ksyms.h" | | 75 | #include "ksyms.h" |
77 | | | 76 | |
78 | #include <sys/param.h> | | 77 | #include <sys/param.h> |
79 | #include <sys/systm.h> | | 78 | #include <sys/systm.h> |
80 | #include <sys/mutex.h> | | 79 | #include <sys/mutex.h> |
81 | #include <sys/cpu.h> | | 80 | #include <sys/cpu.h> |
82 | | | 81 | |
83 | #include <uvm/uvm.h> | | 82 | #include <uvm/uvm.h> |
84 | | | 83 | |
85 | #include <x86/pmap.h> | | 84 | #include <x86/pmap.h> |
86 | #include <machine/gdt.h> | | 85 | #include <machine/gdt.h> |
87 | #include <xen/xenfunc.h> | | 86 | #include <xen/xenfunc.h> |
88 | | | 87 | |
89 | #include <dev/isa/isareg.h> | | 88 | #include <dev/isa/isareg.h> |
90 | #include <machine/isa_machdep.h> | | 89 | #include <machine/isa_machdep.h> |
91 | | | 90 | |
92 | #undef XENDEBUG | | 91 | #undef XENDEBUG |
93 | /* #define XENDEBUG_SYNC */ | | 92 | /* #define XENDEBUG_SYNC */ |
94 | /* #define XENDEBUG_LOW */ | | 93 | /* #define XENDEBUG_LOW */ |
95 | | | 94 | |
96 | #ifdef XENDEBUG | | 95 | #ifdef XENDEBUG |
97 | #define XENPRINTF(x) printf x | | 96 | #define XENPRINTF(x) printf x |
98 | #define XENPRINTK(x) printk x | | 97 | #define XENPRINTK(x) printk x |
99 | #define XENPRINTK2(x) /* printk x */ | | 98 | #define XENPRINTK2(x) /* printk x */ |
100 | | | | |
101 | static char XBUF[256]; | | 99 | static char XBUF[256]; |
102 | #else | | 100 | #else |
103 | #define XENPRINTF(x) | | 101 | #define XENPRINTF(x) |
104 | #define XENPRINTK(x) | | 102 | #define XENPRINTK(x) |
105 | #define XENPRINTK2(x) | | 103 | #define XENPRINTK2(x) |
106 | #endif | | 104 | #endif |
107 | #define PRINTF(x) printf x | | 105 | #define PRINTF(x) printf x |
108 | #define PRINTK(x) printk x | | 106 | #define PRINTK(x) printk x |
109 | | | 107 | |
110 | volatile shared_info_t *HYPERVISOR_shared_info; | | 108 | volatile shared_info_t *HYPERVISOR_shared_info; |
111 | /* Xen requires the start_info struct to be page aligned */ | | 109 | /* Xen requires the start_info struct to be page aligned */ |
112 | union start_info_union start_info_union __aligned(PAGE_SIZE); | | 110 | union start_info_union start_info_union __aligned(PAGE_SIZE); |
113 | unsigned long *xpmap_phys_to_machine_mapping; | | 111 | unsigned long *xpmap_phys_to_machine_mapping; |
114 | kmutex_t pte_lock; | | 112 | kmutex_t pte_lock; |
115 | | | 113 | |
116 | void xen_failsafe_handler(void); | | 114 | void xen_failsafe_handler(void); |
117 | | | 115 | |
118 | #define HYPERVISOR_mmu_update_self(req, count, success_count) \ | | 116 | #define HYPERVISOR_mmu_update_self(req, count, success_count) \ |
119 | HYPERVISOR_mmu_update((req), (count), (success_count), DOMID_SELF) | | 117 | HYPERVISOR_mmu_update((req), (count), (success_count), DOMID_SELF) |
120 | | | 118 | |
| | | 119 | extern volatile struct xencons_interface *xencons_interface; /* XXX */ |
| | | 120 | extern struct xenstore_domain_interface *xenstore_interface; /* XXX */ |
| | | 121 | |
| | | 122 | static void xen_bt_set_readonly(vaddr_t); |
| | | 123 | static void xen_bootstrap_tables(vaddr_t, vaddr_t, size_t, size_t, int); |
| | | 124 | |
| | | 125 | vaddr_t xen_pmap_bootstrap(void); |
| | | 126 | |
121 | /* | | 127 | /* |
122 | * kcpuset internally uses an array of uint32_t while xen uses an array of | | 128 | * kcpuset internally uses an array of uint32_t while xen uses an array of |
123 | * u_long. As we're little-endian we can cast one to the other. | | 129 | * u_long. As we're little-endian we can cast one to the other. |
124 | */ | | 130 | */ |
125 | typedef union { | | 131 | typedef union { |
126 | #ifdef _LP64 | | 132 | #ifdef _LP64 |
127 | uint32_t xcpum_km[2]; | | 133 | uint32_t xcpum_km[2]; |
128 | #else | | 134 | #else |
129 | uint32_t xcpum_km[1]; | | 135 | uint32_t xcpum_km[1]; |
130 | #endif | | 136 | #endif |
131 | u_long xcpum_xm; | | 137 | u_long xcpum_xm; |
132 | } xcpumask_t; | | 138 | } xcpumask_t; |
133 | | | 139 | |
134 | void | | 140 | void |
135 | xen_failsafe_handler(void) | | 141 | xen_failsafe_handler(void) |
136 | { | | 142 | { |
137 | | | 143 | |
138 | panic("xen_failsafe_handler called!\n"); | | 144 | panic("xen_failsafe_handler called!\n"); |
139 | } | | 145 | } |
140 | | | 146 | |
141 | | | | |
142 | void | | 147 | void |
143 | xen_set_ldt(vaddr_t base, uint32_t entries) | | 148 | xen_set_ldt(vaddr_t base, uint32_t entries) |
144 | { | | 149 | { |
145 | vaddr_t va; | | 150 | vaddr_t va; |
146 | vaddr_t end; | | 151 | vaddr_t end; |
147 | pt_entry_t *ptp; | | 152 | pt_entry_t *ptp; |
148 | int s; | | 153 | int s; |
149 | | | 154 | |
150 | #ifdef __x86_64__ | | 155 | #ifdef __x86_64__ |
151 | end = base + (entries << 3); | | 156 | end = base + (entries << 3); |
152 | #else | | 157 | #else |
153 | end = base + entries * sizeof(union descriptor); | | 158 | end = base + entries * sizeof(union descriptor); |
154 | #endif | | 159 | #endif |
| @@ -558,365 +563,324 @@ xpq_debug_dump(void) | | | @@ -558,365 +563,324 @@ xpq_debug_dump(void) |
558 | "%" PRIx64 " %08" PRIx64, | | 563 | "%" PRIx64 " %08" PRIx64, |
559 | xpq_queue[i].ptr, xpq_queue[i].val); | | 564 | xpq_queue[i].ptr, xpq_queue[i].val); |
560 | if (++i < xpq_idx) | | 565 | if (++i < xpq_idx) |
561 | snprintf(XBUF + strlen(XBUF), | | 566 | snprintf(XBUF + strlen(XBUF), |
562 | sizeof(XBUF) - strlen(XBUF), | | 567 | sizeof(XBUF) - strlen(XBUF), |
563 | "%" PRIx64 " %08" PRIx64, | | 568 | "%" PRIx64 " %08" PRIx64, |
564 | xpq_queue[i].ptr, xpq_queue[i].val); | | 569 | xpq_queue[i].ptr, xpq_queue[i].val); |
565 | XENPRINTK2(("%d: %s\n", xpq_idx, XBUF)); | | 570 | XENPRINTK2(("%d: %s\n", xpq_idx, XBUF)); |
566 | } | | 571 | } |
567 | } | | 572 | } |
568 | #endif | | 573 | #endif |
569 | | | 574 | |
570 | | | 575 | |
571 | extern volatile struct xencons_interface *xencons_interface; /* XXX */ | | | |
572 | extern struct xenstore_domain_interface *xenstore_interface; /* XXX */ | | | |
573 | | | | |
574 | static void xen_bt_set_readonly(vaddr_t); | | | |
575 | static void xen_bootstrap_tables(vaddr_t, vaddr_t, int, int, int); | | | |
576 | | | | |
577 | /* How many PDEs ? */ | | | |
578 | #if L2_SLOT_KERNBASE > 0 | | 576 | #if L2_SLOT_KERNBASE > 0 |
579 | #define TABLE_L2_ENTRIES (2 * (NKL2_KIMG_ENTRIES + 1)) | | 577 | #define TABLE_L2_ENTRIES (2 * (NKL2_KIMG_ENTRIES + 1)) |
580 | #else | | 578 | #else |
581 | #define TABLE_L2_ENTRIES (NKL2_KIMG_ENTRIES + 1) | | 579 | #define TABLE_L2_ENTRIES (NKL2_KIMG_ENTRIES + 1) |
582 | #endif | | 580 | #endif |
583 | | | 581 | |
584 | /* | | | |
585 | * Construct and switch to new pagetables | | | |
586 | * first_avail is the first vaddr we can use after | | | |
587 | * we get rid of Xen pagetables | | | |
588 | */ | | | |
589 | | | | |
590 | vaddr_t xen_pmap_bootstrap(void); | | | |
591 | | | | |
592 | /* | | | |
593 | * Function to get rid of Xen bootstrap tables | | | |
594 | */ | | | |
595 | | | | |
596 | /* How many PDP do we need: */ | | | |
597 | #ifdef PAE | | 582 | #ifdef PAE |
598 | /* | | 583 | /* |
599 | * For PAE, we consider a single contigous L2 "superpage" of 4 pages, | | 584 | * For PAE, we consider a single contigous L2 "superpage" of 4 pages, all of |
600 | * all of them mapped by the L3 page. We also need a shadow page | | 585 | * them mapped by the L3 page. We also need a shadow page for L3[3]. |
601 | * for L3[3]. | | | |
602 | */ | | 586 | */ |
603 | static const int l2_4_count = 6; | | 587 | static const int l2_4_count = 6; |
604 | #elif defined(__x86_64__) | | 588 | #elif defined(__x86_64__) |
605 | static const int l2_4_count = PTP_LEVELS; | | 589 | static const int l2_4_count = PTP_LEVELS; |
606 | #else | | 590 | #else |
607 | static const int l2_4_count = PTP_LEVELS - 1; | | 591 | static const int l2_4_count = PTP_LEVELS - 1; |
608 | #endif | | 592 | #endif |
609 | | | 593 | |
| | | 594 | /* |
| | | 595 | * Xen locore: get rid of the Xen bootstrap tables. Build and switch to new page |
| | | 596 | * tables. |
| | | 597 | */ |
610 | vaddr_t | | 598 | vaddr_t |
611 | xen_pmap_bootstrap(void) | | 599 | xen_pmap_bootstrap(void) |
612 | { | | 600 | { |
613 | int count, oldcount; | | 601 | size_t count, oldcount, mapsize; |
614 | long mapsize; | | | |
615 | vaddr_t bootstrap_tables, init_tables; | | 602 | vaddr_t bootstrap_tables, init_tables; |
616 | | | 603 | |
617 | xen_init_features(); | | 604 | xen_init_features(); |
618 | | | 605 | |
619 | memset(xpq_idx_array, 0, sizeof(xpq_idx_array)); | | 606 | memset(xpq_idx_array, 0, sizeof(xpq_idx_array)); |
620 | | | 607 | |
621 | xpmap_phys_to_machine_mapping = | | 608 | xpmap_phys_to_machine_mapping = |
622 | (unsigned long *)xen_start_info.mfn_list; | | 609 | (unsigned long *)xen_start_info.mfn_list; |
623 | init_tables = xen_start_info.pt_base; | | | |
624 | __PRINTK(("xen_arch_pmap_bootstrap init_tables=0x%lx\n", init_tables)); | | | |
625 | | | 610 | |
626 | /* Space after Xen boostrap tables should be free */ | | 611 | /* Space after Xen boostrap tables should be free */ |
627 | bootstrap_tables = xen_start_info.pt_base + | | 612 | init_tables = xen_start_info.pt_base; |
628 | (xen_start_info.nr_pt_frames * PAGE_SIZE); | | 613 | bootstrap_tables = init_tables + |
| | | 614 | (xen_start_info.nr_pt_frames * PAGE_SIZE); |
629 | | | 615 | |
630 | /* | | 616 | /* |
631 | * Calculate how many space we need | | 617 | * Calculate how much space we need. First, everything mapped before |
632 | * first everything mapped before the Xen bootstrap tables | | 618 | * the Xen bootstrap tables. |
633 | */ | | 619 | */ |
634 | mapsize = init_tables - KERNTEXTOFF; | | 620 | mapsize = init_tables - KERNTEXTOFF; |
635 | /* after the tables we'll have: | | 621 | /* after the tables we'll have: |
636 | * - UAREA | | 622 | * - UAREA |
637 | * - dummy user PGD (x86_64) | | 623 | * - dummy user PGD (x86_64) |
638 | * - HYPERVISOR_shared_info | | 624 | * - HYPERVISOR_shared_info |
639 | * - early_zerop | | 625 | * - early_zerop |
640 | * - ISA I/O mem (if needed) | | 626 | * - ISA I/O mem (if needed) |
641 | */ | | 627 | */ |
642 | mapsize += UPAGES * PAGE_SIZE; | | 628 | mapsize += UPAGES * PAGE_SIZE; |
643 | #ifdef __x86_64__ | | 629 | #ifdef __x86_64__ |
644 | mapsize += PAGE_SIZE; | | 630 | mapsize += PAGE_SIZE; |
645 | #endif | | 631 | #endif |
646 | mapsize += PAGE_SIZE; | | 632 | mapsize += PAGE_SIZE; |
647 | mapsize += PAGE_SIZE; | | 633 | mapsize += PAGE_SIZE; |
648 | | | | |
649 | #ifdef DOM0OPS | | 634 | #ifdef DOM0OPS |
650 | if (xendomain_is_dom0()) { | | 635 | if (xendomain_is_dom0()) { |
651 | /* space for ISA I/O mem */ | | | |
652 | mapsize += IOM_SIZE; | | 636 | mapsize += IOM_SIZE; |
653 | } | | 637 | } |
654 | #endif | | 638 | #endif |
655 | /* at this point mapsize doesn't include the table size */ | | | |
656 | | | 639 | |
| | | 640 | /* |
| | | 641 | * At this point, mapsize doesn't include the table size. |
| | | 642 | */ |
657 | #ifdef __x86_64__ | | 643 | #ifdef __x86_64__ |
658 | count = TABLE_L2_ENTRIES; | | 644 | count = TABLE_L2_ENTRIES; |
659 | #else | | 645 | #else |
660 | count = (mapsize + (NBPD_L2 -1)) >> L2_SHIFT; | | 646 | count = (mapsize + (NBPD_L2 -1)) >> L2_SHIFT; |
661 | #endif /* __x86_64__ */ | | 647 | #endif |
662 | | | 648 | |
663 | /* now compute how many L2 pages we need exactly */ | | 649 | /* |
664 | XENPRINTK(("bootstrap_final mapsize 0x%lx count %d\n", mapsize, count)); | | 650 | * Now compute how many L2 pages we need exactly. This is useful only |
| | | 651 | * on i386, since the initial count for amd64 is already enough. |
| | | 652 | */ |
665 | while (mapsize + (count + l2_4_count) * PAGE_SIZE + KERNTEXTOFF > | | 653 | while (mapsize + (count + l2_4_count) * PAGE_SIZE + KERNTEXTOFF > |
666 | ((long)count << L2_SHIFT) + KERNBASE) { | | 654 | (count << L2_SHIFT) + KERNBASE) { |
667 | count++; | | 655 | count++; |
668 | } | | 656 | } |
| | | 657 | |
669 | #ifndef __x86_64__ | | 658 | #ifndef __x86_64__ |
670 | /* | | 659 | /* |
671 | * one more L2 page: we'll alocate several pages after kva_start | | 660 | * One more L2 page: we'll allocate several pages after kva_start |
672 | * in pmap_bootstrap() before pmap_growkernel(), which have not been | | 661 | * in pmap_bootstrap() before pmap_growkernel(), which have not been |
673 | * counted here. It's not a big issue to allocate one more L2 as | | 662 | * counted here. It's not a big issue to allocate one more L2 as |
674 | * pmap_growkernel() will be called anyway. | | 663 | * pmap_growkernel() will be called anyway. |
675 | */ | | 664 | */ |
676 | count++; | | 665 | count++; |
677 | nkptp[1] = count; | | 666 | nkptp[1] = count; |
678 | #endif | | 667 | #endif |
679 | | | 668 | |
680 | /* | | 669 | /* |
681 | * install bootstrap pages. We may need more L2 pages than will | | 670 | * Install bootstrap pages. We may need more L2 pages than will |
682 | * have the final table here, as it's installed after the final table | | 671 | * have the final table here, as it's installed after the final table. |
683 | */ | | 672 | */ |
684 | oldcount = count; | | 673 | oldcount = count; |
685 | | | 674 | |
686 | bootstrap_again: | | 675 | bootstrap_again: |
687 | XENPRINTK(("bootstrap_again oldcount %d\n", oldcount)); | | 676 | |
688 | /* | | 677 | /* |
689 | * Xen space we'll reclaim may not be enough for our new page tables, | | 678 | * Xen space we'll reclaim may not be enough for our new page tables, |
690 | * move bootstrap tables if necessary | | 679 | * move bootstrap tables if necessary. |
691 | */ | | 680 | */ |
692 | if (bootstrap_tables < init_tables + ((count + l2_4_count) * PAGE_SIZE)) | | 681 | if (bootstrap_tables < init_tables + ((count + l2_4_count) * PAGE_SIZE)) |
693 | bootstrap_tables = init_tables + | | 682 | bootstrap_tables = init_tables + |
694 | ((count + l2_4_count) * PAGE_SIZE); | | 683 | ((count + l2_4_count) * PAGE_SIZE); |
695 | /* make sure we have enough to map the bootstrap_tables */ | | 684 | |
| | | 685 | /* Make sure we have enough to map the bootstrap tables. */ |
696 | if (bootstrap_tables + ((oldcount + l2_4_count) * PAGE_SIZE) > | | 686 | if (bootstrap_tables + ((oldcount + l2_4_count) * PAGE_SIZE) > |
697 | ((long)oldcount << L2_SHIFT) + KERNBASE) { | | 687 | (oldcount << L2_SHIFT) + KERNBASE) { |
698 | oldcount++; | | 688 | oldcount++; |
699 | goto bootstrap_again; | | 689 | goto bootstrap_again; |
700 | } | | 690 | } |
701 | | | 691 | |
702 | /* Create temporary tables */ | | 692 | /* Create temporary tables */ |
703 | xen_bootstrap_tables(xen_start_info.pt_base, bootstrap_tables, | | 693 | xen_bootstrap_tables(init_tables, bootstrap_tables, |
704 | xen_start_info.nr_pt_frames, oldcount, 0); | | 694 | xen_start_info.nr_pt_frames, oldcount, 0); |
705 | | | 695 | |
706 | /* Create final tables */ | | 696 | /* Create final tables */ |
707 | xen_bootstrap_tables(bootstrap_tables, init_tables, | | 697 | xen_bootstrap_tables(bootstrap_tables, init_tables, |
708 | oldcount + l2_4_count, count, 1); | | 698 | oldcount + l2_4_count, count, 1); |
709 | | | 699 | |
710 | /* zero out free space after tables */ | | 700 | /* Zero out free space after tables */ |
711 | memset((void *)(init_tables + ((count + l2_4_count) * PAGE_SIZE)), 0, | | 701 | memset((void *)(init_tables + ((count + l2_4_count) * PAGE_SIZE)), 0, |
712 | (UPAGES + 1) * PAGE_SIZE); | | 702 | (UPAGES + 1) * PAGE_SIZE); |
713 | | | 703 | |
714 | /* Finally, flush TLB. */ | | 704 | /* Finally, flush TLB. */ |
715 | xpq_queue_tlb_flush(); | | 705 | xpq_queue_tlb_flush(); |
716 | | | 706 | |
717 | return (init_tables + ((count + l2_4_count) * PAGE_SIZE)); | | 707 | return (init_tables + ((count + l2_4_count) * PAGE_SIZE)); |
718 | } | | 708 | } |
719 | | | 709 | |
720 | /* | | 710 | /* |
721 | * Build a new table and switch to it. | | 711 | * Build a new table and switch to it. |
722 | * old_count is # of old tables (including PGD, PDTPE and PDE). | | 712 | * old_count is # of old tables (including PGD, PDTPE and PDE). |
723 | * new_count is # of new tables (PTE only). | | 713 | * new_count is # of new tables (PTE only). |
724 | * We assume the areas don't overlap. | | 714 | * We assume the areas don't overlap. |
725 | */ | | 715 | */ |
726 | static void | | 716 | static void |
727 | xen_bootstrap_tables(vaddr_t old_pgd, vaddr_t new_pgd, | | 717 | xen_bootstrap_tables(vaddr_t old_pgd, vaddr_t new_pgd, size_t old_count, |
728 | int old_count, int new_count, int final) | | 718 | size_t new_count, int final) |
729 | { | | 719 | { |
730 | pd_entry_t *pdtpe, *pde, *pte; | | 720 | pd_entry_t *pdtpe, *pde, *pte; |
731 | pd_entry_t *bt_pgd; | | 721 | pd_entry_t *bt_pgd; |
732 | paddr_t addr; | | 722 | paddr_t addr; |
733 | vaddr_t page, avail, map_end; | | 723 | vaddr_t page, avail, map_end; |
734 | int i; | | 724 | int i; |
735 | extern char __rodata_start; | | 725 | extern char __rodata_start; |
736 | extern char __data_start; | | 726 | extern char __data_start; |
737 | extern char __kernel_end; | | 727 | extern char __kernel_end; |
738 | extern char *early_zerop; /* from pmap.c */ | | 728 | extern char *early_zerop; /* from pmap.c */ |
739 | pt_entry_t pg_nx; | | 729 | pt_entry_t pg_nx; |
740 | u_int descs[4]; | | 730 | u_int descs[4]; |
741 | | | 731 | |
742 | __PRINTK(("xen_bootstrap_tables(%#" PRIxVADDR ", %#" PRIxVADDR "," | | | |
743 | " %d, %d)\n", | | | |
744 | old_pgd, new_pgd, old_count, new_count)); | | | |
745 | | | | |
746 | /* | | 732 | /* |
747 | * Set the NX/XD bit, if available. descs[3] = %edx. | | 733 | * Set the NX/XD bit, if available. descs[3] = %edx. |
748 | */ | | 734 | */ |
749 | x86_cpuid(0x80000001, descs); | | 735 | x86_cpuid(0x80000001, descs); |
750 | pg_nx = (descs[3] & CPUID_NOX) ? PG_NX : 0; | | 736 | pg_nx = (descs[3] & CPUID_NOX) ? PG_NX : 0; |
751 | | | 737 | |
752 | /* | | 738 | /* |
753 | * size of R/W area after kernel text: | | 739 | * Size of RW area after the kernel image: |
754 | * xencons_interface (if present) | | 740 | * xencons_interface (if present) |
755 | * xenstore_interface (if present) | | 741 | * xenstore_interface (if present) |
756 | * table pages (new_count + l2_4_count entries) | | 742 | * table pages (new_count + l2_4_count entries) |
757 | * extra mappings (only when final is true): | | 743 | * Extra mappings (only when final is true): |
758 | * UAREA | | 744 | * UAREA |
759 | * dummy user PGD (x86_64 only)/gdt page (i386 only) | | 745 | * dummy user PGD (x86_64 only) / GDT page (i386 only) |
760 | * HYPERVISOR_shared_info | | 746 | * HYPERVISOR_shared_info |
761 | * early_zerop | | 747 | * early_zerop |
762 | * ISA I/O mem (if needed) | | 748 | * ISA I/O mem (if needed) |
763 | */ | | 749 | */ |
764 | map_end = new_pgd + ((new_count + l2_4_count) * PAGE_SIZE); | | 750 | map_end = new_pgd + ((new_count + l2_4_count) * PAGE_SIZE); |
765 | if (final) { | | 751 | if (final) { |
766 | map_end += (UPAGES + 1) * PAGE_SIZE; | | 752 | map_end += (UPAGES + 1) * PAGE_SIZE; |
767 | HYPERVISOR_shared_info = (shared_info_t *)map_end; | | 753 | HYPERVISOR_shared_info = (shared_info_t *)map_end; |
768 | map_end += PAGE_SIZE; | | 754 | map_end += PAGE_SIZE; |
769 | early_zerop = (char *)map_end; | | 755 | early_zerop = (char *)map_end; |
770 | map_end += PAGE_SIZE; | | 756 | map_end += PAGE_SIZE; |
771 | } | | 757 | } |
772 | | | 758 | |
773 | /* | | 759 | /* |
774 | * we always set atdevbase, as it's used by init386 to find the first | | 760 | * We always set atdevbase, as it's used by init386 to find the first |
775 | * available VA. map_end is updated only if we are dom0, so | | 761 | * available VA. map_end is updated only if we are dom0, so |
776 | * atdevbase -> atdevbase + IOM_SIZE will be mapped only in | | 762 | * atdevbase -> atdevbase + IOM_SIZE will be mapped only in |
777 | * this case. | | 763 | * this case. |
778 | */ | | 764 | */ |
779 | if (final) | | 765 | if (final) |
780 | atdevbase = map_end; | | 766 | atdevbase = map_end; |
781 | #ifdef DOM0OPS | | 767 | #ifdef DOM0OPS |
782 | if (final && xendomain_is_dom0()) { | | 768 | if (final && xendomain_is_dom0()) { |
783 | /* ISA I/O mem */ | | 769 | /* ISA I/O mem */ |
784 | map_end += IOM_SIZE; | | 770 | map_end += IOM_SIZE; |
785 | } | | 771 | } |
786 | #endif /* DOM0OPS */ | | 772 | #endif |
787 | | | 773 | |
788 | __PRINTK(("xen_bootstrap_tables map_end 0x%lx\n", map_end)); | | 774 | __PRINTK(("xen_bootstrap_tables map_end 0x%lx\n", map_end)); |
789 | __PRINTK(("console %#lx ", xen_start_info.console_mfn)); | | 775 | __PRINTK(("console %#lx ", xen_start_info.console_mfn)); |
790 | __PRINTK(("xenstore %#" PRIx32 "\n", xen_start_info.store_mfn)); | | 776 | __PRINTK(("xenstore %#" PRIx32 "\n", xen_start_info.store_mfn)); |
791 | | | 777 | |
792 | /* | | 778 | /* |
793 | * Create bootstrap page tables. What we need: | | 779 | * Create bootstrap page tables. What we need: |
794 | * - a PGD (level 4) | | 780 | * - a PGD (level 4) |
795 | * - a PDTPE (level 3) | | 781 | * - a PDTPE (level 3) |
796 | * - a PDE (level 2) | | 782 | * - a PDE (level 2) |
797 | * - some PTEs (level 1) | | 783 | * - some PTEs (level 1) |
798 | */ | | 784 | */ |
799 | | | 785 | |
800 | bt_pgd = (pd_entry_t *)new_pgd; | | 786 | bt_pgd = (pd_entry_t *)new_pgd; |
801 | memset(bt_pgd, 0, PAGE_SIZE); | | 787 | memset(bt_pgd, 0, PAGE_SIZE); |
802 | avail = new_pgd + PAGE_SIZE; | | 788 | avail = new_pgd + PAGE_SIZE; |
803 | | | 789 | |
804 | #if PTP_LEVELS > 3 | | 790 | #if PTP_LEVELS > 3 |
805 | /* per-cpu L4 PD */ | | 791 | /* Per-cpu L4 */ |
806 | pd_entry_t *bt_cpu_pgd = bt_pgd; | | 792 | pd_entry_t *bt_cpu_pgd = bt_pgd; |
807 | /* pmap_kernel() "shadow" L4 PD */ | | 793 | /* pmap_kernel() "shadow" L4 */ |
808 | bt_pgd = (pd_entry_t *)avail; | | 794 | bt_pgd = (pd_entry_t *)avail; |
809 | memset(bt_pgd, 0, PAGE_SIZE); | | 795 | memset(bt_pgd, 0, PAGE_SIZE); |
810 | avail += PAGE_SIZE; | | 796 | avail += PAGE_SIZE; |
811 | | | 797 | |
812 | /* Install level 3 */ | | 798 | /* Install L3 */ |
813 | pdtpe = (pd_entry_t *)avail; | | 799 | pdtpe = (pd_entry_t *)avail; |
814 | memset(pdtpe, 0, PAGE_SIZE); | | 800 | memset(pdtpe, 0, PAGE_SIZE); |
815 | avail += PAGE_SIZE; | | 801 | avail += PAGE_SIZE; |
816 | | | 802 | |
817 | addr = ((u_long)pdtpe) - KERNBASE; | | 803 | addr = ((u_long)pdtpe) - KERNBASE; |
818 | bt_pgd[pl4_pi(KERNTEXTOFF)] = bt_cpu_pgd[pl4_pi(KERNTEXTOFF)] = | | 804 | bt_pgd[pl4_pi(KERNTEXTOFF)] = bt_cpu_pgd[pl4_pi(KERNTEXTOFF)] = |
819 | xpmap_ptom_masked(addr) | PG_k | PG_RW | PG_V; | | 805 | xpmap_ptom_masked(addr) | PG_k | PG_RW | PG_V; |
820 | | | | |
821 | __PRINTK(("L3 va %#lx pa %#" PRIxPADDR " entry %#" PRIxPADDR | | | |
822 | " -> L4[%#x]\n", | | | |
823 | pdtpe, addr, bt_pgd[pl4_pi(KERNTEXTOFF)], pl4_pi(KERNTEXTOFF))); | | | |
824 | #else | | 806 | #else |
825 | pdtpe = bt_pgd; | | 807 | pdtpe = bt_pgd; |
826 | #endif /* PTP_LEVELS > 3 */ | | 808 | #endif |
827 | | | 809 | |
828 | #if PTP_LEVELS > 2 | | 810 | #if PTP_LEVELS > 2 |
829 | /* Level 2 */ | | 811 | /* Level 2 */ |
830 | pde = (pd_entry_t *)avail; | | 812 | pde = (pd_entry_t *)avail; |
831 | memset(pde, 0, PAGE_SIZE); | | 813 | memset(pde, 0, PAGE_SIZE); |
832 | avail += PAGE_SIZE; | | 814 | avail += PAGE_SIZE; |
833 | | | 815 | |
834 | addr = ((u_long)pde) - KERNBASE; | | 816 | addr = ((u_long)pde) - KERNBASE; |
835 | pdtpe[pl3_pi(KERNTEXTOFF)] = | | 817 | pdtpe[pl3_pi(KERNTEXTOFF)] = |
836 | xpmap_ptom_masked(addr) | PG_k | PG_V | PG_RW; | | 818 | xpmap_ptom_masked(addr) | PG_k | PG_V | PG_RW; |
837 | __PRINTK(("L2 va %#lx pa %#" PRIxPADDR " entry %#" PRIxPADDR | | | |
838 | " -> L3[%#x]\n", | | | |
839 | pde, addr, pdtpe[pl3_pi(KERNTEXTOFF)], pl3_pi(KERNTEXTOFF))); | | | |
840 | #elif defined(PAE) | | 819 | #elif defined(PAE) |
841 | /* our PAE-style level 2: 5 contigous pages (4 L2 + 1 shadow) */ | | 820 | /* Our PAE-style level 2: 5 contigous pages (4 L2 + 1 shadow) */ |
842 | pde = (pd_entry_t *)avail; | | 821 | pde = (pd_entry_t *)avail; |
843 | memset(pde, 0, PAGE_SIZE * 5); | | 822 | memset(pde, 0, PAGE_SIZE * 5); |
844 | avail += PAGE_SIZE * 5; | | 823 | avail += PAGE_SIZE * 5; |
845 | addr = ((u_long)pde) - KERNBASE; | | 824 | addr = ((u_long)pde) - KERNBASE; |
| | | 825 | |
846 | /* | | 826 | /* |
847 | * enter L2 pages in the L3. | | 827 | * Enter L2 pages in L3. The real L2 kernel PD will be the last one |
848 | * The real L2 kernel PD will be the last one (so that | | 828 | * (so that pde[L2_SLOT_KERN] always points to the shadow). |
849 | * pde[L2_SLOT_KERN] always point to the shadow). | | | |
850 | */ | | 829 | */ |
851 | for (i = 0; i < 3; i++, addr += PAGE_SIZE) { | | 830 | for (i = 0; i < 3; i++, addr += PAGE_SIZE) { |
852 | /* | | 831 | /* |
853 | * Xen doesn't want R/W mappings in L3 entries, it'll add it | | 832 | * Xen doesn't want RW mappings in L3 entries, it'll add it |
854 | * itself. | | 833 | * itself. |
855 | */ | | 834 | */ |
856 | pdtpe[i] = xpmap_ptom_masked(addr) | PG_k | PG_V; | | 835 | pdtpe[i] = xpmap_ptom_masked(addr) | PG_k | PG_V; |
857 | __PRINTK(("L2 va %#lx pa %#" PRIxPADDR " entry %#" PRIxPADDR | | | |
858 | " -> L3[%#x]\n", | | | |
859 | (vaddr_t)pde + PAGE_SIZE * i, addr, pdtpe[i], i)); | | | |
860 | } | | 836 | } |
861 | addr += PAGE_SIZE; | | 837 | addr += PAGE_SIZE; |
862 | pdtpe[3] = xpmap_ptom_masked(addr) | PG_k | PG_V; | | 838 | pdtpe[3] = xpmap_ptom_masked(addr) | PG_k | PG_V; |
863 | __PRINTK(("L2 va %#lx pa %#" PRIxPADDR " entry %#" PRIxPADDR | | 839 | #else |
864 | " -> L3[%#x]\n", | | | |
865 | (vaddr_t)pde + PAGE_SIZE * 4, addr, pdtpe[3], 3)); | | | |
866 | #else /* PAE */ | | | |
867 | pde = bt_pgd; | | 840 | pde = bt_pgd; |
868 | #endif /* PTP_LEVELS > 2 */ | | 841 | #endif |
869 | | | 842 | |
870 | /* Level 1 */ | | 843 | /* Level 1 */ |
871 | page = KERNTEXTOFF; | | 844 | page = KERNTEXTOFF; |
872 | for (i = 0; i < new_count; i ++) { | | 845 | for (i = 0; i < new_count; i ++) { |
873 | vaddr_t cur_page = page; | | 846 | vaddr_t cur_page = page; |
874 | | | 847 | |
875 | pte = (pd_entry_t *)avail; | | 848 | pte = (pd_entry_t *)avail; |
876 | avail += PAGE_SIZE; | | 849 | avail += PAGE_SIZE; |
877 | | | 850 | |
878 | memset(pte, 0, PAGE_SIZE); | | 851 | memset(pte, 0, PAGE_SIZE); |
879 | while (pl2_pi(page) == pl2_pi(cur_page)) { | | 852 | while (pl2_pi(page) == pl2_pi(cur_page)) { |
880 | if (page >= map_end) { | | 853 | if (page >= map_end) { |
881 | /* not mapped at all */ | | 854 | /* not mapped at all */ |
882 | pte[pl1_pi(page)] = 0; | | 855 | pte[pl1_pi(page)] = 0; |
883 | page += PAGE_SIZE; | | 856 | page += PAGE_SIZE; |
884 | continue; | | 857 | continue; |
885 | } | | 858 | } |
886 | pte[pl1_pi(page)] = xpmap_ptom_masked(page - KERNBASE); | | 859 | pte[pl1_pi(page)] = xpmap_ptom_masked(page - KERNBASE); |
887 | if (page == (vaddr_t)HYPERVISOR_shared_info) { | | 860 | if (page == (vaddr_t)HYPERVISOR_shared_info) { |
888 | pte[pl1_pi(page)] = xen_start_info.shared_info; | | 861 | pte[pl1_pi(page)] = xen_start_info.shared_info; |
889 | __PRINTK(("HYPERVISOR_shared_info " | | | |
890 | "va %#lx pte %#" PRIxPADDR "\n", | | | |
891 | HYPERVISOR_shared_info, pte[pl1_pi(page)])); | | | |
892 | } | | 862 | } |
893 | if ((xpmap_ptom_masked(page - KERNBASE) >> PAGE_SHIFT) | | 863 | if ((xpmap_ptom_masked(page - KERNBASE) >> PAGE_SHIFT) |
894 | == xen_start_info.console.domU.mfn) { | | 864 | == xen_start_info.console.domU.mfn) { |
895 | xencons_interface = (void *)page; | | 865 | xencons_interface = (void *)page; |
896 | pte[pl1_pi(page)] = xen_start_info.console_mfn; | | 866 | pte[pl1_pi(page)] = xen_start_info.console_mfn; |
897 | pte[pl1_pi(page)] <<= PAGE_SHIFT; | | 867 | pte[pl1_pi(page)] <<= PAGE_SHIFT; |
898 | __PRINTK(("xencons_interface " | | | |
899 | "va %#lx pte %#" PRIxPADDR "\n", | | | |
900 | xencons_interface, pte[pl1_pi(page)])); | | | |
901 | } | | 868 | } |
902 | if ((xpmap_ptom_masked(page - KERNBASE) >> PAGE_SHIFT) | | 869 | if ((xpmap_ptom_masked(page - KERNBASE) >> PAGE_SHIFT) |
903 | == xen_start_info.store_mfn) { | | 870 | == xen_start_info.store_mfn) { |
904 | xenstore_interface = (void *)page; | | 871 | xenstore_interface = (void *)page; |
905 | pte[pl1_pi(page)] = xen_start_info.store_mfn; | | 872 | pte[pl1_pi(page)] = xen_start_info.store_mfn; |
906 | pte[pl1_pi(page)] <<= PAGE_SHIFT; | | 873 | pte[pl1_pi(page)] <<= PAGE_SHIFT; |
907 | __PRINTK(("xenstore_interface " | | | |
908 | "va %#lx pte %#" PRIxPADDR "\n", | | | |
909 | xenstore_interface, pte[pl1_pi(page)])); | | | |
910 | } | | 874 | } |
911 | #ifdef DOM0OPS | | 875 | #ifdef DOM0OPS |
912 | if (page >= (vaddr_t)atdevbase && | | 876 | if (page >= (vaddr_t)atdevbase && |
913 | page < (vaddr_t)atdevbase + IOM_SIZE) { | | 877 | page < (vaddr_t)atdevbase + IOM_SIZE) { |
914 | pte[pl1_pi(page)] = | | 878 | pte[pl1_pi(page)] = |
915 | IOM_BEGIN + (page - (vaddr_t)atdevbase); | | 879 | IOM_BEGIN + (page - (vaddr_t)atdevbase); |
916 | pte[pl1_pi(page)] |= pg_nx; | | 880 | pte[pl1_pi(page)] |= pg_nx; |
917 | } | | 881 | } |
918 | #endif | | 882 | #endif |
919 | | | 883 | |
920 | pte[pl1_pi(page)] |= PG_k | PG_V; | | 884 | pte[pl1_pi(page)] |= PG_k | PG_V; |
921 | if (page < (vaddr_t)&__rodata_start) { | | 885 | if (page < (vaddr_t)&__rodata_start) { |
922 | /* Map the kernel text RX. */ | | 886 | /* Map the kernel text RX. */ |
| @@ -926,105 +890,94 @@ xen_bootstrap_tables(vaddr_t old_pgd, va | | | @@ -926,105 +890,94 @@ xen_bootstrap_tables(vaddr_t old_pgd, va |
926 | /* Map the kernel rodata R. */ | | 890 | /* Map the kernel rodata R. */ |
927 | pte[pl1_pi(page)] |= PG_RO | pg_nx; | | 891 | pte[pl1_pi(page)] |= PG_RO | pg_nx; |
928 | } else if (page >= old_pgd && | | 892 | } else if (page >= old_pgd && |
929 | page < old_pgd + (old_count * PAGE_SIZE)) { | | 893 | page < old_pgd + (old_count * PAGE_SIZE)) { |
930 | /* Map the old page tables R. */ | | 894 | /* Map the old page tables R. */ |
931 | pte[pl1_pi(page)] |= PG_RO | pg_nx; | | 895 | pte[pl1_pi(page)] |= PG_RO | pg_nx; |
932 | } else if (page >= new_pgd && | | 896 | } else if (page >= new_pgd && |
933 | page < new_pgd + ((new_count + l2_4_count) * PAGE_SIZE)) { | | 897 | page < new_pgd + ((new_count + l2_4_count) * PAGE_SIZE)) { |
934 | /* Map the new page tables R. */ | | 898 | /* Map the new page tables R. */ |
935 | pte[pl1_pi(page)] |= PG_RO | pg_nx; | | 899 | pte[pl1_pi(page)] |= PG_RO | pg_nx; |
936 | #ifdef i386 | | 900 | #ifdef i386 |
937 | } else if (page == (vaddr_t)tmpgdt) { | | 901 | } else if (page == (vaddr_t)tmpgdt) { |
938 | /* | | 902 | /* |
939 | * Map bootstrap gdt R/O. Later, we | | 903 | * Map bootstrap gdt R/O. Later, we will re-add |
940 | * will re-add this to page to uvm | | 904 | * this page to uvm after making it writable. |
941 | * after making it writable. | | | |
942 | */ | | 905 | */ |
943 | | | | |
944 | pte[pl1_pi(page)] = 0; | | 906 | pte[pl1_pi(page)] = 0; |
945 | page += PAGE_SIZE; | | 907 | page += PAGE_SIZE; |
946 | continue; | | 908 | continue; |
947 | #endif /* i386 */ | | 909 | #endif |
948 | } else if (page >= (vaddr_t)&__data_start && | | 910 | } else if (page >= (vaddr_t)&__data_start && |
949 | page < (vaddr_t)&__kernel_end) { | | 911 | page < (vaddr_t)&__kernel_end) { |
950 | /* Map the kernel data+bss RW. */ | | 912 | /* Map the kernel data+bss RW. */ |
951 | pte[pl1_pi(page)] |= PG_RW | pg_nx; | | 913 | pte[pl1_pi(page)] |= PG_RW | pg_nx; |
952 | } else { | | 914 | } else { |
953 | /* Map the page RW. */ | | 915 | /* Map the page RW. */ |
954 | pte[pl1_pi(page)] |= PG_RW | pg_nx; | | 916 | pte[pl1_pi(page)] |= PG_RW | pg_nx; |
955 | } | | 917 | } |
956 | | | 918 | |
957 | if ((page >= old_pgd && page < old_pgd + (old_count * PAGE_SIZE)) | | | |
958 | || page >= new_pgd) { | | | |
959 | __PRINTK(("va %#lx pa %#lx " | | | |
960 | "entry 0x%" PRIxPADDR " -> L1[%#x]\n", | | | |
961 | page, page - KERNBASE, | | | |
962 | pte[pl1_pi(page)], pl1_pi(page))); | | | |
963 | } | | | |
964 | page += PAGE_SIZE; | | 919 | page += PAGE_SIZE; |
965 | } | | 920 | } |
966 | | | 921 | |
967 | addr = ((u_long) pte) - KERNBASE; | | 922 | addr = ((u_long)pte) - KERNBASE; |
968 | pde[pl2_pi(cur_page)] = | | 923 | pde[pl2_pi(cur_page)] = |
969 | xpmap_ptom_masked(addr) | PG_k | PG_RW | PG_V; | | 924 | xpmap_ptom_masked(addr) | PG_k | PG_RW | PG_V; |
970 | __PRINTK(("L1 va %#lx pa %#" PRIxPADDR " entry %#" PRIxPADDR | | 925 | |
971 | " -> L2[%#x]\n", | | | |
972 | pte, addr, pde[pl2_pi(cur_page)], pl2_pi(cur_page))); | | | |
973 | /* Mark readonly */ | | 926 | /* Mark readonly */ |
974 | xen_bt_set_readonly((vaddr_t) pte); | | 927 | xen_bt_set_readonly((vaddr_t)pte); |
975 | } | | 928 | } |
976 | | | 929 | |
977 | /* Install recursive page tables mapping */ | | 930 | /* Install recursive page tables mapping */ |
978 | #ifdef PAE | | 931 | #ifdef PAE |
979 | /* | | 932 | /* |
980 | * we need a shadow page for the kernel's L2 page | | 933 | * We need a shadow page for the kernel's L2 page. |
981 | * The real L2 kernel PD will be the last one (so that | | 934 | * The real L2 kernel PD will be the last one (so that |
982 | * pde[L2_SLOT_KERN] always point to the shadow. | | 935 | * pde[L2_SLOT_KERN] always points to the shadow). |
983 | */ | | 936 | */ |
984 | memcpy(&pde[L2_SLOT_KERN + NPDPG], &pde[L2_SLOT_KERN], PAGE_SIZE); | | 937 | memcpy(&pde[L2_SLOT_KERN + NPDPG], &pde[L2_SLOT_KERN], PAGE_SIZE); |
985 | cpu_info_primary.ci_kpm_pdir = &pde[L2_SLOT_KERN + NPDPG]; | | 938 | cpu_info_primary.ci_kpm_pdir = &pde[L2_SLOT_KERN + NPDPG]; |
986 | cpu_info_primary.ci_kpm_pdirpa = | | 939 | cpu_info_primary.ci_kpm_pdirpa = |
987 | (vaddr_t) cpu_info_primary.ci_kpm_pdir - KERNBASE; | | 940 | (vaddr_t) cpu_info_primary.ci_kpm_pdir - KERNBASE; |
988 | | | 941 | |
989 | /* | | 942 | /* |
990 | * We don't enter a recursive entry from the L3 PD. Instead, | | 943 | * We don't enter a recursive entry from the L3 PD. Instead, we enter |
991 | * we enter the first 4 L2 pages, which includes the kernel's L2 | | 944 | * the first 4 L2 pages, which includes the kernel's L2 shadow. But we |
992 | * shadow. But we have to entrer the shadow after switching | | 945 | * have to enter the shadow after switching %cr3, or Xen will refcount |
993 | * %cr3, or Xen will refcount some PTE with the wrong type. | | 946 | * some PTEs with the wrong type. |
994 | */ | | 947 | */ |
995 | addr = (u_long)pde - KERNBASE; | | 948 | addr = (u_long)pde - KERNBASE; |
996 | for (i = 0; i < 3; i++, addr += PAGE_SIZE) { | | 949 | for (i = 0; i < 3; i++, addr += PAGE_SIZE) { |
997 | pde[PDIR_SLOT_PTE + i] = xpmap_ptom_masked(addr) | PG_k | PG_V | | | 950 | pde[PDIR_SLOT_PTE + i] = xpmap_ptom_masked(addr) | PG_k | PG_V | |
998 | pg_nx; | | 951 | pg_nx; |
999 | __PRINTK(("pde[%d] va %#" PRIxVADDR " pa %#" PRIxPADDR | | 952 | __PRINTK(("pde[%d] va %#" PRIxVADDR " pa %#" PRIxPADDR |
1000 | " entry %#" PRIxPADDR "\n", | | 953 | " entry %#" PRIxPADDR "\n", |
1001 | (int)(PDIR_SLOT_PTE + i), pde + PAGE_SIZE * i, | | 954 | (int)(PDIR_SLOT_PTE + i), pde + PAGE_SIZE * i, |
1002 | addr, pde[PDIR_SLOT_PTE + i])); | | 955 | addr, pde[PDIR_SLOT_PTE + i])); |
1003 | } | | 956 | } |
1004 | #if 0 | | 957 | #if 0 |
1005 | addr += PAGE_SIZE; /* point to shadow L2 */ | | 958 | addr += PAGE_SIZE; /* point to shadow L2 */ |
1006 | pde[PDIR_SLOT_PTE + 3] = xpmap_ptom_masked(addr) | PG_k | PG_V; | | 959 | pde[PDIR_SLOT_PTE + 3] = xpmap_ptom_masked(addr) | PG_k | PG_V; |
1007 | __PRINTK(("pde[%d] va 0x%lx pa 0x%lx entry 0x%" PRIx64 "\n", | | 960 | __PRINTK(("pde[%d] va 0x%lx pa 0x%lx entry 0x%" PRIx64 "\n", |
1008 | (int)(PDIR_SLOT_PTE + 3), pde + PAGE_SIZE * 4, (long)addr, | | 961 | (int)(PDIR_SLOT_PTE + 3), pde + PAGE_SIZE * 4, (long)addr, |
1009 | (int64_t)pde[PDIR_SLOT_PTE + 3])); | | 962 | (int64_t)pde[PDIR_SLOT_PTE + 3])); |
1010 | #endif | | 963 | #endif |
1011 | /* Mark tables RO, and pin the kernel's shadow as L2 */ | | 964 | /* Mark tables RO, and pin the kernel's shadow as L2 */ |
1012 | addr = (u_long)pde - KERNBASE; | | 965 | addr = (u_long)pde - KERNBASE; |
1013 | for (i = 0; i < 5; i++, addr += PAGE_SIZE) { | | 966 | for (i = 0; i < 5; i++, addr += PAGE_SIZE) { |
1014 | xen_bt_set_readonly(((vaddr_t)pde) + PAGE_SIZE * i); | | 967 | xen_bt_set_readonly(((vaddr_t)pde) + PAGE_SIZE * i); |
| | | 968 | #if 0 |
1015 | if (i == 2 || i == 3) | | 969 | if (i == 2 || i == 3) |
1016 | continue; | | 970 | continue; |
1017 | #if 0 | | | |
1018 | __PRINTK(("pin L2 %d addr 0x%" PRIx64 "\n", i, (int64_t)addr)); | | 971 | __PRINTK(("pin L2 %d addr 0x%" PRIx64 "\n", i, (int64_t)addr)); |
1019 | xpq_queue_pin_l2_table(xpmap_ptom_masked(addr)); | | 972 | xpq_queue_pin_l2_table(xpmap_ptom_masked(addr)); |
1020 | #endif | | 973 | #endif |
1021 | } | | 974 | } |
1022 | if (final) { | | 975 | if (final) { |
1023 | addr = (u_long)pde - KERNBASE + 3 * PAGE_SIZE; | | 976 | addr = (u_long)pde - KERNBASE + 3 * PAGE_SIZE; |
1024 | __PRINTK(("pin L2 %d addr %#" PRIxPADDR "\n", 2, addr)); | | 977 | __PRINTK(("pin L2 %d addr %#" PRIxPADDR "\n", 2, addr)); |
1025 | xpq_queue_pin_l2_table(xpmap_ptom_masked(addr)); | | 978 | xpq_queue_pin_l2_table(xpmap_ptom_masked(addr)); |
1026 | } | | 979 | } |
1027 | #if 0 | | 980 | #if 0 |
1028 | addr = (u_long)pde - KERNBASE + 2 * PAGE_SIZE; | | 981 | addr = (u_long)pde - KERNBASE + 2 * PAGE_SIZE; |
1029 | __PRINTK(("pin L2 %d addr 0x%" PRIx64 "\n", 2, (int64_t)addr)); | | 982 | __PRINTK(("pin L2 %d addr 0x%" PRIx64 "\n", 2, (int64_t)addr)); |
1030 | xpq_queue_pin_l2_table(xpmap_ptom_masked(addr)); | | 983 | xpq_queue_pin_l2_table(xpmap_ptom_masked(addr)); |
| @@ -1034,30 +987,30 @@ xen_bootstrap_tables(vaddr_t old_pgd, va | | | @@ -1034,30 +987,30 @@ xen_bootstrap_tables(vaddr_t old_pgd, va |
1034 | /* Recursive entry in pmap_kernel(). */ | | 987 | /* Recursive entry in pmap_kernel(). */ |
1035 | bt_pgd[PDIR_SLOT_PTE] = xpmap_ptom_masked((paddr_t)bt_pgd - KERNBASE) | | 988 | bt_pgd[PDIR_SLOT_PTE] = xpmap_ptom_masked((paddr_t)bt_pgd - KERNBASE) |
1036 | | PG_k | PG_RO | PG_V | pg_nx; | | 989 | | PG_k | PG_RO | PG_V | pg_nx; |
1037 | #ifdef __x86_64__ | | 990 | #ifdef __x86_64__ |
1038 | /* Recursive entry in higher-level per-cpu PD. */ | | 991 | /* Recursive entry in higher-level per-cpu PD. */ |
1039 | bt_cpu_pgd[PDIR_SLOT_PTE] = xpmap_ptom_masked((paddr_t)bt_cpu_pgd - KERNBASE) | | 992 | bt_cpu_pgd[PDIR_SLOT_PTE] = xpmap_ptom_masked((paddr_t)bt_cpu_pgd - KERNBASE) |
1040 | | PG_k | PG_RO | PG_V | pg_nx; | | 993 | | PG_k | PG_RO | PG_V | pg_nx; |
1041 | #endif | | 994 | #endif |
1042 | __PRINTK(("bt_pgd[PDIR_SLOT_PTE] va %#" PRIxVADDR " pa %#" PRIxPADDR | | 995 | __PRINTK(("bt_pgd[PDIR_SLOT_PTE] va %#" PRIxVADDR " pa %#" PRIxPADDR |
1043 | " entry %#" PRIxPADDR "\n", new_pgd, (paddr_t)new_pgd - KERNBASE, | | 996 | " entry %#" PRIxPADDR "\n", new_pgd, (paddr_t)new_pgd - KERNBASE, |
1044 | bt_pgd[PDIR_SLOT_PTE])); | | 997 | bt_pgd[PDIR_SLOT_PTE])); |
1045 | | | 998 | |
1046 | /* Mark tables RO */ | | 999 | /* Mark tables RO */ |
1047 | xen_bt_set_readonly((vaddr_t) pde); | | 1000 | xen_bt_set_readonly((vaddr_t)pde); |
1048 | #endif | | 1001 | #endif |
1049 | #if PTP_LEVELS > 2 || defined(PAE) | | 1002 | #if PTP_LEVELS > 2 || defined(PAE) |
1050 | xen_bt_set_readonly((vaddr_t) pdtpe); | | 1003 | xen_bt_set_readonly((vaddr_t)pdtpe); |
1051 | #endif | | 1004 | #endif |
1052 | #if PTP_LEVELS > 3 | | 1005 | #if PTP_LEVELS > 3 |
1053 | xen_bt_set_readonly(new_pgd); | | 1006 | xen_bt_set_readonly(new_pgd); |
1054 | #endif | | 1007 | #endif |
1055 | | | 1008 | |
1056 | /* Pin the PGD */ | | 1009 | /* Pin the PGD */ |
1057 | __PRINTK(("pin PGD: %"PRIxVADDR"\n", new_pgd - KERNBASE)); | | 1010 | __PRINTK(("pin PGD: %"PRIxVADDR"\n", new_pgd - KERNBASE)); |
1058 | #ifdef __x86_64__ | | 1011 | #ifdef __x86_64__ |
1059 | xpq_queue_pin_l4_table(xpmap_ptom_masked(new_pgd - KERNBASE)); | | 1012 | xpq_queue_pin_l4_table(xpmap_ptom_masked(new_pgd - KERNBASE)); |
1060 | #elif PAE | | 1013 | #elif PAE |
1061 | xpq_queue_pin_l3_table(xpmap_ptom_masked(new_pgd - KERNBASE)); | | 1014 | xpq_queue_pin_l3_table(xpmap_ptom_masked(new_pgd - KERNBASE)); |
1062 | #else | | 1015 | #else |
1063 | xpq_queue_pin_l2_table(xpmap_ptom_masked(new_pgd - KERNBASE)); | | 1016 | xpq_queue_pin_l2_table(xpmap_ptom_masked(new_pgd - KERNBASE)); |
| @@ -1068,56 +1021,56 @@ xen_bootstrap_tables(vaddr_t old_pgd, va | | | @@ -1068,56 +1021,56 @@ xen_bootstrap_tables(vaddr_t old_pgd, va |
1068 | PDPpaddr = (u_long)pde - KERNBASE; /* PDP is the L2 with PAE */ | | 1021 | PDPpaddr = (u_long)pde - KERNBASE; /* PDP is the L2 with PAE */ |
1069 | #else | | 1022 | #else |
1070 | PDPpaddr = (u_long)bt_pgd - KERNBASE; | | 1023 | PDPpaddr = (u_long)bt_pgd - KERNBASE; |
1071 | #endif | | 1024 | #endif |
1072 | | | 1025 | |
1073 | /* Switch to new tables */ | | 1026 | /* Switch to new tables */ |
1074 | __PRINTK(("switch to PGD\n")); | | 1027 | __PRINTK(("switch to PGD\n")); |
1075 | xpq_queue_pt_switch(xpmap_ptom_masked(new_pgd - KERNBASE)); | | 1028 | xpq_queue_pt_switch(xpmap_ptom_masked(new_pgd - KERNBASE)); |
1076 | __PRINTK(("bt_pgd[PDIR_SLOT_PTE] now entry %#" PRIxPADDR "\n", | | 1029 | __PRINTK(("bt_pgd[PDIR_SLOT_PTE] now entry %#" PRIxPADDR "\n", |
1077 | bt_pgd[PDIR_SLOT_PTE])); | | 1030 | bt_pgd[PDIR_SLOT_PTE])); |
1078 | | | 1031 | |
1079 | #ifdef PAE | | 1032 | #ifdef PAE |
1080 | if (final) { | | 1033 | if (final) { |
1081 | /* save the address of the L3 page */ | | 1034 | /* Save the address of the L3 page */ |
1082 | cpu_info_primary.ci_pae_l3_pdir = pdtpe; | | 1035 | cpu_info_primary.ci_pae_l3_pdir = pdtpe; |
1083 | cpu_info_primary.ci_pae_l3_pdirpa = (new_pgd - KERNBASE); | | 1036 | cpu_info_primary.ci_pae_l3_pdirpa = (new_pgd - KERNBASE); |
1084 | | | 1037 | |
1085 | /* now enter kernel's PTE mappings */ | | 1038 | /* Now enter the kernel's PTE mappings */ |
1086 | addr = (u_long)pde - KERNBASE + PAGE_SIZE * 3; | | 1039 | addr = (u_long)pde - KERNBASE + PAGE_SIZE * 3; |
1087 | xpq_queue_pte_update( | | 1040 | xpq_queue_pte_update( |
1088 | xpmap_ptom(((vaddr_t)&pde[PDIR_SLOT_PTE + 3]) - KERNBASE), | | 1041 | xpmap_ptom(((vaddr_t)&pde[PDIR_SLOT_PTE + 3]) - KERNBASE), |
1089 | xpmap_ptom_masked(addr) | PG_k | PG_V); | | 1042 | xpmap_ptom_masked(addr) | PG_k | PG_V); |
1090 | xpq_flush_queue(); | | 1043 | xpq_flush_queue(); |
1091 | } | | 1044 | } |
1092 | #elif defined(__x86_64__) | | 1045 | #elif defined(__x86_64__) |
1093 | if (final) { | | 1046 | if (final) { |
1094 | /* save the address of the real per-cpu L4 pgd page */ | | 1047 | /* Save the address of the real per-cpu L4 pgd page */ |
1095 | cpu_info_primary.ci_kpm_pdir = bt_cpu_pgd; | | 1048 | cpu_info_primary.ci_kpm_pdir = bt_cpu_pgd; |
1096 | cpu_info_primary.ci_kpm_pdirpa = ((paddr_t) bt_cpu_pgd - KERNBASE); | | 1049 | cpu_info_primary.ci_kpm_pdirpa = ((paddr_t) bt_cpu_pgd - KERNBASE); |
1097 | } | | 1050 | } |
1098 | #endif | | 1051 | #endif |
1099 | __USE(pdtpe); | | 1052 | __USE(pdtpe); |
1100 | | | 1053 | |
1101 | /* Now we can safely reclaim space taken by old tables */ | | 1054 | /* Now we can safely reclaim space taken by old tables */ |
1102 | | | 1055 | |
1103 | __PRINTK(("unpin old PGD\n")); | | 1056 | __PRINTK(("unpin old PGD\n")); |
1104 | /* Unpin old PGD */ | | 1057 | /* Unpin old PGD */ |
1105 | xpq_queue_unpin_table(xpmap_ptom_masked(old_pgd - KERNBASE)); | | 1058 | xpq_queue_unpin_table(xpmap_ptom_masked(old_pgd - KERNBASE)); |
1106 | /* Mark old tables RW */ | | 1059 | /* Mark old tables RW */ |
1107 | page = old_pgd; | | 1060 | page = old_pgd; |
1108 | addr = (paddr_t) pde[pl2_pi(page)] & PG_FRAME; | | 1061 | addr = (paddr_t)pde[pl2_pi(page)] & PG_FRAME; |
1109 | addr = xpmap_mtop(addr); | | 1062 | addr = xpmap_mtop(addr); |
1110 | pte = (pd_entry_t *) ((u_long)addr + KERNBASE); | | 1063 | pte = (pd_entry_t *)((u_long)addr + KERNBASE); |
1111 | pte += pl1_pi(page); | | 1064 | pte += pl1_pi(page); |
1112 | __PRINTK(("*pde %#" PRIxPADDR " addr %#" PRIxPADDR " pte %#lx\n", | | 1065 | __PRINTK(("*pde %#" PRIxPADDR " addr %#" PRIxPADDR " pte %#lx\n", |
1113 | pde[pl2_pi(page)], addr, (long)pte)); | | 1066 | pde[pl2_pi(page)], addr, (long)pte)); |
1114 | while (page < old_pgd + (old_count * PAGE_SIZE) && page < map_end) { | | 1067 | while (page < old_pgd + (old_count * PAGE_SIZE) && page < map_end) { |
1115 | addr = xpmap_ptom(((u_long) pte) - KERNBASE); | | 1068 | addr = xpmap_ptom(((u_long) pte) - KERNBASE); |
1116 | XENPRINTK(("addr %#" PRIxPADDR " pte %#lx " | | 1069 | XENPRINTK(("addr %#" PRIxPADDR " pte %#lx " |
1117 | "*pte %#" PRIxPADDR "\n", | | 1070 | "*pte %#" PRIxPADDR "\n", |
1118 | addr, (long)pte, *pte)); | | 1071 | addr, (long)pte, *pte)); |
1119 | xpq_queue_pte_update(addr, *pte | PG_RW); | | 1072 | xpq_queue_pte_update(addr, *pte | PG_RW); |
1120 | page += PAGE_SIZE; | | 1073 | page += PAGE_SIZE; |
1121 | /* | | 1074 | /* |
1122 | * Our PTEs are contiguous so it's safe to just "++" here. | | 1075 | * Our PTEs are contiguous so it's safe to just "++" here. |
1123 | */ | | 1076 | */ |
| @@ -1127,39 +1080,39 @@ xen_bootstrap_tables(vaddr_t old_pgd, va | | | @@ -1127,39 +1080,39 @@ xen_bootstrap_tables(vaddr_t old_pgd, va |
1127 | } | | 1080 | } |
1128 | | | 1081 | |
1129 | | | 1082 | |
1130 | /* | | 1083 | /* |
1131 | * Bootstrap helper functions | | 1084 | * Bootstrap helper functions |
1132 | */ | | 1085 | */ |
1133 | | | 1086 | |
1134 | /* | | 1087 | /* |
1135 | * Mark a page readonly | | 1088 | * Mark a page readonly |
1136 | * XXX: assuming vaddr = paddr + KERNBASE | | 1089 | * XXX: assuming vaddr = paddr + KERNBASE |
1137 | */ | | 1090 | */ |
1138 | | | 1091 | |
1139 | static void | | 1092 | static void |
1140 | xen_bt_set_readonly (vaddr_t page) | | 1093 | xen_bt_set_readonly(vaddr_t page) |
1141 | { | | 1094 | { |
1142 | pt_entry_t entry; | | 1095 | pt_entry_t entry; |
1143 | | | 1096 | |
1144 | entry = xpmap_ptom_masked(page - KERNBASE); | | 1097 | entry = xpmap_ptom_masked(page - KERNBASE); |
1145 | entry |= PG_k | PG_V; | | 1098 | entry |= PG_k | PG_V; |
1146 | | | 1099 | |
1147 | HYPERVISOR_update_va_mapping (page, entry, UVMF_INVLPG); | | 1100 | HYPERVISOR_update_va_mapping(page, entry, UVMF_INVLPG); |
1148 | } | | 1101 | } |
1149 | | | 1102 | |
1150 | #ifdef __x86_64__ | | 1103 | #ifdef __x86_64__ |
1151 | void | | 1104 | void |
1152 | xen_set_user_pgd(paddr_t page) | | 1105 | xen_set_user_pgd(paddr_t page) |
1153 | { | | 1106 | { |
1154 | struct mmuext_op op; | | 1107 | struct mmuext_op op; |
1155 | int s = splvm(); | | 1108 | int s = splvm(); |
1156 | | | 1109 | |
1157 | xpq_flush_queue(); | | 1110 | xpq_flush_queue(); |
1158 | op.cmd = MMUEXT_NEW_USER_BASEPTR; | | 1111 | op.cmd = MMUEXT_NEW_USER_BASEPTR; |
1159 | op.arg1.mfn = xpmap_ptom_masked(page) >> PAGE_SHIFT; | | 1112 | op.arg1.mfn = xpmap_ptom_masked(page) >> PAGE_SHIFT; |
1160 | if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) | | 1113 | if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) |
1161 | panic("xen_set_user_pgd: failed to install new user page" | | 1114 | panic("xen_set_user_pgd: failed to install new user page" |
1162 | " directory %#" PRIxPADDR, page); | | 1115 | " directory %#" PRIxPADDR, page); |
1163 | splx(s); | | 1116 | splx(s); |
1164 | } | | 1117 | } |
1165 | #endif /* __x86_64__ */ | | 1118 | #endif /* __x86_64__ */ |