Commit 590bc601d800d16a77676926898019f7285bd615
1 parent
ff867ddc
MIPS atomic instructions
Implement MIPS ll/sc instructions using atomic compare+exchange. Signed-off-by: Paul Brook <paul@codesourcery.com>
Showing
3 changed files
with
124 additions
and
24 deletions
linux-user/main.c
... | ... | @@ -1826,6 +1826,55 @@ static const uint8_t mips_syscall_args[] = { |
1826 | 1826 | |
1827 | 1827 | #undef MIPS_SYS |
1828 | 1828 | |
1829 | +static int do_store_exclusive(CPUMIPSState *env) | |
1830 | +{ | |
1831 | + target_ulong addr; | |
1832 | + target_ulong page_addr; | |
1833 | + target_ulong val; | |
1834 | + int flags; | |
1835 | + int segv = 0; | |
1836 | + int reg; | |
1837 | + int d; | |
1838 | + | |
1839 | + addr = env->CP0_LLAddr; | |
1840 | + page_addr = addr & TARGET_PAGE_MASK; | |
1841 | + start_exclusive(); | |
1842 | + mmap_lock(); | |
1843 | + flags = page_get_flags(page_addr); | |
1844 | + if ((flags & PAGE_READ) == 0) { | |
1845 | + segv = 1; | |
1846 | + } else { | |
1847 | + reg = env->llreg & 0x1f; | |
1848 | + d = (env->llreg & 0x20) != 0; | |
1849 | + if (d) { | |
1850 | + segv = get_user_s64(val, addr); | |
1851 | + } else { | |
1852 | + segv = get_user_s32(val, addr); | |
1853 | + } | |
1854 | + if (!segv) { | |
1855 | + if (val != env->llval) { | |
1856 | + env->active_tc.gpr[reg] = 0; | |
1857 | + } else { | |
1858 | + if (d) { | |
1859 | + segv = put_user_u64(env->llnewval, addr); | |
1860 | + } else { | |
1861 | + segv = put_user_u32(env->llnewval, addr); | |
1862 | + } | |
1863 | + if (!segv) { | |
1864 | + env->active_tc.gpr[reg] = 1; | |
1865 | + } | |
1866 | + } | |
1867 | + } | |
1868 | + } | |
1869 | + env->CP0_LLAddr = -1; | |
1870 | + if (!segv) { | |
1871 | + env->active_tc.PC += 4; | |
1872 | + } | |
1873 | + mmap_unlock(); | |
1874 | + end_exclusive(); | |
1875 | + return segv; | |
1876 | +} | |
1877 | + | |
1829 | 1878 | void cpu_loop(CPUMIPSState *env) |
1830 | 1879 | { |
1831 | 1880 | target_siginfo_t info; |
... | ... | @@ -1833,7 +1882,9 @@ void cpu_loop(CPUMIPSState *env) |
1833 | 1882 | unsigned int syscall_num; |
1834 | 1883 | |
1835 | 1884 | for(;;) { |
1885 | + cpu_exec_start(env); | |
1836 | 1886 | trapnr = cpu_mips_exec(env); |
1887 | + cpu_exec_end(env); | |
1837 | 1888 | switch(trapnr) { |
1838 | 1889 | case EXCP_SYSCALL: |
1839 | 1890 | syscall_num = env->active_tc.gpr[2] - 4000; |
... | ... | @@ -1910,6 +1961,15 @@ void cpu_loop(CPUMIPSState *env) |
1910 | 1961 | } |
1911 | 1962 | } |
1912 | 1963 | break; |
1964 | + case EXCP_SC: | |
1965 | + if (do_store_exclusive(env)) { | |
1966 | + info.si_signo = TARGET_SIGSEGV; | |
1967 | + info.si_errno = 0; | |
1968 | + info.si_code = TARGET_SEGV_MAPERR; | |
1969 | + info._sifields._sigfault._addr = env->active_tc.PC; | |
1970 | + queue_signal(env, info.si_signo, &info); | |
1971 | + } | |
1972 | + break; | |
1913 | 1973 | default: |
1914 | 1974 | // error: |
1915 | 1975 | fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", | ... | ... |
target-mips/cpu.h
... | ... | @@ -375,6 +375,9 @@ struct CPUMIPSState { |
375 | 375 | int32_t CP0_Config7; |
376 | 376 | /* XXX: Maybe make LLAddr per-TC? */ |
377 | 377 | target_ulong CP0_LLAddr; |
378 | + target_ulong llval; | |
379 | + target_ulong llnewval; | |
380 | + target_ulong llreg; | |
378 | 381 | target_ulong CP0_WatchLo[8]; |
379 | 382 | int32_t CP0_WatchHi[8]; |
380 | 383 | target_ulong CP0_XContext; |
... | ... | @@ -559,6 +562,8 @@ enum { |
559 | 562 | |
560 | 563 | EXCP_LAST = EXCP_CACHE, |
561 | 564 | }; |
565 | +/* Dummy exception for conditional stores. */ | |
566 | +#define EXCP_SC 0x100 | |
562 | 567 | |
563 | 568 | int cpu_mips_exec(CPUMIPSState *s); |
564 | 569 | CPUMIPSState *cpu_mips_init(const char *cpu_model); | ... | ... |
target-mips/translate.c
... | ... | @@ -919,6 +919,7 @@ static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \ |
919 | 919 | tcg_gen_mov_tl(t0, arg1); \ |
920 | 920 | tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \ |
921 | 921 | tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_LLAddr)); \ |
922 | + tcg_gen_st_tl(ret, cpu_env, offsetof(CPUState, llval)); \ | |
922 | 923 | tcg_temp_free(t0); \ |
923 | 924 | } |
924 | 925 | OP_LD_ATOMIC(ll,ld32s); |
... | ... | @@ -927,32 +928,66 @@ OP_LD_ATOMIC(lld,ld64); |
927 | 928 | #endif |
928 | 929 | #undef OP_LD_ATOMIC |
929 | 930 | |
930 | -#define OP_ST_ATOMIC(insn,fname,almask) \ | |
931 | -static inline void op_ldst_##insn(TCGv ret, TCGv arg1, TCGv arg2, DisasContext *ctx) \ | |
932 | -{ \ | |
933 | - TCGv t0 = tcg_temp_new(); \ | |
934 | - int l1 = gen_new_label(); \ | |
935 | - int l2 = gen_new_label(); \ | |
936 | - int l3 = gen_new_label(); \ | |
937 | - \ | |
938 | - tcg_gen_andi_tl(t0, arg2, almask); \ | |
939 | - tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \ | |
940 | - tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUState, CP0_BadVAddr)); \ | |
941 | - generate_exception(ctx, EXCP_AdES); \ | |
942 | - gen_set_label(l1); \ | |
943 | - tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_LLAddr)); \ | |
944 | - tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \ | |
945 | - tcg_temp_free(t0); \ | |
946 | - tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx); \ | |
947 | - tcg_gen_movi_tl(ret, 1); \ | |
948 | - tcg_gen_br(l3); \ | |
949 | - gen_set_label(l2); \ | |
950 | - tcg_gen_movi_tl(ret, 0); \ | |
951 | - gen_set_label(l3); \ | |
931 | +#ifdef CONFIG_USER_ONLY | |
932 | +#define OP_ST_ATOMIC(insn,fname,ldname,almask) \ | |
933 | +static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \ | |
934 | +{ \ | |
935 | + TCGv t0 = tcg_temp_new(); \ | |
936 | + int l1 = gen_new_label(); \ | |
937 | + int l2 = gen_new_label(); \ | |
938 | + \ | |
939 | + tcg_gen_andi_tl(t0, arg2, almask); \ | |
940 | + tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \ | |
941 | + tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUState, CP0_BadVAddr)); \ | |
942 | + generate_exception(ctx, EXCP_AdES); \ | |
943 | + gen_set_label(l1); \ | |
944 | + tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_LLAddr)); \ | |
945 | + tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \ | |
946 | + tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \ | |
947 | + tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, llreg)); \ | |
948 | + tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUState, llnewval)); \ | |
949 | + gen_helper_0i(raise_exception, EXCP_SC); \ | |
950 | + gen_set_label(l2); \ | |
951 | + tcg_gen_movi_tl(t0, 0); \ | |
952 | + gen_store_gpr(t0, rt); \ | |
953 | + tcg_temp_free(t0); \ | |
952 | 954 | } |
953 | -OP_ST_ATOMIC(sc,st32,0x3); | |
955 | +#else | |
956 | +#define OP_ST_ATOMIC(insn,fname,ldname,almask) \ | |
957 | +static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \ | |
958 | +{ \ | |
959 | + TCGv t0 = tcg_temp_new(); \ | |
960 | + TCGv t1 = tcg_temp_new(); \ | |
961 | + int l1 = gen_new_label(); \ | |
962 | + int l2 = gen_new_label(); \ | |
963 | + int l3 = gen_new_label(); \ | |
964 | + \ | |
965 | + tcg_gen_andi_tl(t0, arg2, almask); \ | |
966 | + tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \ | |
967 | + tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUState, CP0_BadVAddr)); \ | |
968 | + generate_exception(ctx, EXCP_AdES); \ | |
969 | + gen_set_label(l1); \ | |
970 | + tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_LLAddr)); \ | |
971 | + tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \ | |
972 | + tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, llval)); \ | |
973 | + tcg_gen_qemu_##ldname(t1, arg2, ctx->mem_idx); \ | |
974 | + tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l2); \ | |
975 | + tcg_temp_free(t1); \ | |
976 | + tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx); \ | |
977 | + tcg_gen_movi_tl(t0, 1); \ | |
978 | + gen_store_gpr(t0, rt); \ | |
979 | + tcg_gen_br(l3); \ | |
980 | + gen_set_label(l2); \ | |
981 | + tcg_gen_movi_tl(t0, 0); \ | |
982 | + gen_store_gpr(t0, rt); \ | |
983 | + gen_set_label(l3); \ | |
984 | + tcg_temp_free(t0); \ | |
985 | +} | |
986 | +#endif | |
987 | + | |
988 | +OP_ST_ATOMIC(sc,st32,ld32s,0x3); | |
954 | 989 | #if defined(TARGET_MIPS64) |
955 | -OP_ST_ATOMIC(scd,st64,0x7); | |
990 | +OP_ST_ATOMIC(scd,st64,ld64,0x7); | |
956 | 991 | #endif |
957 | 992 | #undef OP_ST_ATOMIC |
958 | 993 | ... | ... |