* Adam Steen <[email protected]> [2020-02-18 04:56:57 +0000]:
Hi
Please see the patch below to handle invalid writes to cr0 as per the
Intel SDM Volume 3.
The 3 cases i am handling with this change are
1. CR0.PG: Setting the PG flag when the PE flag is clear causes a
general-protection exception (#GP). (Intel SDM Volume 3abcd page 76, Section
2.5 Control Registers)
2. CR0.CD and CR0.NW, CD: 0 and NW: 1 Invalid setting. Generates a
general-protection exception (#GP) with an error code of 0.
(Intel SDM Volume 3abcd page 438, Table 11-5. Cache Operating Modes,
via Intel SDM Volume 3abcd page 76, See also comment from CR0.CD
3. Bits 63:32 of CR0 and CR4 are reserved and must be written with zeros.
Writing a nonzero value to any of the upper 32 bits results in a
general-protection exception, #GP(0). (Intel SDM Volume 3abcd page
75, 2.5 Control Registers, Paragraph 2, bullet point 2.
Cheers
Adam
? div
Index: sys/arch/amd64/amd64/vmm.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/amd64/vmm.c,v
retrieving revision 1.262
diff -u -p -u -p -r1.262 vmm.c
--- sys/arch/amd64/amd64/vmm.c 17 Feb 2020 18:16:10 -0000 1.262
+++ sys/arch/amd64/amd64/vmm.c 18 Feb 2020 02:59:53 -0000
@@ -5685,6 +5685,33 @@ vmx_handle_cr0_write(struct vcpu *vcpu,
return (EINVAL);
}
+ /* 2.5 CONTROL REGISTERS CR0.PG */
+ if ((r & CR0_PG) && (r & CR0_PE) == 0) {
+ DPRINTF("%s: PG flag set when the PE flag is clear,"
+ " inject #GP, cr0=0x%llx\n", __func__, r);
+ vmm_inject_gp(vcpu);
+ return (0);
+ }
+
+ /*
+ * 11.5.1 Cache Control Registers and Bits
+ * Table 11-5. Cache Operating Modes
+ */
+ if ((r & CR0_NW) && (r & CR0_CD) == 0) {
+ DPRINTF("%s: NW flag set when the CD flag is clear,"
+ " inject #GP, cr0=0x%llx\n", __func__, r);
+ vmm_inject_gp(vcpu);
+ return (0);
+ }
+
+ /* 2.5 CONTROL REGISTERS */
+ if (r & 0xFFFFFFFF00000000ULL) {
+ DPRINTF("%s: setting bits 63:32 of %%cr0 is invalid,"
+ " inject #GP, cr0=0x%llx\n", __func__, r);
+ vmm_inject_gp(vcpu);
+ return (0);
+ }
+
/* CR0 must always have NE set */
r |= CR0_NE;
Looks good!
ok pd@