linux-coco.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
From: Alexey Kardashevskiy <aik@amd.com>
To: <x86@kernel.org>
Cc: <kvm@vger.kernel.org>, <linux-crypto@vger.kernel.org>,
	<linux-pci@vger.kernel.org>, <linux-arch@vger.kernel.org>,
	"Sean Christopherson" <seanjc@google.com>,
	Paolo Bonzini <pbonzini@redhat.com>,
	"Tom Lendacky" <thomas.lendacky@amd.com>,
	Ashish Kalra <ashish.kalra@amd.com>,
	Joerg Roedel <joro@8bytes.org>,
	Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>,
	Robin Murphy <robin.murphy@arm.com>,
	"Jason Gunthorpe" <jgg@ziepe.ca>,
	Kevin Tian <kevin.tian@intel.com>,
	Bjorn Helgaas <bhelgaas@google.com>,
	Dan Williams <dan.j.williams@intel.com>,
	"Christoph Hellwig" <hch@lst.de>,
	Nikunj A Dadhania <nikunj@amd.com>,
	Michael Roth <michael.roth@amd.com>,
	Vasant Hegde <vasant.hegde@amd.com>,
	Joao Martins <joao.m.martins@oracle.com>,
	Nicolin Chen <nicolinc@nvidia.com>,
	Lu Baolu <baolu.lu@linux.intel.com>,
	Steve Sistare <steven.sistare@oracle.com>,
	"Lukas Wunner" <lukas@wunner.de>,
	Jonathan Cameron <Jonathan.Cameron@huawei.com>,
	Suzuki K Poulose <suzuki.poulose@arm.com>,
	Dionna Glaze <dionnaglaze@google.com>,
	Yi Liu <yi.l.liu@intel.com>, <iommu@lists.linux.dev>,
	<linux-coco@lists.linux.dev>, Zhi Wang <zhiw@nvidia.com>,
	AXu Yilun <yilun.xu@linux.intel.com>,
	"Aneesh Kumar K . V" <aneesh.kumar@kernel.org>,
	Alexey Kardashevskiy <aik@amd.com>
Subject: [RFC PATCH v2 08/22] pci/tsm: Add PCI driver for TSM
Date: Tue, 18 Feb 2025 22:09:55 +1100	[thread overview]
Message-ID: <20250218111017.491719-9-aik@amd.com> (raw)
In-Reply-To: <20250218111017.491719-1-aik@amd.com>

The PCI TSM module scans the PCI bus to initialize a TSM context for
physical ("TDEV") and virtual ("TDI") functions. It also implements
bus operations which at the moment is just an SPDM bouncer which talks
to the PF's DOE mailboxes.

The purpose of this module is to keep drivers/virt/coco/(guest|host)
unaware of PCI as much as possible (which is not always the case).

This module does not add new sysfs interfaces.

Signed-off-by: Alexey Kardashevskiy <aik@amd.com>
---
 drivers/pci/Makefile          |   3 +
 include/uapi/linux/pci_regs.h |   1 +
 drivers/pci/tsm.c             | 233 ++++++++++++++++++++
 drivers/pci/Kconfig           |  15 ++
 4 files changed, 252 insertions(+)

diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 8050b04cc350..59d774bf9c32 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -43,6 +43,9 @@ obj-$(CONFIG_PCI_CMA)		+= cma.o cma.asn1.o
 $(obj)/cma.o:			$(obj)/cma.asn1.h
 $(obj)/cma.asn1.o:		$(obj)/cma.asn1.c $(obj)/cma.asn1.h
 
+tsm_pci-y			:= tsm.o
+obj-$(CONFIG_PCI_TSM)		+= tsm_pci.o
+
 # Endpoint library must be initialized before its users
 obj-$(CONFIG_PCI_ENDPOINT)	+= endpoint/
 
diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
index 15bd8e2b3cf5..9c4a1995da8c 100644
--- a/include/uapi/linux/pci_regs.h
+++ b/include/uapi/linux/pci_regs.h
@@ -499,6 +499,7 @@
 #define  PCI_EXP_DEVCAP_PWR_VAL	0x03fc0000 /* Slot Power Limit Value */
 #define  PCI_EXP_DEVCAP_PWR_SCL	0x0c000000 /* Slot Power Limit Scale */
 #define  PCI_EXP_DEVCAP_FLR     0x10000000 /* Function Level Reset */
+#define  PCI_EXP_DEVCAP_TEE     0x40000000 /* TEE I/O (TDISP) Support */
 #define PCI_EXP_DEVCTL		0x08	/* Device Control */
 #define  PCI_EXP_DEVCTL_CERE	0x0001	/* Correctable Error Reporting En. */
 #define  PCI_EXP_DEVCTL_NFERE	0x0002	/* Non-Fatal Error Reporting Enable */
diff --git a/drivers/pci/tsm.c b/drivers/pci/tsm.c
new file mode 100644
index 000000000000..1539db584887
--- /dev/null
+++ b/drivers/pci/tsm.c
@@ -0,0 +1,233 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * TEE Security Manager for the TEE Device Interface Security Protocol
+ * (TDISP, PCIe r6.1 sec 11)
+ *
+ * Copyright(c) 2024 Intel Corporation. All rights reserved.
+ */
+
+#define dev_fmt(fmt) "TSM: " fmt
+
+#include <linux/pci.h>
+#include <linux/pci-doe.h>
+#include <linux/sysfs.h>
+#include <linux/xarray.h>
+#include <linux/module.h>
+#include <linux/pci-ide.h>
+#include <linux/tsm.h>
+
+#define DRIVER_VERSION	"0.1"
+#define DRIVER_AUTHOR	"aik@amd.com"
+#define DRIVER_DESC	"TSM TDISP library"
+
+static bool is_physical_endpoint(struct pci_dev *pdev)
+{
+	if (!pci_is_pcie(pdev))
+		return false;
+
+	if (pdev->is_virtfn)
+		return false;
+
+	if (pci_pcie_type(pdev) != PCI_EXP_TYPE_ENDPOINT)
+		return false;
+
+	return true;
+}
+
+static bool is_endpoint(struct pci_dev *pdev)
+{
+	if (!pci_is_pcie(pdev))
+		return false;
+
+	if (pci_pcie_type(pdev) != PCI_EXP_TYPE_ENDPOINT)
+		return false;
+
+	return true;
+}
+
+struct tsm_pci_dev_data {
+	struct pci_doe_mb *doe_mb;
+	struct pci_doe_mb *doe_mb_sec;
+};
+
+#define tsm_dev_to_pcidata(tdev) ((struct tsm_pci_dev_data *)tsm_dev_to_bdata(tdev))
+
+static int tsm_pci_dev_spdm_forward(struct tsm_spdm *spdm, u8 type)
+{
+	struct tsm_dev *tdev = container_of(spdm, struct tsm_dev, spdm);
+	struct tsm_pci_dev_data *tdata = tsm_dev_to_pcidata(tdev);
+	struct pci_doe_mb *doe_mb;
+	int rc;
+
+	if (type == TSM_PROTO_SECURED_CMA_SPDM)
+		doe_mb = tdata->doe_mb_sec;
+	else if (type == TSM_PROTO_CMA_SPDM)
+		doe_mb = tdata->doe_mb;
+	else
+		return -EINVAL;
+
+	if (!doe_mb)
+		return -EFAULT;
+
+	rc = pci_doe(doe_mb, PCI_VENDOR_ID_PCI_SIG, type,
+		     spdm->req, spdm->req_len, spdm->rsp, spdm->rsp_len);
+	if (rc >= 0)
+		spdm->rsp_len = rc;
+
+	return rc;
+}
+
+static struct tsm_bus_ops tsm_pci_ops = {
+	.spdm_forward = tsm_pci_dev_spdm_forward,
+};
+
+static int tsm_pci_dev_init(struct tsm_bus_subsys *tsm_bus,
+			    struct pci_dev *pdev,
+			    struct tsm_dev **ptdev)
+{
+	struct tsm_pci_dev_data *tdata;
+	int ret = tsm_dev_init(tsm_bus, &pdev->dev, sizeof(*tdata), ptdev);
+
+	if (ret)
+		return ret;
+
+	tdata = tsm_dev_to_bdata(*ptdev);
+
+	tdata->doe_mb = pci_find_doe_mailbox(pdev,
+					     PCI_VENDOR_ID_PCI_SIG,
+					     PCI_DOE_PROTOCOL_CMA_SPDM);
+	tdata->doe_mb_sec = pci_find_doe_mailbox(pdev,
+						 PCI_VENDOR_ID_PCI_SIG,
+						 PCI_DOE_PROTOCOL_SECURED_CMA_SPDM);
+
+	if (tdata->doe_mb || tdata->doe_mb_sec)
+		pci_notice(pdev, "DOE SPDM=%s SecuredSPDM=%s\n",
+			   tdata->doe_mb ? "yes":"no", tdata->doe_mb_sec ? "yes":"no");
+
+	return ret;
+}
+
+static int tsm_pci_alloc_device(struct tsm_bus_subsys *tsm_bus,
+				struct pci_dev *pdev)
+{
+	int ret = 0;
+
+	/* Set up TDIs for HV (physical functions) and VM (all functions) */
+	if ((pdev->devcap & PCI_EXP_DEVCAP_TEE) &&
+	    (((pdev->is_physfn && (PCI_FUNC(pdev->devfn) == 0)) ||
+	      (!pdev->is_physfn && !pdev->is_virtfn)))) {
+
+		struct tsm_dev *tdev = NULL;
+
+		if (!is_physical_endpoint(pdev))
+			return 0;
+
+		ret = tsm_pci_dev_init(tsm_bus, pdev, &tdev);
+		if (ret)
+			return ret;
+
+		ret = tsm_tdi_init(tdev, &pdev->dev);
+		tsm_dev_put(tdev);
+		return ret;
+	}
+
+	/* Set up TDIs for HV (virtual functions), should do nothing in VMs */
+	if (pdev->is_virtfn) {
+		struct pci_dev *pf0 = pci_get_slot(pdev->physfn->bus,
+						   pdev->physfn->devfn & ~7);
+
+		if (pf0 && (pf0->devcap & PCI_EXP_DEVCAP_TEE)) {
+			struct tsm_dev *tdev = tsm_dev_get(&pf0->dev);
+
+			if (!is_endpoint(pdev))
+				return 0;
+
+			ret = tsm_tdi_init(tdev, &pdev->dev);
+			tsm_dev_put(tdev);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static void tsm_pci_dev_free(struct pci_dev *pdev)
+{
+	struct tsm_tdi *tdi = tsm_tdi_get(&pdev->dev);
+
+	if (tdi) {
+		tsm_tdi_put(tdi);
+		tsm_tdi_free(tdi);
+	}
+
+	struct tsm_dev *tdev = tsm_dev_get(&pdev->dev);
+
+	if (tdev) {
+		tsm_dev_put(tdev);
+		tsm_dev_free(tdev);
+	}
+
+	WARN_ON(!tdi && tdev);
+}
+
+static int tsm_pci_bus_notifier(struct notifier_block *nb, unsigned long action, void *data)
+{
+	struct tsm_bus_subsys *tsm_bus = container_of(nb, struct tsm_bus_subsys, notifier);
+
+	switch (action) {
+	case BUS_NOTIFY_ADD_DEVICE:
+		tsm_pci_alloc_device(tsm_bus, to_pci_dev(data));
+		break;
+	case BUS_NOTIFY_DEL_DEVICE:
+		tsm_pci_dev_free(to_pci_dev(data));
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+struct tsm_bus_subsys *pci_tsm_register(struct tsm_subsys *tsm)
+{
+	struct tsm_bus_subsys *tsm_bus = kzalloc(sizeof(*tsm_bus), GFP_KERNEL);
+	struct pci_dev *pdev = NULL;
+
+	pr_info("Scan TSM PCI\n");
+	tsm_bus->ops = &tsm_pci_ops;
+	tsm_bus->tsm = tsm;
+	tsm_bus->notifier.notifier_call = tsm_pci_bus_notifier;
+	for_each_pci_dev(pdev)
+		tsm_pci_alloc_device(tsm_bus, pdev);
+	bus_register_notifier(&pci_bus_type, &tsm_bus->notifier);
+	return tsm_bus;
+}
+EXPORT_SYMBOL_GPL(pci_tsm_register);
+
+void pci_tsm_unregister(struct tsm_bus_subsys *subsys)
+{
+	struct pci_dev *pdev = NULL;
+
+	pr_info("Shut down TSM PCI\n");
+	bus_unregister_notifier(&pci_bus_type, &subsys->notifier);
+	for_each_pci_dev(pdev)
+		tsm_pci_dev_free(pdev);
+}
+EXPORT_SYMBOL_GPL(pci_tsm_unregister);
+
+static int __init tsm_pci_init(void)
+{
+	pr_info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
+	return 0;
+}
+
+static void __exit tsm_pci_cleanup(void)
+{
+	pr_info(DRIVER_DESC " version: " DRIVER_VERSION " unload\n");
+}
+
+module_init(tsm_pci_init);
+module_exit(tsm_pci_cleanup);
+
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 9212c0decdc5..9285e7511860 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -137,6 +137,21 @@ config PCI_CMA
 config PCI_IDE
 	bool
 
+config PCI_TSM
+	tristate "TEE Security Manager for PCI Device Security"
+	select PCI_IDE
+	depends on TSM
+	default m
+	help
+	  The TEE (Trusted Execution Environment) Device Interface
+	  Security Protocol (TDISP) defines a "TSM" as a platform agent
+	  that manages device authentication, link encryption, link
+	  integrity protection, and assignment of PCI device functions
+	  (virtual or physical) to confidential computing VMs that can
+	  access (DMA) guest private memory.
+
+	  Enable a platform TSM driver to use this capability.
+
 config PCI_DOE
 	bool
 
-- 
2.47.1


  parent reply	other threads:[~2025-02-18 11:13 UTC|newest]

Thread overview: 96+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-02-18 11:09 [RFC PATCH v2 00/22] TSM: Secure VFIO, TDISP, SEV TIO Alexey Kardashevskiy
2025-02-18 11:09 ` [RFC PATCH v2 01/22] pci/doe: Define protocol types and make those public Alexey Kardashevskiy
2025-04-15 20:15   ` Bjorn Helgaas
2025-02-18 11:09 ` [RFC PATCH v2 02/22] PCI/IDE: Fixes to make it work on AMD SNP-SEV Alexey Kardashevskiy
2025-02-18 11:09 ` [RFC PATCH v2 03/22] PCI/IDE: Init IDs on all IDE streams beforehand Alexey Kardashevskiy
2025-02-18 11:09 ` [RFC PATCH v2 04/22] iommu/amd: Report SEV-TIO support Alexey Kardashevskiy
2025-02-18 11:09 ` [RFC PATCH v2 05/22] crypto: ccp: Enable SEV-TIO feature in the PSP when supported Alexey Kardashevskiy
2025-03-22 11:50   ` Francesco Lavra
2025-03-26  4:26     ` Alexey Kardashevskiy
2025-02-18 11:09 ` [RFC PATCH v2 06/22] KVM: X86: Define tsm_get_vmid Alexey Kardashevskiy
2025-03-13  1:51   ` Dan Williams
2025-03-13  4:31     ` Alexey Kardashevskiy
2025-03-13 19:09       ` Dan Williams
2025-03-14  3:28         ` Alexey Kardashevskiy
2025-04-24  3:37           ` Alexey Kardashevskiy
2025-02-18 11:09 ` [RFC PATCH v2 07/22] coco/tsm: Add tsm and tsm-host modules Alexey Kardashevskiy
2025-03-14  1:14   ` Dan Williams
2025-05-14 18:39   ` Zhi Wang
2025-05-29  5:30     ` Alexey Kardashevskiy
2025-02-18 11:09 ` Alexey Kardashevskiy [this message]
2025-04-15 20:25   ` [RFC PATCH v2 08/22] pci/tsm: Add PCI driver for TSM Bjorn Helgaas
2025-02-18 11:09 ` [RFC PATCH v2 09/22] crypto/ccp: Implement SEV TIO firmware interface Alexey Kardashevskiy
2025-03-23 11:35   ` Francesco Lavra
2025-02-18 11:09 ` [RFC PATCH v2 10/22] KVM: SVM: Add uAPI to change RMP for MMIO Alexey Kardashevskiy
2025-03-15  0:08   ` Dan Williams
2025-03-27  5:00     ` Alexey Kardashevskiy
2025-02-18 11:09 ` [RFC PATCH v2 11/22] KVM: SEV: Add TIO VMGEXIT Alexey Kardashevskiy
2025-02-18 11:09 ` [RFC PATCH v2 12/22] iommufd: Allow mapping from guest_memfd Alexey Kardashevskiy
2025-02-18 14:16   ` Jason Gunthorpe
2025-02-18 23:35     ` Alexey Kardashevskiy
2025-02-18 23:51       ` Jason Gunthorpe
2025-02-19  0:43         ` Alexey Kardashevskiy
2025-02-19 13:35           ` Jason Gunthorpe
2025-02-19 20:23             ` Michael Roth
2025-02-19 20:37               ` Jason Gunthorpe
2025-02-19 21:30                 ` Michael Roth
2025-02-20  0:57                   ` Jason Gunthorpe
2025-03-13  4:51                 ` Alexey Kardashevskiy
2025-03-19 17:40                   ` Jason Gunthorpe
2025-02-20  2:29             ` Alexey Kardashevskiy
2025-02-18 11:10 ` [RFC PATCH v2 13/22] iommufd: amd-iommu: Add vdevice support Alexey Kardashevskiy
2025-04-01 16:11   ` Jason Gunthorpe
2025-04-10  6:39     ` Alexey Kardashevskiy
2025-04-10  8:43       ` Tian, Kevin
2025-04-10 13:05       ` Jason Gunthorpe
2025-04-14  4:17         ` Alexey Kardashevskiy
2025-02-18 11:10 ` [RFC PATCH v2 14/22] iommufd: Add TIO calls Alexey Kardashevskiy
2025-02-25  9:00   ` Xu Yilun
2025-02-26  0:12     ` Alexey Kardashevskiy
2025-02-26 10:49       ` Xu Yilun
2025-02-26 13:12         ` Jason Gunthorpe
2025-02-27  0:33           ` Alexey Kardashevskiy
2025-03-01  0:32             ` Jason Gunthorpe
2025-03-05  3:09               ` Alexey Kardashevskiy
2025-03-05 19:18                 ` Jason Gunthorpe
2025-02-27  3:59           ` Xu Yilun
2025-03-01  0:37             ` Jason Gunthorpe
2025-03-03  5:32               ` Xu Yilun
2025-03-05 19:28                 ` Jason Gunthorpe
2025-03-06  6:47                   ` Xu Yilun
2025-03-06 18:26                     ` Jason Gunthorpe
2025-03-07  6:49                       ` Xu Yilun
2025-03-07  2:19                     ` Alexey Kardashevskiy
2025-03-07 15:17                       ` Jason Gunthorpe
2025-03-12 10:41                         ` Suzuki K Poulose
2025-03-12  1:11                       ` Xu Yilun
2025-02-26 13:08       ` Jason Gunthorpe
2025-03-15  1:11         ` Dan Williams
2025-03-17  2:32           ` Alexey Kardashevskiy
2025-04-01 15:53             ` Jason Gunthorpe
2025-03-13 11:01   ` Xu Yilun
2025-03-14  2:49     ` Alexey Kardashevskiy
2025-03-28  5:27   ` Aneesh Kumar K.V
2025-04-01 16:03     ` Jason Gunthorpe
2025-04-07 11:40       ` Aneesh Kumar K.V
2025-04-07 16:40         ` Jason Gunthorpe
2025-04-01 16:12   ` Jason Gunthorpe
2025-04-03  8:39     ` Alexey Kardashevskiy
2025-02-18 11:10 ` [RFC PATCH v2 15/22] KVM: X86: Handle private MMIO as shared Alexey Kardashevskiy
2025-05-15  8:18   ` Zhi Wang
2025-05-29  5:30     ` Alexey Kardashevskiy
2025-02-18 11:10 ` [RFC PATCH v2 16/22] coco/tsm: Add tsm-guest module Alexey Kardashevskiy
2025-04-05 17:15   ` Francesco Lavra
2025-02-18 11:10 ` [RFC PATCH v2 17/22] resource: Mark encrypted MMIO resource on validation Alexey Kardashevskiy
2025-04-05 18:19   ` Francesco Lavra
2025-02-18 11:10 ` [RFC PATCH v2 18/22] coco/sev-guest: Implement the guest support for SEV TIO Alexey Kardashevskiy
2025-04-07 11:05   ` Francesco Lavra
2025-02-18 11:10 ` [RFC PATCH v2 19/22] RFC: pci: Add BUS_NOTIFY_PCI_BUS_MASTER event Alexey Kardashevskiy
2025-04-15 20:26   ` Bjorn Helgaas
2025-02-18 11:10 ` [RFC PATCH v2 20/22] sev-guest: Stop changing encrypted page state for TDISP devices Alexey Kardashevskiy
2025-02-27 16:01   ` Borislav Petkov
2025-02-18 11:10 ` [RFC PATCH v2 21/22] pci: Allow encrypted MMIO mapping via sysfs Alexey Kardashevskiy
2025-04-15 20:28   ` Bjorn Helgaas
2025-02-18 11:10 ` [RFC PATCH v2 22/22] pci: Define pci_iomap_range_encrypted Alexey Kardashevskiy
2025-04-15 20:30   ` Bjorn Helgaas
2025-02-27 15:48 ` [RFC PATCH v2 00/22] TSM: Secure VFIO, TDISP, SEV TIO Borislav Petkov

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=20250218111017.491719-9-aik@amd.com \
    --to=aik@amd.com \
    --cc=Jonathan.Cameron@huawei.com \
    --cc=aneesh.kumar@kernel.org \
    --cc=ashish.kalra@amd.com \
    --cc=baolu.lu@linux.intel.com \
    --cc=bhelgaas@google.com \
    --cc=dan.j.williams@intel.com \
    --cc=dionnaglaze@google.com \
    --cc=hch@lst.de \
    --cc=iommu@lists.linux.dev \
    --cc=jgg@ziepe.ca \
    --cc=joao.m.martins@oracle.com \
    --cc=joro@8bytes.org \
    --cc=kevin.tian@intel.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-arch@vger.kernel.org \
    --cc=linux-coco@lists.linux.dev \
    --cc=linux-crypto@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=lukas@wunner.de \
    --cc=michael.roth@amd.com \
    --cc=nicolinc@nvidia.com \
    --cc=nikunj@amd.com \
    --cc=pbonzini@redhat.com \
    --cc=robin.murphy@arm.com \
    --cc=seanjc@google.com \
    --cc=steven.sistare@oracle.com \
    --cc=suravee.suthikulpanit@amd.com \
    --cc=suzuki.poulose@arm.com \
    --cc=thomas.lendacky@amd.com \
    --cc=vasant.hegde@amd.com \
    --cc=x86@kernel.org \
    --cc=yi.l.liu@intel.com \
    --cc=yilun.xu@linux.intel.com \
    --cc=zhiw@nvidia.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).