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: Stefan Weil
Subject: Re: [Qemu-commits] [COMMIT 590bc60] MIPS atomic instructions
Date: Sat, 11 Jul 2009 15:26:51 +0200
User-agent: Mozilla-Thunderbird 2.0.0.19 (X11/20090103)

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.

Regards,
Stefan

tail /tmp/qemu.log

cpu_mips_handle_mmu_fault pc 803be010 ad 80440000 rw 0 mmu_idx 0 smmu 1
cpu_mips_handle_mmu_fault address=80440000 ret 0 physical 00440000 prot 3
cpu_mips_handle_mmu_fault pc 803be010 ad 8044218c rw 0 mmu_idx 0 smmu 1
cpu_mips_handle_mmu_fault address=8044218c ret 0 physical 0044218c prot 3
IN: lock_kernel
0x803be024:  ll v1,-1952(v0)
0x803be028:  bnez       v1,0x803be084
0x803be02c:  li v1,1

cpu_mips_handle_mmu_fault pc 803be024 ad 8045f860 rw 0 mmu_idx 0 smmu 1
cpu_mips_handle_mmu_fault address=8045f860 ret 0 physical 0045f860 prot 3
IN: lock_kernel
0x803be030:  sc v1,-1952(v0)
0x803be034:  beqz       v1,0x803be084
0x803be038:  nop

helper_raise_exception_err: 13 0
do_interrupt enter: PC 803be030 EPC 00000000 address error store exception
do_interrupt: PC 80000180 EPC 803be030 cause 5
    S 10000002 C 00000414 A 00000001 D 00000000
cpu_mips_handle_mmu_fault pc 80000180 ad 80000180 rw 2 mmu_idx 0 smmu 1
cpu_mips_handle_mmu_fault address=80000180 ret 0 physical 00000180 prot 3
IN:
0x80000180:  nop
0x80000184:  nop
0x80000188:  nop
0x8000018c:  nop
0x80000190:  nop
0x80000194:  nop
0x80000198:  nop
0x8000019c:  nop

git bisect:

590bc601d800d16a77676926898019f7285bd615 is first bad commit
commit 590bc601d800d16a77676926898019f7285bd615
Author: Paul Brook <address@hidden>
Date:   Thu Jul 9 17:45:17 2009 +0100

    MIPS atomic instructions

    Implement MIPS ll/sc instructions using atomic compare+exchange.

    Signed-off-by: Paul Brook <address@hidden>

:040000 040000 6a2612835514be1613a4442a2d2049f4e86b6c1c
99d5856ab75ce7c78476dcea1944664b96f7b893 M      linux-user
:040000 040000 1f589f37740184bd10cc93a59b4f936bb20766c6
de548a4e6629b53204045f58c5285aff5a8ea4e4 M      target-mips





reply via email to

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