From: Ben Horgan <ben.horgan@arm.com>
To: James Morse <james.morse@arm.com>,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org
Cc: D Scott Phillips OS <scott@os.amperecomputing.com>,
carl@os.amperecomputing.com, lcherian@marvell.com,
bobo.shaobowang@huawei.com, tan.shaopeng@fujitsu.com,
baolin.wang@linux.alibaba.com,
Jamie Iles <quic_jiles@quicinc.com>,
Xin Hao <xhao@linux.alibaba.com>,
peternewman@google.com, dfustini@baylibre.com,
amitsinght@marvell.com, David Hildenbrand <david@kernel.org>,
Dave Martin <dave.martin@arm.com>, Koba Ko <kobak@nvidia.com>,
Shanker Donthineni <sdonthineni@nvidia.com>,
fenghuay@nvidia.com, baisheng.gao@unisoc.com,
Jonathan Cameron <jonathan.cameron@huawei.com>,
Gavin Shan <gshan@redhat.com>,
rohit.mathew@arm.com, reinette.chatre@intel.com,
Punit Agrawal <punit.agrawal@oss.qualcomm.com>,
Zeng Heng <zengheng4@huawei.com>
Subject: Re: [RFC PATCH 33/38] arm_mpam: Generate a configuration for min controls
Date: Tue, 9 Dec 2025 16:45:16 +0000 [thread overview]
Message-ID: <f00a0467-6f32-4105-b1b8-ca9490db57bf@arm.com> (raw)
In-Reply-To: <20251205215901.17772-34-james.morse@arm.com>
Hi James,
On 12/5/25 21:58, James Morse wrote:
> MPAM supports a minimum and maximum control for memory bandwidth. The
> purpose of the minimum control is to give priority to tasks that are
> below their minimum value. Resctrl only provides one value for the
> bandwidth configuration, which is used for the maximum.
>
> The minimum control is always programmed to zero on hardware that
> supports it.
>
> Generate a minimum bandwidth value that is 5% lower than the
> value provided by resctrl. This means tasks that are not
> receiving their target bandwidth can be prioritised by the
> hardware.
To ensure that the min is always programmed we need to add a
reset_mbw_min to the reset_cfg for the ris level reset and give a value
in mpam_reset_component_cfg() for the component level reset.
>
> CC: Zeng Heng <zengheng4@huawei.com>
> Signed-off-by: James Morse <james.morse@arm.com>
> ---
> drivers/resctrl/mpam_devices.c | 68 +++++++++++++++++++++++++++--
> drivers/resctrl/mpam_internal.h | 2 +
> drivers/resctrl/test_mpam_devices.c | 66 ++++++++++++++++++++++++++++
> 3 files changed, 132 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c
> index 1334093fc03e..741e14e1e6cf 100644
> --- a/drivers/resctrl/mpam_devices.c
> +++ b/drivers/resctrl/mpam_devices.c
> @@ -721,6 +721,13 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris)
> mpam_set_feature(mpam_feat_mbw_part, props);
>
> props->bwa_wd = FIELD_GET(MPAMF_MBW_IDR_BWA_WD, mbw_features);
> +
> + /*
> + * The BWA_WD field can represent 0-63, but the control fields it
> + * describes have a maximum of 16 bits.
> + */
> + props->bwa_wd = min(props->bwa_wd, 16);
> +
> if (props->bwa_wd && FIELD_GET(MPAMF_MBW_IDR_HAS_MAX, mbw_features))
> mpam_set_feature(mpam_feat_mbw_max, props);
>
> @@ -1387,7 +1394,7 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid,
>
> if (mpam_has_feature(mpam_feat_mbw_min, rprops) &&
> mpam_has_feature(mpam_feat_mbw_min, cfg))
> - mpam_write_partsel_reg(msc, MBW_MIN, 0);
> + mpam_write_partsel_reg(msc, MBW_MIN, cfg->mbw_min);
>
> if (mpam_has_feature(mpam_feat_mbw_max, rprops) &&
> mpam_has_feature(mpam_feat_mbw_max, cfg)) {
> @@ -2693,24 +2700,77 @@ static bool mpam_update_config(struct mpam_config *cfg,
> maybe_update_config(cfg, mpam_feat_cpor_part, newcfg, cpbm, has_changes);
> maybe_update_config(cfg, mpam_feat_mbw_part, newcfg, mbw_pbm, has_changes);
> maybe_update_config(cfg, mpam_feat_mbw_max, newcfg, mbw_max, has_changes);
> + maybe_update_config(cfg, mpam_feat_mbw_min, newcfg, mbw_min, has_changes);
>
> return has_changes;
> }
>
> +static void mpam_extend_config(struct mpam_class *class, struct mpam_config *cfg)
> +{
> + struct mpam_props *cprops = &class->props;
> + u16 min, min_hw_granule, delta;
> + u16 max_hw_value, res0_bits;
> +
> + /*
> + * MAX and MIN should be set together. If only one is provided,
> + * generate a configuration for the other. If only one control
> + * type is supported, the other value will be ignored.
> + *
> + * Resctrl can only configure the MAX.
> + */
> + if (mpam_has_feature(mpam_feat_mbw_max, cfg) &&
> + !mpam_has_feature(mpam_feat_mbw_min, cfg)) {
> + /*
> + * Calculate the values the 'min' control can hold.
> + * e.g. on a platform with bwa_wd = 8, min_hw_granule is 0x00ff
> + * because those bits are RES0. Configurations of this value
> + * are effectively zero. But configurations need to saturate
> + * at min_hw_granule on systems with mismatched bwa_wd, where
> + * the 'less than 0' values are implemented on some MSC, but
> + * not others.
> + */
> + res0_bits = 16 - cprops->bwa_wd;
> + max_hw_value = ((1 << cprops->bwa_wd) - 1) << res0_bits;
> + min_hw_granule = ~max_hw_value;
> +
> + delta = ((5 * MPAMCFG_MBW_MAX_MAX) / 100) - 1;
> + if (cfg->mbw_max > delta)
> + min = cfg->mbw_max - delta;
> + else
> + min = 0;
> +
> + cfg->mbw_min = max(min, min_hw_granule);
> + mpam_set_feature(mpam_feat_mbw_min, cfg);
> + }
> +}
> +
> int mpam_apply_config(struct mpam_component *comp, u16 partid,
> - struct mpam_config *cfg)
> + struct mpam_config *user_cfg)
> {
> struct mpam_write_config_arg arg;
> struct mpam_msc_ris *ris;
> + struct mpam_config cfg;
> struct mpam_vmsc *vmsc;
> struct mpam_msc *msc;
>
> lockdep_assert_cpus_held();
>
> +
> /* Don't pass in the current config! */
> - WARN_ON_ONCE(&comp->cfg[partid] == cfg);
> + WARN_ON_ONCE(&comp->cfg[partid] == user_cfg);
>
> - if (!mpam_update_config(&comp->cfg[partid], cfg))
> + /*
> + * Copy the config to avoid writing back the 'extended' version to
> + * the caller.
> + * This avoids mpam_devices.c setting a mbm_min that mpam_resctrl.c
> + * is unaware of ... when it then changes mbm_max to be lower than
> + * mbm_min.
> + */
> + cfg = *user_cfg;
> +
> + mpam_extend_config(comp->class, &cfg);
> +
> + if (!mpam_update_config(&comp->cfg[partid], &cfg))
> return 0;
>
> arg.comp = comp;
> diff --git a/drivers/resctrl/mpam_internal.h b/drivers/resctrl/mpam_internal.h
> index b13d5e55e701..d381906545ed 100644
> --- a/drivers/resctrl/mpam_internal.h
> +++ b/drivers/resctrl/mpam_internal.h
> @@ -277,6 +277,7 @@ struct mpam_config {
> u32 cpbm;
> u32 mbw_pbm;
> u16 mbw_max;
> + u16 mbw_min;
>
> bool reset_cpbm;
> bool reset_mbw_pbm;
> @@ -618,6 +619,7 @@ static inline void mpam_resctrl_teardown_class(struct mpam_class *class) { }
> * MPAMCFG_MBW_MAX - MPAM memory maximum bandwidth partitioning configuration
> * register
> */
> +#define MPAMCFG_MBW_MAX_MAX_NR_BITS 16
> #define MPAMCFG_MBW_MAX_MAX GENMASK(15, 0)
> #define MPAMCFG_MBW_MAX_HARDLIM BIT(31)
>
> diff --git a/drivers/resctrl/test_mpam_devices.c b/drivers/resctrl/test_mpam_devices.c
> index 3e8d564a0c64..2f802fd9f249 100644
> --- a/drivers/resctrl/test_mpam_devices.c
> +++ b/drivers/resctrl/test_mpam_devices.c
> @@ -322,6 +322,71 @@ static void test_mpam_enable_merge_features(struct kunit *test)
> mutex_unlock(&mpam_list_lock);
> }
>
> +static void test_mpam_extend_config(struct kunit *test)
> +{
> + struct mpam_config fake_cfg = { };
> + struct mpam_class fake_class = { };
> +
> + /* Configurations with both are not modified */
> + fake_class.props.bwa_wd = 16;
> + fake_cfg.mbw_max = 0xfeef;
> + fake_cfg.mbw_min = 0xfeef;
> + bitmap_zero(fake_cfg.features, MPAM_FEATURE_LAST);
> + mpam_set_feature(mpam_feat_mbw_max, &fake_cfg);
> + mpam_set_feature(mpam_feat_mbw_min, &fake_cfg);
> + mpam_extend_config(&fake_class, &fake_cfg);
> + KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_mbw_max, &fake_cfg));
> + KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_mbw_min, &fake_cfg));
> + KUNIT_EXPECT_EQ(test, fake_cfg.mbw_max, 0xfeef);
> + KUNIT_EXPECT_EQ(test, fake_cfg.mbw_min, 0xfeef);
> +
> + /* When a min is missing, it is generated */
> + fake_class.props.bwa_wd = 16;
> + fake_cfg.mbw_max = 0xfeef;
> + fake_cfg.mbw_min = 0;
> + bitmap_zero(fake_cfg.features, MPAM_FEATURE_LAST);
> + mpam_set_feature(mpam_feat_mbw_max, &fake_cfg);
> + mpam_extend_config(&fake_class, &fake_cfg);
> + KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_mbw_max, &fake_cfg));
> + KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_mbw_min, &fake_cfg));
> + KUNIT_EXPECT_EQ(test, fake_cfg.mbw_max, 0xfeef);
> + KUNIT_EXPECT_EQ(test, fake_cfg.mbw_min, 0xf224);
> +
> + fake_class.props.bwa_wd = 8;
> + fake_cfg.mbw_max = 0xfeef;
> + fake_cfg.mbw_min = 0;
> + bitmap_zero(fake_cfg.features, MPAM_FEATURE_LAST);
> + mpam_set_feature(mpam_feat_mbw_max, &fake_cfg);
> + mpam_extend_config(&fake_class, &fake_cfg);
> + KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_mbw_max, &fake_cfg));
> + KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_mbw_min, &fake_cfg));
> + KUNIT_EXPECT_EQ(test, fake_cfg.mbw_max, 0xfeef);
> + KUNIT_EXPECT_EQ(test, fake_cfg.mbw_min, 0xf224);
> +
> + /* 5% below the minimum granule, is still the minimum granule */
> + fake_class.props.bwa_wd = 12;
> + fake_cfg.mbw_max = 0xf;
> + fake_cfg.mbw_min = 0;
> + bitmap_zero(fake_cfg.features, MPAM_FEATURE_LAST);
> + mpam_set_feature(mpam_feat_mbw_max, &fake_cfg);
> + mpam_extend_config(&fake_class, &fake_cfg);
> + KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_mbw_max, &fake_cfg));
> + KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_mbw_min, &fake_cfg));
> + KUNIT_EXPECT_EQ(test, fake_cfg.mbw_max, 0xf);
> + KUNIT_EXPECT_EQ(test, fake_cfg.mbw_min, 0xf);
> +
> + fake_class.props.bwa_wd = 16;
> + fake_cfg.mbw_max = 0x4;
> + fake_cfg.mbw_min = 0;
> + bitmap_zero(fake_cfg.features, MPAM_FEATURE_LAST);
> + mpam_set_feature(mpam_feat_mbw_max, &fake_cfg);
> + mpam_extend_config(&fake_class, &fake_cfg);
> + KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_mbw_max, &fake_cfg));
> + KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_mbw_min, &fake_cfg));
> + KUNIT_EXPECT_EQ(test, fake_cfg.mbw_max, 0x4);
> + KUNIT_EXPECT_EQ(test, fake_cfg.mbw_min, 0x0);
> +}
> +
> static void test_mpam_reset_msc_bitmap(struct kunit *test)
> {
> char __iomem *buf = kunit_kzalloc(test, SZ_16K, GFP_KERNEL);
> @@ -378,6 +443,7 @@ static struct kunit_case mpam_devices_test_cases[] = {
> KUNIT_CASE(test_mpam_reset_msc_bitmap),
> KUNIT_CASE(test_mpam_enable_merge_features),
> KUNIT_CASE(test__props_mismatch),
> + KUNIT_CASE(test_mpam_extend_config),
> {}
> };
>
Thanks,
Ben
next prev parent reply other threads:[~2025-12-09 16:45 UTC|newest]
Thread overview: 95+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-12-05 21:58 [RFC PATCH 00/38] arm_mpam: Add KVM/arm64 and resctrl glue code James Morse
2025-12-05 21:58 ` [RFC PATCH 01/38] arm64: mpam: Context switch the MPAM registers James Morse
2025-12-05 23:53 ` Fenghua Yu
2025-12-09 15:08 ` Ben Horgan
2025-12-09 14:49 ` Ben Horgan
2025-12-12 12:30 ` Ben Horgan
2025-12-18 10:35 ` Jonathan Cameron
2025-12-18 14:52 ` Ben Horgan
2025-12-18 14:55 ` Ben Horgan
2025-12-18 15:38 ` Jonathan Cameron
2025-12-18 15:54 ` Ben Horgan
2025-12-05 21:58 ` [RFC PATCH 02/38] arm64: mpam: Re-initialise MPAM regs when CPU comes online James Morse
2025-12-09 15:13 ` Ben Horgan
2025-12-11 11:23 ` Ben Horgan
2025-12-11 11:32 ` Ben Horgan
2025-12-05 21:58 ` [RFC PATCH 03/38] arm64: mpam: Advertise the CPUs MPAM limits to the driver James Morse
2025-12-18 10:38 ` Jonathan Cameron
2025-12-05 21:58 ` [RFC PATCH 04/38] arm64: mpam: Add cpu_pm notifier to restore MPAM sysregs James Morse
2025-12-11 13:41 ` Ben Horgan
2025-12-05 21:58 ` [RFC PATCH 05/38] arm64: mpam: Add helpers to change a task or cpu's MPAM PARTID/PMG values James Morse
2025-12-18 10:44 ` Jonathan Cameron
2025-12-19 11:56 ` Ben Horgan
2025-12-05 21:58 ` [RFC PATCH 06/38] KVM: arm64: Force guest EL1 to use user-space's partid configuration James Morse
2025-12-09 15:32 ` Ben Horgan
2025-12-12 11:31 ` Ben Horgan
2025-12-05 21:58 ` [RFC PATCH 07/38] arm_mpam: resctrl: Add boilerplate cpuhp and domain allocation James Morse
2025-12-09 15:43 ` Ben Horgan
2025-12-18 11:30 ` Jonathan Cameron
2025-12-19 12:02 ` Ben Horgan
2025-12-22 11:48 ` Jonathan Cameron
2026-01-02 11:07 ` Ben Horgan
2025-12-19 12:17 ` Ben Horgan
2025-12-05 21:58 ` [RFC PATCH 08/38] arm_mpam: resctrl: Pick the caches we will use as resctrl resources James Morse
2025-12-09 15:57 ` Ben Horgan
2025-12-16 10:14 ` Ben Horgan
2025-12-18 11:38 ` Jonathan Cameron
2025-12-19 12:04 ` Ben Horgan
2025-12-05 21:58 ` [RFC PATCH 09/38] arm_mpam: resctrl: Implement resctrl_arch_reset_all_ctrls() James Morse
2025-12-05 21:58 ` [RFC PATCH 10/38] arm_mpam: resctrl: Add resctrl_arch_get_config() James Morse
2025-12-05 21:58 ` [RFC PATCH 11/38] arm_mpam: resctrl: Implement helpers to update configuration James Morse
2025-12-18 11:47 ` Jonathan Cameron
2025-12-05 21:58 ` [RFC PATCH 12/38] arm_mpam: resctrl: Add plumbing against arm64 task and cpu hooks James Morse
2025-12-05 21:58 ` [RFC PATCH 13/38] arm_mpam: resctrl: Add CDP emulation James Morse
2025-12-16 13:49 ` Ben Horgan
2025-12-16 14:24 ` Ben Horgan
2025-12-18 11:58 ` Jonathan Cameron
2025-12-05 21:58 ` [RFC PATCH 14/38] arm_mpam: resctrl: Add rmid index helpers James Morse
2025-12-05 21:58 ` [RFC PATCH 15/38] arm_mpam: resctrl: Convert to/from MPAMs fixed-point formats James Morse
2025-12-05 21:58 ` [RFC PATCH 16/38] arm_mpam: resctrl: Add support for 'MB' resource James Morse
2025-12-12 4:27 ` Gavin Shan
2025-12-16 15:56 ` Ben Horgan
2025-12-05 21:58 ` [RFC PATCH 17/38] arm_mpam: resctrl: Add kunit test for control format conversions James Morse
2025-12-05 21:58 ` [RFC PATCH 18/38] arm_mpam: resctrl: Add support for csu counters James Morse
2025-12-16 13:55 ` Ben Horgan
2025-12-18 13:20 ` Jonathan Cameron
2025-12-19 12:06 ` Ben Horgan
2025-12-05 21:58 ` [RFC PATCH 19/38] arm_mpam: resctrl: pick classes for use as mbm counters James Morse
2025-12-18 13:36 ` Jonathan Cameron
2025-12-05 21:58 ` [RFC PATCH 20/38] arm_mpam: resctrl: Pre-allocate free running monitors James Morse
2025-12-05 21:58 ` [RFC PATCH 21/38] arm_mpam: resctrl: Pre-allocate assignable monitors James Morse
2025-12-18 13:42 ` Jonathan Cameron
2025-12-05 21:58 ` [RFC PATCH 22/38] arm_mpam: resctrl: Add kunit test for ABMC/CDP interactions James Morse
2025-12-05 21:58 ` [RFC PATCH 23/38] arm_mpam: resctrl: Add resctrl_arch_config_cntr() for ABMC use James Morse
2025-12-05 21:58 ` [RFC PATCH 24/38] arm_mpam: resctrl: Allow resctrl to allocate monitors James Morse
2025-12-16 16:58 ` Ben Horgan
2025-12-18 13:49 ` Jonathan Cameron
2025-12-05 21:58 ` [RFC PATCH 25/38] arm_mpam: resctrl: Add resctrl_arch_rmid_read() and resctrl_arch_reset_rmid() James Morse
2025-12-18 13:53 ` Jonathan Cameron
2025-12-05 21:58 ` [RFC PATCH 26/38] arm_mpam: resctrl: Add resctrl_arch_cntr_read() & resctrl_arch_reset_cntr() James Morse
2025-12-05 21:58 ` [RFC PATCH 27/38] arm_mpam: resctrl: Add empty definitions for assorted resctrl functions James Morse
2025-12-09 16:31 ` Ben Horgan
2025-12-05 21:58 ` [RFC PATCH 28/38] arm64: mpam: Select ARCH_HAS_CPU_RESCTRL James Morse
2025-12-09 16:33 ` Ben Horgan
2025-12-18 13:55 ` Jonathan Cameron
2025-12-05 21:58 ` [RFC PATCH 29/38] arm_mpam: resctrl: Call resctrl_init() on platforms that can support resctrl James Morse
2025-12-05 21:58 ` [RFC PATCH 30/38] arm_mpam: resctrl: Call resctrl_exit() in the event of errors James Morse
2025-12-05 21:58 ` [RFC PATCH 31/38] arm_mpam: resctrl: Update the rmid reallocation limit James Morse
2025-12-06 0:06 ` Fenghua Yu
2025-12-09 16:36 ` Ben Horgan
2025-12-05 21:58 ` [RFC PATCH 32/38] arm_mpam: resctrl: Sort the order of the domain lists James Morse
2025-12-05 21:58 ` [RFC PATCH 33/38] arm_mpam: Generate a configuration for min controls James Morse
2025-12-09 16:45 ` Ben Horgan [this message]
2025-12-05 21:58 ` [RFC PATCH 34/38] arm_mpam: Add quirk framework James Morse
2025-12-18 14:04 ` Jonathan Cameron
2025-12-19 12:19 ` Ben Horgan
2025-12-05 21:58 ` [RFC PATCH 35/38] arm_mpam: Add workaround for T241-MPAM-1 James Morse
2025-12-10 12:20 ` Ben Horgan
2025-12-05 21:58 ` [RFC PATCH 36/38] arm_mpam: Add workaround for T241-MPAM-4 James Morse
2025-12-09 16:58 ` Ben Horgan
2025-12-05 21:59 ` [RFC PATCH 37/38] arm_mpam: Add workaround for T241-MPAM-6 James Morse
2025-12-09 17:06 ` Ben Horgan
2025-12-05 21:59 ` [RFC PATCH 38/38] arm_mpam: Quirk CMN-650's CSU NRDY behaviour James Morse
2025-12-09 14:40 ` [RFC PATCH 00/38] arm_mpam: Add KVM/arm64 and resctrl glue code Ben Horgan
2025-12-09 15:53 ` Peter Newman
2025-12-09 16:14 ` Ben Horgan
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=f00a0467-6f32-4105-b1b8-ca9490db57bf@arm.com \
--to=ben.horgan@arm.com \
--cc=amitsinght@marvell.com \
--cc=baisheng.gao@unisoc.com \
--cc=baolin.wang@linux.alibaba.com \
--cc=bobo.shaobowang@huawei.com \
--cc=carl@os.amperecomputing.com \
--cc=dave.martin@arm.com \
--cc=david@kernel.org \
--cc=dfustini@baylibre.com \
--cc=fenghuay@nvidia.com \
--cc=gshan@redhat.com \
--cc=james.morse@arm.com \
--cc=jonathan.cameron@huawei.com \
--cc=kobak@nvidia.com \
--cc=lcherian@marvell.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=peternewman@google.com \
--cc=punit.agrawal@oss.qualcomm.com \
--cc=quic_jiles@quicinc.com \
--cc=reinette.chatre@intel.com \
--cc=rohit.mathew@arm.com \
--cc=scott@os.amperecomputing.com \
--cc=sdonthineni@nvidia.com \
--cc=tan.shaopeng@fujitsu.com \
--cc=xhao@linux.alibaba.com \
--cc=zengheng4@huawei.com \
/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).