blob: cc5eceeb7ebbfc59b3dc9a724ed73101ee3741ae [file] [log] [blame]
Andreas Färberf20f9df2013-07-07 12:07:54 +02001/*
2 * x86 gdb server stub
3 *
4 * Copyright (c) 2003-2005 Fabrice Bellard
5 * Copyright (c) 2013 SUSE LINUX Products GmbH
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
Chetan Pantd9ff33a2020-10-23 12:28:01 +000010 * version 2.1 of the License, or (at your option) any later version.
Andreas Färberf20f9df2013-07-07 12:07:54 +020011 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 */
Peter Maydellb6a0aa02016-01-26 18:17:03 +000020#include "qemu/osdep.h"
Paolo Bonzini33c11872016-03-15 16:58:45 +010021#include "cpu.h"
Philippe Mathieu-Daudé8b4d80b2024-05-07 16:05:48 +020022#include "gdbstub/helpers.h"
Andreas Färberf20f9df2013-07-07 12:07:54 +020023
24#ifdef TARGET_X86_64
25static const int gpr_map[16] = {
26 R_EAX, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI, R_EBP, R_ESP,
27 8, 9, 10, 11, 12, 13, 14, 15
28};
29#else
30#define gpr_map gpr_map32
31#endif
32static const int gpr_map32[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
33
Doug Gale7b0f97b2019-01-24 00:34:57 -033034/*
35 * Keep these in sync with assignment to
36 * gdb_num_core_regs in target/i386/cpu.c
37 * and with the machine description
38 */
39
40/*
41 * SEG: 6 segments, plus fs_base, gs_base, kernel_gs_base
42 */
43
44/*
45 * general regs -----> 8 or 16
46 */
47#define IDX_NB_IP 1
48#define IDX_NB_FLAGS 1
49#define IDX_NB_SEG (6 + 3)
50#define IDX_NB_CTL 6
51#define IDX_NB_FP 16
52/*
53 * fpu regs ----------> 8 or 16
54 */
55#define IDX_NB_MXCSR 1
56/*
57 * total ----> 8+1+1+9+6+16+8+1=50 or 16+1+1+9+6+16+16+1=66
58 */
59
Andreas Färberf20f9df2013-07-07 12:07:54 +020060#define IDX_IP_REG CPU_NB_REGS
Doug Gale7b0f97b2019-01-24 00:34:57 -033061#define IDX_FLAGS_REG (IDX_IP_REG + IDX_NB_IP)
62#define IDX_SEG_REGS (IDX_FLAGS_REG + IDX_NB_FLAGS)
63#define IDX_CTL_REGS (IDX_SEG_REGS + IDX_NB_SEG)
64#define IDX_FP_REGS (IDX_CTL_REGS + IDX_NB_CTL)
65#define IDX_XMM_REGS (IDX_FP_REGS + IDX_NB_FP)
Andreas Färberf20f9df2013-07-07 12:07:54 +020066#define IDX_MXCSR_REG (IDX_XMM_REGS + CPU_NB_REGS)
67
Doug Gale7b0f97b2019-01-24 00:34:57 -033068#define IDX_CTL_CR0_REG (IDX_CTL_REGS + 0)
69#define IDX_CTL_CR2_REG (IDX_CTL_REGS + 1)
70#define IDX_CTL_CR3_REG (IDX_CTL_REGS + 2)
71#define IDX_CTL_CR4_REG (IDX_CTL_REGS + 3)
72#define IDX_CTL_CR8_REG (IDX_CTL_REGS + 4)
73#define IDX_CTL_EFER_REG (IDX_CTL_REGS + 5)
74
75#ifdef TARGET_X86_64
76#define GDB_FORCE_64 1
77#else
78#define GDB_FORCE_64 0
79#endif
80
Claudio Fontana4d81e282021-03-22 14:27:55 +010081static int gdb_read_reg_cs64(uint32_t hflags, GByteArray *buf, target_ulong val)
82{
83 if ((hflags & HF_CS64_MASK) || GDB_FORCE_64) {
84 return gdb_get_reg64(buf, val);
85 }
86 return gdb_get_reg32(buf, val);
87}
88
89static int gdb_write_reg_cs64(uint32_t hflags, uint8_t *buf, target_ulong *val)
90{
91 if (hflags & HF_CS64_MASK) {
92 *val = ldq_p(buf);
93 return 8;
94 }
95 *val = ldl_p(buf);
96 return 4;
97}
Doug Gale7b0f97b2019-01-24 00:34:57 -033098
Ilya Leoshkeviche7a44272024-09-12 11:28:22 +020099static int gdb_get_reg(CPUX86State *env, GByteArray *mem_buf, target_ulong val)
100{
101 if (TARGET_LONG_BITS == 64) {
102 if (env->hflags & HF_CS64_MASK) {
103 return gdb_get_reg64(mem_buf, val);
104 } else {
105 return gdb_get_reg64(mem_buf, val & 0xffffffffUL);
106 }
107 } else {
108 return gdb_get_reg32(mem_buf, val);
109 }
110}
111
Alex Bennéea010bdb2020-03-16 17:21:41 +0000112int x86_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
Andreas Färberf20f9df2013-07-07 12:07:54 +0200113{
Andreas Färber5b50e792013-06-29 04:18:45 +0200114 X86CPU *cpu = X86_CPU(cs);
115 CPUX86State *env = &cpu->env;
116
Doug Gale7b0f97b2019-01-24 00:34:57 -0330117 uint64_t tpr;
118
Doug Evanse3592bc2016-11-03 23:35:32 +0000119 /* N.B. GDB can't deal with changes in registers or sizes in the middle
120 of a session. So if we're in 32-bit mode on a 64-bit cpu, still act
121 as if we're on a 64-bit cpu. */
122
Andreas Färberf20f9df2013-07-07 12:07:54 +0200123 if (n < CPU_NB_REGS) {
Doug Evanse3592bc2016-11-03 23:35:32 +0000124 if (TARGET_LONG_BITS == 64) {
125 if (env->hflags & HF_CS64_MASK) {
126 return gdb_get_reg64(mem_buf, env->regs[gpr_map[n]]);
127 } else if (n < CPU_NB_REGS32) {
128 return gdb_get_reg64(mem_buf,
129 env->regs[gpr_map[n]] & 0xffffffffUL);
130 } else {
Alex Bennéeb7b87562020-03-16 17:21:40 +0000131 return gdb_get_regl(mem_buf, 0);
Doug Evanse3592bc2016-11-03 23:35:32 +0000132 }
133 } else {
Andreas Färber986a2992013-07-07 13:05:05 +0200134 return gdb_get_reg32(mem_buf, env->regs[gpr_map32[n]]);
Andreas Färberf20f9df2013-07-07 12:07:54 +0200135 }
136 } else if (n >= IDX_FP_REGS && n < IDX_FP_REGS + 8) {
TaiseiIto49be78c2022-12-19 13:04:12 +0900137 int st_index = n - IDX_FP_REGS;
138 int r_index = (st_index + env->fpstt) % 8;
139 floatx80 *fp = &env->fpregs[r_index].d;
Alex Bennéeb7b87562020-03-16 17:21:40 +0000140 int len = gdb_get_reg64(mem_buf, cpu_to_le64(fp->low));
Peter Xubbc40fe2020-04-14 21:06:25 +0100141 len += gdb_get_reg16(mem_buf, cpu_to_le16(fp->high));
Alex Bennéeb7b87562020-03-16 17:21:40 +0000142 return len;
Andreas Färberf20f9df2013-07-07 12:07:54 +0200143 } else if (n >= IDX_XMM_REGS && n < IDX_XMM_REGS + CPU_NB_REGS) {
144 n -= IDX_XMM_REGS;
Doug Evanse3592bc2016-11-03 23:35:32 +0000145 if (n < CPU_NB_REGS32 || TARGET_LONG_BITS == 64) {
Alex Bennéeb7b87562020-03-16 17:21:40 +0000146 return gdb_get_reg128(mem_buf,
Alex Bennéee618e1f2022-04-19 10:10:19 +0100147 env->xmm_regs[n].ZMM_Q(1),
148 env->xmm_regs[n].ZMM_Q(0));
Andreas Färberf20f9df2013-07-07 12:07:54 +0200149 }
150 } else {
151 switch (n) {
152 case IDX_IP_REG:
Ilya Leoshkeviche7a44272024-09-12 11:28:22 +0200153 return gdb_get_reg(env, mem_buf, env->eip);
Andreas Färberf20f9df2013-07-07 12:07:54 +0200154 case IDX_FLAGS_REG:
Andreas Färber986a2992013-07-07 13:05:05 +0200155 return gdb_get_reg32(mem_buf, env->eflags);
Andreas Färberf20f9df2013-07-07 12:07:54 +0200156
157 case IDX_SEG_REGS:
Andreas Färber986a2992013-07-07 13:05:05 +0200158 return gdb_get_reg32(mem_buf, env->segs[R_CS].selector);
Andreas Färberf20f9df2013-07-07 12:07:54 +0200159 case IDX_SEG_REGS + 1:
Andreas Färber986a2992013-07-07 13:05:05 +0200160 return gdb_get_reg32(mem_buf, env->segs[R_SS].selector);
Andreas Färberf20f9df2013-07-07 12:07:54 +0200161 case IDX_SEG_REGS + 2:
Andreas Färber986a2992013-07-07 13:05:05 +0200162 return gdb_get_reg32(mem_buf, env->segs[R_DS].selector);
Andreas Färberf20f9df2013-07-07 12:07:54 +0200163 case IDX_SEG_REGS + 3:
Andreas Färber986a2992013-07-07 13:05:05 +0200164 return gdb_get_reg32(mem_buf, env->segs[R_ES].selector);
Andreas Färberf20f9df2013-07-07 12:07:54 +0200165 case IDX_SEG_REGS + 4:
Andreas Färber986a2992013-07-07 13:05:05 +0200166 return gdb_get_reg32(mem_buf, env->segs[R_FS].selector);
Andreas Färberf20f9df2013-07-07 12:07:54 +0200167 case IDX_SEG_REGS + 5:
Andreas Färber986a2992013-07-07 13:05:05 +0200168 return gdb_get_reg32(mem_buf, env->segs[R_GS].selector);
Doug Gale7b0f97b2019-01-24 00:34:57 -0330169 case IDX_SEG_REGS + 6:
Claudio Fontana4d81e282021-03-22 14:27:55 +0100170 return gdb_read_reg_cs64(env->hflags, mem_buf, env->segs[R_FS].base);
Doug Gale7b0f97b2019-01-24 00:34:57 -0330171 case IDX_SEG_REGS + 7:
Claudio Fontana4d81e282021-03-22 14:27:55 +0100172 return gdb_read_reg_cs64(env->hflags, mem_buf, env->segs[R_GS].base);
Doug Gale7b0f97b2019-01-24 00:34:57 -0330173
174 case IDX_SEG_REGS + 8:
175#ifdef TARGET_X86_64
Claudio Fontana4d81e282021-03-22 14:27:55 +0100176 return gdb_read_reg_cs64(env->hflags, mem_buf, env->kernelgsbase);
Doug Gale7b0f97b2019-01-24 00:34:57 -0330177#else
178 return gdb_get_reg32(mem_buf, 0);
179#endif
180
Andreas Färberf20f9df2013-07-07 12:07:54 +0200181 case IDX_FP_REGS + 8:
Andreas Färber986a2992013-07-07 13:05:05 +0200182 return gdb_get_reg32(mem_buf, env->fpuc);
Andreas Färberf20f9df2013-07-07 12:07:54 +0200183 case IDX_FP_REGS + 9:
Andreas Färber986a2992013-07-07 13:05:05 +0200184 return gdb_get_reg32(mem_buf, (env->fpus & ~0x3800) |
185 (env->fpstt & 0x7) << 11);
Andreas Färberf20f9df2013-07-07 12:07:54 +0200186 case IDX_FP_REGS + 10:
Andreas Färber986a2992013-07-07 13:05:05 +0200187 return gdb_get_reg32(mem_buf, 0); /* ftag */
Andreas Färberf20f9df2013-07-07 12:07:54 +0200188 case IDX_FP_REGS + 11:
Andreas Färber986a2992013-07-07 13:05:05 +0200189 return gdb_get_reg32(mem_buf, 0); /* fiseg */
Andreas Färberf20f9df2013-07-07 12:07:54 +0200190 case IDX_FP_REGS + 12:
Andreas Färber986a2992013-07-07 13:05:05 +0200191 return gdb_get_reg32(mem_buf, 0); /* fioff */
Andreas Färberf20f9df2013-07-07 12:07:54 +0200192 case IDX_FP_REGS + 13:
Andreas Färber986a2992013-07-07 13:05:05 +0200193 return gdb_get_reg32(mem_buf, 0); /* foseg */
Andreas Färberf20f9df2013-07-07 12:07:54 +0200194 case IDX_FP_REGS + 14:
Andreas Färber986a2992013-07-07 13:05:05 +0200195 return gdb_get_reg32(mem_buf, 0); /* fooff */
Andreas Färberf20f9df2013-07-07 12:07:54 +0200196 case IDX_FP_REGS + 15:
Andreas Färber986a2992013-07-07 13:05:05 +0200197 return gdb_get_reg32(mem_buf, 0); /* fop */
Andreas Färberf20f9df2013-07-07 12:07:54 +0200198
199 case IDX_MXCSR_REG:
Joseph Myers418b0f92020-06-25 23:58:31 +0000200 update_mxcsr_from_sse_status(env);
Andreas Färber986a2992013-07-07 13:05:05 +0200201 return gdb_get_reg32(mem_buf, env->mxcsr);
Doug Gale7b0f97b2019-01-24 00:34:57 -0330202
203 case IDX_CTL_CR0_REG:
Claudio Fontana4d81e282021-03-22 14:27:55 +0100204 return gdb_read_reg_cs64(env->hflags, mem_buf, env->cr[0]);
Doug Gale7b0f97b2019-01-24 00:34:57 -0330205 case IDX_CTL_CR2_REG:
Claudio Fontana4d81e282021-03-22 14:27:55 +0100206 return gdb_read_reg_cs64(env->hflags, mem_buf, env->cr[2]);
Doug Gale7b0f97b2019-01-24 00:34:57 -0330207 case IDX_CTL_CR3_REG:
Claudio Fontana4d81e282021-03-22 14:27:55 +0100208 return gdb_read_reg_cs64(env->hflags, mem_buf, env->cr[3]);
Doug Gale7b0f97b2019-01-24 00:34:57 -0330209 case IDX_CTL_CR4_REG:
Claudio Fontana4d81e282021-03-22 14:27:55 +0100210 return gdb_read_reg_cs64(env->hflags, mem_buf, env->cr[4]);
Doug Gale7b0f97b2019-01-24 00:34:57 -0330211 case IDX_CTL_CR8_REG:
Claudio Fontana4d81e282021-03-22 14:27:55 +0100212#ifndef CONFIG_USER_ONLY
Doug Gale7b0f97b2019-01-24 00:34:57 -0330213 tpr = cpu_get_apic_tpr(cpu->apic_state);
214#else
215 tpr = 0;
216#endif
Claudio Fontana4d81e282021-03-22 14:27:55 +0100217 return gdb_read_reg_cs64(env->hflags, mem_buf, tpr);
Doug Gale7b0f97b2019-01-24 00:34:57 -0330218
219 case IDX_CTL_EFER_REG:
Claudio Fontana4d81e282021-03-22 14:27:55 +0100220 return gdb_read_reg_cs64(env->hflags, mem_buf, env->efer);
Andreas Färberf20f9df2013-07-07 12:07:54 +0200221 }
222 }
223 return 0;
224}
225
Philippe Mathieu-Daudéc117e5b2021-01-10 00:34:27 +0100226static int x86_cpu_gdb_load_seg(X86CPU *cpu, X86Seg sreg, uint8_t *mem_buf)
Andreas Färberf20f9df2013-07-07 12:07:54 +0200227{
Andreas Färber5b50e792013-06-29 04:18:45 +0200228 CPUX86State *env = &cpu->env;
Andreas Färberf20f9df2013-07-07 12:07:54 +0200229 uint16_t selector = ldl_p(mem_buf);
230
231 if (selector != env->segs[sreg].selector) {
232#if defined(CONFIG_USER_ONLY)
233 cpu_x86_load_seg(env, sreg, selector);
234#else
235 unsigned int limit, flags;
236 target_ulong base;
237
238 if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
Paolo Bonzinib98dbc92014-05-15 16:07:04 +0200239 int dpl = (env->eflags & VM_MASK) ? 3 : 0;
Andreas Färberf20f9df2013-07-07 12:07:54 +0200240 base = selector << 4;
241 limit = 0xffff;
Paolo Bonzinib98dbc92014-05-15 16:07:04 +0200242 flags = DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
243 DESC_A_MASK | (dpl << DESC_DPL_SHIFT);
Andreas Färberf20f9df2013-07-07 12:07:54 +0200244 } else {
245 if (!cpu_x86_get_descr_debug(env, selector, &base, &limit,
246 &flags)) {
247 return 4;
248 }
249 }
250 cpu_x86_load_seg_cache(env, sreg, selector, base, limit, flags);
251#endif
252 }
253 return 4;
254}
255
Ilya Leoshkeviche7a44272024-09-12 11:28:22 +0200256static int gdb_write_reg(CPUX86State *env, uint8_t *mem_buf, target_ulong *val)
257{
258 if (TARGET_LONG_BITS == 64) {
259 if (env->hflags & HF_CS64_MASK) {
260 *val = ldq_p(mem_buf);
261 } else {
262 *val = ldq_p(mem_buf) & 0xffffffffUL;
263 }
264 return 8;
265 } else {
266 *val = (uint32_t)ldl_p(mem_buf);
267 return 4;
268 }
269}
270
Andreas Färber5b50e792013-06-29 04:18:45 +0200271int x86_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
Andreas Färberf20f9df2013-07-07 12:07:54 +0200272{
Andreas Färber5b50e792013-06-29 04:18:45 +0200273 X86CPU *cpu = X86_CPU(cs);
274 CPUX86State *env = &cpu->env;
Claudio Fontana4d81e282021-03-22 14:27:55 +0100275 target_ulong tmp;
276 int len;
Andreas Färberf20f9df2013-07-07 12:07:54 +0200277
Doug Evanse3592bc2016-11-03 23:35:32 +0000278 /* N.B. GDB can't deal with changes in registers or sizes in the middle
279 of a session. So if we're in 32-bit mode on a 64-bit cpu, still act
280 as if we're on a 64-bit cpu. */
281
Andreas Färberf20f9df2013-07-07 12:07:54 +0200282 if (n < CPU_NB_REGS) {
Doug Evanse3592bc2016-11-03 23:35:32 +0000283 if (TARGET_LONG_BITS == 64) {
284 if (env->hflags & HF_CS64_MASK) {
285 env->regs[gpr_map[n]] = ldtul_p(mem_buf);
286 } else if (n < CPU_NB_REGS32) {
287 env->regs[gpr_map[n]] = ldtul_p(mem_buf) & 0xffffffffUL;
288 }
Andreas Färberf20f9df2013-07-07 12:07:54 +0200289 return sizeof(target_ulong);
290 } else if (n < CPU_NB_REGS32) {
291 n = gpr_map32[n];
292 env->regs[n] &= ~0xffffffffUL;
293 env->regs[n] |= (uint32_t)ldl_p(mem_buf);
294 return 4;
295 }
296 } else if (n >= IDX_FP_REGS && n < IDX_FP_REGS + 8) {
Alex Bennéeb7b87562020-03-16 17:21:40 +0000297 floatx80 *fp = (floatx80 *) &env->fpregs[n - IDX_FP_REGS];
298 fp->low = le64_to_cpu(* (uint64_t *) mem_buf);
299 fp->high = le16_to_cpu(* (uint16_t *) (mem_buf + 8));
Andreas Färberf20f9df2013-07-07 12:07:54 +0200300 return 10;
301 } else if (n >= IDX_XMM_REGS && n < IDX_XMM_REGS + CPU_NB_REGS) {
302 n -= IDX_XMM_REGS;
Doug Evanse3592bc2016-11-03 23:35:32 +0000303 if (n < CPU_NB_REGS32 || TARGET_LONG_BITS == 64) {
Eduardo Habkost19cbd872015-11-26 17:14:32 -0200304 env->xmm_regs[n].ZMM_Q(0) = ldq_p(mem_buf);
305 env->xmm_regs[n].ZMM_Q(1) = ldq_p(mem_buf + 8);
Andreas Färberf20f9df2013-07-07 12:07:54 +0200306 return 16;
307 }
308 } else {
309 switch (n) {
310 case IDX_IP_REG:
Ilya Leoshkeviche7a44272024-09-12 11:28:22 +0200311 return gdb_write_reg(env, mem_buf, &env->eip);
Andreas Färberf20f9df2013-07-07 12:07:54 +0200312 case IDX_FLAGS_REG:
313 env->eflags = ldl_p(mem_buf);
314 return 4;
315
316 case IDX_SEG_REGS:
Andreas Färber5b50e792013-06-29 04:18:45 +0200317 return x86_cpu_gdb_load_seg(cpu, R_CS, mem_buf);
Andreas Färberf20f9df2013-07-07 12:07:54 +0200318 case IDX_SEG_REGS + 1:
Andreas Färber5b50e792013-06-29 04:18:45 +0200319 return x86_cpu_gdb_load_seg(cpu, R_SS, mem_buf);
Andreas Färberf20f9df2013-07-07 12:07:54 +0200320 case IDX_SEG_REGS + 2:
Andreas Färber5b50e792013-06-29 04:18:45 +0200321 return x86_cpu_gdb_load_seg(cpu, R_DS, mem_buf);
Andreas Färberf20f9df2013-07-07 12:07:54 +0200322 case IDX_SEG_REGS + 3:
Andreas Färber5b50e792013-06-29 04:18:45 +0200323 return x86_cpu_gdb_load_seg(cpu, R_ES, mem_buf);
Andreas Färberf20f9df2013-07-07 12:07:54 +0200324 case IDX_SEG_REGS + 4:
Andreas Färber5b50e792013-06-29 04:18:45 +0200325 return x86_cpu_gdb_load_seg(cpu, R_FS, mem_buf);
Andreas Färberf20f9df2013-07-07 12:07:54 +0200326 case IDX_SEG_REGS + 5:
Andreas Färber5b50e792013-06-29 04:18:45 +0200327 return x86_cpu_gdb_load_seg(cpu, R_GS, mem_buf);
Doug Gale7b0f97b2019-01-24 00:34:57 -0330328 case IDX_SEG_REGS + 6:
Claudio Fontana4d81e282021-03-22 14:27:55 +0100329 return gdb_write_reg_cs64(env->hflags, mem_buf, &env->segs[R_FS].base);
Doug Gale7b0f97b2019-01-24 00:34:57 -0330330 case IDX_SEG_REGS + 7:
Claudio Fontana4d81e282021-03-22 14:27:55 +0100331 return gdb_write_reg_cs64(env->hflags, mem_buf, &env->segs[R_GS].base);
Doug Gale7b0f97b2019-01-24 00:34:57 -0330332 case IDX_SEG_REGS + 8:
mkdolata@us.ibm.com5a071922020-01-07 14:26:07 +0100333#ifdef TARGET_X86_64
Claudio Fontana4d81e282021-03-22 14:27:55 +0100334 return gdb_write_reg_cs64(env->hflags, mem_buf, &env->kernelgsbase);
Doug Gale7b0f97b2019-01-24 00:34:57 -0330335#endif
mkdolata@us.ibm.com5a071922020-01-07 14:26:07 +0100336 return 4;
Doug Gale7b0f97b2019-01-24 00:34:57 -0330337
Andreas Färberf20f9df2013-07-07 12:07:54 +0200338 case IDX_FP_REGS + 8:
Pavel Dovgalyuk5bde1402014-09-17 12:05:19 +0400339 cpu_set_fpuc(env, ldl_p(mem_buf));
Andreas Färberf20f9df2013-07-07 12:07:54 +0200340 return 4;
341 case IDX_FP_REGS + 9:
342 tmp = ldl_p(mem_buf);
343 env->fpstt = (tmp >> 11) & 7;
344 env->fpus = tmp & ~0x3800;
345 return 4;
346 case IDX_FP_REGS + 10: /* ftag */
347 return 4;
348 case IDX_FP_REGS + 11: /* fiseg */
349 return 4;
350 case IDX_FP_REGS + 12: /* fioff */
351 return 4;
352 case IDX_FP_REGS + 13: /* foseg */
353 return 4;
354 case IDX_FP_REGS + 14: /* fooff */
355 return 4;
356 case IDX_FP_REGS + 15: /* fop */
357 return 4;
358
359 case IDX_MXCSR_REG:
Richard Henderson4e47e392014-02-24 14:59:54 -0800360 cpu_set_mxcsr(env, ldl_p(mem_buf));
Andreas Färberf20f9df2013-07-07 12:07:54 +0200361 return 4;
Doug Gale7b0f97b2019-01-24 00:34:57 -0330362
363 case IDX_CTL_CR0_REG:
Claudio Fontana4d81e282021-03-22 14:27:55 +0100364 len = gdb_write_reg_cs64(env->hflags, mem_buf, &tmp);
Claudio Fontana1852f092021-03-22 14:27:56 +0100365#ifndef CONFIG_USER_ONLY
Claudio Fontana4d81e282021-03-22 14:27:55 +0100366 cpu_x86_update_cr0(env, tmp);
Claudio Fontana1852f092021-03-22 14:27:56 +0100367#endif
Claudio Fontana4d81e282021-03-22 14:27:55 +0100368 return len;
Doug Gale7b0f97b2019-01-24 00:34:57 -0330369
370 case IDX_CTL_CR2_REG:
Claudio Fontana4d81e282021-03-22 14:27:55 +0100371 len = gdb_write_reg_cs64(env->hflags, mem_buf, &tmp);
Claudio Fontana1852f092021-03-22 14:27:56 +0100372#ifndef CONFIG_USER_ONLY
Claudio Fontana4d81e282021-03-22 14:27:55 +0100373 env->cr[2] = tmp;
Claudio Fontana1852f092021-03-22 14:27:56 +0100374#endif
Claudio Fontana4d81e282021-03-22 14:27:55 +0100375 return len;
Doug Gale7b0f97b2019-01-24 00:34:57 -0330376
377 case IDX_CTL_CR3_REG:
Claudio Fontana4d81e282021-03-22 14:27:55 +0100378 len = gdb_write_reg_cs64(env->hflags, mem_buf, &tmp);
Claudio Fontana1852f092021-03-22 14:27:56 +0100379#ifndef CONFIG_USER_ONLY
Claudio Fontana4d81e282021-03-22 14:27:55 +0100380 cpu_x86_update_cr3(env, tmp);
Claudio Fontana1852f092021-03-22 14:27:56 +0100381#endif
Claudio Fontana4d81e282021-03-22 14:27:55 +0100382 return len;
Doug Gale7b0f97b2019-01-24 00:34:57 -0330383
384 case IDX_CTL_CR4_REG:
Claudio Fontana4d81e282021-03-22 14:27:55 +0100385 len = gdb_write_reg_cs64(env->hflags, mem_buf, &tmp);
Claudio Fontana1852f092021-03-22 14:27:56 +0100386#ifndef CONFIG_USER_ONLY
Claudio Fontana4d81e282021-03-22 14:27:55 +0100387 cpu_x86_update_cr4(env, tmp);
Claudio Fontana1852f092021-03-22 14:27:56 +0100388#endif
Claudio Fontana4d81e282021-03-22 14:27:55 +0100389 return len;
Doug Gale7b0f97b2019-01-24 00:34:57 -0330390
391 case IDX_CTL_CR8_REG:
Claudio Fontana4d81e282021-03-22 14:27:55 +0100392 len = gdb_write_reg_cs64(env->hflags, mem_buf, &tmp);
393#ifndef CONFIG_USER_ONLY
394 cpu_set_apic_tpr(cpu->apic_state, tmp);
Doug Gale7b0f97b2019-01-24 00:34:57 -0330395#endif
Claudio Fontana4d81e282021-03-22 14:27:55 +0100396 return len;
Doug Gale7b0f97b2019-01-24 00:34:57 -0330397
398 case IDX_CTL_EFER_REG:
Claudio Fontana4d81e282021-03-22 14:27:55 +0100399 len = gdb_write_reg_cs64(env->hflags, mem_buf, &tmp);
Claudio Fontana1852f092021-03-22 14:27:56 +0100400#ifndef CONFIG_USER_ONLY
Claudio Fontana4d81e282021-03-22 14:27:55 +0100401 cpu_load_efer(env, tmp);
Claudio Fontana1852f092021-03-22 14:27:56 +0100402#endif
Claudio Fontana4d81e282021-03-22 14:27:55 +0100403 return len;
Andreas Färberf20f9df2013-07-07 12:07:54 +0200404 }
405 }
406 /* Unrecognised register. */
407 return 0;
408}