1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #include <arch/breakpoint.h>
4 #include <arch/null_breakpoint.h>
5 #include <bootstate.h>
6 #include <console/console.h>
7 #include <types.h>
8
9 static struct breakpoint_handle null_deref_bp;
10 static struct breakpoint_handle null_fetch_bp;
11
handle_fetch_breakpoint(struct breakpoint_handle handle,struct eregs * regs)12 static int handle_fetch_breakpoint(struct breakpoint_handle handle, struct eregs *regs)
13 {
14 printk(BIOS_ERR, "Instruction fetch from address zero\n");
15 return CONFIG(DEBUG_NULL_DEREF_HALT);
16 }
17
handle_deref_breakpoint(struct breakpoint_handle handle,struct eregs * regs)18 static int handle_deref_breakpoint(struct breakpoint_handle handle, struct eregs *regs)
19 {
20 #if ENV_X86_64
21 printk(BIOS_ERR, "Null dereference at rip: 0x%llx\n", regs->rip);
22 #else
23 printk(BIOS_ERR, "Null dereference at eip: 0x%x\n", regs->eip);
24 #endif
25 return CONFIG(DEBUG_NULL_DEREF_HALT);
26 }
27
create_deref_breakpoint(void)28 static void create_deref_breakpoint(void)
29 {
30 enum breakpoint_result res =
31 breakpoint_create_data(&null_deref_bp, NULL, sizeof(uintptr_t), false);
32
33 if (res != BREAKPOINT_RES_OK) {
34 printk(BIOS_ERR, "Failed to create NULL dereference breakpoint\n");
35 return;
36 }
37
38 breakpoint_set_handler(null_deref_bp, &handle_deref_breakpoint);
39 breakpoint_enable(null_deref_bp, true);
40 }
41
create_instruction_breakpoint(void)42 static void create_instruction_breakpoint(void)
43 {
44 enum breakpoint_result res = breakpoint_create_instruction(&null_fetch_bp, NULL);
45
46 if (res != BREAKPOINT_RES_OK) {
47 printk(BIOS_ERR, "Failed to create address zero instruction fetch breakpoint\n");
48 return;
49 }
50
51 breakpoint_set_handler(null_fetch_bp, &handle_fetch_breakpoint);
52 breakpoint_enable(null_fetch_bp, true);
53 }
54
null_breakpoint_init(void)55 void null_breakpoint_init(void)
56 {
57 create_deref_breakpoint();
58 create_instruction_breakpoint();
59 }
60
null_breakpoint_disable(void)61 void null_breakpoint_disable(void)
62 {
63 breakpoint_remove(null_fetch_bp);
64 breakpoint_remove(null_deref_bp);
65 }
66
null_breakpoint_disable_hook(void * unused)67 static void null_breakpoint_disable_hook(void *unused)
68 {
69 null_breakpoint_disable();
70 }
71
72 BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY, null_breakpoint_disable_hook, NULL);
73 BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_BOOT, BS_ON_ENTRY, null_breakpoint_disable_hook, NULL);
74