1 #include <xen/bug.h>
2 #include <xen/errno.h>
3 #include <xen/kernel.h>
4 #include <xen/lib.h>
5 #include <xen/livepatch.h>
6 #include <xen/string.h>
7 #include <xen/types.h>
8 #include <xen/virtual_region.h>
9 
10 /*
11  * Returns a negative value in case of an error otherwise
12  * BUGFRAME_{run_fn, warn, bug, assert}
13  */
do_bug_frame(const struct cpu_user_regs * regs,unsigned long pc)14 int do_bug_frame(const struct cpu_user_regs *regs, unsigned long pc)
15 {
16     const struct bug_frame *bug = NULL;
17     const struct virtual_region *region;
18     const char *prefix = "", *filename, *predicate;
19     unsigned long fixup;
20     unsigned int id, lineno;
21 
22     region = find_text_region(pc);
23     if ( !region )
24         return -EINVAL;
25 
26     for ( id = 0; id < BUGFRAME_NR; id++ )
27     {
28         const struct bug_frame *b;
29 
30         for ( b = region->frame[id].start;
31               b < region->frame[id].stop; b++ )
32         {
33             if ( bug_loc(b) == pc )
34             {
35                 bug = b;
36                 goto found;
37             }
38         }
39     }
40 
41  found:
42     if ( !bug )
43         return -ENOENT;
44 
45     if ( id == BUGFRAME_run_fn )
46     {
47         bug_fn_t *fn = bug_ptr(bug);
48 
49         fn(regs);
50 
51         return id;
52     }
53 
54     /* WARN, BUG or ASSERT: decode the filename pointer and line number. */
55     filename = bug_ptr(bug);
56     if ( !is_kernel(filename) && !is_patch(filename) )
57         return -EINVAL;
58     fixup = strlen(filename);
59     if ( fixup > 50 )
60     {
61         filename += fixup - 47;
62         prefix = "...";
63     }
64     lineno = bug_line(bug);
65 
66     switch ( id )
67     {
68     case BUGFRAME_warn:
69         printk("Xen WARN at %s%s:%d\n", prefix, filename, lineno);
70         show_execution_state(regs);
71 
72         break;
73 
74     case BUGFRAME_bug:
75         printk("Xen BUG at %s%s:%d\n", prefix, filename, lineno);
76         show_execution_state(regs);
77         panic("Xen BUG at %s%s:%d\n", prefix, filename, lineno);
78 
79     case BUGFRAME_assert:
80         /* ASSERT: decode the predicate string pointer. */
81         predicate = bug_msg(bug);
82         if ( !is_kernel(predicate) && !is_patch(predicate) )
83             predicate = "<unknown>";
84 
85         printk("Assertion '%s' failed at %s%s:%d\n",
86                predicate, prefix, filename, lineno);
87         show_execution_state(regs);
88         panic("Assertion '%s' failed at %s%s:%d\n",
89               predicate, prefix, filename, lineno);
90     }
91 
92     return id;
93 }
94