A few simple fixes for ARM, x86, PPC and generic code. The x86 MMU fix
is a bit larger because the surrounding code needed a cleanup, but nothing worrisome. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQEcBAABAgAGBQJW4UwZAAoJEL/70l94x66DG3YH/0PfUr4sW0jnWRVXmYlPVka4 sNFYrdtYnx08PwXu2sWMm1F+OBXlF/t0ZSJXJ9OBF8WdKIu8TU4yBOINRAvGO/oE slrivjktLTKgicTtIXP5BpRR14ohwHIGcuiIlppxvnhmQz1/rMtig7fvhZxYI545 lJyIbyquNR86tiVdUSG9/T9+ulXXXCvOspYv8jPXZx7VKBXKTvp5P5qavSqciRb+ O9RqY+GDCR/5vrw+MV0J7H9ZydeEJeD02LcWguTGMATTm0RCrhydvSbou42UcKfY osWii0kwt2LhcM/sTOz+cWnLJ6gwU9T+ZtJTTbLvYWXWDLP/+icp9ACMkwNciNo= =/y4V -----END PGP SIGNATURE----- Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm Pull KVM fixes from Paolo Bonzini: "A few simple fixes for ARM, x86, PPC and generic code. The x86 MMU fix is a bit larger because the surrounding code needed a cleanup, but nothing worrisome" * tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: KVM: MMU: fix reserved bit check for ept=0/CR0.WP=0/CR4.SMEP=1/EFER.NX=0 KVM: MMU: fix ept=0/pte.u=1/pte.w=0/CR0.WP=0/CR4.SMEP=1/EFER.NX=0 combo kvm: cap halt polling at exactly halt_poll_ns KVM: s390: correct fprs on SIGP (STOP AND) STORE STATUS KVM: VMX: disable PEBS before a guest entry KVM: PPC: Book3S HV: Sanitize special-purpose register values on guest exit
This commit is contained in:
commit
f2c1242194
|
@ -358,7 +358,8 @@ In the first case there are two additional complications:
|
|||
- if CR4.SMEP is enabled: since we've turned the page into a kernel page,
|
||||
the kernel may now execute it. We handle this by also setting spte.nx.
|
||||
If we get a user fetch or read fault, we'll change spte.u=1 and
|
||||
spte.nx=gpte.nx back.
|
||||
spte.nx=gpte.nx back. For this to work, KVM forces EFER.NX to 1 when
|
||||
shadow paging is in use.
|
||||
- if CR4.SMAP is disabled: since the page has been changed to a kernel
|
||||
page, it can not be reused when CR4.SMAP is enabled. We set
|
||||
CR4.SMAP && !CR0.WP into shadow page's role to avoid this case. Note,
|
||||
|
|
|
@ -1370,6 +1370,20 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
|
|||
std r6, VCPU_ACOP(r9)
|
||||
stw r7, VCPU_GUEST_PID(r9)
|
||||
std r8, VCPU_WORT(r9)
|
||||
/*
|
||||
* Restore various registers to 0, where non-zero values
|
||||
* set by the guest could disrupt the host.
|
||||
*/
|
||||
li r0, 0
|
||||
mtspr SPRN_IAMR, r0
|
||||
mtspr SPRN_CIABR, r0
|
||||
mtspr SPRN_DAWRX, r0
|
||||
mtspr SPRN_TCSCR, r0
|
||||
mtspr SPRN_WORT, r0
|
||||
/* Set MMCRS to 1<<31 to freeze and disable the SPMC counters */
|
||||
li r0, 1
|
||||
sldi r0, r0, 31
|
||||
mtspr SPRN_MMCRS, r0
|
||||
8:
|
||||
|
||||
/* Save and reset AMR and UAMOR before turning on the MMU */
|
||||
|
|
|
@ -2381,7 +2381,7 @@ int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long gpa)
|
|||
|
||||
/* manually convert vector registers if necessary */
|
||||
if (MACHINE_HAS_VX) {
|
||||
convert_vx_to_fp(fprs, current->thread.fpu.vxrs);
|
||||
convert_vx_to_fp(fprs, (__vector128 *) vcpu->run->s.regs.vrs);
|
||||
rc = write_guest_abs(vcpu, gpa + __LC_FPREGS_SAVE_AREA,
|
||||
fprs, 128);
|
||||
} else {
|
||||
|
|
|
@ -3721,13 +3721,15 @@ static void reset_rsvds_bits_mask_ept(struct kvm_vcpu *vcpu,
|
|||
void
|
||||
reset_shadow_zero_bits_mask(struct kvm_vcpu *vcpu, struct kvm_mmu *context)
|
||||
{
|
||||
bool uses_nx = context->nx || context->base_role.smep_andnot_wp;
|
||||
|
||||
/*
|
||||
* Passing "true" to the last argument is okay; it adds a check
|
||||
* on bit 8 of the SPTEs which KVM doesn't use anyway.
|
||||
*/
|
||||
__reset_rsvds_bits_mask(vcpu, &context->shadow_zero_check,
|
||||
boot_cpu_data.x86_phys_bits,
|
||||
context->shadow_root_level, context->nx,
|
||||
context->shadow_root_level, uses_nx,
|
||||
guest_cpuid_has_gbpages(vcpu), is_pse(vcpu),
|
||||
true);
|
||||
}
|
||||
|
|
|
@ -1813,6 +1813,13 @@ static void add_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr,
|
|||
return;
|
||||
}
|
||||
break;
|
||||
case MSR_IA32_PEBS_ENABLE:
|
||||
/* PEBS needs a quiescent period after being disabled (to write
|
||||
* a record). Disabling PEBS through VMX MSR swapping doesn't
|
||||
* provide that period, so a CPU could write host's record into
|
||||
* guest's memory.
|
||||
*/
|
||||
wrmsrl(MSR_IA32_PEBS_ENABLE, 0);
|
||||
}
|
||||
|
||||
for (i = 0; i < m->nr; ++i)
|
||||
|
@ -1850,26 +1857,31 @@ static void reload_tss(void)
|
|||
|
||||
static bool update_transition_efer(struct vcpu_vmx *vmx, int efer_offset)
|
||||
{
|
||||
u64 guest_efer;
|
||||
u64 ignore_bits;
|
||||
u64 guest_efer = vmx->vcpu.arch.efer;
|
||||
u64 ignore_bits = 0;
|
||||
|
||||
guest_efer = vmx->vcpu.arch.efer;
|
||||
if (!enable_ept) {
|
||||
/*
|
||||
* NX is needed to handle CR0.WP=1, CR4.SMEP=1. Testing
|
||||
* host CPUID is more efficient than testing guest CPUID
|
||||
* or CR4. Host SMEP is anyway a requirement for guest SMEP.
|
||||
*/
|
||||
if (boot_cpu_has(X86_FEATURE_SMEP))
|
||||
guest_efer |= EFER_NX;
|
||||
else if (!(guest_efer & EFER_NX))
|
||||
ignore_bits |= EFER_NX;
|
||||
}
|
||||
|
||||
/*
|
||||
* NX is emulated; LMA and LME handled by hardware; SCE meaningless
|
||||
* outside long mode
|
||||
* LMA and LME handled by hardware; SCE meaningless outside long mode.
|
||||
*/
|
||||
ignore_bits = EFER_NX | EFER_SCE;
|
||||
ignore_bits |= EFER_SCE;
|
||||
#ifdef CONFIG_X86_64
|
||||
ignore_bits |= EFER_LMA | EFER_LME;
|
||||
/* SCE is meaningful only in long mode on Intel */
|
||||
if (guest_efer & EFER_LMA)
|
||||
ignore_bits &= ~(u64)EFER_SCE;
|
||||
#endif
|
||||
guest_efer &= ~ignore_bits;
|
||||
guest_efer |= host_efer & ignore_bits;
|
||||
vmx->guest_msrs[efer_offset].data = guest_efer;
|
||||
vmx->guest_msrs[efer_offset].mask = ~ignore_bits;
|
||||
|
||||
clear_atomic_switch_msr(vmx, MSR_EFER);
|
||||
|
||||
|
@ -1880,16 +1892,21 @@ static bool update_transition_efer(struct vcpu_vmx *vmx, int efer_offset)
|
|||
*/
|
||||
if (cpu_has_load_ia32_efer ||
|
||||
(enable_ept && ((vmx->vcpu.arch.efer ^ host_efer) & EFER_NX))) {
|
||||
guest_efer = vmx->vcpu.arch.efer;
|
||||
if (!(guest_efer & EFER_LMA))
|
||||
guest_efer &= ~EFER_LME;
|
||||
if (guest_efer != host_efer)
|
||||
add_atomic_switch_msr(vmx, MSR_EFER,
|
||||
guest_efer, host_efer);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
guest_efer &= ~ignore_bits;
|
||||
guest_efer |= host_efer & ignore_bits;
|
||||
|
||||
return true;
|
||||
vmx->guest_msrs[efer_offset].data = guest_efer;
|
||||
vmx->guest_msrs[efer_offset].mask = ~ignore_bits;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned long segment_base(u16 selector)
|
||||
|
|
|
@ -1952,6 +1952,9 @@ static void grow_halt_poll_ns(struct kvm_vcpu *vcpu)
|
|||
else
|
||||
val *= halt_poll_ns_grow;
|
||||
|
||||
if (val > halt_poll_ns)
|
||||
val = halt_poll_ns;
|
||||
|
||||
vcpu->halt_poll_ns = val;
|
||||
trace_kvm_halt_poll_ns_grow(vcpu->vcpu_id, val, old);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue