[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH for-4.12 v4 2/3] x86/svm: Drop enum instruction_index and simplify svm_get_insn_len()
Passing a 32-bit integer index into an array with entries containing less than 32 bits of data is wasteful, and creates an unnecessary error condition of passing an out-of-range index. The width of the X86EMUL_OPC() encoding is currently 20 bits for the instructions used, which leaves room for a modrm byte. Drop opc_tab[] entirely, and encode the expected opcode/modrm information directly. Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> --- CC: Jan Beulich <JBeulich@xxxxxxxx> CC: Wei Liu <wei.liu2@xxxxxxxxxx> CC: Roger Pau Monné <roger.pau@xxxxxxxxxx> CC: Boris Ostrovsky <boris.ostrovsky@xxxxxxxxxx> CC: Suravee Suthikulpanit <suravee.suthikulpanit@xxxxxxx> CC: Brian Woods <brian.woods@xxxxxxx> CC: Juergen Gross <jgross@xxxxxxxx> The internals of X86EMUL_OPC() mean that we can't actually check for overflows with BUILD_BUG_ON(), but if the opcode encoding does changes and overflow, then the resulting fallout will be very obvious in debug builds of Xen. v3: * New v4: * Drop MODRM(), use Octal instead. --- xen/arch/x86/hvm/svm/emulate.c | 51 +++++++-------------------------- xen/include/asm-x86/hvm/svm/emulate.h | 53 +++++++++++++++++++---------------- 2 files changed, 39 insertions(+), 65 deletions(-) diff --git a/xen/arch/x86/hvm/svm/emulate.c b/xen/arch/x86/hvm/svm/emulate.c index 7799908..fb0d823 100644 --- a/xen/arch/x86/hvm/svm/emulate.c +++ b/xen/arch/x86/hvm/svm/emulate.c @@ -54,36 +54,6 @@ static unsigned long svm_nextrip_insn_length(struct vcpu *v) return vmcb->nextrip - vmcb->rip; } -static const struct { - unsigned int opcode; - struct { - unsigned int rm:3; - unsigned int reg:3; - unsigned int mod:2; -#define MODRM(mod, reg, rm) { rm, reg, mod } - } modrm; -} opc_tab[INSTR_MAX_COUNT] = { - [INSTR_PAUSE] = { X86EMUL_OPC_F3(0, 0x90) }, - [INSTR_INT3] = { X86EMUL_OPC( 0, 0xcc) }, - [INSTR_ICEBP] = { X86EMUL_OPC( 0, 0xf1) }, - [INSTR_HLT] = { X86EMUL_OPC( 0, 0xf4) }, - [INSTR_XSETBV] = { X86EMUL_OPC(0x0f, 0x01), MODRM(3, 2, 1) }, - [INSTR_VMRUN] = { X86EMUL_OPC(0x0f, 0x01), MODRM(3, 3, 0) }, - [INSTR_VMCALL] = { X86EMUL_OPC(0x0f, 0x01), MODRM(3, 3, 1) }, - [INSTR_VMLOAD] = { X86EMUL_OPC(0x0f, 0x01), MODRM(3, 3, 2) }, - [INSTR_VMSAVE] = { X86EMUL_OPC(0x0f, 0x01), MODRM(3, 3, 3) }, - [INSTR_STGI] = { X86EMUL_OPC(0x0f, 0x01), MODRM(3, 3, 4) }, - [INSTR_CLGI] = { X86EMUL_OPC(0x0f, 0x01), MODRM(3, 3, 5) }, - [INSTR_INVLPGA] = { X86EMUL_OPC(0x0f, 0x01), MODRM(3, 3, 7) }, - [INSTR_RDTSCP] = { X86EMUL_OPC(0x0f, 0x01), MODRM(3, 7, 1) }, - [INSTR_INVD] = { X86EMUL_OPC(0x0f, 0x08) }, - [INSTR_WBINVD] = { X86EMUL_OPC(0x0f, 0x09) }, - [INSTR_WRMSR] = { X86EMUL_OPC(0x0f, 0x30) }, - [INSTR_RDTSC] = { X86EMUL_OPC(0x0f, 0x31) }, - [INSTR_RDMSR] = { X86EMUL_OPC(0x0f, 0x32) }, - [INSTR_CPUID] = { X86EMUL_OPC(0x0f, 0xa2) }, -}; - /* * First-gen SVM didn't have the NextRIP feature, meaning that when we take a * fault-style vmexit, we have to decode the instruction stream to calculate @@ -93,12 +63,13 @@ static const struct { * hardware reported instruction length (if available) with the result from * x86_decode_insn(). */ -unsigned int svm_get_insn_len(struct vcpu *v, enum instruction_index insn) +unsigned int svm_get_insn_len(struct vcpu *v, unsigned int instr_enc) { struct vmcb_struct *vmcb = v->arch.hvm.svm.vmcb; struct hvm_emulate_ctxt ctxt; struct x86_emulate_state *state; unsigned long nrip_len, emul_len; + unsigned int instr_opcode, instr_modrm; unsigned int modrm_rm, modrm_reg; int modrm_mod; @@ -131,20 +102,18 @@ unsigned int svm_get_insn_len(struct vcpu *v, enum instruction_index insn) } #endif - if ( insn >= ARRAY_SIZE(opc_tab) ) - { - ASSERT_UNREACHABLE(); - return 0; - } + /* Extract components from instr_enc. */ + instr_modrm = instr_enc & 0xff; + instr_opcode = instr_enc >> 8; - if ( opc_tab[insn].opcode == ctxt.ctxt.opcode ) + if ( instr_opcode == ctxt.ctxt.opcode ) { - if ( !opc_tab[insn].modrm.mod ) + if ( !instr_modrm ) return emul_len; - if ( modrm_mod == opc_tab[insn].modrm.mod && - (modrm_rm & 7) == opc_tab[insn].modrm.rm && - (modrm_reg & 7) == opc_tab[insn].modrm.reg ) + if ( modrm_mod == MASK_EXTR(instr_modrm, 0300) && + (modrm_reg & 7) == MASK_EXTR(instr_modrm, 0070) && + (modrm_rm & 7) == MASK_EXTR(instr_modrm, 0007) ) return emul_len; } diff --git a/xen/include/asm-x86/hvm/svm/emulate.h b/xen/include/asm-x86/hvm/svm/emulate.h index 82359ec..9af1006 100644 --- a/xen/include/asm-x86/hvm/svm/emulate.h +++ b/xen/include/asm-x86/hvm/svm/emulate.h @@ -19,33 +19,38 @@ #ifndef __ASM_X86_HVM_SVM_EMULATE_H__ #define __ASM_X86_HVM_SVM_EMULATE_H__ -/* Enumerate some standard instructions that we support */ -enum instruction_index { - INSTR_INVD, - INSTR_WBINVD, - INSTR_CPUID, - INSTR_RDMSR, - INSTR_WRMSR, - INSTR_VMCALL, - INSTR_HLT, - INSTR_INT3, - INSTR_RDTSC, - INSTR_RDTSCP, - INSTR_PAUSE, - INSTR_XSETBV, - INSTR_VMRUN, - INSTR_VMLOAD, - INSTR_VMSAVE, - INSTR_STGI, - INSTR_CLGI, - INSTR_INVLPGA, - INSTR_ICEBP, - INSTR_MAX_COUNT /* Must be last - Number of instructions supported */ -}; +/* + * Encoding for svm_get_insn_len(). We take X86EMUL_OPC() for the main + * opcode, shifted left to make room for the ModRM byte. + * + * The Grp7 instructions have their ModRM byte expressed in octal for easier + * cross referencing with the opcode extension table. + */ +#define INSTR_ENC(opc, modrm) (((opc) << 8) | (modrm)) + +#define INSTR_PAUSE INSTR_ENC(X86EMUL_OPC_F3(0, 0x90), 0) +#define INSTR_INT3 INSTR_ENC(X86EMUL_OPC( 0, 0xcc), 0) +#define INSTR_ICEBP INSTR_ENC(X86EMUL_OPC( 0, 0xf1), 0) +#define INSTR_HLT INSTR_ENC(X86EMUL_OPC( 0, 0xf4), 0) +#define INSTR_XSETBV INSTR_ENC(X86EMUL_OPC(0x0f, 0x01), 0321) +#define INSTR_VMRUN INSTR_ENC(X86EMUL_OPC(0x0f, 0x01), 0330) +#define INSTR_VMCALL INSTR_ENC(X86EMUL_OPC(0x0f, 0x01), 0331) +#define INSTR_VMLOAD INSTR_ENC(X86EMUL_OPC(0x0f, 0x01), 0332) +#define INSTR_VMSAVE INSTR_ENC(X86EMUL_OPC(0x0f, 0x01), 0333) +#define INSTR_STGI INSTR_ENC(X86EMUL_OPC(0x0f, 0x01), 0334) +#define INSTR_CLGI INSTR_ENC(X86EMUL_OPC(0x0f, 0x01), 0335) +#define INSTR_INVLPGA INSTR_ENC(X86EMUL_OPC(0x0f, 0x01), 0337) +#define INSTR_RDTSCP INSTR_ENC(X86EMUL_OPC(0x0f, 0x01), 0371) +#define INSTR_INVD INSTR_ENC(X86EMUL_OPC(0x0f, 0x08), 0) +#define INSTR_WBINVD INSTR_ENC(X86EMUL_OPC(0x0f, 0x09), 0) +#define INSTR_WRMSR INSTR_ENC(X86EMUL_OPC(0x0f, 0x30), 0) +#define INSTR_RDTSC INSTR_ENC(X86EMUL_OPC(0x0f, 0x31), 0) +#define INSTR_RDMSR INSTR_ENC(X86EMUL_OPC(0x0f, 0x32), 0) +#define INSTR_CPUID INSTR_ENC(X86EMUL_OPC(0x0f, 0xa2), 0) struct vcpu; -unsigned int svm_get_insn_len(struct vcpu *v, enum instruction_index instr); +unsigned int svm_get_insn_len(struct vcpu *v, unsigned int instr_enc); #endif /* __ASM_X86_HVM_SVM_EMULATE_H__ */ -- 2.1.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |