xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Julien Grall <julien.grall@citrix.com>
To: vijay.kilari@gmail.com, Ian.Campbell@citrix.com,
	stefano.stabellini@eu.citrix.com, stefano.stabellini@citrix.com,
	tim@xen.org, xen-devel@lists.xen.org
Cc: Prasun.Kapoor@caviumnetworks.com,
	manish.jaggi@caviumnetworks.com,
	Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
Subject: Re: [PATCH v5 10/22] xen/arm: ITS: Add GITS registers emulation
Date: Tue, 28 Jul 2015 20:01:06 +0100	[thread overview]
Message-ID: <55B7D172.4020704@citrix.com> (raw)
In-Reply-To: <1437995524-19772-11-git-send-email-vijay.kilari@gmail.com>

Hi Vijay,

On 27/07/15 12:11, vijay.kilari@gmail.com wrote:
> From: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
> 
> Emulate GITS* registers
> 
> Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
> ---
> v4: - Removed GICR register emulation
> ---
>  xen/arch/arm/irq.c            |    3 +
>  xen/arch/arm/vgic-v3-its.c    |  365 ++++++++++++++++++++++++++++++++++++++++-
>  xen/include/asm-arm/gic-its.h |   15 ++
>  xen/include/asm-arm/gic.h     |    1 +
>  4 files changed, 381 insertions(+), 3 deletions(-)
> 
> diff --git a/xen/arch/arm/irq.c b/xen/arch/arm/irq.c
> index 1f38605..85cacb0 100644
> --- a/xen/arch/arm/irq.c
> +++ b/xen/arch/arm/irq.c
> @@ -31,6 +31,9 @@
>  static unsigned int local_irqs_type[NR_LOCAL_IRQS];
>  static DEFINE_SPINLOCK(local_irqs_type_lock);
>  
> +/* Number of LPI supported in XEN */
> +unsigned int num_of_lpis = 8192;
> +

It makes little sense to introduce the support of LPIs in Xen in a patch
called "Add GITS registers emulation".

This should go in a specific ITS (not vITS) patch.

Furthermore, you need to explain where to the 8192 comes from...

Lastly I would rename num_of_lpis into nr_lpis.

