mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
xen: introduce CONFIG_GENERIC_BUG_FRAME
A large part of the content of the bug.h is repeated among all architectures, so it was decided to create a new config CONFIG_GENERIC_BUG_FRAME. The version of <bug.h> from x86 was taken as the base version. The patch introduces the following stuff: * common bug.h header * generic implementation of do_bug_frame * new config CONFIG_GENERIC_BUG_FRAME Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com> Reviewed-by: Jan Beulich <jbeulich@suse.com> Tested-by: Julien Grall <jgrall@amazon.com> Acked-by: Julien Grall <jgrall@amazon.com>
This commit is contained in:
1 parent
de7d113212
commit
60a9b07150
4 files changed
+289
No files matched your search
@@ -29,6 +29,9 @@ config ALTERNATIVE_CALL
|
||||
config ARCH_MAP_DOMAIN_PAGE
|
||||
bool
|
||||
|
||||
config GENERIC_BUG_FRAME
|
||||
bool
|
||||
|
||||
config HAS_ALTERNATIVE
|
||||
bool
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
obj-$(CONFIG_ARGO) += argo.o
|
||||
obj-y += bitmap.o
|
||||
obj-$(CONFIG_GENERIC_BUG_FRAME) += bug.o
|
||||
obj-$(CONFIG_HYPFS_CONFIG) += config_data.o
|
||||
obj-$(CONFIG_CORE_PARKING) += core_parking.o
|
||||
obj-y += cpu.o
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
#include <xen/bug.h>
|
||||
/*
|
||||
* Ideally <xen/debugger.h> should be included in <asm/bug.h>
|
||||
* but an issue with compilation can occur as <xen/debugger.h> uses
|
||||
* BUG/ASSERT/etc macros inside but they will be defined later in
|
||||
* <xen/bug.h> after return from inclusion of <asm/bug.h>:
|
||||
*
|
||||
* <xen/bug.h>:
|
||||
* ...
|
||||
* <asm/bug.h>:
|
||||
* ...
|
||||
* <xen/debugger.h> -> some of included header in it uses BUG/ASSERT/etc
|
||||
* ...
|
||||
* ...
|
||||
* #define BUG() ...
|
||||
* ...
|
||||
* #define ASSERT() ...
|
||||
* ...
|
||||
*/
|
||||
#include <xen/debugger.h>
|
||||
#include <xen/errno.h>
|
||||
#include <xen/kernel.h>
|
||||
#include <xen/livepatch.h>
|
||||
#include <xen/string.h>
|
||||
#include <xen/types.h>
|
||||
#include <xen/virtual_region.h>
|
||||
|
||||
/*
|
||||
* Returns a negative value in case of an error otherwise
|
||||
* BUGFRAME_{run_fn, warn, bug, assert}
|
||||
*/
|
||||
int do_bug_frame(struct cpu_user_regs *regs, unsigned long pc)
|
||||
{
|
||||
const struct bug_frame *bug = NULL;
|
||||
const struct virtual_region *region;
|
||||
const char *prefix = "", *filename, *predicate;
|
||||
unsigned long fixup;
|
||||
unsigned int id, lineno;
|
||||
|
||||
region = find_text_region(pc);
|
||||
if ( !region )
|
||||
return -EINVAL;
|
||||
|
||||
for ( id = 0; id < BUGFRAME_NR; id++ )
|
||||
{
|
||||
const struct bug_frame *b;
|
||||
size_t i;
|
||||
|
||||
for ( i = 0, b = region->frame[id].bugs;
|
||||
i < region->frame[id].n_bugs; b++, i++ )
|
||||
{
|
||||
if ( bug_loc(b) == pc )
|
||||
{
|
||||
bug = b;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
found:
|
||||
if ( !bug )
|
||||
return -ENOENT;
|
||||
|
||||
if ( id == BUGFRAME_run_fn )
|
||||
{
|
||||
void (*fn)(struct cpu_user_regs *) = bug_ptr(bug);
|
||||
|
||||
fn(regs);
|
||||
|
||||
/* Re-enforce consistent types, because of the casts involved. */
|
||||
if ( false )
|
||||
run_in_exception_handler(fn);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
/* WARN, BUG or ASSERT: decode the filename pointer and line number. */
|
||||
filename = bug_ptr(bug);
|
||||
if ( !is_kernel(filename) && !is_patch(filename) )
|
||||
return -EINVAL;
|
||||
fixup = strlen(filename);
|
||||
if ( fixup > 50 )
|
||||
{
|
||||
filename += fixup - 47;
|
||||
prefix = "...";
|
||||
}
|
||||
lineno = bug_line(bug);
|
||||
|
||||
switch ( id )
|
||||
{
|
||||
case BUGFRAME_warn:
|
||||
printk("Xen WARN at %s%s:%d\n", prefix, filename, lineno);
|
||||
show_execution_state(regs);
|
||||
|
||||
break;
|
||||
|
||||
case BUGFRAME_bug:
|
||||
printk("Xen BUG at %s%s:%d\n", prefix, filename, lineno);
|
||||
|
||||
if ( BUG_DEBUGGER_TRAP_FATAL(regs) )
|
||||
break;
|
||||
|
||||
show_execution_state(regs);
|
||||
panic("Xen BUG at %s%s:%d\n", prefix, filename, lineno);
|
||||
|
||||
case BUGFRAME_assert:
|
||||
/* ASSERT: decode the predicate string pointer. */
|
||||
predicate = bug_msg(bug);
|
||||
if ( !is_kernel(predicate) && !is_patch(predicate) )
|
||||
predicate = "<unknown>";
|
||||
|
||||
printk("Assertion '%s' failed at %s%s:%d\n",
|
||||
predicate, prefix, filename, lineno);
|
||||
|
||||
if ( BUG_DEBUGGER_TRAP_FATAL(regs) )
|
||||
break;
|
||||
|
||||
show_execution_state(regs);
|
||||
panic("Assertion '%s' failed at %s%s:%d\n",
|
||||
predicate, prefix, filename, lineno);
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
#ifndef __XEN_BUG_H__
|
||||
#define __XEN_BUG_H__
|
||||
|
||||
#define BUGFRAME_run_fn 0
|
||||
#define BUGFRAME_warn 1
|
||||
#define BUGFRAME_bug 2
|
||||
#define BUGFRAME_assert 3
|
||||
|
||||
#define BUGFRAME_NR 4
|
||||
|
||||
#define BUG_DISP_WIDTH 24
|
||||
#define BUG_LINE_LO_WIDTH (31 - BUG_DISP_WIDTH)
|
||||
#define BUG_LINE_HI_WIDTH (31 - BUG_DISP_WIDTH)
|
||||
|
||||
#include <asm/bug.h>
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#ifndef BUG_DEBUGGER_TRAP_FATAL
|
||||
#define BUG_DEBUGGER_TRAP_FATAL(regs) 0
|
||||
#endif
|
||||
|
||||
#include <xen/lib.h>
|
||||
|
||||
#ifndef BUG_FRAME_STRUCT
|
||||
|
||||
struct bug_frame {
|
||||
signed int loc_disp:BUG_DISP_WIDTH;
|
||||
unsigned int line_hi:BUG_LINE_HI_WIDTH;
|
||||
signed int ptr_disp:BUG_DISP_WIDTH;
|
||||
unsigned int line_lo:BUG_LINE_LO_WIDTH;
|
||||
signed int msg_disp[];
|
||||
};
|
||||
|
||||
#define bug_loc(b) ((unsigned long)(b) + (b)->loc_disp)
|
||||
|
||||
#define bug_ptr(b) ((const void *)(b) + (b)->ptr_disp)
|
||||
|
||||
#define bug_line(b) (((((b)->line_hi + ((b)->loc_disp < 0)) & \
|
||||
((1 << BUG_LINE_HI_WIDTH) - 1)) << \
|
||||
BUG_LINE_LO_WIDTH) + \
|
||||
(((b)->line_lo + ((b)->ptr_disp < 0)) & \
|
||||
((1 << BUG_LINE_LO_WIDTH) - 1)))
|
||||
|
||||
#define bug_msg(b) ((const char *)(b) + (b)->msg_disp[1])
|
||||
|
||||
#define BUG_CHECK_LINE_WIDTH(line) \
|
||||
BUILD_BUG_ON((line) >> (BUG_LINE_LO_WIDTH + BUG_LINE_HI_WIDTH))
|
||||
|
||||
#elif !defined(BUG_CHECK_LINE_WIDTH)
|
||||
|
||||
#define BUG_CHECK_LINE_WIDTH(line) ((void)(line))
|
||||
|
||||
#endif /* BUG_FRAME_STRUCT */
|
||||
|
||||
|
||||
/*
|
||||
* Some architectures mark immediate instruction operands in a special way.
|
||||
* In such cases the special marking may need omitting when specifying
|
||||
* directive operands. Allow architectures to specify a suitable
|
||||
* modifier.
|
||||
*/
|
||||
#ifndef BUG_ASM_CONST
|
||||
#define BUG_ASM_CONST ""
|
||||
#endif
|
||||
|
||||
#ifndef _ASM_BUGFRAME_TEXT
|
||||
|
||||
#define _ASM_BUGFRAME_TEXT(second_frame) \
|
||||
".Lbug%=:"BUG_INSTR"\n" \
|
||||
" .pushsection .bug_frames.%"BUG_ASM_CONST"[bf_type], \"a\", %%progbits\n" \
|
||||
" .p2align 2\n" \
|
||||
".Lfrm%=:\n" \
|
||||
" .long (.Lbug%= - .Lfrm%=) + %"BUG_ASM_CONST"[bf_line_hi]\n" \
|
||||
" .long (%"BUG_ASM_CONST"[bf_ptr] - .Lfrm%=) + %"BUG_ASM_CONST"[bf_line_lo]\n"\
|
||||
" .if " #second_frame "\n" \
|
||||
" .long 0, %"BUG_ASM_CONST"[bf_msg] - .Lfrm%=\n" \
|
||||
" .endif\n" \
|
||||
" .popsection\n"
|
||||
|
||||
#define _ASM_BUGFRAME_INFO(type, line, ptr, msg) \
|
||||
[bf_type] "i" (type), \
|
||||
[bf_ptr] "i" (ptr), \
|
||||
[bf_msg] "i" (msg), \
|
||||
[bf_line_lo] "i" ((line & ((1 << BUG_LINE_LO_WIDTH) - 1)) \
|
||||
<< BUG_DISP_WIDTH), \
|
||||
[bf_line_hi] "i" (((line) >> BUG_LINE_LO_WIDTH) << BUG_DISP_WIDTH)
|
||||
|
||||
#endif /* _ASM_BUGFRAME_TEXT */
|
||||
|
||||
#ifndef BUG_FRAME
|
||||
|
||||
#define BUG_FRAME(type, line, ptr, second_frame, msg) do { \
|
||||
BUG_CHECK_LINE_WIDTH(line); \
|
||||
BUILD_BUG_ON((type) >= BUGFRAME_NR); \
|
||||
asm volatile ( _ASM_BUGFRAME_TEXT(second_frame) \
|
||||
:: _ASM_BUGFRAME_INFO(type, line, ptr, msg) ); \
|
||||
} while ( false )
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef run_in_exception_handler
|
||||
|
||||
/*
|
||||
* TODO: untangle header dependences, break BUILD_BUG_ON() out of xen/lib.h,
|
||||
* and use a real static inline here to get proper type checking of fn().
|
||||
*/
|
||||
#define run_in_exception_handler(fn) do { \
|
||||
(void)((fn) == (void (*)(struct cpu_user_regs *))NULL); \
|
||||
BUG_FRAME(BUGFRAME_run_fn, 0, fn, 0, NULL); \
|
||||
} while ( false )
|
||||
|
||||
#endif /* run_in_exception_handler */
|
||||
|
||||
#ifndef WARN
|
||||
#define WARN() BUG_FRAME(BUGFRAME_warn, __LINE__, __FILE__, 0, NULL)
|
||||
#endif
|
||||
|
||||
#ifndef BUG
|
||||
#define BUG() do { \
|
||||
BUG_FRAME(BUGFRAME_bug, __LINE__, __FILE__, 0, NULL); \
|
||||
unreachable(); \
|
||||
} while ( false )
|
||||
#endif
|
||||
|
||||
#ifndef assert_failed
|
||||
#define assert_failed(msg) do { \
|
||||
BUG_FRAME(BUGFRAME_assert, __LINE__, __FILE__, 1, msg); \
|
||||
unreachable(); \
|
||||
} while ( false )
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_GENERIC_BUG_FRAME
|
||||
|
||||
struct cpu_user_regs;
|
||||
|
||||
/*
|
||||
* Returns a negative value in case of an error otherwise
|
||||
* BUGFRAME_{run_fn, warn, bug, assert}
|
||||
*/
|
||||
int do_bug_frame(struct cpu_user_regs *regs, unsigned long pc);
|
||||
|
||||
#endif /* CONFIG_GENERIC_BUG_FRAME */
|
||||
|
||||
extern const struct bug_frame __start_bug_frames[],
|
||||
__stop_bug_frames_0[],
|
||||
__stop_bug_frames_1[],
|
||||
__stop_bug_frames_2[],
|
||||
__stop_bug_frames_3[];
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#endif /* __XEN_BUG_H__ */
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-file-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||