All of lore.kernel.org
 help / color / mirror / Atom feed
From: Anup Patel <anup@brainfault.org>
To: Alistair Francis <alistair23@gmail.com>
Cc: Anup Patel <apatel@ventanamicro.com>,
	Peter Maydell <peter.maydell@linaro.org>,
	 Palmer Dabbelt <palmer@dabbelt.com>,
	Alistair Francis <Alistair.Francis@wdc.com>,
	 Sagar Karandikar <sagark@eecs.berkeley.edu>,
	Atish Patra <atishp@atishpatra.org>,
	 "open list:RISC-V" <qemu-riscv@nongnu.org>,
	 "qemu-devel@nongnu.org Developers" <qemu-devel@nongnu.org>
Subject: Re: [PATCH v3 3/4] target/riscv: Update [m|h]tinst CSR in riscv_cpu_do_interrupt()
Date: Tue, 7 Jun 2022 08:31:38 +0530	[thread overview]
Message-ID: <CAAhSdy2SmVF=iswGuZkteBtFtjWhHwg6TdgbRGOL4KVEx5cvuQ@mail.gmail.com> (raw)
In-Reply-To: <CAKmqyKPrnd80=xk=scf+-Wags8hR6NGSu4P8kH_fUpcELUVkiQ@mail.gmail.com>

On Mon, Jun 6, 2022 at 7:23 AM Alistair Francis <alistair23@gmail.com> wrote:
>
> On Mon, Jun 6, 2022 at 11:48 AM Alistair Francis <alistair23@gmail.com> wrote:
> >
> > On Thu, May 26, 2022 at 8:12 PM Anup Patel <apatel@ventanamicro.com> wrote:
> > >
> > > We should write transformed instruction encoding of the trapped
> > > instruction in [m|h]tinst CSR at time of taking trap as defined
> > > by the RISC-V privileged specification v1.12.
> > >
> > > Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> >
> > Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
>
> Whoops, I thought there was another patch. This doesn't seem to
> implemented the guest-page fault pseudoinstructions which can be
> generated while doing VS-stage translation

I did not understand. Which guest-page fault pseudo-instructions ?

Regards,
Anup

