qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH 4/4] TCG x86: add RDTSCP support


From: Aurelien Jarno
Subject: Re: [Qemu-devel] [PATCH 4/4] TCG x86: add RDTSCP support
Date: Sun, 4 Oct 2009 14:47:22 +0200
User-agent: Mutt/1.5.18 (2008-05-17)

On Sat, Sep 19, 2009 at 12:30:49AM +0200, Andre Przywara wrote:
> RDTSCP reads the time stamp counter and atomically also the content
> of a 32-bit MSR, which can be freely set by the OS. This allows CPU
> local data to be queried by userspace.
> Linux uses this to allow a fast implementation of the getcpu()
> syscall, which uses the vsyscall page to avoid a context switch.
> AMD CPUs since K8RevF and Intel CPUs since Nehalem support this
> instruction.
> RDTSCP is guarded by the RDTSCP CPUID bit (Fn8000_0001:EDX[27]).

Thanks, applied.

> Signed-off-by: Andre Przywara <address@hidden>
> ---
>  target-i386/cpu.h       |    5 +++-
>  target-i386/helper.h    |    1 +
>  target-i386/machine.c   |    4 +++
>  target-i386/op_helper.c |   12 ++++++++++
>  target-i386/translate.c |   57 ++++++++++++++++++++++++++++++++++------------
>  5 files changed, 63 insertions(+), 16 deletions(-)
> 
> diff --git a/target-i386/cpu.h b/target-i386/cpu.h
> index b9a6392..f318942 100644
> --- a/target-i386/cpu.h
> +++ b/target-i386/cpu.h
> @@ -322,6 +322,7 @@
>  #define MSR_FSBASE                      0xc0000100
>  #define MSR_GSBASE                      0xc0000101
>  #define MSR_KERNELGSBASE                0xc0000102
> +#define MSR_TSC_AUX                     0xc0000103
>  
>  #define MSR_VM_HSAVE_PA                 0xc0010117
>  
> @@ -694,6 +695,8 @@ typedef struct CPUX86State {
>      uint64 mcg_status;
>      uint64 mcg_ctl;
>      uint64 *mce_banks;
> +
> +    uint64_t tsc_aux;
>  } CPUX86State;
>  
>  CPUX86State *cpu_x86_init(const char *cpu_model);
> @@ -854,7 +857,7 @@ uint64_t cpu_get_tsc(CPUX86State *env);
>  #define cpu_signal_handler cpu_x86_signal_handler
>  #define cpu_list x86_cpu_list
>  
> -#define CPU_SAVE_VERSION 10
> +#define CPU_SAVE_VERSION 11
>  
>  /* MMU modes definitions */
>  #define MMU_MODE0_SUFFIX _kernel
> diff --git a/target-i386/helper.h b/target-i386/helper.h
> index 38d0708..ef8d4e1 100644
> --- a/target-i386/helper.h
> +++ b/target-i386/helper.h
> @@ -80,6 +80,7 @@ DEF_HELPER_1(cmpxchg16b, void, tl)
>  DEF_HELPER_0(single_step, void)
>  DEF_HELPER_0(cpuid, void)
>  DEF_HELPER_0(rdtsc, void)
> +DEF_HELPER_0(rdtscp, void)
>  DEF_HELPER_0(rdpmc, void)
>  DEF_HELPER_0(rdmsr, void)
>  DEF_HELPER_0(wrmsr, void)
> diff --git a/target-i386/machine.c b/target-i386/machine.c
> index ab31329..e5a060f 100644
> --- a/target-i386/machine.c
> +++ b/target-i386/machine.c
> @@ -171,6 +171,7 @@ void cpu_save(QEMUFile *f, void *opaque)
>              qemu_put_be64s(f, &env->mce_banks[4*i + 3]);
>          }
>      }
> +    qemu_put_be64s(f, &env->tsc_aux);
>   }
>  
>  #ifdef USE_X86LDOUBLE
> @@ -377,6 +378,9 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
>          }
>      }
>  
> +    if (version_id >= 11) {
> +        qemu_get_be64s(f, &env->tsc_aux);
> +    }
>      /* XXX: ensure compatiblity for halted bit ? */
>      /* XXX: compute redundant hflags bits */
>      env->hflags = hflags;
> diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
> index 9ffda36..a457bdd 100644
> --- a/target-i386/op_helper.c
> +++ b/target-i386/op_helper.c
> @@ -2969,6 +2969,12 @@ void helper_rdtsc(void)
>      EDX = (uint32_t)(val >> 32);
>  }
>  
> +void helper_rdtscp(void)
> +{
> +    helper_rdtsc();
> +    ECX = (uint32_t)(env->tsc_aux);
> +}
> +
>  void helper_rdpmc(void)
>  {
>      if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
> @@ -3107,6 +3113,9 @@ void helper_wrmsr(void)
>              && (val == 0 || val == ~(uint64_t)0))
>              env->mcg_ctl = val;
>          break;
> +    case MSR_TSC_AUX:
> +        env->tsc_aux = val;
> +        break;
>      default:
>          if ((uint32_t)ECX >= MSR_MC0_CTL
>              && (uint32_t)ECX < MSR_MC0_CTL + (4 * env->mcg_cap & 0xff)) {
> @@ -3177,6 +3186,9 @@ void helper_rdmsr(void)
>      case MSR_KERNELGSBASE:
>          val = env->kernelgsbase;
>          break;
> +    case MSR_TSC_AUX:
> +        val = env->tsc_aux;
> +        break;
>  #endif
>      case MSR_MTRRphysBase(0):
>      case MSR_MTRRphysBase(1):
> diff --git a/target-i386/translate.c b/target-i386/translate.c
> index 5cbcf07..306685d 100644
> --- a/target-i386/translate.c
> +++ b/target-i386/translate.c
> @@ -7217,31 +7217,58 @@ static target_ulong disas_insn(DisasContext *s, 
> target_ulong pc_start)
>                  gen_eob(s);
>              }
>              break;
> -        case 7: /* invlpg */
> -            if (s->cpl != 0) {
> -                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
> +        case 7:
> +            if (mod != 3) { /* invlpg */
> +                if (s->cpl != 0) {
> +                    gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
> +                } else {
> +                    if (s->cc_op != CC_OP_DYNAMIC)
> +                        gen_op_set_cc_op(s->cc_op);
> +                    gen_jmp_im(pc_start - s->cs_base);
> +                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
> +                    gen_helper_invlpg(cpu_A0);
> +                    gen_jmp_im(s->pc - s->cs_base);
> +                    gen_eob(s);
> +                }
>              } else {
> -                if (mod == 3) {
> +                switch (rm) {
> +                case 0: /* swapgs */
>  #ifdef TARGET_X86_64
> -                    if (CODE64(s) && rm == 0) {
> -                        /* swapgs */
> -                        tcg_gen_ld_tl(cpu_T[0], cpu_env, 
> offsetof(CPUX86State,segs[R_GS].base));
> -                        tcg_gen_ld_tl(cpu_T[1], cpu_env, 
> offsetof(CPUX86State,kernelgsbase));
> -                        tcg_gen_st_tl(cpu_T[1], cpu_env, 
> offsetof(CPUX86State,segs[R_GS].base));
> -                        tcg_gen_st_tl(cpu_T[0], cpu_env, 
> offsetof(CPUX86State,kernelgsbase));
> +                    if (CODE64(s)) {
> +                        if (s->cpl != 0) {
> +                            gen_exception(s, EXCP0D_GPF, pc_start - 
> s->cs_base);
> +                        } else {
> +                            tcg_gen_ld_tl(cpu_T[0], cpu_env,
> +                                offsetof(CPUX86State,segs[R_GS].base));
> +                            tcg_gen_ld_tl(cpu_T[1], cpu_env,
> +                                offsetof(CPUX86State,kernelgsbase));
> +                            tcg_gen_st_tl(cpu_T[1], cpu_env,
> +                                offsetof(CPUX86State,segs[R_GS].base));
> +                            tcg_gen_st_tl(cpu_T[0], cpu_env,
> +                                offsetof(CPUX86State,kernelgsbase));
> +                        }
>                      } else
>  #endif
>                      {
>                          goto illegal_op;
>                      }
> -                } else {
> +                    break;
> +                case 1: /* rdtscp */
> +                    if (!(s->cpuid_ext2_features & CPUID_EXT2_RDTSCP))
> +                        goto illegal_op;
>                      if (s->cc_op != CC_OP_DYNAMIC)
>                          gen_op_set_cc_op(s->cc_op);
>                      gen_jmp_im(pc_start - s->cs_base);
> -                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
> -                    gen_helper_invlpg(cpu_A0);
> -                    gen_jmp_im(s->pc - s->cs_base);
> -                    gen_eob(s);
> +                    if (use_icount)
> +                        gen_io_start();
> +                    gen_helper_rdtscp();
> +                    if (use_icount) {
> +                        gen_io_end();
> +                        gen_jmp(s, s->pc - s->cs_base);
> +                    }
> +                    break;
> +                default:
> +                    goto illegal_op;
>                  }
>              }
>              break;
> -- 
> 1.6.1.3
> 
> 
> 
> 
> 

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
address@hidden                 http://www.aurel32.net




reply via email to

[Prev in Thread] Current Thread [Next in Thread]