LCOV - code coverage report
Current view: top level - arch/x86/include/asm - insn.h (source / functions) Hit Total Coverage
Test: combined.info Lines: 8 47 17.0 %
Date: 2022-04-01 14:58:12 Functions: 0 1 0.0 %
Branches: 7 44 15.9 %

           Branch data     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                 :            : /* insn_attr_t is defined in inat.h */
      11                 :            : #include <asm/inat.h>
      12                 :            : 
      13                 :            : struct insn_field {
      14                 :            :         union {
      15                 :            :                 insn_value_t value;
      16                 :            :                 insn_byte_t bytes[4];
      17                 :            :         };
      18                 :            :         /* !0 if we've run insn_get_xxx() for this field */
      19                 :            :         unsigned char got;
      20                 :            :         unsigned char nbytes;
      21                 :            : };
      22                 :            : 
      23                 :            : struct insn {
      24                 :            :         struct insn_field prefixes;     /*
      25                 :            :                                          * Prefixes
      26                 :            :                                          * prefixes.bytes[3]: last prefix
      27                 :            :                                          */
      28                 :            :         struct insn_field rex_prefix;   /* REX prefix */
      29                 :            :         struct insn_field vex_prefix;   /* VEX prefix */
      30                 :            :         struct insn_field opcode;       /*
      31                 :            :                                          * opcode.bytes[0]: opcode1
      32                 :            :                                          * opcode.bytes[1]: opcode2
      33                 :            :                                          * opcode.bytes[2]: opcode3
      34                 :            :                                          */
      35                 :            :         struct insn_field modrm;
      36                 :            :         struct insn_field sib;
      37                 :            :         struct insn_field displacement;
      38                 :            :         union {
      39                 :            :                 struct insn_field immediate;
      40                 :            :                 struct insn_field moffset1;     /* for 64bit MOV */
      41                 :            :                 struct insn_field immediate1;   /* for 64bit imm or off16/32 */
      42                 :            :         };
      43                 :            :         union {
      44                 :            :                 struct insn_field moffset2;     /* for 64bit MOV */
      45                 :            :                 struct insn_field immediate2;   /* for 64bit imm or seg16 */
      46                 :            :         };
      47                 :            : 
      48                 :            :         int     emulate_prefix_size;
      49                 :            :         insn_attr_t attr;
      50                 :            :         unsigned char opnd_bytes;
      51                 :            :         unsigned char addr_bytes;
      52                 :            :         unsigned char length;
      53                 :            :         unsigned char x86_64;
      54                 :            : 
      55                 :            :         const insn_byte_t *kaddr;       /* kernel address of insn to analyze */
      56                 :            :         const insn_byte_t *end_kaddr;   /* kernel address of last insn in buffer */
      57                 :            :         const insn_byte_t *next_byte;
      58                 :            : };
      59                 :            : 
      60                 :            : #define MAX_INSN_SIZE   15
      61                 :            : 
      62                 :            : #define X86_MODRM_MOD(modrm) (((modrm) & 0xc0) >> 6)
      63                 :            : #define X86_MODRM_REG(modrm) (((modrm) & 0x38) >> 3)
      64                 :            : #define X86_MODRM_RM(modrm) ((modrm) & 0x07)
      65                 :            : 
      66                 :            : #define X86_SIB_SCALE(sib) (((sib) & 0xc0) >> 6)
      67                 :            : #define X86_SIB_INDEX(sib) (((sib) & 0x38) >> 3)
      68                 :            : #define X86_SIB_BASE(sib) ((sib) & 0x07)
      69                 :            : 
      70                 :            : #define X86_REX_W(rex) ((rex) & 8)
      71                 :            : #define X86_REX_R(rex) ((rex) & 4)
      72                 :            : #define X86_REX_X(rex) ((rex) & 2)
      73                 :            : #define X86_REX_B(rex) ((rex) & 1)
      74                 :            : 
      75                 :            : /* VEX bit flags  */
      76                 :            : #define X86_VEX_W(vex)  ((vex) & 0x80)      /* VEX3 Byte2 */
      77                 :            : #define X86_VEX_R(vex)  ((vex) & 0x80)      /* VEX2/3 Byte1 */
      78                 :            : #define X86_VEX_X(vex)  ((vex) & 0x40)      /* VEX3 Byte1 */
      79                 :            : #define X86_VEX_B(vex)  ((vex) & 0x20)      /* VEX3 Byte1 */
      80                 :            : #define X86_VEX_L(vex)  ((vex) & 0x04)      /* VEX3 Byte2, VEX2 Byte1 */
      81                 :            : /* VEX bit fields */
      82                 :            : #define X86_EVEX_M(vex) ((vex) & 0x03)              /* EVEX Byte1 */
      83                 :            : #define X86_VEX3_M(vex) ((vex) & 0x1f)              /* VEX3 Byte1 */
      84                 :            : #define X86_VEX2_M      1                       /* VEX2.M always 1 */
      85                 :            : #define X86_VEX_V(vex)  (((vex) & 0x78) >> 3) /* VEX3 Byte2, VEX2 Byte1 */
      86                 :            : #define X86_VEX_P(vex)  ((vex) & 0x03)              /* VEX3 Byte2, VEX2 Byte1 */
      87                 :            : #define X86_VEX_M_MAX   0x1f                    /* VEX3.M Maximum value */
      88                 :            : 
      89                 :            : extern void insn_init(struct insn *insn, const void *kaddr, int buf_len, int x86_64);
      90                 :            : extern void insn_get_prefixes(struct insn *insn);
      91                 :            : extern void insn_get_opcode(struct insn *insn);
      92                 :            : extern void insn_get_modrm(struct insn *insn);
      93                 :            : extern void insn_get_sib(struct insn *insn);
      94                 :            : extern void insn_get_displacement(struct insn *insn);
      95                 :            : extern void insn_get_immediate(struct insn *insn);
      96                 :            : extern void insn_get_length(struct insn *insn);
      97                 :            : 
      98                 :            : /* Attribute will be determined after getting ModRM (for opcode groups) */
      99                 :            : static inline void insn_get_attribute(struct insn *insn)
     100                 :            : {
     101                 :            :         insn_get_modrm(insn);
     102                 :            : }
     103                 :            : 
     104                 :            : /* Instruction uses RIP-relative addressing */
     105                 :            : extern int insn_rip_relative(struct insn *insn);
     106                 :            : 
     107                 :            : /* Init insn for kernel text */
     108                 :        165 : static inline void kernel_insn_init(struct insn *insn,
     109                 :            :                                     const void *kaddr, int buf_len)
     110                 :            : {
     111                 :            : #ifdef CONFIG_X86_64
     112                 :        165 :         insn_init(insn, kaddr, buf_len, 1);
     113                 :            : #else /* CONFIG_X86_32 */
     114                 :            :         insn_init(insn, kaddr, buf_len, 0);
     115                 :            : #endif
     116                 :            : }
     117                 :            : 
     118                 :        165 : static inline int insn_is_avx(struct insn *insn)
     119                 :            : {
     120   [ -  -  -  + ]:        165 :         if (!insn->prefixes.got)
     121                 :          0 :                 insn_get_prefixes(insn);
     122   [ -  -  -  + ]:        165 :         return (insn->vex_prefix.value != 0);
     123                 :            : }
     124                 :            : 
     125                 :          0 : static inline int insn_is_evex(struct insn *insn)
     126                 :            : {
     127         [ #  # ]:          0 :         if (!insn->prefixes.got)
     128                 :          0 :                 insn_get_prefixes(insn);
     129         [ #  # ]:          0 :         return (insn->vex_prefix.nbytes == 4);
     130                 :            : }
     131                 :            : 
     132                 :          0 : static inline int insn_has_emulate_prefix(struct insn *insn)
     133                 :            : {
     134         [ #  # ]:          0 :         return !!insn->emulate_prefix_size;
     135                 :            : }
     136                 :            : 
     137                 :            : /* Ensure this instruction is decoded completely */
     138                 :        165 : static inline int insn_complete(struct insn *insn)
     139                 :            : {
     140   [ +  -  +  - ]:        165 :         return insn->opcode.got && insn->modrm.got && insn->sib.got &&
     141   [ +  -  +  -  :        330 :                 insn->displacement.got && insn->immediate.got;
                   -  + ]
     142                 :            : }
     143                 :            : 
     144                 :          0 : static inline insn_byte_t insn_vex_m_bits(struct insn *insn)
     145                 :            : {
     146         [ #  # ]:          0 :         if (insn->vex_prefix.nbytes == 2)    /* 2 bytes VEX */
     147                 :            :                 return X86_VEX2_M;
     148         [ #  # ]:          0 :         else if (insn->vex_prefix.nbytes == 3)       /* 3 bytes VEX */
     149                 :          0 :                 return X86_VEX3_M(insn->vex_prefix.bytes[1]);
     150                 :            :         else                                    /* EVEX */
     151                 :          0 :                 return X86_EVEX_M(insn->vex_prefix.bytes[1]);
     152                 :            : }
     153                 :            : 
     154                 :          0 : static inline insn_byte_t insn_vex_p_bits(struct insn *insn)
     155                 :            : {
     156         [ #  # ]:          0 :         if (insn->vex_prefix.nbytes == 2)    /* 2 bytes VEX */
     157                 :          0 :                 return X86_VEX_P(insn->vex_prefix.bytes[1]);
     158                 :            :         else
     159                 :          0 :                 return X86_VEX_P(insn->vex_prefix.bytes[2]);
     160                 :            : }
     161                 :            : 
     162                 :            : /* Get the last prefix id from last prefix or VEX prefix */
     163                 :          0 : static inline int insn_last_prefix_id(struct insn *insn)
     164                 :            : {
     165   [ #  #  #  # ]:          0 :         if (insn_is_avx(insn))
     166         [ #  # ]:          0 :                 return insn_vex_p_bits(insn);   /* VEX_p is a SIMD prefix id */
     167                 :            : 
     168         [ #  # ]:          0 :         if (insn->prefixes.bytes[3])
     169                 :          0 :                 return inat_get_last_prefix_id(insn->prefixes.bytes[3]);
     170                 :            : 
     171                 :            :         return 0;
     172                 :            : }
     173                 :            : 
     174                 :            : /* Offset of each field from kaddr */
     175                 :          0 : static inline int insn_offset_rex_prefix(struct insn *insn)
     176                 :            : {
     177                 :          0 :         return insn->prefixes.nbytes;
     178                 :            : }
     179                 :          0 : static inline int insn_offset_vex_prefix(struct insn *insn)
     180                 :            : {
     181                 :          0 :         return insn_offset_rex_prefix(insn) + insn->rex_prefix.nbytes;
     182                 :            : }
     183                 :          0 : static inline int insn_offset_opcode(struct insn *insn)
     184                 :            : {
     185                 :          0 :         return insn_offset_vex_prefix(insn) + insn->vex_prefix.nbytes;
     186                 :            : }
     187                 :          0 : static inline int insn_offset_modrm(struct insn *insn)
     188                 :            : {
     189                 :          0 :         return insn_offset_opcode(insn) + insn->opcode.nbytes;
     190                 :            : }
     191                 :          0 : static inline int insn_offset_sib(struct insn *insn)
     192                 :            : {
     193                 :          0 :         return insn_offset_modrm(insn) + insn->modrm.nbytes;
     194                 :            : }
     195                 :          0 : static inline int insn_offset_displacement(struct insn *insn)
     196                 :            : {
     197                 :          0 :         return insn_offset_sib(insn) + insn->sib.nbytes;
     198                 :            : }
     199                 :          0 : static inline int insn_offset_immediate(struct insn *insn)
     200                 :            : {
     201                 :          0 :         return insn_offset_displacement(insn) + insn->displacement.nbytes;
     202                 :            : }
     203                 :            : 
     204                 :            : #define POP_SS_OPCODE 0x1f
     205                 :            : #define MOV_SREG_OPCODE 0x8e
     206                 :            : 
     207                 :            : /*
     208                 :            :  * Intel SDM Vol.3A 6.8.3 states;
     209                 :            :  * "Any single-step trap that would be delivered following the MOV to SS
     210                 :            :  * instruction or POP to SS instruction (because EFLAGS.TF is 1) is
     211                 :            :  * suppressed."
     212                 :            :  * This function returns true if @insn is MOV SS or POP SS. On these
     213                 :            :  * instructions, single stepping is suppressed.
     214                 :            :  */
     215                 :          0 : static inline int insn_masking_exception(struct insn *insn)
     216                 :            : {
     217   [ #  #  #  # ]:          0 :         return insn->opcode.bytes[0] == POP_SS_OPCODE ||
     218                 :          0 :                 (insn->opcode.bytes[0] == MOV_SREG_OPCODE &&
     219         [ #  # ]:          0 :                  X86_MODRM_REG(insn->modrm.bytes[0]) == 2);
     220                 :            : }
     221                 :            : 
     222                 :            : #endif /* _ASM_X86_INSN_H */

Generated by: LCOV version 1.14