From: Christoph Manszewski <christoph.manszewski@intel.com>
To: igt-dev@lists.freedesktop.org
Cc: "Zbigniew Kempczyński" <zbigniew.kempczynski@intel.com>,
"Kamil Konieczny" <kamil.konieczny@linux.intel.com>,
"Dominik Grzegorzek" <dominik.grzegorzek@intel.com>,
"Maciej Patelczyk" <maciej.patelczyk@intel.com>,
"Dominik Karol Piątkowski" <dominik.karol.piatkowski@intel.com>,
"Pawel Sikora" <pawel.sikora@intel.com>,
"Andrzej Hajda" <andrzej.hajda@intel.com>,
"Kolanupaka Naveena" <kolanupaka.naveena@intel.com>,
"Mika Kuoppala" <mika.kuoppala@intel.com>,
"Gwan-gyeong Mun" <gwan-gyeong.mun@intel.com>
Subject: [PATCH i-g-t v2 38/66] tests/xe_exec_sip: Port tests for shaders and sip
Date: Tue, 30 Jul 2024 13:44:55 +0200 [thread overview]
Message-ID: <20240730114523.334156-39-christoph.manszewski@intel.com> (raw)
In-Reply-To: <20240730114523.334156-1-christoph.manszewski@intel.com>
SIP is a System Instruction Pointer, which the hardware will
except/jump into when some defined event occurs, debug mode
is enabled and pipeline setup has included sip program.
Events like illegal instruction or breakpoint hit will jump
into SIP directly. Driver can also except into sip during hang
resolution and SIP can do, for example, eu thread state snapshot
before the hang resolution ends up in a hardware state reset.
Signed-off-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: Dominik Grzegorzek <dominik.grzegorzek@intel.com>
Signed-off-by: Christoph Manszewski <christoph.manszewski@intel.com>
Cc: Dominik Grzegorzek <dominik.grzegorzek@intel.com>
---
tests/intel/xe_exec_sip.c | 129 ++++++++++++++++++++++++++++++++++----
1 file changed, 116 insertions(+), 13 deletions(-)
diff --git a/tests/intel/xe_exec_sip.c b/tests/intel/xe_exec_sip.c
index 4b599e7f6..e52889818 100644
--- a/tests/intel/xe_exec_sip.c
+++ b/tests/intel/xe_exec_sip.c
@@ -21,6 +21,7 @@
#include "gpgpu_shader.h"
#include "igt.h"
#include "igt_sysfs.h"
+#include "xe/xe_eudebug.h"
#include "xe/xe_ioctl.h"
#include "xe/xe_query.h"
@@ -30,9 +31,16 @@
#define COLOR_C4 0xc4
#define SHADER_CANARY 0x01010101
+#define SIP_CANARY 0x02020202
#define NSEC_PER_MSEC (1000 * 1000ull)
+#define SHADER_BREAKPOINT 0
+#define SHADER_WRITE 1
+#define SHADER_WAIT 2
+#define SIP_WRITE 3
+#define SIP_NULL 4
+
static struct intel_buf *
create_fill_buf(int fd, int width, int height, uint8_t color)
{
@@ -52,27 +60,78 @@ create_fill_buf(int fd, int width, int height, uint8_t color)
return buf;
}
-static struct gpgpu_shader *get_shader(int fd)
+static struct gpgpu_shader *get_shader(int fd, const int shadertype)
{
static struct gpgpu_shader *shader;
shader = gpgpu_shader_create(fd);
gpgpu_shader__write_dword(shader, SHADER_CANARY, 0);
+
+ switch (shadertype) {
+ case SHADER_WAIT:
+ gpgpu_shader__wait(shader);
+ break;
+ case SHADER_WRITE:
+ break;
+ case SHADER_BREAKPOINT:
+ gpgpu_shader__nop(shader);
+ gpgpu_shader__breakpoint(shader);
+ break;
+ }
+
gpgpu_shader__eot(shader);
return shader;
}
-static uint32_t gpgpu_shader(int fd, struct intel_bb *ibb, unsigned int threads,
- unsigned int width, unsigned int height)
+static struct gpgpu_shader *get_sip(int fd, const int siptype,
+ const int shadertype, unsigned int y_offset)
+{
+ static struct gpgpu_shader *sip;
+
+ if (siptype == SIP_NULL)
+ return NULL;
+
+ sip = gpgpu_shader_create(fd);
+ gpgpu_shader__write_dword(sip, SIP_CANARY, y_offset);
+
+ switch (siptype) {
+ case SIP_WRITE:
+ break;
+ /* TODO: Add alternative SIP instructions here */
+ }
+
+ gpgpu_shader__end_system_routine(sip, shadertype == SHADER_BREAKPOINT);
+ return sip;
+}
+
+static uint32_t gpgpu_shader(int fd, struct intel_bb *ibb, const int shadertype, const int siptype,
+ unsigned int threads, unsigned int width, unsigned int height)
{
struct intel_buf *buf = create_fill_buf(fd, width, height, COLOR_C4);
- struct gpgpu_shader *shader = get_shader(fd);
+ struct gpgpu_shader *sip = get_sip(fd, siptype, shadertype, height / 2);
+ struct gpgpu_shader *shader = get_shader(fd, shadertype);
+
+ gpgpu_shader_exec(ibb, buf, 1, threads, shader, sip, 0, 0);
- gpgpu_shader_exec(ibb, buf, 1, threads, shader, NULL, 0, 0);
+ if (sip)
+ gpgpu_shader_destroy(sip);
gpgpu_shader_destroy(shader);
+
return buf->handle;
}
+static bool has_debugger(int fd)
+{
+ struct drm_xe_eudebug_connect param = { .pid = getpid() };
+ int debugfd;
+
+ debugfd = igt_ioctl(fd, DRM_IOCTL_XE_EUDEBUG_CONNECT, ¶m);
+ if (debugfd >= 0)
+ close(debugfd);
+
+ return debugfd >= 0;
+}
+
static void check_fill_buf(uint8_t *ptr, const int width, const int x,
const int y, const uint8_t color)
{
@@ -84,10 +143,10 @@ static void check_fill_buf(uint8_t *ptr, const int width, const int x,
}
static void check_buf(int fd, uint32_t handle, int width, int height,
- uint8_t poison_c)
+ int siptype, uint8_t poison_c)
{
unsigned int sz = ALIGN(width * height, 4096);
- int thread_count = 0;
+ int thread_count = 0, sip_count = 0;
uint32_t *ptr;
int i, j;
@@ -105,7 +164,25 @@ static void check_buf(int fd, uint32_t handle, int width, int height,
i = 0;
}
+ for (i = 0, j = height / 2; j < height; ++j) {
+ if (ptr[j * width / 4] == SIP_CANARY) {
+ ++sip_count;
+ i = 4;
+ }
+
+ for (; i < width; i++)
+ check_fill_buf((uint8_t *)ptr, width, i, j, poison_c);
+
+ i = 0;
+ }
+
igt_assert(thread_count);
+ if (siptype != SIP_NULL && has_debugger(fd))
+ igt_assert_f(thread_count == sip_count,
+ "Thread and SIP count mismatch, %d != %d\n",
+ thread_count, sip_count);
+ else
+ igt_assert(sip_count == 0);
munmap(ptr, sz);
}
@@ -128,16 +205,22 @@ xe_sysfs_get_job_timeout_ms(int fd, struct drm_xe_engine_class_instance *eci)
* Description: check basic shader with write operation
* Run type: BAT
*
+ * SUBTEST: wait-writesip-nodebug
+ * Description: verify that we don't enter SIP after wait with debugging disabled.
+ *
+ * SUBTEST: breakpoint-writesip
+ * Description: Test that we enter SIP after hitting breakpoint in shader.
+ *
*/
-static void test_sip(struct drm_xe_engine_class_instance *eci, uint32_t flags)
+static void test_sip(int shader, int sip, struct drm_xe_engine_class_instance *eci)
{
unsigned int threads = 512;
unsigned int height = max_t(threads, HEIGHT, threads * 2);
- uint32_t exec_queue_id, handle, vm_id;
unsigned int width = WIDTH;
struct timespec ts = { };
- uint64_t timeout;
+ uint32_t exec_queue_id, handle, vm_id;
struct intel_bb *ibb;
+ uint64_t timeout;
int fd;
igt_debug("Using %s\n", xe_engine_class_string(eci->engine_class));
@@ -156,12 +239,12 @@ static void test_sip(struct drm_xe_engine_class_instance *eci, uint32_t flags)
ibb = intel_bb_create_with_context(fd, exec_queue_id, vm_id, NULL, 4096);
igt_nsec_elapsed(&ts);
- handle = gpgpu_shader(fd, ibb, threads, width, height);
+ handle = gpgpu_shader(fd, ibb, shader, sip, threads, width, height);
intel_bb_sync(ibb);
igt_assert_lt_u64(igt_nsec_elapsed(&ts), timeout);
- check_buf(fd, handle, width, height, COLOR_C4);
+ check_buf(fd, handle, width, height, sip, COLOR_C4);
gem_close(fd, handle);
intel_bb_destroy(ibb);
@@ -189,7 +272,27 @@ igt_main
fd = drm_open_driver(DRIVER_XE);
test_render_and_compute("sanity", fd, eci)
- test_sip(eci, 0);
+ test_sip(SHADER_WRITE, SIP_NULL, eci);
+
+ /* Debugger disabled (TD_CTL not set) */
+ igt_subtest_group {
+ igt_fixture {
+ igt_require(!has_debugger(fd));
+ }
+
+ test_render_and_compute("wait-writesip-nodebug", fd, eci)
+ test_sip(SHADER_WAIT, SIP_WRITE, eci);
+ }
+
+ /* Debugger enabled (TD_CTL set) */
+ igt_subtest_group {
+ igt_fixture {
+ igt_require(has_debugger(fd));
+ }
+
+ test_render_and_compute("breakpoint-writesip", fd, eci)
+ test_sip(SHADER_BREAKPOINT, SIP_WRITE, eci);
+ }
igt_fixture
drm_close_driver(fd);
--
2.34.1
next prev parent reply other threads:[~2024-07-30 11:48 UTC|newest]
Thread overview: 113+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-07-30 11:44 [PATCH i-g-t v2 00/66] Test coverage for GPU debug support Christoph Manszewski
2024-07-30 11:44 ` [PATCH i-g-t v2 01/66] drm-uapi/xe: Sync with eudebug uapi Christoph Manszewski
2024-08-08 13:18 ` Kamil Konieczny
2024-08-08 15:05 ` Manszewski, Christoph
2024-07-30 11:44 ` [PATCH i-g-t v2 02/66] tests/xe_eudebug: Test eudebug connection Christoph Manszewski
2024-08-01 9:16 ` Grzegorzek, Dominik
2024-08-02 10:14 ` Manszewski, Christoph
2024-08-01 9:30 ` Piatkowski, Dominik Karol
2024-07-30 11:44 ` [PATCH i-g-t v2 03/66] lib/xe_eudebug: Introduce eu debug testing framework Christoph Manszewski
2024-08-01 11:18 ` Piatkowski, Dominik Karol
2024-07-30 11:44 ` [PATCH i-g-t v2 04/66] lib/xe_eudebug: Allow client to wait for debugger Christoph Manszewski
2024-07-30 11:44 ` [PATCH i-g-t v2 05/66] lib/xe_eudebug: Add exec_queue support Christoph Manszewski
2024-07-30 11:44 ` [PATCH i-g-t v2 06/66] lib/xe_eudebug: Add attention events support Christoph Manszewski
2024-08-01 11:20 ` Piatkowski, Dominik Karol
2024-07-30 11:44 ` [PATCH i-g-t v2 07/66] lib/xe_ioctl: Add wrapper with vm_bind_op extension parameter Christoph Manszewski
2024-08-01 11:23 ` Piatkowski, Dominik Karol
2024-07-30 11:44 ` [PATCH i-g-t v2 08/66] lib/xe_eudebug: Add support for vm_bind events Christoph Manszewski
2024-08-01 11:28 ` Piatkowski, Dominik Karol
2024-07-30 11:44 ` [PATCH i-g-t v2 09/66] lib/xe_eudebug: Add metadata support Christoph Manszewski
2024-07-30 11:44 ` [PATCH i-g-t v2 10/66] lib/xe_eudebug: Add support for user fence acking Christoph Manszewski
2024-08-01 11:34 ` Piatkowski, Dominik Karol
2024-07-30 11:44 ` [PATCH i-g-t v2 11/66] lib/xe_eudebug: Add support for dynamic debugger sysfs toggle Christoph Manszewski
2024-08-01 11:51 ` Piatkowski, Dominik Karol
2024-07-30 11:44 ` [PATCH i-g-t v2 12/66] tests/xe_eudebug: Test open close events Christoph Manszewski
2024-08-01 11:53 ` Piatkowski, Dominik Karol
2024-07-30 11:44 ` [PATCH i-g-t v2 13/66] tests/xe_eudebug: Exercise read_event ioctl Christoph Manszewski
2024-08-01 12:01 ` Piatkowski, Dominik Karol
2024-07-30 11:44 ` [PATCH i-g-t v2 14/66] tests/xe_eudebug: Add vm events sanity check Christoph Manszewski
2024-08-01 12:04 ` Piatkowski, Dominik Karol
2024-07-30 11:44 ` [PATCH i-g-t v2 15/66] tests/xe_eudebug: Race discovery against eudebug attach Christoph Manszewski
2024-08-01 12:08 ` Piatkowski, Dominik Karol
2024-07-30 11:44 ` [PATCH i-g-t v2 16/66] tests/xe_eudebug: Introduce basic exec_queue testing Christoph Manszewski
2024-08-01 12:15 ` Piatkowski, Dominik Karol
2024-07-30 11:44 ` [PATCH i-g-t v2 17/66] tests/xe_eudebug: Include exec queues in discovery testing Christoph Manszewski
2024-07-30 11:44 ` [PATCH i-g-t v2 18/66] tests/xe_eudebug: Add vm open/pread/pwrite basic tests Christoph Manszewski
2024-08-01 12:20 ` Piatkowski, Dominik Karol
2024-07-30 11:44 ` [PATCH i-g-t v2 19/66] tests/xe_eudebug: Add basic vm-bind coverage Christoph Manszewski
2024-07-30 11:44 ` [PATCH i-g-t v2 20/66] tests/xe_eudebug: Exercise debug metadata events sent to debugger Christoph Manszewski
2024-07-30 11:44 ` [PATCH i-g-t v2 21/66] tests/xe_eudebug: Add support for dynamic debugger sysfs toggle Christoph Manszewski
2024-08-01 12:25 ` Piatkowski, Dominik Karol
2024-07-30 11:44 ` [PATCH i-g-t v2 22/66] tests/xe_eudebug: Add coverage for sysfs debugger toggle Christoph Manszewski
2024-08-01 12:28 ` Piatkowski, Dominik Karol
2024-07-30 11:44 ` [PATCH i-g-t v2 23/66] lib/xe_eudebug: Allow debugger to wait for client Christoph Manszewski
2024-08-01 12:31 ` Piatkowski, Dominik Karol
2024-07-30 11:44 ` [PATCH i-g-t v2 24/66] tests/xe_eudebug: Add vm-bind discovery tests Christoph Manszewski
2024-07-30 11:44 ` [PATCH i-g-t v2 25/66] tests/xe_eudebug: Add basic-vm-bind-metadata-discovery Christoph Manszewski
2024-07-30 11:44 ` [PATCH i-g-t v2 26/66] tests/xe_eudebug: Add basic-vm-access-parameters test Christoph Manszewski
2024-08-01 12:42 ` Piatkowski, Dominik Karol
2024-07-30 11:44 ` [PATCH i-g-t v2 27/66] lib/xe_eudebug: Add mutex for log events write Christoph Manszewski
2024-08-01 12:43 ` Piatkowski, Dominik Karol
2024-07-30 11:44 ` [PATCH i-g-t v2 28/66] tests/xe_eudebug: Add basic-client-th test Christoph Manszewski
2024-08-01 12:49 ` Piatkowski, Dominik Karol
2024-07-30 11:44 ` [PATCH i-g-t v2 29/66] tests/xe_eudebug: Added connect-user test Christoph Manszewski
2024-07-30 11:44 ` [PATCH i-g-t v2 30/66] tests/xe_eudebug: Add discovery-race-vmbind subtest Christoph Manszewski
2024-08-01 6:25 ` Piatkowski, Dominik Karol
2024-07-30 11:44 ` [PATCH i-g-t v2 31/66] tests/xe_eudebug: Add userptr variant of basic-vm-access test Christoph Manszewski
2024-07-30 11:44 ` [PATCH i-g-t v2 32/66] tests/xe_eudebug: Add basic-vm-bind-ufence Christoph Manszewski
2024-07-30 11:44 ` [PATCH i-g-t v2 33/66] tests/xe_eudebug: Add multigpu scenarios Christoph Manszewski
2024-07-30 11:44 ` [PATCH i-g-t v2 34/66] tests/xe_eudebug: Add vm-bind-clear test Christoph Manszewski
2024-07-30 11:44 ` [PATCH i-g-t v2 35/66] tests/xe_eudebug: Exercise lseek Christoph Manszewski
2024-07-30 11:44 ` [PATCH i-g-t v2 36/66] tests/xe_eudebug: Test multiple bo sizes Christoph Manszewski
2024-07-30 11:44 ` [PATCH i-g-t v2 37/66] lib/gpgpu_shader: Extend shader building library Christoph Manszewski
2024-07-30 11:44 ` Christoph Manszewski [this message]
2024-07-30 11:44 ` [PATCH i-g-t v2 39/66] tests/xe_exec_sip: Check if we reset due to unhandled attention Christoph Manszewski
2024-08-01 12:57 ` Piatkowski, Dominik Karol
2024-08-01 19:04 ` Grzegorzek, Dominik
2024-07-30 11:44 ` [PATCH i-g-t v2 40/66] tests/xe_exec_sip: Check usercoredump for attentions Christoph Manszewski
2024-07-30 11:44 ` [PATCH i-g-t v2 41/66] tests/xe_exec_sip: Add support for dynamic debugger sysfs toggle Christoph Manszewski
2024-08-01 12:58 ` Piatkowski, Dominik Karol
2024-07-30 11:44 ` [PATCH i-g-t v2 42/66] tests/xe_exec_sip: Add breakpoint-writesip-twice test Christoph Manszewski
2024-07-30 11:45 ` [PATCH i-g-t v2 43/66] tests/xe_exec_sip: Add sanity-after-timeout test Christoph Manszewski
2024-08-01 7:08 ` Piatkowski, Dominik Karol
2024-07-30 11:45 ` [PATCH i-g-t v2 44/66] tests/xe_exec_sip: Add breakpoint-waitsip-heavy test Christoph Manszewski
2024-07-30 11:45 ` [PATCH i-g-t v2 45/66] tests/xe_exec_sip: Add nodebug test cases Christoph Manszewski
2024-08-01 7:23 ` Piatkowski, Dominik Karol
2024-07-30 11:45 ` [PATCH i-g-t v2 46/66] lib/gpgpu_shader: Add write_on_exception template Christoph Manszewski
2024-07-30 11:45 ` [PATCH i-g-t v2 47/66] lib/gpgpu_shader: Add set/clear exception register (cr0.1) helpers Christoph Manszewski
2024-07-30 11:45 ` [PATCH i-g-t v2 48/66] lib/intel_batchbuffer: Add helper to get pointer at specified offset Christoph Manszewski
2024-07-30 11:45 ` [PATCH i-g-t v2 49/66] lib/gpgpu_shader: Allow enabling illegal opcode exceptions in shader Christoph Manszewski
2024-07-30 11:45 ` [PATCH i-g-t v2 50/66] tests/xe_exec_sip: Rework invalid instruction tests Christoph Manszewski
2024-08-01 19:22 ` Grzegorzek, Dominik
2024-07-30 11:45 ` [PATCH i-g-t v2 51/66] lib/intel_batchbuffer: Add support for long-running mode execution Christoph Manszewski
2024-07-30 11:45 ` [PATCH i-g-t v2 52/66] tests/xe_eudebug_online: Debug client which runs workloads on EU Christoph Manszewski
2024-07-30 11:45 ` [PATCH i-g-t v2 53/66] tests/xe_eudebug_online: Set dynamic breakpoint on interrupt-all Christoph Manszewski
2024-08-05 6:27 ` Piatkowski, Dominik Karol
2024-07-30 11:45 ` [PATCH i-g-t v2 54/66] tests/xe_eudebug_online: Add support for dynamic debugger sysfs toggle Christoph Manszewski
2024-08-05 6:30 ` Piatkowski, Dominik Karol
2024-07-30 11:45 ` [PATCH i-g-t v2 55/66] tests/xe_eudebug_online: Add tdctl-parameters test Christoph Manszewski
2024-07-30 11:45 ` [PATCH i-g-t v2 56/66] tests/xe_eudebug_online: Add reset-with-attention test Christoph Manszewski
2024-08-05 6:46 ` Piatkowski, Dominik Karol
2024-07-30 11:45 ` [PATCH i-g-t v2 57/66] lib/xe_eudebug: Expose xe_eudebug_connect Christoph Manszewski
2024-08-05 6:48 ` Piatkowski, Dominik Karol
2024-07-30 11:45 ` [PATCH i-g-t v2 58/66] tests/xe_eudebug_online: Add interrupt-reconnect test Christoph Manszewski
2024-08-05 7:53 ` Piatkowski, Dominik Karol
2024-07-30 11:45 ` [PATCH i-g-t v2 59/66] tests/xe_eudebug_online: Add single-step and single-step-one tests Christoph Manszewski
2024-07-30 11:45 ` [PATCH i-g-t v2 60/66] tests/xe_eudebug_online: What if user does not set debug mode? Christoph Manszewski
2024-08-05 7:55 ` Piatkowski, Dominik Karol
2024-07-30 11:45 ` [PATCH i-g-t v2 61/66] tests/xe_eudebug_online: Adds debugger-reopen test Christoph Manszewski
2024-08-01 8:22 ` Piatkowski, Dominik Karol
2024-07-30 11:45 ` [PATCH i-g-t v2 62/66] tests/xe_eudebug_online: Add caching tests Christoph Manszewski
2024-08-01 12:52 ` Piatkowski, Dominik Karol
2024-07-30 11:45 ` [PATCH i-g-t v2 63/66] tests/xe_eudebug_online: Add subtests w/o long running mode Christoph Manszewski
2024-08-01 9:09 ` Piatkowski, Dominik Karol
2024-08-01 19:27 ` Grzegorzek, Dominik
2024-07-30 11:45 ` [PATCH i-g-t v2 64/66] tests/xe_eudebug_online: Add multisession test cases Christoph Manszewski
2024-07-30 11:45 ` [PATCH i-g-t v2 65/66] tests/xe_eudebug_online: Check if eu debugger disables preemption timeout Christoph Manszewski
2024-07-30 11:45 ` [PATCH i-g-t v2 66/66] tests/xe_live_ktest: Add xe_eudebug live test Christoph Manszewski
2024-07-30 16:15 ` ✗ GitLab.Pipeline: warning for Test coverage for GPU debug support (rev2) Patchwork
2024-07-30 16:23 ` ✓ CI.xeBAT: success " Patchwork
2024-07-30 16:36 ` ✗ Fi.CI.BAT: failure " Patchwork
2024-07-30 17:16 ` ✗ CI.xeFULL: " Patchwork
2024-08-08 11:13 ` [PATCH i-g-t v2 00/66] Test coverage for GPU debug support Zbigniew Kempczyński
2024-08-08 11:42 ` Manszewski, Christoph
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=20240730114523.334156-39-christoph.manszewski@intel.com \
--to=christoph.manszewski@intel.com \
--cc=andrzej.hajda@intel.com \
--cc=dominik.grzegorzek@intel.com \
--cc=dominik.karol.piatkowski@intel.com \
--cc=gwan-gyeong.mun@intel.com \
--cc=igt-dev@lists.freedesktop.org \
--cc=kamil.konieczny@linux.intel.com \
--cc=kolanupaka.naveena@intel.com \
--cc=maciej.patelczyk@intel.com \
--cc=mika.kuoppala@intel.com \
--cc=pawel.sikora@intel.com \
--cc=zbigniew.kempczynski@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