>
> Alistair
>
> >
> > Alistair
> >
> > > ---
> > >  target/riscv/cpu_helper.c | 210 +++++++++++++++++++++++++++++++++++++-
> > >  target/riscv/instmap.h    |  43 ++++++++
> > >  2 files changed, 249 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> > > index d99fac9d2d..2a2b6776fb 100644
> > > --- a/target/riscv/cpu_helper.c
> > > +++ b/target/riscv/cpu_helper.c
> > > @@ -22,6 +22,7 @@
> > >  #include "qemu/main-loop.h"
> > >  #include "cpu.h"
> > >  #include "exec/exec-all.h"
> > > +#include "instmap.h"
> > >  #include "tcg/tcg-op.h"
> > >  #include "trace.h"
> > >  #include "semihosting/common-semi.h"
> > > @@ -1316,6 +1317,200 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
> > >
> > >      return true;
> > >  }
> > > +
> > > +static target_ulong riscv_transformed_insn(CPURISCVState *env,
> > > +                                           target_ulong insn)
> > > +{
> > > +    bool xinsn_has_addr_offset = false;
> > > +    target_ulong xinsn = 0;
> > > +
> > > +    /*
> > > +     * Only Quadrant 0 and Quadrant 2 of RVC instruction space need to
> > > +     * be uncompressed. The Quadrant 1 of RVC instruction space need
> > > +     * not be transformed because these instructions won't generate
> > > +     * any load/store trap.
> > > +     */
> > > +
> > > +    if ((insn & 0x3) != 0x3) {
> > > +        /* Transform 16bit instruction into 32bit instruction */
> > > +        switch (GET_C_OP(insn)) {
> > > +        case OPC_RISC_C_OP_QUAD0: /* Quadrant 0 */
> > > +            switch (GET_C_FUNC(insn)) {
> > > +            case OPC_RISC_C_FUNC_FLD_LQ:
> > > +                if (riscv_cpu_xlen(env) != 128) { /* C.FLD (RV32/64) */
> > > +                    xinsn = OPC_RISC_FLD;
> > > +                    xinsn = SET_RD(xinsn, GET_C_RS2S(insn));
> > > +                    xinsn = SET_RS1(xinsn, GET_C_RS1S(insn));
> > > +                    xinsn = SET_I_IMM(xinsn, GET_C_LD_IMM(insn));
> > > +                    xinsn_has_addr_offset = true;
> > > +                }
> > > +                break;
> > > +            case OPC_RISC_C_FUNC_LW: /* C.LW */
> > > +                xinsn = OPC_RISC_LW;
> > > +                xinsn = SET_RD(xinsn, GET_C_RS2S(insn));
> > > +                xinsn = SET_RS1(xinsn, GET_C_RS1S(insn));
> > > +                xinsn = SET_I_IMM(xinsn, GET_C_LW_IMM(insn));
> > > +                xinsn_has_addr_offset = true;
> > > +                break;
> > > +            case OPC_RISC_C_FUNC_FLW_LD:
> > > +                if (riscv_cpu_xlen(env) == 32) { /* C.FLW (RV32) */
> > > +                    xinsn = OPC_RISC_FLW;
> > > +                    xinsn = SET_RD(xinsn, GET_C_RS2S(insn));
> > > +                    xinsn = SET_RS1(xinsn, GET_C_RS1S(insn));
> > > +                    xinsn = SET_I_IMM(xinsn, GET_C_LW_IMM(insn));
> > > +                    xinsn_has_addr_offset = true;
> > > +                } else { /* C.LD (RV64/RV128) */
> > > +                    xinsn = OPC_RISC_LD;
> > > +                    xinsn = SET_RD(xinsn, GET_C_RS2S(insn));
> > > +                    xinsn = SET_RS1(xinsn, GET_C_RS1S(insn));
> > > +                    xinsn = SET_I_IMM(xinsn, GET_C_LD_IMM(insn));
> > > +                    xinsn_has_addr_offset = true;
> > > +                }
> > > +                break;
> > > +            case OPC_RISC_C_FUNC_FSD_SQ:
> > > +                if (riscv_cpu_xlen(env) != 128) { /* C.FSD (RV32/64) */
> > > +                    xinsn = OPC_RISC_FSD;
> > > +                    xinsn = SET_RS2(xinsn, GET_C_RS2S(insn));
> > > +                    xinsn = SET_RS1(xinsn, GET_C_RS1S(insn));
> > > +                    xinsn = SET_S_IMM(xinsn, GET_C_SD_IMM(insn));
> > > +                    xinsn_has_addr_offset = true;
> > > +                }
> > > +                break;
> > > +            case OPC_RISC_C_FUNC_SW: /* C.SW */
> > > +                xinsn = OPC_RISC_SW;
> > > +                xinsn = SET_RS2(xinsn, GET_C_RS2S(insn));
> > > +                xinsn = SET_RS1(xinsn, GET_C_RS1S(insn));
> > > +                xinsn = SET_S_IMM(xinsn, GET_C_SW_IMM(insn));
> > > +                xinsn_has_addr_offset = true;
> > > +                break;
> > > +            case OPC_RISC_C_FUNC_FSW_SD:
> > > +                if (riscv_cpu_xlen(env) == 32) { /* C.FSW (RV32) */
> > > +                    xinsn = OPC_RISC_FSW;
> > > +                    xinsn = SET_RS2(xinsn, GET_C_RS2S(insn));
> > > +                    xinsn = SET_RS1(xinsn, GET_C_RS1S(insn));
> > > +                    xinsn = SET_S_IMM(xinsn, GET_C_SW_IMM(insn));
> > > +                    xinsn_has_addr_offset = true;
> > > +                } else { /* C.SD (RV64/RV128) */
> > > +                    xinsn = OPC_RISC_SD;
> > > +                    xinsn = SET_RS2(xinsn, GET_C_RS2S(insn));
> > > +                    xinsn = SET_RS1(xinsn, GET_C_RS1S(insn));
> > > +                    xinsn = SET_S_IMM(xinsn, GET_C_SD_IMM(insn));
> > > +                    xinsn_has_addr_offset = true;
> > > +                }
> > > +                break;
> > > +            default:
> > > +                break;
> > > +            }
> > > +            break;
> > > +        case OPC_RISC_C_OP_QUAD2: /* Quadrant 2 */
> > > +            switch (GET_C_FUNC(insn)) {
> > > +            case OPC_RISC_C_FUNC_FLDSP_LQSP:
> > > +                if (riscv_cpu_xlen(env) != 128) { /* C.FLDSP (RV32/64) */
> > > +                    xinsn = OPC_RISC_FLD;
> > > +                    xinsn = SET_RD(xinsn, GET_C_RD(insn));
> > > +                    xinsn = SET_RS1(xinsn, 2);
> > > +                    xinsn = SET_I_IMM(xinsn, GET_C_LDSP_IMM(insn));
> > > +                    xinsn_has_addr_offset = true;
> > > +                }
> > > +                break;
> > > +            case OPC_RISC_C_FUNC_LWSP: /* C.LWSP */
> > > +                xinsn = OPC_RISC_LW;
> > > +                xinsn = SET_RD(xinsn, GET_C_RD(insn));
> > > +                xinsn = SET_RS1(xinsn, 2);
> > > +                xinsn = SET_I_IMM(xinsn, GET_C_LWSP_IMM(insn));
> > > +                xinsn_has_addr_offset = true;
> > > +                break;
> > > +            case OPC_RISC_C_FUNC_FLWSP_LDSP:
> > > +                if (riscv_cpu_xlen(env) == 32) { /* C.FLWSP (RV32) */
> > > +                    xinsn = OPC_RISC_FLW;
> > > +                    xinsn = SET_RD(xinsn, GET_C_RD(insn));
> > > +                    xinsn = SET_RS1(xinsn, 2);
> > > +                    xinsn = SET_I_IMM(xinsn, GET_C_LWSP_IMM(insn));
> > > +                    xinsn_has_addr_offset = true;
> > > +                } else { /* C.LDSP (RV64/RV128) */
> > > +                    xinsn = OPC_RISC_LD;
> > > +                    xinsn = SET_RD(xinsn, GET_C_RD(insn));
> > > +                    xinsn = SET_RS1(xinsn, 2);
> > > +                    xinsn = SET_I_IMM(xinsn, GET_C_LDSP_IMM(insn));
> > > +                    xinsn_has_addr_offset = true;
> > > +                }
> > > +                break;
> > > +            case OPC_RISC_C_FUNC_FSDSP_SQSP:
> > > +                if (riscv_cpu_xlen(env) != 128) { /* C.FSDSP (RV32/64) */
> > > +                    xinsn = OPC_RISC_FSD;
> > > +                    xinsn = SET_RS2(xinsn, GET_C_RS2(insn));
> > > +                    xinsn = SET_RS1(xinsn, 2);
> > > +                    xinsn = SET_S_IMM(xinsn, GET_C_SDSP_IMM(insn));
> > > +                    xinsn_has_addr_offset = true;
> > > +                }
> > > +                break;
> > > +            case OPC_RISC_C_FUNC_SWSP: /* C.SWSP */
> > > +                xinsn = OPC_RISC_SW;
> > > +                xinsn = SET_RS2(xinsn, GET_C_RS2(insn));
> > > +                xinsn = SET_RS1(xinsn, 2);
> > > +                xinsn = SET_S_IMM(xinsn, GET_C_SWSP_IMM(insn));
> > > +                xinsn_has_addr_offset = true;
> > > +                break;
> > > +            case 7:
> > > +                if (riscv_cpu_xlen(env) == 32) { /* C.FSWSP (RV32) */
> > > +                    xinsn = OPC_RISC_FSW;
> > > +                    xinsn = SET_RS2(xinsn, GET_C_RS2(insn));
> > > +                    xinsn = SET_RS1(xinsn, 2);
> > > +                    xinsn = SET_S_IMM(xinsn, GET_C_SWSP_IMM(insn));
> > > +                    xinsn_has_addr_offset = true;
> > > +                } else { /* C.SDSP (RV64/RV128) */
> > > +                    xinsn = OPC_RISC_SD;
> > > +                    xinsn = SET_RS2(xinsn, GET_C_RS2(insn));
> > > +                    xinsn = SET_RS1(xinsn, 2);
> > > +                    xinsn = SET_S_IMM(xinsn, GET_C_SDSP_IMM(insn));
> > > +                    xinsn_has_addr_offset = true;
> > > +                }
> > > +                break;
> > > +            default:
> > > +                break;
> > > +            }
> > > +            break;
> > > +        default:
> > > +            break;
> > > +        }
> > > +
> > > +        /*
> > > +         * Clear Bit1 of transformed instruction to indicate that
> > > +         * original insruction was a 16bit instruction
> > > +         */
> > > +        xinsn &= ~((target_ulong)0x2);
> > > +    } else {
> > > +        /* No need to transform 32bit (or wider) instructions */
> > > +        xinsn = insn;
> > > +
> > > +        /* Check for instructions which need address offset */
> > > +        switch (MASK_OP_MAJOR(insn)) {
> > > +        case OPC_RISC_LOAD:
> > > +        case OPC_RISC_STORE:
> > > +        case OPC_RISC_ATOMIC:
> > > +        case OPC_RISC_FP_LOAD:
> > > +        case OPC_RISC_FP_STORE:
> > > +             xinsn_has_addr_offset = true;
> > > +             break;
> > > +        case OPC_RISC_SYSTEM:
> > > +             if (MASK_OP_SYSTEM(insn) == OPC_RISC_HLVHSV) {
> > > +                 xinsn_has_addr_offset = true;
> > > +             }
> > > +             break;
> > > +        }
> > > +    }
> > > +
> > > +    if (xinsn_has_addr_offset) {
> > > +        /*
> > > +         * The "Addr. Offset" field in transformed instruction is non-zero
> > > +         * only for misaligned load/store traps which are very unlikely on
> > > +         * QEMU so for now always set "Addr. Offset" to zero.
> > > +         */
> > > +        xinsn = SET_RS1(xinsn, 0);
> > > +    }
> > > +
> > > +    return xinsn;
> > > +}
> > >  #endif /* !CONFIG_USER_ONLY */
> > >
> > >  /*
> > > @@ -1340,6 +1535,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> > >      target_ulong cause = cs->exception_index & RISCV_EXCP_INT_MASK;
> > >      uint64_t deleg = async ? env->mideleg : env->medeleg;
> > >      target_ulong tval = 0;
> > > +    target_ulong tinst = 0;
> > >      target_ulong htval = 0;
> > >      target_ulong mtval2 = 0;
> > >
> > > @@ -1355,18 +1551,22 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> > >      if (!async) {
> > >          /* set tval to badaddr for traps with address information */
> > >          switch (cause) {
> > > -        case RISCV_EXCP_INST_GUEST_PAGE_FAULT:
> > >          case RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT:
> > >          case RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT:
> > > -        case RISCV_EXCP_INST_ADDR_MIS:
> > > -        case RISCV_EXCP_INST_ACCESS_FAULT:
> > >          case RISCV_EXCP_LOAD_ADDR_MIS:
> > >          case RISCV_EXCP_STORE_AMO_ADDR_MIS:
> > >          case RISCV_EXCP_LOAD_ACCESS_FAULT:
> > >          case RISCV_EXCP_STORE_AMO_ACCESS_FAULT:
> > > -        case RISCV_EXCP_INST_PAGE_FAULT:
> > >          case RISCV_EXCP_LOAD_PAGE_FAULT:
> > >          case RISCV_EXCP_STORE_PAGE_FAULT:
> > > +            write_gva = env->two_stage_lookup;
> > > +            tval = env->badaddr;
> > > +            tinst = riscv_transformed_insn(env, env->bins);
> > > +            break;
> > > +        case RISCV_EXCP_INST_GUEST_PAGE_FAULT:
> > > +        case RISCV_EXCP_INST_ADDR_MIS:
> > > +        case RISCV_EXCP_INST_ACCESS_FAULT:
> > > +        case RISCV_EXCP_INST_PAGE_FAULT:
> > >              write_gva = env->two_stage_lookup;
> > >              tval = env->badaddr;
> > >              break;
> > > @@ -1448,6 +1648,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> > >          env->sepc = env->pc;
> > >          env->stval = tval;
> > >          env->htval = htval;
> > > +        env->htinst = tinst;
> > >          env->pc = (env->stvec >> 2 << 2) +
> > >              ((async && (env->stvec & 3) == 1) ? cause * 4 : 0);
> > >          riscv_cpu_set_mode(env, PRV_S);
> > > @@ -1478,6 +1679,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> > >          env->mepc = env->pc;
> > >          env->mtval = tval;
> > >          env->mtval2 = mtval2;
> > > +        env->mtinst = tinst;
> > >          env->pc = (env->mtvec >> 2 << 2) +
> > >              ((async && (env->mtvec & 3) == 1) ? cause * 4 : 0);
> > >          riscv_cpu_set_mode(env, PRV_M);
> > > diff --git a/target/riscv/instmap.h b/target/riscv/instmap.h
> > > index 40b6d2b64d..f564a69d90 100644
> > > --- a/target/riscv/instmap.h
> > > +++ b/target/riscv/instmap.h
> > > @@ -184,6 +184,8 @@ enum {
> > >      OPC_RISC_CSRRWI      = OPC_RISC_SYSTEM | (0x5 << 12),
> > >      OPC_RISC_CSRRSI      = OPC_RISC_SYSTEM | (0x6 << 12),
> > >      OPC_RISC_CSRRCI      = OPC_RISC_SYSTEM | (0x7 << 12),
> > > +
> > > +    OPC_RISC_HLVHSV      = OPC_RISC_SYSTEM | (0x4 << 12),
> > >  };
> > >
> > >  #define MASK_OP_FP_LOAD(op)   (MASK_OP_MAJOR(op) | (op & (0x7 << 12)))
> > > @@ -316,6 +318,12 @@ enum {
> > >  #define GET_RS2(inst)  extract32(inst, 20, 5)
> > >  #define GET_RD(inst)   extract32(inst, 7, 5)
> > >  #define GET_IMM(inst)  sextract64(inst, 20, 12)
> > > +#define SET_RS1(inst, val)  deposit32(inst, 15, 5, val)
> > > +#define SET_RS2(inst, val)  deposit32(inst, 20, 5, val)
> > > +#define SET_RD(inst, val)   deposit32(inst, 7, 5, val)
> > > +#define SET_I_IMM(inst, val)  deposit32(inst, 20, 12, val)
> > > +#define SET_S_IMM(inst, val)  \
> > > +    deposit32(deposit32(inst, 7, 5, val), 25, 7, (val) >> 5)
> > >
> > >  /* RVC decoding macros */
> > >  #define GET_C_IMM(inst)             (extract32(inst, 2, 5) \
> > > @@ -346,6 +354,8 @@ enum {
> > >                                      | (extract32(inst, 5, 1) << 6))
> > >  #define GET_C_LD_IMM(inst)          ((extract16(inst, 10, 3) << 3) \
> > >                                      | (extract16(inst, 5, 2) << 6))
> > > +#define GET_C_SW_IMM(inst)          GET_C_LW_IMM(inst)
> > > +#define GET_C_SD_IMM(inst)          GET_C_LD_IMM(inst)
> > >  #define GET_C_J_IMM(inst)           ((extract32(inst, 3, 3) << 1) \
> > >                                      | (extract32(inst, 11, 1) << 4) \
> > >                                      | (extract32(inst, 2, 1) << 5) \
> > > @@ -366,4 +376,37 @@ enum {
> > >  #define GET_C_RS1S(inst)            (8 + extract16(inst, 7, 3))
> > >  #define GET_C_RS2S(inst)            (8 + extract16(inst, 2, 3))
> > >
> > > +#define GET_C_FUNC(inst)           extract32(inst, 13, 3)
> > > +#define GET_C_OP(inst)             extract32(inst, 0, 2)
> > > +
> > > +enum {
> > > +    /* RVC Quadrants */
> > > +    OPC_RISC_C_OP_QUAD0 = 0x0,
> > > +    OPC_RISC_C_OP_QUAD1 = 0x1,
> > > +    OPC_RISC_C_OP_QUAD2 = 0x2
> > > +};
> > > +
> > > +enum {
> > > +    /* RVC Quadrant 0 */
> > > +    OPC_RISC_C_FUNC_ADDI4SPN = 0x0,
> > > +    OPC_RISC_C_FUNC_FLD_LQ = 0x1,
> > > +    OPC_RISC_C_FUNC_LW = 0x2,
> > > +    OPC_RISC_C_FUNC_FLW_LD = 0x3,
> > > +    OPC_RISC_C_FUNC_FSD_SQ = 0x5,
> > > +    OPC_RISC_C_FUNC_SW = 0x6,
> > > +    OPC_RISC_C_FUNC_FSW_SD = 0x7
> > > +};
> > > +
> > > +enum {
> > > +    /* RVC Quadrant 2 */
> > > +    OPC_RISC_C_FUNC_SLLI_SLLI64 = 0x0,
> > > +    OPC_RISC_C_FUNC_FLDSP_LQSP = 0x1,
> > > +    OPC_RISC_C_FUNC_LWSP = 0x2,
> > > +    OPC_RISC_C_FUNC_FLWSP_LDSP = 0x3,
> > > +    OPC_RISC_C_FUNC_JR_MV_EBREAK_JALR_ADD = 0x4,
> > > +    OPC_RISC_C_FUNC_FSDSP_SQSP = 0x5,
> > > +    OPC_RISC_C_FUNC_SWSP = 0x6,
> > > +    OPC_RISC_C_FUNC_FSWSP_SDSP = 0x7
> > > +};
> > > +
> > >  #endif
> > > --
> > > 2.34.1
> > >
> > >


  reply	other threads:[~2022-06-07  3:10 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-26 10:05 [PATCH v3 0/4] QEMU RISC-V nested virtualization fixes Anup Patel
2022-05-26 10:05 ` [PATCH v3 1/4] target/riscv: Don't force update priv spec version to latest Anup Patel
2022-05-26 10:05 ` [PATCH v3 2/4] target/riscv: Add dummy mcountinhibit CSR for priv spec v1.11 or higher Anup Patel
2022-05-26 10:05 ` [PATCH v3 3/4] target/riscv: Update [m|h]tinst CSR in riscv_cpu_do_interrupt() Anup Patel
2022-06-06  1:48   ` Alistair Francis
2022-06-06  1:53     ` Alistair Francis
2022-06-07  3:01       ` Anup Patel [this message]
2022-06-07  3:04         ` Anup Patel
2022-05-26 10:05 ` [PATCH v3 4/4] target/riscv: Force disable extensions if priv spec version does not match Anup Patel
2022-06-06  1:55   ` Alistair Francis
2022-06-07  2:50     ` Anup Patel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAAhSdy2SmVF=iswGuZkteBtFtjWhHwg6TdgbRGOL4KVEx5cvuQ@mail.gmail.com' \
    --to=anup@brainfault.org \
    --cc=Alistair.Francis@wdc.com \
    --cc=alistair23@gmail.com \
    --cc=apatel@ventanamicro.com \
    --cc=atishp@atishpatra.org \
    --cc=palmer@dabbelt.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-riscv@nongnu.org \
    --cc=sagark@eecs.berkeley.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.