From 3f01cd14533f12f04a87a9cf1111dd948094bac4 Mon Sep 17 00:00:00 2001 From: Robert Zieba Date: Thu, 14 Apr 2022 10:36:15 -0600 Subject: arch/x86: Add support for catching null dereferences through debug regs This commit adds support for catching null dereferences and execution through x86's debug registers. This is particularly useful when running 32-bit coreboot as paging is not enabled to catch these through page faults. This commit adds three new configs to support this feature: DEBUG_HW_BREAKPOINTS, DEBUG_NULL_DEREF_BREAKPOINTS and DEBUG_NULL_DEREF_HALT. BUG=b:223902046 TEST=Ran on nipperkin device, verifying that HW breakpoints work as expected. Change-Id: I113590689046a13c2a552741bbfe7668a834354a Signed-off-by: Robert Zieba Reviewed-on: https://review.coreboot.org/c/coreboot/+/63657 Tested-by: build bot (Jenkins) Reviewed-by: Raul Rangel --- src/arch/x86/include/arch/breakpoint.h | 58 +++++++++++++++++++++++++++++ src/arch/x86/include/arch/null_breakpoint.h | 16 ++++++++ 2 files changed, 74 insertions(+) create mode 100644 src/arch/x86/include/arch/breakpoint.h create mode 100644 src/arch/x86/include/arch/null_breakpoint.h (limited to 'src/arch/x86/include') diff --git a/src/arch/x86/include/arch/breakpoint.h b/src/arch/x86/include/arch/breakpoint.h new file mode 100644 index 0000000000..32e9f48d09 --- /dev/null +++ b/src/arch/x86/include/arch/breakpoint.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef _BREAKPOINT_H_ +#define _BREAKPOINT_H_ + +#include +#include + +#if CONFIG(DEBUG_HW_BREAKPOINTS) && \ + (CONFIG(DEBUG_HW_BREAKPOINTS_IN_ALL_STAGES) || ENV_RAMSTAGE) +struct breakpoint_handle { + int bp; +}; + +typedef int (*breakpoint_handler)(struct breakpoint_handle, struct eregs *info); + +enum breakpoint_result { + BREAKPOINT_RES_OK = 0, + BREAKPOINT_RES_NONE_AVAILABLE = -1, + BREAKPOINT_RES_INVALID_HANDLE = -2, + BREAKPOINT_RES_INVALID_LENGTH = -3 +}; + +enum breakpoint_type { + BREAKPOINT_TYPE_INSTRUCTION = 0x0, + BREAKPOINT_TYPE_DATA_WRITE = 0x1, + BREAKPOINT_TYPE_IO = 0x2, + BREAKPOINT_TYPE_DATA_RW = 0x3, +}; + +/* Creates an instruction breakpoint at the given address. */ +enum breakpoint_result breakpoint_create_instruction(struct breakpoint_handle *out_handle, + void *virt_addr); +/* Creates a data breakpoint at the given address for len bytes. */ +enum breakpoint_result breakpoint_create_data(struct breakpoint_handle *out_handle, + void *virt_addr, size_t len, bool write_only); +/* Removes a given breakpoint. */ +enum breakpoint_result breakpoint_remove(struct breakpoint_handle handle); +/* Enables or disables a given breakpoint. */ +enum breakpoint_result breakpoint_enable(struct breakpoint_handle handle, bool enabled); +/* Returns the type of a breakpoint. */ +enum breakpoint_result breakpoint_get_type(struct breakpoint_handle handle, + enum breakpoint_type *type); +/* + * Sets a handler function to be called when the breakpoint is hit. The handler should return 0 + * to continue or any other value to halt execution as a fatal error. + */ +enum breakpoint_result breakpoint_set_handler(struct breakpoint_handle handle, + breakpoint_handler handler); +/* Called by x86_exception to dispatch breakpoint exceptions to the correct handler. */ +int breakpoint_dispatch_handler(struct eregs *info); +#else +static inline int breakpoint_dispatch_handler(struct eregs *info) +{ + /* Not implemented */ + return 0; +} +#endif +#endif /* _BREAKPOINT_H_ */ diff --git a/src/arch/x86/include/arch/null_breakpoint.h b/src/arch/x86/include/arch/null_breakpoint.h new file mode 100644 index 0000000000..bc86dc03e4 --- /dev/null +++ b/src/arch/x86/include/arch/null_breakpoint.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef _NULL_BREAKPOINT_H_ +#define _NULL_BREAKPOINT_H_ + +#if CONFIG(DEBUG_NULL_DEREF_BREAKPOINTS) && \ + (CONFIG(DEBUG_NULL_DEREF_BREAKPOINTS_IN_ALL_STAGES) || ENV_RAMSTAGE) + +/* Places data and instructions breakpoints at address zero. */ +void null_breakpoint_init(void); +#else +static inline void null_breakpoint_init(void) +{ + /* Not implemented */ +} +#endif +#endif /* _NULL_BREAKPOINT_H_ */ -- cgit v1.2.3