kgdb,x86: Individual register get/set for x86
[sfrench/cifs-2.6.git] / arch / x86 / kernel / kgdb.c
index 01ab17ae2ae72c7bdf2d2c4de2a51f19f59755bf..bae89825e14e83caa3a67b248ee1b0d2df8d7f09 100644 (file)
 #include <asm/system.h>
 #include <asm/apic.h>
 
-/**
- *     pt_regs_to_gdb_regs - Convert ptrace regs to GDB regs
- *     @gdb_regs: A pointer to hold the registers in the order GDB wants.
- *     @regs: The &struct pt_regs of the current process.
- *
- *     Convert the pt_regs in @regs into the format for registers that
- *     GDB expects, stored in @gdb_regs.
- */
-void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] =
 {
-#ifndef CONFIG_X86_32
-       u32 *gdb_regs32 = (u32 *)gdb_regs;
+#ifdef CONFIG_X86_32
+       { "ax", 4, offsetof(struct pt_regs, ax) },
+       { "cx", 4, offsetof(struct pt_regs, cx) },
+       { "dx", 4, offsetof(struct pt_regs, dx) },
+       { "bx", 4, offsetof(struct pt_regs, bx) },
+       { "sp", 4, offsetof(struct pt_regs, sp) },
+       { "bp", 4, offsetof(struct pt_regs, bp) },
+       { "si", 4, offsetof(struct pt_regs, si) },
+       { "di", 4, offsetof(struct pt_regs, di) },
+       { "ip", 4, offsetof(struct pt_regs, ip) },
+       { "flags", 4, offsetof(struct pt_regs, flags) },
+       { "cs", 4, offsetof(struct pt_regs, cs) },
+       { "ss", 4, offsetof(struct pt_regs, ss) },
+       { "ds", 4, offsetof(struct pt_regs, ds) },
+       { "es", 4, offsetof(struct pt_regs, es) },
+       { "fs", 4, -1 },
+       { "gs", 4, -1 },
+#else
+       { "ax", 8, offsetof(struct pt_regs, ax) },
+       { "bx", 8, offsetof(struct pt_regs, bx) },
+       { "cx", 8, offsetof(struct pt_regs, cx) },
+       { "dx", 8, offsetof(struct pt_regs, dx) },
+       { "si", 8, offsetof(struct pt_regs, dx) },
+       { "di", 8, offsetof(struct pt_regs, di) },
+       { "bp", 8, offsetof(struct pt_regs, bp) },
+       { "sp", 8, offsetof(struct pt_regs, sp) },
+       { "r8", 8, offsetof(struct pt_regs, r8) },
+       { "r9", 8, offsetof(struct pt_regs, r9) },
+       { "r10", 8, offsetof(struct pt_regs, r10) },
+       { "r11", 8, offsetof(struct pt_regs, r11) },
+       { "r12", 8, offsetof(struct pt_regs, r12) },
+       { "r13", 8, offsetof(struct pt_regs, r13) },
+       { "r14", 8, offsetof(struct pt_regs, r14) },
+       { "r15", 8, offsetof(struct pt_regs, r15) },
+       { "ip", 8, offsetof(struct pt_regs, ip) },
+       { "flags", 4, offsetof(struct pt_regs, flags) },
+       { "cs", 4, offsetof(struct pt_regs, cs) },
+       { "ss", 4, offsetof(struct pt_regs, ss) },
 #endif
-       gdb_regs[GDB_AX]        = regs->ax;
-       gdb_regs[GDB_BX]        = regs->bx;
-       gdb_regs[GDB_CX]        = regs->cx;
-       gdb_regs[GDB_DX]        = regs->dx;
-       gdb_regs[GDB_SI]        = regs->si;
-       gdb_regs[GDB_DI]        = regs->di;
-       gdb_regs[GDB_BP]        = regs->bp;
-       gdb_regs[GDB_PC]        = regs->ip;
+};
+
+int dbg_set_reg(int regno, void *mem, struct pt_regs *regs)
+{
+       if (
 #ifdef CONFIG_X86_32
-       gdb_regs[GDB_PS]        = regs->flags;
-       gdb_regs[GDB_DS]        = regs->ds;
-       gdb_regs[GDB_ES]        = regs->es;
-       gdb_regs[GDB_CS]        = regs->cs;
-       gdb_regs[GDB_FS]        = 0xFFFF;
-       gdb_regs[GDB_GS]        = 0xFFFF;
-       if (user_mode_vm(regs)) {
-               gdb_regs[GDB_SS] = regs->ss;
-               gdb_regs[GDB_SP] = regs->sp;
-       } else {
-               gdb_regs[GDB_SS] = __KERNEL_DS;
-               gdb_regs[GDB_SP] = kernel_stack_pointer(regs);
+           regno == GDB_SS || regno == GDB_FS || regno == GDB_GS ||
+#endif
+           regno == GDB_SP || regno == GDB_ORIG_AX)
+               return 0;
+
+       if (dbg_reg_def[regno].offset != -1)
+               memcpy((void *)regs + dbg_reg_def[regno].offset, mem,
+                      dbg_reg_def[regno].size);
+       return 0;
+}
+
+char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
+{
+       if (regno == GDB_ORIG_AX) {
+               memcpy(mem, &regs->orig_ax, sizeof(regs->orig_ax));
+               return "orig_ax";
        }
-#else
-       gdb_regs[GDB_R8]        = regs->r8;
-       gdb_regs[GDB_R9]        = regs->r9;
-       gdb_regs[GDB_R10]       = regs->r10;
-       gdb_regs[GDB_R11]       = regs->r11;
-       gdb_regs[GDB_R12]       = regs->r12;
-       gdb_regs[GDB_R13]       = regs->r13;
-       gdb_regs[GDB_R14]       = regs->r14;
-       gdb_regs[GDB_R15]       = regs->r15;
-       gdb_regs32[GDB_PS]      = regs->flags;
-       gdb_regs32[GDB_CS]      = regs->cs;
-       gdb_regs32[GDB_SS]      = regs->ss;
-       gdb_regs[GDB_SP]        = kernel_stack_pointer(regs);
+       if (regno >= DBG_MAX_REG_NUM || regno < 0)
+               return NULL;
+
+       if (dbg_reg_def[regno].offset != -1)
+               memcpy(mem, (void *)regs + dbg_reg_def[regno].offset,
+                      dbg_reg_def[regno].size);
+
+       switch (regno) {
+#ifdef CONFIG_X86_32
+       case GDB_SS:
+               if (!user_mode_vm(regs))
+                       *(unsigned long *)mem = __KERNEL_DS;
+               break;
+       case GDB_SP:
+               if (!user_mode_vm(regs))
+                       *(unsigned long *)mem = kernel_stack_pointer(regs);
+               break;
+       case GDB_GS:
+       case GDB_FS:
+               *(unsigned long *)mem = 0xFFFF;
+               break;
 #endif
+       }
+       return dbg_reg_def[regno].name;
 }
 
 /**
@@ -150,47 +189,6 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
        gdb_regs[GDB_SP]        = p->thread.sp;
 }
 
-/**
- *     gdb_regs_to_pt_regs - Convert GDB regs to ptrace regs.
- *     @gdb_regs: A pointer to hold the registers we've received from GDB.
- *     @regs: A pointer to a &struct pt_regs to hold these values in.
- *
- *     Convert the GDB regs in @gdb_regs into the pt_regs, and store them
- *     in @regs.
- */
-void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
-{
-#ifndef CONFIG_X86_32
-       u32 *gdb_regs32 = (u32 *)gdb_regs;
-#endif
-       regs->ax                = gdb_regs[GDB_AX];
-       regs->bx                = gdb_regs[GDB_BX];
-       regs->cx                = gdb_regs[GDB_CX];
-       regs->dx                = gdb_regs[GDB_DX];
-       regs->si                = gdb_regs[GDB_SI];
-       regs->di                = gdb_regs[GDB_DI];
-       regs->bp                = gdb_regs[GDB_BP];
-       regs->ip                = gdb_regs[GDB_PC];
-#ifdef CONFIG_X86_32
-       regs->flags             = gdb_regs[GDB_PS];
-       regs->ds                = gdb_regs[GDB_DS];
-       regs->es                = gdb_regs[GDB_ES];
-       regs->cs                = gdb_regs[GDB_CS];
-#else
-       regs->r8                = gdb_regs[GDB_R8];
-       regs->r9                = gdb_regs[GDB_R9];
-       regs->r10               = gdb_regs[GDB_R10];
-       regs->r11               = gdb_regs[GDB_R11];
-       regs->r12               = gdb_regs[GDB_R12];
-       regs->r13               = gdb_regs[GDB_R13];
-       regs->r14               = gdb_regs[GDB_R14];
-       regs->r15               = gdb_regs[GDB_R15];
-       regs->flags             = gdb_regs32[GDB_PS];
-       regs->cs                = gdb_regs32[GDB_CS];
-       regs->ss                = gdb_regs32[GDB_SS];
-#endif
-}
-
 static struct hw_breakpoint {
        unsigned                enabled;
        unsigned long           addr;