Re: [RFC] allow userspace to set MSR no-ops

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux