ping
https://lore.kernel.org/qemu-devel/[email protected]/T/#u

пн, 8 июн. 2026 г., 19:19 Andrey Polivoda <[email protected]>:

> Intel and AMD CPUs implement SYSRETQ instruction differently.
> One of these differences is whether a canonicality check of the address
> that
> will be loaded to RIP is performed: Intel CPUs do this check, AMD CPUs
> don't.
>
> Currently, QEMU does not perform this check when emulating Intel CPUs.
> This patch corrects this by implementing the canonlicality check on a new
> RIP
> value from RCX and performing it only when emulating Intel CPUs.
>
> Flags and segment registers' caches are updated only after checking the
> new RIP
> value to ensure that CPU state is not modified in case the #GP(0) exception
> is raised due to the check failure.
>
> Cc: [email protected]
> Cc: Paolo Bonzini <[email protected]>
> Cc: Richard Henderson <[email protected]>
> Fixes: 14ce26e75513 ("x86_64 target support")
> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3223
> Signed-off-by: Andrey Polivoda <[email protected]>
> ---
>  target/i386/tcg/seg_helper.c | 17 +++++++++++++----
>  1 file changed, 13 insertions(+), 4 deletions(-)
>
> diff --git a/target/i386/tcg/seg_helper.c b/target/i386/tcg/seg_helper.c
> index 58aac72011..d5c174b7fd 100644
> --- a/target/i386/tcg/seg_helper.c
> +++ b/target/i386/tcg/seg_helper.c
> @@ -1096,17 +1096,22 @@ void helper_sysret(CPUX86State *env, int dflag)
>      selector = (env->star >> 48) & 0xffff;
>  #ifdef TARGET_X86_64
>      if (env->hflags & HF_LMA_MASK) {
> -        cpu_load_eflags(env, (uint32_t)(env->regs[11]), TF_MASK | AC_MASK
> -                        | ID_MASK | IF_MASK | IOPL_MASK | VM_MASK |
> RF_MASK |
> -                        NT_MASK);
>          if (dflag == 2) {
> +            uint64_t new_rip = env->regs[R_ECX];
> +            if (IS_INTEL_CPU(env)) {
> +                int shift = (get_pg_mode(env) & PG_MODE_LA57) ? 56 : 47;
> +                int64_t sext = (int64_t)new_rip >> shift;
> +                if (sext != 0 && sext != -1) {
> +                    raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
> +                }
> +            }
>              cpu_x86_load_seg_cache(env, R_CS, (selector + 16) | 3,
>                                     0, 0xffffffff,
>                                     DESC_G_MASK | DESC_P_MASK |
>                                     DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
>                                     DESC_CS_MASK | DESC_R_MASK |
> DESC_A_MASK |
>                                     DESC_L_MASK);
> -            env->eip = env->regs[R_ECX];
> +            env->eip = new_rip;
>          } else {
>              cpu_x86_load_seg_cache(env, R_CS, selector | 3,
>                                     0, 0xffffffff,
> @@ -1120,6 +1125,10 @@ void helper_sysret(CPUX86State *env, int dflag)
>                                 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
>                                 DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
>                                 DESC_W_MASK | DESC_A_MASK);
> +
> +        cpu_load_eflags(env, (uint32_t)(env->regs[11]), TF_MASK | AC_MASK
> +                        | ID_MASK | IF_MASK | IOPL_MASK | VM_MASK |
> RF_MASK |
> +                        NT_MASK);
>      } else
>  #endif
>      {
> --
> 2.53.0
>
>

Reply via email to