>  /* Describe an IRQ assigned to a guest */
>  struct irq_guest
>  {
> diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c
> index 3a003d4..1c7d9b6 100644
> --- a/xen/arch/arm/vgic-v3-its.c
> +++ b/xen/arch/arm/vgic-v3-its.c
> @@ -33,8 +33,16 @@
>  #include <asm/atomic.h>
>  #include <xen/log2.h>
>  
> -#define DEBUG_ITS
> -
> +//#define DEBUG_ITS
> +

This change should go in patch #8.

> +/* GITS_PIDRn register values for ARM implementations */
> +#define GITS_PIDR0_VAL               (0x94)
> +#define GITS_PIDR1_VAL               (0xb4)
> +#define GITS_PIDR2_VAL               (0x3b)
> +#define GITS_PIDR3_VAL               (0x00)
> +#define GITS_PIDR4_VAL               (0x04)
> +#define GITS_BASER_INIT_VAL          ((1UL << GITS_BASER_TYPE_SHIFT) | \
> +                                     (0x7UL << GITS_BASER_ENTRY_SIZE_SHIFT))
>  #ifdef DEBUG_ITS
>  # define DPRINTK(fmt, args...) dprintk(XENLOG_DEBUG, fmt, ##args)
>  #else
> @@ -60,6 +68,14 @@ void vits_setup_hw(struct gic_its_info *its_info)
>      vits_hw.info = its_info;
>  }
>  
> +static inline uint32_t vits_get_max_collections(struct domain *d)
> +{
> +    /* Collection ID is only 16 bit */

16 bit = 65536 not 256.

You need to explain that the ITS is only supporting 256 collections in
hardware and that our implementation doesn't support memory provisioning
for collection.

Furthermore if the number of collection is based on 16 bits, the
function should return uint16_t not uint32_t.


> +    ASSERT(d->max_vcpus < 256);
> +

Please add a comment to explain why d->max_vcpus + 1 with may a
reference to the public spec.

> +    return (d->max_vcpus + 1);
> +}
> +
>  static int vits_access_guest_table(struct domain *d, paddr_t entry, void *addr,
>                                     uint32_t size, bool_t set)
>  {
> @@ -502,7 +518,7 @@ static int vits_read_virt_cmd(struct vcpu *v, struct vgic_its *vits,
>      return 0;
>  }
>  
> -int vits_process_cmd(struct vcpu *v, struct vgic_its *vits)
> +static int vits_process_cmd(struct vcpu *v, struct vgic_its *vits)

Please, Move the static where the function has been defined.

>  {
>      its_cmd_block virt_cmd;
>  
> @@ -527,11 +543,338 @@ err:
>      return 0;
>  }

[..]

> +static int vgic_v3_gits_mmio_read(struct vcpu *v, mmio_info_t *info)
> +{
> +    struct vgic_its *vits = v->domain->arch.vgic.vits;
> +    struct hsr_dabt dabt = info->dabt;
> +    struct cpu_user_regs *regs = guest_cpu_user_regs();
> +    register_t *r = select_user_reg(regs, dabt.reg);
> +    uint64_t val = 0;
> +    uint32_t gits_reg;
> +
> +    gits_reg = info->gpa - vits->gits_base;
> +    DPRINTK("%pv: vITS: GITS_MMIO_READ offset 0x%"PRIx32"\n", v, gits_reg);
> +
> +    switch ( gits_reg )
> +    {
> +    case GITS_CTLR:
> +        if ( dabt.size != DABT_WORD ) goto bad_width;
> +        vits_spin_lock(vits);
> +        *r = vits->ctrl | GITS_CTLR_QUIESCENT;

Why did you put GITS_CTLR_QUIESCENT?

> +        vits_spin_unlock(vits);
> +        return 1;
> +    case GITS_IIDR:
> +        if ( dabt.size != DABT_WORD ) goto bad_width;
> +        *r = GICV3_GICD_IIDR_VAL;
> +        return 1;
> +    case GITS_TYPER:
> +    case GITS_TYPER + 4:
> +        /*
> +         * GITS_TYPER.HCC = max_vcpus + 1 (max collection supported )
> +         * GITS_TYPER.Devbits = HW supported Devbits size
> +         * GITS_TYPER.IDbits = HW supported IDbits size
> +         * GITS_TYPER.PTA = 0 ( Target addresses are linear processor numbers

Missing )

> +         * GITS_TYPER.ITTSize = Size of struct vitt
> +         * GITS_TYPER.Physical = 1
> +         */
> +        if ( dabt.size != DABT_DOUBLE_WORD &&
> +             dabt.size != DABT_WORD ) goto bad_width;
> +        val = ((vits_get_max_collections(v->domain) << GITS_TYPER_HCC_SHIFT ) |
> +               ((vits_hw.info->dev_bits - 1) << GITS_TYPER_DEVBITS_SHIFT)     |
> +               ((vits_hw.info->eventid_bits - 1) << GITS_TYPER_IDBITS_SHIFT)  |
> +               ((sizeof(struct vitt) - 1) << GITS_TYPER_ITT_SIZE_SHIFT)       |
> +                 GITS_TYPER_PHYSICAL_LPIS);
> +        if ( dabt.size == DABT_DOUBLE_WORD )
> +            *r = val;
> +        else
> +            *r = vits_get_word(gits_reg, val);
> +        return 1;
> +    case 0x0010 ... 0x007c:
> +    case 0xc000 ... 0xffcc:
> +        /* Implementation defined -- read ignored */
> +        goto read_as_zero;
> +    case GITS_CBASER:
> +    case GITS_CBASER + 4:
> +        /* Only read support 32/64-bit access */

"Read supports only 32/64-bit access"

> +        if ( dabt.size != DABT_DOUBLE_WORD &&
> +             dabt.size != DABT_WORD ) goto bad_width;
> +        vits_spin_lock(vits);
> +        if ( dabt.size == DABT_DOUBLE_WORD )
> +            *r = vits->cmd_base;
> +        else
> +            *r = vits_get_word(gits_reg, vits->cmd_base);
> +        vits_spin_unlock(vits);
> +        return 1;
> +    case GITS_CWRITER:
> +        /* Only read support 32/64-bit access */

Ditto

> +        vits_spin_lock(vits);
> +        val = vits->cmd_write;
> +        vits_spin_unlock(vits);
> +        if ( dabt.size == DABT_DOUBLE_WORD )
> +            *r = val;
> +        else if (dabt.size == DABT_WORD )
> +            *r = (u32)val;
> +        else
> +            goto bad_width;
> +        return 1;
> +    case GITS_CWRITER + 4:
> +        /* BITS[63:20] are RES0 */
> +        goto read_as_zero_32;
> +    case GITS_CREADR:
> +        /* Only read support 32/64-bit access */

Ditto

> +        val = atomic_read(&vits->cmd_read);
> +        if ( dabt.size == DABT_DOUBLE_WORD )
> +            *r = val;
> +        else if (dabt.size == DABT_WORD )
> +            *r = (u32)val;
> +        else
> +            goto bad_width;
> +        return 1;
> +    case GITS_CREADR + 4:
> +        /* BITS[63:20] are RES0 */
> +        goto read_as_zero_32;
> +    case 0x0098 ... 0x009c:
> +    case 0x00a0 ... 0x00fc:
> +    case 0x0140 ... 0xbffc:
> +        /* Reserved -- read ignored */
> +        goto read_as_zero;
> +    case GITS_BASER0:
> +	    /* XXX: Support only 32-bit access */

As said on v4, this comment is wrong. You only support 64-bit.

> +        if ( dabt.size == DABT_DOUBLE_WORD )
> +        {
> +            vits_spin_lock(vits);
> +            *r = vits->baser0;
> +            vits_spin_unlock(vits);
> +        }
> +        else
> +            goto bad_width;

I would prefer to see

if ( dabt.size != DATB_DOUBLE_WORD )
  goto bad_width;

vits_spin_lock(...)

To avoid one indentation layer more for most of the lines and keep the
error before.


> +        return 1;
> +    case GITS_BASER1 ... GITS_BASERN:
> +        goto read_as_zero;
> +    case GITS_PIDR0:
> +        if ( dabt.size != DABT_WORD )
> +            goto bad_width;
> +        *r = GITS_PIDR0_VAL;
> +        return 1;
> +    case GITS_PIDR1:
> +        if ( dabt.size != DABT_WORD )
> +            goto bad_width;
> +        *r = GITS_PIDR1_VAL;
> +        return 1;
> +    case GITS_PIDR2:
> +        if ( dabt.size != DABT_WORD )
> +            goto bad_width;
> +        *r = GITS_PIDR2_VAL;
> +        return 1;
> +    case GITS_PIDR3:
> +        if ( dabt.size != DABT_WORD )
> +            goto bad_width;
> +        *r = GITS_PIDR3_VAL;
> +        return 1;
> +    case GITS_PIDR4:
> +        if ( dabt.size != DABT_WORD )
> +            goto bad_width;
> +        *r = GITS_PIDR4_VAL;
> +        return 1;
> +    case GITS_PIDR5 ... GITS_PIDR7:
> +        goto read_as_zero_32;
> +   default:
> +        dprintk(XENLOG_G_ERR,
> +                "%pv: vITS: unhandled read r%"PRId32" offset 0x%#08"PRIx32"\n",

Reg is definitely not a PRId32.

> +                v, dabt.reg, gits_reg);
> +        return 0;
> +    }
> +
> +bad_width:
> +    dprintk(XENLOG_G_ERR,
> +            "%pv: vITS: bad read width %d r%"PRId32" offset 0x%#08"PRIx32"\n",

Ditto.

> +            v, dabt.size, dabt.reg, gits_reg);
> +    domain_crash_synchronous();
> +    return 0;
> +
> +read_as_zero_32:
> +    if ( dabt.size != DABT_WORD ) goto bad_width;
> +read_as_zero:
> +    *r = 0;
> +    return 1;
> +}
> +
> +/*
> + * GITS_BASER.Type[58:56], GITS_BASER.Entry_size[55:48]
> + * and GITS_BASER.Shareability[11:10] are read-only.

As said on v4, implemented Shareability as fixed (i.e read-only) is
deprecated. I'd like to see a TODO here.

> + * Mask those fields while emulating GITS_BASER reg.
> + */

As said on v4,

Other fields are (or could be RO) in GITS_BASER:
    - Indirect: we only support flat table
    - Page_Size: it's fine to only support 4KB granularity. It also
means less code.

I don't mind if you don't do the latter. The former is a mandatory.

> +#define GITS_BASER_MASK  (~((0x7UL << GITS_BASER_TYPE_SHIFT)     | \
> +                         (0xffUL << GITS_BASER_ENTRY_SIZE_SHIFT) | \
> +                         (0x3UL << GITS_BASER_SHAREABILITY_SHIFT)))

