Is this interface supposed to support changing MSR handing at runtime or is the ioctl only meant to be called prior to KVM_RUN? Thanks, Richard On Wed, Oct 28, 2009 at 1:23 PM, David Windsor <dwindsor@xxxxxxxxx> wrote: > > Hi, > > I've encountered a situation in which I would like to allow userspace > to set the MSRs which KVM should not emulate and instead implement > these as no-ops. > > I have not seen any work in this space, furthermore there is an item > on the KVM TODO that is very similar to what I'm trying to do. > > The userspace interface is an extension of kvm_vcpu_ioctl, adding the > KVM_SET_MSRS_NOOP flag. It takes a struct kvm_msrs as a list of which > MSRs should be no-ops and adds the field noop to struct kvm_msr_entry. > This patch only affects vmx, but if the approach is sane, I can > extend it to support svm as well. > > > > diff -purN linux-2.6.32-rc5/arch/x86/include/asm/kvm.h > linux-2.6.32-rc5-kvm-msrs-noop/arch/x86/include/asm/kvm.h > --- linux-2.6.32-rc5/arch/x86/include/asm/kvm.h 2009-10-15 > 20:41:50.000000000 -0400 > +++ linux-2.6.32-rc5-kvm-msrs-noop/arch/x86/include/asm/kvm.h 2009-10-27 > 22:44:58.000000000 -0400 > @@ -144,6 +144,7 @@ struct kvm_msr_entry { > __u32 index; > __u32 reserved; > __u64 data; > + __u8 noop; > }; > > /* for KVM_GET_MSRS and KVM_SET_MSRS */ > diff -purN linux-2.6.32-rc5/arch/x86/include/asm/kvm_host.h > linux-2.6.32-rc5-kvm-msrs-noop/arch/x86/include/asm/kvm_host.h > --- linux-2.6.32-rc5/arch/x86/include/asm/kvm_host.h 2009-10-15 > 20:41:50.000000000 -0400 > +++ linux-2.6.32-rc5-kvm-msrs-noop/arch/x86/include/asm/kvm_host.h > 2009-10-27 > 22:44:58.000000000 -0400 > @@ -481,6 +481,7 @@ struct kvm_x86_ops { > struct kvm_guest_debug *dbg); > int (*get_msr)(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata); > int (*set_msr)(struct kvm_vcpu *vcpu, u32 msr_index, u64 data); > + int (*set_msr_noop)(struct kvm_vcpu *vcpu, u32 msr_index); > u64 (*get_segment_base)(struct kvm_vcpu *vcpu, int seg); > void (*get_segment)(struct kvm_vcpu *vcpu, > struct kvm_segment *var, int seg); > diff -purN linux-2.6.32-rc5/arch/x86/kvm/vmx.c > linux-2.6.32-rc5-kvm-msrs-noop/arch/x86/kvm/vmx.c > --- linux-2.6.32-rc5/arch/x86/kvm/vmx.c 2009-10-15 20:41:50.000000000 -0400 > +++ linux-2.6.32-rc5-kvm-msrs-noop/arch/x86/kvm/vmx.c 2009-10-27 > 22:44:58.000000000 -0400 > @@ -983,6 +983,13 @@ static int vmx_get_msr(struct kvm_vcpu * > return -EINVAL; > } > > + msr = find_msr_entry(to_vmx(vcpu), msr_index); > + if (msr) { > + if (msr->noop) { > + return 0; > + } > + } > + > switch (msr_index) { > #ifdef CONFIG_X86_64 > case MSR_FS_BASE: > @@ -1032,6 +1039,13 @@ static int vmx_set_msr(struct kvm_vcpu * > u64 host_tsc; > int ret = 0; > > + msr = find_msr_entry(to_vmx(vcpu), msr_index); > + if (msr) { > + if (msr->noop) { > + return ret; > + } > + } > + > switch (msr_index) { > case MSR_EFER: > vmx_load_host_state(vmx); > @@ -1078,6 +1092,21 @@ static int vmx_set_msr(struct kvm_vcpu * > return ret; > } > > +static int vmx_set_msr_noop(struct kvm_vcpu *vcpu, u32 msr) > +{ > + struct kvm_msr_entry *m; > + > + if (!vcpu) > + return -1; > + > + m = find_msr_entry(to_vmx(vcpu), msr); > + if (!m) > + return -1; > + > + m->noop = 1; > + return 0; > +} > + > static void vmx_cache_reg(struct kvm_vcpu *vcpu, enum kvm_reg reg) > { > __set_bit(reg, (unsigned long *)&vcpu->arch.regs_avail); > @@ -3942,6 +3971,7 @@ static struct kvm_x86_ops vmx_x86_ops = > .set_guest_debug = set_guest_debug, > .get_msr = vmx_get_msr, > .set_msr = vmx_set_msr, > + .set_msr_noop = vmx_set_msr_noop, > .get_segment_base = vmx_get_segment_base, > .get_segment = vmx_get_segment, > .set_segment = vmx_set_segment, > diff -purN linux-2.6.32-rc5/arch/x86/kvm/x86.c > linux-2.6.32-rc5-kvm-msrs-noop/arch/x86/kvm/x86.c > --- linux-2.6.32-rc5/arch/x86/kvm/x86.c 2009-10-15 20:41:50.000000000 -0400 > +++ linux-2.6.32-rc5-kvm-msrs-noop/arch/x86/kvm/x86.c 2009-10-27 > 22:44:58.000000000 -0400 > @@ -975,6 +975,31 @@ int kvm_get_msr(struct kvm_vcpu *vcpu, u > return kvm_x86_ops->get_msr(vcpu, msr_index, pdata); > } > > +static int kvm_set_msrs_noop(struct kvm_vcpu *vcpu, struct kvm_msrs > __user *user_msrs) > +{ > + int i, r; > + int size; > + struct kvm_msrs msrs; > + struct kvm_msr_entry *entries; > + > + if (copy_from_user(&msrs, user_msrs, sizeof msrs)) > + goto out; > + > + size = sizeof(struct kvm_msr_entry) * msrs.nmsrs; > + if (copy_from_user(entries, user_msrs->entries, size)) > + goto out; > + > + for (i = 0; i < msrs.nmsrs; i++) { > + r = kvm_x86_ops->set_msr_noop(vcpu, entries[i].index); > + if (r) > + goto out; > + } > + > + return 0; > +out: > + return -1; > +} > + > static int get_msr_mtrr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) > { > u64 *p = (u64 *)&vcpu->arch.mtrr_state.fixed_ranges; > @@ -1864,6 +1889,9 @@ long kvm_arch_vcpu_ioctl(struct file *fi > case KVM_SET_MSRS: > r = msr_io(vcpu, argp, do_set_msr, 0); > break; > + case KVM_SET_MSRS_NOOP: > + r = kvm_set_msrs_noop(vcpu, argp); > + break; > case KVM_TPR_ACCESS_REPORTING: { > struct kvm_tpr_access_ctl tac; > > diff -purN linux-2.6.32-rc5/include/linux/kvm.h > linux-2.6.32-rc5-kvm-msrs-noop/include/linux/kvm.h > --- linux-2.6.32-rc5/include/linux/kvm.h 2009-10-15 > 20:41:50.000000000 -0400 > +++ linux-2.6.32-rc5-kvm-msrs-noop/include/linux/kvm.h 2009-10-27 > 22:46:36.000000000 -0400 > @@ -593,6 +593,7 @@ struct kvm_irqfd { > #define KVM_X86_SETUP_MCE _IOW(KVMIO, 0x9c, __u64) > #define KVM_X86_GET_MCE_CAP_SUPPORTED _IOR(KVMIO, 0x9d, __u64) > #define KVM_X86_SET_MCE _IOW(KVMIO, 0x9e, struct kvm_x86_mce) > +#define KVM_SET_MSRS_NOOP _IOW(KVMIO, 0x9f, struct kvm_msrs) > > /* > * Deprecated interfaces > -- > To unsubscribe from this list: send the line "unsubscribe kvm" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html