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