| Paul Gortmaker | 50af5ea | 2012-01-20 18:35:53 -0500 | [diff] [blame] | 1 | #include <linux/bug.h> | 
| Vegard Nossum | ac61a75 | 2009-02-27 11:35:55 +0100 | [diff] [blame] | 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 | } |