aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm/kvm_main.c
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2007-06-07 12:18:30 -0400
committerAvi Kivity <avi@qumranet.com>2007-07-16 05:05:46 -0400
commitd9e368d61263055eceac2966bb7ea31b89da3425 (patch)
tree9d507b851ea7bd667cdd50dde640e47e0d4773e9 /drivers/kvm/kvm_main.c
parent39c3b86e5c193e09f69f0e99c93600a4999ffc60 (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/kvm_main.c')
-rw-r--r--drivers/kvm/kvm_main.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index 4e1a017f3db7..633c2eded08d 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -41,6 +41,8 @@
41#include <linux/fs.h> 41#include <linux/fs.h>
42#include <linux/mount.h> 42#include <linux/mount.h>
43#include <linux/sched.h> 43#include <linux/sched.h>
44#include <linux/cpumask.h>
45#include <linux/smp.h>
44 46
45#include "x86_emulate.h" 47#include "x86_emulate.h"
46#include "segment_descriptor.h" 48#include "segment_descriptor.h"
@@ -309,6 +311,48 @@ static void vcpu_put(struct kvm_vcpu *vcpu)
309 mutex_unlock(&vcpu->mutex); 311 mutex_unlock(&vcpu->mutex);
310} 312}
311 313
314static void ack_flush(void *_completed)
315{
316 atomic_t *completed = _completed;
317
318 atomic_inc(completed);
319}
320
321void kvm_flush_remote_tlbs(struct kvm *kvm)
322{
323 int i, cpu, needed;
324 cpumask_t cpus;
325 struct kvm_vcpu *vcpu;
326 atomic_t completed;
327
328 atomic_set(&completed, 0);
329 cpus_clear(cpus);
330 needed = 0;
331 for (i = 0; i < kvm->nvcpus; ++i) {
332 vcpu = &kvm->vcpus[i];
333 if (test_and_set_bit(KVM_TLB_FLUSH, &vcpu->requests))
334 continue;
335 cpu = vcpu->cpu;
336 if (cpu != -1 && cpu != raw_smp_processor_id())
337 if (!cpu_isset(cpu, cpus)) {
338 cpu_set(cpu, cpus);
339 ++needed;
340 }
341 }
342
343 /*
344 * We really want smp_call_function_mask() here. But that's not
345 * available, so ipi all cpus in parallel and wait for them
346 * to complete.
347 */
348 for (cpu = first_cpu(cpus); cpu != NR_CPUS; cpu = next_cpu(cpu, cpus))
349 smp_call_function_single(cpu, ack_flush, &completed, 1, 0);
350 while (atomic_read(&completed) != needed) {
351 cpu_relax();
352 barrier();
353 }
354}
355
312static struct kvm *kvm_create_vm(void) 356static struct kvm *kvm_create_vm(void)
313{ 357{
314 struct kvm *kvm = kzalloc(sizeof(struct kvm), GFP_KERNEL); 358 struct kvm *kvm = kzalloc(sizeof(struct kvm), GFP_KERNEL);