mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-19 19:17:48 +07:00
KVM: x86: Remove emulator's broken checks on CR0/CR3/CR4 loads
commit d0fe7b6404408835ed60232cb3bf28324b2f95db upstream.
Remove the emulator's checks for illegal CR0, CR3, and CR4 values, as
the checks are redundant, outdated, and in the case of SEV's C-bit,
broken. The emulator manually calculates MAXPHYADDR from CPUID and
neglects to mask off the C-bit. For all other checks, kvm_set_cr*() are
a superset of the emulator checks, e.g. see CR4.LA57.
Fixes: a780a3ea62
("KVM: X86: Fix reserved bits check for MOV to CR3")
Cc: Babu Moger <babu.moger@amd.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
Message-Id: <20210422022128.3464144-2-seanjc@google.com>
Cc: stable@vger.kernel.org
[Unify check_cr_read and check_cr_write. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
c8b49e01a2
commit
f59c2220f6
@ -4220,7 +4220,7 @@ static bool valid_cr(int nr)
|
||||
}
|
||||
}
|
||||
|
||||
static int check_cr_read(struct x86_emulate_ctxt *ctxt)
|
||||
static int check_cr_access(struct x86_emulate_ctxt *ctxt)
|
||||
{
|
||||
if (!valid_cr(ctxt->modrm_reg))
|
||||
return emulate_ud(ctxt);
|
||||
@ -4228,80 +4228,6 @@ static int check_cr_read(struct x86_emulate_ctxt *ctxt)
|
||||
return X86EMUL_CONTINUE;
|
||||
}
|
||||
|
||||
static int check_cr_write(struct x86_emulate_ctxt *ctxt)
|
||||
{
|
||||
u64 new_val = ctxt->src.val64;
|
||||
int cr = ctxt->modrm_reg;
|
||||
u64 efer = 0;
|
||||
|
||||
static u64 cr_reserved_bits[] = {
|
||||
0xffffffff00000000ULL,
|
||||
0, 0, 0, /* CR3 checked later */
|
||||
CR4_RESERVED_BITS,
|
||||
0, 0, 0,
|
||||
CR8_RESERVED_BITS,
|
||||
};
|
||||
|
||||
if (!valid_cr(cr))
|
||||
return emulate_ud(ctxt);
|
||||
|
||||
if (new_val & cr_reserved_bits[cr])
|
||||
return emulate_gp(ctxt, 0);
|
||||
|
||||
switch (cr) {
|
||||
case 0: {
|
||||
u64 cr4;
|
||||
if (((new_val & X86_CR0_PG) && !(new_val & X86_CR0_PE)) ||
|
||||
((new_val & X86_CR0_NW) && !(new_val & X86_CR0_CD)))
|
||||
return emulate_gp(ctxt, 0);
|
||||
|
||||
cr4 = ctxt->ops->get_cr(ctxt, 4);
|
||||
ctxt->ops->get_msr(ctxt, MSR_EFER, &efer);
|
||||
|
||||
if ((new_val & X86_CR0_PG) && (efer & EFER_LME) &&
|
||||
!(cr4 & X86_CR4_PAE))
|
||||
return emulate_gp(ctxt, 0);
|
||||
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
u64 rsvd = 0;
|
||||
|
||||
ctxt->ops->get_msr(ctxt, MSR_EFER, &efer);
|
||||
if (efer & EFER_LMA) {
|
||||
u64 maxphyaddr;
|
||||
u32 eax, ebx, ecx, edx;
|
||||
|
||||
eax = 0x80000008;
|
||||
ecx = 0;
|
||||
if (ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx,
|
||||
&edx, true))
|
||||
maxphyaddr = eax & 0xff;
|
||||
else
|
||||
maxphyaddr = 36;
|
||||
rsvd = rsvd_bits(maxphyaddr, 63);
|
||||
if (ctxt->ops->get_cr(ctxt, 4) & X86_CR4_PCIDE)
|
||||
rsvd &= ~X86_CR3_PCID_NOFLUSH;
|
||||
}
|
||||
|
||||
if (new_val & rsvd)
|
||||
return emulate_gp(ctxt, 0);
|
||||
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
ctxt->ops->get_msr(ctxt, MSR_EFER, &efer);
|
||||
|
||||
if ((efer & EFER_LMA) && !(new_val & X86_CR4_PAE))
|
||||
return emulate_gp(ctxt, 0);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return X86EMUL_CONTINUE;
|
||||
}
|
||||
|
||||
static int check_dr7_gd(struct x86_emulate_ctxt *ctxt)
|
||||
{
|
||||
unsigned long dr7;
|
||||
@ -4841,10 +4767,10 @@ static const struct opcode twobyte_table[256] = {
|
||||
D(ImplicitOps | ModRM | SrcMem | NoAccess), /* 8 * reserved NOP */
|
||||
D(ImplicitOps | ModRM | SrcMem | NoAccess), /* NOP + 7 * reserved NOP */
|
||||
/* 0x20 - 0x2F */
|
||||
DIP(ModRM | DstMem | Priv | Op3264 | NoMod, cr_read, check_cr_read),
|
||||
DIP(ModRM | DstMem | Priv | Op3264 | NoMod, cr_read, check_cr_access),
|
||||
DIP(ModRM | DstMem | Priv | Op3264 | NoMod, dr_read, check_dr_read),
|
||||
IIP(ModRM | SrcMem | Priv | Op3264 | NoMod, em_cr_write, cr_write,
|
||||
check_cr_write),
|
||||
check_cr_access),
|
||||
IIP(ModRM | SrcMem | Priv | Op3264 | NoMod, em_dr_write, dr_write,
|
||||
check_dr_write),
|
||||
N, N, N, N,
|
||||
|
Loading…
Reference in New Issue
Block a user