feat: integrate gdb support over serial port for bare-metal debugging.
[lunaix-os.git] / lunaix-os / debug / sdbg.c
1 #include <hal/acpi/acpi.h>
2 #include <hal/ioapic.h>
3 #include <klibc/stdio.h>
4 #include <lunaix/lxconsole.h>
5 #include <lunaix/peripheral/serial.h>
6 #include <lunaix/syslog.h>
7 #include <sdbg/gdbstub.h>
8 #include <sdbg/lsdbg.h>
9 #include <sdbg/protocol.h>
10
11 // #define USE_LSDBG_BACKEND
12
13 volatile int debug_mode = 0;
14
15 void
16 sdbg_loop(const isr_param* param)
17 {
18     // This is importnat, because we will handle any subsequent RX/TX in a
19     // synchronized way. And we don't want these irq queue up at our APIC and
20     // confuse the CPU after ACK with APIC.
21     serial_disable_irq(SERIAL_COM1);
22     if (param->vector == 1 || param->vector == 3) {
23         goto cont;
24     }
25
26     if (!debug_mode) {
27         // Oh... C.M.C. is about to help the debugging!
28         if (serial_rx_byte(SERIAL_COM1) != '@') {
29             goto done;
30         }
31         if (serial_rx_byte(SERIAL_COM1) != 'c') {
32             goto done;
33         }
34         if (serial_rx_byte(SERIAL_COM1) != 'm') {
35             goto done;
36         }
37         if (serial_rx_byte(SERIAL_COM1) != 'c') {
38             goto done;
39         }
40         debug_mode = 1;
41     } else {
42         if (serial_rx_byte(SERIAL_COM1) != '@') {
43             goto cont;
44         }
45         if (serial_rx_byte(SERIAL_COM1) != 'y') {
46             goto cont;
47         }
48         if (serial_rx_byte(SERIAL_COM1) != 'a') {
49             goto cont;
50         }
51         if (serial_rx_byte(SERIAL_COM1) != 'y') {
52             goto cont;
53         }
54         debug_mode = 0;
55         goto done;
56     }
57
58 cont:
59     kprint_dbg(" DEBUG");
60 #ifdef USE_LSDBG_BACKEND
61     lunaix_sdbg_loop(param);
62 #else
63     gdbstub_loop(param);
64 #endif
65     console_flush();
66
67 done:
68     serial_enable_irq(SERIAL_COM1);
69 }
70
71 extern uint8_t
72 ioapic_get_irq(acpi_context* acpi_ctx, uint8_t old_irq);
73
74 void
75 sdbg_init()
76 {
77     intr_subscribe(UART_COM1, sdbg_loop);
78     intr_subscribe(INSTR_DEBUG, sdbg_loop); // #DB
79
80     acpi_context* acpi_ctx = acpi_get_context();
81     uint8_t irq = ioapic_get_irq(acpi_ctx, COM1_IRQ);
82     ioapic_redirect(irq, UART_COM1, 0, IOAPIC_DELMOD_FIXED);
83 }