aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorJon Medhurst <tixy@yxit.co.uk>2011-08-28 11:35:11 -0400
committerJon Medhurst <tixy@yxit.co.uk>2011-09-20 14:17:43 -0400
commit68f360e753668b61366b7b4b2a5aa77ac5157c37 (patch)
tree41d56fb8ab553eb24da427f56e1cef6ad7da9830 /arch
parent2c89240b630e94c1a5949860b7bfcf28130bd9c8 (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.c103
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
449static 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
458static 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
481static 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
489struct table_test_args {
490 const union decode_item *root_table;
491 u32 parent_mask;
492 u32 parent_value;
493};
494
495static 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
520static 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
1120static int run_test_cases(void (*tests)(void)) 1206static 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