From 4dc89b782095d7a0b919fafd7b1322b3cb1279f1 Mon Sep 17 00:00:00 2001 From: Yongbok Kim Date: Mon, 29 Jun 2015 10:11:23 +0100 Subject: [PATCH 1/9] target-mips: fix MIPS64R6-generic configuration Fix core configuration for MIPS64R6-generic to make it as close as I6400. I6400 core has 48-bit of Virtual Address available (SEGBITS). MIPS SIMD Architecture is available. Rearrange order of bits to match the specification. Signed-off-by: Yongbok Kim Reviewed-by: Aurelien Jarno Reviewed-by: Leon Alrae Signed-off-by: Leon Alrae --- target-mips/mips-defs.h | 2 +- target-mips/translate_init.c | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/target-mips/mips-defs.h b/target-mips/mips-defs.h index 20aa87c24c..53b185ebd3 100644 --- a/target-mips/mips-defs.h +++ b/target-mips/mips-defs.h @@ -11,7 +11,7 @@ #if defined(TARGET_MIPS64) #define TARGET_LONG_BITS 64 #define TARGET_PHYS_ADDR_SPACE_BITS 48 -#define TARGET_VIRT_ADDR_SPACE_BITS 42 +#define TARGET_VIRT_ADDR_SPACE_BITS 48 #else #define TARGET_LONG_BITS 32 #define TARGET_PHYS_ADDR_SPACE_BITS 40 diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c index ddfaff8052..9304e746b4 100644 --- a/target-mips/translate_init.c +++ b/target-mips/translate_init.c @@ -655,14 +655,14 @@ static const mips_def_t mips_defs[] = (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) | (0 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP), .CP0_Config2 = MIPS_CONFIG2, - .CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_RXI) | (1 << CP0C3_BP) | - (1 << CP0C3_BI) | (1 << CP0C3_ULRI) | (1 << CP0C3_LPA) | - (1U << CP0C3_M), - .CP0_Config4 = MIPS_CONFIG4 | (0xfc << CP0C4_KScrExist) | - (3 << CP0C4_IE) | (1 << CP0C4_M), + .CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) | (1 << CP0C3_MSAP) | + (1 << CP0C3_BP) | (1 << CP0C3_BI) | (1 << CP0C3_ULRI) | + (1 << CP0C3_RXI) | (1 << CP0C3_LPA), + .CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M) | (3 << CP0C4_IE) | + (0xfc << CP0C4_KScrExist), .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_LLB), - .CP0_Config5_rw_bitmask = (1 << CP0C5_SBRI) | (1 << CP0C5_FRE) | - (1 << CP0C5_UFE), + .CP0_Config5_rw_bitmask = (1 << CP0C5_MSAEn) | (1 << CP0C5_SBRI) | + (1 << CP0C5_FRE) | (1 << CP0C5_UFE), .CP0_LLAddr_rw_bitmask = 0, .CP0_LLAddr_shift = 0, .SYNCI_Step = 32, @@ -674,9 +674,9 @@ static const mips_def_t mips_defs[] = .CP1_fcr0 = (1 << FCR0_FREP) | (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV), - .SEGBITS = 42, + .SEGBITS = 48, .PABITS = 48, - .insn_flags = CPU_MIPS64R6, + .insn_flags = CPU_MIPS64R6 | ASE_MSA, .mmu_type = MMU_TYPE_R4000, }, { From d4f4f0d5d9e74c19614479592c8bc865d92773d0 Mon Sep 17 00:00:00 2001 From: Yongbok Kim Date: Tue, 30 Jun 2015 15:44:28 +0100 Subject: [PATCH 2/9] target-mips: fix to clear MSACSR.Cause MSACSR.Cause bits are needed to be cleared before a vector floating-point instructions. FEXDO.df, FEXUPL.df and FEXUPR.df were missed out. Signed-off-by: Yongbok Kim Reviewed-by: Aurelien Jarno Reviewed-by: Leon Alrae Signed-off-by: Leon Alrae --- target-mips/msa_helper.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c index 26ffdc726e..a1cb48f2a9 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -2642,6 +2642,8 @@ void helper_msa_fexdo_df(CPUMIPSState *env, uint32_t df, uint32_t wd, wr_t *pwt = &(env->active_fpu.fpr[wt].wr); uint32_t i; + clear_msacsr_cause(env); + switch (df) { case DF_WORD: for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { @@ -3192,6 +3194,8 @@ void helper_msa_fexupl_df(CPUMIPSState *env, uint32_t df, uint32_t wd, wr_t *pws = &(env->active_fpu.fpr[ws].wr); uint32_t i; + clear_msacsr_cause(env); + switch (df) { case DF_WORD: for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { @@ -3224,6 +3228,8 @@ void helper_msa_fexupr_df(CPUMIPSState *env, uint32_t df, uint32_t wd, wr_t *pws = &(env->active_fpu.fpr[ws].wr); uint32_t i; + clear_msacsr_cause(env); + switch (df) { case DF_WORD: for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { From 6b9c26fb5eed2345398daca4eef601da2f3d7867 Mon Sep 17 00:00:00 2001 From: Yongbok Kim Date: Tue, 30 Jun 2015 16:33:15 +0100 Subject: [PATCH 3/9] disas/mips: fix disassembling R6 instructions In the Release 6 of the MIPS Architecture, LL, SC, LLD, SCD, PREF and CACHE instructions have 9 bits offsets. Signed-off-by: Yongbok Kim Reviewed-by: Aurelien Jarno Reviewed-by: Leon Alrae Signed-off-by: Leon Alrae --- disas/mips.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/disas/mips.c b/disas/mips.c index 32940feb95..01336a8385 100644 --- a/disas/mips.c +++ b/disas/mips.c @@ -1296,12 +1296,12 @@ const struct mips_opcode mips_builtin_opcodes[] = {"dmod", "d,s,t", 0x000000de, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I64R6}, {"ddivu", "d,s,t", 0x0000009f, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I64R6}, {"dmodu", "d,s,t", 0x000000df, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I64R6}, -{"ll", "t,o(b)", 0x7c000036, 0xfc00007f, LDD|RD_b|WR_t, 0, I32R6}, -{"sc", "t,o(b)", 0x7c000026, 0xfc00007f, LDD|RD_b|WR_t, 0, I32R6}, -{"lld", "t,o(b)", 0x7c000037, 0xfc00007f, LDD|RD_b|WR_t, 0, I64R6}, -{"scd", "t,o(b)", 0x7c000027, 0xfc00007f, LDD|RD_b|WR_t, 0, I64R6}, -{"pref", "h,o(b)", 0x7c000035, 0xfc00007f, RD_b, 0, I32R6}, -{"cache", "k,o(b)", 0x7c000025, 0xfc00007f, RD_b, 0, I32R6}, +{"ll", "t,+o(b)", 0x7c000036, 0xfc00007f, LDD|RD_b|WR_t, 0, I32R6}, +{"sc", "t,+o(b)", 0x7c000026, 0xfc00007f, LDD|RD_b|WR_t, 0, I32R6}, +{"lld", "t,+o(b)", 0x7c000037, 0xfc00007f, LDD|RD_b|WR_t, 0, I64R6}, +{"scd", "t,+o(b)", 0x7c000027, 0xfc00007f, LDD|RD_b|WR_t, 0, I64R6}, +{"pref", "h,+o(b)", 0x7c000035, 0xfc00007f, RD_b, 0, I32R6}, +{"cache", "k,+o(b)", 0x7c000025, 0xfc00007f, RD_b, 0, I32R6}, {"seleqz", "d,v,t", 0x00000035, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I32R6}, {"selnez", "d,v,t", 0x00000037, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I32R6}, {"maddf.s", "D,S,T", 0x46000018, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I32R6}, From 6a973e6b6584221bed89a01e755b88e58b496652 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Wed, 1 Jul 2015 15:59:13 +0200 Subject: [PATCH 4/9] target-mips: fix ASID synchronisation for MIPS MT When syncing the task ASID with EntryHi, correctly or the value instead of assigning it. Reported-by: "Dr. David Alan Gilbert" Signed-off-by: Aurelien Jarno Cc: Leon Alrae Reviewed-by: Leon Alrae Signed-off-by: Leon Alrae --- target-mips/op_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 2a9ddff70f..d457a29f3e 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -661,7 +661,7 @@ static void sync_c0_tcstatus(CPUMIPSState *cpu, int tc, /* Sync the TASID with EntryHi. */ cpu->CP0_EntryHi &= ~0xff; - cpu->CP0_EntryHi = tasid; + cpu->CP0_EntryHi |= tasid; compute_hflags(cpu); } From fe87c2b36ae9c1c9a5279f3891f3bce1b573baa0 Mon Sep 17 00:00:00 2001 From: Leon Alrae Date: Tue, 14 Jul 2015 11:08:13 +0100 Subject: [PATCH 5/9] target-mips: correct DERET instruction Fix Debug Mode flag clearing, and when DERET is placed between LL and SC do not make SC fail. Signed-off-by: Leon Alrae Reviewed-by: Aurelien Jarno --- target-mips/op_helper.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index d457a29f3e..9c28631dc1 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -2154,10 +2154,9 @@ void helper_deret(CPUMIPSState *env) debug_pre_eret(env); set_pc(env, env->CP0_DEPC); - env->hflags &= MIPS_HFLAG_DM; + env->hflags &= ~MIPS_HFLAG_DM; compute_hflags(env); debug_post_eret(env); - env->lladdr = 1; } #endif /* !CONFIG_USER_ONLY */ From 47ada0ad3431b39863918dc80386634693d317b5 Mon Sep 17 00:00:00 2001 From: Leon Alrae Date: Tue, 14 Jul 2015 11:08:14 +0100 Subject: [PATCH 6/9] target-mips: fix logically dead code reported by Coverity Make use of CMPOP in floating-point compare instructions. Signed-off-by: Leon Alrae Reviewed-by: Aurelien Jarno --- target-mips/translate.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/target-mips/translate.c b/target-mips/translate.c index 73028572c9..4a1ffdbd94 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -9552,6 +9552,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_cmp_s(ctx, func-48, ft, fs, cc); opn = condnames[func-48]; } + optype = CMPOP; break; case OPC_ADD_D: check_cp1_registers(ctx, fs | ft | fd); @@ -10036,6 +10037,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_cmp_d(ctx, func-48, ft, fs, cc); opn = condnames[func-48]; } + optype = CMPOP; break; case OPC_CVT_S_D: check_cp1_registers(ctx, fs); @@ -10461,6 +10463,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, gen_cmp_ps(ctx, func-48, ft, fs, cc); opn = condnames[func-48]; } + optype = CMPOP; break; default: MIPS_INVAL(opn); From 26e7e982b267e71d40cd20e9e234fedef6770a90 Mon Sep 17 00:00:00 2001 From: Leon Alrae Date: Tue, 14 Jul 2015 11:08:15 +0100 Subject: [PATCH 7/9] target-mips: fix resource leak reported by Coverity UHI assert and link operations call lock_user_string() twice to obtain two strings pointed by gpr[4] and gpr[5]. If the second lock_user_string() fails, then the first one won't get freed. Fix this by introducing another macro responsible for obtaining two strings and handling allocation failure. Signed-off-by: Leon Alrae Reviewed-by: Aurelien Jarno --- target-mips/mips-semi.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/target-mips/mips-semi.c b/target-mips/mips-semi.c index 1162c76df9..5050940c20 100644 --- a/target-mips/mips-semi.c +++ b/target-mips/mips-semi.c @@ -220,6 +220,23 @@ static int copy_argn_to_target(CPUMIPSState *env, int arg_num, } \ } while (0) +#define GET_TARGET_STRINGS_2(p, addr, p2, addr2) \ + do { \ + p = lock_user_string(addr); \ + if (!p) { \ + gpr[2] = -1; \ + gpr[3] = EFAULT; \ + goto uhi_done; \ + } \ + p2 = lock_user_string(addr2); \ + if (!p2) { \ + unlock_user(p, addr, 0); \ + gpr[2] = -1; \ + gpr[3] = EFAULT; \ + goto uhi_done; \ + } \ + } while (0) + #define FREE_TARGET_STRING(p, gpr) \ do { \ unlock_user(p, gpr, 0); \ @@ -322,8 +339,7 @@ void helper_do_semihosting(CPUMIPSState *env) FREE_TARGET_STRING(p, gpr[4]); break; case UHI_assert: - GET_TARGET_STRING(p, gpr[4]); - GET_TARGET_STRING(p2, gpr[5]); + GET_TARGET_STRINGS_2(p, gpr[4], p2, gpr[5]); printf("assertion '"); printf("\"%s\"", p); printf("': file \"%s\", line %d\n", p2, (int)gpr[6]); @@ -341,8 +357,7 @@ void helper_do_semihosting(CPUMIPSState *env) break; #ifndef _WIN32 case UHI_link: - GET_TARGET_STRING(p, gpr[4]); - GET_TARGET_STRING(p2, gpr[5]); + GET_TARGET_STRINGS_2(p, gpr[4], p2, gpr[5]); gpr[2] = link(p, p2); gpr[3] = errno_mips(errno); FREE_TARGET_STRING(p2, gpr[5]); From f01a361bfcce4bd0c439b0e051ef2a1e56727a44 Mon Sep 17 00:00:00 2001 From: Andrew Bennett Date: Mon, 29 Jun 2015 10:20:07 +0000 Subject: [PATCH 8/9] linux-user: Fix MIPS N64 trap and break instruction bug For the MIPS N64 ABI when QEMU reads the break/trap instruction so that it can inspect the break/trap code it reads 8 rather than 4 bytes which means it finds the code field from the instruction after the break/trap instruction. This then causes the break/trap handling code to fail because it does not understand the code number. The fix forces QEMU to always read 4 bytes of instruction data rather than deciding how much to read based on the ABI. Signed-off-by: Andrew Bennett Reviewed-by: Leon Alrae Signed-off-by: Leon Alrae --- linux-user/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux-user/main.c b/linux-user/main.c index 05914b11e4..fdee981351 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -2577,7 +2577,7 @@ done_syscall: code = (trap_instr >> 6) & 0x3f; } } else { - ret = get_user_ual(trap_instr, env->active_tc.PC); + ret = get_user_u32(trap_instr, env->active_tc.PC); if (ret != 0) { goto error; } @@ -2611,7 +2611,7 @@ done_syscall: trap_instr = (instr[0] << 16) | instr[1]; } else { - ret = get_user_ual(trap_instr, env->active_tc.PC); + ret = get_user_u32(trap_instr, env->active_tc.PC); } if (ret != 0) { From 908680c6441ac468f4871d513f42be396ea0d264 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 14 Jul 2015 17:45:16 +0200 Subject: [PATCH 9/9] target-mips: fix page fault address for LWL/LWR/LDL/LDR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a LWL, LWR, LDL or LDR instruction triggers a page fault, QEMU currently reports the aligned address in CP0 BadVAddr, while the Windows NT kernel expects the unaligned address. This patch adds a byte access with the unaligned address at the beginning of the LWL/LWR/LDL/LDR instructions to possibly trigger a page fault and fill the QEMU TLB. Cc: Leon Alrae Reported-by: Hervé Poussineau Tested-by: Hervé Poussineau Signed-off-by: Aurelien Jarno Signed-off-by: Leon Alrae --- target-mips/translate.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/target-mips/translate.c b/target-mips/translate.c index 4a1ffdbd94..d1de35ad30 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -2142,6 +2142,9 @@ static void gen_ld(DisasContext *ctx, uint32_t opc, break; case OPC_LDL: t1 = tcg_temp_new(); + /* Do a byte access to possibly trigger a page + fault with the unaligned address. */ + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); tcg_gen_andi_tl(t1, t0, 7); #ifndef TARGET_WORDS_BIGENDIAN tcg_gen_xori_tl(t1, t1, 7); @@ -2163,6 +2166,9 @@ static void gen_ld(DisasContext *ctx, uint32_t opc, break; case OPC_LDR: t1 = tcg_temp_new(); + /* Do a byte access to possibly trigger a page + fault with the unaligned address. */ + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); tcg_gen_andi_tl(t1, t0, 7); #ifdef TARGET_WORDS_BIGENDIAN tcg_gen_xori_tl(t1, t1, 7); @@ -2229,6 +2235,9 @@ static void gen_ld(DisasContext *ctx, uint32_t opc, break; case OPC_LWL: t1 = tcg_temp_new(); + /* Do a byte access to possibly trigger a page + fault with the unaligned address. */ + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); tcg_gen_andi_tl(t1, t0, 3); #ifndef TARGET_WORDS_BIGENDIAN tcg_gen_xori_tl(t1, t1, 3); @@ -2251,6 +2260,9 @@ static void gen_ld(DisasContext *ctx, uint32_t opc, break; case OPC_LWR: t1 = tcg_temp_new(); + /* Do a byte access to possibly trigger a page + fault with the unaligned address. */ + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); tcg_gen_andi_tl(t1, t0, 3); #ifdef TARGET_WORDS_BIGENDIAN tcg_gen_xori_tl(t1, t1, 3);