[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen staging] x86/svm: Drop enum instruction_index and simplify svm_get_insn_len()
commit 411900525f49f15ca85854b768353a27c87bf1b8 Author: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> AuthorDate: Thu Dec 13 17:01:24 2018 +0000 Commit: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> CommitDate: Fri Feb 1 11:25:32 2019 +0000 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> Acked-by: Brian Woods <brian.woods@xxxxxxx> Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx> Release-acked-by: Juergen Gross <jgross@xxxxxxxx> --- 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 2569faa349..e01402210a 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) }, -}; - /* * Early processors with SVM didn't have the NextRIP feature, meaning that * when we take a fault-style VMExit, we have to decode the instruction stream @@ -92,12 +62,13 @@ static const struct { * In debug builds, always compare the 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; @@ -130,20 +101,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 82359ec15c..9af10061c5 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__ */ -- generated by git-patchbot for /home/xen/git/xen.git#staging _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |