Index: vmm/core/constants.h
===================================================================
--- vmm/core/constants.h	(リビジョン 153)
+++ vmm/core/constants.h	(作業コピー)
@@ -238,6 +238,7 @@
 #define VMCS_GUEST_GS_ACCESS_RIGHTS	0x481E
 #define VMCS_GUEST_LDTR_ACCESS_RIGHTS	0x4820
 #define VMCS_GUEST_TR_ACCESS_RIGHTS	0x4822
+#define VMCS_GUEST_ACCESS_RIGHTS_UNUSABLE	0x10000
 #define VMCS_GUEST_INTERRUPTIBILITY_STATE	0x4824
 #define VMCS_GUEST_ACTIVITY_STATE	0x4826
 #define VMCS_GUEST_SMBASE		0x4828
@@ -604,6 +605,7 @@
 #define CR4_OSFXSR_BIT			0x200
 #define CR4_OSXMMEXCPT_BIT		0x400
 #define CR4_VMXE_BIT			0x2000
+#define CR4_PCIDE_BIT			0x20000
 #define CR4_OSXSAVE_BIT			0x40000
 #define CR4_SMEP_BIT			0x100000
 
Index: vmm/core/vt_main.c
===================================================================
--- vmm/core/vt_main.c	(リビジョン 153)
+++ vmm/core/vt_main.c	(作業コピー)
@@ -332,11 +332,362 @@
 	return VT_VMEXIT;
 }
 
