LCOV - code coverage report
Current view: top level - arch/x86/include/asm - insn.h (source / functions) Hit Total Coverage
Test: landlock.info Lines: 13 34 38.2 %
Date: 2021-04-22 12:43:58 Functions: 1 2 50.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: GPL-2.0-or-later */
       2             : #ifndef _ASM_X86_INSN_H
       3             : #define _ASM_X86_INSN_H
       4             : /*
       5             :  * x86 instruction analysis
       6             :  *
       7             :  * Copyright (C) IBM Corporation, 2009
       8             :  */
       9             : 
      10             : #include <asm/byteorder.h>
      11             : /* insn_attr_t is defined in inat.h */
      12             : #include <asm/inat.h>
      13             : 
      14             : #if defined(__BYTE_ORDER) ? __BYTE_ORDER == __LITTLE_ENDIAN : defined(__LITTLE_ENDIAN)
      15             : 
      16             : struct insn_field {
      17             :         union {
      18             :                 insn_value_t value;
      19             :                 insn_byte_t bytes[4];
      20             :         };
      21             :         /* !0 if we've run insn_get_xxx() for this field */
      22             :         unsigned char got;
      23             :         unsigned char nbytes;
      24             : };
      25             : 
      26          38 : static inline void insn_field_set(struct insn_field *p, insn_value_t v,
      27             :                                   unsigned char n)
      28             : {
      29          38 :         p->value = v;
      30           0 :         p->nbytes = n;
      31          38 : }
      32             : 
      33          38 : static inline void insn_set_byte(struct insn_field *p, unsigned char n,
      34             :                                  insn_byte_t v)
      35             : {
      36          38 :         p->bytes[n] = v;
      37           0 : }
      38             : 
      39             : #else
      40             : 
      41             : struct insn_field {
      42             :         insn_value_t value;
      43             :         union {
      44             :                 insn_value_t little;
      45             :                 insn_byte_t bytes[4];
      46             :         };
      47             :         /* !0 if we've run insn_get_xxx() for this field */
      48             :         unsigned char got;
      49             :         unsigned char nbytes;
      50             : };
      51             : 
      52             : static inline void insn_field_set(struct insn_field *p, insn_value_t v,
      53             :                                   unsigned char n)
      54             : {
      55             :         p->value = v;
      56             :         p->little = __cpu_to_le32(v);
      57             :         p->nbytes = n;
      58             : }
      59             : 
      60             : static inline void insn_set_byte(struct insn_field *p, unsigned char n,
      61             :                                  insn_byte_t v)
      62             : {
      63             :         p->bytes[n] = v;
      64             :         p->value = __le32_to_cpu(p->little);
      65             : }
      66             : #endif
      67             : 
      68             : struct insn {
      69             :         struct insn_field prefixes;     /*
      70             :                                          * Prefixes
      71             :                                          * prefixes.bytes[3]: last prefix
      72             :                                          */
      73             :         struct insn_field rex_prefix;   /* REX prefix */
      74             :         struct insn_field vex_prefix;   /* VEX prefix */
      75             :         struct insn_field opcode;       /*
      76             :                                          * opcode.bytes[0]: opcode1
      77             :                                          * opcode.bytes[1]: opcode2
      78             :                                          * opcode.bytes[2]: opcode3
      79             :                                          */
      80             :         struct insn_field modrm;
      81             :         struct insn_field sib;
      82             :         struct insn_field displacement;
      83             :         union {
      84             :                 struct insn_field immediate;
      85             :                 struct insn_field moffset1;     /* for 64bit MOV */
      86             :                 struct insn_field immediate1;   /* for 64bit imm or off16/32 */
      87             :         };
      88             :         union {
      89             :                 struct insn_field moffset2;     /* for 64bit MOV */
      90             :                 struct insn_field immediate2;   /* for 64bit imm or seg16 */
      91             :         };
      92             : 
      93             :         int     emulate_prefix_size;
      94             :         insn_attr_t attr;
      95             :         unsigned char opnd_bytes;
      96             :         unsigned char addr_bytes;
      97             :         unsigned char length;
      98             :         unsigned char x86_64;
      99             : 
     100             :         const insn_byte_t *kaddr;       /* kernel address of insn to analyze */
     101             :         const insn_byte_t *end_kaddr;   /* kernel address of last insn in buffer */
     102             :         const insn_byte_t *next_byte;
     103             : };
     104             : 
     105             : #define MAX_INSN_SIZE   15
     106             : 
     107             : #define X86_MODRM_MOD(modrm) (((modrm) & 0xc0) >> 6)
     108             : #define X86_MODRM_REG(modrm) (((modrm) & 0x38) >> 3)
     109             : #define X86_MODRM_RM(modrm) ((modrm) & 0x07)
     110             : 
     111             : #define X86_SIB_SCALE(sib) (((sib) & 0xc0) >> 6)
     112             : #define X86_SIB_INDEX(sib) (((sib) & 0x38) >> 3)
     113             : #define X86_SIB_BASE(sib) ((sib) & 0x07)
     114             : 
     115             : #define X86_REX_W(rex) ((rex) & 8)
     116             : #define X86_REX_R(rex) ((rex) & 4)
     117             : #define X86_REX_X(rex) ((rex) & 2)
     118             : #define X86_REX_B(rex) ((rex) & 1)
     119             : 
     120             : /* VEX bit flags  */
     121             : #define X86_VEX_W(vex)  ((vex) & 0x80)      /* VEX3 Byte2 */
     122             : #define X86_VEX_R(vex)  ((vex) & 0x80)      /* VEX2/3 Byte1 */
     123             : #define X86_VEX_X(vex)  ((vex) & 0x40)      /* VEX3 Byte1 */
     124             : #define X86_VEX_B(vex)  ((vex) & 0x20)      /* VEX3 Byte1 */
     125             : #define X86_VEX_L(vex)  ((vex) & 0x04)      /* VEX3 Byte2, VEX2 Byte1 */
     126             : /* VEX bit fields */
     127             : #define X86_EVEX_M(vex) ((vex) & 0x03)              /* EVEX Byte1 */
     128             : #define X86_VEX3_M(vex) ((vex) & 0x1f)              /* VEX3 Byte1 */
     129             : #define X86_VEX2_M      1                       /* VEX2.M always 1 */
     130             : #define X86_VEX_V(vex)  (((vex) & 0x78) >> 3) /* VEX3 Byte2, VEX2 Byte1 */
     131             : #define X86_VEX_P(vex)  ((vex) & 0x03)              /* VEX3 Byte2, VEX2 Byte1 */
     132             : #define X86_VEX_M_MAX   0x1f                    /* VEX3.M Maximum value */
     133             : 
     134             : extern void insn_init(struct insn *insn, const void *kaddr, int buf_len, int x86_64);
     135             : extern void insn_get_prefixes(struct insn *insn);
     136             : extern void insn_get_opcode(struct insn *insn);
     137             : extern void insn_get_modrm(struct insn *insn);
     138             : extern void insn_get_sib(struct insn *insn);
     139             : extern void insn_get_displacement(struct insn *insn);
     140             : extern void insn_get_immediate(struct insn *insn);
     141             : extern void insn_get_length(struct insn *insn);
     142             : 
     143             : /* Attribute will be determined after getting ModRM (for opcode groups) */
     144             : static inline void insn_get_attribute(struct insn *insn)
     145             : {
     146             :         insn_get_modrm(insn);
     147             : }
     148             : 
     149             : /* Instruction uses RIP-relative addressing */
     150             : extern int insn_rip_relative(struct insn *insn);
     151             : 
     152             : /* Init insn for kernel text */
     153          38 : static inline void kernel_insn_init(struct insn *insn,
     154             :                                     const void *kaddr, int buf_len)
     155             : {
     156             : #ifdef CONFIG_X86_64
     157          38 :         insn_init(insn, kaddr, buf_len, 1);
     158             : #else /* CONFIG_X86_32 */
     159             :         insn_init(insn, kaddr, buf_len, 0);
     160             : #endif
     161             : }
     162             : 
     163          38 : static inline int insn_is_avx(struct insn *insn)
     164             : {
     165          38 :         if (!insn->prefixes.got)
     166           0 :                 insn_get_prefixes(insn);
     167          38 :         return (insn->vex_prefix.value != 0);
     168             : }
     169             : 
     170           0 : static inline int insn_is_evex(struct insn *insn)
     171             : {
     172           0 :         if (!insn->prefixes.got)
     173           0 :                 insn_get_prefixes(insn);
     174           0 :         return (insn->vex_prefix.nbytes == 4);
     175             : }
     176             : 
     177             : static inline int insn_has_emulate_prefix(struct insn *insn)
     178             : {
     179             :         return !!insn->emulate_prefix_size;
     180             : }
     181             : 
     182             : /* Ensure this instruction is decoded completely */
     183          38 : static inline int insn_complete(struct insn *insn)
     184             : {
     185          38 :         return insn->opcode.got && insn->modrm.got && insn->sib.got &&
     186          76 :                 insn->displacement.got && insn->immediate.got;
     187             : }
     188             : 
     189           0 : static inline insn_byte_t insn_vex_m_bits(struct insn *insn)
     190             : {
     191           0 :         if (insn->vex_prefix.nbytes == 2)    /* 2 bytes VEX */
     192             :                 return X86_VEX2_M;
     193           0 :         else if (insn->vex_prefix.nbytes == 3)       /* 3 bytes VEX */
     194           0 :                 return X86_VEX3_M(insn->vex_prefix.bytes[1]);
     195             :         else                                    /* EVEX */
     196           0 :                 return X86_EVEX_M(insn->vex_prefix.bytes[1]);
     197             : }
     198             : 
     199           0 : static inline insn_byte_t insn_vex_p_bits(struct insn *insn)
     200             : {
     201           0 :         if (insn->vex_prefix.nbytes == 2)    /* 2 bytes VEX */
     202           0 :                 return X86_VEX_P(insn->vex_prefix.bytes[1]);
     203             :         else
     204           0 :                 return X86_VEX_P(insn->vex_prefix.bytes[2]);
     205             : }
     206             : 
     207             : /* Get the last prefix id from last prefix or VEX prefix */
     208           0 : static inline int insn_last_prefix_id(struct insn *insn)
     209             : {
     210           0 :         if (insn_is_avx(insn))
     211           0 :                 return insn_vex_p_bits(insn);   /* VEX_p is a SIMD prefix id */
     212             : 
     213           0 :         if (insn->prefixes.bytes[3])
     214           0 :                 return inat_get_last_prefix_id(insn->prefixes.bytes[3]);
     215             : 
     216             :         return 0;
     217             : }
     218             : 
     219             : /* Offset of each field from kaddr */
     220             : static inline int insn_offset_rex_prefix(struct insn *insn)
     221             : {
     222             :         return insn->prefixes.nbytes;
     223             : }
     224             : static inline int insn_offset_vex_prefix(struct insn *insn)
     225             : {
     226             :         return insn_offset_rex_prefix(insn) + insn->rex_prefix.nbytes;
     227             : }
     228             : static inline int insn_offset_opcode(struct insn *insn)
     229             : {
     230             :         return insn_offset_vex_prefix(insn) + insn->vex_prefix.nbytes;
     231             : }
     232             : static inline int insn_offset_modrm(struct insn *insn)
     233             : {
     234             :         return insn_offset_opcode(insn) + insn->opcode.nbytes;
     235             : }
     236             : static inline int insn_offset_sib(struct insn *insn)
     237             : {
     238             :         return insn_offset_modrm(insn) + insn->modrm.nbytes;
     239             : }
     240             : static inline int insn_offset_displacement(struct insn *insn)
     241             : {
     242             :         return insn_offset_sib(insn) + insn->sib.nbytes;
     243             : }
     244             : static inline int insn_offset_immediate(struct insn *insn)
     245             : {
     246             :         return insn_offset_displacement(insn) + insn->displacement.nbytes;
     247             : }
     248             : 
     249             : /**
     250             :  * for_each_insn_prefix() -- Iterate prefixes in the instruction
     251             :  * @insn: Pointer to struct insn.
     252             :  * @idx:  Index storage.
     253             :  * @prefix: Prefix byte.
     254             :  *
     255             :  * Iterate prefix bytes of given @insn. Each prefix byte is stored in @prefix
     256             :  * and the index is stored in @idx (note that this @idx is just for a cursor,
     257             :  * do not change it.)
     258             :  * Since prefixes.nbytes can be bigger than 4 if some prefixes
     259             :  * are repeated, it cannot be used for looping over the prefixes.
     260             :  */
     261             : #define for_each_insn_prefix(insn, idx, prefix) \
     262             :         for (idx = 0; idx < ARRAY_SIZE(insn->prefixes.bytes) && (prefix = insn->prefixes.bytes[idx]) != 0; idx++)
     263             : 
     264             : #define POP_SS_OPCODE 0x1f
     265             : #define MOV_SREG_OPCODE 0x8e
     266             : 
     267             : /*
     268             :  * Intel SDM Vol.3A 6.8.3 states;
     269             :  * "Any single-step trap that would be delivered following the MOV to SS
     270             :  * instruction or POP to SS instruction (because EFLAGS.TF is 1) is
     271             :  * suppressed."
     272             :  * This function returns true if @insn is MOV SS or POP SS. On these
     273             :  * instructions, single stepping is suppressed.
     274             :  */
     275             : static inline int insn_masking_exception(struct insn *insn)
     276             : {
     277             :         return insn->opcode.bytes[0] == POP_SS_OPCODE ||
     278             :                 (insn->opcode.bytes[0] == MOV_SREG_OPCODE &&
     279             :                  X86_MODRM_REG(insn->modrm.bytes[0]) == 2);
     280             : }
     281             : 
     282             : #endif /* _ASM_X86_INSN_H */

Generated by: LCOV version 1.14