summary refs log tree commit diff stats
path: root/target/i386/gdbstub.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/i386/gdbstub.c')
-rw-r--r--target/i386/gdbstub.c193
1 files changed, 189 insertions, 4 deletions
diff --git a/target/i386/gdbstub.c b/target/i386/gdbstub.c
index 9b94ab852c..1221433bc7 100644
--- a/target/i386/gdbstub.c
+++ b/target/i386/gdbstub.c
@@ -32,18 +32,61 @@ static const int gpr_map[16] = {
 #endif
 static const int gpr_map32[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
 
+/*
+ * Keep these in sync with assignment to
+ * gdb_num_core_regs in target/i386/cpu.c
+ * and with the machine description
+ */
+
+/*
+ * SEG: 6 segments, plus fs_base, gs_base, kernel_gs_base
+ */
+
+/*
+ * general regs ----->  8 or 16
+ */
+#define IDX_NB_IP       1
+#define IDX_NB_FLAGS    1
+#define IDX_NB_SEG      (6 + 3)
+#define IDX_NB_CTL      6
+#define IDX_NB_FP       16
+/*
+ * fpu regs ----------> 8 or 16
+ */
+#define IDX_NB_MXCSR    1
+/*
+ *          total ----> 8+1+1+9+6+16+8+1=50 or 16+1+1+9+6+16+16+1=66
+ */
+
 #define IDX_IP_REG      CPU_NB_REGS
-#define IDX_FLAGS_REG   (IDX_IP_REG + 1)
-#define IDX_SEG_REGS    (IDX_FLAGS_REG + 1)
-#define IDX_FP_REGS     (IDX_SEG_REGS + 6)
-#define IDX_XMM_REGS    (IDX_FP_REGS + 16)
+#define IDX_FLAGS_REG   (IDX_IP_REG + IDX_NB_IP)
+#define IDX_SEG_REGS    (IDX_FLAGS_REG + IDX_NB_FLAGS)
+#define IDX_CTL_REGS    (IDX_SEG_REGS + IDX_NB_SEG)
+#define IDX_FP_REGS     (IDX_CTL_REGS + IDX_NB_CTL)
+#define IDX_XMM_REGS    (IDX_FP_REGS + IDX_NB_FP)
 #define IDX_MXCSR_REG   (IDX_XMM_REGS + CPU_NB_REGS)
 
+#define IDX_CTL_CR0_REG     (IDX_CTL_REGS + 0)
+#define IDX_CTL_CR2_REG     (IDX_CTL_REGS + 1)
+#define IDX_CTL_CR3_REG     (IDX_CTL_REGS + 2)
+#define IDX_CTL_CR4_REG     (IDX_CTL_REGS + 3)
+#define IDX_CTL_CR8_REG     (IDX_CTL_REGS + 4)
+#define IDX_CTL_EFER_REG    (IDX_CTL_REGS + 5)
+
+#ifdef TARGET_X86_64
+#define GDB_FORCE_64 1
+#else
+#define GDB_FORCE_64 0
+#endif
+
+
 int x86_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
     X86CPU *cpu = X86_CPU(cs);
     CPUX86State *env = &cpu->env;
 
+    uint64_t tpr;
+
     /* N.B. GDB can't deal with changes in registers or sizes in the middle
        of a session. So if we're in 32-bit mode on a 64-bit cpu, still act
        as if we're on a 64-bit cpu. */
@@ -105,6 +148,28 @@ int x86_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
         case IDX_SEG_REGS + 5:
             return gdb_get_reg32(mem_buf, env->segs[R_GS].selector);
 
+        case IDX_SEG_REGS + 6:
+            if ((env->hflags & HF_CS64_MASK) || GDB_FORCE_64) {
+                return gdb_get_reg64(mem_buf, env->segs[R_FS].base);
+            }
+            return gdb_get_reg32(mem_buf, env->segs[R_FS].base);
+
+        case IDX_SEG_REGS + 7:
+            if ((env->hflags & HF_CS64_MASK) || GDB_FORCE_64) {
+                return gdb_get_reg64(mem_buf, env->segs[R_GS].base);
+            }
+            return gdb_get_reg32(mem_buf, env->segs[R_GS].base);
+
+        case IDX_SEG_REGS + 8:
+#ifdef TARGET_X86_64
+            if ((env->hflags & HF_CS64_MASK) || GDB_FORCE_64) {
+                return gdb_get_reg64(mem_buf, env->kernelgsbase);
+            }
+            return gdb_get_reg32(mem_buf, env->kernelgsbase);
+#else
+            return gdb_get_reg32(mem_buf, 0);
+#endif
+
         case IDX_FP_REGS + 8:
             return gdb_get_reg32(mem_buf, env->fpuc);
         case IDX_FP_REGS + 9:
@@ -125,6 +190,47 @@ int x86_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
 
         case IDX_MXCSR_REG:
             return gdb_get_reg32(mem_buf, env->mxcsr);
+
+        case IDX_CTL_CR0_REG:
+            if ((env->hflags & HF_CS64_MASK) || GDB_FORCE_64) {
+                return gdb_get_reg64(mem_buf, env->cr[0]);
+            }
+            return gdb_get_reg32(mem_buf, env->cr[0]);
+
+        case IDX_CTL_CR2_REG:
+            if ((env->hflags & HF_CS64_MASK) || GDB_FORCE_64) {
+                return gdb_get_reg64(mem_buf, env->cr[2]);
+            }
+            return gdb_get_reg32(mem_buf, env->cr[2]);
+
+        case IDX_CTL_CR3_REG:
+            if ((env->hflags & HF_CS64_MASK) || GDB_FORCE_64) {
+                return gdb_get_reg64(mem_buf, env->cr[3]);
+            }
+            return gdb_get_reg32(mem_buf, env->cr[3]);
+
+        case IDX_CTL_CR4_REG:
+            if ((env->hflags & HF_CS64_MASK) || GDB_FORCE_64) {
+                return gdb_get_reg64(mem_buf, env->cr[4]);
+            }
+            return gdb_get_reg32(mem_buf, env->cr[4]);
+
+        case IDX_CTL_CR8_REG:
+#ifdef CONFIG_SOFTMMU
+            tpr = cpu_get_apic_tpr(cpu->apic_state);
+#else
+            tpr = 0;
+#endif
+            if ((env->hflags & HF_CS64_MASK) || GDB_FORCE_64) {
+                return gdb_get_reg64(mem_buf, tpr);
+            }
+            return gdb_get_reg32(mem_buf, tpr);
+
+        case IDX_CTL_EFER_REG:
+            if ((env->hflags & HF_CS64_MASK) || GDB_FORCE_64) {
+                return gdb_get_reg64(mem_buf, env->efer);
+            }
+            return gdb_get_reg32(mem_buf, env->efer);
         }
     }
     return 0;
