diff options
Diffstat (limited to 'drivers/kvm/x86.c')
-rw-r--r-- | drivers/kvm/x86.c | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/drivers/kvm/x86.c b/drivers/kvm/x86.c index 2edc53ec8b3b..4902b35060f5 100644 --- a/drivers/kvm/x86.c +++ b/drivers/kvm/x86.c | |||
@@ -564,6 +564,41 @@ out: | |||
564 | return r; | 564 | return r; |
565 | } | 565 | } |
566 | 566 | ||
567 | /* | ||
568 | * Make sure that a cpu that is being hot-unplugged does not have any vcpus | ||
569 | * cached on it. | ||
570 | */ | ||
571 | void decache_vcpus_on_cpu(int cpu) | ||
572 | { | ||
573 | struct kvm *vm; | ||
574 | struct kvm_vcpu *vcpu; | ||
575 | int i; | ||
576 | |||
577 | spin_lock(&kvm_lock); | ||
578 | list_for_each_entry(vm, &vm_list, vm_list) | ||
579 | for (i = 0; i < KVM_MAX_VCPUS; ++i) { | ||
580 | vcpu = vm->vcpus[i]; | ||
581 | if (!vcpu) | ||
582 | continue; | ||
583 | /* | ||
584 | * If the vcpu is locked, then it is running on some | ||
585 | * other cpu and therefore it is not cached on the | ||
586 | * cpu in question. | ||
587 | * | ||
588 | * If it's not locked, check the last cpu it executed | ||
589 | * on. | ||
590 | */ | ||
591 | if (mutex_trylock(&vcpu->mutex)) { | ||
592 | if (vcpu->cpu == cpu) { | ||
593 | kvm_x86_ops->vcpu_decache(vcpu); | ||
594 | vcpu->cpu = -1; | ||
595 | } | ||
596 | mutex_unlock(&vcpu->mutex); | ||
597 | } | ||
598 | } | ||
599 | spin_unlock(&kvm_lock); | ||
600 | } | ||
601 | |||
567 | long kvm_arch_dev_ioctl(struct file *filp, | 602 | long kvm_arch_dev_ioctl(struct file *filp, |
568 | unsigned int ioctl, unsigned long arg) | 603 | unsigned int ioctl, unsigned long arg) |
569 | { | 604 | { |
@@ -2319,3 +2354,125 @@ void kvm_put_guest_fpu(struct kvm_vcpu *vcpu) | |||
2319 | fx_restore(&vcpu->host_fx_image); | 2354 | fx_restore(&vcpu->host_fx_image); |
2320 | } | 2355 | } |
2321 | EXPORT_SYMBOL_GPL(kvm_put_guest_fpu); | 2356 | EXPORT_SYMBOL_GPL(kvm_put_guest_fpu); |
2357 | |||
2358 | void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu) | ||
2359 | { | ||
2360 | kvm_x86_ops->vcpu_free(vcpu); | ||
2361 | } | ||
2362 | |||
2363 | struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, | ||
2364 | unsigned int id) | ||
2365 | { | ||
2366 | int r; | ||
2367 | struct kvm_vcpu *vcpu = kvm_x86_ops->vcpu_create(kvm, id); | ||
2368 | |||
2369 | if (IS_ERR(vcpu)) { | ||
2370 | r = -ENOMEM; | ||
2371 | goto fail; | ||
2372 | } | ||
2373 | |||
2374 | /* We do fxsave: this must be aligned. */ | ||
2375 | BUG_ON((unsigned long)&vcpu->host_fx_image & 0xF); | ||
2376 | |||
2377 | vcpu_load(vcpu); | ||
2378 | r = kvm_arch_vcpu_reset(vcpu); | ||
2379 | if (r == 0) | ||
2380 | r = kvm_mmu_setup(vcpu); | ||
2381 | vcpu_put(vcpu); | ||
2382 | if (r < 0) | ||
2383 | goto free_vcpu; | ||
2384 | |||
2385 | return vcpu; | ||
2386 | free_vcpu: | ||
2387 | kvm_x86_ops->vcpu_free(vcpu); | ||
2388 | fail: | ||
2389 | return ERR_PTR(r); | ||
2390 | } | ||
2391 | |||
2392 | void kvm_arch_vcpu_destory(struct kvm_vcpu *vcpu) | ||
2393 | { | ||
2394 | vcpu_load(vcpu); | ||
2395 | kvm_mmu_unload(vcpu); | ||
2396 | vcpu_put(vcpu); | ||
2397 | |||
2398 | kvm_x86_ops->vcpu_free(vcpu); | ||
2399 | } | ||
2400 | |||
2401 | int kvm_arch_vcpu_reset(struct kvm_vcpu *vcpu) | ||
2402 | { | ||
2403 | return kvm_x86_ops->vcpu_reset(vcpu); | ||
2404 | } | ||
2405 | |||
2406 | void kvm_arch_hardware_enable(void *garbage) | ||
2407 | { | ||
2408 | kvm_x86_ops->hardware_enable(garbage); | ||
2409 | } | ||
2410 | |||
2411 | void kvm_arch_hardware_disable(void *garbage) | ||
2412 | { | ||
2413 | kvm_x86_ops->hardware_disable(garbage); | ||
2414 | } | ||
2415 | |||
2416 | int kvm_arch_hardware_setup(void) | ||
2417 | { | ||
2418 | return kvm_x86_ops->hardware_setup(); | ||
2419 | } | ||
2420 | |||
2421 | void kvm_arch_hardware_unsetup(void) | ||
2422 | { | ||
2423 | kvm_x86_ops->hardware_unsetup(); | ||
2424 | } | ||
2425 | |||
2426 | void kvm_arch_check_processor_compat(void *rtn) | ||
2427 | { | ||
2428 | kvm_x86_ops->check_processor_compatibility(rtn); | ||
2429 | } | ||
2430 | |||
2431 | int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) | ||
2432 | { | ||
2433 | struct page *page; | ||
2434 | struct kvm *kvm; | ||
2435 | int r; | ||
2436 | |||
2437 | BUG_ON(vcpu->kvm == NULL); | ||
2438 | kvm = vcpu->kvm; | ||
2439 | |||
2440 | vcpu->mmu.root_hpa = INVALID_PAGE; | ||
2441 | if (!irqchip_in_kernel(kvm) || vcpu->vcpu_id == 0) | ||
2442 | vcpu->mp_state = VCPU_MP_STATE_RUNNABLE; | ||
2443 | else | ||
2444 | vcpu->mp_state = VCPU_MP_STATE_UNINITIALIZED; | ||
2445 | |||
2446 | page = alloc_page(GFP_KERNEL | __GFP_ZERO); | ||
2447 | if (!page) { | ||
2448 | r = -ENOMEM; | ||
2449 | goto fail; | ||
2450 | } | ||
2451 | vcpu->pio_data = page_address(page); | ||
2452 | |||
2453 | r = kvm_mmu_create(vcpu); | ||
2454 | if (r < 0) | ||
2455 | goto fail_free_pio_data; | ||
2456 | |||
2457 | if (irqchip_in_kernel(kvm)) { | ||
2458 | r = kvm_create_lapic(vcpu); | ||
2459 | if (r < 0) | ||
2460 | goto fail_mmu_destroy; | ||
2461 | } | ||
2462 | |||
2463 | return 0; | ||
2464 | |||
2465 | fail_mmu_destroy: | ||
2466 | kvm_mmu_destroy(vcpu); | ||
2467 | fail_free_pio_data: | ||
2468 | free_page((unsigned long)vcpu->pio_data); | ||
2469 | fail: | ||
2470 | return r; | ||
2471 | } | ||
2472 | |||
2473 | void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu) | ||
2474 | { | ||
2475 | kvm_free_lapic(vcpu); | ||
2476 | kvm_mmu_destroy(vcpu); | ||
2477 | free_page((unsigned long)vcpu->pio_data); | ||
2478 | } | ||