[..]

> +    case GITS_CWRITER:
> +        if ( dabt.size != DABT_DOUBLE_WORD && dabt.size != DABT_WORD )
> +            goto bad_width;
> +        vits_spin_lock(vits);
> +        /* Only BITS[19:0] are writable */
> +        vits->cmd_write = *r & 0xfffe0;
> +        ret = 1;
> +        if ( vits->ctrl & GITS_CTLR_ENABLE )
> +        {
> +            /* CWRITER should be within the range */
> +            if ( vits->cmd_write < (vits->cmd_qsize & 0xfffe0) )
> +                ret = vits_process_cmd(v, vits);
> +        }

Please do only 1 if rather than 2 nested if for only one line.

> +        vits_spin_unlock(vits);
> +        return ret;

[..]

>  int vits_domain_init(struct domain *d)
>  {
>      struct vgic_its *vits;
>      int i;
>  
> +    if ( is_hardware_domain(d) )
> +        d->arch.vgic.nr_lpis = num_of_lpis;
> +    else
> +        d->arch.vgic.nr_lpis = NR_LPIS;

NR_LPIS is defined in patch #14. And the name seems to be wrong.

Anyway, I don't understand why you are trying to initialize vITS on
guest. We agree that it should only be used on DOM0 for now until we
effectively need it for the guest.

Furthermore, it miss at least the toolstack in order to get the part
guest ready.

So please ensure that the vITS is not initialized for the guest.

> +
>      d->arch.vgic.vits = xzalloc(struct vgic_its);
>      if ( !d->arch.vgic.vits )
>          return -ENOMEM;
> @@ -539,6 +882,7 @@ int vits_domain_init(struct domain *d)
>      vits = d->arch.vgic.vits;
>  
>      spin_lock_init(&vits->lock);
> +    spin_lock_init(&vits->prop_lock);

The field prop_lock is added in patch #12. Please move the
spin_lock_init there.

To remind you, *every* patch should be able to compile one by one on
both aarch64, and arm32. I suspect this is not currently the case.

>  
>      vits->collections = xzalloc_array(struct its_collection, nr_cpu_ids);
>      if ( !vits->collections )
> @@ -550,6 +894,21 @@ int vits_domain_init(struct domain *d)
>      for ( i = 0; i < nr_cpu_ids; i++ )
>          vits->collections[i].target_address = ~0UL;
>  
> +    d->arch.vgic.id_bits = get_count_order(d->arch.vgic.nr_lpis + FIRST_GIC_LPI);

ID bits is defined in patch #12. And you don't even use it here...

> +    vits->baser0 = GITS_BASER_INIT_VAL;
> +
> +    if ( is_hardware_domain(d) )
> +    {
> +        /*
> +         * Only one virtual ITS is provided to domain.
> +         * Assign first physical ITS address to Dom0 virtual ITS.
> +         */
> +        vits->gits_base = vits_hw.info->its_hw[0].phys_base;
> +        vits->gits_size = vits_hw.info->its_hw[0].phys_size;
> +    }

Here another example where the code for the guest is missing. Please be
consistent i.e either try to support it at the whole or not at all.

The latter seems the more plausible for now.

> +
> +    register_mmio_handler(d, &vgic_gits_mmio_handler, vits->gits_base, SZ_64K);
> +
>      return 0;
>  }
>  
> diff --git a/xen/include/asm-arm/gic-its.h b/xen/include/asm-arm/gic-its.h
> index 23ff66c..0854cde 100644
> --- a/xen/include/asm-arm/gic-its.h
> +++ b/xen/include/asm-arm/gic-its.h
> @@ -21,6 +21,9 @@
>  #include <asm/gic_v3_defs.h>
>  #include <xen/rbtree.h>
>  
> +/* Number of LPI supported */
> +extern unsigned int num_of_lpis;
> +

