* 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@

Reply via email to