1/** \file
2 * \brief x86-specific parts of in-kernel GDB stub.
3 *
4 * This file implements x86 architecture support for the kernel-side GDB stubs.
5 */
6
7/*
8 * Copyright (c) 2007, 2008, 2010, ETH Zurich.
9 * All rights reserved.
10 *
11 * This file is distributed under the terms in the attached LICENSE file.
12 * If you do not find this file, copies can be found by writing to:
13 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
14 */
15
16#include <kernel.h>
17#include <stdio.h>
18#include <paging_kernel_arch.h>
19#include <gdb_stub.h>
20#include <arch_gdb_stub.h>
21#include <barrelfish_kpi/cpu.h>
22
23#ifdef __k1om__
24#define KERNEL_STACK_SIZE K1OM_KERNEL_STACK_SIZE
25#define MEMORY_OFFSET K1OM_MEMORY_OFFSET
26#define KERNEL_STACK k1om_kernel_stack
27#else
28#define KERNEL_STACK_SIZE X86_64_KERNEL_STACK_SIZE
29#define MEMORY_OFFSET X86_64_MEMORY_OFFSET
30#define KERNEL_STACK x86_64_kernel_stack
31#endif
32
33/** \brief GDB register save area / frame.
34 *
35 * Stores pointer to current save frame used by GDB. Used to read/modify
36 * register contents, and reloaded when program execution resumes. */
37uintptr_t *gdb_arch_registers;
38
39/** \brief Separate stack area for the stub to run on */
40static uintptr_t gdb_stack[KERNEL_STACK_SIZE/sizeof(uintptr_t)];
41/** \brief Pointer to top of GDB stack area. */
42uintptr_t * SNT gdb_stack_top = &gdb_stack[KERNEL_STACK_SIZE/sizeof(uintptr_t)];
43
44/** \brief Converts exception vector to signal number.
45 *
46 * This function takes an x86 exception vector and attempts to
47 * translate this number into a Unix-compatible signal value.
48 */
49static int exception_to_signal(int vector)
50{
51    switch (vector) {
52        case 0:     return 8;   // divide by zero
53        case 1:     return 5;   // debug exception
54        case 3:     return 5;   // breakpoint
55        case 4:     return 16;  // into instruction (overflow)
56        case 5:     return 16;  // bound instruction
57        case 6:     return 4;   // Invalid opcode
58        case 7:     return 8;   // coprocessor not available
59        case 8:     return 7;   // double fault
60        case 9:     return 11;  // coprocessor segment overrun
61        case 10:    return 11;  // Invalid TSS
62        case 11:    return 11;  // Segment not present
63        case 12:    return 11;  // stack exception
64        case 13:    return 11;  // general protection
65        case 14:    return 11;  // page fault
66        case 16:    return 7;   // coprocessor error
67        default:    return 7;   // "software generated"
68    }
69}
70
71__asm__ (
72    ".global gdb_handle_exception       \n"
73    "gdb_handle_exception:              \n"
74    "mov gdb_stack_top(%rip), %rsp      \n"
75    "jmp gdb_handle_exception_onstack   \n"
76);
77
78/** \brief Entry point for an exception; we are now on our own stack.
79 *
80 * This function sets up the GDB-format register save frame, constructs the
81 * initial message to the remote GDB and calls into the generic debugger entry
82 * point.
83 */
84void gdb_handle_exception_onstack(int vector, uintptr_t * NONNULL
85        COUNT(GDB_X86_64_NUM_REGS) save_area) __attribute__((noreturn));
86void gdb_handle_exception_onstack(int vector, uintptr_t * NONNULL
87        COUNT(GDB_X86_64_NUM_REGS) save_area)
88{
89    /* sanity check that we didn't trap inside the debugger...
90     * if we did, we're definitely hosed now! */
91    if (save_area[GDB_X86_64_RSP_REG] >= (lvaddr_t)&gdb_stack &&
92        save_area[GDB_X86_64_RSP_REG] <= (lvaddr_t)gdb_stack_top) {
93        panic("Nested exception within GDB stub");
94    }
95
96    /* were we in user mode at the time of the trap? */
97    if ((save_area[GDB_X86_64_CS_REG] & 0x3) != 0) {
98        printk(LOG_NOTE,
99               "Entered from user-mode (at least, CPL in CS is non-zero)\n");
100
101    /* while we're checking the stack pointer, sanity check that it's
102     * within the normal kernel stack region */
103    } else if (save_area[GDB_X86_64_RSP_REG] < (lvaddr_t)&KERNEL_STACK ||
104              save_area[GDB_X86_64_RSP_REG] > (lvaddr_t)&KERNEL_STACK +
105               KERNEL_STACK_SIZE) {
106        printk(LOG_WARN, "BIG FAT WARNING: kernel stack pointer (0x%lx) is "
107               "invalid!\n", save_area[GDB_X86_64_RSP_REG]);
108        printk(LOG_WARN, "Boldly attempting to continue into GDB anyway...\n");
109    }
110
111    char buffer[64];
112    int signal = exception_to_signal(vector);
113
114#if 0 // this is broken, because the register data needs to be in LE byte order
115    // T <signal> RSP:<stack ptr>; RIP:<inst ptr>;
116    int r = snprintf(buffer, sizeof(buffer), "T%02hhx%x:%lx;%x:%lx;", signal,
117                     RSP_REG, save_area[RSP_REG],
118                     RIP_REG, save_area[RIP_REG]);
119#else
120    int r = snprintf(buffer, sizeof(buffer), "S%02x", signal);
121#endif
122    assert(r < sizeof(buffer));
123    if (r >= sizeof(buffer)) {
124        // ensure termination in the case of overflow
125        buffer[sizeof(buffer) - 1] = '\0';
126    }
127
128    gdb_arch_registers = save_area;
129    gdb_stub_entry(signal, buffer);
130}
131
132/** \brief Get the value of a single register in the frame.
133 * \param regnum register number (as defined by the #gdb_register_nums enum)
134 * \param value pointer to location in which to return current value
135 * \return Zero on success, nonzero on failure (invalid regnum).
136 */
137int gdb_arch_get_register(int regnum, uintptr_t *value)
138{
139    if (regnum < 0 || regnum >= GDB_X86_64_NUM_REGS) {
140        return -1;
141    }
142
143    *value = gdb_arch_registers[regnum];
144    return 0;
145}
146
147/** \brief Set the value of a single register in the frame.
148 * \param regnum register number (as defined by the #gdb_register_nums enum)
149 * \param value new value
150 * \return Zero on success, nonzero on failure (invalid regnum).
151 */
152int gdb_arch_set_register(int regnum, uintptr_t value)
153{
154    if (regnum < 0 || regnum >= GDB_X86_64_NUM_REGS) {
155        return -1;
156    }
157
158    gdb_arch_registers[regnum] = value;
159    return 0;
160}
161
162/** \brief Resume execution.
163 *
164 * Resumes execution with the CPU state stored in the #gdb_arch_registers frame.
165 */
166void gdb_resume(void) __attribute__((noreturn));
167
168__asm__ (
169    ".global gdb_resume                 \n"
170    "gdb_resume:                        \n"
171    /* load address (in PIC manner) of register frame */
172    "movq gdb_arch_registers(%rip), %r15\n"
173    /* setup stack for iretq below */
174    "movq (19*8)(%r15), %rax            \n" // SS
175    "pushq %rax                         \n"
176    "movq (7*8)(%r15), %rax             \n" // RSP
177    "pushq %rax                         \n"
178    "movq (17*8)(%r15), %rax            \n" // EFLAGS
179    "pushq %rax                         \n"
180    "movq (18*8)(%r15), %rax            \n" // CS
181    "pushq %rax                         \n"
182    "movq (16*8)(%r15), %rax            \n" // EIP
183    "pushq %rax                         \n"
184    /* load remaining registers directly */
185    "movq (0*8)(%r15), %rax             \n"
186    "movq (1*8)(%r15), %rbx             \n"
187    "movq (2*8)(%r15), %rcx             \n"
188    "movq (3*8)(%r15), %rdx             \n"
189    "movq (4*8)(%r15), %rsi             \n"
190    "movq (5*8)(%r15), %rdi             \n"
191    "movq (6*8)(%r15), %rbp             \n"
192    "movq (8*8)(%r15), %r8              \n"
193    "movq (9*8)(%r15), %r9              \n"
194    "movq (10*8)(%r15), %r10            \n"
195    "movq (11*8)(%r15), %r11            \n"
196    "movq (12*8)(%r15), %r12            \n"
197    "movq (13*8)(%r15), %r13            \n"
198    "movq (14*8)(%r15), %r14            \n"
199    "movq (15*8)(%r15), %r15            \n"
200    /* return! */
201    "iretq                              \n"
202);
203
204/** \brief Resume program execution.
205 * \param addr Address to resume at, or 0 to continue at last address.
206 */
207void gdb_arch_continue(lvaddr_t addr)
208{
209    if (addr != 0) {
210        gdb_arch_registers[GDB_X86_64_RIP_REG] = addr;
211    }
212
213    /* clear the trace bit */
214    gdb_arch_registers[GDB_X86_64_EFLAGS_REG] &= ~0x100; // XXX
215
216    gdb_resume(); /* doesn't return */
217}
218
219/** \brief Single-step program execution.
220 * \param addr Address to resume at, or 0 to continue at last address.
221 */
222void gdb_arch_single_step(lvaddr_t addr)
223{
224    if (addr != 0) {
225        gdb_arch_registers[GDB_X86_64_RIP_REG] = addr;
226    }
227
228    /* set the trace bit for single-step */
229    gdb_arch_registers[GDB_X86_64_EFLAGS_REG] |= 0x100; // XXX
230
231    gdb_resume(); /* doesn't return */
232}
233
234/** \brief Ensures that the page containing addr is mapped.
235 * \return Zero on success, negative on failure.
236 */
237static int ensure_mapping(lvaddr_t addr)
238{
239    static lpaddr_t lastaddr;
240
241    /* check if address is in kernel image */
242    if (addr >= (lvaddr_t)&_start_kernel && addr < (lvaddr_t)&_end_kernel) {
243        return 0;
244    }
245
246    /* if address is outside "physical" memory region, fail the access */
247    if (addr < MEMORY_OFFSET) {
248        return -1;
249    }
250
251    /* we now know we have a valid "physical memory" region address */
252    lpaddr_t paddr = mem_to_local_phys(addr);
253    paddr -= paddr & X86_64_MEM_PAGE_MASK; // page-align
254
255    /* quick and dirty optimisation: if this address is on the same page as
256     * the last time we were called, return immediately */
257    if (lastaddr == paddr && lastaddr != 0) {
258        return 0;
259    }
260
261    int r = paging_x86_64_map_memory(paddr, X86_64_MEM_PAGE_SIZE);
262    if (r < 0) {
263        return r;
264    }
265
266    lastaddr = paddr;
267    return 0;
268}
269
270/** \brief Writes a byte to an arbitrary address in kernel memory.
271 * \return Zero on success, nonzero on error (invalid address)
272 */
273int gdb_arch_write_byte(uint8_t *addr, uint8_t val)
274{
275    int r = ensure_mapping((lvaddr_t)addr);
276    if (r < 0) {
277        return r;
278    }
279
280    *addr = val;
281    return 0;
282}
283
284/** \brief Reads a byte from an arbitrary address in kernel memory.
285 * \return Zero on success, nonzero on error (invalid address)
286 */
287int gdb_arch_read_byte(uint8_t *addr, uint8_t *val)
288{
289    int r = ensure_mapping((lvaddr_t)addr);
290    if (r < 0) {
291        return r;
292    }
293
294    *val = *addr;
295    return 0;
296}
297