All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Alex Bennée" <alex.bennee@linaro.org>
To: Peter Maydell <peter.maydell@linaro.org>
Cc: qemu-arm@nongnu.org,  qemu-devel@nongnu.org
Subject: Re: [PATCH 02/76] tests/tcg/x86_64/fma: Test some x86 fused-multiply-add cases
Date: Fri, 24 Jan 2025 17:15:26 +0000	[thread overview]
Message-ID: <87r04si15d.fsf@draig.linaro.org> (raw)
In-Reply-To: <20250124162836.2332150-3-peter.maydell@linaro.org> (Peter Maydell's message of "Fri, 24 Jan 2025 16:27:22 +0000")

Peter Maydell <peter.maydell@linaro.org> writes:

> Add a test case which tests some corner case behaviour of
> fused-multiply-add on x86:
>  * 0 * Inf + SNaN should raise Invalid
>  * 0 * Inf + QNaN shouldh not raise Invalid
>  * tininess should be detected after rounding
>
> There is also one currently-disabled test case:
>  * flush-to-zero should be done after rounding
>
> This is disabled because QEMU's emulation currently does this
> incorrectly (and so would fail the test).  The test case is kept in
> but disabled, as the justification for why the test running harness
> has support for testing both with and without FTZ set.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  tests/tcg/x86_64/fma.c           | 109 +++++++++++++++++++++++++++++++
>  tests/tcg/x86_64/Makefile.target |   1 +
>  2 files changed, 110 insertions(+)
>  create mode 100644 tests/tcg/x86_64/fma.c
>
> diff --git a/tests/tcg/x86_64/fma.c b/tests/tcg/x86_64/fma.c
> new file mode 100644
> index 00000000000..09c622ebc00
> --- /dev/null
> +++ b/tests/tcg/x86_64/fma.c
> @@ -0,0 +1,109 @@
> +/*
> + * Test some fused multiply add corner cases.
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +#include <stdio.h>
> +#include <stdint.h>
> +#include <stdbool.h>
> +#include <inttypes.h>
> +
> +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
> +
> +/*
> + * Perform one "n * m + a" operation using the vfmadd insn and return
> + * the result; on return *mxcsr_p is set to the bottom 6 bits of MXCSR
> + * (the Flag bits). If ftz is true then we set MXCSR.FTZ while doing
> + * the operation.
> + * We print the operation and its results to stdout.
> + */
> +static uint64_t do_fmadd(uint64_t n, uint64_t m, uint64_t a,
> +                         bool ftz, uint32_t *mxcsr_p)
> +{
> +    uint64_t r;
> +    uint32_t mxcsr = 0;
> +    uint32_t ftz_bit = ftz ? (1 << 15) : 0;
> +    uint32_t saved_mxcsr = 0;
> +
> +    asm volatile("stmxcsr %[saved_mxcsr]\n"
> +                 "stmxcsr %[mxcsr]\n"
> +                 "andl $0xffff7fc0, %[mxcsr]\n"
> +                 "orl %[ftz_bit], %[mxcsr]\n"
> +                 "ldmxcsr %[mxcsr]\n"
> +                 "movq %[a], %%xmm0\n"
> +                 "movq %[m], %%xmm1\n"
> +                 "movq %[n], %%xmm2\n"
> +                 /* xmm0 = xmm0 + xmm2 * xmm1 */
> +                 "vfmadd231sd %%xmm1, %%xmm2, %%xmm0\n"
> +                 "movq %%xmm0, %[r]\n"
> +                 "stmxcsr %[mxcsr]\n"
> +                 "ldmxcsr %[saved_mxcsr]\n"
> +                 : [r] "=r" (r), [mxcsr] "=m" (mxcsr),
> +                   [saved_mxcsr] "=m" (saved_mxcsr)
> +                 : [n] "r" (n), [m] "r" (m), [a] "r" (a),
> +                   [ftz_bit] "r" (ftz_bit)
> +                 : "xmm0", "xmm1", "xmm2");
> +    *mxcsr_p = mxcsr & 0x3f;
> +    printf("vfmadd132sd 0x%" PRIx64 " 0x%" PRIx64 " 0x%" PRIx64
> +           " = 0x%" PRIx64 " MXCSR flags 0x%" PRIx32 "\n",
> +           n, m, a, r, *mxcsr_p);
> +    return r;
> +}
> +
> +typedef struct testdata {
> +    /* Input n, m, a */
> +    uint64_t n;
> +    uint64_t m;
> +    uint64_t a;
> +    bool ftz;
> +    /* Expected result */
> +    uint64_t expected_r;
> +    /* Expected low 6 bits of MXCSR (the Flag bits) */
> +    uint32_t expected_mxcsr;
> +} testdata;
> +
> +static testdata tests[] = {
> +    { 0, 0x7ff0000000000000, 0x7ff000000000aaaa, false, /* 0 * Inf + SNaN */
> +      0x7ff800000000aaaa, 1 }, /* Should be QNaN and does raise Invalid */
> +    { 0, 0x7ff0000000000000, 0x7ff800000000aaaa, false, /* 0 * Inf + QNaN */
> +      0x7ff800000000aaaa, 0 }, /* Should be QNaN and does *not* raise Invalid */
> +    /*
> +     * These inputs give a result which is tiny before rounding but which
> +     * becomes non-tiny after rounding. x86 is a "detect tininess after
> +     * rounding" architecture, so it should give a non-denormal result and
> +     * not set the Underflow flag (only the Precision flag for an inexact
> +     * result).
> +     */
> +    { 0x3fdfffffffffffff, 0x001fffffffffffff, 0x801fffffffffffff, false,
> +      0x8010000000000000, 0x20 },
> +    /*
> +     * Flushing of denormal outputs to zero should also happen after
> +     * rounding, so setting FTZ should not affect the result or the flags.
> +     * QEMU currently does not emulate this correctly because we do the
> +     * flush-to-zero check before rounding, so we incorrectly produce a
> +     * zero result and set Underflow as well as Precision.
> +     */
> +#ifdef ENABLE_FAILING_TESTS
> +    { 0x3fdfffffffffffff, 0x001fffffffffffff, 0x801fffffffffffff, true,
> +      0x8010000000000000, 0x20 }, /* Enabling FTZ shouldn't change flags */
> +#endif

We could extend the multiarch/float_madds test to handle doubles as well
(or create a new multiarch test).

If the right FMA instructions can be forced via cflags you could then
add a specific binary to exercise the vfmadd231sd instruction like we do
for neon:

  float_madds: CFLAGS+=-mfpu=neon-vfpv4

The test does basic testing but ideally you would add a reference output
to check against.

> +};
> +
> +int main(void)
> +{
> +    bool passed = true;
> +    for (int i = 0; i < ARRAY_SIZE(tests); i++) {
> +        uint32_t mxcsr;
> +        uint64_t r = do_fmadd(tests[i].n, tests[i].m, tests[i].a,
> +                              tests[i].ftz, &mxcsr);
> +        if (r != tests[i].expected_r) {
> +            printf("expected result 0x%" PRIx64 "\n", tests[i].expected_r);
> +            passed = false;
> +        }
> +        if (mxcsr != tests[i].expected_mxcsr) {
> +            printf("expected MXCSR flags 0x%x\n", tests[i].expected_mxcsr);
> +            passed = false;
> +        }
> +    }
> +    return passed ? 0 : 1;
> +}
> diff --git a/tests/tcg/x86_64/Makefile.target b/tests/tcg/x86_64/Makefile.target
> index d6dff559c7d..be20fc64e88 100644
> --- a/tests/tcg/x86_64/Makefile.target
> +++ b/tests/tcg/x86_64/Makefile.target
> @@ -18,6 +18,7 @@ X86_64_TESTS += adox
>  X86_64_TESTS += test-1648
>  X86_64_TESTS += test-2175
>  X86_64_TESTS += cross-modifying-code
> +X86_64_TESTS += fma
>  TESTS=$(MULTIARCH_TESTS) $(X86_64_TESTS) test-x86_64
>  else
>  TESTS=$(MULTIARCH_TESTS)

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro

  reply	other threads:[~2025-01-24 17:15 UTC|newest]

Thread overview: 167+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-01-24 16:27 [PATCH 00/76] target/arm: Implement FEAT_AFP and FEAT_RPRES Peter Maydell
2025-01-24 16:27 ` [PATCH 01/76] target/i386: Do not raise Invalid for 0 * Inf + QNaN Peter Maydell
2025-01-24 16:27 ` [PATCH 02/76] tests/tcg/x86_64/fma: Test some x86 fused-multiply-add cases Peter Maydell
2025-01-24 17:15   ` Alex Bennée [this message]
2025-01-27  9:54     ` Peter Maydell
2025-01-24 16:27 ` [PATCH 03/76] target/arm: arm_reset_sve_state() should set FPSR, not FPCR Peter Maydell
2025-01-25 15:07   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 04/76] target/arm: Use FPSR_ constants in vfp_exceptbits_from_host() Peter Maydell
2025-01-25 15:07   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 05/76] target/arm: Use uint32_t " Peter Maydell
2025-01-25 15:08   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 06/76] target/arm: Define new fp_status_a32 and fp_status_a64 Peter Maydell
2025-01-25 15:12   ` Richard Henderson
2025-01-27  4:59   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 07/76] target/arm: Use vfp.fp_status_a64 in A64-only helper functions Peter Maydell
2025-01-25 15:15   ` Richard Henderson
2025-01-28 12:35     ` Peter Maydell
2025-01-28 15:54       ` Richard Henderson
2025-01-24 16:27 ` [PATCH 08/76] target/arm: Use fp_status_a32 in vjvct helper Peter Maydell
2025-01-25 15:16   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 09/76] target/arm: Use fp_status_a32 in vfp_cmp helpers Peter Maydell
2025-01-25 15:18   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 10/76] target/arm: Use FPST_FPCR_A32 in A32 decoder Peter Maydell
2025-01-25 15:18   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 11/76] target/arm: Use FPST_FPCR_A64 in A64 decoder Peter Maydell
2025-01-25 15:19   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 12/76] target/arm: Remove now-unused vfp.fp_status and FPST_FPCR Peter Maydell
2025-01-25 15:20   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 13/76] target/arm: Define new fp_status_f16_a32 and fp_status_f16_a64 Peter Maydell
2025-01-25 15:21   ` Richard Henderson
2025-01-27  5:00   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 14/76] target/arm: Use fp_status_f16_a32 in AArch32-only helpers Peter Maydell
2025-01-25 15:21   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 15/76] target/arm: Use fp_status_f16_a64 in AArch64-only helpers Peter Maydell
2025-01-25 15:22   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 16/76] target/arm: Use FPST_FPCR_F16_A32 in A32 decoder Peter Maydell
2025-01-25 15:23   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 17/76] target/arm: Use FPST_FPCR_F16_A64 in A64 decoder Peter Maydell
2025-01-25 15:23   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 18/76] target/arm: Remove now-unused vfp.fp_status_f16 and FPST_FPCR_F16 Peter Maydell
2025-01-25 15:23   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 19/76] fpu: Rename float_flag_input_denormal to float_flag_input_denormal_flushed Peter Maydell
2025-01-25 15:25   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 20/76] fpu: Rename float_flag_output_denormal to float_flag_output_denormal_flushed Peter Maydell
2025-01-25 15:26   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 21/76] fpu: Fix a comment in softfloat-types.h Peter Maydell
2025-01-25 15:27   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 22/76] fpu: Add float_class_denormal Peter Maydell
2025-01-25 15:31   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 23/76] fpu: Implement float_flag_input_denormal_used Peter Maydell
2025-01-25 15:42   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 24/76] fpu: allow flushing of output denormals to be after rounding Peter Maydell
2025-01-25 16:41   ` Richard Henderson
2025-01-27 10:01     ` Peter Maydell
2025-01-27 16:09       ` Richard Henderson
2025-01-29 13:04     ` Peter Maydell
2025-01-31 13:36       ` Richard Henderson
2025-01-24 16:27 ` [PATCH 25/76] target/arm: Remove redundant advsimd float16 helpers Peter Maydell
2025-01-25 16:59   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 26/76] target/arm: Use FPST_FPCR_F16_A64 for halfprec-to-other conversions Peter Maydell
2025-01-25 17:01   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 27/76] target/arm: Define FPCR AH, FIZ, NEP bits Peter Maydell
2025-01-25 17:08   ` Richard Henderson
2025-01-31 17:05     ` Peter Maydell
2025-01-24 16:27 ` [PATCH 28/76] target/arm: Implement FPCR.FIZ handling Peter Maydell
2025-01-25 17:25   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 29/76] target/arm: Adjust FP behaviour for FPCR.AH = 1 Peter Maydell
2025-01-25 17:27   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 30/76] target/arm: Adjust exception flag handling for AH " Peter Maydell
2025-01-25 17:29   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 31/76] target/arm: Add FPCR.AH to tbflags Peter Maydell
2025-01-25 17:30   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 32/76] target/arm: Set up float_status to use for FPCR.AH=1 behaviour Peter Maydell
2025-01-25 17:36   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 33/76] target/arm: Use FPST_FPCR_AH for FRECPE, FRECPS, FRECPX, FRSQRTE, FRSQRTS Peter Maydell
2025-01-25 17:40   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 34/76] target/arm: Use FPST_FPCR_AH for BFCVT* insns Peter Maydell
2025-01-25 17:42   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 35/76] target/arm: Use FPST_FPCR_AH for BFMLAL*, BFMLSL* insns Peter Maydell
2025-01-25 17:44   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 36/76] target/arm: Add FPCR.NEP to TBFLAGS Peter Maydell
2025-01-25 17:45   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 37/76] target/arm: Define and use new write_fp_*reg_merging() functions Peter Maydell
2025-01-25 17:52   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 38/76] target/arm: Handle FPCR.NEP for 3-input scalar operations Peter Maydell
2025-01-25 17:53   ` Richard Henderson
2025-01-24 16:27 ` [PATCH 39/76] target/arm: Handle FPCR.NEP for BFCVT scalar Peter Maydell
2025-01-25 17:55   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 40/76] target/arm: Handle FPCR.NEP for 1-input scalar operations Peter Maydell
2025-01-26 12:33   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 41/76] target/arm: Handle FPCR.NEP in do_cvtf_scalar() Peter Maydell
2025-01-26 12:33   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 42/76] target/arm: Handle FPCR.NEP for scalar FABS and FNEG Peter Maydell
2025-01-26 12:34   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 43/76] target/arm: Handle FPCR.NEP for FCVTXN (scalar) Peter Maydell
2025-01-26 12:36   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 44/76] target/arm: Handle FPCR.NEP for NEP for FMUL, FMULX scalar by element Peter Maydell
2025-01-26 12:36   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 45/76] target/arm: Implement FPCR.AH semantics for scalar FMIN/FMAX Peter Maydell
2025-01-26 12:43   ` Richard Henderson
2025-01-31 13:09     ` Peter Maydell
2025-01-31 13:37       ` Richard Henderson
2025-01-24 16:28 ` [PATCH 46/76] target/arm: Implement FPCR.AH semantics for vector FMIN/FMAX Peter Maydell
2025-01-26 12:45   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 47/76] target/arm: Implement FPCR.AH semantics for FMAXV and FMINV Peter Maydell
2025-01-26 12:47   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 48/76] target/arm: Implement FPCR.AH semantics for FMINP and FMAXP Peter Maydell
2025-01-26 12:49   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 49/76] target/arm: Implement FPCR.AH semantics for SVE FMAXV and FMINV Peter Maydell
2025-01-26 12:51   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 50/76] target/arm: Implement FPCR.AH semantics for SVE FMIN/FMAX immediate Peter Maydell
2025-01-26 12:54   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 51/76] target/arm: Implement FPCR.AH semantics for SVE FMIN/FMAX vector Peter Maydell
2025-01-26 12:55   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 52/76] target/arm: Implement FPCR.AH handling of negation of NaN Peter Maydell
2025-01-26 13:00   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 53/76] target/arm: Implement FPCR.AH handling for scalar FABS and FABD Peter Maydell
2025-01-26 13:01   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 54/76] target/arm: Handle FPCR.AH in vector FABD Peter Maydell
2025-01-26 13:03   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 55/76] target/arm: Handle FPCR.AH in SVE FNEG Peter Maydell
2025-01-26 13:05   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 56/76] target/arm: Handle FPCR.AH in SVE FABS Peter Maydell
2025-01-26 13:05   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 57/76] target/arm: Handle FPCR.AH in SVE FABD Peter Maydell
2025-01-26 13:06   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 58/76] target/arm: Handle FPCR.AH in negation steps in FCADD Peter Maydell
2025-01-26 13:08   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 59/76] target/arm: Handle FPCR.AH in negation steps in SVE FCADD Peter Maydell
2025-01-26 13:10   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 60/76] target/arm: Handle FPCR.AH in FMLSL Peter Maydell
2025-01-26 13:13   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 61/76] target/arm: Handle FPCR.AH in FRECPS and FRSQRTS scalar insns Peter Maydell
2025-01-26 13:14   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 62/76] target/arm: Handle FPCR.AH in FRECPS and FRSQRTS vector insns Peter Maydell
2025-01-26 13:15   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 63/76] target/arm: Handle FPCR.AH in negation step in FMLS (indexed) Peter Maydell
2025-01-26 13:16   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 64/76] target/arm: Handle FPCR.AH in negation in FMLS (vector) Peter Maydell
2025-01-26 13:17   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 65/76] target/arm: Handle FPCR.AH in negation step in SVE " Peter Maydell
2025-01-26 13:19   ` Richard Henderson
2025-01-27 20:41   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 66/76] target/arm: Handle FPCR.AH in SVE FTSSEL Peter Maydell
2025-01-26 13:20   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 67/76] target/arm: Handle FPCR.AH in SVE FTMAD Peter Maydell
2025-01-26 13:21   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 68/76] target/arm: Enable FEAT_AFP for '-cpu max' Peter Maydell
2025-01-26 13:21   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 69/76] target/arm: Plumb FEAT_RPRES frecpe and frsqrte through to new helper Peter Maydell
2025-01-26 13:23   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 70/76] target/arm: Implement increased precision FRECPE Peter Maydell
2025-01-26 13:26   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 71/76] target/arm: Implement increased precision FRSQRTE Peter Maydell
2025-01-26 13:28   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 72/76] target/arm: Enable FEAT_RPRES for -cpu max Peter Maydell
2025-01-26 13:29   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 73/76] target/i386: Detect flush-to-zero after rounding Peter Maydell
2025-01-26 13:30   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 74/76] target/i386: Use correct type for get_float_exception_flags() values Peter Maydell
2025-01-26 13:30   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 75/76] target/i386: Wire up MXCSR.DE and FPUS.DE correctly Peter Maydell
2025-01-26 13:31   ` Richard Henderson
2025-01-24 16:28 ` [PATCH 76/76] tests/tcg/x86_64/fma: add test for exact-denormal output Peter Maydell
2025-01-26 13:32   ` Richard Henderson
2025-01-24 16:35 ` [PATCH 00/76] target/arm: Implement FEAT_AFP and FEAT_RPRES Peter Maydell
2025-01-28 13:23 ` Peter Maydell

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=87r04si15d.fsf@draig.linaro.org \
    --to=alex.bennee@linaro.org \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.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 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.