aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorJon Medhurst <tixy@yxit.co.uk>2011-08-28 11:38:35 -0400
committerJon Medhurst <tixy@yxit.co.uk>2011-09-20 14:17:44 -0400
commit963780dfe390e80e148eb84f0c84a01533a64d28 (patch)
treef89638b13a62b240886bc9363f857df6c8d4b290 /arch/arm
parent68f360e753668b61366b7b4b2a5aa77ac5157c37 (diff)
ARM: kprobes: Add decoding table test coverage analysis
This is used to verify that all combinations of CPU instructions described by the kprobes decoding tables have a test case. Signed-off-by: Jon Medhurst <tixy@yxit.co.uk> Acked-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/kernel/kprobes-test.c261
1 files changed, 261 insertions, 0 deletions
diff --git a/arch/arm/kernel/kprobes-test.c b/arch/arm/kernel/kprobes-test.c
index 6c0946c023f8..fe169e934d42 100644
--- a/arch/arm/kernel/kprobes-test.c
+++ b/arch/arm/kernel/kprobes-test.c
@@ -178,6 +178,7 @@
178 178
179#include <linux/kernel.h> 179#include <linux/kernel.h>
180#include <linux/module.h> 180#include <linux/module.h>
181#include <linux/slab.h>
181#include <linux/kprobes.h> 182#include <linux/kprobes.h>
182 183
183#include "kprobes.h" 184#include "kprobes.h"
@@ -529,6 +530,250 @@ static int table_test(const union decode_item *table)
529 530
530 531
531/* 532/*
533 * Decoding table test coverage analysis
534 *
535 * coverage_start() builds a coverage_table which contains a list of
536 * coverage_entry's to match each entry in the specified kprobes instruction
537 * decoding table.
538 *
539 * When test cases are run, coverage_add() is called to process each case.
540 * This looks up the corresponding entry in the coverage_table and sets it as
541 * being matched, as well as clearing the regs flag appropriate for the test.
542 *
543 * After all test cases have been run, coverage_end() is called to check that
544 * all entries in coverage_table have been matched and that all regs flags are
545 * cleared. I.e. that all possible combinations of instructions described by
546 * the kprobes decoding tables have had a test case executed for them.
547 */
548
549bool coverage_fail;
550
551#define MAX_COVERAGE_ENTRIES 256
552
553struct coverage_entry {
554 const struct decode_header *header;
555 unsigned regs;
556 unsigned nesting;
557 char matched;
558};
559
560struct coverage_table {
561 struct coverage_entry *base;
562 unsigned num_entries;
563 unsigned nesting;
564};
565
566struct coverage_table coverage;
567
568#define COVERAGE_ANY_REG (1<<0)
569#define COVERAGE_SP (1<<1)
570#define COVERAGE_PC (1<<2)
571#define COVERAGE_PCWB (1<<3)
572
573static const char coverage_register_lookup[16] = {
574 [REG_TYPE_ANY] = COVERAGE_ANY_REG | COVERAGE_SP | COVERAGE_PC,
575 [REG_TYPE_SAMEAS16] = COVERAGE_ANY_REG,
576 [REG_TYPE_SP] = COVERAGE_SP,
577 [REG_TYPE_PC] = COVERAGE_PC,
578 [REG_TYPE_NOSP] = COVERAGE_ANY_REG | COVERAGE_SP,
579 [REG_TYPE_NOSPPC] = COVERAGE_ANY_REG | COVERAGE_SP | COVERAGE_PC,
580 [REG_TYPE_NOPC] = COVERAGE_ANY_REG | COVERAGE_PC,
581 [REG_TYPE_NOPCWB] = COVERAGE_ANY_REG | COVERAGE_PC | COVERAGE_PCWB,
582 [REG_TYPE_NOPCX] = COVERAGE_ANY_REG,
583 [REG_TYPE_NOSPPCX] = COVERAGE_ANY_REG | COVERAGE_SP,
584};
585
586unsigned coverage_start_registers(const struct decode_header *h)
587{
588 unsigned regs = 0;
589 int i;
590 for (i = 0; i < 20; i += 4) {
591 int r = (h->type_regs.bits >> (DECODE_TYPE_BITS + i)) & 0xf;
592 regs |= coverage_register_lookup[r] << i;
593 }
594 return regs;
595}
596
597static int coverage_start_fn(const struct decode_header *h, void *args)
598{
599 struct coverage_table *coverage = (struct coverage_table *)args;
600 enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
601 struct coverage_entry *entry = coverage->base + coverage->num_entries;
602
603 if (coverage->num_entries == MAX_COVERAGE_ENTRIES - 1) {
604 pr_err("FAIL: Out of space for test coverage data");
605 return -ENOMEM;
606 }
607
608 ++coverage->num_entries;
609
610 entry->header = h;
611 entry->regs = coverage_start_registers(h);
612 entry->nesting = coverage->nesting;
613 entry->matched = false;
614
615 if (type == DECODE_TYPE_TABLE) {
616 struct decode_table *d = (struct decode_table *)h;
617 int ret;
618 ++coverage->nesting;
619 ret = table_iter(d->table.table, coverage_start_fn, coverage);
620 --coverage->nesting;
621 return ret;
622 }
623
624 return 0;
625}
626
627static int coverage_start(const union decode_item *table)
628{
629 coverage.base = kmalloc(MAX_COVERAGE_ENTRIES *
630 sizeof(struct coverage_entry), GFP_KERNEL);
631 coverage.num_entries = 0;
632 coverage.nesting = 0;
633 return table_iter(table, coverage_start_fn, &coverage);
634}
635
636static void
637coverage_add_registers(struct coverage_entry *entry, kprobe_opcode_t insn)
638{
639 int regs = entry->header->type_regs.bits >> DECODE_TYPE_BITS;
640 int i;
641 for (i = 0; i < 20; i += 4) {
642 enum decode_reg_type reg_type = (regs >> i) & 0xf;
643 int reg = (insn >> i) & 0xf;
644 int flag;
645
646 if (!reg_type)
647 continue;
648
649 if (reg == 13)
650 flag = COVERAGE_SP;
651 else if (reg == 15)
652 flag = COVERAGE_PC;
653 else
654 flag = COVERAGE_ANY_REG;
655 entry->regs &= ~(flag << i);
656
657 switch (reg_type) {
658
659 case REG_TYPE_NONE:
660 case REG_TYPE_ANY:
661 case REG_TYPE_SAMEAS16:
662 break;
663
664 case REG_TYPE_SP:
665 if (reg != 13)
666 return;
667 break;
668
669 case REG_TYPE_PC:
670 if (reg != 15)
671 return;
672 break;
673
674 case REG_TYPE_NOSP:
675 if (reg == 13)
676 return;
677 break;
678
679 case REG_TYPE_NOSPPC:
680 case REG_TYPE_NOSPPCX:
681 if (reg == 13 || reg == 15)
682 return;
683 break;
684
685 case REG_TYPE_NOPCWB:
686 if (!is_writeback(insn))
687 break;
688 if (reg == 15) {
689 entry->regs &= ~(COVERAGE_PCWB << i);
690 return;
691 }
692 break;
693
694 case REG_TYPE_NOPC:
695 case REG_TYPE_NOPCX:
696 if (reg == 15)
697 return;
698 break;
699 }
700
701 }
702}
703
704static void coverage_add(kprobe_opcode_t insn)
705{
706 struct coverage_entry *entry = coverage.base;
707 struct coverage_entry *end = coverage.base + coverage.num_entries;
708 bool matched = false;
709 unsigned nesting = 0;
710
711 for (; entry < end; ++entry) {
712 const struct decode_header *h = entry->header;
713 enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
714
715 if (entry->nesting > nesting)
716 continue; /* Skip sub-table we didn't match */
717
718 if (entry->nesting < nesting)
719 break; /* End of sub-table we were scanning */
720
721 if (!matched) {
722 if ((insn & h->mask.bits) != h->value.bits)
723 continue;
724 entry->matched = true;
725 }
726
727 switch (type) {
728
729 case DECODE_TYPE_TABLE:
730 ++nesting;
731 break;
732
733 case DECODE_TYPE_CUSTOM:
734 case DECODE_TYPE_SIMULATE:
735 case DECODE_TYPE_EMULATE:
736 coverage_add_registers(entry, insn);
737 return;
738
739 case DECODE_TYPE_OR:
740 matched = true;
741 break;
742
743 case DECODE_TYPE_REJECT:
744 default:
745 return;
746 }
747
748 }
749}
750
751static void coverage_end(void)
752{
753 struct coverage_entry *entry = coverage.base;
754 struct coverage_entry *end = coverage.base + coverage.num_entries;
755
756 for (; entry < end; ++entry) {
757 u32 mask = entry->header->mask.bits;
758 u32 value = entry->header->value.bits;
759
760 if (entry->regs) {
761 pr_err("FAIL: Register test coverage missing for %08x %08x (%05x)\n",
762 mask, value, entry->regs);
763 coverage_fail = true;
764 }
765 if (!entry->matched) {
766 pr_err("FAIL: Test coverage entry missing for %08x %08x\n",
767 mask, value);
768 coverage_fail = true;
769 }
770 }
771
772 kfree(coverage.base);
773}
774
775
776/*
532 * Framework for instruction set test cases 777 * Framework for instruction set test cases
533 */ 778 */
534 779
@@ -1039,6 +1284,8 @@ static uintptr_t __used kprobes_test_case_start(const char *title, void *stack)
1039 } 1284 }
1040 } 1285 }
1041 1286
1287 coverage_add(current_instruction);
1288
1042 if (end_arg->flags & ARG_FLAG_UNSUPPORTED) { 1289 if (end_arg->flags & ARG_FLAG_UNSUPPORTED) {
1043 if (register_test_probe(&test_case_probe) < 0) 1290 if (register_test_probe(&test_case_probe) < 0)
1044 goto pass; 1291 goto pass;
@@ -1213,8 +1460,13 @@ static int run_test_cases(void (*tests)(void), const union decode_item *table)
1213 return ret; 1460 return ret;
1214 1461
1215 pr_info(" Run test cases\n"); 1462 pr_info(" Run test cases\n");
1463 ret = coverage_start(table);
1464 if (ret)
1465 return ret;
1466
1216 tests(); 1467 tests();
1217 1468
1469 coverage_end();
1218 return 0; 1470 return 0;
1219} 1471}
1220 1472
@@ -1274,6 +1526,15 @@ static int __init run_all_tests(void)
1274 goto out; 1526 goto out;
1275 } 1527 }
1276 1528
1529#if __LINUX_ARM_ARCH__ >= 7
1530 /* We are able to run all test cases so coverage should be complete */
1531 if (coverage_fail) {
1532 pr_err("FAIL: Test coverage checks failed\n");
1533 ret = -EINVAL;
1534 goto out;
1535 }
1536#endif
1537
1277out: 1538out:
1278 if (ret == 0) 1539 if (ret == 0)
1279 pr_info("Finished kprobe tests OK\n"); 1540 pr_info("Finished kprobe tests OK\n");