Commit | Line | Data |
---|---|---|
50af5ead | 1 | #include <linux/bug.h> |
ac61a757 VN |
2 | #include <linux/kernel.h> |
3 | ||
4 | #include "opcode.h" | |
5 | #include "selftest.h" | |
6 | ||
7 | struct selftest_opcode { | |
8 | unsigned int expected_size; | |
9 | const uint8_t *insn; | |
10 | const char *desc; | |
11 | }; | |
12 | ||
13 | static const struct selftest_opcode selftest_opcodes[] = { | |
14 | /* REP MOVS */ | |
15 | {1, "\xf3\xa4", "rep movsb <mem8>, <mem8>"}, | |
16 | {4, "\xf3\xa5", "rep movsl <mem32>, <mem32>"}, | |
17 | ||
18 | /* MOVZX / MOVZXD */ | |
19 | {1, "\x66\x0f\xb6\x51\xf8", "movzwq <mem8>, <reg16>"}, | |
20 | {1, "\x0f\xb6\x51\xf8", "movzwq <mem8>, <reg32>"}, | |
21 | ||
22 | /* MOVSX / MOVSXD */ | |
23 | {1, "\x66\x0f\xbe\x51\xf8", "movswq <mem8>, <reg16>"}, | |
24 | {1, "\x0f\xbe\x51\xf8", "movswq <mem8>, <reg32>"}, | |
25 | ||
26 | #ifdef CONFIG_X86_64 | |
27 | /* MOVZX / MOVZXD */ | |
28 | {1, "\x49\x0f\xb6\x51\xf8", "movzbq <mem8>, <reg64>"}, | |
29 | {2, "\x49\x0f\xb7\x51\xf8", "movzbq <mem16>, <reg64>"}, | |
30 | ||
31 | /* MOVSX / MOVSXD */ | |
32 | {1, "\x49\x0f\xbe\x51\xf8", "movsbq <mem8>, <reg64>"}, | |
33 | {2, "\x49\x0f\xbf\x51\xf8", "movsbq <mem16>, <reg64>"}, | |
34 | {4, "\x49\x63\x51\xf8", "movslq <mem32>, <reg64>"}, | |
35 | #endif | |
36 | }; | |
37 | ||
38 | static bool selftest_opcode_one(const struct selftest_opcode *op) | |
39 | { | |
40 | unsigned size; | |
41 | ||
42 | kmemcheck_opcode_decode(op->insn, &size); | |
43 | ||
44 | if (size == op->expected_size) | |
45 | return true; | |
46 | ||
47 | printk(KERN_WARNING "kmemcheck: opcode %s: expected size %d, got %d\n", | |
48 | op->desc, op->expected_size, size); | |
49 | return false; | |
50 | } | |
51 | ||
52 | static bool selftest_opcodes_all(void) | |
53 | { | |
54 | bool pass = true; | |
55 | unsigned int i; | |
56 | ||
57 | for (i = 0; i < ARRAY_SIZE(selftest_opcodes); ++i) | |
58 | pass = pass && selftest_opcode_one(&selftest_opcodes[i]); | |
59 | ||
60 | return pass; | |
61 | } | |
62 | ||
63 | bool kmemcheck_selftest(void) | |
64 | { | |
65 | bool pass = true; | |
66 | ||
67 | pass = pass && selftest_opcodes_all(); | |
68 | ||
69 | return pass; | |
70 | } |