From nobody Tue Feb 10 06:07:38 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1544015399445857.3688331416612; Wed, 5 Dec 2018 05:09:59 -0800 (PST) Received: from localhost ([::1]:34134 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gUWw4-0004Qq-DA for importer@patchew.org; Wed, 05 Dec 2018 08:09:52 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34359) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gUWh5-0002lD-ST for qemu-devel@nongnu.org; Wed, 05 Dec 2018 07:54:25 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gUWh2-0006f2-MA for qemu-devel@nongnu.org; Wed, 05 Dec 2018 07:54:23 -0500 Received: from mail.ispras.ru ([83.149.199.45]:50544) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gUWh2-0006eU-3K for qemu-devel@nongnu.org; Wed, 05 Dec 2018 07:54:20 -0500 Received: from Misha-PC.lan02.inno (unknown [85.142.117.226]) by mail.ispras.ru (Postfix) with ESMTPSA id 43DCB540082; Wed, 5 Dec 2018 15:54:19 +0300 (MSK) From: Mikhail Abakumov To: qemu-devel@nongnu.org Date: Wed, 05 Dec 2018 15:54:17 +0300 Message-ID: <154401445762.8440.8972233788056583038.stgit@Misha-PC.lan02.inno> In-Reply-To: <154401431697.8440.845616703562380651.stgit@Misha-PC.lan02.inno> References: <154401431697.8440.845616703562380651.stgit@Misha-PC.lan02.inno> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 83.149.199.45 Subject: [Qemu-devel] [PATCH 2 24/39] windbg: [de]serialization cpu context X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: sw@weilnetz.de, lprosek@redhat.com, dovgaluk@ispras.ru, rkagan@virtuozzo.com, pbonzini@redhat.com, den@openvz.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Mikhail Abakumov Signed-off-by: Pavel Dovgalyuk --- target/i386/windbgstub.c | 374 ++++++++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 372 insertions(+), 2 deletions(-) diff --git a/target/i386/windbgstub.c b/target/i386/windbgstub.c index e2ed2b3105..7a091e1dee 100644 --- a/target/i386/windbgstub.c +++ b/target/i386/windbgstub.c @@ -280,7 +280,6 @@ static InitedAddr kdDebuggerDataBlock; static InitedAddr kdVersion; #endif /* TARGET_I386 */ =20 -__attribute__ ((unused)) /* unused yet */ static void windbg_set_dr(CPUState *cs, int index, target_ulong value) { X86CPU *cpu =3D X86_CPU(cs); @@ -300,7 +299,6 @@ static void windbg_set_dr(CPUState *cs, int index, targ= et_ulong value) } =20 /* copy from gdbstub.c */ -__attribute__ ((unused)) /* unused yet */ static void windbg_set_sr(CPUState *cs, int sreg, uint16_t selector) { X86CPU *cpu =3D X86_CPU(cs); @@ -403,6 +401,378 @@ static void windbg_set_sr(CPUState *cs, int sreg, uin= t16_t selector) CASE_FIELD(stct, field, field_size, block) #endif /* TARGET_I386 */ =20 +#define GEN_WINDBG_CONTEXT_RW(fun_name, is_read) = \ +static int fun_name(CPUState *cs, uint8_t *buf, int buf_size, = \ + int offset, int len) = \ +{ = \ + X86CPU *cpu =3D X86_CPU(cs); = \ + CPUX86State *env =3D &cpu->env; = \ + uint32_t ctx_flags =3D CPU_CONTEXT_ALL; = \ + uint32_t tmp32, i; = \ + uint32_t f_size =3D 0; = \ + = \ + if (len < 0 || len > buf_size) { = \ + WINDBG_ERROR("" #fun_name ": incorrect length %d", len); = \ + return 1; = \ + } = \ + = \ + if (offset < 0 || offset + len > sizeof(CPU_CONTEXT)) { = \ + WINDBG_ERROR("" #fun_name ": incorrect offset %d", offset); = \ + return 2; = \ + } = \ + = \ + len =3D MIN(len, sizeof(CPU_CONTEXT) - offset); = \ + = \ + while (offset < len) { = \ + switch (offset) { = \ + CASE_FIELD(CPU_CONTEXT, ContextFlags, f_size, { = \ + rwl_p(buf, ctx_flags, is_read); = \ + }); = \ + /* DEBUG REGISTERS */ = \ + CASE_FIELD(CPU_CONTEXT, Dr0, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_DEBUG_REGISTERS) { = \ + RW_DR(buf, cs, 0, is_read); = \ + } = \ + }); = \ + CASE_FIELD(CPU_CONTEXT, Dr1, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_DEBUG_REGISTERS) { = \ + RW_DR(buf, cs, 1, is_read); = \ + } = \ + }); = \ + CASE_FIELD(CPU_CONTEXT, Dr2, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_DEBUG_REGISTERS) { = \ + RW_DR(buf, cs, 2, is_read); = \ + } = \ + }); = \ + CASE_FIELD(CPU_CONTEXT, Dr3, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_DEBUG_REGISTERS) { = \ + RW_DR(buf, cs, 3, is_read); = \ + } = \ + }); = \ + CASE_FIELD(CPU_CONTEXT, Dr6, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_DEBUG_REGISTERS) { = \ + RW_DR(buf, cs, 6, is_read); = \ + } = \ + }); = \ + CASE_FIELD(CPU_CONTEXT, Dr7, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_DEBUG_REGISTERS) { = \ + RW_DR(buf, cs, 7, is_read); = \ + } = \ + }); = \ + /* SEGMENT REGISTERS */ = \ + CASE_FIELD(CPU_CONTEXT, SegCs, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_SEGMENTS) { = \ + RW_SR(buf, cs, R_CS, is_read); = \ + } = \ + }); = \ + CASE_FIELD(CPU_CONTEXT, SegDs, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_SEGMENTS) { = \ + RW_SR(buf, cs, R_DS, is_read); = \ + } = \ + }); = \ + CASE_FIELD(CPU_CONTEXT, SegEs, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_SEGMENTS) { = \ + RW_SR(buf, cs, R_ES, is_read); = \ + } = \ + }); = \ + CASE_FIELD(CPU_CONTEXT, SegFs, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_SEGMENTS) { = \ + RW_SR(buf, cs, R_FS, is_read); = \ + } = \ + }); = \ + CASE_FIELD(CPU_CONTEXT, SegGs, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_SEGMENTS) { = \ + RW_SR(buf, cs, R_GS, is_read); = \ + } = \ + }); = \ + CASE_FIELD(CPU_CONTEXT, SegSs, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_SEGMENTS) { = \ + RW_SR(buf, cs, R_SS, is_read); = \ + } = \ + }); = \ + /* INTEGER REGISTERS */ = \ + CASE_FIELD_X32_64(CPU_CONTEXT, Eax, Rax, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_INTEGER) { = \ + rwtul_p(buf, env->regs[R_EAX], is_read); = \ + } = \ + }); = \ + CASE_FIELD_X32_64(CPU_CONTEXT, Ecx, Rcx, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_INTEGER) { = \ + rwtul_p(buf, env->regs[R_ECX], is_read); = \ + } = \ + }); = \ + CASE_FIELD_X32_64(CPU_CONTEXT, Edx, Rdx, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_INTEGER) { = \ + rwtul_p(buf, env->regs[R_EDX], is_read); = \ + } = \ + }); = \ + CASE_FIELD_X32_64(CPU_CONTEXT, Ebx, Rbx, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_INTEGER) { = \ + rwtul_p(buf, env->regs[R_EBX], is_read); = \ + } = \ + }); = \ + CASE_FIELD_X32_64(CPU_CONTEXT, Esi, Rsi, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_INTEGER) { = \ + rwtul_p(buf, env->regs[R_ESI], is_read); = \ + } = \ + }); = \ + CASE_FIELD_X32_64(CPU_CONTEXT, Edi, Rdi, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_INTEGER) { = \ + rwtul_p(buf, env->regs[R_EDI], is_read); = \ + } = \ + }); = \ + CASE_FIELD_X64(CPU_CONTEXT, R8, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_INTEGER) { = \ + rwtul_p(buf, env->regs[8], is_read); = \ + } = \ + }); = \ + CASE_FIELD_X64(CPU_CONTEXT, R9, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_INTEGER) { = \ + rwtul_p(buf, env->regs[9], is_read); = \ + } = \ + }); = \ + CASE_FIELD_X64(CPU_CONTEXT, R10, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_INTEGER) { = \ + rwtul_p(buf, env->regs[10], is_read); = \ + } = \ + }); = \ + CASE_FIELD_X64(CPU_CONTEXT, R11, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_INTEGER) { = \ + rwtul_p(buf, env->regs[11], is_read); = \ + } = \ + }); = \ + CASE_FIELD_X64(CPU_CONTEXT, R12, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_INTEGER) { = \ + rwtul_p(buf, env->regs[12], is_read); = \ + } = \ + }); = \ + CASE_FIELD_X64(CPU_CONTEXT, R13, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_INTEGER) { = \ + rwtul_p(buf, env->regs[13], is_read); = \ + } = \ + }); = \ + CASE_FIELD_X64(CPU_CONTEXT, R14, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_INTEGER) { = \ + rwtul_p(buf, env->regs[14], is_read); = \ + } = \ + }); = \ + CASE_FIELD_X64(CPU_CONTEXT, R15, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_INTEGER) { = \ + rwtul_p(buf, env->regs[15], is_read); = \ + } = \ + }); = \ + /* CONTROL REGISTERS */ = \ + CASE_FIELD_X32_64(CPU_CONTEXT, Esp, Rsp, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_CONTROL) { = \ + rwtul_p(buf, env->regs[R_ESP], is_read); = \ + } = \ + }); = \ + CASE_FIELD_X32_64(CPU_CONTEXT, Ebp, Rbp, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_CONTROL) { = \ + rwtul_p(buf, env->regs[R_EBP], is_read); = \ + } = \ + }); = \ + CASE_FIELD_X32_64(CPU_CONTEXT, Eip, Rip, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_CONTROL) { = \ + rwtul_p(buf, env->eip, is_read); = \ + } = \ + }); = \ + CASE_FIELD(CPU_CONTEXT, EFlags, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_CONTROL) { = \ + rwl_p(buf, env->eflags, is_read); = \ + } = \ + }); = \ + /* FLOAT REGISTERS */ = \ + CASE_FIELD(CPU_CONTEXT, FloatSave.ControlWord, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_FLOATING_POINT) { = \ + if (is_read) { = \ + cpu_set_fpuc(env, TARGET_SAFE(ldl_p, lduw_p)(buf)); = \ + } else { = \ + TARGET_SAFE(stl_p, stw_p)(buf, env->fpuc); = \ + } = \ + } = \ + }); = \ + CASE_FIELD(CPU_CONTEXT, FloatSave.StatusWord, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_FLOATING_POINT) { = \ + if (is_read) { = \ + tmp32 =3D TARGET_SAFE(ldl_p, lduw_p)(buf); = \ + env->fpstt =3D (tmp32 >> 11) & 7; = \ + env->fpus =3D tmp32 & ~0x3800; = \ + } else { = \ + tmp32 =3D env->fpus & ~(7 << 11); = \ + tmp32 |=3D (env->fpstt & 7) << 11; = \ + TARGET_SAFE(stl_p, stw_p)(buf, tmp32); = \ + } = \ + } = \ + }); = \ + CASE_FIELD(CPU_CONTEXT, FloatSave.TagWord, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_FLOATING_POINT) { = \ + if (is_read) { = \ + tmp32 =3D TARGET_SAFE(ldl_p(buf), buf[0]); = \ + for (i =3D 0; i < 8; ++i) { = \ + env->fptags[i] =3D !((tmp32 >> i) & 1); = \ + } = \ + } else { = \ + tmp32 =3D 0; = \ + for (i =3D 0; i < 8; ++i) { = \ + tmp32 |=3D (!env->fptags[i]) << i; = \ + } = \ + TARGET_SAFE(stl_p, stb_p)(buf, tmp32); = \ + } = \ + } = \ + }); = \ + CASE_FIELD_X64(CPU_CONTEXT, FloatSave.Reserved1, f_size, {}); = \ + CASE_FIELD_X64(CPU_CONTEXT, FloatSave.ErrorOpcode, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_FLOATING_POINT) { = \ + rwuw_p(buf, env->fpop, is_read); = \ + } = \ + }); = \ + CASE_FIELD(CPU_CONTEXT, FloatSave.ErrorOffset, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_FLOATING_POINT) { = \ + if (is_read) { = \ + env->fpip &=3D ~0xffffffffL; = \ + env->fpip |=3D ldl_p(buf); = \ + } else { = \ + stl_p(buf, env->fpip & 0xffffffff); = \ + } = \ + } = \ + }); = \ + CASE_FIELD(CPU_CONTEXT, FloatSave.ErrorSelector, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_FLOATING_POINT) { = \ + if (is_read) { = \ + env->fpip &=3D 0xffffffffL; = \ + env->fpip |=3D ((uint64_t) ldl_p(buf)) << 32; = \ + } else { = \ + stl_p(buf, (env->fpip >> 32) & 0xffffffff); = \ + } = \ + } = \ + }); = \ + CASE_FIELD_X64(CPU_CONTEXT, FloatSave.Reserved2, f_size, {}); = \ + CASE_FIELD(CPU_CONTEXT, FloatSave.DataOffset, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_FLOATING_POINT) { = \ + if (is_read) { = \ + env->fpdp &=3D ~0xffffffffL; = \ + env->fpdp |=3D ldl_p(buf); = \ + } else { = \ + stl_p(buf, env->fpdp & 0xffffffff); = \ + } = \ + } = \ + }); = \ + CASE_FIELD(CPU_CONTEXT, FloatSave.DataSelector, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_FLOATING_POINT) { = \ + if (is_read) { = \ + env->fpdp &=3D 0xffffffffL; = \ + env->fpdp |=3D ((uint64_t) ldl_p(buf)) << 32; = \ + } else { = \ + stl_p(buf, (env->fpdp >> 32) & 0xffffffff); = \ + } = \ + } = \ + }); = \ + CASE_FIELD_X64(CPU_CONTEXT, FloatSave.Reserved3, f_size, {}); = \ + CASE_FIELD_X32(CPU_CONTEXT, FloatSave.Cr0NpxState, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_FLOATING_POINT) { = \ + rwl_p(buf, env->xcr0, is_read); = \ + } = \ + }); = \ + CASE_FIELD_X64(CPU_CONTEXT, FloatSave.MxCsr, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_FLOATING_POINT) { = \ + rwl_p(buf, env->mxcsr, is_read); = \ + } = \ + }); = \ + CASE_FIELD_X64(CPU_CONTEXT, FloatSave.MxCsr_Mask, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_FLOATING_POINT) { = \ + /* FIXME: this is unimplemented in qemu? */ = \ + /* rwl_p(buf, env->mxcsr_mask, is_read); */ = \ + } = \ + }); = \ + CASE_FIELD_X32_64(CPU_CONTEXT, FloatSave.RegisterArea, = \ + FloatSave.FloatRegisters, f_size, {= \ + if (ctx_flags & CPU_CONTEXT_FLOATING_POINT) { = \ + uint8_t *mem =3D buf; = \ + for (i =3D 0; i < 8; ++i, mem +=3D TARGET_SAFE(10, 16)) { = \ + floatx80 fl =3D env->fpregs[i].d; = \ + if (is_read) { = \ + fl.low =3D ldq_p(mem); = \ + fl.high =3D TARGET_SAFE(lduw_p, ldq_p)(mem + 8); = \ + } else { = \ + stq_p(mem, fl.low); = \ + TARGET_SAFE(stw_p, stq_p)(mem + 8, fl.high); = \ + } = \ + } = \ + } = \ + }); = \ + CASE_FIELD_X64(CPU_CONTEXT, FloatSave.XmmRegisters, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_FLOATING_POINT) { = \ + uint8_t *mem =3D buf; = \ + if (is_read) { = \ + for (i =3D 0; i < CPU_NB_REGS; ++i, mem +=3D 16) { = \ + env->xmm_regs[i].ZMM_Q(0) =3D ldl_p(mem); = \ + env->xmm_regs[i].ZMM_Q(1) =3D ldl_p(mem + 8); = \ + } = \ + } else { = \ + for (i =3D 0; i < CPU_NB_REGS; ++i, mem +=3D 16) { = \ + stq_p(mem, env->xmm_regs[i].ZMM_Q(0)); = \ + stq_p(mem + 8, env->xmm_regs[i].ZMM_Q(1)); = \ + } = \ + } = \ + } = \ + }); = \ + CASE_FIELD_X64(CPU_CONTEXT, FloatSave.Reserved4, f_size, {}); = \ + /* EXTENDED REGISTERS I386 */ = \ + CASE_FIELD_X32(CPU_CONTEXT, ExtendedRegisters, f_size, { = \ + if (ctx_flags & CPU_CONTEXT_EXTENDED_REGISTERS) { = \ + uint8_t *mem =3D buf + 160; = \ + if (is_read) { = \ + for (i =3D 0; i < CPU_NB_REGS; ++i, mem +=3D 16) { = \ + env->xmm_regs[i].ZMM_Q(0) =3D ldl_p(mem); = \ + env->xmm_regs[i].ZMM_Q(1) =3D ldl_p(mem + 8); = \ + } = \ + cpu_set_mxcsr(env, ldl_p(mem + 24)); = \ + } else { = \ + for (i =3D 0; i < CPU_NB_REGS; ++i, mem +=3D 16) { = \ + stq_p(mem, env->xmm_regs[i].ZMM_Q(0)); = \ + stq_p(mem + 8, env->xmm_regs[i].ZMM_Q(1)); = \ + } = \ + stl_p(mem + 24, env->mxcsr); = \ + } = \ + } = \ + }); = \ + /* UNKNOWN REGISTERS */ = \ + CASE_FIELD_X64(CPU_CONTEXT, P1Home, f_size, {}); = \ + CASE_FIELD_X64(CPU_CONTEXT, P2Home, f_size, {}); = \ + CASE_FIELD_X64(CPU_CONTEXT, P3Home, f_size, {}); = \ + CASE_FIELD_X64(CPU_CONTEXT, P4Home, f_size, {}); = \ + CASE_FIELD_X64(CPU_CONTEXT, P5Home, f_size, {}); = \ + CASE_FIELD_X64(CPU_CONTEXT, P6Home, f_size, {}); = \ + CASE_FIELD_X64(CPU_CONTEXT, MxCsr, f_size, { = \ + if (is_read) { = \ + cpu_set_mxcsr(env, ldl_p(buf)); = \ + } else { = \ + stl_p(buf, env->mxcsr); = \ + } = \ + }); = \ + CASE_FIELD_X64(CPU_CONTEXT, VectorRegister, f_size, {}); = \ + CASE_FIELD_X64(CPU_CONTEXT, VectorControl, f_size, {}); = \ + CASE_FIELD_X64(CPU_CONTEXT, DebugControl, f_size, {}); = \ + CASE_FIELD_X64(CPU_CONTEXT, LastBranchToRip, f_size, {}); = \ + CASE_FIELD_X64(CPU_CONTEXT, LastBranchFromRip, f_size, {}); = \ + CASE_FIELD_X64(CPU_CONTEXT, LastExceptionToRip, f_size, {}); = \ + CASE_FIELD_X64(CPU_CONTEXT, LastExceptionFromRip, f_size, {}); = \ + default: = \ + f_size =3D 1; = \ + } = \ + offset +=3D f_size; = \ + buf +=3D f_size; = \ + } = \ + return 0; = \ +} + +__attribute__ ((unused)) /* unused yet */ +GEN_WINDBG_CONTEXT_RW(windbg_read_context, false) + +__attribute__ ((unused)) /* unused yet */ +GEN_WINDBG_CONTEXT_RW(windbg_write_context, true) + static bool find_KPCR(CPUState *cs) { X86CPU *cpu =3D X86_CPU(cs);