x86_emulate.c

来自「linux 内核源代码」· C语言 代码 · 共 1,663 行 · 第 1/3 页

C
1,663
字号
/****************************************************************************** * x86_emulate.c * * Generic x86 (32-bit and 64-bit) instruction decoder and emulator. * * Copyright (c) 2005 Keir Fraser * * Linux coding style, mod r/m decoder, segment base fixes, real-mode * privileged instructions: * * Copyright (C) 2006 Qumranet * *   Avi Kivity <avi@qumranet.com> *   Yaniv Kamay <yaniv@qumranet.com> * * This work is licensed under the terms of the GNU GPL, version 2.  See * the COPYING file in the top-level directory. * * From: xen-unstable 10676:af9809f51f81a3c43f276f00c81a52ef558afda4 */#ifndef __KERNEL__#include <stdio.h>#include <stdint.h>#include <public/xen.h>#define DPRINTF(_f, _a ...) printf( _f , ## _a )#else#include "kvm.h"#define DPRINTF(x...) do {} while (0)#endif#include "x86_emulate.h"#include <linux/module.h>/* * Opcode effective-address decode tables. * Note that we only emulate instructions that have at least one memory * operand (excluding implicit stack references). We assume that stack * references and instruction fetches will never occur in special memory * areas that require emulation. So, for example, 'mov <imm>,<reg>' need * not be handled. *//* Operand sizes: 8-bit operands or specified/overridden size. */#define ByteOp      (1<<0)	/* 8-bit operands. *//* Destination operand type. */#define ImplicitOps (1<<1)	/* Implicit in opcode. No generic decode. */#define DstReg      (2<<1)	/* Register operand. */#define DstMem      (3<<1)	/* Memory operand. */#define DstMask     (3<<1)/* Source operand type. */#define SrcNone     (0<<3)	/* No source operand. */#define SrcImplicit (0<<3)	/* Source operand is implicit in the opcode. */#define SrcReg      (1<<3)	/* Register operand. */#define SrcMem      (2<<3)	/* Memory operand. */#define SrcMem16    (3<<3)	/* Memory operand (16-bit). */#define SrcMem32    (4<<3)	/* Memory operand (32-bit). */#define SrcImm      (5<<3)	/* Immediate operand. */#define SrcImmByte  (6<<3)	/* 8-bit sign-extended immediate operand. */#define SrcMask     (7<<3)/* Generic ModRM decode. */#define ModRM       (1<<6)/* Destination is only written; never read. */#define Mov         (1<<7)#define BitOp       (1<<8)static u8 opcode_table[256] = {	/* 0x00 - 0x07 */	ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,	ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,	0, 0, 0, 0,	/* 0x08 - 0x0F */	ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,	ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,	0, 0, 0, 0,	/* 0x10 - 0x17 */	ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,	ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,	0, 0, 0, 0,	/* 0x18 - 0x1F */	ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,	ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,	0, 0, 0, 0,	/* 0x20 - 0x27 */	ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,	ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,	SrcImmByte, SrcImm, 0, 0,	/* 0x28 - 0x2F */	ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,	ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,	0, 0, 0, 0,	/* 0x30 - 0x37 */	ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,	ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,	0, 0, 0, 0,	/* 0x38 - 0x3F */	ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,	ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,	0, 0, 0, 0,	/* 0x40 - 0x4F */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0x50 - 0x57 */	ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,	ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,	/* 0x58 - 0x5F */	ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,	ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,	/* 0x60 - 0x67 */	0, 0, 0, DstReg | SrcMem32 | ModRM | Mov /* movsxd (x86/64) */ ,	0, 0, 0, 0,	/* 0x68 - 0x6F */	0, 0, ImplicitOps|Mov, 0,	SrcNone  | ByteOp  | ImplicitOps, SrcNone  | ImplicitOps, /* insb, insw/insd */	SrcNone  | ByteOp  | ImplicitOps, SrcNone  | ImplicitOps, /* outsb, outsw/outsd */	/* 0x70 - 0x77 */	ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,	ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,	/* 0x78 - 0x7F */	ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,	ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,	/* 0x80 - 0x87 */	ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImm | ModRM,	ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM,	ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,	ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,	/* 0x88 - 0x8F */	ByteOp | DstMem | SrcReg | ModRM | Mov, DstMem | SrcReg | ModRM | Mov,	ByteOp | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,	0, ModRM | DstReg, 0, DstMem | SrcNone | ModRM | Mov,	/* 0x90 - 0x9F */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps, ImplicitOps, 0, 0,	/* 0xA0 - 0xA7 */	ByteOp | DstReg | SrcMem | Mov, DstReg | SrcMem | Mov,	ByteOp | DstMem | SrcReg | Mov, DstMem | SrcReg | Mov,	ByteOp | ImplicitOps | Mov, ImplicitOps | Mov,	ByteOp | ImplicitOps, ImplicitOps,	/* 0xA8 - 0xAF */	0, 0, ByteOp | ImplicitOps | Mov, ImplicitOps | Mov,	ByteOp | ImplicitOps | Mov, ImplicitOps | Mov,	ByteOp | ImplicitOps, ImplicitOps,	/* 0xB0 - 0xBF */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0xC0 - 0xC7 */	ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM,	0, ImplicitOps, 0, 0,	ByteOp | DstMem | SrcImm | ModRM | Mov, DstMem | SrcImm | ModRM | Mov,	/* 0xC8 - 0xCF */	0, 0, 0, 0, 0, 0, 0, 0,	/* 0xD0 - 0xD7 */	ByteOp | DstMem | SrcImplicit | ModRM, DstMem | SrcImplicit | ModRM,	ByteOp | DstMem | SrcImplicit | ModRM, DstMem | SrcImplicit | ModRM,	0, 0, 0, 0,	/* 0xD8 - 0xDF */	0, 0, 0, 0, 0, 0, 0, 0,	/* 0xE0 - 0xE7 */	0, 0, 0, 0, 0, 0, 0, 0,	/* 0xE8 - 0xEF */	ImplicitOps, SrcImm|ImplicitOps, 0, SrcImmByte|ImplicitOps, 0, 0, 0, 0,	/* 0xF0 - 0xF7 */	0, 0, 0, 0,	ImplicitOps, 0,	ByteOp | DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM,	/* 0xF8 - 0xFF */	0, 0, 0, 0,	0, 0, ByteOp | DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM};static u16 twobyte_table[256] = {	/* 0x00 - 0x0F */	0, SrcMem | ModRM | DstReg, 0, 0, 0, 0, ImplicitOps, 0,	ImplicitOps, ImplicitOps, 0, 0, 0, ImplicitOps | ModRM, 0, 0,	/* 0x10 - 0x1F */	0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0,	/* 0x20 - 0x2F */	ModRM | ImplicitOps, ModRM, ModRM | ImplicitOps, ModRM, 0, 0, 0, 0,	0, 0, 0, 0, 0, 0, 0, 0,	/* 0x30 - 0x3F */	ImplicitOps, 0, ImplicitOps, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0x40 - 0x47 */	DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,	DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,	DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,	DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,	/* 0x48 - 0x4F */	DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,	DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,	DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,	DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,	/* 0x50 - 0x5F */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0x60 - 0x6F */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0x70 - 0x7F */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0x80 - 0x8F */	ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,	ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,	ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,	ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,	/* 0x90 - 0x9F */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0xA0 - 0xA7 */	0, 0, 0, DstMem | SrcReg | ModRM | BitOp, 0, 0, 0, 0,	/* 0xA8 - 0xAF */	0, 0, 0, DstMem | SrcReg | ModRM | BitOp, 0, 0, 0, 0,	/* 0xB0 - 0xB7 */	ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, 0,	    DstMem | SrcReg | ModRM | BitOp,	0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov,	    DstReg | SrcMem16 | ModRM | Mov,	/* 0xB8 - 0xBF */	0, 0, DstMem | SrcImmByte | ModRM, DstMem | SrcReg | ModRM | BitOp,	0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov,	    DstReg | SrcMem16 | ModRM | Mov,	/* 0xC0 - 0xCF */	0, 0, 0, DstMem | SrcReg | ModRM | Mov, 0, 0, 0, ImplicitOps | ModRM,	0, 0, 0, 0, 0, 0, 0, 0,	/* 0xD0 - 0xDF */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0xE0 - 0xEF */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0xF0 - 0xFF */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};/* Type, address-of, and value of an instruction's operand. */struct operand {	enum { OP_REG, OP_MEM, OP_IMM } type;	unsigned int bytes;	unsigned long val, orig_val, *ptr;};/* EFLAGS bit definitions. */#define EFLG_OF (1<<11)#define EFLG_DF (1<<10)#define EFLG_SF (1<<7)#define EFLG_ZF (1<<6)#define EFLG_AF (1<<4)#define EFLG_PF (1<<2)#define EFLG_CF (1<<0)/* * Instruction emulation: * Most instructions are emulated directly via a fragment of inline assembly * code. This allows us to save/restore EFLAGS and thus very easily pick up * any modified flags. */#if defined(CONFIG_X86_64)#define _LO32 "k"		/* force 32-bit operand */#define _STK  "%%rsp"		/* stack pointer */#elif defined(__i386__)#define _LO32 ""		/* force 32-bit operand */#define _STK  "%%esp"		/* stack pointer */#endif/* * These EFLAGS bits are restored from saved value during emulation, and * any changes are written back to the saved value after emulation. */#define EFLAGS_MASK (EFLG_OF|EFLG_SF|EFLG_ZF|EFLG_AF|EFLG_PF|EFLG_CF)/* Before executing instruction: restore necessary bits in EFLAGS. */#define _PRE_EFLAGS(_sav, _msk, _tmp) \	/* EFLAGS = (_sav & _msk) | (EFLAGS & ~_msk); */	\	"push %"_sav"; "					\	"movl %"_msk",%"_LO32 _tmp"; "				\	"andl %"_LO32 _tmp",("_STK"); "				\	"pushf; "						\	"notl %"_LO32 _tmp"; "					\	"andl %"_LO32 _tmp",("_STK"); "				\	"pop  %"_tmp"; "					\	"orl  %"_LO32 _tmp",("_STK"); "				\	"popf; "						\	/* _sav &= ~msk; */					\	"movl %"_msk",%"_LO32 _tmp"; "				\	"notl %"_LO32 _tmp"; "					\	"andl %"_LO32 _tmp",%"_sav"; "/* After executing instruction: write-back necessary bits in EFLAGS. */#define _POST_EFLAGS(_sav, _msk, _tmp) \	/* _sav |= EFLAGS & _msk; */		\	"pushf; "				\	"pop  %"_tmp"; "			\	"andl %"_msk",%"_LO32 _tmp"; "		\	"orl  %"_LO32 _tmp",%"_sav"; "/* Raw emulation: instruction has two explicit operands. */#define __emulate_2op_nobyte(_op,_src,_dst,_eflags,_wx,_wy,_lx,_ly,_qx,_qy) \	do { 								    \		unsigned long _tmp;					    \									    \		switch ((_dst).bytes) {					    \		case 2:							    \			__asm__ __volatile__ (				    \				_PRE_EFLAGS("0","4","2")		    \				_op"w %"_wx"3,%1; "			    \				_POST_EFLAGS("0","4","2")		    \				: "=m" (_eflags), "=m" ((_dst).val),        \				  "=&r" (_tmp)				    \				: _wy ((_src).val), "i" (EFLAGS_MASK) );    \			break;						    \		case 4:							    \			__asm__ __volatile__ (				    \				_PRE_EFLAGS("0","4","2")		    \				_op"l %"_lx"3,%1; "			    \				_POST_EFLAGS("0","4","2")		    \				: "=m" (_eflags), "=m" ((_dst).val),	    \				  "=&r" (_tmp)				    \				: _ly ((_src).val), "i" (EFLAGS_MASK) );    \			break;						    \		case 8:							    \			__emulate_2op_8byte(_op, _src, _dst,		    \					    _eflags, _qx, _qy);		    \			break;						    \		}							    \	} while (0)#define __emulate_2op(_op,_src,_dst,_eflags,_bx,_by,_wx,_wy,_lx,_ly,_qx,_qy) \	do {								     \		unsigned long _tmp;					     \		switch ( (_dst).bytes )					     \		{							     \		case 1:							     \			__asm__ __volatile__ (				     \				_PRE_EFLAGS("0","4","2")		     \				_op"b %"_bx"3,%1; "			     \				_POST_EFLAGS("0","4","2")		     \				: "=m" (_eflags), "=m" ((_dst).val),	     \				  "=&r" (_tmp)				     \				: _by ((_src).val), "i" (EFLAGS_MASK) );     \			break;						     \		default:						     \			__emulate_2op_nobyte(_op, _src, _dst, _eflags,	     \					     _wx, _wy, _lx, _ly, _qx, _qy);  \			break;						     \		}							     \	} while (0)/* Source operand is byte-sized and may be restricted to just %cl. */#define emulate_2op_SrcB(_op, _src, _dst, _eflags)                      \	__emulate_2op(_op, _src, _dst, _eflags,				\		      "b", "c", "b", "c", "b", "c", "b", "c")/* Source operand is byte, word, long or quad sized. */#define emulate_2op_SrcV(_op, _src, _dst, _eflags)                      \	__emulate_2op(_op, _src, _dst, _eflags,				\		      "b", "q", "w", "r", _LO32, "r", "", "r")/* Source operand is word, long or quad sized. */#define emulate_2op_SrcV_nobyte(_op, _src, _dst, _eflags)               \	__emulate_2op_nobyte(_op, _src, _dst, _eflags,			\			     "w", "r", _LO32, "r", "", "r")/* Instruction has only one explicit operand (no source operand). */#define emulate_1op(_op, _dst, _eflags)                                    \	do {								\		unsigned long _tmp;					\									\		switch ( (_dst).bytes )					\		{							\		case 1:							\			__asm__ __volatile__ (				\				_PRE_EFLAGS("0","3","2")		\				_op"b %1; "				\				_POST_EFLAGS("0","3","2")		\				: "=m" (_eflags), "=m" ((_dst).val),	\				  "=&r" (_tmp)				\				: "i" (EFLAGS_MASK) );			\			break;						\		case 2:							\			__asm__ __volatile__ (				\				_PRE_EFLAGS("0","3","2")		\				_op"w %1; "				\				_POST_EFLAGS("0","3","2")		\				: "=m" (_eflags), "=m" ((_dst).val),	\				  "=&r" (_tmp)				\				: "i" (EFLAGS_MASK) );			\			break;						\		case 4:							\			__asm__ __volatile__ (				\				_PRE_EFLAGS("0","3","2")		\				_op"l %1; "				\				_POST_EFLAGS("0","3","2")		\				: "=m" (_eflags), "=m" ((_dst).val),	\				  "=&r" (_tmp)				\				: "i" (EFLAGS_MASK) );			\			break;						\		case 8:							\			__emulate_1op_8byte(_op, _dst, _eflags);	\			break;						\		}							\	} while (0)/* Emulate an instruction with quadword operands (x86/64 only). */#if defined(CONFIG_X86_64)#define __emulate_2op_8byte(_op, _src, _dst, _eflags, _qx, _qy)           \	do {								  \		__asm__ __volatile__ (					  \			_PRE_EFLAGS("0","4","2")			  \			_op"q %"_qx"3,%1; "				  \			_POST_EFLAGS("0","4","2")			  \			: "=m" (_eflags), "=m" ((_dst).val), "=&r" (_tmp) \			: _qy ((_src).val), "i" (EFLAGS_MASK) );	  \	} while (0)#define __emulate_1op_8byte(_op, _dst, _eflags)                           \	do {								  \		__asm__ __volatile__ (					  \			_PRE_EFLAGS("0","3","2")			  \			_op"q %1; "					  \			_POST_EFLAGS("0","3","2")			  \			: "=m" (_eflags), "=m" ((_dst).val), "=&r" (_tmp) \			: "i" (EFLAGS_MASK) );				  \	} while (0)#elif defined(__i386__)#define __emulate_2op_8byte(_op, _src, _dst, _eflags, _qx, _qy)#define __emulate_1op_8byte(_op, _dst, _eflags)#endif				/* __i386__ *//* Fetch next part of the instruction being emulated. */#define insn_fetch(_type, _size, _eip)                                  \({	unsigned long _x;						\	rc = ops->read_std((unsigned long)(_eip) + ctxt->cs_base, &_x,	\                                                  (_size), ctxt->vcpu); \	if ( rc != 0 )							\		goto done;						\	(_eip) += (_size);						\	(_type)_x;							\})/* Access/update address held in a register, based on addressing mode. */#define address_mask(reg)						\	((ad_bytes == sizeof(unsigned long)) ? 				\		(reg) :	((reg) & ((1UL << (ad_bytes << 3)) - 1)))#define register_address(base, reg)                                     \	((base) + address_mask(reg))#define register_address_increment(reg, inc)                            \	do {								\		/* signed type ensures sign extension to long */        \		int _inc = (inc);					\		if ( ad_bytes == sizeof(unsigned long) )		\			(reg) += _inc;					\		else							\			(reg) = ((reg) & ~((1UL << (ad_bytes << 3)) - 1)) | \			   (((reg) + _inc) & ((1UL << (ad_bytes << 3)) - 1)); \	} while (0)#define JMP_REL(rel) 							\	do {								\		register_address_increment(_eip, rel);			\	} while (0)/* * Given the 'reg' portion of a ModRM byte, and a register block, return a * pointer into the block that addresses the relevant register. * @highbyte_regs specifies whether to decode AH,CH,DH,BH. */static void *decode_register(u8 modrm_reg, unsigned long *regs,			     int highbyte_regs){	void *p;	p = &regs[modrm_reg];	if (highbyte_regs && modrm_reg >= 4 && modrm_reg < 8)		p = (unsigned char *)&regs[modrm_reg & 3] + 1;	return p;}static int read_descriptor(struct x86_emulate_ctxt *ctxt,			   struct x86_emulate_ops *ops,			   void *ptr,			   u16 *size, unsigned long *address, int op_bytes){	int rc;	if (op_bytes == 2)		op_bytes = 3;	*address = 0;	rc = ops->read_std((unsigned long)ptr, (unsigned long *)size, 2,			   ctxt->vcpu);	if (rc)		return rc;	rc = ops->read_std((unsigned long)ptr + 2, address, op_bytes,			   ctxt->vcpu);	return rc;}static int test_cc(unsigned int condition, unsigned int flags){	int rc = 0;	switch ((condition & 15) >> 1) {	case 0: /* o */		rc |= (flags & EFLG_OF);		break;	case 1: /* b/c/nae */		rc |= (flags & EFLG_CF);		break;	case 2: /* z/e */		rc |= (flags & EFLG_ZF);		break;	case 3: /* be/na */		rc |= (flags & (EFLG_CF|EFLG_ZF));		break;	case 4: /* s */		rc |= (flags & EFLG_SF);		break;	case 5: /* p/pe */		rc |= (flags & EFLG_PF);		break;	case 7: /* le/ng */		rc |= (flags & EFLG_ZF);		/* fall through */	case 6: /* l/nge */		rc |= (!(flags & EFLG_SF) != !(flags & EFLG_OF));		break;	}	/* Odd condition identifiers (lsb == 1) have inverted sense. */	return (!!rc ^ (condition & 1));}intx86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops){	unsigned d;	u8 b, sib, twobyte = 0, rex_prefix = 0;	u8 modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0;	unsigned long *override_base = NULL;	unsigned int op_bytes, ad_bytes, lock_prefix = 0, rep_prefix = 0, i;	int rc = 0;	struct operand src, dst;	unsigned long cr2 = ctxt->cr2;	int mode = ctxt->mode;	unsigned long modrm_ea;	int use_modrm_ea, index_reg = 0, base_reg = 0, scale, rip_relative = 0;	int no_wb = 0;	u64 msr_data;	/* Shadow copy of register state. Committed on successful emulation. */	unsigned long _regs[NR_VCPU_REGS];	unsigned long _eip = ctxt->vcpu->rip, _eflags = ctxt->eflags;	unsigned long modrm_val = 0;	memcpy(_regs, ctxt->vcpu->regs, sizeof _regs);	switch (mode) {	case X86EMUL_MODE_REAL:	case X86EMUL_MODE_PROT16:		op_bytes = ad_bytes = 2;		break;	case X86EMUL_MODE_PROT32:		op_bytes = ad_bytes = 4;		break;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?