qemu-commits
[Top][All Lists]
Advanced

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

Re: [Qemu-commits] [COMMIT 590bc60] MIPS atomic instructions


From: Aurelien Jarno
Subject: Re: [Qemu-commits] [COMMIT 590bc60] MIPS atomic instructions
Date: Sun, 12 Jul 2009 02:44:23 +0200
User-agent: Mutt/1.5.18 (2008-05-17)

On Sat, Jul 11, 2009 at 03:26:51PM +0200, Stefan Weil wrote:
> Anthony Liguori schrieb:
> > From: Paul Brook <address@hidden>
> >
> > Implement MIPS ll/sc instructions using atomic compare+exchange.
> >
> > Signed-off-by: Paul Brook <address@hidden>
> >
> > diff --git a/linux-user/main.c b/linux-user/main.c
> > index 7348447..30290a5 100644
> > --- a/linux-user/main.c
> > +++ b/linux-user/main.c
> > @@ -1826,6 +1826,55 @@ static const uint8_t mips_syscall_args[] = {
> >  
> >  #undef MIPS_SYS
> >  
> > +static int do_store_exclusive(CPUMIPSState *env)
> > +{
> > +    target_ulong addr;
> > +    target_ulong page_addr;
> > +    target_ulong val;
> > +    int flags;
> > +    int segv = 0;
> > +    int reg;
> > +    int d;
> > +
> > +    addr = env->CP0_LLAddr;
> > +    page_addr = addr & TARGET_PAGE_MASK;
> > +    start_exclusive();
> > +    mmap_lock();
> > +    flags = page_get_flags(page_addr);
> > +    if ((flags & PAGE_READ) == 0) {
> > +        segv = 1;
> > +    } else {
> > +        reg = env->llreg & 0x1f;
> > +        d = (env->llreg & 0x20) != 0;
> > +        if (d) {
> > +            segv = get_user_s64(val, addr);
> > +        } else {
> > +            segv = get_user_s32(val, addr);
> > +        }
> > +        if (!segv) {
> > +            if (val != env->llval) {
> > +                env->active_tc.gpr[reg] = 0;
> > +            } else {
> > +                if (d) {
> > +                    segv = put_user_u64(env->llnewval, addr);
> > +                } else {
> > +                    segv = put_user_u32(env->llnewval, addr);
> > +                }
> > +                if (!segv) {
> > +                    env->active_tc.gpr[reg] = 1;
> > +                }
> > +            }
> > +        }
> > +    }
> > +    env->CP0_LLAddr = -1;
> > +    if (!segv) {
> > +        env->active_tc.PC += 4;
> > +    }
> > +    mmap_unlock();
> > +    end_exclusive();
> > +    return segv;
> > +}
> > +
> >  void cpu_loop(CPUMIPSState *env)
> >  {
> >      target_siginfo_t info;
> > @@ -1833,7 +1882,9 @@ void cpu_loop(CPUMIPSState *env)
> >      unsigned int syscall_num;
> >  
> >      for(;;) {
> > +        cpu_exec_start(env);
> >          trapnr = cpu_mips_exec(env);
> > +        cpu_exec_end(env);
> >          switch(trapnr) {
> >          case EXCP_SYSCALL:
> >              syscall_num = env->active_tc.gpr[2] - 4000;
> > @@ -1910,6 +1961,15 @@ void cpu_loop(CPUMIPSState *env)
> >                    }
> >              }
> >              break;
> > +        case EXCP_SC:
> > +            if (do_store_exclusive(env)) {
> > +                info.si_signo = TARGET_SIGSEGV;
> > +                info.si_errno = 0;
> > +                info.si_code = TARGET_SEGV_MAPERR;
> > +                info._sifields._sigfault._addr = env->active_tc.PC;
> > +                queue_signal(env, info.si_signo, &info);
> > +            }
> > +            break;
> >          default:
> >              //        error:
> >              fprintf(stderr, "qemu: unhandled CPU exception 0x%x - 
> > aborting\n",
> > diff --git a/target-mips/cpu.h b/target-mips/cpu.h
> > index 6ebb82b..bb9a49b 100644
> > --- a/target-mips/cpu.h
> > +++ b/target-mips/cpu.h
> > @@ -375,6 +375,9 @@ struct CPUMIPSState {
> >      int32_t CP0_Config7;
> >      /* XXX: Maybe make LLAddr per-TC? */
> >      target_ulong CP0_LLAddr;
> > +    target_ulong llval;
> > +    target_ulong llnewval;
> > +    target_ulong llreg;
> >      target_ulong CP0_WatchLo[8];
> >      int32_t CP0_WatchHi[8];
> >      target_ulong CP0_XContext;
> > @@ -559,6 +562,8 @@ enum {
> >  
> >      EXCP_LAST = EXCP_CACHE,
> >  };
> > +/* Dummy exception for conditional stores.  */
> > +#define EXCP_SC 0x100
> >  
> >  int cpu_mips_exec(CPUMIPSState *s);
> >  CPUMIPSState *cpu_mips_init(const char *cpu_model);
> > diff --git a/target-mips/translate.c b/target-mips/translate.c
> > index d316b9d..cf467f8 100644
> > --- a/target-mips/translate.c
> > +++ b/target-mips/translate.c
> > @@ -919,6 +919,7 @@ static inline void op_ldst_##insn(TCGv ret, TCGv arg1, 
> > DisasContext *ctx)  \
> >      tcg_gen_mov_tl(t0, arg1);                                              
> > \
> >      tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx);                         
> > \
> >      tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_LLAddr));            
> > \
> > +    tcg_gen_st_tl(ret, cpu_env, offsetof(CPUState, llval));                
> > \
> >      tcg_temp_free(t0);                                                     
> > \
> >  }
> >  OP_LD_ATOMIC(ll,ld32s);
> > @@ -927,32 +928,66 @@ OP_LD_ATOMIC(lld,ld64);
> >  #endif
> >  #undef OP_LD_ATOMIC
> >  
> > -#define OP_ST_ATOMIC(insn,fname,almask)                                    
> >           \
> > -static inline void op_ldst_##insn(TCGv ret, TCGv arg1, TCGv arg2, 
> > DisasContext *ctx) \
> > -{                                                                          
> >           \
> > -    TCGv t0 = tcg_temp_new();                                              
> >           \
> > -    int l1 = gen_new_label();                                              
> >           \
> > -    int l2 = gen_new_label();                                              
> >           \
> > -    int l3 = gen_new_label();                                              
> >           \
> > -                                                                           
> >           \
> > -    tcg_gen_andi_tl(t0, arg2, almask);                                     
> >           \
> > -    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);                            
> >           \
> > -    tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUState, CP0_BadVAddr));        
> >           \
> > -    generate_exception(ctx, EXCP_AdES);                                    
> >           \
> > -    gen_set_label(l1);                                                     
> >           \
> > -    tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_LLAddr));            
> >           \
> > -    tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2);                          
> >           \
> > -    tcg_temp_free(t0);                                                     
> >           \
> > -    tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx);                        
> >           \
> > -    tcg_gen_movi_tl(ret, 1);                                               
> >           \
> > -    tcg_gen_br(l3);                                                        
> >           \
> > -    gen_set_label(l2);                                                     
> >           \
> > -    tcg_gen_movi_tl(ret, 0);                                               
> >           \
> > -    gen_set_label(l3);                                                     
> >           \
> > +#ifdef CONFIG_USER_ONLY
> > +#define OP_ST_ATOMIC(insn,fname,ldname,almask)                             
> >   \
> > +static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, 
> > DisasContext *ctx) \
> > +{                                                                          
> >   \
> > +    TCGv t0 = tcg_temp_new();                                              
> >   \
> > +    int l1 = gen_new_label();                                              
> >   \
> > +    int l2 = gen_new_label();                                              
> >   \
> > +                                                                           
> >   \
> > +    tcg_gen_andi_tl(t0, arg2, almask);                                     
> >   \
> > +    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);                            
> >   \
> > +    tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUState, CP0_BadVAddr));        
> >   \
> > +    generate_exception(ctx, EXCP_AdES);                                    
> >   \
> > +    gen_set_label(l1);                                                     
> >   \
> > +    tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_LLAddr));            
> >   \
> > +    tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2);                          
> >   \
> > +    tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20));                      
> >   \
> > +    tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, llreg));                 
> >   \
> > +    tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUState, llnewval));            
> >   \
> > +    gen_helper_0i(raise_exception, EXCP_SC);                               
> >   \
> > +    gen_set_label(l2);                                                     
> >   \
> > +    tcg_gen_movi_tl(t0, 0);                                                
> >   \
> > +    gen_store_gpr(t0, rt);                                                 
> >   \
> > +    tcg_temp_free(t0);                                                     
> >   \
> >  }
> > -OP_ST_ATOMIC(sc,st32,0x3);
> > +#else
> > +#define OP_ST_ATOMIC(insn,fname,ldname,almask)                             
> >   \
> > +static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, 
> > DisasContext *ctx) \
> > +{                                                                          
> >   \
> > +    TCGv t0 = tcg_temp_new();                                              
> >   \
> > +    TCGv t1 = tcg_temp_new();                                              
> >   \
> > +    int l1 = gen_new_label();                                              
> >   \
> > +    int l2 = gen_new_label();                                              
> >   \
> > +    int l3 = gen_new_label();                                              
> >   \
> > +                                                                           
> >   \
> > +    tcg_gen_andi_tl(t0, arg2, almask);                                     
> >   \
> > +    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);                            
> >   \
> > +    tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUState, CP0_BadVAddr));        
> >   \
> > +    generate_exception(ctx, EXCP_AdES);                                    
> >   \
> > +    gen_set_label(l1);                                                     
> >   \
> > +    tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_LLAddr));            
> >   \
> > +    tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2);                          
> >   \
> > +    tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, llval));                 
> >   \
> > +    tcg_gen_qemu_##ldname(t1, arg2, ctx->mem_idx);                         
> >   \
> > +    tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l2);                            
> >   \
> > +    tcg_temp_free(t1);                                                     
> >   \
> > +    tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx);                        
> >   \
> > +    tcg_gen_movi_tl(t0, 1);                                                
> >   \
> > +    gen_store_gpr(t0, rt);                                                 
> >   \
> > +    tcg_gen_br(l3);                                                        
> >   \
> > +    gen_set_label(l2);                                                     
> >   \
> > +    tcg_gen_movi_tl(t0, 0);                                                
> >   \
> > +    gen_store_gpr(t0, rt);                                                 
> >   \
> > +    gen_set_label(l3);                                                     
> >   \
> > +    tcg_temp_free(t0);                                                     
> >   \
> > +}
> > +#endif
> > +
> > +OP_ST_ATOMIC(sc,st32,ld32s,0x3);
> >  #if defined(TARGET_MIPS64)
> > -OP_ST_ATOMIC(scd,st64,0x7);
> > +OP_ST_ATOMIC(scd,st64,ld64,0x7);
> >  #endif
> >  #undef OP_ST_ATOMIC
> >  
> 
> After this patch, MIPS malta fails to boot linux.
> Other MIPS emulations even crash QEMU.
> 

The macro has been modified to take different arguments, but the main
code hasn't been changed. As a result it does not even compile with
--enable-debug-tcg.

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




reply via email to

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