aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/x86.c
diff options
context:
space:
mode:
authorXiao Guangrong <xiaoguangrong@cn.fujitsu.com>2011-07-11 15:33:44 -0400
committerAvi Kivity <avi@redhat.com>2011-07-24 04:50:40 -0400
commitce88decffd17bf9f373cc233c961ad2054965667 (patch)
tree65202d01a10c790eacb4b63bacc5fccfbe5bb050 /arch/x86/kvm/x86.c
parentdd3bfd59dbc69fd970394ab354cfca5f959d5755 (diff)
KVM: MMU: mmio page fault support
The idea is from Avi: | We could cache the result of a miss in an spte by using a reserved bit, and | checking the page fault error code (or seeing if we get an ept violation or | ept misconfiguration), so if we get repeated mmio on a page, we don't need to | search the slot list/tree. | (https://lkml.org/lkml/2011/2/22/221) When the page fault is caused by mmio, we cache the info in the shadow page table, and also set the reserved bits in the shadow page table, so if the mmio is caused again, we can quickly identify it and emulate it directly Searching mmio gfn in memslots is heavy since we need to walk all memeslots, it can be reduced by this feature, and also avoid walking guest page table for soft mmu. [jan: fix operator precedence issue] Signed-off-by: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r--arch/x86/kvm/x86.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 64c42d90112b..2c9661f230a9 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -5062,6 +5062,30 @@ void kvm_after_handle_nmi(struct kvm_vcpu *vcpu)
5062} 5062}
5063EXPORT_SYMBOL_GPL(kvm_after_handle_nmi); 5063EXPORT_SYMBOL_GPL(kvm_after_handle_nmi);
5064 5064
5065static void kvm_set_mmio_spte_mask(void)
5066{
5067 u64 mask;
5068 int maxphyaddr = boot_cpu_data.x86_phys_bits;
5069
5070 /*
5071 * Set the reserved bits and the present bit of an paging-structure
5072 * entry to generate page fault with PFER.RSV = 1.
5073 */
5074 mask = ((1ull << (62 - maxphyaddr + 1)) - 1) << maxphyaddr;
5075 mask |= 1ull;
5076
5077#ifdef CONFIG_X86_64
5078 /*
5079 * If reserved bit is not supported, clear the present bit to disable
5080 * mmio page fault.
5081 */
5082 if (maxphyaddr == 52)
5083 mask &= ~1ull;
5084#endif
5085
5086 kvm_mmu_set_mmio_spte_mask(mask);
5087}
5088
5065int kvm_arch_init(void *opaque) 5089int kvm_arch_init(void *opaque)
5066{ 5090{
5067 int r; 5091 int r;
@@ -5088,6 +5112,7 @@ int kvm_arch_init(void *opaque)
5088 if (r) 5112 if (r)
5089 goto out; 5113 goto out;
5090 5114
5115 kvm_set_mmio_spte_mask();
5091 kvm_init_msr_list(); 5116 kvm_init_msr_list();
5092 5117
5093 kvm_x86_ops = ops; 5118 kvm_x86_ops = ops;