linux/arch/frv/kernel/debug-stub.c
<<
>>
Prefs
   1/* debug-stub.c: debug-mode stub
   2 *
   3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
   4 * Written by David Howells (dhowells@redhat.com)
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License
   8 * as published by the Free Software Foundation; either version
   9 * 2 of the License, or (at your option) any later version.
  10 */
  11
  12#include <linux/string.h>
  13#include <linux/kernel.h>
  14#include <linux/signal.h>
  15#include <linux/sched.h>
  16#include <linux/init.h>
  17#include <linux/serial_reg.h>
  18
  19#include <asm/system.h>
  20#include <asm/serial-regs.h>
  21#include <asm/timer-regs.h>
  22#include <asm/irc-regs.h>
  23#include <asm/gdb-stub.h>
  24#include "gdb-io.h"
  25
  26/* CPU board CON5 */
  27#define __UART0(X) (*(volatile uint8_t *)(UART0_BASE + (UART_##X)))
  28
  29#define LSR_WAIT_FOR0(STATE)                    \
  30do {                                            \
  31} while (!(__UART0(LSR) & UART_LSR_##STATE))
  32
  33#define FLOWCTL_QUERY0(LINE)    ({ __UART0(MSR) & UART_MSR_##LINE; })
  34#define FLOWCTL_CLEAR0(LINE)    do { __UART0(MCR) &= ~UART_MCR_##LINE; } while (0)
  35#define FLOWCTL_SET0(LINE)      do { __UART0(MCR) |= UART_MCR_##LINE; } while (0)
  36
  37#define FLOWCTL_WAIT_FOR0(LINE)                 \
  38do {                                            \
  39        gdbstub_do_rx();                        \
  40} while(!FLOWCTL_QUERY(LINE))
  41
  42struct frv_debug_status __debug_status;
  43
  44static void __init debug_stub_init(void);
  45
  46/*****************************************************************************/
  47/*
  48 * debug mode handler stub
  49 * - we come here with the CPU in debug mode and with exceptions disabled
  50 * - handle debugging services for userspace
  51 */
  52asmlinkage void debug_stub(void)
  53{
  54        unsigned long hsr0;
  55        int type = 0;
  56
  57        static u8 inited = 0;
  58        if (!inited) {
  59                debug_stub_init();
  60                type = -1;
  61                inited = 1;
  62        }
  63
  64        hsr0 = __get_HSR(0);
  65        if (hsr0 & HSR0_ETMD)
  66                __set_HSR(0, hsr0 & ~HSR0_ETMD);
  67
  68        /* disable single stepping */
  69        __debug_status.dcr &= ~DCR_SE;
  70
  71        /* kernel mode can propose an exception be handled in debug mode by jumping to a special
  72         * location */
  73        if (__debug_frame->pc == (unsigned long) __break_hijack_kernel_event_breaks_here) {
  74                /* replace the debug frame with the kernel frame and discard
  75                 * the top kernel context */
  76                *__debug_frame = *__frame;
  77                __frame = __debug_frame->next_frame;
  78                __debug_status.brr = (__debug_frame->tbr & TBR_TT) << 12;
  79                __debug_status.brr |= BRR_EB;
  80        }
  81
  82        if (__debug_frame->pc == (unsigned long) __debug_bug_trap + 4) {
  83                __debug_frame->pc = __debug_frame->lr;
  84                type = __debug_frame->gr8;
  85        }
  86
  87#ifdef CONFIG_GDBSTUB
  88        gdbstub(type);
  89#endif
  90
  91        if (hsr0 & HSR0_ETMD)
  92                __set_HSR(0, __get_HSR(0) | HSR0_ETMD);
  93
  94} /* end debug_stub() */
  95
  96/*****************************************************************************/
  97/*
  98 * debug stub initialisation
  99 */
 100static void __init debug_stub_init(void)
 101{
 102        __set_IRR(6, 0xff000000);       /* map ERRs to NMI */
 103        __set_IITMR(1, 0x20000000);     /* ERR0/1, UART0/1 IRQ detect levels */
 104
 105        asm volatile("  movgs   gr0,ibar0       \n"
 106                     "  movgs   gr0,ibar1       \n"
 107                     "  movgs   gr0,ibar2       \n"
 108                     "  movgs   gr0,ibar3       \n"
 109                     "  movgs   gr0,dbar0       \n"
 110                     "  movgs   gr0,dbmr00      \n"
 111                     "  movgs   gr0,dbmr01      \n"
 112                     "  movgs   gr0,dbdr00      \n"
 113                     "  movgs   gr0,dbdr01      \n"
 114                     "  movgs   gr0,dbar1       \n"
 115                     "  movgs   gr0,dbmr10      \n"
 116                     "  movgs   gr0,dbmr11      \n"
 117                     "  movgs   gr0,dbdr10      \n"
 118                     "  movgs   gr0,dbdr11      \n"
 119                     );
 120
 121        /* deal with debugging stub initialisation and initial pause */
 122        if (__debug_frame->pc == (unsigned long) __debug_stub_init_break)
 123                __debug_frame->pc = (unsigned long) start_kernel;
 124
 125        /* enable the debug events we want to trap */
 126        __debug_status.dcr = DCR_EBE;
 127
 128#ifdef CONFIG_GDBSTUB
 129        gdbstub_init();
 130#endif
 131
 132        __clr_MASK_all();
 133        __clr_MASK(15);
 134        __clr_RC(15);
 135
 136} /* end debug_stub_init() */
 137
 138/*****************************************************************************/
 139/*
 140 * kernel "exit" trap for gdb stub
 141 */
 142void debug_stub_exit(int status)
 143{
 144
 145#ifdef CONFIG_GDBSTUB
 146        gdbstub_exit(status);
 147#endif
 148
 149} /* end debug_stub_exit() */
 150
 151/*****************************************************************************/
 152/*
 153 * send string to serial port
 154 */
 155void debug_to_serial(const char *p, int n)
 156{
 157        char ch;
 158
 159        for (; n > 0; n--) {
 160                ch = *p++;
 161                FLOWCTL_SET0(DTR);
 162                LSR_WAIT_FOR0(THRE);
 163                // FLOWCTL_WAIT_FOR(CTS);
 164
 165                if (ch == 0x0a) {
 166                        __UART0(TX) = 0x0d;
 167                        mb();
 168                        LSR_WAIT_FOR0(THRE);
 169                        // FLOWCTL_WAIT_FOR(CTS);
 170                }
 171                __UART0(TX) = ch;
 172                mb();
 173
 174                FLOWCTL_CLEAR0(DTR);
 175        }
 176
 177} /* end debug_to_serial() */
 178
 179/*****************************************************************************/
 180/*
 181 * send string to serial port
 182 */
 183void debug_to_serial2(const char *fmt, ...)
 184{
 185        va_list va;
 186        char buf[64];
 187        int n;
 188
 189        va_start(va, fmt);
 190        n = vsprintf(buf, fmt, va);
 191        va_end(va);
 192
 193        debug_to_serial(buf, n);
 194
 195} /* end debug_to_serial2() */
 196
 197/*****************************************************************************/
 198/*
 199 * set up the ttyS0 serial port baud rate timers
 200 */
 201void __init console_set_baud(unsigned baud)
 202{
 203        unsigned value, high, low;
 204        u8 lcr;
 205
 206        /* work out the divisor to give us the nearest higher baud rate */
 207        value = __serial_clock_speed_HZ / 16 / baud;
 208
 209        /* determine the baud rate range */
 210        high = __serial_clock_speed_HZ / 16 / value;
 211        low = __serial_clock_speed_HZ / 16 / (value + 1);
 212
 213        /* pick the nearest bound */
 214        if (low + (high - low) / 2 > baud)
 215                value++;
 216
 217        lcr = __UART0(LCR);
 218        __UART0(LCR) |= UART_LCR_DLAB;
 219        mb();
 220        __UART0(DLL) = value & 0xff;
 221        __UART0(DLM) = (value >> 8) & 0xff;
 222        mb();
 223        __UART0(LCR) = lcr;
 224        mb();
 225
 226} /* end console_set_baud() */
 227
 228/*****************************************************************************/
 229/*
 230 *
 231 */
 232int __init console_get_baud(void)
 233{
 234        unsigned value;
 235        u8 lcr;
 236
 237        lcr = __UART0(LCR);
 238        __UART0(LCR) |= UART_LCR_DLAB;
 239        mb();
 240        value =  __UART0(DLM) << 8;
 241        value |= __UART0(DLL);
 242        __UART0(LCR) = lcr;
 243        mb();
 244
 245        return value;
 246} /* end console_get_baud() */
 247
 248/*****************************************************************************/
 249/*
 250 * display BUG() info
 251 */
 252#ifndef CONFIG_NO_KERNEL_MSG
 253void __debug_bug_printk(const char *file, unsigned line)
 254{
 255        printk("kernel BUG at %s:%d!\n", file, line);
 256
 257} /* end __debug_bug_printk() */
 258#endif
 259