diff options
author | Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com> | 2013-02-05 02:11:09 -0500 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2013-02-06 19:28:01 -0500 |
commit | caf6900f2d8aaebe404c976753f6813ccd31d95e (patch) | |
tree | 327bd3a7bca9cc02e4f4c157885ddd0340d009ee /arch | |
parent | 5037878e2223278aa627162aa0bf106dffac19d4 (diff) |
KVM: MMU: lazily drop large spte
Currently, kvm zaps the large spte if write-protected is needed, the later
read can fault on that spte. Actually, we can make the large spte readonly
instead of making them not present, the page fault caused by read access can
be avoided
The idea is from Avi:
| As I mentioned before, write-protecting a large spte is a good idea,
| since it moves some work from protect-time to fault-time, so it reduces
| jitter. This removes the need for the return value.
Reviewed-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kvm/mmu.c | 23 |
1 files changed, 7 insertions, 16 deletions
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 0242a8a1b2e2..2a8d99a1e034 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c | |||
@@ -1106,8 +1106,7 @@ static void drop_large_spte(struct kvm_vcpu *vcpu, u64 *sptep) | |||
1106 | 1106 | ||
1107 | /* | 1107 | /* |
1108 | * Write-protect on the specified @sptep, @pt_protect indicates whether | 1108 | * Write-protect on the specified @sptep, @pt_protect indicates whether |
1109 | * spte writ-protection is caused by protecting shadow page table. | 1109 | * spte write-protection is caused by protecting shadow page table. |
1110 | * @flush indicates whether tlb need be flushed. | ||
1111 | * | 1110 | * |
1112 | * Note: write protection is difference between drity logging and spte | 1111 | * Note: write protection is difference between drity logging and spte |
1113 | * protection: | 1112 | * protection: |
@@ -1116,10 +1115,9 @@ static void drop_large_spte(struct kvm_vcpu *vcpu, u64 *sptep) | |||
1116 | * - for spte protection, the spte can be writable only after unsync-ing | 1115 | * - for spte protection, the spte can be writable only after unsync-ing |
1117 | * shadow page. | 1116 | * shadow page. |
1118 | * | 1117 | * |
1119 | * Return true if the spte is dropped. | 1118 | * Return true if tlb need be flushed. |
1120 | */ | 1119 | */ |
1121 | static bool | 1120 | static bool spte_write_protect(struct kvm *kvm, u64 *sptep, bool pt_protect) |
1122 | spte_write_protect(struct kvm *kvm, u64 *sptep, bool *flush, bool pt_protect) | ||
1123 | { | 1121 | { |
1124 | u64 spte = *sptep; | 1122 | u64 spte = *sptep; |
1125 | 1123 | ||
@@ -1129,17 +1127,11 @@ spte_write_protect(struct kvm *kvm, u64 *sptep, bool *flush, bool pt_protect) | |||
1129 | 1127 | ||
1130 | rmap_printk("rmap_write_protect: spte %p %llx\n", sptep, *sptep); | 1128 | rmap_printk("rmap_write_protect: spte %p %llx\n", sptep, *sptep); |
1131 | 1129 | ||
1132 | if (__drop_large_spte(kvm, sptep)) { | ||
1133 | *flush |= true; | ||
1134 | return true; | ||
1135 | } | ||
1136 | |||
1137 | if (pt_protect) | 1130 | if (pt_protect) |
1138 | spte &= ~SPTE_MMU_WRITEABLE; | 1131 | spte &= ~SPTE_MMU_WRITEABLE; |
1139 | spte = spte & ~PT_WRITABLE_MASK; | 1132 | spte = spte & ~PT_WRITABLE_MASK; |
1140 | 1133 | ||
1141 | *flush |= mmu_spte_update(sptep, spte); | 1134 | return mmu_spte_update(sptep, spte); |
1142 | return false; | ||
1143 | } | 1135 | } |
1144 | 1136 | ||
1145 | static bool __rmap_write_protect(struct kvm *kvm, unsigned long *rmapp, | 1137 | static bool __rmap_write_protect(struct kvm *kvm, unsigned long *rmapp, |
@@ -1151,11 +1143,8 @@ static bool __rmap_write_protect(struct kvm *kvm, unsigned long *rmapp, | |||
1151 | 1143 | ||
1152 | for (sptep = rmap_get_first(*rmapp, &iter); sptep;) { | 1144 | for (sptep = rmap_get_first(*rmapp, &iter); sptep;) { |
1153 | BUG_ON(!(*sptep & PT_PRESENT_MASK)); | 1145 | BUG_ON(!(*sptep & PT_PRESENT_MASK)); |
1154 | if (spte_write_protect(kvm, sptep, &flush, pt_protect)) { | ||
1155 | sptep = rmap_get_first(*rmapp, &iter); | ||
1156 | continue; | ||
1157 | } | ||
1158 | 1146 | ||
1147 | flush |= spte_write_protect(kvm, sptep, pt_protect); | ||
1159 | sptep = rmap_get_next(&iter); | 1148 | sptep = rmap_get_next(&iter); |
1160 | } | 1149 | } |
1161 | 1150 | ||
@@ -2596,6 +2585,8 @@ static int __direct_map(struct kvm_vcpu *vcpu, gpa_t v, int write, | |||
2596 | break; | 2585 | break; |
2597 | } | 2586 | } |
2598 | 2587 | ||
2588 | drop_large_spte(vcpu, iterator.sptep); | ||
2589 | |||
2599 | if (!is_shadow_present_pte(*iterator.sptep)) { | 2590 | if (!is_shadow_present_pte(*iterator.sptep)) { |
2600 | u64 base_addr = iterator.addr; | 2591 | u64 base_addr = iterator.addr; |
2601 | 2592 | ||