@@ -229,6 +335,32 @@ int x86_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
         case IDX_SEG_REGS + 5:
             return x86_cpu_gdb_load_seg(cpu, R_GS, mem_buf);
 
+        case IDX_SEG_REGS + 6:
+            if (env->hflags & HF_CS64_MASK) {
+                env->segs[R_FS].base = ldq_p(mem_buf);
+                return 8;
+            }
+            env->segs[R_FS].base = ldl_p(mem_buf);
+            return 4;
+
+        case IDX_SEG_REGS + 7:
+            if (env->hflags & HF_CS64_MASK) {
+                env->segs[R_GS].base = ldq_p(mem_buf);
+                return 8;
+            }
+            env->segs[R_GS].base = ldl_p(mem_buf);
+            return 4;
+
+#ifdef TARGET_X86_64
+        case IDX_SEG_REGS + 8:
+            if (env->hflags & HF_CS64_MASK) {
+                env->kernelgsbase = ldq_p(mem_buf);
+                return 8;
+            }
+            env->kernelgsbase = ldl_p(mem_buf);
+            return 4;
+#endif
+
         case IDX_FP_REGS + 8:
             cpu_set_fpuc(env, ldl_p(mem_buf));
             return 4;
@@ -253,6 +385,59 @@ int x86_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
         case IDX_MXCSR_REG:
             cpu_set_mxcsr(env, ldl_p(mem_buf));
             return 4;
+
+        case IDX_CTL_CR0_REG:
+            if (env->hflags & HF_CS64_MASK) {
+                cpu_x86_update_cr0(env, ldq_p(mem_buf));
+                return 8;
+            }
+            cpu_x86_update_cr0(env, ldl_p(mem_buf));
+            return 4;
+
+        case IDX_CTL_CR2_REG:
+            if (env->hflags & HF_CS64_MASK) {
+                env->cr[2] = ldq_p(mem_buf);
+                return 8;
+            }
+            env->cr[2] = ldl_p(mem_buf);
+            return 4;
+
+        case IDX_CTL_CR3_REG:
+            if (env->hflags & HF_CS64_MASK) {
+                cpu_x86_update_cr3(env, ldq_p(mem_buf));
+                return 8;
+            }
+            cpu_x86_update_cr3(env, ldl_p(mem_buf));
+            return 4;
+
+        case IDX_CTL_CR4_REG:
+            if (env->hflags & HF_CS64_MASK) {
+                cpu_x86_update_cr4(env, ldq_p(mem_buf));
+                return 8;
+            }
+            cpu_x86_update_cr4(env, ldl_p(mem_buf));
+            return 4;
+
+        case IDX_CTL_CR8_REG:
+            if (env->hflags & HF_CS64_MASK) {
+#ifdef CONFIG_SOFTMMU
+                cpu_set_apic_tpr(cpu->apic_state, ldq_p(mem_buf));
+#endif
+                return 8;
+            }
+#ifdef CONFIG_SOFTMMU
+            cpu_set_apic_tpr(cpu->apic_state, ldl_p(mem_buf));
+#endif
+            return 4;
+
+        case IDX_CTL_EFER_REG:
+            if (env->hflags & HF_CS64_MASK) {
+                cpu_load_efer(env, ldq_p(mem_buf));
+                return 8;
+            }
+            cpu_load_efer(env, ldl_p(mem_buf));
+            return 4;
+
         }
     }
     /* Unrecognised register.  */