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

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

 



It is intended to be used only during startup, typically by a launcher
that is aware which MSRs should be emulated as no-ops.

On Wed, Oct 28, 2009 at 2:28 PM, Richard Winthers <rwinthers@xxxxxxxxx> wrote:
> 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