diff options
author | Jon Medhurst <tixy@yxit.co.uk> | 2011-08-28 11:35:11 -0400 |
---|---|---|
committer | Jon Medhurst <tixy@yxit.co.uk> | 2011-09-20 14:17:43 -0400 |
commit | 68f360e753668b61366b7b4b2a5aa77ac5157c37 (patch) | |
tree | 41d56fb8ab553eb24da427f56e1cef6ad7da9830 /arch | |
parent | 2c89240b630e94c1a5949860b7bfcf28130bd9c8 (diff) |
ARM: kprobes: Add decoding table self-consistency tests
These check that the bitmask and match value used in the decoding tables
are self consistent.
Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
Acked-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/kernel/kprobes-test.c | 103 |
1 files changed, 99 insertions, 4 deletions
diff --git a/arch/arm/kernel/kprobes-test.c b/arch/arm/kernel/kprobes-test.c index b12be0fe183c..6c0946c023f8 100644 --- a/arch/arm/kernel/kprobes-test.c +++ b/arch/arm/kernel/kprobes-test.c | |||
@@ -443,6 +443,92 @@ static int run_api_tests(long (*func)(long, long)) | |||
443 | 443 | ||
444 | 444 | ||
445 | /* | 445 | /* |
446 | * Decoding table self-consistency tests | ||
447 | */ | ||
448 | |||
449 | static const int decode_struct_sizes[NUM_DECODE_TYPES] = { | ||
450 | [DECODE_TYPE_TABLE] = sizeof(struct decode_table), | ||
451 | [DECODE_TYPE_CUSTOM] = sizeof(struct decode_custom), | ||
452 | [DECODE_TYPE_SIMULATE] = sizeof(struct decode_simulate), | ||
453 | [DECODE_TYPE_EMULATE] = sizeof(struct decode_emulate), | ||
454 | [DECODE_TYPE_OR] = sizeof(struct decode_or), | ||
455 | [DECODE_TYPE_REJECT] = sizeof(struct decode_reject) | ||
456 | }; | ||
457 | |||
458 | static int table_iter(const union decode_item *table, | ||
459 | int (*fn)(const struct decode_header *, void *), | ||
460 | void *args) | ||
461 | { | ||
462 | const struct decode_header *h = (struct decode_header *)table; | ||
463 | int result; | ||
464 | |||
465 | for (;;) { | ||
466 | enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK; | ||
467 | |||
468 | if (type == DECODE_TYPE_END) | ||
469 | return 0; | ||
470 | |||
471 | result = fn(h, args); | ||
472 | if (result) | ||
473 | return result; | ||
474 | |||
475 | h = (struct decode_header *) | ||
476 | ((uintptr_t)h + decode_struct_sizes[type]); | ||
477 | |||
478 | } | ||
479 | } | ||
480 | |||
481 | static int table_test_fail(const struct decode_header *h, const char* message) | ||
482 | { | ||
483 | |||
484 | pr_err("FAIL: kprobes test failure \"%s\" (mask %08x, value %08x)\n", | ||
485 | message, h->mask.bits, h->value.bits); | ||
486 | return -EINVAL; | ||
487 | } | ||
488 | |||
489 | struct table_test_args { | ||
490 | const union decode_item *root_table; | ||
491 | u32 parent_mask; | ||
492 | u32 parent_value; | ||
493 | }; | ||
494 | |||
495 | static int table_test_fn(const struct decode_header *h, void *args) | ||
496 | { | ||
497 | struct table_test_args *a = (struct table_test_args *)args; | ||
498 | enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK; | ||
499 | |||
500 | if (h->value.bits & ~h->mask.bits) | ||
501 | return table_test_fail(h, "Match value has bits not in mask"); | ||
502 | |||
503 | if ((h->mask.bits & a->parent_mask) != a->parent_mask) | ||
504 | return table_test_fail(h, "Mask has bits not in parent mask"); | ||
505 | |||
506 | if ((h->value.bits ^ a->parent_value) & a->parent_mask) | ||
507 | return table_test_fail(h, "Value is inconsistent with parent"); | ||
508 | |||
509 | if (type == DECODE_TYPE_TABLE) { | ||
510 | struct decode_table *d = (struct decode_table *)h; | ||
511 | struct table_test_args args2 = *a; | ||
512 | args2.parent_mask = h->mask.bits; | ||
513 | args2.parent_value = h->value.bits; | ||
514 | return table_iter(d->table.table, table_test_fn, &args2); | ||
515 | } | ||
516 | |||
517 | return 0; | ||
518 | } | ||
519 | |||
520 | static int table_test(const union decode_item *table) | ||
521 | { | ||
522 | struct table_test_args args = { | ||
523 | .root_table = table, | ||
524 | .parent_mask = 0, | ||
525 | .parent_value = 0 | ||
526 | }; | ||
527 | return table_iter(args.root_table, table_test_fn, &args); | ||
528 | } | ||
529 | |||
530 | |||
531 | /* | ||
446 | * Framework for instruction set test cases | 532 | * Framework for instruction set test cases |
447 | */ | 533 | */ |
448 | 534 | ||
@@ -1117,8 +1203,15 @@ end: | |||
1117 | * Top level test functions | 1203 | * Top level test functions |
1118 | */ | 1204 | */ |
1119 | 1205 | ||
1120 | static int run_test_cases(void (*tests)(void)) | 1206 | static int run_test_cases(void (*tests)(void), const union decode_item *table) |
1121 | { | 1207 | { |
1208 | int ret; | ||
1209 | |||
1210 | pr_info(" Check decoding tables\n"); | ||
1211 | ret = table_test(table); | ||
1212 | if (ret) | ||
1213 | return ret; | ||
1214 | |||
1122 | pr_info(" Run test cases\n"); | 1215 | pr_info(" Run test cases\n"); |
1123 | tests(); | 1216 | tests(); |
1124 | 1217 | ||
@@ -1140,7 +1233,7 @@ static int __init run_all_tests(void) | |||
1140 | goto out; | 1233 | goto out; |
1141 | 1234 | ||
1142 | pr_info("ARM instruction simulation\n"); | 1235 | pr_info("ARM instruction simulation\n"); |
1143 | ret = run_test_cases(kprobe_arm_test_cases); | 1236 | ret = run_test_cases(kprobe_arm_test_cases, kprobe_decode_arm_table); |
1144 | if (ret) | 1237 | if (ret) |
1145 | goto out; | 1238 | goto out; |
1146 | 1239 | ||
@@ -1162,12 +1255,14 @@ static int __init run_all_tests(void) | |||
1162 | goto out; | 1255 | goto out; |
1163 | 1256 | ||
1164 | pr_info("16-bit Thumb instruction simulation\n"); | 1257 | pr_info("16-bit Thumb instruction simulation\n"); |
1165 | ret = run_test_cases(kprobe_thumb16_test_cases); | 1258 | ret = run_test_cases(kprobe_thumb16_test_cases, |
1259 | kprobe_decode_thumb16_table); | ||
1166 | if (ret) | 1260 | if (ret) |
1167 | goto out; | 1261 | goto out; |
1168 | 1262 | ||
1169 | pr_info("32-bit Thumb instruction simulation\n"); | 1263 | pr_info("32-bit Thumb instruction simulation\n"); |
1170 | ret = run_test_cases(kprobe_thumb32_test_cases); | 1264 | ret = run_test_cases(kprobe_thumb32_test_cases, |
1265 | kprobe_decode_thumb32_table); | ||
1171 | if (ret) | 1266 | if (ret) |
1172 | goto out; | 1267 | goto out; |
1173 | #endif | 1268 | #endif |