aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorXiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>2013-02-05 02:11:09 -0500
committerMarcelo Tosatti <mtosatti@redhat.com>2013-02-06 19:28:01 -0500
commitcaf6900f2d8aaebe404c976753f6813ccd31d95e (patch)
tree327bd3a7bca9cc02e4f4c157885ddd0340d009ee /arch
parent5037878e2223278aa627162aa0bf106dffac19d4 (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.c23
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 */
1121static bool 1120static bool spte_write_protect(struct kvm *kvm, u64 *sptep, bool pt_protect)
1122spte_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
1145static bool __rmap_write_protect(struct kvm *kvm, unsigned long *rmapp, 1137static 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