diff options
author | Avi Kivity <avi@qumranet.com> | 2007-06-07 12:18:30 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2007-07-16 05:05:46 -0400 |
commit | d9e368d61263055eceac2966bb7ea31b89da3425 (patch) | |
tree | 9d507b851ea7bd667cdd50dde640e47e0d4773e9 /drivers/kvm/vmx.c | |
parent | 39c3b86e5c193e09f69f0e99c93600a4999ffc60 (diff) |
KVM: Flush remote tlbs when reducing shadow pte permissions
When a vcpu causes a shadow tlb entry to have reduced permissions, it
must also clear the tlb on remote vcpus. We do that by:
- setting a bit on the vcpu that requests a tlb flush before the next entry
- if the vcpu is currently executing, we send an ipi to make sure it
exits before we continue
Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm/vmx.c')
-rw-r--r-- | drivers/kvm/vmx.c | 22 |
1 files changed, 15 insertions, 7 deletions
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c index a1f51b9d482d..b969db1e0830 100644 --- a/drivers/kvm/vmx.c +++ b/drivers/kvm/vmx.c | |||
@@ -1972,6 +1972,11 @@ static int dm_request_for_irq_injection(struct kvm_vcpu *vcpu, | |||
1972 | (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF)); | 1972 | (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF)); |
1973 | } | 1973 | } |
1974 | 1974 | ||
1975 | static void vmx_flush_tlb(struct kvm_vcpu *vcpu) | ||
1976 | { | ||
1977 | vmcs_writel(GUEST_CR3, vmcs_readl(GUEST_CR3)); | ||
1978 | } | ||
1979 | |||
1975 | static int vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | 1980 | static int vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) |
1976 | { | 1981 | { |
1977 | u8 fail; | 1982 | u8 fail; |
@@ -1997,9 +2002,15 @@ again: | |||
1997 | */ | 2002 | */ |
1998 | vmcs_writel(HOST_CR0, read_cr0()); | 2003 | vmcs_writel(HOST_CR0, read_cr0()); |
1999 | 2004 | ||
2005 | local_irq_disable(); | ||
2006 | |||
2007 | vcpu->guest_mode = 1; | ||
2008 | if (vcpu->requests) | ||
2009 | if (test_and_clear_bit(KVM_TLB_FLUSH, &vcpu->requests)) | ||
2010 | vmx_flush_tlb(vcpu); | ||
2011 | |||
2000 | asm ( | 2012 | asm ( |
2001 | /* Store host registers */ | 2013 | /* Store host registers */ |
2002 | "pushf \n\t" | ||
2003 | #ifdef CONFIG_X86_64 | 2014 | #ifdef CONFIG_X86_64 |
2004 | "push %%rax; push %%rbx; push %%rdx;" | 2015 | "push %%rax; push %%rbx; push %%rdx;" |
2005 | "push %%rsi; push %%rdi; push %%rbp;" | 2016 | "push %%rsi; push %%rdi; push %%rbp;" |
@@ -2091,7 +2102,6 @@ again: | |||
2091 | "pop %%ecx; popa \n\t" | 2102 | "pop %%ecx; popa \n\t" |
2092 | #endif | 2103 | #endif |
2093 | "setbe %0 \n\t" | 2104 | "setbe %0 \n\t" |
2094 | "popf \n\t" | ||
2095 | : "=q" (fail) | 2105 | : "=q" (fail) |
2096 | : "r"(vcpu->launched), "d"((unsigned long)HOST_RSP), | 2106 | : "r"(vcpu->launched), "d"((unsigned long)HOST_RSP), |
2097 | "c"(vcpu), | 2107 | "c"(vcpu), |
@@ -2115,6 +2125,9 @@ again: | |||
2115 | [cr2]"i"(offsetof(struct kvm_vcpu, cr2)) | 2125 | [cr2]"i"(offsetof(struct kvm_vcpu, cr2)) |
2116 | : "cc", "memory" ); | 2126 | : "cc", "memory" ); |
2117 | 2127 | ||
2128 | vcpu->guest_mode = 0; | ||
2129 | local_irq_enable(); | ||
2130 | |||
2118 | ++vcpu->stat.exits; | 2131 | ++vcpu->stat.exits; |
2119 | 2132 | ||
2120 | vcpu->interrupt_window_open = (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & 3) == 0; | 2133 | vcpu->interrupt_window_open = (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & 3) == 0; |
@@ -2167,11 +2180,6 @@ out: | |||
2167 | return r; | 2180 | return r; |
2168 | } | 2181 | } |
2169 | 2182 | ||
2170 | static void vmx_flush_tlb(struct kvm_vcpu *vcpu) | ||
2171 | { | ||
2172 | vmcs_writel(GUEST_CR3, vmcs_readl(GUEST_CR3)); | ||
2173 | } | ||
2174 | |||
2175 | static void vmx_inject_page_fault(struct kvm_vcpu *vcpu, | 2183 | static void vmx_inject_page_fault(struct kvm_vcpu *vcpu, |
2176 | unsigned long addr, | 2184 | unsigned long addr, |
2177 | u32 err_code) | 2185 | u32 err_code) |