cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

instructions.c (7791B)


      1// SPDX-License-Identifier: GPL-2.0
      2static struct ins x86__instructions[] = {
      3	{ .name = "adc",	.ops = &mov_ops,  },
      4	{ .name = "adcb",	.ops = &mov_ops,  },
      5	{ .name = "adcl",	.ops = &mov_ops,  },
      6	{ .name = "add",	.ops = &mov_ops,  },
      7	{ .name = "addl",	.ops = &mov_ops,  },
      8	{ .name = "addq",	.ops = &mov_ops,  },
      9	{ .name = "addsd",	.ops = &mov_ops,  },
     10	{ .name = "addw",	.ops = &mov_ops,  },
     11	{ .name = "and",	.ops = &mov_ops,  },
     12	{ .name = "andb",	.ops = &mov_ops,  },
     13	{ .name = "andl",	.ops = &mov_ops,  },
     14	{ .name = "andpd",	.ops = &mov_ops,  },
     15	{ .name = "andps",	.ops = &mov_ops,  },
     16	{ .name = "andq",	.ops = &mov_ops,  },
     17	{ .name = "andw",	.ops = &mov_ops,  },
     18	{ .name = "bsr",	.ops = &mov_ops,  },
     19	{ .name = "bt",		.ops = &mov_ops,  },
     20	{ .name = "btr",	.ops = &mov_ops,  },
     21	{ .name = "bts",	.ops = &mov_ops,  },
     22	{ .name = "btsq",	.ops = &mov_ops,  },
     23	{ .name = "call",	.ops = &call_ops, },
     24	{ .name = "callq",	.ops = &call_ops, },
     25	{ .name = "cmovbe",	.ops = &mov_ops,  },
     26	{ .name = "cmove",	.ops = &mov_ops,  },
     27	{ .name = "cmovae",	.ops = &mov_ops,  },
     28	{ .name = "cmp",	.ops = &mov_ops,  },
     29	{ .name = "cmpb",	.ops = &mov_ops,  },
     30	{ .name = "cmpl",	.ops = &mov_ops,  },
     31	{ .name = "cmpq",	.ops = &mov_ops,  },
     32	{ .name = "cmpw",	.ops = &mov_ops,  },
     33	{ .name = "cmpxch",	.ops = &mov_ops,  },
     34	{ .name = "cmpxchg",	.ops = &mov_ops,  },
     35	{ .name = "cs",		.ops = &mov_ops,  },
     36	{ .name = "dec",	.ops = &dec_ops,  },
     37	{ .name = "decl",	.ops = &dec_ops,  },
     38	{ .name = "divsd",	.ops = &mov_ops,  },
     39	{ .name = "divss",	.ops = &mov_ops,  },
     40	{ .name = "gs",		.ops = &mov_ops,  },
     41	{ .name = "imul",	.ops = &mov_ops,  },
     42	{ .name = "inc",	.ops = &dec_ops,  },
     43	{ .name = "incl",	.ops = &dec_ops,  },
     44	{ .name = "ja",		.ops = &jump_ops, },
     45	{ .name = "jae",	.ops = &jump_ops, },
     46	{ .name = "jb",		.ops = &jump_ops, },
     47	{ .name = "jbe",	.ops = &jump_ops, },
     48	{ .name = "jc",		.ops = &jump_ops, },
     49	{ .name = "jcxz",	.ops = &jump_ops, },
     50	{ .name = "je",		.ops = &jump_ops, },
     51	{ .name = "jecxz",	.ops = &jump_ops, },
     52	{ .name = "jg",		.ops = &jump_ops, },
     53	{ .name = "jge",	.ops = &jump_ops, },
     54	{ .name = "jl",		.ops = &jump_ops, },
     55	{ .name = "jle",	.ops = &jump_ops, },
     56	{ .name = "jmp",	.ops = &jump_ops, },
     57	{ .name = "jmpq",	.ops = &jump_ops, },
     58	{ .name = "jna",	.ops = &jump_ops, },
     59	{ .name = "jnae",	.ops = &jump_ops, },
     60	{ .name = "jnb",	.ops = &jump_ops, },
     61	{ .name = "jnbe",	.ops = &jump_ops, },
     62	{ .name = "jnc",	.ops = &jump_ops, },
     63	{ .name = "jne",	.ops = &jump_ops, },
     64	{ .name = "jng",	.ops = &jump_ops, },
     65	{ .name = "jnge",	.ops = &jump_ops, },
     66	{ .name = "jnl",	.ops = &jump_ops, },
     67	{ .name = "jnle",	.ops = &jump_ops, },
     68	{ .name = "jno",	.ops = &jump_ops, },
     69	{ .name = "jnp",	.ops = &jump_ops, },
     70	{ .name = "jns",	.ops = &jump_ops, },
     71	{ .name = "jnz",	.ops = &jump_ops, },
     72	{ .name = "jo",		.ops = &jump_ops, },
     73	{ .name = "jp",		.ops = &jump_ops, },
     74	{ .name = "jpe",	.ops = &jump_ops, },
     75	{ .name = "jpo",	.ops = &jump_ops, },
     76	{ .name = "jrcxz",	.ops = &jump_ops, },
     77	{ .name = "js",		.ops = &jump_ops, },
     78	{ .name = "jz",		.ops = &jump_ops, },
     79	{ .name = "lea",	.ops = &mov_ops,  },
     80	{ .name = "lock",	.ops = &lock_ops, },
     81	{ .name = "mov",	.ops = &mov_ops,  },
     82	{ .name = "movapd",	.ops = &mov_ops,  },
     83	{ .name = "movaps",	.ops = &mov_ops,  },
     84	{ .name = "movb",	.ops = &mov_ops,  },
     85	{ .name = "movdqa",	.ops = &mov_ops,  },
     86	{ .name = "movdqu",	.ops = &mov_ops,  },
     87	{ .name = "movl",	.ops = &mov_ops,  },
     88	{ .name = "movq",	.ops = &mov_ops,  },
     89	{ .name = "movsd",	.ops = &mov_ops,  },
     90	{ .name = "movslq",	.ops = &mov_ops,  },
     91	{ .name = "movss",	.ops = &mov_ops,  },
     92	{ .name = "movupd",	.ops = &mov_ops,  },
     93	{ .name = "movups",	.ops = &mov_ops,  },
     94	{ .name = "movw",	.ops = &mov_ops,  },
     95	{ .name = "movzbl",	.ops = &mov_ops,  },
     96	{ .name = "movzwl",	.ops = &mov_ops,  },
     97	{ .name = "mulsd",	.ops = &mov_ops,  },
     98	{ .name = "mulss",	.ops = &mov_ops,  },
     99	{ .name = "nop",	.ops = &nop_ops,  },
    100	{ .name = "nopl",	.ops = &nop_ops,  },
    101	{ .name = "nopw",	.ops = &nop_ops,  },
    102	{ .name = "or",		.ops = &mov_ops,  },
    103	{ .name = "orb",	.ops = &mov_ops,  },
    104	{ .name = "orl",	.ops = &mov_ops,  },
    105	{ .name = "orps",	.ops = &mov_ops,  },
    106	{ .name = "orq",	.ops = &mov_ops,  },
    107	{ .name = "pand",	.ops = &mov_ops,  },
    108	{ .name = "paddq",	.ops = &mov_ops,  },
    109	{ .name = "pcmpeqb",	.ops = &mov_ops,  },
    110	{ .name = "por",	.ops = &mov_ops,  },
    111	{ .name = "rclb",	.ops = &mov_ops,  },
    112	{ .name = "rcll",	.ops = &mov_ops,  },
    113	{ .name = "ret",	.ops = &ret_ops,  },
    114	{ .name = "retq",	.ops = &ret_ops,  },
    115	{ .name = "sbb",	.ops = &mov_ops,  },
    116	{ .name = "sbbl",	.ops = &mov_ops,  },
    117	{ .name = "sete",	.ops = &mov_ops,  },
    118	{ .name = "sub",	.ops = &mov_ops,  },
    119	{ .name = "subl",	.ops = &mov_ops,  },
    120	{ .name = "subq",	.ops = &mov_ops,  },
    121	{ .name = "subsd",	.ops = &mov_ops,  },
    122	{ .name = "subw",	.ops = &mov_ops,  },
    123	{ .name = "test",	.ops = &mov_ops,  },
    124	{ .name = "testb",	.ops = &mov_ops,  },
    125	{ .name = "testl",	.ops = &mov_ops,  },
    126	{ .name = "ucomisd",	.ops = &mov_ops,  },
    127	{ .name = "ucomiss",	.ops = &mov_ops,  },
    128	{ .name = "vaddsd",	.ops = &mov_ops,  },
    129	{ .name = "vandpd",	.ops = &mov_ops,  },
    130	{ .name = "vmovdqa",	.ops = &mov_ops,  },
    131	{ .name = "vmovq",	.ops = &mov_ops,  },
    132	{ .name = "vmovsd",	.ops = &mov_ops,  },
    133	{ .name = "vmulsd",	.ops = &mov_ops,  },
    134	{ .name = "vorpd",	.ops = &mov_ops,  },
    135	{ .name = "vsubsd",	.ops = &mov_ops,  },
    136	{ .name = "vucomisd",	.ops = &mov_ops,  },
    137	{ .name = "xadd",	.ops = &mov_ops,  },
    138	{ .name = "xbeginl",	.ops = &jump_ops, },
    139	{ .name = "xbeginq",	.ops = &jump_ops, },
    140	{ .name = "xchg",	.ops = &mov_ops,  },
    141	{ .name = "xor",	.ops = &mov_ops, },
    142	{ .name = "xorb",	.ops = &mov_ops, },
    143	{ .name = "xorpd",	.ops = &mov_ops, },
    144	{ .name = "xorps",	.ops = &mov_ops, },
    145};
    146
    147static bool amd__ins_is_fused(struct arch *arch, const char *ins1,
    148			      const char *ins2)
    149{
    150	if (strstr(ins2, "jmp"))
    151		return false;
    152
    153	/* Family >= 15h supports cmp/test + branch fusion */
    154	if (arch->family >= 0x15 && (strstarts(ins1, "test") ||
    155	    (strstarts(ins1, "cmp") && !strstr(ins1, "xchg")))) {
    156		return true;
    157	}
    158
    159	/* Family >= 19h supports some ALU + branch fusion */
    160	if (arch->family >= 0x19 && (strstarts(ins1, "add") ||
    161	    strstarts(ins1, "sub") || strstarts(ins1, "and") ||
    162	    strstarts(ins1, "inc") || strstarts(ins1, "dec") ||
    163	    strstarts(ins1, "or") || strstarts(ins1, "xor"))) {
    164		return true;
    165	}
    166
    167	return false;
    168}
    169
    170static bool intel__ins_is_fused(struct arch *arch, const char *ins1,
    171				const char *ins2)
    172{
    173	if (arch->family != 6 || arch->model < 0x1e || strstr(ins2, "jmp"))
    174		return false;
    175
    176	if (arch->model == 0x1e) {
    177		/* Nehalem */
    178		if ((strstr(ins1, "cmp") && !strstr(ins1, "xchg")) ||
    179		     strstr(ins1, "test")) {
    180			return true;
    181		}
    182	} else {
    183		/* Newer platform */
    184		if ((strstr(ins1, "cmp") && !strstr(ins1, "xchg")) ||
    185		     strstr(ins1, "test") ||
    186		     strstr(ins1, "add") ||
    187		     strstr(ins1, "sub") ||
    188		     strstr(ins1, "and") ||
    189		     strstr(ins1, "inc") ||
    190		     strstr(ins1, "dec")) {
    191			return true;
    192		}
    193	}
    194
    195	return false;
    196}
    197
    198static int x86__cpuid_parse(struct arch *arch, char *cpuid)
    199{
    200	unsigned int family, model, stepping;
    201	int ret;
    202
    203	/*
    204	 * cpuid = "GenuineIntel,family,model,stepping"
    205	 */
    206	ret = sscanf(cpuid, "%*[^,],%u,%u,%u", &family, &model, &stepping);
    207	if (ret == 3) {
    208		arch->family = family;
    209		arch->model = model;
    210		arch->ins_is_fused = strstarts(cpuid, "AuthenticAMD") ?
    211					amd__ins_is_fused :
    212					intel__ins_is_fused;
    213		return 0;
    214	}
    215
    216	return -1;
    217}
    218
    219static int x86__annotate_init(struct arch *arch, char *cpuid)
    220{
    221	int err = 0;
    222
    223	if (arch->initialized)
    224		return 0;
    225
    226	if (cpuid) {
    227		if (x86__cpuid_parse(arch, cpuid))
    228			err = SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_CPUID_PARSING;
    229	}
    230
    231	arch->initialized = true;
    232	return err;
    233}