qemu-ppc
[Top][All Lists]
Advanced

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

Re: [Qemu-ppc] [PATCH 47/58] Implement POWER7's CFAR in TCG


From: Blue Swirl
Subject: Re: [Qemu-ppc] [PATCH 47/58] Implement POWER7's CFAR in TCG
Date: Sat, 17 Sep 2011 17:08:29 +0000

On Wed, Sep 14, 2011 at 8:43 AM, Alexander Graf <address@hidden> wrote:
> From: David Gibson <address@hidden>
>
> This patch implements support for the CFAR SPR on POWER7 (Come From
> Address Register), which snapshots the PC value at the time of a branch or
> an rfid.  The latest powerpc-next kernel also catches it and can show it in
> xmon or in the signal frames.
>
> This works well enough to let recent kernels boot (which otherwise oops
> on the CFAR access).  It hasn't been tested enough to be confident that the
> CFAR values are actually accurate, but one thing at a time.

This looks accurate at least for the cases covered.

A higher performance implementation could be to only update the
register lazily when the SPR is read, in most other times CFAR would
be only stored to DisasContext.

> Signed-off-by: Ben Herrenschmidt <address@hidden>
> Signed-off-by: David Gibson <address@hidden>
> Signed-off-by: Alexander Graf <address@hidden>
> ---
>  target-ppc/cpu.h            |    8 ++++++++
>  target-ppc/translate.c      |   28 ++++++++++++++++++++++++++++
>  target-ppc/translate_init.c |   23 ++++++++++++++++++++++-
>  3 files changed, 58 insertions(+), 1 deletions(-)
>
> diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
> index 32706df..3f4af22 100644
> --- a/target-ppc/cpu.h
> +++ b/target-ppc/cpu.h
> @@ -555,6 +555,8 @@ enum {
>     /* Decrementer clock: RTC clock (POWER, 601) or bus clock                
> */
>     POWERPC_FLAG_RTC_CLK  = 0x00010000,
>     POWERPC_FLAG_BUS_CLK  = 0x00020000,
> +    /* Has CFAR                                                              
> */
> +    POWERPC_FLAG_CFAR     = 0x00040000,
>  };
>
>  
> /*****************************************************************************/
> @@ -872,6 +874,10 @@ struct CPUPPCState {
>     target_ulong ctr;
>     /* condition register */
>     uint32_t crf[8];
> +#if defined(TARGET_PPC64)
> +    /* CFAR */
> +    target_ulong cfar;
> +#endif
>     /* XER */
>     target_ulong xer;
>     /* Reservation address */
> @@ -1204,6 +1210,7 @@ static inline void cpu_clone_regs(CPUState *env, 
> target_ulong newsp)
>  #define SPR_601_UDECR         (0x006)
>  #define SPR_LR                (0x008)
>  #define SPR_CTR               (0x009)
> +#define SPR_DSCR              (0x011)
>  #define SPR_DSISR             (0x012)
>  #define SPR_DAR               (0x013) /* DAE for PowerPC 601 */
>  #define SPR_601_RTCU          (0x014)
> @@ -1212,6 +1219,7 @@ static inline void cpu_clone_regs(CPUState *env, 
> target_ulong newsp)
>  #define SPR_SDR1              (0x019)
>  #define SPR_SRR0              (0x01A)
>  #define SPR_SRR1              (0x01B)
> +#define SPR_CFAR              (0x01C)
>  #define SPR_AMR               (0x01D)
>  #define SPR_BOOKE_PID         (0x030)
>  #define SPR_BOOKE_DECAR       (0x036)
> diff --git a/target-ppc/translate.c b/target-ppc/translate.c
> index 4277460..1e362fc 100644
> --- a/target-ppc/translate.c
> +++ b/target-ppc/translate.c
> @@ -69,6 +69,9 @@ static TCGv cpu_nip;
>  static TCGv cpu_msr;
>  static TCGv cpu_ctr;
>  static TCGv cpu_lr;
> +#if defined(TARGET_PPC64)
> +static TCGv cpu_cfar;
> +#endif
>  static TCGv cpu_xer;
>  static TCGv cpu_reserve;
>  static TCGv_i32 cpu_fpscr;
> @@ -154,6 +157,11 @@ void ppc_translate_init(void)
>     cpu_lr = tcg_global_mem_new(TCG_AREG0,
>                                 offsetof(CPUState, lr), "lr");
>
> +#if defined(TARGET_PPC64)
> +    cpu_cfar = tcg_global_mem_new(TCG_AREG0,
> +                                  offsetof(CPUState, cfar), "cfar");
> +#endif
> +
>     cpu_xer = tcg_global_mem_new(TCG_AREG0,
>                                  offsetof(CPUState, xer), "xer");
>
> @@ -187,6 +195,7 @@ typedef struct DisasContext {
>     int le_mode;
>  #if defined(TARGET_PPC64)
>     int sf_mode;
> +    int has_cfar;
>  #endif
>     int fpu_enabled;
>     int altivec_enabled;
> @@ -3345,6 +3354,14 @@ static inline void gen_qemu_st32fiw(DisasContext *ctx, 
> TCGv_i64 arg1, TCGv arg2)
>  /* stfiwx */
>  GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
>
> +static inline void gen_update_cfar(DisasContext *ctx, target_ulong nip)
> +{
> +#if defined(TARGET_PPC64)
> +    if (ctx->has_cfar)

Braces missing, please use checkpatch.pl.

> +        tcg_gen_movi_tl(cpu_cfar, nip);
> +#endif
> +}
> +
>  /***                                Branch                                 
> ***/
>  static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
>  {
> @@ -3407,6 +3424,7 @@ static void gen_b(DisasContext *ctx)
>         target = li;
>     if (LK(ctx->opcode))
>         gen_setlr(ctx, ctx->nip);
> +    gen_update_cfar(ctx, ctx->nip);
>     gen_goto_tb(ctx, 0, target);
>  }
>
> @@ -3469,6 +3487,7 @@ static inline void gen_bcond(DisasContext *ctx, int 
> type)
>         }
>         tcg_temp_free_i32(temp);
>     }
> +    gen_update_cfar(ctx, ctx->nip);
>     if (type == BCOND_IM) {
>         target_ulong li = (target_long)((int16_t)(BD(ctx->opcode)));
>         if (likely(AA(ctx->opcode) == 0)) {
> @@ -3580,6 +3599,7 @@ static void gen_rfi(DisasContext *ctx)
>         gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
>         return;
>     }
> +    gen_update_cfar(ctx, ctx->nip);
>     gen_helper_rfi();
>     gen_sync_exception(ctx);
>  #endif
> @@ -3596,6 +3616,7 @@ static void gen_rfid(DisasContext *ctx)
>         gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
>         return;
>     }
> +    gen_update_cfar(ctx, ctx->nip);
>     gen_helper_rfid();
>     gen_sync_exception(ctx);
>  #endif
> @@ -9263,6 +9284,12 @@ void cpu_dump_state (CPUState *env, FILE *f, 
> fprintf_function cpu_fprintf,
>          */
>     }
>
> +#if defined(TARGET_PPC64)
> +    if (env->flags & POWERPC_FLAG_CFAR) {
> +        cpu_fprintf(f, " CFAR " TARGET_FMT_lx"\n", env->cfar);
> +    }
> +#endif
> +
>     switch (env->mmu_model) {
>     case POWERPC_MMU_32B:
>     case POWERPC_MMU_601:
> @@ -9371,6 +9398,7 @@ static inline void 
> gen_intermediate_code_internal(CPUState *env,
>     ctx.le_mode = env->hflags & (1 << MSR_LE) ? 1 : 0;
>  #if defined(TARGET_PPC64)
>     ctx.sf_mode = msr_sf;
> +    ctx.has_cfar = !!(env->flags & POWERPC_FLAG_CFAR);
>  #endif
>     ctx.fpu_enabled = msr_fp;
>     if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
> diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
> index 9ea193d..211f3bd 100644
> --- a/target-ppc/translate_init.c
> +++ b/target-ppc/translate_init.c
> @@ -129,6 +129,19 @@ static void spr_write_lr (void *opaque, int sprn, int 
> gprn)
>     tcg_gen_mov_tl(cpu_lr, cpu_gpr[gprn]);
>  }
>
> +/* CFAR */
> +#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
> +static void spr_read_cfar (void *opaque, int gprn, int sprn)
> +{
> +    tcg_gen_mov_tl(cpu_gpr[gprn], cpu_cfar);
> +}
> +
> +static void spr_write_cfar (void *opaque, int sprn, int gprn)
> +{
> +    tcg_gen_mov_tl(cpu_cfar, cpu_gpr[gprn]);
> +}
> +#endif /* defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) */
> +
>  /* CTR */
>  static void spr_read_ctr (void *opaque, int gprn, int sprn)
>  {
> @@ -6489,7 +6502,7 @@ static void init_proc_970MP (CPUPPCState *env)
>  #define POWERPC_BFDM_POWER7   (bfd_mach_ppc64)
>  #define POWERPC_FLAG_POWER7   (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |          
>   \
>                               POWERPC_FLAG_BE | POWERPC_FLAG_PMM |            
> \
> -                              POWERPC_FLAG_BUS_CLK)
> +                              POWERPC_FLAG_BUS_CLK | POWERPC_FLAG_CFAR)
>  #define check_pow_POWER7    check_pow_nocheck
>
>  static void init_proc_POWER7 (CPUPPCState *env)
> @@ -6508,6 +6521,14 @@ static void init_proc_POWER7 (CPUPPCState *env)
>                  &spr_read_purr, SPR_NOACCESS,
>                  &spr_read_purr, SPR_NOACCESS,
>                  0x00000000);
> +    spr_register(env, SPR_CFAR, "SPR_CFAR",
> +                 SPR_NOACCESS, SPR_NOACCESS,
> +                 &spr_read_cfar, &spr_write_cfar,
> +                 0x00000000);
> +    spr_register(env, SPR_DSCR, "SPR_DSCR",
> +                 SPR_NOACCESS, SPR_NOACCESS,
> +                 &spr_read_generic, &spr_write_generic,
> +                 0x00000000);
>  #endif /* !CONFIG_USER_ONLY */
>     /* Memory management */
>     /* XXX : not implemented */
> --
> 1.6.0.2
>
>



reply via email to

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