Merge master.kernel.org:/pub/scm/linux/kernel/git/herbert/crypto-2.6
[linux-drm-fsl-dcu.git] / arch / sh / kernel / kgdb_stub.c
index 9c6315f0335dfdc45bac2f8aa47a3fc9fa0adb11..a5323364cbca7c7c884d9c407ce02d7c777d9511 100644 (file)
@@ -6,11 +6,11 @@
  * David Grothe <dave@gcom.com>, Tigran Aivazian <tigran@sco.com>,
  * Amit S. Kale <akale@veritas.com>,  William Gatliff <bgat@open-widgets.com>,
  * Ben Lee, Steve Chamberlain and Benoit Miller <fulg@iname.com>.
- * 
+ *
  * This version by Henry Bell <henry.bell@st.com>
  * Minor modifications by Jeremy Siegel <jsiegel@mvista.com>
- * 
- * Contains low-level support for remote debug using GDB. 
+ *
+ * Contains low-level support for remote debug using GDB.
  *
  * To enable debugger support, two things need to happen. A call to
  * set_debug_traps() is necessary in order to allow any breakpoints
@@ -48,7 +48,7 @@
  *    k             kill (Detach GDB)
  *
  *    d             Toggle debug flag
- *    D             Detach GDB 
+ *    D             Detach GDB
  *
  *    Hct           Set thread t for operations,           OK or ENN
  *                  c = 'c' (step, cont), c = 'g' (other
@@ -58,7 +58,7 @@
  *    qfThreadInfo  Get list of current threads (first)    m<id>
  *    qsThreadInfo   "    "  "     "      "   (subsequent)
  *    qOffsets      Get section offsets                  Text=x;Data=y;Bss=z
- * 
+ *
  *    TXX           Find if thread XX is alive             OK or ENN
  *    ?             What was the last sigval ?             SNN   (signal NN)
  *    O             Output to GDB console
@@ -74,7 +74,7 @@
  *       '$' or '#'.  If <data> starts with two characters followed by
  *       ':', then the existing stubs interpret this as a sequence number.
  *
- *       CSUM1 and CSUM2 are ascii hex representation of an 8-bit 
+ *       CSUM1 and CSUM2 are ascii hex representation of an 8-bit
  *       checksum of <data>, the most significant nibble is sent first.
  *       the hex digits 0-9,a-f are used.
  *
@@ -86,8 +86,8 @@
  * Responses can be run-length encoded to save space.  A '*' means that
  * the next character is an ASCII encoding giving a repeat count which
  * stands for that many repititions of the character preceding the '*'.
- * The encoding is n+29, yielding a printable character where n >=3 
- * (which is where RLE starts to win).  Don't use an n > 126. 
+ * The encoding is n+29, yielding a printable character where n >=3
+ * (which is where RLE starts to win).  Don't use an n > 126.
  *
  * So "0* " means the same as "0000".
  */
 #include <linux/delay.h>
 #include <linux/linkage.h>
 #include <linux/init.h>
-
-#ifdef CONFIG_SH_KGDB_CONSOLE
 #include <linux/console.h>
-#endif
-
+#include <linux/sysrq.h>
 #include <asm/system.h>
+#include <asm/cacheflush.h>
 #include <asm/current.h>
 #include <asm/signal.h>
 #include <asm/pgtable.h>
@@ -153,7 +151,6 @@ char kgdb_in_gdb_mode;
 char in_nmi;                   /* Set during NMI to prevent reentry */
 int kgdb_nofault;              /* Boolean to ignore bus errs (i.e. in GDB) */
 int kgdb_enabled = 1;          /* Default to enabled, cmdline can disable */
-int kgdb_halt;
 
 /* Exposed for user access */
 struct task_struct *kgdb_current;
@@ -246,14 +243,6 @@ static char out_buffer[OUTBUFMAX];
 
 static void kgdb_to_gdb(const char *s);
 
-#ifdef CONFIG_KGDB_THREAD
-static struct task_struct *trapped_thread;
-static struct task_struct *current_thread;
-typedef unsigned char threadref[8];
-#define BUF_THREAD_ID_SIZE 16
-#endif
-
-
 /* Convert ch to hex */
 static int hex(const char ch)
 {
@@ -328,7 +317,7 @@ static int hex_to_int(char **ptr, int *int_value)
 }
 
 /*  Copy the binary array pointed to by buf into mem.  Fix $, #,
-    and 0x7d escaped with 0x7d.  Return a pointer to the character 
+    and 0x7d escaped with 0x7d.  Return a pointer to the character
     after the last byte written. */
 static char *ebin_to_mem(const char *buf, char *mem, int count)
 {
@@ -349,66 +338,6 @@ static char *pack_hex_byte(char *pkt, int byte)
        return pkt;
 }
 
-#ifdef CONFIG_KGDB_THREAD
-
-/* Pack a thread ID */
-static char *pack_threadid(char *pkt, threadref * id)
-{
-       char *limit;
-       unsigned char *altid;
-
-       altid = (unsigned char *) id;
-
-       limit = pkt + BUF_THREAD_ID_SIZE;
-       while (pkt < limit)
-               pkt = pack_hex_byte(pkt, *altid++);
-       return pkt;
-}
-
-/* Convert an integer into our threadref */
-static void int_to_threadref(threadref * id, const int value)
-{
-       unsigned char *scan = (unsigned char *) id;
-       int i = 4;
-
-       while (i--)
-               *scan++ = 0;
-
-       *scan++ = (value >> 24) & 0xff;
-       *scan++ = (value >> 16) & 0xff;
-       *scan++ = (value >> 8) & 0xff;
-       *scan++ = (value & 0xff);
-}
-
-/* Return a task structure ptr for a particular pid */
-static struct task_struct *get_thread(int pid)
-{
-       struct task_struct *thread;
-
-       /* Use PID_MAX w/gdb for pid 0 */
-       if (pid == PID_MAX) pid = 0;
-
-       /* First check via PID */
-       thread = find_task_by_pid(pid);
-
-       if (thread)
-               return thread;
-
-       /* Start at the start */
-       thread = init_tasks[0];
-
-       /* Walk along the linked list of tasks */
-       do {
-               if (thread->pid == pid)
-                       return thread;
-               thread = thread->next_task;
-       } while (thread != init_tasks[0]);
-
-       return NULL;
-}
-
-#endif /* CONFIG_KGDB_THREAD */
-
 /* Scan for the start char '$', read the packet and check the checksum */
 static void get_packet(char *buffer, int buflen)
 {
@@ -452,7 +381,7 @@ static void get_packet(char *buffer, int buflen)
                                /* Ack successful transfer */
                                put_debug_char('+');
 
-                               /* If a sequence char is present, reply 
+                               /* If a sequence char is present, reply
                                   the sequence ID */
                                if (buffer[2] == ':') {
                                        put_debug_char(buffer[0]);
@@ -611,74 +540,6 @@ static void gdb_regs_to_kgdb_regs(const int *gdb_regs,
        regs->vbr = gdb_regs[VBR];
 }
 
-#ifdef CONFIG_KGDB_THREAD
-/* Make a local copy of registers from the specified thread */
-asmlinkage void ret_from_fork(void);
-static void thread_regs_to_gdb_regs(const struct task_struct *thread,
-                                   int *gdb_regs)
-{
-       int regno;
-       int *tregs;
-
-       /* Initialize to zero */
-       for (regno = 0; regno < MAXREG; regno++)
-               gdb_regs[regno] = 0;
-
-       /* Just making sure... */
-       if (thread == NULL)
-               return;
-
-       /* A new fork has pt_regs on the stack from a fork() call */
-       if (thread->thread.pc == (unsigned long)ret_from_fork) {
-
-               int vbr_val;
-               struct pt_regs *kregs;
-               kregs = (struct pt_regs*)thread->thread.sp;
-
-               gdb_regs[R0] = kregs->regs[R0];
-               gdb_regs[R1] = kregs->regs[R1];
-               gdb_regs[R2] = kregs->regs[R2];
-               gdb_regs[R3] = kregs->regs[R3];
-               gdb_regs[R4] = kregs->regs[R4];
-               gdb_regs[R5] = kregs->regs[R5];
-               gdb_regs[R6] = kregs->regs[R6];
-               gdb_regs[R7] = kregs->regs[R7];
-               gdb_regs[R8] = kregs->regs[R8];
-               gdb_regs[R9] = kregs->regs[R9];
-               gdb_regs[R10] = kregs->regs[R10];
-               gdb_regs[R11] = kregs->regs[R11];
-               gdb_regs[R12] = kregs->regs[R12];
-               gdb_regs[R13] = kregs->regs[R13];
-               gdb_regs[R14] = kregs->regs[R14];
-               gdb_regs[R15] = kregs->regs[R15];
-               gdb_regs[PC] = kregs->pc;
-               gdb_regs[PR] = kregs->pr;
-               gdb_regs[GBR] = kregs->gbr;
-               gdb_regs[MACH] = kregs->mach;
-               gdb_regs[MACL] = kregs->macl;
-               gdb_regs[SR] = kregs->sr;
-
-               asm("stc vbr, %0":"=r"(vbr_val));
-               gdb_regs[VBR] = vbr_val;
-               return;
-       }
-
-       /* Otherwise, we have only some registers from switch_to() */
-       tregs = (int *)thread->thread.sp;
-       gdb_regs[R15] = (int)tregs;
-       gdb_regs[R14] = *tregs++;
-       gdb_regs[R13] = *tregs++;
-       gdb_regs[R12] = *tregs++;
-       gdb_regs[R11] = *tregs++;
-       gdb_regs[R10] = *tregs++;
-       gdb_regs[R9] = *tregs++;
-       gdb_regs[R8] = *tregs++;
-       gdb_regs[PR] = *tregs++;
-       gdb_regs[GBR] = *tregs++;
-       gdb_regs[PC] = thread->thread.pc;
-}
-#endif /* CONFIG_KGDB_THREAD */
-
 /* Calculate the new address for after a step */
 static short *get_step_address(void)
 {
@@ -759,7 +620,7 @@ static short *get_step_address(void)
        return (short *) addr;
 }
 
-/* Set up a single-step.  Replace the instruction immediately after the 
+/* Set up a single-step.  Replace the instruction immediately after the
    current instruction (i.e. next in the expected flow of control) with a
    trap instruction, so that returning will cause only a single instruction
    to be executed. Note that this model is slightly broken for instructions
@@ -797,37 +658,11 @@ static void undo_single_step(void)
 /* Send a signal message */
 static void send_signal_msg(const int signum)
 {
-#ifndef CONFIG_KGDB_THREAD
        out_buffer[0] = 'S';
        out_buffer[1] = highhex(signum);
        out_buffer[2] = lowhex(signum);
        out_buffer[3] = 0;
        put_packet(out_buffer);
-#else /* CONFIG_KGDB_THREAD */
-       int threadid;
-       threadref thref;
-       char *out = out_buffer;
-       const char *tstring = "thread";
-
-       *out++ = 'T';
-       *out++ = highhex(signum);
-       *out++ = lowhex(signum);
-
-       while (*tstring) {
-               *out++ = *tstring++;
-       }
-       *out++ = ':';
-
-       threadid = trapped_thread->pid;
-       if (threadid == 0) threadid = PID_MAX;
-       int_to_threadref(&thref, threadid);
-       pack_threadid(out, &thref);
-       out += BUF_THREAD_ID_SIZE;
-       *out++ = ';';
-
-       *out = 0;
-       put_packet(out_buffer);
-#endif /* CONFIG_KGDB_THREAD */
 }
 
 /* Reply that all was well */
@@ -962,15 +797,7 @@ static void step_with_sig_msg(void)
 /* Send register contents */
 static void send_regs_msg(void)
 {
-#ifdef CONFIG_KGDB_THREAD
-       if (!current_thread)
-               kgdb_regs_to_gdb_regs(&trap_registers, registers);
-       else
-               thread_regs_to_gdb_regs(current_thread, registers);
-#else
        kgdb_regs_to_gdb_regs(&trap_registers, registers);
-#endif
-
        mem_to_hex((char *) registers, out_buffer, NUMREGBYTES);
        put_packet(out_buffer);
 }
@@ -978,201 +805,13 @@ static void send_regs_msg(void)
 /* Set register contents - currently can't set other thread's registers */
 static void set_regs_msg(void)
 {
-#ifdef CONFIG_KGDB_THREAD
-       if (!current_thread) {
-#endif
-               kgdb_regs_to_gdb_regs(&trap_registers, registers);
-               hex_to_mem(&in_buffer[1], (char *) registers, NUMREGBYTES);
-               gdb_regs_to_kgdb_regs(registers, &trap_registers);
-               send_ok_msg();
-#ifdef CONFIG_KGDB_THREAD
-       } else
-               send_err_msg();
-#endif
-}
-
-
-#ifdef CONFIG_KGDB_THREAD
-
-/* Set the status for a thread */
-void set_thread_msg(void)
-{
-       int threadid;
-       struct task_struct *thread = NULL;
-       char *ptr;
-
-       switch (in_buffer[1]) {
-
-               /* To select which thread for gG etc messages, i.e. supported */
-       case 'g':
-
-               ptr = &in_buffer[2];
-               hex_to_int(&ptr, &threadid);
-               thread = get_thread(threadid);
-
-               /* If we haven't found it */
-               if (!thread) {
-                       send_err_msg();
-                       break;
-               }
-
-               /* Set current_thread (or not) */
-               if (thread == trapped_thread)
-                       current_thread = NULL;
-               else
-                       current_thread = thread;
-               send_ok_msg();
-               break;
-
-       /* To select which thread for cCsS messages, i.e. unsupported */
-       case 'c':
-               send_ok_msg();
-               break;
-
-       default:
-               send_empty_msg();
-               break;
-       }
-}
-
-/* Is a thread alive? */
-static void thread_status_msg(void)
-{
-       char *ptr;
-       int threadid;
-       struct task_struct *thread = NULL;
-
-       ptr = &in_buffer[1];
-       hex_to_int(&ptr, &threadid);
-       thread = get_thread(threadid);
-       if (thread)
-               send_ok_msg();
-       else
-               send_err_msg();
-}
-/* Send the current thread ID */
-static void thread_id_msg(void)
-{
-       int threadid;
-       threadref thref;
-
-       out_buffer[0] = 'Q';
-       out_buffer[1] = 'C';
-
-       if (current_thread)
-               threadid = current_thread->pid;
-       else if (trapped_thread)
-               threadid = trapped_thread->pid;
-       else /* Impossible, but just in case! */
-       {
-               send_err_msg();
-               return;
-       }
-
-       /* Translate pid 0 to PID_MAX for gdb */
-       if (threadid == 0) threadid = PID_MAX;
-
-       int_to_threadref(&thref, threadid);
-       pack_threadid(out_buffer + 2, &thref);
-       out_buffer[2 + BUF_THREAD_ID_SIZE] = '\0';
-       put_packet(out_buffer);
-}
-
-/* Send thread info */
-static void thread_info_msg(void)
-{
-       struct task_struct *thread = NULL;
-       int threadid;
-       char *pos;
-       threadref thref;
-
-       /* Start with 'm' */
-       out_buffer[0] = 'm';
-       pos = &out_buffer[1];
-
-       /* For all possible thread IDs - this will overrun if > 44 threads! */
-       /* Start at 1 and include PID_MAX (since GDB won't use pid 0...) */
-       for (threadid = 1; threadid <= PID_MAX; threadid++) {
-
-               read_lock(&tasklist_lock);
-               thread = get_thread(threadid);
-               read_unlock(&tasklist_lock);
-
-               /* If it's a valid thread */
-               if (thread) {
-                       int_to_threadref(&thref, threadid);
-                       pack_threadid(pos, &thref);
-                       pos += BUF_THREAD_ID_SIZE;
-                       *pos++ = ',';
-               }
-       }
-       *--pos = 0;             /* Lose final comma */
-       put_packet(out_buffer);
-
-}
-
-/* Return printable info for gdb's 'info threads' command */
-static void thread_extra_info_msg(void)
-{
-       int threadid;
-       struct task_struct *thread = NULL;
-       char buffer[20], *ptr;
-       int i;
-
-       /* Extract thread ID */
-       ptr = &in_buffer[17];
-       hex_to_int(&ptr, &threadid);
-       thread = get_thread(threadid);
-
-       /* If we don't recognise it, say so */
-       if (thread == NULL)
-               strcpy(buffer, "(unknown)");
-       else
-               strcpy(buffer, thread->comm);
-
-       /* Construct packet */
-       for (i = 0, ptr = out_buffer; buffer[i]; i++)
-               ptr = pack_hex_byte(ptr, buffer[i]);
-
-       if (thread->thread.pc == (unsigned long)ret_from_fork) {
-               strcpy(buffer, "<new fork>");
-               for (i = 0; buffer[i]; i++)
-                       ptr = pack_hex_byte(ptr, buffer[i]);
-       }
-
-       *ptr = '\0';
-       put_packet(out_buffer);
-}
-
-/* Handle all qFooBarBaz messages - have to use an if statement as
-   opposed to a switch because q messages can have > 1 char id. */
-static void query_msg(void)
-{
-       const char *q_start = &in_buffer[1];
-
-       /* qC = return current thread ID */
-       if (strncmp(q_start, "C", 1) == 0)
-               thread_id_msg();
-
-       /* qfThreadInfo = query all threads (first) */
-       else if (strncmp(q_start, "fThreadInfo", 11) == 0)
-               thread_info_msg();
-
-       /* qsThreadInfo = query all threads (subsequent). We know we have sent
-          them all after the qfThreadInfo message, so there are no to send */
-       else if (strncmp(q_start, "sThreadInfo", 11) == 0)
-               put_packet("l");        /* el = last */
-
-       /* qThreadExtraInfo = supply printable information per thread */
-       else if (strncmp(q_start, "ThreadExtraInfo", 15) == 0)
-               thread_extra_info_msg();
-
-       /* Unsupported - empty message as per spec */
-       else
-               send_empty_msg();
+       kgdb_regs_to_gdb_regs(&trap_registers, registers);
+       hex_to_mem(&in_buffer[1], (char *) registers, NUMREGBYTES);
+       gdb_regs_to_kgdb_regs(registers, &trap_registers);
+       send_ok_msg();
 }
-#endif /* CONFIG_KGDB_THREAD */
 
+#ifdef CONFIG_SH_KGDB_CONSOLE
 /*
  * Bring up the ports..
  */
@@ -1185,6 +824,9 @@ static int kgdb_serial_setup(void)
 
        return 0;
 }
+#else
+#define kgdb_serial_setup()    0
+#endif
 
 /* The command loop, read and act on requests */
 static void kgdb_command_loop(const int excep_code, const int trapa_value)
@@ -1193,7 +835,7 @@ static void kgdb_command_loop(const int excep_code, const int trapa_value)
 
        if (excep_code == NMI_VEC) {
 #ifndef CONFIG_KGDB_NMI
-               KGDB_PRINTK("Ignoring unexpected NMI?\n");
+               printk(KERN_NOTICE "KGDB: Ignoring unexpected NMI?\n");
                return;
 #else /* CONFIG_KGDB_NMI */
                if (!kgdb_enabled) {
@@ -1207,19 +849,10 @@ static void kgdb_command_loop(const int excep_code, const int trapa_value)
        if (!kgdb_enabled)
                return;
 
-#ifdef CONFIG_KGDB_THREAD
-       /* Until GDB specifies a thread */
-       current_thread = NULL;
-       trapped_thread = current;
-#endif
-
        /* Enter GDB mode (e.g. after detach) */
        if (!kgdb_in_gdb_mode) {
                /* Do serial setup, notify user, issue preemptive ack */
-               kgdb_serial_setup();
-               KGDB_PRINTK("Waiting for GDB (on %s%d at %d baud)\n",
-                           (kgdb_porttype ? kgdb_porttype->name : ""),
-                           kgdb_portnum, kgdb_baud);
+               printk(KERN_NOTICE "KGDB: Waiting for GDB\n");
                kgdb_in_gdb_mode = 1;
                put_debug_char('+');
        }
@@ -1233,21 +866,18 @@ static void kgdb_command_loop(const int excep_code, const int trapa_value)
           will later be replaced by its original one.  Do NOT do this for
           trap 0xff, since that indicates a compiled-in breakpoint which
           will not be replaced (and we would retake the trap forever) */
-       if ((excep_code == TRAP_VEC) && (trapa_value != (0xff << 2))) {
+       if ((excep_code == TRAP_VEC) && (trapa_value != (0x3c << 2)))
                trap_registers.pc -= 2;
-       }
 
        /* Undo any stepping we may have done */
        undo_single_step();
 
        while (1) {
-
                out_buffer[0] = 0;
                get_packet(in_buffer, BUFMAX);
 
                /* Examine first char of buffer to see what we need to do */
                switch (in_buffer[0]) {
-
                case '?':       /* Send which signal we've received */
                        send_signal_msg(sigval);
                        break;
@@ -1291,21 +921,6 @@ static void kgdb_command_loop(const int excep_code, const int trapa_value)
                        step_msg();
                        return;
 
-#ifdef CONFIG_KGDB_THREAD
-
-               case 'H':       /* Task related */
-                       set_thread_msg();
-                       break;
-
-               case 'T':       /* Query thread status */
-                       thread_status_msg();
-                       break;
-
-               case 'q':       /* Handle query - currently thread-related */
-                       query_msg();
-                       break;
-#endif
-
                case 'k':       /* 'Kill the program' with a kernel ? */
                        break;
 
@@ -1323,7 +938,7 @@ static void kgdb_command_loop(const int excep_code, const int trapa_value)
 }
 
 /* There has been an exception, most likely a breakpoint. */
-void kgdb_handle_exception(struct pt_regs *regs)
+static void handle_exception(struct pt_regs *regs)
 {
        int excep_code, vbr_val;
        int count;
@@ -1352,7 +967,7 @@ void kgdb_handle_exception(struct pt_regs *regs)
        kgdb_trapa_val = trapa_value;
 
        /* Act on the exception */
-       kgdb_command_loop(excep_code >> 5, trapa_value);
+       kgdb_command_loop(excep_code, trapa_value);
 
        kgdb_current = NULL;
 
@@ -1368,18 +983,14 @@ void kgdb_handle_exception(struct pt_regs *regs)
 
        vbr_val = trap_registers.vbr;
        asm("ldc %0, vbr": :"r"(vbr_val));
-
-       return;
 }
 
-/* Trigger a breakpoint by function */
-void breakpoint(void)
+asmlinkage void kgdb_handle_exception(unsigned long r4, unsigned long r5,
+                                     unsigned long r6, unsigned long r7,
+                                     struct pt_regs __regs)
 {
-       if (!kgdb_enabled) {
-               kgdb_enabled = 1;
-               kgdb_init();
-       }
-       BREAKPOINT();
+       struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
+       handle_exception(regs);
 }
 
 /* Initialise the KGDB data structures and serial configuration */
@@ -1394,24 +1005,16 @@ int kgdb_init(void)
        kgdb_in_gdb_mode = 0;
 
        if (kgdb_serial_setup() != 0) {
-               KGDB_PRINTK("serial setup error\n");
+               printk(KERN_NOTICE "KGDB: serial setup error\n");
                return -1;
        }
 
        /* Init ptr to exception handler */
-       kgdb_debug_hook = kgdb_handle_exception;
+       kgdb_debug_hook = handle_exception;
        kgdb_bus_err_hook = kgdb_handle_bus_error;
 
        /* Enter kgdb now if requested, or just report init done */
-       if (kgdb_halt) {
-               kgdb_in_gdb_mode = 1;
-               put_debug_char('+');
-               breakpoint();
-       }
-       else
-       {
-               KGDB_PRINTK("stub is initialized.\n");
-       }
+       printk(KERN_NOTICE "KGDB: stub is initialized.\n");
 
        return 0;
 }
@@ -1436,7 +1039,7 @@ static void kgdb_msg_write(const char *s, unsigned count)
 
                /* Calculate how many this time */
                wcount = (count > MAXOUT) ? MAXOUT : count;
-               
+
                /* Pack in hex chars */
                for (i = 0; i < wcount; i++)
                        bufptr = pack_hex_byte(bufptr, s[i]);
@@ -1466,3 +1069,25 @@ void kgdb_console_write(struct console *co, const char *s, unsigned count)
        kgdb_msg_write(s, count);
 }
 #endif
+
+#ifdef CONFIG_KGDB_SYSRQ
+static void sysrq_handle_gdb(int key, struct tty_struct *tty)
+{
+       printk("Entering GDB stub\n");
+       breakpoint();
+}
+
+static struct sysrq_key_op sysrq_gdb_op = {
+        .handler        = sysrq_handle_gdb,
+        .help_msg       = "Gdb",
+        .action_msg     = "GDB",
+};
+
+static int gdb_register_sysrq(void)
+{
+       printk("Registering GDB sysrq handler\n");
+       register_sysrq_key('g', &sysrq_gdb_op);
+       return 0;
+}
+module_init(gdb_register_sysrq);
+#endif