+#define CHECK_VMCS_1(reg_name, bitmask)				\
+do {								\
+	ulong reg_val;						\
+	asm_vmread((reg_name), &reg_val);			\
+	if ((reg_val & (bitmask)) != (bitmask)) {		\
+		printf("%s 0x%lx (0x%lx must be 1)\n",		\
+		       #reg_name, (reg_val), (ulong)(bitmask));	\
+	}							\
+} while(0)
+
+#define CHECK_VMCS_0(reg_name, bitmask)				\
+do {								\
+	ulong reg_val;						\
+	asm_vmread((reg_name), &reg_val);			\
+	if ((reg_val & (bitmask)) != 0) {		\
+		printf("%s 0x%lx (0x%lx must be 0)\n",		\
+		       #reg_name, reg_val, (ulong)(bitmask));	\
+	}							\
+} while(0)
+
+#define CHECK_VMCS_VIRTUAL_8086_SEG(sel, base, limit, access)	\
+do {								\
+	ulong reg_val, reg_val2;				\
+	asm_vmread((sel), &reg_val);				\
+	asm_vmread((base), &reg_val2);				\
+	if ((reg_val << 4) != reg_val2) {			\
+		printf("%s %lx, %s %lx\n",			\
+		       #sel, reg_val, #base, reg_val2);		\
+	}							\
+	asm_vmread((limit), &reg_val);				\
+	if (reg_val != 0xffff) {				\
+		printf("%s %lx must be 0xffff\n",		\
+		       #limit, reg_val);			\
+	}							\
+	asm_vmread((access), &reg_val);				\
+	if (reg_val != 0xf3) {					\
+		printf("%s %lx must be 0xf3\n",			\
+		       #access, reg_val);			\
+	}							\
+} while(0)
+
+#define CHECK_VMCS_SEG_COMMON(sel, base, limit, access)		\
+do {								\
+	ulong reg_val, reg_val2;				\
+	asm_vmread((access), &reg_val);				\
+	if((reg_val & VMCS_GUEST_ACCESS_RIGHTS_UNUSABLE) == 0) {	\
+		if ((reg_val & 0x80) != 0x80) {			\
+			printf("Bit 7(P) of %s 0x%lx must be 1\n",	\
+			       #access, reg_val);		\
+		}						\
+		if ((reg_val & 0xffff0f00) != 0) {			\
+			printf("Reserved fields of %s 0x%lx must be 0\n", \
+			       #access, reg_val);		\
+		}						\
+		asm_vmread((limit), &reg_val2);			\
+		if (((reg_val2 & 0xfff) < 0xffff)		\
+		    && (reg_val & 0x8000) != 0) {		\
+			printf("Bit 15(G) of %s 0x%lx must be 0. "	\
+			       "limit 0x%lx\n",			\
+			       #access, reg_val, reg_val2);	\
+		}						\
+		if (((reg_val2 & 0xfff00000) >= 0x100000)	\
+		    && (reg_val & 0x8000) != 0x8000) {		\
+			printf("Bit 15(G) of %s 0x%lx must be 1. "	\
+			       "limit 0x%lx\n",			\
+			       #access, reg_val, reg_val2);	\
+		}						\
+	}							\
+} while(0)
+
+#define CHECK_VMCS_SEG(sel, base, limit, access)		\
+do {								\
+	ulong reg_val;						\
+	ulong reg_val2;						\
+	asm_vmread((access), &reg_val);				\
+	if((reg_val & VMCS_GUEST_ACCESS_RIGHTS_UNUSABLE) == 0) {	\
+		if ((reg_val & 0x1) != 0x1) {			\
+			printf("Bit 0 of %s 0x%lx must be 1\n",	\
+			       #access, reg_val);		\
+		}						\
+		if ((reg_val & 0x8) == 0x8 && (reg_val & 0x2) != 0x2) {	\
+			printf("If bit 3 is 1, bit 1 of %s 0x%lx must be 1\n", \
+			       #access, reg_val);		\
+		}						\
+		if ((reg_val & 0x10) != 0x10) {			\
+			printf("Bit 4(S) of %s 0x%lx must be 1\n",	\
+			       #access, reg_val);		\
+		}						\
+		asm_vmread((sel), &reg_val2);			\
+		if ((reg_val & 0x3) <= 11			\
+		    && ((reg_val & 0x60 >> 5) < (reg_val2 & 0x3)))	\
+			printf("DPL of %s 0x%lx can't be less than "	\
+			      "RPL of %s 0x%lx\n",		\
+			       #access, reg_val, #sel, reg_val2);	\
+	}							\
+	CHECK_VMCS_SEG_COMMON(sel, base, limit, access);	\
+} while(0)
+
 static void
+vt_check_cr_dr_msr(void)
+{
+	ulong reg_val;
+
+	/*
+	 * 26.3.1.1 Checks on Guest Control Registers, Debug Registers,
+	 and MSRs
+	*/
+	CHECK_VMCS_1(VMCS_GUEST_CR0, CR0_PE_BIT | CR0_NE_BIT | CR0_PG_BIT);
+	CHECK_VMCS_1(VMCS_GUEST_CR4, CR4_VMXE_BIT);
+
+	/* TODO: check IA32_DEBUGCTL MSR */
+
+	asm_vmread(VMCS_VMENTRY_CTL, &reg_val);
+	if (reg_val & VMCS_VMENTRY_CTL_64_GUEST_BIT) {
+		CHECK_VMCS_1(VMCS_GUEST_CR0, CR0_PE_BIT);
+		CHECK_VMCS_1(VMCS_GUEST_CR4, CR4_PAE_BIT);
+	} else {
+		CHECK_VMCS_0(VMCS_GUEST_CR4, CR4_PCIDE_BIT);
+	}
+}
+
+static void
+vt_check_seg(void)
+{
+	ulong reg_val, reg_val2;
+
+	/*
+	 * 26.3.1.2 Checks on Guest Segment Registers
+	 */
+
+	/* TR */
+	CHECK_VMCS_0(VMCS_GUEST_TR_SEL, 0x4); /* TI (bit 2) */
+
+	/* LDTR */
+	asm_vmread (VMCS_GUEST_LDTR_ACCESS_RIGHTS, &reg_val);
+	if ((reg_val & VMCS_GUEST_ACCESS_RIGHTS_UNUSABLE) == 0) {
+		CHECK_VMCS_0(VMCS_GUEST_LDTR_SEL, 0x4); /* TI (bit 2) */
+	}
+
+	asm_vmread (VMCS_GUEST_RFLAGS, &reg_val);
+	if (reg_val & RFLAGS_VM_BIT) {
+		/* virtual 8086 */
+		CHECK_VMCS_VIRTUAL_8086_SEG(VMCS_GUEST_CS_SEL,
+					    VMCS_GUEST_CS_BASE,
+					    VMCS_GUEST_CS_LIMIT,
+					    VMCS_GUEST_CS_ACCESS_RIGHTS);
+		CHECK_VMCS_VIRTUAL_8086_SEG(VMCS_GUEST_SS_SEL,
+					    VMCS_GUEST_SS_BASE,
+					    VMCS_GUEST_SS_LIMIT,
+					    VMCS_GUEST_SS_ACCESS_RIGHTS);
+		CHECK_VMCS_VIRTUAL_8086_SEG(VMCS_GUEST_DS_SEL,
+					    VMCS_GUEST_DS_BASE,
+					    VMCS_GUEST_DS_LIMIT,
+					    VMCS_GUEST_DS_ACCESS_RIGHTS);
+		CHECK_VMCS_VIRTUAL_8086_SEG(VMCS_GUEST_ES_SEL,
+					    VMCS_GUEST_ES_BASE,
+					    VMCS_GUEST_ES_LIMIT,
+					    VMCS_GUEST_ES_ACCESS_RIGHTS);
+		CHECK_VMCS_VIRTUAL_8086_SEG(VMCS_GUEST_FS_SEL,
+					    VMCS_GUEST_FS_BASE,
+					    VMCS_GUEST_FS_LIMIT,
+					    VMCS_GUEST_FS_ACCESS_RIGHTS);
+		CHECK_VMCS_VIRTUAL_8086_SEG(VMCS_GUEST_GS_SEL,
+					    VMCS_GUEST_GS_BASE,
+					    VMCS_GUEST_GS_LIMIT,
+					    VMCS_GUEST_GS_ACCESS_RIGHTS);
+	} else {
+		asm_vmread(VMCS_GUEST_SS_SEL, &reg_val);
+		asm_vmread(VMCS_GUEST_CS_SEL, &reg_val2);
+		if ((reg_val & 0x3) != (reg_val2 & 0x3)) {
+			printf("RPL of VMCS_GUEST_SS_SEL 0x%lx "
+			       "and VMCS_GUEST_CS_SEL 0x%lx "
+			       "are not the same.\n",
+			       reg_val, reg_val2);
+
+		}
+
+		/* CS */
+		asm_vmread(VMCS_GUEST_CS_ACCESS_RIGHTS, &reg_val);
+		switch(reg_val & 0xf) {
+		case 9:
+		case 11:
+			asm_vmread(VMCS_GUEST_SS_ACCESS_RIGHTS, &reg_val2);
+			if ((reg_val & 0x60) != (reg_val2 & 0x60)) {
+				printf("DPL of CS and SS are not the same. "
+				       "0x%lx, 0x%lx\n", reg_val, reg_val2);
+				
+			}
+			break;
+		case 13:
+		case 15:
+			asm_vmread(VMCS_GUEST_SS_ACCESS_RIGHTS, &reg_val2);
+			if ((reg_val & 0x60) > (reg_val2 & 0x60)) {
+				printf("DPL of CS can't be grater than "
+				       "DPL of SS%lx, 0x%lx\n",
+				       reg_val, reg_val2);
+			}
+			break;
+		default:
+			printf("VMCS_GUEST_CS_ACCESS_RIGHTS 0x%lx (type)\n",
+			       reg_val);
+			break;
+		}
+		if ((reg_val & 0x10) != 0x10) {
+			printf("VMCS_GUEST_CS_ACCESS_RIGHTS 0x%lx (S)\n",
+			       reg_val);
+		}
+		CHECK_VMCS_SEG_COMMON(VMCS_GUEST_CS_SEL,
+				      VMCS_GUEST_CS_BASE,
+				      VMCS_GUEST_CS_LIMIT,
+				      VMCS_GUEST_CS_ACCESS_RIGHTS);
+
+		/* SS */
+		asm_vmread(VMCS_GUEST_SS_ACCESS_RIGHTS, &reg_val);
+		if((reg_val & VMCS_GUEST_ACCESS_RIGHTS_UNUSABLE) == 0) {
+			switch(reg_val & 0xf) {
+			case 3:
+			case 7:
+				break;
+			default:
+				printf("VMCS_GUEST_SS_ACCESS_RIGHTS 0x%lx "
+				       "(type)\n",
+				       reg_val);
+				break;
+			}
+			if ((reg_val & 0x10) != 0x10) {
+				printf("VMCS_GUEST_SS_ACCESS_RIGHTS "
+				       "0x%lx (S)\n",
+				       reg_val);
+			}
+		}
+		asm_vmread(VMCS_GUEST_SS_SEL, &reg_val2);
+		if (((reg_val & 0x60) >> 5) != (reg_val2 & 0x03)) {
+			printf("DPL of VMCS_GUEST_SS_ACCESS_RIGHTS 0x%lx "
+			       "and RPL of VMCS_GUEST_SS_SEL 0x%lx "
+			       "are not the same\n",
+			       reg_val, reg_val2);
+
+		}
+		CHECK_VMCS_SEG_COMMON(VMCS_GUEST_SS_SEL,
+				      VMCS_GUEST_SS_BASE,
+				      VMCS_GUEST_SS_LIMIT,
+				      VMCS_GUEST_SS_ACCESS_RIGHTS);
+
+		CHECK_VMCS_SEG(VMCS_GUEST_DS_SEL,
+			       VMCS_GUEST_DS_BASE,
+			       VMCS_GUEST_DS_LIMIT,
+			       VMCS_GUEST_DS_ACCESS_RIGHTS);
+		CHECK_VMCS_SEG(VMCS_GUEST_ES_SEL,
+			       VMCS_GUEST_ES_BASE,
+			       VMCS_GUEST_ES_LIMIT,
+			       VMCS_GUEST_ES_ACCESS_RIGHTS);
+		CHECK_VMCS_SEG(VMCS_GUEST_FS_SEL,
+			       VMCS_GUEST_FS_BASE,
+			       VMCS_GUEST_FS_LIMIT,
+			       VMCS_GUEST_FS_ACCESS_RIGHTS);
+		CHECK_VMCS_SEG(VMCS_GUEST_GS_SEL,
+			       VMCS_GUEST_GS_BASE,
+			       VMCS_GUEST_GS_LIMIT,
+			       VMCS_GUEST_GS_ACCESS_RIGHTS);
+	}
+	/* TR */
+	asm_vmread(VMCS_GUEST_TR_ACCESS_RIGHTS, &reg_val);
+	if((reg_val & VMCS_GUEST_ACCESS_RIGHTS_UNUSABLE) == 0) {
+		if ((reg_val & 0x10) != 0) {
+			printf("VMCS_GUEST_TR_ACCESS_RIGHTS "
+			       "0x%lx (S)\n",
+			       reg_val);
+		}
+	}
+	CHECK_VMCS_SEG_COMMON(VMCS_GUEST_TR_SEL,
+			      VMCS_GUEST_TR_BASE,
+			      VMCS_GUEST_TR_LIMIT,
+			      VMCS_GUEST_TR_ACCESS_RIGHTS);
+	/* LDTR */
+	asm_vmread(VMCS_GUEST_LDTR_ACCESS_RIGHTS, &reg_val);
+	if((reg_val & VMCS_GUEST_ACCESS_RIGHTS_UNUSABLE) == 0) {
+		switch(reg_val & 0xf) {
+		case 2:
+			break;
+		default:
+			printf("VMCS_GUEST_LDTR_ACCESS_RIGHTS 0x%lx "
+			       "(type)\n",
+			       reg_val);
+			break;
+		}
+		if ((reg_val & 0x10) != 0) {
+			printf("VMCS_GUEST_LDTR_ACCESS_RIGHTS "
+			       "0x%lx (S)\n",
+			       reg_val);
+		}
+	}
+	CHECK_VMCS_SEG_COMMON(VMCS_GUEST_LDTR_SEL,
+			      VMCS_GUEST_LDTR_BASE,
+			      VMCS_GUEST_LDTR_LIMIT,
+			      VMCS_GUEST_LDTR_ACCESS_RIGHTS);
+
+	asm_vmread(VMCS_VMENTRY_CTL, &reg_val);
+	if (reg_val & VMCS_VMENTRY_CTL_64_GUEST_BIT) {
+		/* IA-32e mode */
+
+		/* CS */
+		asm_vmread(VMCS_GUEST_CS_ACCESS_RIGHTS, &reg_val);
+		if ((reg_val & 0x4000) != 0) {
+			printf("VMCS_GUEST_CS_ACCESS_RIGHTS 0x%lx (D/B)\n",
+			       reg_val);
+		}
+		if ((reg_val & 0x2000) != 0x2000) {
+			printf("VMCS_GUEST_CS_ACCESS_RIGHTS 0x%lx (L)\n",
+			       reg_val);
+		}
+
+		/* TR */
+		asm_vmread(VMCS_GUEST_TR_ACCESS_RIGHTS, &reg_val);
+		if((reg_val & VMCS_GUEST_ACCESS_RIGHTS_UNUSABLE) == 0) {
+			switch(reg_val & 0xf) {
+			case 3:
+			case 11:
+				break;
+			default:
+				printf("VMCS_GUEST_TR_ACCESS_RIGHTS 0x%lx "
+				       "(type)\n",
+				       reg_val);
+				break;
+			}
+		}
+	} else {
+		/* TR */
+		asm_vmread(VMCS_GUEST_TR_ACCESS_RIGHTS, &reg_val);
+		if((reg_val & VMCS_GUEST_ACCESS_RIGHTS_UNUSABLE) == 0) {
+			switch(reg_val & 0xf) {
+			case 11:
+				break;
+			default:
+				printf("VMCS_GUEST_TR_ACCESS_RIGHTS 0x%lx "
+				       "(type)\n",
+				       reg_val);
+				break;
+			}
+		}
+	}
+}
+
+static void
+vt_vm_entry_check(void)
+{
+	vt_check_cr_dr_msr();
+	vt_check_seg();
+}
+
+static void
 vt_vm_run (void)
 {
 	enum vt_status status;
 
+	vt_vm_entry_check();
 	if (!current->u.vt.launched) {
 		current->u.vt.launched = true;
 		status = call_vt_vmlaunch ();
