From 433bb163d9aaba72e4f5a29cecec052ca199a47a Mon Sep 17 00:00:00 2001 From: elicn Date: Sat, 28 Sep 2024 22:11:01 +0300 Subject: [PATCH 1/5] Add read and write cases for i386 CR8 --- qemu/target/i386/cpu.h | 2 +- qemu/target/i386/unicorn.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/qemu/target/i386/cpu.h b/qemu/target/i386/cpu.h index b16ebd29..4ddb7a51 100644 --- a/qemu/target/i386/cpu.h +++ b/qemu/target/i386/cpu.h @@ -1397,7 +1397,7 @@ typedef struct CPUX86State { SegmentCache gdt; /* only base and limit are used */ SegmentCache idt; /* only base and limit are used */ - target_ulong cr[5]; /* NOTE: cr1 is unused */ + target_ulong cr[9]; /* NOTE: cr1, cr5-cr7 are not used */ int32_t a20_mask; BNDReg bnd_regs[4]; diff --git a/qemu/target/i386/unicorn.c b/qemu/target/i386/unicorn.c index ceddb55d..0172999b 100644 --- a/qemu/target/i386/unicorn.c +++ b/qemu/target/i386/unicorn.c @@ -594,6 +594,7 @@ uc_err reg_read(void *_env, int mode, unsigned int regid, void *value, case UC_X86_REG_CR2: case UC_X86_REG_CR3: case UC_X86_REG_CR4: + case UC_X86_REG_CR8: CHECK_REG_TYPE(int64_t); *(int64_t *)value = env->cr[regid - UC_X86_REG_CR0]; break; @@ -1402,6 +1403,9 @@ uc_err reg_write(void *_env, int mode, unsigned int regid, const void *value, case UC_X86_REG_CR4: CHECK_REG_TYPE(uint64_t); cpu_x86_update_cr4(env, *(uint32_t *)value); + goto write_cr64; + case UC_X86_REG_CR8: + CHECK_REG_TYPE(uint64_t); write_cr64: env->cr[regid - UC_X86_REG_CR0] = *(uint64_t *)value; break; From 6cb9bfe5c04e59ea7ae94f7c6a33a8109282361a Mon Sep 17 00:00:00 2001 From: elicn Date: Sat, 28 Sep 2024 22:11:54 +0300 Subject: [PATCH 2/5] Avoid updating CR3 when writing CR1 and CR2 --- qemu/target/i386/unicorn.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/qemu/target/i386/unicorn.c b/qemu/target/i386/unicorn.c index 0172999b..449da907 100644 --- a/qemu/target/i386/unicorn.c +++ b/qemu/target/i386/unicorn.c @@ -1156,6 +1156,8 @@ uc_err reg_write(void *_env, int mode, unsigned int regid, const void *value, goto write_cr; case UC_X86_REG_CR1: case UC_X86_REG_CR2: + CHECK_REG_TYPE(uint32_t); + goto write_cr; case UC_X86_REG_CR3: CHECK_REG_TYPE(uint32_t); cpu_x86_update_cr3(env, *(uint32_t *)value); @@ -1396,6 +1398,8 @@ uc_err reg_write(void *_env, int mode, unsigned int regid, const void *value, goto write_cr64; case UC_X86_REG_CR1: case UC_X86_REG_CR2: + CHECK_REG_TYPE(uint64_t); + goto write_cr64; case UC_X86_REG_CR3: CHECK_REG_TYPE(uint64_t); cpu_x86_update_cr3(env, *(uint32_t *)value); From e3675162ba22c343edf5ab6173f33f6758513a5e Mon Sep 17 00:00:00 2001 From: elicn Date: Sat, 28 Sep 2024 22:15:00 +0300 Subject: [PATCH 3/5] Add read and write support for i386 XMM16-31 --- qemu/target/i386/cpu.h | 10 +++++-- qemu/target/i386/unicorn.c | 60 +++++++++++++++++++++++++++++--------- 2 files changed, 53 insertions(+), 17 deletions(-) diff --git a/qemu/target/i386/cpu.h b/qemu/target/i386/cpu.h index 4ddb7a51..10d93b89 100644 --- a/qemu/target/i386/cpu.h +++ b/qemu/target/i386/cpu.h @@ -1432,11 +1432,15 @@ typedef struct CPUX86State { ZMMReg xmm_t0; MMXReg mmx_t0; - XMMReg ymmh_regs[CPU_NB_REGS]; + /* + * YMM is not supported by QEMU at all + * As of qemu 5.0.1, ymmh_regs is nowhere used. + */ + XMMReg ymmh_regs[CPU_NB_REGS]; /* currently not in use */ uint64_t opmask_regs[NB_OPMASK_REGS]; - YMMReg zmmh_regs[CPU_NB_REGS]; - ZMMReg hi16_zmm_regs[CPU_NB_REGS]; + YMMReg zmmh_regs[CPU_NB_REGS]; /* currently not in use */ + ZMMReg hi16_zmm_regs[CPU_NB_REGS]; /* currently not in use */ /* sysenter registers */ uint32_t sysenter_cs; diff --git a/qemu/target/i386/unicorn.c b/qemu/target/i386/unicorn.c index 449da907..6482a91f 100644 --- a/qemu/target/i386/unicorn.c +++ b/qemu/target/i386/unicorn.c @@ -285,9 +285,9 @@ uc_err reg_read(void *_env, int mode, unsigned int regid, void *value, case UC_X86_REG_XMM5: case UC_X86_REG_XMM6: case UC_X86_REG_XMM7: { - CHECK_REG_TYPE(float64[2]); - float64 *dst = (float64 *)value; - ZMMReg *reg = (ZMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; + CHECK_REG_TYPE(uint64_t[2]); + uint64_t *dst = (uint64_t *)value; + const ZMMReg* const reg = &env->xmm_regs[regid - UC_X86_REG_XMM0]; dst[0] = reg->ZMM_Q(0); dst[1] = reg->ZMM_Q(1); return ret; @@ -968,10 +968,26 @@ uc_err reg_read(void *_env, int mode, unsigned int regid, void *value, case UC_X86_REG_XMM12: case UC_X86_REG_XMM13: case UC_X86_REG_XMM14: - case UC_X86_REG_XMM15: { - CHECK_REG_TYPE(float64[2]); - float64 *dst = (float64 *)value; - ZMMReg *reg = (ZMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; + case UC_X86_REG_XMM15: + case UC_X86_REG_XMM16: + case UC_X86_REG_XMM17: + case UC_X86_REG_XMM18: + case UC_X86_REG_XMM19: + case UC_X86_REG_XMM20: + case UC_X86_REG_XMM21: + case UC_X86_REG_XMM22: + case UC_X86_REG_XMM23: + case UC_X86_REG_XMM24: + case UC_X86_REG_XMM25: + case UC_X86_REG_XMM26: + case UC_X86_REG_XMM27: + case UC_X86_REG_XMM28: + case UC_X86_REG_XMM29: + case UC_X86_REG_XMM30: + case UC_X86_REG_XMM31: { + CHECK_REG_TYPE(uint64_t[2]); + uint64_t *dst = (uint64_t *)value; + const ZMMReg* const reg = &env->xmm_regs[regid - UC_X86_REG_XMM0]; dst[0] = reg->ZMM_Q(0); dst[1] = reg->ZMM_Q(1); break; @@ -1046,9 +1062,9 @@ uc_err reg_write(void *_env, int mode, unsigned int regid, const void *value, case UC_X86_REG_XMM5: case UC_X86_REG_XMM6: case UC_X86_REG_XMM7: { - CHECK_REG_TYPE(float64[2]); - float64 *src = (float64 *)value; - ZMMReg *reg = (ZMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; + CHECK_REG_TYPE(uint64_t[2]); + const uint64_t *src = (const uint64_t *)value; + ZMMReg *reg = &env->xmm_regs[regid - UC_X86_REG_XMM0]; reg->ZMM_Q(0) = src[0]; reg->ZMM_Q(1) = src[1]; return ret; @@ -1794,10 +1810,26 @@ uc_err reg_write(void *_env, int mode, unsigned int regid, const void *value, case UC_X86_REG_XMM12: case UC_X86_REG_XMM13: case UC_X86_REG_XMM14: - case UC_X86_REG_XMM15: { - CHECK_REG_TYPE(float64[2]); - float64 *src = (float64 *)value; - ZMMReg *reg = (ZMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; + case UC_X86_REG_XMM15: + case UC_X86_REG_XMM16: + case UC_X86_REG_XMM17: + case UC_X86_REG_XMM18: + case UC_X86_REG_XMM19: + case UC_X86_REG_XMM20: + case UC_X86_REG_XMM21: + case UC_X86_REG_XMM22: + case UC_X86_REG_XMM23: + case UC_X86_REG_XMM24: + case UC_X86_REG_XMM25: + case UC_X86_REG_XMM26: + case UC_X86_REG_XMM27: + case UC_X86_REG_XMM28: + case UC_X86_REG_XMM29: + case UC_X86_REG_XMM30: + case UC_X86_REG_XMM31: { + CHECK_REG_TYPE(uint64_t[2]); + const uint64_t *src = (const uint64_t *)value; + ZMMReg *reg = &env->xmm_regs[regid - UC_X86_REG_XMM0]; reg->ZMM_Q(0) = src[0]; reg->ZMM_Q(1) = src[1]; break; From 5164dbd609748ce104ec1103caba0a680a25fc90 Mon Sep 17 00:00:00 2001 From: elicn Date: Sat, 28 Sep 2024 22:16:45 +0300 Subject: [PATCH 4/5] Add read and write support for i386 YMM8-31 --- qemu/target/i386/unicorn.c | 118 ++++++++++++++++++++++++++----------- 1 file changed, 82 insertions(+), 36 deletions(-) diff --git a/qemu/target/i386/unicorn.c b/qemu/target/i386/unicorn.c index 6482a91f..f5c5980c 100644 --- a/qemu/target/i386/unicorn.c +++ b/qemu/target/i386/unicorn.c @@ -311,23 +311,14 @@ uc_err reg_read(void *_env, int mode, unsigned int regid, void *value, case UC_X86_REG_YMM4: case UC_X86_REG_YMM5: case UC_X86_REG_YMM6: - case UC_X86_REG_YMM7: - case UC_X86_REG_YMM8: - case UC_X86_REG_YMM9: - case UC_X86_REG_YMM10: - case UC_X86_REG_YMM11: - case UC_X86_REG_YMM12: - case UC_X86_REG_YMM13: - case UC_X86_REG_YMM14: - case UC_X86_REG_YMM15: { - CHECK_REG_TYPE(float64[4]); - float64 *dst = (float64 *)value; - ZMMReg *lo_reg = (ZMMReg *)&env->xmm_regs[regid - UC_X86_REG_YMM0]; - XMMReg *hi_reg = &env->ymmh_regs[regid - UC_X86_REG_YMM0]; - dst[0] = lo_reg->ZMM_Q(0); - dst[1] = lo_reg->ZMM_Q(1); - dst[2] = hi_reg->_d[0]; - dst[3] = hi_reg->_d[1]; + case UC_X86_REG_YMM7: { + CHECK_REG_TYPE(uint64_t[4]); + uint64_t *dst = (uint64_t *)value; + const ZMMReg* const reg = &env->xmm_regs[regid - UC_X86_REG_YMM0]; + dst[0] = reg->ZMM_Q(0); + dst[1] = reg->ZMM_Q(1); + dst[2] = reg->ZMM_Q(2); + dst[3] = reg->ZMM_Q(3); return ret; } @@ -992,6 +983,39 @@ uc_err reg_read(void *_env, int mode, unsigned int regid, void *value, dst[1] = reg->ZMM_Q(1); break; } + case UC_X86_REG_YMM8: + case UC_X86_REG_YMM9: + case UC_X86_REG_YMM10: + case UC_X86_REG_YMM11: + case UC_X86_REG_YMM12: + case UC_X86_REG_YMM13: + case UC_X86_REG_YMM14: + case UC_X86_REG_YMM15: + case UC_X86_REG_YMM16: + case UC_X86_REG_YMM17: + case UC_X86_REG_YMM18: + case UC_X86_REG_YMM19: + case UC_X86_REG_YMM20: + case UC_X86_REG_YMM21: + case UC_X86_REG_YMM22: + case UC_X86_REG_YMM23: + case UC_X86_REG_YMM24: + case UC_X86_REG_YMM25: + case UC_X86_REG_YMM26: + case UC_X86_REG_YMM27: + case UC_X86_REG_YMM28: + case UC_X86_REG_YMM29: + case UC_X86_REG_YMM30: + case UC_X86_REG_YMM31: { + CHECK_REG_TYPE(uint64_t[4]); + uint64_t *dst = (uint64_t *)value; + const ZMMReg* const reg = &env->xmm_regs[regid - UC_X86_REG_YMM0]; + dst[0] = reg->ZMM_Q(0); + dst[1] = reg->ZMM_Q(1); + dst[2] = reg->ZMM_Q(2); + dst[3] = reg->ZMM_Q(3); + break; + } case UC_X86_REG_FS_BASE: CHECK_REG_TYPE(uint64_t); *(uint64_t *)value = (uint64_t)env->segs[R_FS].base; @@ -1088,25 +1112,14 @@ uc_err reg_write(void *_env, int mode, unsigned int regid, const void *value, case UC_X86_REG_YMM4: case UC_X86_REG_YMM5: case UC_X86_REG_YMM6: - case UC_X86_REG_YMM7: - case UC_X86_REG_YMM8: - case UC_X86_REG_YMM9: - case UC_X86_REG_YMM10: - case UC_X86_REG_YMM11: - case UC_X86_REG_YMM12: - case UC_X86_REG_YMM13: - case UC_X86_REG_YMM14: - case UC_X86_REG_YMM15: { - CHECK_REG_TYPE(float64[4]); - float64 *src = (float64 *)value; - ZMMReg *lo_reg = (ZMMReg *)&env->xmm_regs[regid - UC_X86_REG_YMM0]; - XMMReg *hi_reg = &env->ymmh_regs[regid - UC_X86_REG_YMM0]; - lo_reg->ZMM_Q(0) = src[0]; - lo_reg->ZMM_Q(1) = src[1]; - // YMM is not supported by QEMU at all - // As of qemu 5.0.1, ymmh_regs is nowhere used. - hi_reg->_d[0] = src[2]; - hi_reg->_d[1] = src[3]; + case UC_X86_REG_YMM7: { + CHECK_REG_TYPE(uint64_t[4]); + const uint64_t *src = (const uint64_t *)value; + ZMMReg *reg = &env->xmm_regs[regid - UC_X86_REG_YMM0]; + reg->ZMM_Q(0) = src[0]; + reg->ZMM_Q(1) = src[1]; + reg->ZMM_Q(2) = src[2]; + reg->ZMM_Q(3) = src[3]; return ret; } @@ -1834,6 +1847,39 @@ uc_err reg_write(void *_env, int mode, unsigned int regid, const void *value, reg->ZMM_Q(1) = src[1]; break; } + case UC_X86_REG_YMM8: + case UC_X86_REG_YMM9: + case UC_X86_REG_YMM10: + case UC_X86_REG_YMM11: + case UC_X86_REG_YMM12: + case UC_X86_REG_YMM13: + case UC_X86_REG_YMM14: + case UC_X86_REG_YMM15: + case UC_X86_REG_YMM16: + case UC_X86_REG_YMM17: + case UC_X86_REG_YMM18: + case UC_X86_REG_YMM19: + case UC_X86_REG_YMM20: + case UC_X86_REG_YMM21: + case UC_X86_REG_YMM22: + case UC_X86_REG_YMM23: + case UC_X86_REG_YMM24: + case UC_X86_REG_YMM25: + case UC_X86_REG_YMM26: + case UC_X86_REG_YMM27: + case UC_X86_REG_YMM28: + case UC_X86_REG_YMM29: + case UC_X86_REG_YMM30: + case UC_X86_REG_YMM31: { + CHECK_REG_TYPE(uint64_t[4]); + const uint64_t *src = (const uint64_t *)value; + ZMMReg *reg = &env->xmm_regs[regid - UC_X86_REG_YMM0]; + reg->ZMM_Q(0) = src[0]; + reg->ZMM_Q(1) = src[1]; + reg->ZMM_Q(2) = src[2]; + reg->ZMM_Q(3) = src[3]; + break; + } case UC_X86_REG_FS_BASE: CHECK_REG_TYPE(uint64_t); env->segs[R_FS].base = *(uint64_t *)value; From 9af1df6543dc6ea67fd36406e3a20602ee49fa11 Mon Sep 17 00:00:00 2001 From: elicn Date: Sat, 28 Sep 2024 22:17:06 +0300 Subject: [PATCH 5/5] Add read and write support for i386 ZMM0-31 --- qemu/target/i386/unicorn.c | 90 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/qemu/target/i386/unicorn.c b/qemu/target/i386/unicorn.c index f5c5980c..1a073f86 100644 --- a/qemu/target/i386/unicorn.c +++ b/qemu/target/i386/unicorn.c @@ -1016,6 +1016,51 @@ uc_err reg_read(void *_env, int mode, unsigned int regid, void *value, dst[3] = reg->ZMM_Q(3); break; } + case UC_X86_REG_ZMM0: + case UC_X86_REG_ZMM1: + case UC_X86_REG_ZMM2: + case UC_X86_REG_ZMM3: + case UC_X86_REG_ZMM4: + case UC_X86_REG_ZMM5: + case UC_X86_REG_ZMM6: + case UC_X86_REG_ZMM7: + case UC_X86_REG_ZMM8: + case UC_X86_REG_ZMM9: + case UC_X86_REG_ZMM10: + case UC_X86_REG_ZMM11: + case UC_X86_REG_ZMM12: + case UC_X86_REG_ZMM13: + case UC_X86_REG_ZMM14: + case UC_X86_REG_ZMM15: + case UC_X86_REG_ZMM16: + case UC_X86_REG_ZMM17: + case UC_X86_REG_ZMM18: + case UC_X86_REG_ZMM19: + case UC_X86_REG_ZMM20: + case UC_X86_REG_ZMM21: + case UC_X86_REG_ZMM22: + case UC_X86_REG_ZMM23: + case UC_X86_REG_ZMM24: + case UC_X86_REG_ZMM25: + case UC_X86_REG_ZMM26: + case UC_X86_REG_ZMM27: + case UC_X86_REG_ZMM28: + case UC_X86_REG_ZMM29: + case UC_X86_REG_ZMM30: + case UC_X86_REG_ZMM31: { + CHECK_REG_TYPE(uint64_t[8]); + uint64_t *dst = (uint64_t *)value; + const ZMMReg* const reg = &env->xmm_regs[regid - UC_X86_REG_ZMM0]; + dst[0] = reg->ZMM_Q(0); + dst[1] = reg->ZMM_Q(1); + dst[2] = reg->ZMM_Q(2); + dst[3] = reg->ZMM_Q(3); + dst[4] = reg->ZMM_Q(4); + dst[5] = reg->ZMM_Q(5); + dst[6] = reg->ZMM_Q(6); + dst[7] = reg->ZMM_Q(7); + break; + } case UC_X86_REG_FS_BASE: CHECK_REG_TYPE(uint64_t); *(uint64_t *)value = (uint64_t)env->segs[R_FS].base; @@ -1880,6 +1925,51 @@ uc_err reg_write(void *_env, int mode, unsigned int regid, const void *value, reg->ZMM_Q(3) = src[3]; break; } + case UC_X86_REG_ZMM0: + case UC_X86_REG_ZMM1: + case UC_X86_REG_ZMM2: + case UC_X86_REG_ZMM3: + case UC_X86_REG_ZMM4: + case UC_X86_REG_ZMM5: + case UC_X86_REG_ZMM6: + case UC_X86_REG_ZMM7: + case UC_X86_REG_ZMM8: + case UC_X86_REG_ZMM9: + case UC_X86_REG_ZMM10: + case UC_X86_REG_ZMM11: + case UC_X86_REG_ZMM12: + case UC_X86_REG_ZMM13: + case UC_X86_REG_ZMM14: + case UC_X86_REG_ZMM15: + case UC_X86_REG_ZMM16: + case UC_X86_REG_ZMM17: + case UC_X86_REG_ZMM18: + case UC_X86_REG_ZMM19: + case UC_X86_REG_ZMM20: + case UC_X86_REG_ZMM21: + case UC_X86_REG_ZMM22: + case UC_X86_REG_ZMM23: + case UC_X86_REG_ZMM24: + case UC_X86_REG_ZMM25: + case UC_X86_REG_ZMM26: + case UC_X86_REG_ZMM27: + case UC_X86_REG_ZMM28: + case UC_X86_REG_ZMM29: + case UC_X86_REG_ZMM30: + case UC_X86_REG_ZMM31: { + CHECK_REG_TYPE(uint64_t[8]); + const uint64_t *src = (const uint64_t *)value; + ZMMReg *reg = &env->xmm_regs[regid - UC_X86_REG_ZMM0]; + reg->ZMM_Q(0) = src[0]; + reg->ZMM_Q(1) = src[1]; + reg->ZMM_Q(2) = src[2]; + reg->ZMM_Q(3) = src[3]; + reg->ZMM_Q(4) = src[4]; + reg->ZMM_Q(5) = src[5]; + reg->ZMM_Q(6) = src[6]; + reg->ZMM_Q(7) = src[7]; + break; + } case UC_X86_REG_FS_BASE: CHECK_REG_TYPE(uint64_t); env->segs[R_FS].base = *(uint64_t *)value;