KVM: x86 emulator: move 0F 01 sub-opcodes into their own functions

Signed-off-by: Avi Kivity <avi@redhat.com>
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 77a5f54..8e1d0c8 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -2589,6 +2589,95 @@
 	return X86EMUL_CONTINUE;
 }
 
+static int em_vmcall(struct x86_emulate_ctxt *ctxt)
+{
+	struct decode_cache *c = &ctxt->decode;
+	int rc;
+
+	if (c->modrm_mod != 3 || c->modrm_rm != 1)
+		return X86EMUL_UNHANDLEABLE;
+
+	rc = ctxt->ops->fix_hypercall(ctxt);
+	if (rc != X86EMUL_CONTINUE)
+		return rc;
+
+	/* Let the processor re-execute the fixed hypercall */
+	c->eip = ctxt->eip;
+	/* Disable writeback. */
+	c->dst.type = OP_NONE;
+	return X86EMUL_CONTINUE;
+}
+
+static int em_lgdt(struct x86_emulate_ctxt *ctxt)
+{
+	struct decode_cache *c = &ctxt->decode;
+	struct desc_ptr desc_ptr;
+	int rc;
+
+	rc = read_descriptor(ctxt, ctxt->ops, c->src.addr.mem,
+			     &desc_ptr.size, &desc_ptr.address,
+			     c->op_bytes);
+	if (rc != X86EMUL_CONTINUE)
+		return rc;
+	ctxt->ops->set_gdt(ctxt, &desc_ptr);
+	/* Disable writeback. */
+	c->dst.type = OP_NONE;
+	return X86EMUL_CONTINUE;
+}
+
+static int em_svm(struct x86_emulate_ctxt *ctxt)
+{
+	struct decode_cache *c = &ctxt->decode;
+	int rc;
+
+	switch (c->modrm_rm) {
+	case 1:
+		rc = ctxt->ops->fix_hypercall(ctxt);
+		break;
+	default:
+		return X86EMUL_UNHANDLEABLE;
+	}
+	/* Disable writeback. */
+	c->dst.type = OP_NONE;
+	return rc;
+}
+
+static int em_lidt(struct x86_emulate_ctxt *ctxt)
+{
+	struct decode_cache *c = &ctxt->decode;
+	struct desc_ptr desc_ptr;
+	int rc;
+
+	rc = read_descriptor(ctxt, ctxt->ops, c->src.addr.mem,
+			     &desc_ptr.size,
+			     &desc_ptr.address,
+			     c->op_bytes);
+	if (rc != X86EMUL_CONTINUE)
+		return rc;
+	ctxt->ops->set_idt(ctxt, &desc_ptr);
+	/* Disable writeback. */
+	c->dst.type = OP_NONE;
+	return X86EMUL_CONTINUE;
+}
+
+static int em_smsw(struct x86_emulate_ctxt *ctxt)
+{
+	struct decode_cache *c = &ctxt->decode;
+
+	c->dst.bytes = 2;
+	c->dst.val = ctxt->ops->get_cr(ctxt, 0);
+	return X86EMUL_CONTINUE;
+}
+
+static int em_lmsw(struct x86_emulate_ctxt *ctxt)
+{
+	struct decode_cache *c = &ctxt->decode;
+	ctxt->ops->set_cr(ctxt, 0, (ctxt->ops->get_cr(ctxt, 0) & ~0x0eul)
+			  | (c->src.val & 0x0f));
+	c->dst.type = OP_NONE;
+	return X86EMUL_CONTINUE;
+}
+
 static bool valid_cr(int nr)
 {
 	switch (nr) {
@@ -3509,7 +3598,6 @@
 	int rc = X86EMUL_CONTINUE;
 	int saved_dst_type = c->dst.type;
 	int irq; /* Used for int 3, int, and into */
-	struct desc_ptr desc_ptr;
 
 	ctxt->decode.mem_read.pos = 0;
 
@@ -4022,62 +4110,26 @@
 	case 0x01: /* lgdt, lidt, lmsw */
 		switch (c->modrm_reg) {
 		case 0: /* vmcall */
-			if (c->modrm_mod != 3 || c->modrm_rm != 1)
-				goto cannot_emulate;
-
-			rc = ctxt->ops->fix_hypercall(ctxt);
-			if (rc != X86EMUL_CONTINUE)
-				goto done;
-
-			/* Let the processor re-execute the fixed hypercall */
-			c->eip = ctxt->eip;
-			/* Disable writeback. */
-			c->dst.type = OP_NONE;
+			rc = em_vmcall(ctxt);
 			break;
 		case 2: /* lgdt */
-			rc = read_descriptor(ctxt, ops, c->src.addr.mem,
-					     &desc_ptr.size, &desc_ptr.address,
-					     c->op_bytes);
-			if (rc != X86EMUL_CONTINUE)
-				goto done;
-			ctxt->ops->set_gdt(ctxt, &desc_ptr);
-			/* Disable writeback. */
-			c->dst.type = OP_NONE;
+			rc = em_lgdt(ctxt);
 			break;
 		case 3: /* lidt/vmmcall */
-			if (c->modrm_mod == 3) {
-				switch (c->modrm_rm) {
-				case 1:
-					rc = ctxt->ops->fix_hypercall(ctxt);
-					break;
-				default:
-					goto cannot_emulate;
-				}
-			} else {
-				rc = read_descriptor(ctxt, ops, c->src.addr.mem,
-						     &desc_ptr.size,
-						     &desc_ptr.address,
-						     c->op_bytes);
-				if (rc != X86EMUL_CONTINUE)
-					goto done;
-				ctxt->ops->set_idt(ctxt, &desc_ptr);
-			}
-			/* Disable writeback. */
-			c->dst.type = OP_NONE;
+			if (c->modrm_mod == 3)
+				return em_svm(ctxt);
+			else
+				return em_lidt(ctxt);
 			break;
 		case 4: /* smsw */
-			c->dst.bytes = 2;
-			c->dst.val = ops->get_cr(ctxt, 0);
+			rc = em_smsw(ctxt);
 			break;
 		case 6: /* lmsw */
-			ops->set_cr(ctxt, 0, (ops->get_cr(ctxt, 0) & ~0x0eul) |
-				    (c->src.val & 0x0f));
-			c->dst.type = OP_NONE;
+			rc = em_lmsw(ctxt);
 			break;
 		case 5: /* not defined */
-			emulate_ud(ctxt);
-			rc = X86EMUL_PROPAGATE_FAULT;
-			goto done;
+			rc = emulate_ud(ctxt);
+			break;
 		case 7: /* invlpg*/
 			rc = em_invlpg(ctxt);
 			break;