1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-23 11:18:54 +00:00

Follow-up commit to fix CR0 issues. Maintain

architectural state on CR vmexits by guaranteeing
that EFER, CR0 and the VMCS entry controls are
all in sync when transitioning to IA-32e mode.

Submitted by:	Tycho Nightingale (tycho.nightingale <at> plurisbusnetworks.com)
This commit is contained in:
Peter Grehan 2013-08-03 03:16:42 +00:00
parent 1e53269ac2
commit 80a902ef7d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=253909

View File

@ -1084,7 +1084,7 @@ static int
vmx_emulate_cr_access(struct vmx *vmx, int vcpu, uint64_t exitqual)
{
int error, cr, vmcs_guest_cr, vmcs_shadow_cr;
uint64_t regval, ones_mask, zeros_mask;
uint64_t crval, regval, ones_mask, zeros_mask;
const struct vmxctx *vmxctx;
/* We only handle mov to %cr0 or %cr4 at this time */
@ -1174,14 +1174,48 @@ vmx_emulate_cr_access(struct vmx *vmx, int vcpu, uint64_t exitqual)
error, cr);
}
regval |= ones_mask;
regval &= ~zeros_mask;
error = vmwrite(vmcs_guest_cr, regval);
crval = regval | ones_mask;
crval &= ~zeros_mask;
error = vmwrite(vmcs_guest_cr, crval);
if (error) {
panic("vmx_emulate_cr_access: error %d writing cr%d",
error, cr);
}
if (cr == 0 && regval & CR0_PG) {
uint64_t efer, entry_ctls;
/*
* If CR0.PG is 1 and EFER.LME is 1 then EFER.LMA and
* the "IA-32e mode guest" bit in VM-entry control must be
* equal.
*/
error = vmread(VMCS_GUEST_IA32_EFER, &efer);
if (error) {
panic("vmx_emulate_cr_access: error %d efer read",
error);
}
if (efer & EFER_LME) {
efer |= EFER_LMA;
error = vmwrite(VMCS_GUEST_IA32_EFER, efer);
if (error) {
panic("vmx_emulate_cr_access: error %d"
" efer write", error);
}
error = vmread(VMCS_ENTRY_CTLS, &entry_ctls);
if (error) {
panic("vmx_emulate_cr_access: error %d"
" entry ctls read", error);
}
entry_ctls |= VM_ENTRY_GUEST_LMA;
error = vmwrite(VMCS_ENTRY_CTLS, entry_ctls);
if (error) {
panic("vmx_emulate_cr_access: error %d"
" entry ctls write", error);
}
}
}
return (HANDLED);
}