|
17 | 17 | #include <linux/perf_event.h>
|
18 | 18 | #include <linux/hw_breakpoint.h>
|
19 | 19 | #include <linux/smp.h>
|
| 20 | +#include <linux/cfi.h> |
20 | 21 | #include <linux/cpu_pm.h>
|
21 | 22 | #include <linux/coresight.h>
|
22 | 23 |
|
@@ -903,6 +904,37 @@ static void breakpoint_handler(unsigned long unknown, struct pt_regs *regs)
|
903 | 904 | watchpoint_single_step_handler(addr);
|
904 | 905 | }
|
905 | 906 |
|
| 907 | +#ifdef CONFIG_CFI_CLANG |
| 908 | +static void hw_breakpoint_cfi_handler(struct pt_regs *regs) |
| 909 | +{ |
| 910 | + /* |
| 911 | + * TODO: implementing target and type to pass to CFI using the more |
| 912 | + * elaborate report_cfi_failure() requires compiler work. To be able |
| 913 | + * to properly extract target information the compiler needs to |
| 914 | + * emit a stable instructions sequence for the CFI checks so we can |
| 915 | + * decode the instructions preceding the trap and figure out which |
| 916 | + * registers were used. |
| 917 | + */ |
| 918 | + |
| 919 | + switch (report_cfi_failure_noaddr(regs, instruction_pointer(regs))) { |
| 920 | + case BUG_TRAP_TYPE_BUG: |
| 921 | + die("Oops - CFI", regs, 0); |
| 922 | + break; |
| 923 | + case BUG_TRAP_TYPE_WARN: |
| 924 | + /* Skip the breaking instruction */ |
| 925 | + instruction_pointer(regs) += 4; |
| 926 | + break; |
| 927 | + default: |
| 928 | + die("Unknown CFI error", regs, 0); |
| 929 | + break; |
| 930 | + } |
| 931 | +} |
| 932 | +#else |
| 933 | +static void hw_breakpoint_cfi_handler(struct pt_regs *regs) |
| 934 | +{ |
| 935 | +} |
| 936 | +#endif |
| 937 | + |
906 | 938 | /*
|
907 | 939 | * Called from either the Data Abort Handler [watchpoint] or the
|
908 | 940 | * Prefetch Abort Handler [breakpoint] with interrupts disabled.
|
@@ -932,6 +964,9 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
|
932 | 964 | case ARM_ENTRY_SYNC_WATCHPOINT:
|
933 | 965 | watchpoint_handler(addr, fsr, regs);
|
934 | 966 | break;
|
| 967 | + case ARM_ENTRY_CFI_BREAKPOINT: |
| 968 | + hw_breakpoint_cfi_handler(regs); |
| 969 | + break; |
935 | 970 | default:
|
936 | 971 | ret = 1; /* Unhandled fault. */
|
937 | 972 | }
|
|
0 commit comments