Linux Audio
Check our new training course
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
/* * Copyright (c) 2020 Intel Corporation. * * SPDX-License-Identifier: Apache-2.0 */ #include <kernel.h> #include <kernel_internal.h> #include <ia32/exception.h> #include <inttypes.h> #include <debug/gdbstub.h> static struct gdb_ctx ctx; static bool start; /** * Currently we just handle vectors 1 and 3 but lets keep it generic * to be able to notify other exceptions in the future */ static unsigned int get_exception(unsigned int vector) { unsigned int exception; switch (vector) { case IV_DIVIDE_ERROR: exception = GDB_EXCEPTION_DIVIDE_ERROR; break; case IV_DEBUG: exception = GDB_EXCEPTION_BREAKPOINT; break; case IV_BREAKPOINT: exception = GDB_EXCEPTION_BREAKPOINT; break; case IV_OVERFLOW: exception = GDB_EXCEPTION_OVERFLOW; break; case IV_BOUND_RANGE: exception = GDB_EXCEPTION_OVERFLOW; break; case IV_INVALID_OPCODE: exception = GDB_EXCEPTION_INVALID_INSTRUCTION; break; case IV_DEVICE_NOT_AVAILABLE: exception = GDB_EXCEPTION_DIVIDE_ERROR; break; case IV_DOUBLE_FAULT: exception = GDB_EXCEPTION_MEMORY_FAULT; break; case IV_COPROC_SEGMENT_OVERRUN: exception = GDB_EXCEPTION_INVALID_MEMORY; break; case IV_INVALID_TSS: exception = GDB_EXCEPTION_INVALID_MEMORY; break; case IV_SEGMENT_NOT_PRESENT: exception = GDB_EXCEPTION_INVALID_MEMORY; break; case IV_STACK_FAULT: exception = GDB_EXCEPTION_INVALID_MEMORY; break; case IV_GENERAL_PROTECTION: exception = GDB_EXCEPTION_INVALID_MEMORY; break; case IV_PAGE_FAULT: exception = GDB_EXCEPTION_INVALID_MEMORY; break; case IV_X87_FPU_FP_ERROR: exception = GDB_EXCEPTION_MEMORY_FAULT; break; default: exception = GDB_EXCEPTION_MEMORY_FAULT; break; } return exception; } /* * Debug exception handler. */ static void z_gdb_interrupt(unsigned int vector, z_arch_esf_t *esf) { ctx.exception = get_exception(vector); ctx.registers[GDB_EAX] = esf->eax; ctx.registers[GDB_ECX] = esf->ecx; ctx.registers[GDB_EDX] = esf->edx; ctx.registers[GDB_EBX] = esf->ebx; ctx.registers[GDB_ESP] = esf->esp; ctx.registers[GDB_EBP] = esf->ebp; ctx.registers[GDB_ESI] = esf->esi; ctx.registers[GDB_EDI] = esf->edi; ctx.registers[GDB_PC] = esf->eip; ctx.registers[GDB_CS] = esf->cs; ctx.registers[GDB_EFLAGS] = esf->eflags; ctx.registers[GDB_SS] = esf->ss; ctx.registers[GDB_DS] = esf->ds; ctx.registers[GDB_ES] = esf->es; ctx.registers[GDB_FS] = esf->fs; ctx.registers[GDB_GS] = esf->gs; z_gdb_main_loop(&ctx, start); start = false; esf->eax = ctx.registers[GDB_EAX]; esf->ecx = ctx.registers[GDB_ECX]; esf->edx = ctx.registers[GDB_EDX]; esf->ebx = ctx.registers[GDB_EBX]; esf->esp = ctx.registers[GDB_ESP]; esf->ebp = ctx.registers[GDB_EBP]; esf->esi = ctx.registers[GDB_ESI]; esf->edi = ctx.registers[GDB_EDI]; esf->eip = ctx.registers[GDB_PC]; esf->cs = ctx.registers[GDB_CS]; esf->eflags = ctx.registers[GDB_EFLAGS]; esf->ss = ctx.registers[GDB_SS]; esf->ds = ctx.registers[GDB_DS]; esf->es = ctx.registers[GDB_ES]; esf->fs = ctx.registers[GDB_FS]; esf->gs = ctx.registers[GDB_GS]; } void arch_gdb_continue(void) { /* Clear the TRAP FLAG bit */ ctx.registers[GDB_EFLAGS] &= ~BIT(8); } void arch_gdb_step(void) { /* Set the TRAP FLAG bit */ ctx.registers[GDB_EFLAGS] |= BIT(8); } static __used void z_gdb_debug_isr(z_arch_esf_t *esf) { z_gdb_interrupt(IV_DEBUG, esf); } static __used void z_gdb_break_isr(z_arch_esf_t *esf) { z_gdb_interrupt(IV_BREAKPOINT, esf); } void arch_gdb_init(void) { start = true; __asm__ volatile ("int3"); } /* Hook current IDT. */ _EXCEPTION_CONNECT_NOCODE(z_gdb_debug_isr, IV_DEBUG, 3); _EXCEPTION_CONNECT_NOCODE(z_gdb_break_isr, IV_BREAKPOINT, 3);