The prototype of anything declared in irq.c should go in irq.h and not
in the GIC ITS header.

> diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
> index e330fe3..5f37f56 100644
> --- a/xen/include/asm-arm/gic.h
> +++ b/xen/include/asm-arm/gic.h
> @@ -20,6 +20,7 @@
>  
>  #define NR_GIC_LOCAL_IRQS  NR_LOCAL_IRQS
>  #define NR_GIC_SGI         16
> +#define FIRST_GIC_LPI      8192

It make little sense to define it in a patch called "Add GITS registers
emulation".

Regards,

-- 
Julien Grall

  reply	other threads:[~2015-07-28 19:01 UTC|newest]

Thread overview: 81+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-27 11:11 [PATCH v5 00/22] Add ITS support vijay.kilari
2015-07-27 11:11 ` [PATCH v5 01/22] xen/arm: Return success if dt node does not have irq mapping vijay.kilari
2015-07-28 13:13   ` Julien Grall
2015-07-28 13:23     ` Ian Campbell
2015-07-28 13:27       ` Julien Grall
2015-09-02 15:25   ` Ian Campbell
2015-07-27 11:11 ` [PATCH v5 02/22] xen/arm: Add bitmap_find_next_zero_area helper function vijay.kilari
2015-08-11 13:53   ` Jan Beulich
2015-07-27 11:11 ` [PATCH v5 03/22] xen: Add log2 functionality vijay.kilari
2015-07-27 11:11 ` [PATCH v5 04/22] xen/arm: Set nr_cpu_ids to available number of cpus vijay.kilari
2015-07-28 13:21   ` Julien Grall
2015-07-27 11:11 ` [PATCH v5 05/22] xen/arm: ITS: Port ITS driver to Xen vijay.kilari
2015-07-28 16:46   ` Julien Grall
2015-07-29 15:22     ` Vijay Kilari
2015-07-29 16:06       ` Ian Campbell
2015-07-29 16:18         ` Vijay Kilari
2015-07-31 10:28     ` Vijay Kilari
2015-07-31 11:10       ` Julien Grall
2015-07-27 11:11 ` [PATCH v5 06/22] xen/arm: ITS: Add helper functions to manage its_devices vijay.kilari
2015-07-27 11:11 ` [PATCH v5 07/22] xen/arm: ITS: Add virtual ITS driver vijay.kilari
2015-07-28 17:13   ` Julien Grall
2015-07-31  6:49     ` Vijay Kilari
2015-07-31 10:14       ` Julien Grall
2015-07-31 10:32         ` Ian Campbell
2015-07-27 11:11 ` [PATCH v5 08/22] xen/arm: ITS: Add virtual ITS commands support vijay.kilari
2015-07-28 18:04   ` Julien Grall
2015-07-31  6:57     ` Vijay Kilari
2015-07-31 10:16       ` Julien Grall
2015-07-27 11:11 ` [PATCH v5 09/22] xen/arm: ITS: Export ITS info to Virtual ITS vijay.kilari
2015-07-28 18:14   ` Julien Grall
2015-07-31  7:01     ` Vijay Kilari
2015-08-03 15:58       ` Julien Grall
2015-07-27 11:11 ` [PATCH v5 10/22] xen/arm: ITS: Add GITS registers emulation vijay.kilari
2015-07-28 19:01   ` Julien Grall [this message]
2015-07-31  7:25     ` Vijay Kilari
2015-07-31 10:28       ` Julien Grall
2015-08-01  8:50     ` Vijay Kilari
2015-08-03 11:19       ` Julien Grall
2015-07-27 11:11 ` [PATCH v5 11/22] xen/arm: ITS: Enable physical and virtual ITS driver compilation vijay.kilari
2015-07-27 11:11 ` [PATCH v5 12/22] xen/arm: ITS: Add GICR register emulation vijay.kilari
2015-07-30 17:04   ` Julien Grall
2015-07-31  9:08     ` Vijay Kilari
2015-07-31 11:05       ` Julien Grall
2015-08-01 10:25         ` Vijay Kilari
2015-08-01 15:51           ` Julien Grall
2015-08-03  9:36             ` Vijay Kilari
2015-08-03 13:01               ` Julien Grall
2015-08-03 13:51                 ` Vijay Kilari
2015-08-03 13:58                   ` Julien Grall
2015-08-04  6:55                     ` Vijay Kilari
2015-08-04  8:44                       ` Julien Grall
2015-07-27 11:11 ` [PATCH v5 13/22] xen/arm: ITS: Implement gic_is_lpi helper function vijay.kilari
2015-07-30 17:14   ` Julien Grall
2015-07-27 11:11 ` [PATCH v5 14/22] xen/arm: ITS: Allocate irq descriptors for LPIs vijay.kilari
2015-08-04 13:21   ` Julien Grall
2015-07-27 11:11 ` [PATCH v5 15/22] xen/arm: ITS: implement hw_irq_controller " vijay.kilari
2015-08-04 13:45   ` Julien Grall
2015-08-06  8:15     ` Vijay Kilari
2015-08-06 10:05       ` Julien Grall
2015-08-06 10:11         ` Julien Grall
2015-07-27 11:11 ` [PATCH v5 16/22] xen/arm: ITS: Route LPIs vijay.kilari
2015-08-04 14:54   ` Julien Grall
2015-07-27 11:11 ` [PATCH v5 17/22] xen/arm: ITS: Initialize physical ITS vijay.kilari
2015-08-17 19:00   ` Julien Grall
2015-07-27 11:12 ` [PATCH v5 18/22] xen/arm: ITS: Add domain specific ITS initialization vijay.kilari
2015-08-17 18:57   ` Julien Grall
2015-07-27 11:12 ` [PATCH v5 19/22] xen/arm: ITS: Add APIs to add and assign device vijay.kilari
2015-08-17 19:17   ` Julien Grall
2015-07-27 11:12 ` [PATCH v5 20/22] xen/arm: ITS: Map ITS translation space vijay.kilari
2015-08-17 19:20   ` Julien Grall
2015-08-18 19:14   ` Julien Grall
2015-08-18 22:37     ` Marc Zyngier
2015-09-02 15:45       ` Ian Campbell
2015-09-02 15:59         ` Marc Zyngier
2015-07-27 11:12 ` [PATCH v5 21/22] xen/arm: ITS: Generate ITS node for Dom0 vijay.kilari
2015-08-17 19:41   ` Julien Grall
2015-08-21 23:02     ` Vijay Kilari
2015-08-21 23:48       ` Julien Grall
2015-08-26 12:40     ` Vijay Kilari
2015-08-27  0:02       ` Julien Grall
2015-07-27 11:12 ` [PATCH v5 22/22] xen/arm: ITS: Add pci devices in ThunderX vijay.kilari

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=55B7D172.4020704@citrix.com \
    --to=julien.grall@citrix.com \
    --cc=Ian.Campbell@citrix.com \
    --cc=Prasun.Kapoor@caviumnetworks.com \
    --cc=Vijaya.Kumar@caviumnetworks.com \
    --cc=manish.jaggi@caviumnetworks.com \
    --cc=stefano.stabellini@citrix.com \
    --cc=stefano.stabellini@eu.citrix.com \
    --cc=tim@xen.org \
    --cc=vijay.kilari@gmail.com \
    --cc=xen-devel@lists.xen.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).