diff options
| author | Xiao Guangrong <xiaoguangrong@cn.fujitsu.com> | 2011-07-11 15:28:04 -0400 |
|---|---|---|
| committer | Avi Kivity <avi@redhat.com> | 2011-07-24 04:50:33 -0400 |
| commit | c37079586f317d7e7f1a70d36f0e5177691c89c2 (patch) | |
| tree | 264c51d567d0a4bcb572f0c968096683d5913a84 | |
| parent | bd4c86eaa6ff10abc4e00d0f45d2a28b10b09df4 (diff) | |
KVM: MMU: remove bypass_guest_pf
The idea is from Avi:
| Maybe it's time to kill off bypass_guest_pf=1. It's not as effective as
| it used to be, since unsync pages always use shadow_trap_nonpresent_pte,
| and since we convert between the two nonpresent_ptes during sync and unsync.
Signed-off-by: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
| -rw-r--r-- | Documentation/kernel-parameters.txt | 4 | ||||
| -rw-r--r-- | arch/x86/include/asm/kvm_host.h | 3 | ||||
| -rw-r--r-- | arch/x86/kvm/mmu.c | 83 | ||||
| -rw-r--r-- | arch/x86/kvm/mmu_audit.c | 12 | ||||
| -rw-r--r-- | arch/x86/kvm/paging_tmpl.h | 51 | ||||
| -rw-r--r-- | arch/x86/kvm/vmx.c | 11 | ||||
| -rw-r--r-- | arch/x86/kvm/x86.c | 1 |
7 files changed, 33 insertions, 132 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index a7225746ed96..1810a6b51bab 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
| @@ -1159,10 +1159,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
| 1159 | for all guests. | 1159 | for all guests. |
| 1160 | Default is 1 (enabled) if in 64bit or 32bit-PAE mode | 1160 | Default is 1 (enabled) if in 64bit or 32bit-PAE mode |
| 1161 | 1161 | ||
| 1162 | kvm-intel.bypass_guest_pf= | ||
| 1163 | [KVM,Intel] Disables bypassing of guest page faults | ||
| 1164 | on Intel chips. Default is 1 (enabled) | ||
| 1165 | |||
| 1166 | kvm-intel.ept= [KVM,Intel] Disable extended page tables | 1162 | kvm-intel.ept= [KVM,Intel] Disable extended page tables |
| 1167 | (virtualized MMU) support on capable Intel chips. | 1163 | (virtualized MMU) support on capable Intel chips. |
| 1168 | Default is 1 (enabled) | 1164 | Default is 1 (enabled) |
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 8da1400ab581..a198a5b2f04e 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h | |||
| @@ -266,8 +266,6 @@ struct kvm_mmu { | |||
| 266 | gpa_t (*gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t gva, u32 access, | 266 | gpa_t (*gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t gva, u32 access, |
| 267 | struct x86_exception *exception); | 267 | struct x86_exception *exception); |
| 268 | gpa_t (*translate_gpa)(struct kvm_vcpu *vcpu, gpa_t gpa, u32 access); | 268 | gpa_t (*translate_gpa)(struct kvm_vcpu *vcpu, gpa_t gpa, u32 access); |
| 269 | void (*prefetch_page)(struct kvm_vcpu *vcpu, | ||
| 270 | struct kvm_mmu_page *page); | ||
| 271 | int (*sync_page)(struct kvm_vcpu *vcpu, | 269 | int (*sync_page)(struct kvm_vcpu *vcpu, |
| 272 | struct kvm_mmu_page *sp); | 270 | struct kvm_mmu_page *sp); |
| 273 | void (*invlpg)(struct kvm_vcpu *vcpu, gva_t gva); | 271 | void (*invlpg)(struct kvm_vcpu *vcpu, gva_t gva); |
| @@ -647,7 +645,6 @@ void kvm_mmu_module_exit(void); | |||
| 647 | void kvm_mmu_destroy(struct kvm_vcpu *vcpu); | 645 | void kvm_mmu_destroy(struct kvm_vcpu *vcpu); |
| 648 | int kvm_mmu_create(struct kvm_vcpu *vcpu); | 646 | int kvm_mmu_create(struct kvm_vcpu *vcpu); |
| 649 | int kvm_mmu_setup(struct kvm_vcpu *vcpu); | 647 | int kvm_mmu_setup(struct kvm_vcpu *vcpu); |
| 650 | void kvm_mmu_set_nonpresent_ptes(u64 trap_pte, u64 notrap_pte); | ||
| 651 | void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask, | 648 | void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask, |
| 652 | u64 dirty_mask, u64 nx_mask, u64 x_mask); | 649 | u64 dirty_mask, u64 nx_mask, u64 x_mask); |
| 653 | 650 | ||
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 2f8543c65fa3..5334b4e9ecc7 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c | |||
| @@ -186,8 +186,6 @@ static struct kmem_cache *pte_list_desc_cache; | |||
| 186 | static struct kmem_cache *mmu_page_header_cache; | 186 | static struct kmem_cache *mmu_page_header_cache; |
| 187 | static struct percpu_counter kvm_total_used_mmu_pages; | 187 | static struct percpu_counter kvm_total_used_mmu_pages; |
| 188 | 188 | ||
| 189 | static u64 __read_mostly shadow_trap_nonpresent_pte; | ||
| 190 | static u64 __read_mostly shadow_notrap_nonpresent_pte; | ||
| 191 | static u64 __read_mostly shadow_nx_mask; | 189 | static u64 __read_mostly shadow_nx_mask; |
| 192 | static u64 __read_mostly shadow_x_mask; /* mutual exclusive with nx_mask */ | 190 | static u64 __read_mostly shadow_x_mask; /* mutual exclusive with nx_mask */ |
| 193 | static u64 __read_mostly shadow_user_mask; | 191 | static u64 __read_mostly shadow_user_mask; |
| @@ -199,13 +197,6 @@ static inline u64 rsvd_bits(int s, int e) | |||
| 199 | return ((1ULL << (e - s + 1)) - 1) << s; | 197 | return ((1ULL << (e - s + 1)) - 1) << s; |
| 200 | } | 198 | } |
| 201 | 199 | ||
| 202 | void kvm_mmu_set_nonpresent_ptes(u64 trap_pte, u64 notrap_pte) | ||
| 203 | { | ||
| 204 | shadow_trap_nonpresent_pte = trap_pte; | ||
| 205 | shadow_notrap_nonpresent_pte = notrap_pte; | ||
| 206 | } | ||
| 207 | EXPORT_SYMBOL_GPL(kvm_mmu_set_nonpresent_ptes); | ||
| 208 | |||
| 209 | void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask, | 200 | void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask, |
| 210 | u64 dirty_mask, u64 nx_mask, u64 x_mask) | 201 | u64 dirty_mask, u64 nx_mask, u64 x_mask) |
| 211 | { | 202 | { |
| @@ -229,8 +220,7 @@ static int is_nx(struct kvm_vcpu *vcpu) | |||
| 229 | 220 | ||
| 230 | static int is_shadow_present_pte(u64 pte) | 221 | static int is_shadow_present_pte(u64 pte) |
| 231 | { | 222 | { |
| 232 | return pte != shadow_trap_nonpresent_pte | 223 | return pte & PT_PRESENT_MASK; |
| 233 | && pte != shadow_notrap_nonpresent_pte; | ||
| 234 | } | 224 | } |
| 235 | 225 | ||
| 236 | static int is_large_pte(u64 pte) | 226 | static int is_large_pte(u64 pte) |
| @@ -777,9 +767,9 @@ static int set_spte_track_bits(u64 *sptep, u64 new_spte) | |||
| 777 | return 1; | 767 | return 1; |
| 778 | } | 768 | } |
| 779 | 769 | ||
| 780 | static void drop_spte(struct kvm *kvm, u64 *sptep, u64 new_spte) | 770 | static void drop_spte(struct kvm *kvm, u64 *sptep) |
| 781 | { | 771 | { |
| 782 | if (set_spte_track_bits(sptep, new_spte)) | 772 | if (set_spte_track_bits(sptep, 0ull)) |
| 783 | rmap_remove(kvm, sptep); | 773 | rmap_remove(kvm, sptep); |
| 784 | } | 774 | } |
| 785 | 775 | ||
| @@ -814,8 +804,7 @@ static int rmap_write_protect(struct kvm *kvm, u64 gfn) | |||
| 814 | BUG_ON((*spte & (PT_PAGE_SIZE_MASK|PT_PRESENT_MASK)) != (PT_PAGE_SIZE_MASK|PT_PRESENT_MASK)); | 804 | BUG_ON((*spte & (PT_PAGE_SIZE_MASK|PT_PRESENT_MASK)) != (PT_PAGE_SIZE_MASK|PT_PRESENT_MASK)); |
| 815 | pgprintk("rmap_write_protect(large): spte %p %llx %lld\n", spte, *spte, gfn); | 805 | pgprintk("rmap_write_protect(large): spte %p %llx %lld\n", spte, *spte, gfn); |
| 816 | if (is_writable_pte(*spte)) { | 806 | if (is_writable_pte(*spte)) { |
| 817 | drop_spte(kvm, spte, | 807 | drop_spte(kvm, spte); |
| 818 | shadow_trap_nonpresent_pte); | ||
| 819 | --kvm->stat.lpages; | 808 | --kvm->stat.lpages; |
| 820 | spte = NULL; | 809 | spte = NULL; |
| 821 | write_protected = 1; | 810 | write_protected = 1; |
| @@ -836,7 +825,7 @@ static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp, | |||
| 836 | while ((spte = rmap_next(kvm, rmapp, NULL))) { | 825 | while ((spte = rmap_next(kvm, rmapp, NULL))) { |
| 837 | BUG_ON(!(*spte & PT_PRESENT_MASK)); | 826 | BUG_ON(!(*spte & PT_PRESENT_MASK)); |
| 838 | rmap_printk("kvm_rmap_unmap_hva: spte %p %llx\n", spte, *spte); | 827 | rmap_printk("kvm_rmap_unmap_hva: spte %p %llx\n", spte, *spte); |
| 839 | drop_spte(kvm, spte, shadow_trap_nonpresent_pte); | 828 | drop_spte(kvm, spte); |
| 840 | need_tlb_flush = 1; | 829 | need_tlb_flush = 1; |
| 841 | } | 830 | } |
| 842 | return need_tlb_flush; | 831 | return need_tlb_flush; |
| @@ -858,7 +847,7 @@ static int kvm_set_pte_rmapp(struct kvm *kvm, unsigned long *rmapp, | |||
| 858 | rmap_printk("kvm_set_pte_rmapp: spte %p %llx\n", spte, *spte); | 847 | rmap_printk("kvm_set_pte_rmapp: spte %p %llx\n", spte, *spte); |
| 859 | need_flush = 1; | 848 | need_flush = 1; |
| 860 | if (pte_write(*ptep)) { | 849 | if (pte_write(*ptep)) { |
| 861 | drop_spte(kvm, spte, shadow_trap_nonpresent_pte); | 850 | drop_spte(kvm, spte); |
| 862 | spte = rmap_next(kvm, rmapp, NULL); | 851 | spte = rmap_next(kvm, rmapp, NULL); |
| 863 | } else { | 852 | } else { |
| 864 | new_spte = *spte &~ (PT64_BASE_ADDR_MASK); | 853 | new_spte = *spte &~ (PT64_BASE_ADDR_MASK); |
| @@ -1088,7 +1077,7 @@ static void drop_parent_pte(struct kvm_mmu_page *sp, | |||
| 1088 | u64 *parent_pte) | 1077 | u64 *parent_pte) |
| 1089 | { | 1078 | { |
| 1090 | mmu_page_remove_parent_pte(sp, parent_pte); | 1079 | mmu_page_remove_parent_pte(sp, parent_pte); |
| 1091 | __set_spte(parent_pte, shadow_trap_nonpresent_pte); | 1080 | __set_spte(parent_pte, 0ull); |
| 1092 | } | 1081 | } |
| 1093 | 1082 | ||
| 1094 | static struct kvm_mmu_page *kvm_mmu_alloc_page(struct kvm_vcpu *vcpu, | 1083 | static struct kvm_mmu_page *kvm_mmu_alloc_page(struct kvm_vcpu *vcpu, |
| @@ -1130,15 +1119,6 @@ static void mark_unsync(u64 *spte) | |||
| 1130 | kvm_mmu_mark_parents_unsync(sp); | 1119 | kvm_mmu_mark_parents_unsync(sp); |
| 1131 | } | 1120 | } |
| 1132 | 1121 | ||
| 1133 | static void nonpaging_prefetch_page(struct kvm_vcpu *vcpu, | ||
| 1134 | struct kvm_mmu_page *sp) | ||
| 1135 | { | ||
| 1136 | int i; | ||
| 1137 | |||
| 1138 | for (i = 0; i < PT64_ENT_PER_PAGE; ++i) | ||
| 1139 | sp->spt[i] = shadow_trap_nonpresent_pte; | ||
| 1140 | } | ||
| 1141 | |||
| 1142 | static int nonpaging_sync_page(struct kvm_vcpu *vcpu, | 1122 | static int nonpaging_sync_page(struct kvm_vcpu *vcpu, |
| 1143 | struct kvm_mmu_page *sp) | 1123 | struct kvm_mmu_page *sp) |
| 1144 | { | 1124 | { |
| @@ -1420,6 +1400,14 @@ static void mmu_sync_children(struct kvm_vcpu *vcpu, | |||
| 1420 | } | 1400 | } |
| 1421 | } | 1401 | } |
| 1422 | 1402 | ||
| 1403 | static void init_shadow_page_table(struct kvm_mmu_page *sp) | ||
| 1404 | { | ||
| 1405 | int i; | ||
| 1406 | |||
| 1407 | for (i = 0; i < PT64_ENT_PER_PAGE; ++i) | ||
| 1408 | sp->spt[i] = 0ull; | ||
| 1409 | } | ||
| 1410 | |||
| 1423 | static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, | 1411 | static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, |
| 1424 | gfn_t gfn, | 1412 | gfn_t gfn, |
| 1425 | gva_t gaddr, | 1413 | gva_t gaddr, |
| @@ -1482,10 +1470,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, | |||
| 1482 | 1470 | ||
| 1483 | account_shadowed(vcpu->kvm, gfn); | 1471 | account_shadowed(vcpu->kvm, gfn); |
| 1484 | } | 1472 | } |
| 1485 | if (shadow_trap_nonpresent_pte != shadow_notrap_nonpresent_pte) | 1473 | init_shadow_page_table(sp); |
| 1486 | vcpu->arch.mmu.prefetch_page(vcpu, sp); | ||
| 1487 | else | ||
| 1488 | nonpaging_prefetch_page(vcpu, sp); | ||
| 1489 | trace_kvm_mmu_get_page(sp, true); | 1474 | trace_kvm_mmu_get_page(sp, true); |
| 1490 | return sp; | 1475 | return sp; |
| 1491 | } | 1476 | } |
| @@ -1546,7 +1531,7 @@ static void link_shadow_page(u64 *sptep, struct kvm_mmu_page *sp) | |||
| 1546 | static void drop_large_spte(struct kvm_vcpu *vcpu, u64 *sptep) | 1531 | static void drop_large_spte(struct kvm_vcpu *vcpu, u64 *sptep) |
| 1547 | { | 1532 | { |
| 1548 | if (is_large_pte(*sptep)) { | 1533 | if (is_large_pte(*sptep)) { |
| 1549 | drop_spte(vcpu->kvm, sptep, shadow_trap_nonpresent_pte); | 1534 | drop_spte(vcpu->kvm, sptep); |
| 1550 | kvm_flush_remote_tlbs(vcpu->kvm); | 1535 | kvm_flush_remote_tlbs(vcpu->kvm); |
| 1551 | } | 1536 | } |
| 1552 | } | 1537 | } |
| @@ -1582,13 +1567,13 @@ static void mmu_page_zap_pte(struct kvm *kvm, struct kvm_mmu_page *sp, | |||
| 1582 | pte = *spte; | 1567 | pte = *spte; |
| 1583 | if (is_shadow_present_pte(pte)) { | 1568 | if (is_shadow_present_pte(pte)) { |
| 1584 | if (is_last_spte(pte, sp->role.level)) | 1569 | if (is_last_spte(pte, sp->role.level)) |
| 1585 | drop_spte(kvm, spte, shadow_trap_nonpresent_pte); | 1570 | drop_spte(kvm, spte); |
| 1586 | else { | 1571 | else { |
| 1587 | child = page_header(pte & PT64_BASE_ADDR_MASK); | 1572 | child = page_header(pte & PT64_BASE_ADDR_MASK); |
| 1588 | drop_parent_pte(child, spte); | 1573 | drop_parent_pte(child, spte); |
| 1589 | } | 1574 | } |
| 1590 | } | 1575 | } |
| 1591 | __set_spte(spte, shadow_trap_nonpresent_pte); | 1576 | |
| 1592 | if (is_large_pte(pte)) | 1577 | if (is_large_pte(pte)) |
| 1593 | --kvm->stat.lpages; | 1578 | --kvm->stat.lpages; |
| 1594 | } | 1579 | } |
| @@ -1769,20 +1754,6 @@ static void page_header_update_slot(struct kvm *kvm, void *pte, gfn_t gfn) | |||
| 1769 | __set_bit(slot, sp->slot_bitmap); | 1754 | __set_bit(slot, sp->slot_bitmap); |
| 1770 | } | 1755 | } |
| 1771 | 1756 | ||
| 1772 | static void mmu_convert_notrap(struct kvm_mmu_page *sp) | ||
| 1773 | { | ||
| 1774 | int i; | ||
| 1775 | u64 *pt = sp->spt; | ||
| 1776 | |||
| 1777 | if (shadow_trap_nonpresent_pte == shadow_notrap_nonpresent_pte) | ||
| 1778 | return; | ||
| 1779 | |||
| 1780 | for (i = 0; i < PT64_ENT_PER_PAGE; ++i) { | ||
| 1781 | if (pt[i] == shadow_notrap_nonpresent_pte) | ||
| 1782 | __set_spte(&pt[i], shadow_trap_nonpresent_pte); | ||
| 1783 | } | ||
| 1784 | } | ||
| 1785 | |||
| 1786 | /* | 1757 | /* |
| 1787 | * The function is based on mtrr_type_lookup() in | 1758 | * The function is based on mtrr_type_lookup() in |
| 1788 | * arch/x86/kernel/cpu/mtrr/generic.c | 1759 | * arch/x86/kernel/cpu/mtrr/generic.c |
| @@ -1895,7 +1866,6 @@ static void __kvm_unsync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) | |||
| 1895 | sp->unsync = 1; | 1866 | sp->unsync = 1; |
| 1896 | 1867 | ||
| 1897 | kvm_mmu_mark_parents_unsync(sp); | 1868 | kvm_mmu_mark_parents_unsync(sp); |
| 1898 | mmu_convert_notrap(sp); | ||
| 1899 | } | 1869 | } |
| 1900 | 1870 | ||
| 1901 | static void kvm_unsync_pages(struct kvm_vcpu *vcpu, gfn_t gfn) | 1871 | static void kvm_unsync_pages(struct kvm_vcpu *vcpu, gfn_t gfn) |
| @@ -1980,7 +1950,7 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep, | |||
| 1980 | if (level > PT_PAGE_TABLE_LEVEL && | 1950 | if (level > PT_PAGE_TABLE_LEVEL && |
| 1981 | has_wrprotected_page(vcpu->kvm, gfn, level)) { | 1951 | has_wrprotected_page(vcpu->kvm, gfn, level)) { |
| 1982 | ret = 1; | 1952 | ret = 1; |
| 1983 | drop_spte(vcpu->kvm, sptep, shadow_trap_nonpresent_pte); | 1953 | drop_spte(vcpu->kvm, sptep); |
| 1984 | goto done; | 1954 | goto done; |
| 1985 | } | 1955 | } |
| 1986 | 1956 | ||
| @@ -2066,7 +2036,7 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep, | |||
| 2066 | } else if (pfn != spte_to_pfn(*sptep)) { | 2036 | } else if (pfn != spte_to_pfn(*sptep)) { |
| 2067 | pgprintk("hfn old %llx new %llx\n", | 2037 | pgprintk("hfn old %llx new %llx\n", |
| 2068 | spte_to_pfn(*sptep), pfn); | 2038 | spte_to_pfn(*sptep), pfn); |
| 2069 | drop_spte(vcpu->kvm, sptep, shadow_trap_nonpresent_pte); | 2039 | drop_spte(vcpu->kvm, sptep); |
| 2070 | kvm_flush_remote_tlbs(vcpu->kvm); | 2040 | kvm_flush_remote_tlbs(vcpu->kvm); |
| 2071 | } else | 2041 | } else |
| 2072 | was_rmapped = 1; | 2042 | was_rmapped = 1; |
| @@ -2162,7 +2132,7 @@ static void __direct_pte_prefetch(struct kvm_vcpu *vcpu, | |||
| 2162 | spte = sp->spt + i; | 2132 | spte = sp->spt + i; |
| 2163 | 2133 | ||
| 2164 | for (i = 0; i < PTE_PREFETCH_NUM; i++, spte++) { | 2134 | for (i = 0; i < PTE_PREFETCH_NUM; i++, spte++) { |
| 2165 | if (*spte != shadow_trap_nonpresent_pte || spte == sptep) { | 2135 | if (is_shadow_present_pte(*spte) || spte == sptep) { |
| 2166 | if (!start) | 2136 | if (!start) |
| 2167 | continue; | 2137 | continue; |
| 2168 | if (direct_pte_prefetch_many(vcpu, sp, start, spte) < 0) | 2138 | if (direct_pte_prefetch_many(vcpu, sp, start, spte) < 0) |
| @@ -2214,7 +2184,7 @@ static int __direct_map(struct kvm_vcpu *vcpu, gpa_t v, int write, | |||
| 2214 | break; | 2184 | break; |
| 2215 | } | 2185 | } |
| 2216 | 2186 | ||
| 2217 | if (*iterator.sptep == shadow_trap_nonpresent_pte) { | 2187 | if (!is_shadow_present_pte(*iterator.sptep)) { |
| 2218 | u64 base_addr = iterator.addr; | 2188 | u64 base_addr = iterator.addr; |
| 2219 | 2189 | ||
| 2220 | base_addr &= PT64_LVL_ADDR_MASK(iterator.level); | 2190 | base_addr &= PT64_LVL_ADDR_MASK(iterator.level); |
| @@ -2748,7 +2718,6 @@ static int nonpaging_init_context(struct kvm_vcpu *vcpu, | |||
| 2748 | context->page_fault = nonpaging_page_fault; | 2718 | context->page_fault = nonpaging_page_fault; |
| 2749 | context->gva_to_gpa = nonpaging_gva_to_gpa; | 2719 | context->gva_to_gpa = nonpaging_gva_to_gpa; |
| 2750 | context->free = nonpaging_free; | 2720 | context->free = nonpaging_free; |
| 2751 | context->prefetch_page = nonpaging_prefetch_page; | ||
| 2752 | context->sync_page = nonpaging_sync_page; | 2721 | context->sync_page = nonpaging_sync_page; |
| 2753 | context->invlpg = nonpaging_invlpg; | 2722 | context->invlpg = nonpaging_invlpg; |
| 2754 | context->update_pte = nonpaging_update_pte; | 2723 | context->update_pte = nonpaging_update_pte; |
| @@ -2878,7 +2847,6 @@ static int paging64_init_context_common(struct kvm_vcpu *vcpu, | |||
| 2878 | context->new_cr3 = paging_new_cr3; | 2847 | context->new_cr3 = paging_new_cr3; |
| 2879 | context->page_fault = paging64_page_fault; | 2848 | context->page_fault = paging64_page_fault; |
| 2880 | context->gva_to_gpa = paging64_gva_to_gpa; | 2849 | context->gva_to_gpa = paging64_gva_to_gpa; |
| 2881 | context->prefetch_page = paging64_prefetch_page; | ||
| 2882 | context->sync_page = paging64_sync_page; | 2850 | context->sync_page = paging64_sync_page; |
| 2883 | context->invlpg = paging64_invlpg; | 2851 | context->invlpg = paging64_invlpg; |
| 2884 | context->update_pte = paging64_update_pte; | 2852 | context->update_pte = paging64_update_pte; |
| @@ -2907,7 +2875,6 @@ static int paging32_init_context(struct kvm_vcpu *vcpu, | |||
| 2907 | context->page_fault = paging32_page_fault; | 2875 | context->page_fault = paging32_page_fault; |
| 2908 | context->gva_to_gpa = paging32_gva_to_gpa; | 2876 | context->gva_to_gpa = paging32_gva_to_gpa; |
| 2909 | context->free = paging_free; | 2877 | context->free = paging_free; |
| 2910 | context->prefetch_page = paging32_prefetch_page; | ||
| 2911 | context->sync_page = paging32_sync_page; | 2878 | context->sync_page = paging32_sync_page; |
| 2912 | context->invlpg = paging32_invlpg; | 2879 | context->invlpg = paging32_invlpg; |
| 2913 | context->update_pte = paging32_update_pte; | 2880 | context->update_pte = paging32_update_pte; |
| @@ -2932,7 +2899,6 @@ static int init_kvm_tdp_mmu(struct kvm_vcpu *vcpu) | |||
| 2932 | context->new_cr3 = nonpaging_new_cr3; | 2899 | context->new_cr3 = nonpaging_new_cr3; |
| 2933 | context->page_fault = tdp_page_fault; | 2900 | context->page_fault = tdp_page_fault; |
| 2934 | context->free = nonpaging_free; | 2901 | context->free = nonpaging_free; |
| 2935 | context->prefetch_page = nonpaging_prefetch_page; | ||
| 2936 | context->sync_page = nonpaging_sync_page; | 2902 | context->sync_page = nonpaging_sync_page; |
| 2937 | context->invlpg = nonpaging_invlpg; | 2903 | context->invlpg = nonpaging_invlpg; |
| 2938 | context->update_pte = nonpaging_update_pte; | 2904 | context->update_pte = nonpaging_update_pte; |
| @@ -3443,8 +3409,7 @@ void kvm_mmu_slot_remove_write_access(struct kvm *kvm, int slot) | |||
| 3443 | continue; | 3409 | continue; |
| 3444 | 3410 | ||
| 3445 | if (is_large_pte(pt[i])) { | 3411 | if (is_large_pte(pt[i])) { |
| 3446 | drop_spte(kvm, &pt[i], | 3412 | drop_spte(kvm, &pt[i]); |
| 3447 | shadow_trap_nonpresent_pte); | ||
| 3448 | --kvm->stat.lpages; | 3413 | --kvm->stat.lpages; |
| 3449 | continue; | 3414 | continue; |
| 3450 | } | 3415 | } |
diff --git a/arch/x86/kvm/mmu_audit.c b/arch/x86/kvm/mmu_audit.c index 5f6223b8bcf7..2460a265be23 100644 --- a/arch/x86/kvm/mmu_audit.c +++ b/arch/x86/kvm/mmu_audit.c | |||
| @@ -99,18 +99,6 @@ static void audit_mappings(struct kvm_vcpu *vcpu, u64 *sptep, int level) | |||
| 99 | "level = %d\n", sp, level); | 99 | "level = %d\n", sp, level); |
| 100 | return; | 100 | return; |
| 101 | } | 101 | } |
| 102 | |||
| 103 | if (*sptep == shadow_notrap_nonpresent_pte) { | ||
| 104 | audit_printk(vcpu->kvm, "notrap spte in unsync " | ||
| 105 | "sp: %p\n", sp); | ||
| 106 | return; | ||
| 107 | } | ||
| 108 | } | ||
| 109 | |||
| 110 | if (sp->role.direct && *sptep == shadow_notrap_nonpresent_pte) { | ||
| 111 | audit_printk(vcpu->kvm, "notrap spte in direct sp: %p\n", | ||
| 112 | sp); | ||
| 113 | return; | ||
| 114 | } | 102 | } |
| 115 | 103 | ||
| 116 | if (!is_shadow_present_pte(*sptep) || !is_last_spte(*sptep, level)) | 104 | if (!is_shadow_present_pte(*sptep) || !is_last_spte(*sptep, level)) |
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h index fa3b54bbce6b..a4565df501cd 100644 --- a/arch/x86/kvm/paging_tmpl.h +++ b/arch/x86/kvm/paging_tmpl.h | |||
| @@ -337,16 +337,11 @@ static bool FNAME(prefetch_invalid_gpte)(struct kvm_vcpu *vcpu, | |||
| 337 | struct kvm_mmu_page *sp, u64 *spte, | 337 | struct kvm_mmu_page *sp, u64 *spte, |
| 338 | pt_element_t gpte) | 338 | pt_element_t gpte) |
| 339 | { | 339 | { |
| 340 | u64 nonpresent = shadow_trap_nonpresent_pte; | ||
| 341 | |||
| 342 | if (is_rsvd_bits_set(&vcpu->arch.mmu, gpte, PT_PAGE_TABLE_LEVEL)) | 340 | if (is_rsvd_bits_set(&vcpu->arch.mmu, gpte, PT_PAGE_TABLE_LEVEL)) |
| 343 | goto no_present; | 341 | goto no_present; |
| 344 | 342 | ||
| 345 | if (!is_present_gpte(gpte)) { | 343 | if (!is_present_gpte(gpte)) |
| 346 | if (!sp->unsync) | ||
| 347 | nonpresent = shadow_notrap_nonpresent_pte; | ||
| 348 | goto no_present; | 344 | goto no_present; |
| 349 | } | ||
| 350 | 345 | ||
| 351 | if (!(gpte & PT_ACCESSED_MASK)) | 346 | if (!(gpte & PT_ACCESSED_MASK)) |
| 352 | goto no_present; | 347 | goto no_present; |
| @@ -354,7 +349,7 @@ static bool FNAME(prefetch_invalid_gpte)(struct kvm_vcpu *vcpu, | |||
| 354 | return false; | 349 | return false; |
| 355 | 350 | ||
| 356 | no_present: | 351 | no_present: |
| 357 | drop_spte(vcpu->kvm, spte, nonpresent); | 352 | drop_spte(vcpu->kvm, spte); |
| 358 | return true; | 353 | return true; |
| 359 | } | 354 | } |
| 360 | 355 | ||
| @@ -437,7 +432,7 @@ static void FNAME(pte_prefetch)(struct kvm_vcpu *vcpu, struct guest_walker *gw, | |||
| 437 | if (spte == sptep) | 432 | if (spte == sptep) |
| 438 | continue; | 433 | continue; |
| 439 | 434 | ||
| 440 | if (*spte != shadow_trap_nonpresent_pte) | 435 | if (is_shadow_present_pte(*spte)) |
| 441 | continue; | 436 | continue; |
| 442 | 437 | ||
| 443 | gpte = gptep[i]; | 438 | gpte = gptep[i]; |
| @@ -687,11 +682,10 @@ static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva) | |||
| 687 | if (is_shadow_present_pte(*sptep)) { | 682 | if (is_shadow_present_pte(*sptep)) { |
| 688 | if (is_large_pte(*sptep)) | 683 | if (is_large_pte(*sptep)) |
| 689 | --vcpu->kvm->stat.lpages; | 684 | --vcpu->kvm->stat.lpages; |
| 690 | drop_spte(vcpu->kvm, sptep, | 685 | drop_spte(vcpu->kvm, sptep); |
| 691 | shadow_trap_nonpresent_pte); | ||
| 692 | need_flush = 1; | 686 | need_flush = 1; |
| 693 | } else | 687 | } |
| 694 | __set_spte(sptep, shadow_trap_nonpresent_pte); | 688 | |
| 695 | break; | 689 | break; |
| 696 | } | 690 | } |
| 697 | 691 | ||
| @@ -751,36 +745,6 @@ static gpa_t FNAME(gva_to_gpa_nested)(struct kvm_vcpu *vcpu, gva_t vaddr, | |||
| 751 | return gpa; | 745 | return gpa; |
| 752 | } | 746 | } |
| 753 | 747 | ||
| 754 | static void FNAME(prefetch_page)(struct kvm_vcpu *vcpu, | ||
| 755 | struct kvm_mmu_page *sp) | ||
| 756 | { | ||
| 757 | int i, j, offset, r; | ||
| 758 | pt_element_t pt[256 / sizeof(pt_element_t)]; | ||
| 759 | gpa_t pte_gpa; | ||
| 760 | |||
| 761 | if (sp->role.direct | ||
| 762 | || (PTTYPE == 32 && sp->role.level > PT_PAGE_TABLE_LEVEL)) { | ||
| 763 | nonpaging_prefetch_page(vcpu, sp); | ||
| 764 | return; | ||
| 765 | } | ||
| 766 | |||
| 767 | pte_gpa = gfn_to_gpa(sp->gfn); | ||
| 768 | if (PTTYPE == 32) { | ||
| 769 | offset = sp->role.quadrant << PT64_LEVEL_BITS; | ||
| 770 | pte_gpa += offset * sizeof(pt_element_t); | ||
| 771 | } | ||
| 772 | |||
| 773 | for (i = 0; i < PT64_ENT_PER_PAGE; i += ARRAY_SIZE(pt)) { | ||
| 774 | r = kvm_read_guest_atomic(vcpu->kvm, pte_gpa, pt, sizeof pt); | ||
| 775 | pte_gpa += ARRAY_SIZE(pt) * sizeof(pt_element_t); | ||
| 776 | for (j = 0; j < ARRAY_SIZE(pt); ++j) | ||
| 777 | if (r || is_present_gpte(pt[j])) | ||
| 778 | sp->spt[i+j] = shadow_trap_nonpresent_pte; | ||
| 779 | else | ||
| 780 | sp->spt[i+j] = shadow_notrap_nonpresent_pte; | ||
| 781 | } | ||
| 782 | } | ||
| 783 | |||
| 784 | /* | 748 | /* |
| 785 | * Using the cached information from sp->gfns is safe because: | 749 | * Using the cached information from sp->gfns is safe because: |
| 786 | * - The spte has a reference to the struct page, so the pfn for a given gfn | 750 | * - The spte has a reference to the struct page, so the pfn for a given gfn |
| @@ -833,8 +797,7 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) | |||
| 833 | } | 797 | } |
| 834 | 798 | ||
| 835 | if (gfn != sp->gfns[i]) { | 799 | if (gfn != sp->gfns[i]) { |
| 836 | drop_spte(vcpu->kvm, &sp->spt[i], | 800 | drop_spte(vcpu->kvm, &sp->spt[i]); |
| 837 | shadow_trap_nonpresent_pte); | ||
| 838 | vcpu->kvm->tlbs_dirty++; | 801 | vcpu->kvm->tlbs_dirty++; |
| 839 | continue; | 802 | continue; |
| 840 | } | 803 | } |
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index f5b49c7fc89d..a644acb6ed80 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
| @@ -49,9 +49,6 @@ | |||
| 49 | MODULE_AUTHOR("Qumranet"); | 49 | MODULE_AUTHOR("Qumranet"); |
| 50 | MODULE_LICENSE("GPL"); | 50 | MODULE_LICENSE("GPL"); |
| 51 | 51 | ||
| 52 | static int __read_mostly bypass_guest_pf = 1; | ||
| 53 | module_param(bypass_guest_pf, bool, S_IRUGO); | ||
| 54 | |||
| 55 | static int __read_mostly enable_vpid = 1; | 52 | static int __read_mostly enable_vpid = 1; |
| 56 | module_param_named(vpid, enable_vpid, bool, 0444); | 53 | module_param_named(vpid, enable_vpid, bool, 0444); |
| 57 | 54 | ||
| @@ -3632,8 +3629,8 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx) | |||
| 3632 | vmcs_write32(PLE_WINDOW, ple_window); | 3629 | vmcs_write32(PLE_WINDOW, ple_window); |
| 3633 | } | 3630 | } |
| 3634 | 3631 | ||
| 3635 | vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, !!bypass_guest_pf); | 3632 | vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, 0); |
| 3636 | vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, !!bypass_guest_pf); | 3633 | vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, 0); |
| 3637 | vmcs_write32(CR3_TARGET_COUNT, 0); /* 22.2.1 */ | 3634 | vmcs_write32(CR3_TARGET_COUNT, 0); /* 22.2.1 */ |
| 3638 | 3635 | ||
| 3639 | vmcs_write16(HOST_FS_SELECTOR, 0); /* 22.2.4 */ | 3636 | vmcs_write16(HOST_FS_SELECTOR, 0); /* 22.2.4 */ |
| @@ -7103,16 +7100,12 @@ static int __init vmx_init(void) | |||
| 7103 | vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_EIP, false); | 7100 | vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_EIP, false); |
| 7104 | 7101 | ||
| 7105 | if (enable_ept) { | 7102 | if (enable_ept) { |
| 7106 | bypass_guest_pf = 0; | ||
| 7107 | kvm_mmu_set_mask_ptes(0ull, 0ull, 0ull, 0ull, | 7103 | kvm_mmu_set_mask_ptes(0ull, 0ull, 0ull, 0ull, |
| 7108 | VMX_EPT_EXECUTABLE_MASK); | 7104 | VMX_EPT_EXECUTABLE_MASK); |
| 7109 | kvm_enable_tdp(); | 7105 | kvm_enable_tdp(); |
| 7110 | } else | 7106 | } else |
| 7111 | kvm_disable_tdp(); | 7107 | kvm_disable_tdp(); |
| 7112 | 7108 | ||
| 7113 | if (bypass_guest_pf) | ||
| 7114 | kvm_mmu_set_nonpresent_ptes(~0xffeull, 0ull); | ||
| 7115 | |||
| 7116 | return 0; | 7109 | return 0; |
| 7117 | 7110 | ||
| 7118 | out3: | 7111 | out3: |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 028a0f25e8a0..64c42d90112b 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
| @@ -5091,7 +5091,6 @@ int kvm_arch_init(void *opaque) | |||
| 5091 | kvm_init_msr_list(); | 5091 | kvm_init_msr_list(); |
| 5092 | 5092 | ||
| 5093 | kvm_x86_ops = ops; | 5093 | kvm_x86_ops = ops; |
| 5094 | kvm_mmu_set_nonpresent_ptes(0ull, 0ull); | ||
| 5095 | kvm_mmu_set_mask_ptes(PT_USER_MASK, PT_ACCESSED_MASK, | 5094 | kvm_mmu_set_mask_ptes(PT_USER_MASK, PT_ACCESSED_MASK, |
| 5096 | PT_DIRTY_MASK, PT64_NX_MASK, 0); | 5095 | PT_DIRTY_MASK, PT64_NX_MASK, 0); |
| 5097 | 5096 | ||
