aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm/vmx.c
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2007-09-16 12:58:32 -0400
committerAvi Kivity <avi@qumranet.com>2008-01-30 10:52:48 -0500
commitc7addb902054195b995114df154e061c7d604f69 (patch)
tree985910a6c970957126c91e55c55b0e73ae877e0c /drivers/kvm/vmx.c
parent51c6cf662b4b361a09fbd324f4c67875d9bcfbea (diff)
KVM: Allow not-present guest page faults to bypass kvm
There are two classes of page faults trapped by kvm: - host page faults, where the fault is needed to allow kvm to install the shadow pte or update the guest accessed and dirty bits - guest page faults, where the guest has faulted and kvm simply injects the fault back into the guest to handle The second class, guest page faults, is pure overhead. We can eliminate some of it on vmx using the following evil trick: - when we set up a shadow page table entry, if the corresponding guest pte is not present, set up the shadow pte as not present - if the guest pte _is_ present, mark the shadow pte as present but also set one of the reserved bits in the shadow pte - tell the vmx hardware not to trap faults which have the present bit clear With this, normal page-not-present faults go directly to the guest, bypassing kvm entirely. Unfortunately, this trick only works on Intel hardware, as AMD lacks a way to discriminate among page faults based on error code. It is also a little risky since it uses reserved bits which might become unreserved in the future, so a module parameter is provided to disable it. Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm/vmx.c')
-rw-r--r--drivers/kvm/vmx.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index 8eb49e055ec0..27a3318fa6c2 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -26,6 +26,7 @@
26#include <linux/mm.h> 26#include <linux/mm.h>
27#include <linux/highmem.h> 27#include <linux/highmem.h>
28#include <linux/sched.h> 28#include <linux/sched.h>
29#include <linux/moduleparam.h>
29 30
30#include <asm/io.h> 31#include <asm/io.h>
31#include <asm/desc.h> 32#include <asm/desc.h>
@@ -33,6 +34,9 @@
33MODULE_AUTHOR("Qumranet"); 34MODULE_AUTHOR("Qumranet");
34MODULE_LICENSE("GPL"); 35MODULE_LICENSE("GPL");
35 36
37static int bypass_guest_pf = 1;
38module_param(bypass_guest_pf, bool, 0);
39
36struct vmcs { 40struct vmcs {
37 u32 revision_id; 41 u32 revision_id;
38 u32 abort; 42 u32 abort;
@@ -1535,8 +1539,8 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
1535 } 1539 }
1536 vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, exec_control); 1540 vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, exec_control);
1537 1541
1538 vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, 0); 1542 vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, !!bypass_guest_pf);
1539 vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, 0); 1543 vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, !!bypass_guest_pf);
1540 vmcs_write32(CR3_TARGET_COUNT, 0); /* 22.2.1 */ 1544 vmcs_write32(CR3_TARGET_COUNT, 0); /* 22.2.1 */
1541 1545
1542 vmcs_writel(HOST_CR0, read_cr0()); /* 22.2.3 */ 1546 vmcs_writel(HOST_CR0, read_cr0()); /* 22.2.3 */
@@ -2582,6 +2586,9 @@ static int __init vmx_init(void)
2582 if (r) 2586 if (r)
2583 goto out1; 2587 goto out1;
2584 2588
2589 if (bypass_guest_pf)
2590 kvm_mmu_set_nonpresent_ptes(~0xffeull, 0ull);
2591
2585 return 0; 2592 return 0;
2586 2593
2587out1: 2594out1: