KVM fixes for v4.16-rc4
x86: - fix NULL dereference when using userspace lapic - optimize spectre v1 mitigations by allowing guests to use LFENCE - make microcode revision configurable to prevent guests from unnecessarily blacklisting spectre v2 mitigation features -----BEGIN PGP SIGNATURE----- iQEcBAABCAAGBQJambvzAAoJEED/6hsPKofo9HwH/2il8xNSLIYf9pJtxZo/puyQ ZSwByGdeLKBZ1GP1dhdZ8kMk3eBoci0a/sQJmhDiEG6GDf1Mrgri/xj3p60sWwXT iReG+ZhBKg4QMj/IgOJQrh+53JT73QQP14wIhzc/DSi0Fo0ziqDA/lINxqMKc7oF b5qratjsb4xF1db4d1g8Ii1VRk64UoBEVpEoP37OOyAu1rgXgDr+9C832KkP0rb+ pVYT8hLFiaYiwVN+WN52/NrIkqBlMvMp3ouRtMAajCQ9OznnraDJE6eTkPGDSDBM RizSuQbev5R7pcmzCAP9/XKfTbeSUZQei2ZFXQXAOvIXMrQd/ITjbPvnObsceSE= =wtQd -----END PGP SIGNATURE----- Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm Pull KVM fixes from Radim Krčmář: "x86: - fix NULL dereference when using userspace lapic - optimize spectre v1 mitigations by allowing guests to use LFENCE - make microcode revision configurable to prevent guests from unnecessarily blacklisting spectre v2 mitigation feature" * tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: KVM: x86: fix vcpu initialization with userspace lapic KVM: X86: Allow userspace to define the microcode version KVM: X86: Introduce kvm_get_msr_feature() KVM: SVM: Add MSR-based feature support for serializing LFENCE KVM: x86: Add a framework for supporting MSR-based features
This commit is contained in:
commit
03a6c2592f
@ -123,14 +123,15 @@ memory layout to fit in user mode), check KVM_CAP_MIPS_VZ and use the
|
|||||||
flag KVM_VM_MIPS_VZ.
|
flag KVM_VM_MIPS_VZ.
|
||||||
|
|
||||||
|
|
||||||
4.3 KVM_GET_MSR_INDEX_LIST
|
4.3 KVM_GET_MSR_INDEX_LIST, KVM_GET_MSR_FEATURE_INDEX_LIST
|
||||||
|
|
||||||
Capability: basic
|
Capability: basic, KVM_CAP_GET_MSR_FEATURES for KVM_GET_MSR_FEATURE_INDEX_LIST
|
||||||
Architectures: x86
|
Architectures: x86
|
||||||
Type: system
|
Type: system ioctl
|
||||||
Parameters: struct kvm_msr_list (in/out)
|
Parameters: struct kvm_msr_list (in/out)
|
||||||
Returns: 0 on success; -1 on error
|
Returns: 0 on success; -1 on error
|
||||||
Errors:
|
Errors:
|
||||||
|
EFAULT: the msr index list cannot be read from or written to
|
||||||
E2BIG: the msr index list is to be to fit in the array specified by
|
E2BIG: the msr index list is to be to fit in the array specified by
|
||||||
the user.
|
the user.
|
||||||
|
|
||||||
@ -139,16 +140,23 @@ struct kvm_msr_list {
|
|||||||
__u32 indices[0];
|
__u32 indices[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
This ioctl returns the guest msrs that are supported. The list varies
|
The user fills in the size of the indices array in nmsrs, and in return
|
||||||
by kvm version and host processor, but does not change otherwise. The
|
kvm adjusts nmsrs to reflect the actual number of msrs and fills in the
|
||||||
user fills in the size of the indices array in nmsrs, and in return
|
indices array with their numbers.
|
||||||
kvm adjusts nmsrs to reflect the actual number of msrs and fills in
|
|
||||||
the indices array with their numbers.
|
KVM_GET_MSR_INDEX_LIST returns the guest msrs that are supported. The list
|
||||||
|
varies by kvm version and host processor, but does not change otherwise.
|
||||||
|
|
||||||
Note: if kvm indicates supports MCE (KVM_CAP_MCE), then the MCE bank MSRs are
|
Note: if kvm indicates supports MCE (KVM_CAP_MCE), then the MCE bank MSRs are
|
||||||
not returned in the MSR list, as different vcpus can have a different number
|
not returned in the MSR list, as different vcpus can have a different number
|
||||||
of banks, as set via the KVM_X86_SETUP_MCE ioctl.
|
of banks, as set via the KVM_X86_SETUP_MCE ioctl.
|
||||||
|
|
||||||
|
KVM_GET_MSR_FEATURE_INDEX_LIST returns the list of MSRs that can be passed
|
||||||
|
to the KVM_GET_MSRS system ioctl. This lets userspace probe host capabilities
|
||||||
|
and processor features that are exposed via MSRs (e.g., VMX capabilities).
|
||||||
|
This list also varies by kvm version and host processor, but does not change
|
||||||
|
otherwise.
|
||||||
|
|
||||||
|
|
||||||
4.4 KVM_CHECK_EXTENSION
|
4.4 KVM_CHECK_EXTENSION
|
||||||
|
|
||||||
@ -475,14 +483,22 @@ Support for this has been removed. Use KVM_SET_GUEST_DEBUG instead.
|
|||||||
|
|
||||||
4.18 KVM_GET_MSRS
|
4.18 KVM_GET_MSRS
|
||||||
|
|
||||||
Capability: basic
|
Capability: basic (vcpu), KVM_CAP_GET_MSR_FEATURES (system)
|
||||||
Architectures: x86
|
Architectures: x86
|
||||||
Type: vcpu ioctl
|
Type: system ioctl, vcpu ioctl
|
||||||
Parameters: struct kvm_msrs (in/out)
|
Parameters: struct kvm_msrs (in/out)
|
||||||
Returns: 0 on success, -1 on error
|
Returns: number of msrs successfully returned;
|
||||||
|
-1 on error
|
||||||
|
|
||||||
|
When used as a system ioctl:
|
||||||
|
Reads the values of MSR-based features that are available for the VM. This
|
||||||
|
is similar to KVM_GET_SUPPORTED_CPUID, but it returns MSR indices and values.
|
||||||
|
The list of msr-based features can be obtained using KVM_GET_MSR_FEATURE_INDEX_LIST
|
||||||
|
in a system ioctl.
|
||||||
|
|
||||||
|
When used as a vcpu ioctl:
|
||||||
Reads model-specific registers from the vcpu. Supported msr indices can
|
Reads model-specific registers from the vcpu. Supported msr indices can
|
||||||
be obtained using KVM_GET_MSR_INDEX_LIST.
|
be obtained using KVM_GET_MSR_INDEX_LIST in a system ioctl.
|
||||||
|
|
||||||
struct kvm_msrs {
|
struct kvm_msrs {
|
||||||
__u32 nmsrs; /* number of msrs in entries */
|
__u32 nmsrs; /* number of msrs in entries */
|
||||||
|
@ -507,6 +507,7 @@ struct kvm_vcpu_arch {
|
|||||||
u64 smi_count;
|
u64 smi_count;
|
||||||
bool tpr_access_reporting;
|
bool tpr_access_reporting;
|
||||||
u64 ia32_xss;
|
u64 ia32_xss;
|
||||||
|
u64 microcode_version;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Paging state of the vcpu
|
* Paging state of the vcpu
|
||||||
@ -1095,6 +1096,8 @@ struct kvm_x86_ops {
|
|||||||
int (*mem_enc_op)(struct kvm *kvm, void __user *argp);
|
int (*mem_enc_op)(struct kvm *kvm, void __user *argp);
|
||||||
int (*mem_enc_reg_region)(struct kvm *kvm, struct kvm_enc_region *argp);
|
int (*mem_enc_reg_region)(struct kvm *kvm, struct kvm_enc_region *argp);
|
||||||
int (*mem_enc_unreg_region)(struct kvm *kvm, struct kvm_enc_region *argp);
|
int (*mem_enc_unreg_region)(struct kvm *kvm, struct kvm_enc_region *argp);
|
||||||
|
|
||||||
|
int (*get_msr_feature)(struct kvm_msr_entry *entry);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct kvm_arch_async_pf {
|
struct kvm_arch_async_pf {
|
||||||
|
@ -2002,14 +2002,13 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
|
|||||||
|
|
||||||
void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event)
|
void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event)
|
||||||
{
|
{
|
||||||
struct kvm_lapic *apic;
|
struct kvm_lapic *apic = vcpu->arch.apic;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
apic_debug("%s\n", __func__);
|
if (!apic)
|
||||||
|
return;
|
||||||
|
|
||||||
ASSERT(vcpu);
|
apic_debug("%s\n", __func__);
|
||||||
apic = vcpu->arch.apic;
|
|
||||||
ASSERT(apic != NULL);
|
|
||||||
|
|
||||||
/* Stop the timer in case it's a reset to an active apic */
|
/* Stop the timer in case it's a reset to an active apic */
|
||||||
hrtimer_cancel(&apic->lapic_timer.timer);
|
hrtimer_cancel(&apic->lapic_timer.timer);
|
||||||
@ -2568,7 +2567,6 @@ void kvm_apic_accept_events(struct kvm_vcpu *vcpu)
|
|||||||
|
|
||||||
pe = xchg(&apic->pending_events, 0);
|
pe = xchg(&apic->pending_events, 0);
|
||||||
if (test_bit(KVM_APIC_INIT, &pe)) {
|
if (test_bit(KVM_APIC_INIT, &pe)) {
|
||||||
kvm_lapic_reset(vcpu, true);
|
|
||||||
kvm_vcpu_reset(vcpu, true);
|
kvm_vcpu_reset(vcpu, true);
|
||||||
if (kvm_vcpu_is_bsp(apic->vcpu))
|
if (kvm_vcpu_is_bsp(apic->vcpu))
|
||||||
vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
|
vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
|
||||||
|
@ -179,6 +179,8 @@ struct vcpu_svm {
|
|||||||
uint64_t sysenter_eip;
|
uint64_t sysenter_eip;
|
||||||
uint64_t tsc_aux;
|
uint64_t tsc_aux;
|
||||||
|
|
||||||
|
u64 msr_decfg;
|
||||||
|
|
||||||
u64 next_rip;
|
u64 next_rip;
|
||||||
|
|
||||||
u64 host_user_msrs[NR_HOST_SAVE_USER_MSRS];
|
u64 host_user_msrs[NR_HOST_SAVE_USER_MSRS];
|
||||||
@ -1906,6 +1908,7 @@ static void svm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
|
|||||||
u32 dummy;
|
u32 dummy;
|
||||||
u32 eax = 1;
|
u32 eax = 1;
|
||||||
|
|
||||||
|
vcpu->arch.microcode_version = 0x01000065;
|
||||||
svm->spec_ctrl = 0;
|
svm->spec_ctrl = 0;
|
||||||
|
|
||||||
if (!init_event) {
|
if (!init_event) {
|
||||||
@ -3870,6 +3873,22 @@ static int cr8_write_interception(struct vcpu_svm *svm)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int svm_get_msr_feature(struct kvm_msr_entry *msr)
|
||||||
|
{
|
||||||
|
msr->data = 0;
|
||||||
|
|
||||||
|
switch (msr->index) {
|
||||||
|
case MSR_F10H_DECFG:
|
||||||
|
if (boot_cpu_has(X86_FEATURE_LFENCE_RDTSC))
|
||||||
|
msr->data |= MSR_F10H_DECFG_LFENCE_SERIALIZE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
||||||
{
|
{
|
||||||
struct vcpu_svm *svm = to_svm(vcpu);
|
struct vcpu_svm *svm = to_svm(vcpu);
|
||||||
@ -3945,9 +3964,6 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
|||||||
|
|
||||||
msr_info->data = svm->spec_ctrl;
|
msr_info->data = svm->spec_ctrl;
|
||||||
break;
|
break;
|
||||||
case MSR_IA32_UCODE_REV:
|
|
||||||
msr_info->data = 0x01000065;
|
|
||||||
break;
|
|
||||||
case MSR_F15H_IC_CFG: {
|
case MSR_F15H_IC_CFG: {
|
||||||
|
|
||||||
int family, model;
|
int family, model;
|
||||||
@ -3965,6 +3981,9 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
|||||||
msr_info->data = 0x1E;
|
msr_info->data = 0x1E;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case MSR_F10H_DECFG:
|
||||||
|
msr_info->data = svm->msr_decfg;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return kvm_get_msr_common(vcpu, msr_info);
|
return kvm_get_msr_common(vcpu, msr_info);
|
||||||
}
|
}
|
||||||
@ -4143,6 +4162,24 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
|
|||||||
case MSR_VM_IGNNE:
|
case MSR_VM_IGNNE:
|
||||||
vcpu_unimpl(vcpu, "unimplemented wrmsr: 0x%x data 0x%llx\n", ecx, data);
|
vcpu_unimpl(vcpu, "unimplemented wrmsr: 0x%x data 0x%llx\n", ecx, data);
|
||||||
break;
|
break;
|
||||||
|
case MSR_F10H_DECFG: {
|
||||||
|
struct kvm_msr_entry msr_entry;
|
||||||
|
|
||||||
|
msr_entry.index = msr->index;
|
||||||
|
if (svm_get_msr_feature(&msr_entry))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Check the supported bits */
|
||||||
|
if (data & ~msr_entry.data)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Don't allow the guest to change a bit, #GP */
|
||||||
|
if (!msr->host_initiated && (data ^ msr_entry.data))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
svm->msr_decfg = data;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case MSR_IA32_APICBASE:
|
case MSR_IA32_APICBASE:
|
||||||
if (kvm_vcpu_apicv_active(vcpu))
|
if (kvm_vcpu_apicv_active(vcpu))
|
||||||
avic_update_vapic_bar(to_svm(vcpu), data);
|
avic_update_vapic_bar(to_svm(vcpu), data);
|
||||||
@ -6833,6 +6870,7 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
|
|||||||
.vcpu_unblocking = svm_vcpu_unblocking,
|
.vcpu_unblocking = svm_vcpu_unblocking,
|
||||||
|
|
||||||
.update_bp_intercept = update_bp_intercept,
|
.update_bp_intercept = update_bp_intercept,
|
||||||
|
.get_msr_feature = svm_get_msr_feature,
|
||||||
.get_msr = svm_get_msr,
|
.get_msr = svm_get_msr,
|
||||||
.set_msr = svm_set_msr,
|
.set_msr = svm_set_msr,
|
||||||
.get_segment_base = svm_get_segment_base,
|
.get_segment_base = svm_get_segment_base,
|
||||||
|
@ -3227,6 +3227,11 @@ static inline bool vmx_feature_control_msr_valid(struct kvm_vcpu *vcpu,
|
|||||||
return !(val & ~valid_bits);
|
return !(val & ~valid_bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int vmx_get_msr_feature(struct kvm_msr_entry *msr)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reads an msr value (of 'msr_index') into 'pdata'.
|
* Reads an msr value (of 'msr_index') into 'pdata'.
|
||||||
* Returns 0 on success, non-0 otherwise.
|
* Returns 0 on success, non-0 otherwise.
|
||||||
@ -5767,6 +5772,7 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
|
|||||||
vmx->rmode.vm86_active = 0;
|
vmx->rmode.vm86_active = 0;
|
||||||
vmx->spec_ctrl = 0;
|
vmx->spec_ctrl = 0;
|
||||||
|
|
||||||
|
vcpu->arch.microcode_version = 0x100000000ULL;
|
||||||
vmx->vcpu.arch.regs[VCPU_REGS_RDX] = get_rdx_init_val();
|
vmx->vcpu.arch.regs[VCPU_REGS_RDX] = get_rdx_init_val();
|
||||||
kvm_set_cr8(vcpu, 0);
|
kvm_set_cr8(vcpu, 0);
|
||||||
|
|
||||||
@ -12297,6 +12303,7 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {
|
|||||||
.vcpu_put = vmx_vcpu_put,
|
.vcpu_put = vmx_vcpu_put,
|
||||||
|
|
||||||
.update_bp_intercept = update_exception_bitmap,
|
.update_bp_intercept = update_exception_bitmap,
|
||||||
|
.get_msr_feature = vmx_get_msr_feature,
|
||||||
.get_msr = vmx_get_msr,
|
.get_msr = vmx_get_msr,
|
||||||
.set_msr = vmx_set_msr,
|
.set_msr = vmx_set_msr,
|
||||||
.get_segment_base = vmx_get_segment_base,
|
.get_segment_base = vmx_get_segment_base,
|
||||||
|
@ -1049,6 +1049,45 @@ static u32 emulated_msrs[] = {
|
|||||||
|
|
||||||
static unsigned num_emulated_msrs;
|
static unsigned num_emulated_msrs;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List of msr numbers which are used to expose MSR-based features that
|
||||||
|
* can be used by a hypervisor to validate requested CPU features.
|
||||||
|
*/
|
||||||
|
static u32 msr_based_features[] = {
|
||||||
|
MSR_F10H_DECFG,
|
||||||
|
MSR_IA32_UCODE_REV,
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned int num_msr_based_features;
|
||||||
|
|
||||||
|
static int kvm_get_msr_feature(struct kvm_msr_entry *msr)
|
||||||
|
{
|
||||||
|
switch (msr->index) {
|
||||||
|
case MSR_IA32_UCODE_REV:
|
||||||
|
rdmsrl(msr->index, msr->data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (kvm_x86_ops->get_msr_feature(msr))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int do_get_msr_feature(struct kvm_vcpu *vcpu, unsigned index, u64 *data)
|
||||||
|
{
|
||||||
|
struct kvm_msr_entry msr;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
msr.index = index;
|
||||||
|
r = kvm_get_msr_feature(&msr);
|
||||||
|
if (r)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
*data = msr.data;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool kvm_valid_efer(struct kvm_vcpu *vcpu, u64 efer)
|
bool kvm_valid_efer(struct kvm_vcpu *vcpu, u64 efer)
|
||||||
{
|
{
|
||||||
if (efer & efer_reserved_bits)
|
if (efer & efer_reserved_bits)
|
||||||
@ -2222,7 +2261,6 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
|||||||
|
|
||||||
switch (msr) {
|
switch (msr) {
|
||||||
case MSR_AMD64_NB_CFG:
|
case MSR_AMD64_NB_CFG:
|
||||||
case MSR_IA32_UCODE_REV:
|
|
||||||
case MSR_IA32_UCODE_WRITE:
|
case MSR_IA32_UCODE_WRITE:
|
||||||
case MSR_VM_HSAVE_PA:
|
case MSR_VM_HSAVE_PA:
|
||||||
case MSR_AMD64_PATCH_LOADER:
|
case MSR_AMD64_PATCH_LOADER:
|
||||||
@ -2230,6 +2268,10 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
|||||||
case MSR_AMD64_DC_CFG:
|
case MSR_AMD64_DC_CFG:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MSR_IA32_UCODE_REV:
|
||||||
|
if (msr_info->host_initiated)
|
||||||
|
vcpu->arch.microcode_version = data;
|
||||||
|
break;
|
||||||
case MSR_EFER:
|
case MSR_EFER:
|
||||||
return set_efer(vcpu, data);
|
return set_efer(vcpu, data);
|
||||||
case MSR_K7_HWCR:
|
case MSR_K7_HWCR:
|
||||||
@ -2525,7 +2567,7 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
|||||||
msr_info->data = 0;
|
msr_info->data = 0;
|
||||||
break;
|
break;
|
||||||
case MSR_IA32_UCODE_REV:
|
case MSR_IA32_UCODE_REV:
|
||||||
msr_info->data = 0x100000000ULL;
|
msr_info->data = vcpu->arch.microcode_version;
|
||||||
break;
|
break;
|
||||||
case MSR_MTRRcap:
|
case MSR_MTRRcap:
|
||||||
case 0x200 ... 0x2ff:
|
case 0x200 ... 0x2ff:
|
||||||
@ -2680,13 +2722,11 @@ static int __msr_io(struct kvm_vcpu *vcpu, struct kvm_msrs *msrs,
|
|||||||
int (*do_msr)(struct kvm_vcpu *vcpu,
|
int (*do_msr)(struct kvm_vcpu *vcpu,
|
||||||
unsigned index, u64 *data))
|
unsigned index, u64 *data))
|
||||||
{
|
{
|
||||||
int i, idx;
|
int i;
|
||||||
|
|
||||||
idx = srcu_read_lock(&vcpu->kvm->srcu);
|
|
||||||
for (i = 0; i < msrs->nmsrs; ++i)
|
for (i = 0; i < msrs->nmsrs; ++i)
|
||||||
if (do_msr(vcpu, entries[i].index, &entries[i].data))
|
if (do_msr(vcpu, entries[i].index, &entries[i].data))
|
||||||
break;
|
break;
|
||||||
srcu_read_unlock(&vcpu->kvm->srcu, idx);
|
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
@ -2785,6 +2825,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
|
|||||||
case KVM_CAP_SET_BOOT_CPU_ID:
|
case KVM_CAP_SET_BOOT_CPU_ID:
|
||||||
case KVM_CAP_SPLIT_IRQCHIP:
|
case KVM_CAP_SPLIT_IRQCHIP:
|
||||||
case KVM_CAP_IMMEDIATE_EXIT:
|
case KVM_CAP_IMMEDIATE_EXIT:
|
||||||
|
case KVM_CAP_GET_MSR_FEATURES:
|
||||||
r = 1;
|
r = 1;
|
||||||
break;
|
break;
|
||||||
case KVM_CAP_ADJUST_CLOCK:
|
case KVM_CAP_ADJUST_CLOCK:
|
||||||
@ -2899,6 +2940,31 @@ long kvm_arch_dev_ioctl(struct file *filp,
|
|||||||
goto out;
|
goto out;
|
||||||
r = 0;
|
r = 0;
|
||||||
break;
|
break;
|
||||||
|
case KVM_GET_MSR_FEATURE_INDEX_LIST: {
|
||||||
|
struct kvm_msr_list __user *user_msr_list = argp;
|
||||||
|
struct kvm_msr_list msr_list;
|
||||||
|
unsigned int n;
|
||||||
|
|
||||||
|
r = -EFAULT;
|
||||||
|
if (copy_from_user(&msr_list, user_msr_list, sizeof(msr_list)))
|
||||||
|
goto out;
|
||||||
|
n = msr_list.nmsrs;
|
||||||
|
msr_list.nmsrs = num_msr_based_features;
|
||||||
|
if (copy_to_user(user_msr_list, &msr_list, sizeof(msr_list)))
|
||||||
|
goto out;
|
||||||
|
r = -E2BIG;
|
||||||
|
if (n < msr_list.nmsrs)
|
||||||
|
goto out;
|
||||||
|
r = -EFAULT;
|
||||||
|
if (copy_to_user(user_msr_list->indices, &msr_based_features,
|
||||||
|
num_msr_based_features * sizeof(u32)))
|
||||||
|
goto out;
|
||||||
|
r = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case KVM_GET_MSRS:
|
||||||
|
r = msr_io(NULL, argp, do_get_msr_feature, 1);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
r = -EINVAL;
|
r = -EINVAL;
|
||||||
@ -3636,12 +3702,18 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
|
|||||||
r = 0;
|
r = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case KVM_GET_MSRS:
|
case KVM_GET_MSRS: {
|
||||||
|
int idx = srcu_read_lock(&vcpu->kvm->srcu);
|
||||||
r = msr_io(vcpu, argp, do_get_msr, 1);
|
r = msr_io(vcpu, argp, do_get_msr, 1);
|
||||||
|
srcu_read_unlock(&vcpu->kvm->srcu, idx);
|
||||||
break;
|
break;
|
||||||
case KVM_SET_MSRS:
|
}
|
||||||
|
case KVM_SET_MSRS: {
|
||||||
|
int idx = srcu_read_lock(&vcpu->kvm->srcu);
|
||||||
r = msr_io(vcpu, argp, do_set_msr, 0);
|
r = msr_io(vcpu, argp, do_set_msr, 0);
|
||||||
|
srcu_read_unlock(&vcpu->kvm->srcu, idx);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case KVM_TPR_ACCESS_REPORTING: {
|
case KVM_TPR_ACCESS_REPORTING: {
|
||||||
struct kvm_tpr_access_ctl tac;
|
struct kvm_tpr_access_ctl tac;
|
||||||
|
|
||||||
@ -4464,6 +4536,19 @@ static void kvm_init_msr_list(void)
|
|||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
num_emulated_msrs = j;
|
num_emulated_msrs = j;
|
||||||
|
|
||||||
|
for (i = j = 0; i < ARRAY_SIZE(msr_based_features); i++) {
|
||||||
|
struct kvm_msr_entry msr;
|
||||||
|
|
||||||
|
msr.index = msr_based_features[i];
|
||||||
|
if (kvm_get_msr_feature(&msr))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (j < i)
|
||||||
|
msr_based_features[j] = msr_based_features[i];
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
num_msr_based_features = j;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vcpu_mmio_write(struct kvm_vcpu *vcpu, gpa_t addr, int len,
|
static int vcpu_mmio_write(struct kvm_vcpu *vcpu, gpa_t addr, int len,
|
||||||
@ -7975,7 +8060,6 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
|
|||||||
kvm_vcpu_mtrr_init(vcpu);
|
kvm_vcpu_mtrr_init(vcpu);
|
||||||
vcpu_load(vcpu);
|
vcpu_load(vcpu);
|
||||||
kvm_vcpu_reset(vcpu, false);
|
kvm_vcpu_reset(vcpu, false);
|
||||||
kvm_lapic_reset(vcpu, false);
|
|
||||||
kvm_mmu_setup(vcpu);
|
kvm_mmu_setup(vcpu);
|
||||||
vcpu_put(vcpu);
|
vcpu_put(vcpu);
|
||||||
return 0;
|
return 0;
|
||||||
@ -8018,6 +8102,8 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
|
|||||||
|
|
||||||
void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
|
void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
|
||||||
{
|
{
|
||||||
|
kvm_lapic_reset(vcpu, init_event);
|
||||||
|
|
||||||
vcpu->arch.hflags = 0;
|
vcpu->arch.hflags = 0;
|
||||||
|
|
||||||
vcpu->arch.smi_pending = 0;
|
vcpu->arch.smi_pending = 0;
|
||||||
|
@ -761,6 +761,7 @@ struct kvm_ppc_resize_hpt {
|
|||||||
#define KVM_TRACE_PAUSE __KVM_DEPRECATED_MAIN_0x07
|
#define KVM_TRACE_PAUSE __KVM_DEPRECATED_MAIN_0x07
|
||||||
#define KVM_TRACE_DISABLE __KVM_DEPRECATED_MAIN_0x08
|
#define KVM_TRACE_DISABLE __KVM_DEPRECATED_MAIN_0x08
|
||||||
#define KVM_GET_EMULATED_CPUID _IOWR(KVMIO, 0x09, struct kvm_cpuid2)
|
#define KVM_GET_EMULATED_CPUID _IOWR(KVMIO, 0x09, struct kvm_cpuid2)
|
||||||
|
#define KVM_GET_MSR_FEATURE_INDEX_LIST _IOWR(KVMIO, 0x0a, struct kvm_msr_list)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Extension capability list.
|
* Extension capability list.
|
||||||
@ -934,6 +935,7 @@ struct kvm_ppc_resize_hpt {
|
|||||||
#define KVM_CAP_S390_AIS_MIGRATION 150
|
#define KVM_CAP_S390_AIS_MIGRATION 150
|
||||||
#define KVM_CAP_PPC_GET_CPU_CHAR 151
|
#define KVM_CAP_PPC_GET_CPU_CHAR 151
|
||||||
#define KVM_CAP_S390_BPB 152
|
#define KVM_CAP_S390_BPB 152
|
||||||
|
#define KVM_CAP_GET_MSR_FEATURES 153
|
||||||
|
|
||||||
#ifdef KVM_CAP_IRQ_ROUTING
|
#ifdef KVM_CAP_IRQ_ROUTING
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user