From: Eric Auger <eric.auger-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> To: eric.auger.pro-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org, eric.auger-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org, iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org, linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, kvm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, kvmarm-FPEHb7Xf0XXUo1n7N8X6UoWGPAHP3yOg@public.gmane.org, joro-zLv9SwRftAIdnm+yROfE0A@public.gmane.org, alex.williamson-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org, jacob.jun.pan-VuQAYsv1563Yd54FQh9/CA@public.gmane.org, yi.l.liu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org, jean-philippe.brucker-5wv7dgnIgG8@public.gmane.org, will.deacon-5wv7dgnIgG8@public.gmane.org, robin.murphy-5wv7dgnIgG8@public.gmane.org Cc: peter.maydell-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org, kevin.tian-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org, vincent.stehle-5wv7dgnIgG8@public.gmane.org, ashok.raj-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org, marc.zyngier-5wv7dgnIgG8@public.gmane.org, christoffer.dall-5wv7dgnIgG8@public.gmane.org Subject: [PATCH v7 12/23] iommu/smmuv3: Get prepared for nested stage support Date: Mon, 8 Apr 2019 14:19:00 +0200 [thread overview] Message-ID: <20190408121911.24103-13-eric.auger@redhat.com> (raw) In-Reply-To: <20190408121911.24103-1-eric.auger-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> To allow nested stage support, we need to store both stage 1 and stage 2 configurations (and remove the former union). A nested setup is characterized by both s1_cfg and s2_cfg set. We introduce a new ste.abort field that will be set upon guest stage1 configuration passing. If s1_cfg is NULL and ste.abort is set, traffic can't pass. If ste.abort is not set, S1 is bypassed. arm_smmu_write_strtab_ent() is modified to write both stage fields in the STE and deal with the abort field. In nested mode, only stage 2 is "finalized" as the host does not own/configure the stage 1 context descriptor, guest does. Signed-off-by: Eric Auger <eric.auger-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> --- v4 -> v5: - reset ste.abort on detach v3 -> v4: - s1_cfg.nested_abort and nested_bypass removed. - s/ste.nested/ste.abort - arm_smmu_write_strtab_ent modifications with introduction of local abort, bypass and translate local variables - comment updated v1 -> v2: - invalidate the STE before moving from a live STE config to another - add the nested_abort and nested_bypass fields --- drivers/iommu/arm-smmu-v3.c | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 21d027695181..e22e944ffc05 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -211,6 +211,7 @@ #define STRTAB_STE_0_CFG_BYPASS 4 #define STRTAB_STE_0_CFG_S1_TRANS 5 #define STRTAB_STE_0_CFG_S2_TRANS 6 +#define STRTAB_STE_0_CFG_NESTED 7 #define STRTAB_STE_0_S1FMT GENMASK_ULL(5, 4) #define STRTAB_STE_0_S1FMT_LINEAR 0 @@ -514,6 +515,7 @@ struct arm_smmu_strtab_ent { * configured according to the domain type. */ bool assigned; + bool abort; struct arm_smmu_s1_cfg *s1_cfg; struct arm_smmu_s2_cfg *s2_cfg; }; @@ -628,10 +630,8 @@ struct arm_smmu_domain { bool non_strict; enum arm_smmu_domain_stage stage; - union { - struct arm_smmu_s1_cfg s1_cfg; - struct arm_smmu_s2_cfg s2_cfg; - }; + struct arm_smmu_s1_cfg s1_cfg; + struct arm_smmu_s2_cfg s2_cfg; struct iommu_domain domain; @@ -1108,12 +1108,13 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid, __le64 *dst, struct arm_smmu_strtab_ent *ste) { /* - * This is hideously complicated, but we only really care about - * three cases at the moment: + * We care about the following transitions: * * 1. Invalid (all zero) -> bypass/fault (init) - * 2. Bypass/fault -> translation/bypass (attach) - * 3. Translation/bypass -> bypass/fault (detach) + * 2. Bypass/fault -> single stage translation/bypass (attach) + * 3. single stage Translation/bypass -> bypass/fault (detach) + * 4. S2 -> S1 + S2 (attach_pasid_table) + * 5. S1 + S2 -> S2 (detach_pasid_table) * * Given that we can't update the STE atomically and the SMMU * doesn't read the thing in a defined order, that leaves us @@ -1124,7 +1125,7 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid, * 3. Update Config, sync */ u64 val = le64_to_cpu(dst[0]); - bool ste_live = false; + bool abort, bypass, translate, ste_live = false; struct arm_smmu_cmdq_ent prefetch_cmd = { .opcode = CMDQ_OP_PREFETCH_CFG, .prefetch = { @@ -1138,11 +1139,11 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid, break; case STRTAB_STE_0_CFG_S1_TRANS: case STRTAB_STE_0_CFG_S2_TRANS: + case STRTAB_STE_0_CFG_NESTED: ste_live = true; break; case STRTAB_STE_0_CFG_ABORT: - if (disable_bypass) - break; + break; default: BUG(); /* STE corruption */ } @@ -1152,8 +1153,13 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid, val = STRTAB_STE_0_V; /* Bypass/fault */ - if (!ste->assigned || !(ste->s1_cfg || ste->s2_cfg)) { - if (!ste->assigned && disable_bypass) + + abort = (!ste->assigned && disable_bypass) || ste->abort; + translate = ste->s1_cfg || ste->s2_cfg; + bypass = !abort && !translate; + + if (abort || bypass) { + if (abort) val |= FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_ABORT); else val |= FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_BYPASS); @@ -1172,7 +1178,6 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid, } if (ste->s1_cfg) { - BUG_ON(ste_live); dst[1] = cpu_to_le64( FIELD_PREP(STRTAB_STE_1_S1CIR, STRTAB_STE_1_S1C_CACHE_WBRA) | FIELD_PREP(STRTAB_STE_1_S1COR, STRTAB_STE_1_S1C_CACHE_WBRA) | @@ -1191,7 +1196,6 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid, } if (ste->s2_cfg) { - BUG_ON(ste_live); dst[2] = cpu_to_le64( FIELD_PREP(STRTAB_STE_2_S2VMID, ste->s2_cfg->vmid) | FIELD_PREP(STRTAB_STE_2_VTCR, ste->s2_cfg->vtcr) | @@ -1773,6 +1777,7 @@ static void arm_smmu_detach_dev(struct device *dev) } master->ste.assigned = false; + master->ste.abort = false; arm_smmu_install_ste_for_dev(fwspec); } -- 2.20.1
WARNING: multiple messages have this Message-ID (diff)
From: Eric Auger <eric.auger@redhat.com> To: eric.auger.pro@gmail.com, eric.auger@redhat.com, iommu@lists.linux-foundation.org, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu, joro@8bytes.org, alex.williamson@redhat.com, jacob.jun.pan@linux.intel.com, yi.l.liu@intel.com, jean-philippe.brucker@arm.com, will.deacon@arm.com, robin.murphy@arm.com Cc: kevin.tian@intel.com, vincent.stehle@arm.com, ashok.raj@intel.com, marc.zyngier@arm.com Subject: [PATCH v7 12/23] iommu/smmuv3: Get prepared for nested stage support Date: Mon, 8 Apr 2019 14:19:00 +0200 [thread overview] Message-ID: <20190408121911.24103-13-eric.auger@redhat.com> (raw) Message-ID: <20190408121900.MC8g_QQStxD3V2h6Nxj60sU6IOLphiPD6ENRDE5HVsg@z> (raw) In-Reply-To: <20190408121911.24103-1-eric.auger@redhat.com> To allow nested stage support, we need to store both stage 1 and stage 2 configurations (and remove the former union). A nested setup is characterized by both s1_cfg and s2_cfg set. We introduce a new ste.abort field that will be set upon guest stage1 configuration passing. If s1_cfg is NULL and ste.abort is set, traffic can't pass. If ste.abort is not set, S1 is bypassed. arm_smmu_write_strtab_ent() is modified to write both stage fields in the STE and deal with the abort field. In nested mode, only stage 2 is "finalized" as the host does not own/configure the stage 1 context descriptor, guest does. Signed-off-by: Eric Auger <eric.auger@redhat.com> --- v4 -> v5: - reset ste.abort on detach v3 -> v4: - s1_cfg.nested_abort and nested_bypass removed. - s/ste.nested/ste.abort - arm_smmu_write_strtab_ent modifications with introduction of local abort, bypass and translate local variables - comment updated v1 -> v2: - invalidate the STE before moving from a live STE config to another - add the nested_abort and nested_bypass fields --- drivers/iommu/arm-smmu-v3.c | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 21d027695181..e22e944ffc05 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -211,6 +211,7 @@ #define STRTAB_STE_0_CFG_BYPASS 4 #define STRTAB_STE_0_CFG_S1_TRANS 5 #define STRTAB_STE_0_CFG_S2_TRANS 6 +#define STRTAB_STE_0_CFG_NESTED 7 #define STRTAB_STE_0_S1FMT GENMASK_ULL(5, 4) #define STRTAB_STE_0_S1FMT_LINEAR 0 @@ -514,6 +515,7 @@ struct arm_smmu_strtab_ent { * configured according to the domain type. */ bool assigned; + bool abort; struct arm_smmu_s1_cfg *s1_cfg; struct arm_smmu_s2_cfg *s2_cfg; }; @@ -628,10 +630,8 @@ struct arm_smmu_domain { bool non_strict; enum arm_smmu_domain_stage stage; - union { - struct arm_smmu_s1_cfg s1_cfg; - struct arm_smmu_s2_cfg s2_cfg; - }; + struct arm_smmu_s1_cfg s1_cfg; + struct arm_smmu_s2_cfg s2_cfg; struct iommu_domain domain; @@ -1108,12 +1108,13 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid, __le64 *dst, struct arm_smmu_strtab_ent *ste) { /* - * This is hideously complicated, but we only really care about - * three cases at the moment: + * We care about the following transitions: * * 1. Invalid (all zero) -> bypass/fault (init) - * 2. Bypass/fault -> translation/bypass (attach) - * 3. Translation/bypass -> bypass/fault (detach) + * 2. Bypass/fault -> single stage translation/bypass (attach) + * 3. single stage Translation/bypass -> bypass/fault (detach) + * 4. S2 -> S1 + S2 (attach_pasid_table) + * 5. S1 + S2 -> S2 (detach_pasid_table) * * Given that we can't update the STE atomically and the SMMU * doesn't read the thing in a defined order, that leaves us @@ -1124,7 +1125,7 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid, * 3. Update Config, sync */ u64 val = le64_to_cpu(dst[0]); - bool ste_live = false; + bool abort, bypass, translate, ste_live = false; struct arm_smmu_cmdq_ent prefetch_cmd = { .opcode = CMDQ_OP_PREFETCH_CFG, .prefetch = { @@ -1138,11 +1139,11 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid, break; case STRTAB_STE_0_CFG_S1_TRANS: case STRTAB_STE_0_CFG_S2_TRANS: + case STRTAB_STE_0_CFG_NESTED: ste_live = true; break; case STRTAB_STE_0_CFG_ABORT: - if (disable_bypass) - break; + break; default: BUG(); /* STE corruption */ } @@ -1152,8 +1153,13 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid, val = STRTAB_STE_0_V; /* Bypass/fault */ - if (!ste->assigned || !(ste->s1_cfg || ste->s2_cfg)) { - if (!ste->assigned && disable_bypass) + + abort = (!ste->assigned && disable_bypass) || ste->abort; + translate = ste->s1_cfg || ste->s2_cfg; + bypass = !abort && !translate; + + if (abort || bypass) { + if (abort) val |= FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_ABORT); else val |= FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_BYPASS); @@ -1172,7 +1178,6 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid, } if (ste->s1_cfg) { - BUG_ON(ste_live); dst[1] = cpu_to_le64( FIELD_PREP(STRTAB_STE_1_S1CIR, STRTAB_STE_1_S1C_CACHE_WBRA) | FIELD_PREP(STRTAB_STE_1_S1COR, STRTAB_STE_1_S1C_CACHE_WBRA) | @@ -1191,7 +1196,6 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid, } if (ste->s2_cfg) { - BUG_ON(ste_live); dst[2] = cpu_to_le64( FIELD_PREP(STRTAB_STE_2_S2VMID, ste->s2_cfg->vmid) | FIELD_PREP(STRTAB_STE_2_VTCR, ste->s2_cfg->vtcr) | @@ -1773,6 +1777,7 @@ static void arm_smmu_detach_dev(struct device *dev) } master->ste.assigned = false; + master->ste.abort = false; arm_smmu_install_ste_for_dev(fwspec); } -- 2.20.1 _______________________________________________ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
next prev parent reply other threads:[~2019-04-08 12:19 UTC|newest] Thread overview: 83+ messages / expand[flat|nested] mbox.gz Atom feed top 2019-04-08 12:18 [PATCH v7 00/23] SMMUv3 Nested Stage Setup Eric Auger 2019-04-08 12:18 ` Eric Auger 2019-04-08 12:18 ` [PATCH v7 01/23] driver core: add per device iommu param Eric Auger 2019-04-08 12:18 ` Eric Auger 2019-04-08 12:18 ` [PATCH v7 02/23] iommu: introduce device fault data Eric Auger 2019-04-08 12:18 ` Eric Auger 2019-04-08 12:18 ` [PATCH v7 03/23] iommu: introduce device fault report API Eric Auger 2019-04-08 12:18 ` Eric Auger 2019-04-08 12:18 ` [PATCH v7 04/23] iommu: Introduce attach/detach_pasid_table API Eric Auger 2019-04-08 12:18 ` Eric Auger 2019-05-15 12:09 ` Jean-Philippe Brucker 2019-05-15 13:06 ` Auger Eric 2019-05-15 15:57 ` Jean-Philippe Brucker 2019-04-08 12:18 ` [PATCH v7 06/23] iommu: Introduce bind/unbind_guest_msi Eric Auger 2019-04-08 12:18 ` Eric Auger 2019-05-08 13:59 ` Robin Murphy 2019-05-10 14:35 ` Auger Eric 2019-04-08 12:18 ` [PATCH v7 07/23] vfio: VFIO_IOMMU_ATTACH/DETACH_PASID_TABLE Eric Auger 2019-04-08 12:18 ` Eric Auger 2019-04-08 12:18 ` [PATCH v7 08/23] vfio: VFIO_IOMMU_CACHE_INVALIDATE Eric Auger 2019-04-08 12:18 ` Eric Auger 2019-04-08 12:18 ` [PATCH v7 10/23] iommu/arm-smmu-v3: Link domains and devices Eric Auger 2019-04-08 12:18 ` Eric Auger 2019-04-08 12:18 ` [PATCH v7 11/23] iommu/arm-smmu-v3: Maintain a SID->device structure Eric Auger 2019-04-08 12:18 ` Eric Auger 2019-05-08 14:05 ` Robin Murphy 2019-05-08 18:31 ` Jean-Philippe Brucker 2019-04-08 12:19 ` [PATCH v7 14/23] iommu/smmuv3: Implement cache_invalidate Eric Auger 2019-04-08 12:19 ` Eric Auger 2019-05-08 15:01 ` Robin Murphy 2019-05-13 12:16 ` Auger Eric 2019-05-13 14:01 ` Robin Murphy 2019-05-13 14:04 ` Auger Eric 2019-04-08 12:19 ` [PATCH v7 15/23] dma-iommu: Implement NESTED_MSI cookie Eric Auger 2019-04-08 12:19 ` Eric Auger 2019-05-08 16:42 ` Robin Murphy 2019-04-08 12:19 ` [PATCH v7 17/23] iommu/smmuv3: Implement bind/unbind_guest_msi Eric Auger 2019-04-08 12:19 ` Eric Auger 2019-04-08 12:19 ` [PATCH v7 18/23] iommu/smmuv3: Report non recoverable faults Eric Auger 2019-04-08 12:19 ` Eric Auger 2019-05-08 17:20 ` Robin Murphy 2019-05-13 7:46 ` Auger Eric 2019-05-13 11:54 ` Robin Murphy 2019-05-13 12:32 ` Auger Eric 2019-05-13 13:47 ` Robin Murphy 2019-04-08 12:19 ` [PATCH v7 19/23] vfio-pci: Add a new VFIO_REGION_TYPE_NESTED region type Eric Auger 2019-04-08 12:19 ` Eric Auger 2019-04-08 12:19 ` [PATCH v7 20/23] vfio-pci: Register an iommu fault handler Eric Auger 2019-04-08 12:19 ` Eric Auger [not found] ` <20190408121911.24103-1-eric.auger-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> 2019-04-08 12:18 ` [PATCH v7 05/23] iommu: Introduce cache_invalidate API Eric Auger 2019-04-08 12:18 ` Eric Auger 2019-05-01 10:38 ` Jean-Philippe Brucker 2019-05-01 10:38 ` Jean-Philippe Brucker 2019-05-02 6:58 ` Auger Eric 2019-05-02 6:58 ` Auger Eric 2019-05-02 10:53 ` Jean-Philippe Brucker 2019-05-02 10:53 ` Jean-Philippe Brucker 2019-05-02 16:46 ` Jacob Pan 2019-05-02 16:46 ` Jacob Pan 2019-05-07 11:45 ` Jean-Philippe Brucker 2019-04-08 12:18 ` [PATCH v7 09/23] vfio: VFIO_IOMMU_BIND/UNBIND_MSI Eric Auger 2019-04-08 12:18 ` Eric Auger 2019-04-08 12:19 ` Eric Auger [this message] 2019-04-08 12:19 ` [PATCH v7 12/23] iommu/smmuv3: Get prepared for nested stage support Eric Auger 2019-05-08 14:24 ` Robin Murphy 2019-05-10 14:34 ` Auger Eric 2019-05-13 11:43 ` Robin Murphy 2019-05-13 14:40 ` Auger Eric 2019-04-08 12:19 ` [PATCH v7 13/23] iommu/smmuv3: Implement attach/detach_pasid_table Eric Auger 2019-04-08 12:19 ` Eric Auger 2019-05-08 14:38 ` Robin Murphy 2019-05-10 14:35 ` Auger Eric 2019-05-13 12:04 ` Robin Murphy 2019-04-08 12:19 ` [PATCH v7 16/23] iommu/smmuv3: Nested mode single MSI doorbell per domain enforcement Eric Auger 2019-04-08 12:19 ` Eric Auger 2019-04-08 12:19 ` [PATCH v7 21/23] vfio_pci: Allow to mmap the fault queue Eric Auger 2019-04-08 12:19 ` Eric Auger 2019-04-08 12:19 ` [PATCH v7 22/23] vfio-pci: Add VFIO_PCI_DMA_FAULT_IRQ_INDEX Eric Auger 2019-04-08 12:19 ` Eric Auger 2019-04-08 12:19 ` [PATCH v7 23/23] vfio: Document nested stage control Eric Auger 2019-04-08 12:19 ` Eric Auger 2019-04-30 7:09 ` [PATCH v7 00/23] SMMUv3 Nested Stage Setup Auger Eric 2019-04-30 7:09 ` Auger Eric
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=20190408121911.24103-13-eric.auger@redhat.com \ --to=eric.auger-h+wxahxf7alqt0dzr+alfa@public.gmane.org \ --cc=alex.williamson-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org \ --cc=ashok.raj-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \ --cc=christoffer.dall-5wv7dgnIgG8@public.gmane.org \ --cc=eric.auger.pro-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \ --cc=iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org \ --cc=jacob.jun.pan-VuQAYsv1563Yd54FQh9/CA@public.gmane.org \ --cc=jean-philippe.brucker-5wv7dgnIgG8@public.gmane.org \ --cc=joro-zLv9SwRftAIdnm+yROfE0A@public.gmane.org \ --cc=kevin.tian-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \ --cc=kvm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \ --cc=kvmarm-FPEHb7Xf0XXUo1n7N8X6UoWGPAHP3yOg@public.gmane.org \ --cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \ --cc=marc.zyngier-5wv7dgnIgG8@public.gmane.org \ --cc=peter.maydell-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org \ --cc=robin.murphy-5wv7dgnIgG8@public.gmane.org \ --cc=vincent.stehle-5wv7dgnIgG8@public.gmane.org \ --cc=will.deacon-5wv7dgnIgG8@public.gmane.org \ --cc=yi.l.liu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.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: linkBe 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).