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