|
27 | 27 | #include <linux/nmi.h>
|
28 | 28 | #include <linux/swait.h>
|
29 | 29 | #include <linux/syscore_ops.h>
|
| 30 | +#include <linux/efi.h> |
30 | 31 | #include <asm/timer.h>
|
31 | 32 | #include <asm/cpu.h>
|
32 | 33 | #include <asm/traps.h>
|
|
40 | 41 | #include <asm/ptrace.h>
|
41 | 42 | #include <asm/reboot.h>
|
42 | 43 | #include <asm/svm.h>
|
| 44 | +#include <asm/e820/api.h> |
43 | 45 |
|
44 | 46 | DEFINE_STATIC_KEY_FALSE(kvm_async_pf_enabled);
|
45 | 47 |
|
@@ -433,6 +435,8 @@ static void kvm_guest_cpu_offline(bool shutdown)
|
433 | 435 | kvm_disable_steal_time();
|
434 | 436 | if (kvm_para_has_feature(KVM_FEATURE_PV_EOI))
|
435 | 437 | wrmsrl(MSR_KVM_PV_EOI_EN, 0);
|
| 438 | + if (kvm_para_has_feature(KVM_FEATURE_MIGRATION_CONTROL)) |
| 439 | + wrmsrl(MSR_KVM_MIGRATION_CONTROL, 0); |
436 | 440 | kvm_pv_disable_apf();
|
437 | 441 | if (!shutdown)
|
438 | 442 | apf_task_wake_all();
|
@@ -547,6 +551,55 @@ static void kvm_send_ipi_mask_allbutself(const struct cpumask *mask, int vector)
|
547 | 551 | __send_ipi_mask(local_mask, vector);
|
548 | 552 | }
|
549 | 553 |
|
| 554 | +static int __init setup_efi_kvm_sev_migration(void) |
| 555 | +{ |
| 556 | + efi_char16_t efi_sev_live_migration_enabled[] = L"SevLiveMigrationEnabled"; |
| 557 | + efi_guid_t efi_variable_guid = AMD_SEV_MEM_ENCRYPT_GUID; |
| 558 | + efi_status_t status; |
| 559 | + unsigned long size; |
| 560 | + bool enabled; |
| 561 | + |
| 562 | + if (!sev_active() || |
| 563 | + !kvm_para_has_feature(KVM_FEATURE_MIGRATION_CONTROL)) |
| 564 | + return 0; |
| 565 | + |
| 566 | + if (!efi_enabled(EFI_BOOT)) |
| 567 | + return 0; |
| 568 | + |
| 569 | + if (!efi_enabled(EFI_RUNTIME_SERVICES)) { |
| 570 | + pr_info("%s : EFI runtime services are not enabled\n", __func__); |
| 571 | + return 0; |
| 572 | + } |
| 573 | + |
| 574 | + size = sizeof(enabled); |
| 575 | + |
| 576 | + /* Get variable contents into buffer */ |
| 577 | + status = efi.get_variable(efi_sev_live_migration_enabled, |
| 578 | + &efi_variable_guid, NULL, &size, &enabled); |
| 579 | + |
| 580 | + if (status == EFI_NOT_FOUND) { |
| 581 | + pr_info("%s : EFI live migration variable not found\n", __func__); |
| 582 | + return 0; |
| 583 | + } |
| 584 | + |
| 585 | + if (status != EFI_SUCCESS) { |
| 586 | + pr_info("%s : EFI variable retrieval failed\n", __func__); |
| 587 | + return 0; |
| 588 | + } |
| 589 | + |
| 590 | + if (enabled == 0) { |
| 591 | + pr_info("%s: live migration disabled in EFI\n", __func__); |
| 592 | + return 0; |
| 593 | + } |
| 594 | + |
| 595 | + pr_info("%s : live migration enabled in EFI\n", __func__); |
| 596 | + wrmsrl(MSR_KVM_MIGRATION_CONTROL, KVM_MIGRATION_READY); |
| 597 | + |
| 598 | + return 1; |
| 599 | +} |
| 600 | + |
| 601 | +late_initcall(setup_efi_kvm_sev_migration); |
| 602 | + |
550 | 603 | /*
|
551 | 604 | * Set the IPI entry points
|
552 | 605 | */
|
@@ -805,8 +858,37 @@ static bool __init kvm_msi_ext_dest_id(void)
|
805 | 858 | return kvm_para_has_feature(KVM_FEATURE_MSI_EXT_DEST_ID);
|
806 | 859 | }
|
807 | 860 |
|
| 861 | +static void kvm_sev_hc_page_enc_status(unsigned long pfn, int npages, bool enc) |
| 862 | +{ |
| 863 | + kvm_sev_hypercall3(KVM_HC_MAP_GPA_RANGE, pfn << PAGE_SHIFT, npages, |
| 864 | + KVM_MAP_GPA_RANGE_ENC_STAT(enc) | KVM_MAP_GPA_RANGE_PAGE_SZ_4K); |
| 865 | +} |
| 866 | + |
808 | 867 | static void __init kvm_init_platform(void)
|
809 | 868 | {
|
| 869 | + if (sev_active() && |
| 870 | + kvm_para_has_feature(KVM_FEATURE_MIGRATION_CONTROL)) { |
| 871 | + unsigned long nr_pages; |
| 872 | + |
| 873 | + pv_ops.mmu.notify_page_enc_status_changed = |
| 874 | + kvm_sev_hc_page_enc_status; |
| 875 | + |
| 876 | + /* |
| 877 | + * Ensure that _bss_decrypted section is marked as decrypted in the |
| 878 | + * shared pages list. |
| 879 | + */ |
| 880 | + nr_pages = DIV_ROUND_UP(__end_bss_decrypted - __start_bss_decrypted, |
| 881 | + PAGE_SIZE); |
| 882 | + early_set_mem_enc_dec_hypercall((unsigned long)__start_bss_decrypted, |
| 883 | + nr_pages, 0); |
| 884 | + |
| 885 | + /* |
| 886 | + * If not booted using EFI, enable Live migration support. |
| 887 | + */ |
| 888 | + if (!efi_enabled(EFI_BOOT)) |
| 889 | + wrmsrl(MSR_KVM_MIGRATION_CONTROL, |
| 890 | + KVM_MIGRATION_READY); |
| 891 | + } |
810 | 892 | kvmclock_init();
|
811 | 893 | x86_platform.apic_post_init = kvm_apic_init;
|
812 | 894 | }
|
|
0 commit comments