Message ID | 67935c3fd5f29a2ba9d67a91255276d3b9ccc99b.1628076205.git.ashish.kalra@amd.com |
---|---|
State | New |
Headers | show |
Series | Add SEV guest live migration support | expand |
On Wednesday, August 4, 2021 8:00 PM, Ashish Kalra wrote: > +/* > + * Currently this exit is only used by SEV guests for > + * MSR_KVM_MIGRATION_CONTROL to indicate if the guest > + * is ready for migration. > + */ > +static int kvm_handle_x86_msr(X86CPU *cpu, struct kvm_run *run) { > + static uint64_t msr_kvm_migration_control; > + > + if (run->msr.index != MSR_KVM_MIGRATION_CONTROL) { > + run->msr.error = -EINVAL; > + return -1; > + } > + > + switch (run->exit_reason) { > + case KVM_EXIT_X86_RDMSR: > + run->msr.error = 0; > + run->msr.data = msr_kvm_migration_control; > + break; > + case KVM_EXIT_X86_WRMSR: > + msr_kvm_migration_control = run->msr.data; > + if (run->msr.data == KVM_MIGRATION_READY) { > + sev_del_migrate_blocker(); It seems this is enabled/disabled by the guest, which means that the guest can always refuse to be migrated? Best, Wei
On Fri, Sep 10, 2021 at 07:56:36AM +0000, Wang, Wei W wrote: > On Wednesday, August 4, 2021 8:00 PM, Ashish Kalra wrote: > > +/* > > + * Currently this exit is only used by SEV guests for > > + * MSR_KVM_MIGRATION_CONTROL to indicate if the guest > > + * is ready for migration. > > + */ > > +static int kvm_handle_x86_msr(X86CPU *cpu, struct kvm_run *run) { > > + static uint64_t msr_kvm_migration_control; > > + > > + if (run->msr.index != MSR_KVM_MIGRATION_CONTROL) { > > + run->msr.error = -EINVAL; > > + return -1; > > + } > > + > > + switch (run->exit_reason) { > > + case KVM_EXIT_X86_RDMSR: > > + run->msr.error = 0; > > + run->msr.data = msr_kvm_migration_control; > > + break; > > + case KVM_EXIT_X86_WRMSR: > > + msr_kvm_migration_control = run->msr.data; > > + if (run->msr.data == KVM_MIGRATION_READY) { > > + sev_del_migrate_blocker(); > > It seems this is enabled/disabled by the guest, which means that the guest can always refuse to be migrated? > Yes. Are there any specific concerns/issues with that ? Thanks, Ashish
On Friday, September 10, 2021 5:14 PM, Ashish Kalra wrote: > > It seems this is enabled/disabled by the guest, which means that the guest > can always refuse to be migrated? > > > > Yes. > > Are there any specific concerns/issues with that ? It's kind of wired if everybody rejects to migrate from the guest but they ticked the option "agree to be migrated" when they buy the guest (e.g. at a discounted price). In general, I think the migration decision should be made by the management s/w, not the migratable guest. Best, Wei
diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h index 023e694ac4..d04890113c 100644 --- a/include/sysemu/sev.h +++ b/include/sysemu/sev.h @@ -38,5 +38,6 @@ int sev_add_shared_regions_list(unsigned long gfn_start, unsigned long gfn_end); int sev_save_outgoing_shared_regions_list(QEMUFile *f); int sev_load_incoming_shared_regions_list(QEMUFile *f); bool sev_is_gfn_in_unshared_region(unsigned long gfn); +void sev_del_migrate_blocker(void); #endif diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index 303722e06f..785b8fae6b 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -2240,6 +2240,19 @@ static void register_smram_listener(Notifier *n, void *unused) &smram_address_space, 1); } +static __u64 bitmap; +struct kvm_msr_filter msr_filter_allow = { + .flags = KVM_MSR_FILTER_DEFAULT_ALLOW, + .ranges = { + { + .flags = KVM_MSR_FILTER_READ | KVM_MSR_FILTER_WRITE, + .nmsrs = 1, + .base = MSR_KVM_MIGRATION_CONTROL, + .bitmap = (uint8_t *)&bitmap, + } + } +}; + int kvm_arch_init(MachineState *ms, KVMState *s) { uint64_t identity_base = 0xfffbc000; @@ -2298,6 +2311,21 @@ int kvm_arch_init(MachineState *ms, KVMState *s) } } + ret = kvm_check_extension(s, KVM_CAP_X86_USER_SPACE_MSR) ? + kvm_check_extension(s, KVM_CAP_X86_MSR_FILTER) : + -ENOTSUP; + if (ret > 0) { + ret = kvm_vm_enable_cap(s, KVM_CAP_X86_USER_SPACE_MSR, + 0, KVM_MSR_EXIT_REASON_FILTER); + if (ret == 0) { + ret = kvm_vm_ioctl(s, KVM_X86_SET_MSR_FILTER, &msr_filter_allow); + if (ret < 0) { + error_report("kvm: KVM_X86_SET_MSR_FILTER failed : %s", + strerror(-ret)); + } + } + } + ret = kvm_get_supported_msrs(s); if (ret < 0) { return ret; @@ -4472,6 +4500,35 @@ static int kvm_handle_exit_hypercall(X86CPU *cpu, struct kvm_run *run) return 0; } +/* + * Currently this exit is only used by SEV guests for + * MSR_KVM_MIGRATION_CONTROL to indicate if the guest + * is ready for migration. + */ +static int kvm_handle_x86_msr(X86CPU *cpu, struct kvm_run *run) +{ + static uint64_t msr_kvm_migration_control; + + if (run->msr.index != MSR_KVM_MIGRATION_CONTROL) { + run->msr.error = -EINVAL; + return -1; + } + + switch (run->exit_reason) { + case KVM_EXIT_X86_RDMSR: + run->msr.error = 0; + run->msr.data = msr_kvm_migration_control; + break; + case KVM_EXIT_X86_WRMSR: + msr_kvm_migration_control = run->msr.data; + if (run->msr.data == KVM_MIGRATION_READY) { + sev_del_migrate_blocker(); + } + run->msr.error = 0; + } + return 0; +} + int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) { static const uint8_t int3 = 0xcc; @@ -4736,6 +4793,10 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) case KVM_EXIT_HYPERCALL: ret = kvm_handle_exit_hypercall(cpu, run); break; + case KVM_EXIT_X86_RDMSR: + case KVM_EXIT_X86_WRMSR: + ret = kvm_handle_x86_msr(cpu, run); + break; default: fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason); ret = -1; diff --git a/target/i386/sev.c b/target/i386/sev.c index d22f2ef6dc..58f74db0e3 100644 --- a/target/i386/sev.c +++ b/target/i386/sev.c @@ -791,6 +791,12 @@ sev_launch_finish(SevGuestState *sev) } } +void +sev_del_migrate_blocker(void) +{ + migrate_del_blocker(sev_mig_blocker); +} + static int sev_receive_finish(SevGuestState *s) {