diff options
Diffstat (limited to 'target/i386/gdbstub.c')
-rw-r--r-- | target/i386/gdbstub.c | 193 |
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. */ |