From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37480) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aiwuO-0002K6-Qt for qemu-devel@nongnu.org; Thu, 24 Mar 2016 00:30:17 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aiwuE-00072W-7q for qemu-devel@nongnu.org; Thu, 24 Mar 2016 00:30:08 -0400 From: David Gibson Date: Thu, 24 Mar 2016 15:30:51 +1100 Message-Id: <1458793858-4010-10-git-send-email-david@gibson.dropbear.id.au> In-Reply-To: <1458793858-4010-1-git-send-email-david@gibson.dropbear.id.au> References: <1458793858-4010-1-git-send-email-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Subject: [Qemu-devel] [PULL 09/16] ppc: Fix writing to AMR/UAMOR List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: peter.maydell@linaro.org Cc: thuth@redhat.com, agraf@suse.de, qemu-devel@nongnu.org, clg@fr.ibm.com, qemu-ppc@nongnu.org, David Gibson From: Benjamin Herrenschmidt The masks weren't chosen nor applied properly. The architecture specifies that writes to AMR are masked by UAMOR for PR=3D1, otherwise AMOR for HV=3D= 0. The writes to UAMOR are masked by AMOR for HV=3D0 Signed-off-by: Benjamin Herrenschmidt [clg: moved gen_spr_amr() prototype change to next patch ] Signed-off-by: C=C3=A9dric Le Goater Reviewed-by: Thomas Huth Reviewed-by: David Gibson Signed-off-by: David Gibson --- target-ppc/translate_init.c | 74 ++++++++++++++++++++++++++++++++++++---= ------ 1 file changed, 59 insertions(+), 15 deletions(-) diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 5125743..a5b59e7 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -1063,26 +1063,68 @@ static void gen_spr_7xx (CPUPPCState *env) =20 #ifdef TARGET_PPC64 #ifndef CONFIG_USER_ONLY -static void spr_read_uamr (DisasContext *ctx, int gprn, int sprn) +static void spr_write_amr(DisasContext *ctx, int sprn, int gprn) { - gen_load_spr(cpu_gpr[gprn], SPR_AMR); - spr_load_dump_spr(SPR_AMR); -} + TCGv t0 =3D tcg_temp_new(); + TCGv t1 =3D tcg_temp_new(); + TCGv t2 =3D tcg_temp_new(); =20 -static void spr_write_uamr (DisasContext *ctx, int sprn, int gprn) -{ - gen_store_spr(SPR_AMR, cpu_gpr[gprn]); + /* Note, the HV=3D1 PR=3D0 case is handled earlier by simply using + * spr_write_generic for HV mode in the SPR table + */ + + /* Build insertion mask into t1 based on context */ + if (ctx->pr) { + gen_load_spr(t1, SPR_UAMOR); + } else { + gen_load_spr(t1, SPR_AMOR); + } + + /* Mask new bits into t2 */ + tcg_gen_and_tl(t2, t1, cpu_gpr[gprn]); + + /* Load AMR and clear new bits in t0 */ + gen_load_spr(t0, SPR_AMR); + tcg_gen_andc_tl(t0, t0, t1); + + /* Or'in new bits and write it out */ + tcg_gen_or_tl(t0, t0, t2); + gen_store_spr(SPR_AMR, t0); spr_store_dump_spr(SPR_AMR); + + tcg_temp_free(t0); + tcg_temp_free(t1); + tcg_temp_free(t2); } =20 -static void spr_write_uamr_pr (DisasContext *ctx, int sprn, int gprn) +static void spr_write_uamor(DisasContext *ctx, int sprn, int gprn) { TCGv t0 =3D tcg_temp_new(); + TCGv t1 =3D tcg_temp_new(); + TCGv t2 =3D tcg_temp_new(); + + /* Note, the HV=3D1 case is handled earlier by simply using + * spr_write_generic for HV mode in the SPR table + */ =20 + /* Build insertion mask into t1 based on context */ + gen_load_spr(t1, SPR_AMOR); + + /* Mask new bits into t2 */ + tcg_gen_and_tl(t2, t1, cpu_gpr[gprn]); + + /* Load AMR and clear new bits in t0 */ gen_load_spr(t0, SPR_UAMOR); - tcg_gen_and_tl(t0, t0, cpu_gpr[gprn]); - gen_store_spr(SPR_AMR, t0); - spr_store_dump_spr(SPR_AMR); + tcg_gen_andc_tl(t0, t0, t1); + + /* Or'in new bits and write it out */ + tcg_gen_or_tl(t0, t0, t2); + gen_store_spr(SPR_UAMOR, t0); + spr_store_dump_spr(SPR_UAMOR); + + tcg_temp_free(t0); + tcg_temp_free(t1); + tcg_temp_free(t2); } #endif /* CONFIG_USER_ONLY */ =20 @@ -1094,15 +1136,17 @@ static void gen_spr_amr (CPUPPCState *env) * userspace accessible, 29 is privileged. So we only need to set * the kvm ONE_REG id on one of them, we use 29 */ spr_register(env, SPR_UAMR, "UAMR", - &spr_read_uamr, &spr_write_uamr_pr, - &spr_read_uamr, &spr_write_uamr, + &spr_read_generic, &spr_write_amr, + &spr_read_generic, &spr_write_amr, 0); - spr_register_kvm(env, SPR_AMR, "AMR", + spr_register_kvm_hv(env, SPR_AMR, "AMR", SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_amr, &spr_read_generic, &spr_write_generic, KVM_REG_PPC_AMR, 0); - spr_register_kvm(env, SPR_UAMOR, "UAMOR", + spr_register_kvm_hv(env, SPR_UAMOR, "UAMOR", SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_uamor, &spr_read_generic, &spr_write_generic, KVM_REG_PPC_UAMOR, 0); spr_register_hv(env, SPR_AMOR, "AMOR", --=20 2.5.5