From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
To: "Aneesh Kumar K.V (Arm)" <aneesh.kumar@kernel.org>
Cc: <linux-coco@lists.linux.dev>, <kvmarm@lists.linux.dev>,
<linux-pci@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
<aik@amd.com>, <lukas@wunner.de>,
Samuel Ortiz <sameo@rivosinc.com>,
Xu Yilun <yilun.xu@linux.intel.com>,
Jason Gunthorpe <jgg@ziepe.ca>,
"Suzuki K Poulose" <Suzuki.Poulose@arm.com>,
Steven Price <steven.price@arm.com>,
Catalin Marinas <catalin.marinas@arm.com>,
Marc Zyngier <maz@kernel.org>, Will Deacon <will@kernel.org>,
Oliver Upton <oliver.upton@linux.dev>
Subject: Re: [RFC PATCH v1 30/38] coco: host: arm64: Add support for realm host interface (RHI)
Date: Wed, 30 Jul 2025 15:43:10 +0100 [thread overview]
Message-ID: <20250730154310.00003143@huawei.com> (raw)
In-Reply-To: <20250728135216.48084-31-aneesh.kumar@kernel.org>
On Mon, 28 Jul 2025 19:22:07 +0530
"Aneesh Kumar K.V (Arm)" <aneesh.kumar@kernel.org> wrote:
> Device assignment-related RHI calls result in a REC exit, which is
> handled by the tsm guest_request callback.
>
> Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
Comments below.
> ---
> arch/arm64/include/asm/rhi.h | 32 ++++++++++
> drivers/virt/coco/arm-cca-host/arm-cca.c | 68 ++++++++++++++++++++
> drivers/virt/coco/arm-cca-host/rmm-da.c | 81 ++++++++++++++++++++++++
> drivers/virt/coco/arm-cca-host/rmm-da.h | 4 ++
> include/linux/tsm.h | 3 +
> 5 files changed, 188 insertions(+)
> create mode 100644 arch/arm64/include/asm/rhi.h
> diff --git a/drivers/virt/coco/arm-cca-host/arm-cca.c b/drivers/virt/coco/arm-cca-host/arm-cca.c
> index be1296fb1bf2..0807fcf8d222 100644
> --- a/drivers/virt/coco/arm-cca-host/arm-cca.c
> +++ b/drivers/virt/coco/arm-cca-host/arm-cca.c
> +static int cca_tsm_guest_req(struct pci_dev *pdev, struct tsm_guest_req_info *info)
> +{
> + int ret;
> +
> + switch (info->type) {
> + case ARM_CCA_DA_OBJECT_SIZE:
> + {
> + int object_size;
> + struct da_object_size_req req;
> +
> + if (sizeof(req) != info->req_len)
> + return -EINVAL;
> +
> + if (copy_from_user(&req, info->req, info->req_len))
> + return -EFAULT;
> +
> + object_size = rme_get_da_object_size(pdev, req.object_type);
> + if (object_size > 0) {
> + if (info->resp_len < sizeof(object_size))
> + return -EINVAL;
> + if (copy_to_user(info->resp, &object_size, sizeof(object_size)))
> + return -EFAULT;
> + info->resp_len = sizeof(object_size);
> + ret = 0;
return 0;
then else isn't needed.
> + } else
#Style is {} on all legs if any need it.
> + /* error */
> + ret = object_size;
return object_size;
> + break;
> + }
> + case ARM_CCA_DA_OBJECT_READ:
> + {
> + int resp_len;
> + struct da_object_read_req req;
> +
> + if (sizeof(req) != info->req_len)
> + return -EINVAL;
> +
> + if (copy_from_user(&req, info->req, info->req_len))
> + return -EFAULT;
> +
> + resp_len = rme_da_object_read(pdev, req.object_type, req.offset,
> + info->resp_len,
> + info->resp);
> + if (resp_len > 0) {
> + info->resp_len = resp_len;
> + ret = 0;
Similar to above.
> + } else
> + /* error */
> + ret = resp_len;
> + break;
> + }
> + default:
> + ret = -EINVAL;
> + break;
> + }
> + return ret;
As you've probably figured out, I love an early return. This sort
of function shows why as it reduced indent etc in lots of places.
Here you mix and match. Maybe it will make sense later in the series though!
> +}
> diff --git a/drivers/virt/coco/arm-cca-host/rmm-da.c b/drivers/virt/coco/arm-cca-host/rmm-da.c
> index bef33e618fd3..c7da9d12f258 100644
> --- a/drivers/virt/coco/arm-cca-host/rmm-da.c
> +++ b/drivers/virt/coco/arm-cca-host/rmm-da.c
> @@ -10,7 +10,9 @@
> #include <keys/asymmetric-type.h>
> #include <keys/x509-parser.h>
> #include <linux/kvm_types.h>
> +#include <linux/kvm_host.h>
> #include <asm/kvm_rme.h>
> +#include <asm/kvm_emulate.h>
>
> #include "rmm-da.h"
>
> @@ -769,6 +771,85 @@ static int rme_exit_vdev_req_handler(struct realm_rec *rec)
> return 1;
> }
>
> +int rme_get_da_object_size(struct pci_dev *pdev, int type)
> +{
> + int ret = 0;
> + unsigned long len;
> + struct pci_tsm *tsm = pdev->tsm;
> + struct cca_host_dsc_pf0 *dsc_pf0;
> +
> + if (!tsm)
> + return -EINVAL;
> +
> + dsc_pf0 = to_cca_dsc_pf0(tsm->dsm_dev);
> +
> + /* Determine the buffer that should be used */
> + if (type == RHI_DA_OBJECT_INTERFACE_REPORT) {
> + len = dsc_pf0->interface_report.size;
> + } else if (type == RHI_DA_OBJECT_MEASUREMENT) {
> + len = dsc_pf0->measurements.size;
> + } else if (type == RHI_DA_OBJECT_CERTIFICATE) {
> + len = dsc_pf0->cert_chain.cache.size;
> + } else if (type == RHI_DA_OBJECT_VCA) {
> + len = dsc_pf0->vca.size;
> + } else {
> + ret = -EINVAL;
> + goto err_out;
> + }
> +
> + return len;
> +err_out:
Similar to below. This pattern just makes things more complex.
If we need to introduce a label, do it in the patch where you add
code to do something on error.
> + return ret;
> +}
> +
> +int rme_da_object_read(struct pci_dev *pdev, int type, unsigned long offset,
> + unsigned long max_len, void __user *user_buf)
> +{
> + void *buf;
> + int ret = 0;
> + unsigned long len;
> + struct cca_host_dsc_pf0 *dsc_pf0;
> + struct pci_tsm *tsm = pdev->tsm;
> +
> + if (!tsm)
> + return -EINVAL;
> +
> + dsc_pf0 = to_cca_dsc_pf0(tsm->dsm_dev);
> +
> + /* Determine the buffer that should be used */
> + if (type == RHI_DA_OBJECT_INTERFACE_REPORT) {
> + len = dsc_pf0->interface_report.size;
> + buf = dsc_pf0->interface_report.buf;
> + } else if (type == RHI_DA_OBJECT_MEASUREMENT) {
> + len = dsc_pf0->measurements.size;
> + buf = dsc_pf0->measurements.buf;
> + } else if (type == RHI_DA_OBJECT_CERTIFICATE) {
> + len = dsc_pf0->cert_chain.cache.size;
> + buf = dsc_pf0->cert_chain.cache.buf;
> + } else if (type == RHI_DA_OBJECT_VCA) {
> + len = dsc_pf0->vca.size;
> + buf = dsc_pf0->vca.buf;
> + } else {
> + ret = -EINVAL;
> + goto err_out;
> + }
> +
> + /* Assume that the buffer is large enough for the whole report */
> + if ((max_len - offset) < len) {
> + /* FIXME!! the error code */
> + ret = -ENOMEM;
> + goto err_out;
> + }
> +
> + if (copy_to_user(user_buf + offset, buf, len)) {
> + ret = -EIO;
> + goto err_out;
> + }
> + ret = len;
> +err_out:
Definitely makes sense to just return directly in the error paths above and
just return len here
> + return ret;
> +}
> +
> void rme_register_exit_handlers(void)
> {
> realm_exit_vdev_comm_handler = rme_exit_vdev_comm_handler;
> diff --git a/drivers/virt/coco/arm-cca-host/rmm-da.h b/drivers/virt/coco/arm-cca-host/rmm-da.h
> index cebddab8464d..457660ff3b69 100644
> --- a/drivers/virt/coco/arm-cca-host/rmm-da.h
> +++ b/drivers/virt/coco/arm-cca-host/rmm-da.h
> @@ -10,6 +10,7 @@
> #include <linux/pci-ide.h>
> #include <linux/pci-tsm.h>
> #include <asm/rmi_smc.h>
> +#include <asm/rhi.h>
>
> #define MAX_CACHE_OBJ_SIZE 4096
> struct cache_object {
> @@ -101,4 +102,7 @@ void *rme_create_vdev(struct realm *realm, struct pci_dev *pdev,
> void rme_unbind_vdev(struct realm *realm, struct pci_dev *pdev,
> struct pci_dev *pf0_dev);
> void rme_register_exit_handlers(void);
> +int rme_get_da_object_size(struct pci_dev *pdev, int type);
> +int rme_da_object_read(struct pci_dev *pdev, int type, unsigned long offset,
> + unsigned long max_len, void __user *user_buf);
> #endif
> diff --git a/include/linux/tsm.h b/include/linux/tsm.h
> index 497a3b4df5a0..e82046b0c7fa 100644
> --- a/include/linux/tsm.h
> +++ b/include/linux/tsm.h
> @@ -145,5 +145,8 @@ struct tsm_guest_req_info {
> size_t resp_len;
> };
>
> +#define ARM_CCA_DA_OBJECT_SIZE 0x1
> +#define ARM_CCA_DA_OBJECT_READ 0x2
> +
> int tsm_guest_req(struct device *dev, struct tsm_guest_req_info *info);
> #endif /* __TSM_H */
next prev parent reply other threads:[~2025-07-30 14:43 UTC|newest]
Thread overview: 158+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-07-28 13:51 [RFC PATCH v1 00/38] ARM CCA Device Assignment support Aneesh Kumar K.V (Arm)
2025-07-28 13:51 ` [RFC PATCH v1 01/38] tsm: Add tsm_bind/unbind helpers Aneesh Kumar K.V (Arm)
2025-07-28 13:51 ` [RFC PATCH v1 02/38] tsm: Move tsm core outside the host directory Aneesh Kumar K.V (Arm)
2025-07-28 13:51 ` [RFC PATCH v1 03/38] tsm: Move dsm_dev from pci_tdi to pci_tsm Aneesh Kumar K.V (Arm)
2025-08-04 21:52 ` Bjorn Helgaas
2025-08-05 9:24 ` Aneesh Kumar K.V
2025-07-28 13:51 ` [RFC PATCH v1 04/38] tsm: Support DMA Allocation from private memory Aneesh Kumar K.V (Arm)
2025-07-28 14:33 ` Jason Gunthorpe
2025-07-29 8:23 ` Aneesh Kumar K.V
2025-07-29 14:33 ` Jason Gunthorpe
2025-07-30 10:09 ` Suzuki K Poulose
2025-07-31 12:17 ` Jason Gunthorpe
2025-07-31 13:48 ` Suzuki K Poulose
2025-07-31 16:44 ` Jason Gunthorpe
2025-08-01 9:30 ` Suzuki K Poulose
2025-08-01 14:53 ` Jason Gunthorpe
2025-08-02 8:44 ` Aneesh Kumar K.V
2025-08-02 13:41 ` Jason Gunthorpe
2025-08-04 6:58 ` Aneesh Kumar K.V
2025-08-05 15:54 ` Jason Gunthorpe
2025-08-05 10:22 ` Alexey Kardashevskiy
2025-08-05 16:08 ` Jason Gunthorpe
2025-08-04 21:54 ` Bjorn Helgaas
2025-07-28 13:51 ` [RFC PATCH v1 05/38] tsm: Don't overload connect Aneesh Kumar K.V (Arm)
2025-08-04 22:00 ` Bjorn Helgaas
2025-07-28 13:51 ` [RFC PATCH v1 06/38] iommufd: Add and option to request for bar mapping with IORESOURCE_EXCLUSIVE Aneesh Kumar K.V (Arm)
2025-07-28 14:08 ` Jason Gunthorpe
2025-07-29 8:28 ` Aneesh Kumar K.V
2025-07-29 14:29 ` Jason Gunthorpe
2025-07-30 6:55 ` Xu Yilun
2025-07-31 12:22 ` Jason Gunthorpe
2025-08-05 2:26 ` Xu Yilun
2025-08-05 16:10 ` Jason Gunthorpe
2025-07-30 6:43 ` Xu Yilun
2025-08-06 21:18 ` dan.j.williams
2025-07-28 13:51 ` [RFC PATCH v1 07/38] iommufd/viommu: Add support to associate viommu with kvm instance Aneesh Kumar K.V (Arm)
2025-07-28 14:10 ` Jason Gunthorpe
2025-07-29 8:30 ` Aneesh Kumar K.V
2025-07-29 16:26 ` Jonathan Cameron
2025-07-29 23:16 ` Jason Gunthorpe
2025-07-28 13:51 ` [RFC PATCH v1 08/38] iommufd/tsm: Add tsm_op iommufd ioctls Aneesh Kumar K.V (Arm)
2025-07-29 16:34 ` Jonathan Cameron
2025-08-02 9:03 ` Aneesh Kumar K.V
2025-08-04 22:25 ` Bjorn Helgaas
2025-07-28 13:51 ` [RFC PATCH v1 09/38] iommufd/vdevice: Add TSM Guest request uAPI Aneesh Kumar K.V (Arm)
2025-08-04 22:03 ` Bjorn Helgaas
2025-07-28 13:51 ` [RFC PATCH v1 10/38] iommufd/vdevice: Add TSM map ioctl Aneesh Kumar K.V (Arm)
2025-07-28 14:17 ` Jason Gunthorpe
2025-07-29 8:37 ` Aneesh Kumar K.V
2025-07-29 14:31 ` Jason Gunthorpe
2025-08-04 2:32 ` Alexey Kardashevskiy
2025-08-04 8:28 ` Aneesh Kumar K.V
2025-08-05 1:29 ` Alexey Kardashevskiy
2025-08-05 15:48 ` Jason Gunthorpe
2025-07-28 13:51 ` [RFC PATCH v1 11/38] KVM: arm64: CCA: register host tsm platform device Aneesh Kumar K.V (Arm)
2025-07-29 17:10 ` Jonathan Cameron
2025-07-29 23:19 ` Jason Gunthorpe
2025-07-30 8:42 ` Aneesh Kumar K.V
2025-07-30 10:38 ` Jonathan Cameron
2025-07-30 12:23 ` Jonathan Cameron
2025-07-30 13:07 ` Greg KH
2025-07-31 12:11 ` Jason Gunthorpe
2025-07-31 13:22 ` Jonathan Cameron
2025-07-31 16:46 ` Jason Gunthorpe
2025-08-01 8:31 ` Greg KH
2025-08-02 0:54 ` dan.j.williams
2025-07-28 13:51 ` [RFC PATCH v1 12/38] coco: host: arm64: CCA host platform device driver Aneesh Kumar K.V (Arm)
2025-07-29 17:22 ` Jonathan Cameron
2025-07-29 23:22 ` Jason Gunthorpe
2025-07-30 10:28 ` Jonathan Cameron
2025-07-31 12:26 ` Jason Gunthorpe
2025-07-30 8:58 ` Aneesh Kumar K.V
2025-07-30 10:25 ` Jonathan Cameron
2025-07-28 13:51 ` [RFC PATCH v1 13/38] coco: host: arm64: Create a PDEV with rmm Aneesh Kumar K.V (Arm)
2025-07-30 12:39 ` Jonathan Cameron
2025-08-02 10:54 ` Aneesh Kumar K.V
2025-07-31 11:47 ` Arto Merilainen
2025-08-02 10:57 ` Aneesh Kumar K.V
2025-08-04 22:28 ` Bjorn Helgaas
2025-07-28 13:51 ` [RFC PATCH v1 14/38] coco: host: arm64: Device communication support Aneesh Kumar K.V (Arm)
2025-07-30 13:52 ` Jonathan Cameron
2025-07-31 12:28 ` Jason Gunthorpe
2025-08-04 4:17 ` Aneesh Kumar K.V
2025-08-04 22:29 ` Bjorn Helgaas
2025-07-28 13:51 ` [RFC PATCH v1 15/38] coco: host: arm64: Stop and destroy the physical device Aneesh Kumar K.V (Arm)
2025-07-30 13:57 ` Jonathan Cameron
2025-08-04 4:22 ` Aneesh Kumar K.V
2025-07-28 13:51 ` [RFC PATCH v1 16/38] X.509: Make certificate parser public Aneesh Kumar K.V (Arm)
2025-07-28 13:51 ` [RFC PATCH v1 17/38] X.509: Parse Subject Alternative Name in certificates Aneesh Kumar K.V (Arm)
2025-07-28 13:51 ` [RFC PATCH v1 18/38] X.509: Move certificate length retrieval into new helper Aneesh Kumar K.V (Arm)
2025-08-04 22:27 ` Bjorn Helgaas
2025-07-28 13:51 ` [RFC PATCH v1 19/38] coco: host: arm64: set_pubkey support Aneesh Kumar K.V (Arm)
2025-07-30 14:08 ` Jonathan Cameron
2025-08-04 4:29 ` Aneesh Kumar K.V
2025-08-04 22:26 ` Bjorn Helgaas
2025-07-28 13:51 ` [RFC PATCH v1 20/38] coco: host: arm64: Add support for creating a virtual device Aneesh Kumar K.V (Arm)
2025-07-30 14:12 ` Jonathan Cameron
2025-07-28 13:51 ` [RFC PATCH v1 21/38] coco: host: arm64: Add support for virtual device communication Aneesh Kumar K.V (Arm)
2025-07-30 14:13 ` Jonathan Cameron
2025-08-04 4:45 ` Aneesh Kumar K.V
2025-07-28 13:51 ` [RFC PATCH v1 22/38] coco: host: arm64: Stop and destroy virtual device Aneesh Kumar K.V (Arm)
2025-07-30 14:15 ` Jonathan Cameron
2025-07-28 13:52 ` [RFC PATCH v1 23/38] coco: guest: arm64: Update arm CCA guest driver Aneesh Kumar K.V (Arm)
2025-07-30 14:22 ` Jonathan Cameron
2025-07-31 12:29 ` Jason Gunthorpe
2025-07-31 13:54 ` Jonathan Cameron
2025-07-28 13:52 ` [RFC PATCH v1 24/38] arm64: CCA: Register guest tsm callback Aneesh Kumar K.V (Arm)
2025-07-30 14:26 ` Jonathan Cameron
2025-08-04 4:50 ` Aneesh Kumar K.V
2025-07-28 13:52 ` [RFC PATCH v1 25/38] cca: guest: arm64: Realm device lock support Aneesh Kumar K.V (Arm)
2025-07-30 14:32 ` Jonathan Cameron
2025-07-28 13:52 ` [RFC PATCH v1 26/38] KVM: arm64: Add exit handler related to device assignment Aneesh Kumar K.V (Arm)
2025-07-30 14:35 ` Jonathan Cameron
2025-07-28 13:52 ` [RFC PATCH v1 27/38] coco: host: arm64: add RSI_RDEV_GET_INSTANCE_ID related exit handler Aneesh Kumar K.V (Arm)
2025-07-28 13:52 ` [RFC PATCH v1 28/38] coco: host: arm64: Add support for device communication " Aneesh Kumar K.V (Arm)
2025-07-28 13:52 ` [RFC PATCH v1 29/38] coco: guest: arm64: Add support for collecting interface reports Aneesh Kumar K.V (Arm)
2025-07-28 13:52 ` [RFC PATCH v1 30/38] coco: host: arm64: Add support for realm host interface (RHI) Aneesh Kumar K.V (Arm)
2025-07-30 14:43 ` Jonathan Cameron [this message]
2025-07-28 13:52 ` [RFC PATCH v1 31/38] coco: guest: arm64: Add support for fetching interface report and certificate chain from host Aneesh Kumar K.V (Arm)
2025-07-30 14:46 ` Jonathan Cameron
2025-07-28 13:52 ` [RFC PATCH v1 32/38] coco: guest: arm64: Add support for guest initiated TDI bind/unbind Aneesh Kumar K.V (Arm)
2025-07-30 14:51 ` Jonathan Cameron
2025-08-04 22:28 ` Bjorn Helgaas
2025-07-28 13:52 ` [RFC PATCH v1 33/38] KVM: arm64: CCA: handle dev mem map/unmap Aneesh Kumar K.V (Arm)
2025-07-28 13:52 ` [RFC PATCH v1 34/38] coco: guest: arm64: Validate mmio range found in the interface report Aneesh Kumar K.V (Arm)
2025-07-30 15:06 ` Jonathan Cameron
2025-07-31 11:39 ` Arto Merilainen
2025-07-31 16:53 ` Jason Gunthorpe
2025-08-04 6:37 ` Aneesh Kumar K.V
2025-08-04 8:27 ` Arto Merilainen
2025-08-04 22:31 ` Bjorn Helgaas
2025-07-28 13:52 ` [RFC PATCH v1 35/38] coco: guest: arm64: Add Realm device start and stop support Aneesh Kumar K.V (Arm)
2025-07-31 10:40 ` Jonathan Cameron
2025-08-04 22:27 ` Bjorn Helgaas
2025-07-28 13:52 ` [RFC PATCH v1 36/38] KVM: arm64: CCA: enable DA in realm create parameters Aneesh Kumar K.V (Arm)
2025-08-04 22:31 ` Bjorn Helgaas
2025-07-28 13:52 ` [RFC PATCH v1 37/38] coco: guest: arm64: Add support for fetching device measurements Aneesh Kumar K.V (Arm)
2025-07-31 10:16 ` Jonathan Cameron
2025-08-04 22:27 ` Bjorn Helgaas
2025-07-28 13:52 ` [RFC PATCH v1 38/38] coco: guest: arm64: Add support for fetching device info Aneesh Kumar K.V (Arm)
2025-07-31 10:36 ` Jonathan Cameron
2025-08-04 6:48 ` Aneesh Kumar K.V
2025-08-04 10:23 ` Jonathan Cameron
2025-08-08 23:37 ` Eric Biggers
2025-07-30 16:03 ` [RFC PATCH v1 00/38] ARM CCA Device Assignment support Jason Gunthorpe
2025-08-01 2:07 ` dan.j.williams
2025-08-01 15:51 ` Jason Gunthorpe
2025-08-01 21:19 ` dan.j.williams
2025-08-02 14:17 ` Jason Gunthorpe
2025-08-02 23:50 ` dan.j.williams
2025-08-03 22:26 ` Jason Gunthorpe
2025-08-05 5:07 ` Aneesh Kumar K.V
2025-08-05 17:27 ` Jason Gunthorpe
2025-08-05 18:27 ` dan.j.williams
2025-08-05 18:42 ` Jason Gunthorpe
2025-08-05 19:06 ` dan.j.williams
2025-08-05 19:38 ` Jason Gunthorpe
2025-08-05 4:50 ` Aneesh Kumar K.V
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=20250730154310.00003143@huawei.com \
--to=jonathan.cameron@huawei.com \
--cc=Suzuki.Poulose@arm.com \
--cc=aik@amd.com \
--cc=aneesh.kumar@kernel.org \
--cc=catalin.marinas@arm.com \
--cc=jgg@ziepe.ca \
--cc=kvmarm@lists.linux.dev \
--cc=linux-coco@lists.linux.dev \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=lukas@wunner.de \
--cc=maz@kernel.org \
--cc=oliver.upton@linux.dev \
--cc=sameo@rivosinc.com \
--cc=steven.price@arm.com \
--cc=will@kernel.org \
--cc=yilun.xu@linux.intel.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).