|
@@ -7494,6 +7494,29 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int idt_index,
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(kvm_task_switch);
|
|
EXPORT_SYMBOL_GPL(kvm_task_switch);
|
|
|
|
|
|
|
|
+int kvm_valid_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
|
|
|
|
+{
|
|
|
|
+ if ((sregs->efer & EFER_LME) && (sregs->cr0 & X86_CR0_PG_BIT)) {
|
|
|
|
+ /*
|
|
|
|
+ * When EFER.LME and CR0.PG are set, the processor is in
|
|
|
|
+ * 64-bit mode (though maybe in a 32-bit code segment).
|
|
|
|
+ * CR4.PAE and EFER.LMA must be set.
|
|
|
|
+ */
|
|
|
|
+ if (!(sregs->cr4 & X86_CR4_PAE_BIT)
|
|
|
|
+ || !(sregs->efer & EFER_LMA))
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ } else {
|
|
|
|
+ /*
|
|
|
|
+ * Not in 64-bit mode: EFER.LMA is clear and the code
|
|
|
|
+ * segment cannot be 64-bit.
|
|
|
|
+ */
|
|
|
|
+ if (sregs->efer & EFER_LMA || sregs->cs.l)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
|
|
int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
|
|
struct kvm_sregs *sregs)
|
|
struct kvm_sregs *sregs)
|
|
{
|
|
{
|
|
@@ -7506,6 +7529,9 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
|
|
(sregs->cr4 & X86_CR4_OSXSAVE))
|
|
(sregs->cr4 & X86_CR4_OSXSAVE))
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
+ if (kvm_valid_sregs(vcpu, sregs))
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
apic_base_msr.data = sregs->apic_base;
|
|
apic_base_msr.data = sregs->apic_base;
|
|
apic_base_msr.host_initiated = true;
|
|
apic_base_msr.host_initiated = true;
|
|
if (kvm_set_apic_base(vcpu, &apic_base_msr))
|
|
if (kvm_set_apic_base(vcpu, &apic_base_msr))
|