[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-ppc] [PATCH 21/77] ppc: Rework generation of priv and inval in
From: |
Benjamin Herrenschmidt |
Subject: |
Re: [Qemu-ppc] [PATCH 21/77] ppc: Rework generation of priv and inval interrupts |
Date: |
Tue, 24 Nov 2015 11:44:36 +1100 |
On Fri, 2015-11-20 at 18:45 +1100, David Gibson wrote:
>
> So, I'm not 100% following the logic below, but it looks like the
> existing code used SPR_NOACCESS to mark things which generated a
> privilege exception compared to NULL for things which generated an
> invalid instruction exception. Using that encoding, can you simplify
> the logic here? Alternatively can you use the logic here to avoid
> the SPR_NOACESS encoding?
Well, so the SPR_NOACCESS has to do with how you react to a known SPR
who has explicit access permissions. The logic below is described in
the ISA for an unknown SPR number.
I don't know whether the access permission of "known" SPRs always
honor the 0x10 bit trick, and changing that in qemu would be a
fairly large patch. So I'd rather stick to the logic here for
"unknown" SPRs which matches the ISA definition.
I'll update the patch though for arch 2.07 as it defines a few
reserved SPRs as no-ops.
However:
> > - gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
> > +
> > + /* The behaviour depends on MSR:PR and SPR# bit 0x10,
> > + * it can generate a priv, a hv emu or a no-op
> > + */
> > + if (sprn & 0x10) {
> > + if (ctx->pr) {
> > + gen_priv_exception(ctx, POWERPC_EXCP_INVAL_SPR);
> > + }
> > + } else {
> > + if (ctx->pr || sprn == 0 || sprn == 4 || sprn == 5 ||
> > sprn == 6) {
> > + gen_hvpriv_exception(ctx, POWERPC_EXCP_INVAL_SPR);
> > + }
> > + }
> > +#if !defined(CONFIG_USER_ONLY)
> > + /* HV priv */
> > + if (ctx->spr_cb[sprn].hea_read) {
> > + gen_priv_exception(ctx, POWERPC_EXCP_INVAL_SPR);
> > + }
That latest bit is bogus.
> If you're in PR mode, and it's an SPR with an hea_read function and
> has the 0x10 bit set, won't this call gen_priv_exception twice?
Yes, I've removed it. It should be handled by the SPR_NOACCESS.
> I also see no path here which will call gen_inval_exception(), is
> that
> right? If you're in HV mode and it's a truly invalid SPRN, isn't
> that
> what you'd want?
No, the ISA says it's a nop.
Cheers,
Ben.
> > +#endif
> > }
> > }
>
>
>
> >
> > @@ -4395,13 +4423,9 @@ static void gen_mtcrf(DisasContext *ctx)
> > #if defined(TARGET_PPC64)
> > static void gen_mtmsrd(DisasContext *ctx)
> > {
> > -#if defined(CONFIG_USER_ONLY)
> > - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
> > -#else
> > - if (unlikely(ctx->pr)) {
> > - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
> > - return;
> > - }
> > + CHK_SV;
> > +
> > +#if !defined(CONFIG_USER_ONLY)
> > if (ctx->opcode & 0x00010000) {
> > /* Special form that does not need any synchronisation */
> > TCGv t0 = tcg_temp_new();
> > @@ -4420,20 +4444,16 @@ static void gen_mtmsrd(DisasContext *ctx)
> > /* Note that mtmsr is not always defined as context-
> > synchronizing */
> > gen_stop_exception(ctx);
> > }
> > -#endif
> > +#endif /* !defined(CONFIG_USER_ONLY) */
> > }
> > -#endif
> > +#endif /* defined(TARGET_PPC64) */
> >
> > static void gen_mtmsr(DisasContext *ctx)
> > {
> > -#if defined(CONFIG_USER_ONLY)
> > - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
> > -#else
> > - if (unlikely(ctx->pr)) {
> > - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
> > - return;
> > - }
> > - if (ctx->opcode & 0x00010000) {
> > + CHK_SV;
> > +
> > +#if !defined(CONFIG_USER_ONLY)
> > + if (ctx->opcode & 0x00010000) {
> > /* Special form that does not need any synchronisation */
> > TCGv t0 = tcg_temp_new();
> > tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 <<
> > MSR_RI) | (1 << MSR_EE));
> > @@ -4488,7 +4508,7 @@ static void gen_mtspr(DisasContext *ctx)
> > TARGET_FMT_lx "\n", sprn, sprn, ctx->nip -
> > 4);
> > printf("Trying to write privileged spr %d (0x%03x) at
> > "
> > TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
> > - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
> > + gen_priv_exception(ctx, POWERPC_EXCP_PRIV_REG);
> > }
> > } else {
> > /* Not defined */
> > @@ -4496,7 +4516,25 @@ static void gen_mtspr(DisasContext *ctx)
> > TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
> > printf("Trying to write invalid spr %d (0x%03x) at "
> > TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
> > - gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
> > +
> > + /* The behaviour depends on MSR:PR and SPR# bit 0x10,
> > + * it can generate a priv, a hv emu or a no-op
> > + */
> > + if (sprn & 0x10) {
> > + if (ctx->pr) {
> > + gen_priv_exception(ctx, POWERPC_EXCP_INVAL_SPR);
> > + }
> > + } else {
> > + if (ctx->pr || sprn == 0) {
> > + gen_hvpriv_exception(ctx, POWERPC_EXCP_INVAL_SPR);
> > + }
> > + }
> > +#if !defined(CONFIG_USER_ONLY)
> > + /* HV priv */
> > + if (ctx->spr_cb[sprn].hea_write) {
> > + gen_priv_exception(ctx, POWERPC_EXCP_INVAL_SPR);
> > + }
> > +#endif
>
> Same concerns here as for mfspr.
>
> [snip]
> > /* tlbiel */
> > static void gen_tlbiel(DisasContext *ctx)
> > {
> > #if defined(CONFIG_USER_ONLY)
> > - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
> > + GEN_PRIV;
> > #else
> > - if (unlikely(ctx->pr || !ctx->hv)) {
> > - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
> > - return;
> > - }
> > + CHK_SV;
>
> You have CHK_SV here, but the original code checks for HV, as does
> your new code for tlbia and tlbiel, is that right?
>
> [snip]
> > /* tlbsync */
> > static void gen_tlbsync(DisasContext *ctx)
> > {
> > #if defined(CONFIG_USER_ONLY)
> > - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
> > -#else
> > - if (unlikely(ctx->pr)) {
> > - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
> > - return;
> > - }
> > + GEN_PRIV;
> > +#else
> > + CHK_HV;
> > +
>
> Old code didn't check for HV, mode, but AFAICT it should have, so
> this
> looks correct.
>
> [snip]
> > @@ -5941,18 +5921,16 @@ static void gen_mfapidi(DisasContext *ctx)
> > static void gen_tlbiva(DisasContext *ctx)
> > {
> > #if defined(CONFIG_USER_ONLY)
> > - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
> > + GEN_PRIV;
> > #else
> > TCGv t0;
> > - if (unlikely(ctx->pr)) {
> > - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
> > - return;
> > - }
> > +
> > + CHK_SV;
>
> Is the same thing as tlbivax, or some ancient instruction? AFAICT
> the
> ISA says tlbivax is hypervisor privileged.
>
> > t0 = tcg_temp_new();
> > gen_addr_reg_index(ctx, t0);
> > gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
> > tcg_temp_free(t0);
> > -#endif
> > +#endif /* defined(CONFIG_USER_ONLY) */
> > }
>
> [snip]
> > static void gen_tlbivax_booke206(DisasContext *ctx)
> > {
> > #if defined(CONFIG_USER_ONLY)
> > - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
> > + GEN_PRIV;
> > #else
> > TCGv t0;
> > - if (unlikely(ctx->pr)) {
> > - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
> > - return;
> > - }
> >
> > + CHK_SV;
>
> ISA says tlbivax is hypervisor privileged when the CPU has a
> hypervisor mode, which I guess booke206 probably doesn't?
>
> > t0 = tcg_temp_new();
> > gen_addr_reg_index(ctx, t0);
> > -
> > gen_helper_booke206_tlbivax(cpu_env, t0);
> > tcg_temp_free(t0);
> > -#endif
> > +#endif /* defined(CONFIG_USER_ONLY) */
> > }
> >
> > static void gen_tlbilx_booke206(DisasContext *ctx)
> > {
> > #if defined(CONFIG_USER_ONLY)
> > - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
> > + GEN_PRIV;
> > #else
> > TCGv t0;
> > - if (unlikely(ctx->pr)) {
> > - gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
> > - return;
> > - }
> >
> > + CHK_SV;
>
> And apparently hv vs. sv privilege of tlbilx depends on the EPCR
> register. Again, may not be relevant for 2.06.
>
> > t0 = tcg_temp_new();
> > gen_addr_reg_index(ctx, t0);
> >
> > @@ -6672,7 +6574,7 @@ static void gen_tlbilx_booke206(DisasContext
> > *ctx)
> > }
> >
> > tcg_temp_free(t0);
> > -#endif
> > +#endif /* defined(CONFIG_USER_ONLY) */
> > }
>
- Re: [Qemu-ppc] [PATCH 13/77] ppc: tlbie, tlbia and tlbisync are HV only, (continued)
[Qemu-ppc] [PATCH 28/77] ppc/xics: Rename existing XICS classe to XICS_SPAPR, Benjamin Herrenschmidt, 2015/11/10
[Qemu-ppc] [PATCH 25/77] ppc: Add P7/P8 Power Management instructions, Benjamin Herrenschmidt, 2015/11/10
[Qemu-ppc] [PATCH 30/77] ppc/xics: Implement H_IPOLL using an accessor, Benjamin Herrenschmidt, 2015/11/10
[Qemu-ppc] [PATCH 31/77] ppc/xics: Remove unused xics_set_irq_type(), Benjamin Herrenschmidt, 2015/11/10