From: Alexandru Elisei <alexandru.elisei@arm.com> To: linux-arm-kernel@lists.infradead.org, kvmarm@lists.cs.columbia.edu Cc: maz@kernel.org, will@kernel.org Subject: [RFC PATCH v3 11/16] KVM: arm64: Add SPE system registers to VCPU context Date: Tue, 27 Oct 2020 17:27:00 +0000 [thread overview] Message-ID: <20201027172705.15181-12-alexandru.elisei@arm.com> (raw) In-Reply-To: <20201027172705.15181-1-alexandru.elisei@arm.com> Add the SPE system registers to the VCPU context. Omitted are PMBIDR_EL1, which cannot be trapped, and PMSIR_EL1, which is a read-only register. The registers are simply stored in the sys_regs array on a write, and returned on a read; complete emulation and save/restore on world switch will be added in a future patch. Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com> --- arch/arm64/include/asm/kvm_host.h | 11 +++++++ arch/arm64/kvm/spe.c | 10 +++++++ arch/arm64/kvm/sys_regs.c | 48 ++++++++++++++++++++++++------- include/kvm/arm_spe.h | 9 ++++++ 4 files changed, 68 insertions(+), 10 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 27f581750c6e..bcecc6224c59 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -194,6 +194,17 @@ enum vcpu_sysreg { CNTP_CVAL_EL0, CNTP_CTL_EL0, + /* Statistical Profiling Extension Registers. */ + PMSCR_EL1, /* Statistical Profiling Control Register */ + PMSICR_EL1, /* Sampling Interval Counter Register */ + PMSIRR_EL1, /* Sampling Interval Reload Register */ + PMSFCR_EL1, /* Sampling Filter Control Register */ + PMSEVFR_EL1, /* Sampling Event Filter Register */ + PMSLATFR_EL1, /* Sampling Latency Filter Register */ + PMBLIMITR_EL1, /* Profiling Buffer Limit Address Register */ + PMBPTR_EL1, /* Profiling Buffer Write Pointer Register */ + PMBSR_EL1, /* Profiling Buffer Status/syndrome Register */ + /* 32bit specific registers. Keep them at the end of the range */ DACR32_EL2, /* Domain Access Control Register */ IFSR32_EL2, /* Instruction Fault Status Register */ diff --git a/arch/arm64/kvm/spe.c b/arch/arm64/kvm/spe.c index 316ff8dfed5b..0e365a51cac7 100644 --- a/arch/arm64/kvm/spe.c +++ b/arch/arm64/kvm/spe.c @@ -12,6 +12,16 @@ #include <asm/kvm_mmu.h> +void kvm_arm_spe_write_sysreg(struct kvm_vcpu *vcpu, int reg, u64 val) +{ + __vcpu_sys_reg(vcpu, reg) = val; +} + +u64 kvm_arm_spe_read_sysreg(struct kvm_vcpu *vcpu, int reg) +{ + return __vcpu_sys_reg(vcpu, reg); +} + void kvm_arm_spe_notify_vcpu_init(struct kvm_vcpu *vcpu) { vcpu->kvm->arch.spe.finalized = false; diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index aa776c006a2a..2871484993ec 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -244,9 +244,37 @@ static bool access_vm_reg(struct kvm_vcpu *vcpu, return true; } +static bool access_spe_reg(struct kvm_vcpu *vcpu, + struct sys_reg_params *p, + const struct sys_reg_desc *r) +{ + u64 val = p->regval; + int reg = r->reg; + u32 sr = sys_reg((u32)r->Op0, (u32)r->Op1, + (u32)r->CRn, (u32)r->CRm, (u32)r->Op2); + + if (sr == SYS_PMSIDR_EL1) { + /* Ignore writes. */ + if (!p->is_write) + p->regval = read_sysreg_s(SYS_PMSIDR_EL1); + goto out; + } + + if (p->is_write) + kvm_arm_spe_write_sysreg(vcpu, reg, val); + else + p->regval = kvm_arm_spe_read_sysreg(vcpu, reg); + +out: + return true; +} + static unsigned int spe_visibility(const struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { + if (vcpu_has_spe(vcpu)) + return 0; + return REG_HIDDEN_GUEST | REG_HIDDEN_USER; } @@ -1598,16 +1626,16 @@ static const struct sys_reg_desc sys_reg_descs[] = { { SYS_DESC(SYS_FAR_EL1), access_vm_reg, reset_unknown, FAR_EL1 }, { SYS_DESC(SYS_PAR_EL1), NULL, reset_unknown, PAR_EL1 }, - { SYS_DESC(SYS_PMSCR_EL1), .visibility = spe_visibility }, - { SYS_DESC(SYS_PMSICR_EL1), .visibility = spe_visibility }, - { SYS_DESC(SYS_PMSIRR_EL1), .visibility = spe_visibility }, - { SYS_DESC(SYS_PMSFCR_EL1), .visibility = spe_visibility }, - { SYS_DESC(SYS_PMSEVFR_EL1), .visibility = spe_visibility }, - { SYS_DESC(SYS_PMSLATFR_EL1), .visibility = spe_visibility }, - { SYS_DESC(SYS_PMSIDR_EL1), .visibility = spe_visibility }, - { SYS_DESC(SYS_PMBLIMITR_EL1), .visibility = spe_visibility }, - { SYS_DESC(SYS_PMBPTR_EL1), .visibility = spe_visibility }, - { SYS_DESC(SYS_PMBSR_EL1), .visibility = spe_visibility }, + { SYS_DESC(SYS_PMSCR_EL1), access_spe_reg, reset_val, PMSCR_EL1, 0, .visibility = spe_visibility }, + { SYS_DESC(SYS_PMSICR_EL1), access_spe_reg, reset_val, PMSICR_EL1, 0, .visibility = spe_visibility }, + { SYS_DESC(SYS_PMSIRR_EL1), access_spe_reg, reset_val, PMSIRR_EL1, 0, .visibility = spe_visibility }, + { SYS_DESC(SYS_PMSFCR_EL1), access_spe_reg, reset_val, PMSFCR_EL1, 0, .visibility = spe_visibility }, + { SYS_DESC(SYS_PMSEVFR_EL1), access_spe_reg, reset_val, PMSEVFR_EL1, 0, .visibility = spe_visibility }, + { SYS_DESC(SYS_PMSLATFR_EL1), access_spe_reg, reset_val, PMSEVFR_EL1, 0, .visibility = spe_visibility }, + { SYS_DESC(SYS_PMSIDR_EL1), access_spe_reg, .visibility = spe_visibility }, + { SYS_DESC(SYS_PMBLIMITR_EL1), access_spe_reg, reset_val, PMBLIMITR_EL1, 0, .visibility = spe_visibility }, + { SYS_DESC(SYS_PMBPTR_EL1), access_spe_reg, reset_unknown, PMBPTR_EL1, .visibility = spe_visibility }, + { SYS_DESC(SYS_PMBSR_EL1), access_spe_reg, reset_val, PMBSR_EL1, 0, .visibility = spe_visibility }, { SYS_DESC(SYS_PMINTENSET_EL1), access_pminten, reset_unknown, PMINTENSET_EL1 }, { SYS_DESC(SYS_PMINTENCLR_EL1), access_pminten, reset_unknown, PMINTENSET_EL1 }, diff --git a/include/kvm/arm_spe.h b/include/kvm/arm_spe.h index 7f9f3a03aadb..a2429edc4483 100644 --- a/include/kvm/arm_spe.h +++ b/include/kvm/arm_spe.h @@ -38,6 +38,9 @@ int kvm_arm_vm_spe_has_attr(struct kvm *vcpu, struct kvm_device_attr *attr); void kvm_arm_spe_notify_vcpu_init(struct kvm_vcpu *vcpu); +void kvm_arm_spe_write_sysreg(struct kvm_vcpu *vcpu, int reg, u64 val); +u64 kvm_arm_spe_read_sysreg(struct kvm_vcpu *vcpu, int reg); + #else #define kvm_arm_supports_spe() false @@ -87,5 +90,11 @@ static inline int kvm_arm_vm_spe_has_attr(struct kvm *vcpu, static inline void kvm_arm_spe_notify_vcpu_init(struct kvm_vcpu *vcpu) {} +static inline void kvm_arm_spe_write_sysreg(struct kvm_vcpu *vcpu, int reg, u64 val) {} +static inline u64 kvm_arm_spe_read_sysreg(struct kvm_vcpu *vcpu, int reg) +{ + return 0; +} + #endif /* CONFIG_KVM_ARM_SPE */ #endif /* __ASM_ARM_KVM_SPE_H */ -- 2.29.1 _______________________________________________ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
WARNING: multiple messages have this Message-ID (diff)
From: Alexandru Elisei <alexandru.elisei@arm.com> To: linux-arm-kernel@lists.infradead.org, kvmarm@lists.cs.columbia.edu Cc: maz@kernel.org, will@kernel.org, james.morse@arm.com, julien.thierry.kdev@gmail.com, suzuki.poulose@arm.com Subject: [RFC PATCH v3 11/16] KVM: arm64: Add SPE system registers to VCPU context Date: Tue, 27 Oct 2020 17:27:00 +0000 [thread overview] Message-ID: <20201027172705.15181-12-alexandru.elisei@arm.com> (raw) In-Reply-To: <20201027172705.15181-1-alexandru.elisei@arm.com> Add the SPE system registers to the VCPU context. Omitted are PMBIDR_EL1, which cannot be trapped, and PMSIR_EL1, which is a read-only register. The registers are simply stored in the sys_regs array on a write, and returned on a read; complete emulation and save/restore on world switch will be added in a future patch. Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com> --- arch/arm64/include/asm/kvm_host.h | 11 +++++++ arch/arm64/kvm/spe.c | 10 +++++++ arch/arm64/kvm/sys_regs.c | 48 ++++++++++++++++++++++++------- include/kvm/arm_spe.h | 9 ++++++ 4 files changed, 68 insertions(+), 10 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 27f581750c6e..bcecc6224c59 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -194,6 +194,17 @@ enum vcpu_sysreg { CNTP_CVAL_EL0, CNTP_CTL_EL0, + /* Statistical Profiling Extension Registers. */ + PMSCR_EL1, /* Statistical Profiling Control Register */ + PMSICR_EL1, /* Sampling Interval Counter Register */ + PMSIRR_EL1, /* Sampling Interval Reload Register */ + PMSFCR_EL1, /* Sampling Filter Control Register */ + PMSEVFR_EL1, /* Sampling Event Filter Register */ + PMSLATFR_EL1, /* Sampling Latency Filter Register */ + PMBLIMITR_EL1, /* Profiling Buffer Limit Address Register */ + PMBPTR_EL1, /* Profiling Buffer Write Pointer Register */ + PMBSR_EL1, /* Profiling Buffer Status/syndrome Register */ + /* 32bit specific registers. Keep them at the end of the range */ DACR32_EL2, /* Domain Access Control Register */ IFSR32_EL2, /* Instruction Fault Status Register */ diff --git a/arch/arm64/kvm/spe.c b/arch/arm64/kvm/spe.c index 316ff8dfed5b..0e365a51cac7 100644 --- a/arch/arm64/kvm/spe.c +++ b/arch/arm64/kvm/spe.c @@ -12,6 +12,16 @@ #include <asm/kvm_mmu.h> +void kvm_arm_spe_write_sysreg(struct kvm_vcpu *vcpu, int reg, u64 val) +{ + __vcpu_sys_reg(vcpu, reg) = val; +} + +u64 kvm_arm_spe_read_sysreg(struct kvm_vcpu *vcpu, int reg) +{ + return __vcpu_sys_reg(vcpu, reg); +} + void kvm_arm_spe_notify_vcpu_init(struct kvm_vcpu *vcpu) { vcpu->kvm->arch.spe.finalized = false; diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index aa776c006a2a..2871484993ec 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -244,9 +244,37 @@ static bool access_vm_reg(struct kvm_vcpu *vcpu, return true; } +static bool access_spe_reg(struct kvm_vcpu *vcpu, + struct sys_reg_params *p, + const struct sys_reg_desc *r) +{ + u64 val = p->regval; + int reg = r->reg; + u32 sr = sys_reg((u32)r->Op0, (u32)r->Op1, + (u32)r->CRn, (u32)r->CRm, (u32)r->Op2); + + if (sr == SYS_PMSIDR_EL1) { + /* Ignore writes. */ + if (!p->is_write) + p->regval = read_sysreg_s(SYS_PMSIDR_EL1); + goto out; + } + + if (p->is_write) + kvm_arm_spe_write_sysreg(vcpu, reg, val); + else + p->regval = kvm_arm_spe_read_sysreg(vcpu, reg); + +out: + return true; +} + static unsigned int spe_visibility(const struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { + if (vcpu_has_spe(vcpu)) + return 0; + return REG_HIDDEN_GUEST | REG_HIDDEN_USER; } @@ -1598,16 +1626,16 @@ static const struct sys_reg_desc sys_reg_descs[] = { { SYS_DESC(SYS_FAR_EL1), access_vm_reg, reset_unknown, FAR_EL1 }, { SYS_DESC(SYS_PAR_EL1), NULL, reset_unknown, PAR_EL1 }, - { SYS_DESC(SYS_PMSCR_EL1), .visibility = spe_visibility }, - { SYS_DESC(SYS_PMSICR_EL1), .visibility = spe_visibility }, - { SYS_DESC(SYS_PMSIRR_EL1), .visibility = spe_visibility }, - { SYS_DESC(SYS_PMSFCR_EL1), .visibility = spe_visibility }, - { SYS_DESC(SYS_PMSEVFR_EL1), .visibility = spe_visibility }, - { SYS_DESC(SYS_PMSLATFR_EL1), .visibility = spe_visibility }, - { SYS_DESC(SYS_PMSIDR_EL1), .visibility = spe_visibility }, - { SYS_DESC(SYS_PMBLIMITR_EL1), .visibility = spe_visibility }, - { SYS_DESC(SYS_PMBPTR_EL1), .visibility = spe_visibility }, - { SYS_DESC(SYS_PMBSR_EL1), .visibility = spe_visibility }, + { SYS_DESC(SYS_PMSCR_EL1), access_spe_reg, reset_val, PMSCR_EL1, 0, .visibility = spe_visibility }, + { SYS_DESC(SYS_PMSICR_EL1), access_spe_reg, reset_val, PMSICR_EL1, 0, .visibility = spe_visibility }, + { SYS_DESC(SYS_PMSIRR_EL1), access_spe_reg, reset_val, PMSIRR_EL1, 0, .visibility = spe_visibility }, + { SYS_DESC(SYS_PMSFCR_EL1), access_spe_reg, reset_val, PMSFCR_EL1, 0, .visibility = spe_visibility }, + { SYS_DESC(SYS_PMSEVFR_EL1), access_spe_reg, reset_val, PMSEVFR_EL1, 0, .visibility = spe_visibility }, + { SYS_DESC(SYS_PMSLATFR_EL1), access_spe_reg, reset_val, PMSEVFR_EL1, 0, .visibility = spe_visibility }, + { SYS_DESC(SYS_PMSIDR_EL1), access_spe_reg, .visibility = spe_visibility }, + { SYS_DESC(SYS_PMBLIMITR_EL1), access_spe_reg, reset_val, PMBLIMITR_EL1, 0, .visibility = spe_visibility }, + { SYS_DESC(SYS_PMBPTR_EL1), access_spe_reg, reset_unknown, PMBPTR_EL1, .visibility = spe_visibility }, + { SYS_DESC(SYS_PMBSR_EL1), access_spe_reg, reset_val, PMBSR_EL1, 0, .visibility = spe_visibility }, { SYS_DESC(SYS_PMINTENSET_EL1), access_pminten, reset_unknown, PMINTENSET_EL1 }, { SYS_DESC(SYS_PMINTENCLR_EL1), access_pminten, reset_unknown, PMINTENSET_EL1 }, diff --git a/include/kvm/arm_spe.h b/include/kvm/arm_spe.h index 7f9f3a03aadb..a2429edc4483 100644 --- a/include/kvm/arm_spe.h +++ b/include/kvm/arm_spe.h @@ -38,6 +38,9 @@ int kvm_arm_vm_spe_has_attr(struct kvm *vcpu, struct kvm_device_attr *attr); void kvm_arm_spe_notify_vcpu_init(struct kvm_vcpu *vcpu); +void kvm_arm_spe_write_sysreg(struct kvm_vcpu *vcpu, int reg, u64 val); +u64 kvm_arm_spe_read_sysreg(struct kvm_vcpu *vcpu, int reg); + #else #define kvm_arm_supports_spe() false @@ -87,5 +90,11 @@ static inline int kvm_arm_vm_spe_has_attr(struct kvm *vcpu, static inline void kvm_arm_spe_notify_vcpu_init(struct kvm_vcpu *vcpu) {} +static inline void kvm_arm_spe_write_sysreg(struct kvm_vcpu *vcpu, int reg, u64 val) {} +static inline u64 kvm_arm_spe_read_sysreg(struct kvm_vcpu *vcpu, int reg) +{ + return 0; +} + #endif /* CONFIG_KVM_ARM_SPE */ #endif /* __ASM_ARM_KVM_SPE_H */ -- 2.29.1 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2020-10-27 17:26 UTC|newest] Thread overview: 70+ messages / expand[flat|nested] mbox.gz Atom feed top 2020-10-27 17:26 [RFC PATCH v3 00/16] KVM: arm64: Add Statistical Profiling Extension (SPE) support Alexandru Elisei 2020-10-27 17:26 ` Alexandru Elisei 2020-10-27 17:26 ` [RFC PATCH v3 01/16] KVM: arm64: Initialize VCPU mdcr_el2 before loading it Alexandru Elisei 2020-10-27 17:26 ` Alexandru Elisei 2020-11-19 16:58 ` James Morse 2020-11-19 16:58 ` James Morse 2020-12-02 14:25 ` Alexandru Elisei 2020-12-02 14:25 ` Alexandru Elisei 2020-10-27 17:26 ` [RFC PATCH v3 02/16] dt-bindings: ARM SPE: Highlight the need for PPI partitions on heterogeneous systems Alexandru Elisei 2020-10-27 17:26 ` Alexandru Elisei 2020-10-27 17:26 ` [RFC PATCH v3 03/16] KVM: arm64: Hide SPE from guests Alexandru Elisei 2020-10-27 17:26 ` Alexandru Elisei 2020-10-27 17:26 ` [RFC PATCH v3 04/16] arm64: Introduce CPU SPE feature Alexandru Elisei 2020-10-27 17:26 ` Alexandru Elisei 2020-11-19 16:58 ` James Morse 2020-11-19 16:58 ` James Morse 2020-12-02 14:29 ` Alexandru Elisei 2020-12-02 14:29 ` Alexandru Elisei 2020-12-02 17:23 ` Will Deacon 2020-12-02 17:23 ` Will Deacon 2020-12-03 10:07 ` Alexandru Elisei 2020-12-03 10:07 ` Alexandru Elisei 2020-10-27 17:26 ` [RFC PATCH v3 05/16] KVM: arm64: Introduce VCPU " Alexandru Elisei 2020-10-27 17:26 ` Alexandru Elisei 2020-10-27 17:26 ` [RFC PATCH v3 06/16] KVM: arm64: Introduce SPE primitives Alexandru Elisei 2020-10-27 17:26 ` Alexandru Elisei 2020-11-19 16:58 ` James Morse 2020-11-19 16:58 ` James Morse 2020-12-02 15:13 ` Alexandru Elisei 2020-12-02 15:13 ` Alexandru Elisei 2020-10-27 17:26 ` [RFC PATCH v3 07/16] KVM: arm64: Define SPE data structure for each VCPU Alexandru Elisei 2020-10-27 17:26 ` Alexandru Elisei 2020-10-27 17:26 ` [RFC PATCH v3 08/16] KVM: arm64: Add a new VCPU device control group for SPE Alexandru Elisei 2020-10-27 17:26 ` Alexandru Elisei 2020-11-05 9:58 ` Haibo Xu 2020-11-05 9:58 ` Haibo Xu 2020-12-02 15:20 ` Alexandru Elisei 2020-12-02 15:20 ` Alexandru Elisei 2020-11-19 16:58 ` James Morse 2020-11-19 16:58 ` James Morse 2020-12-02 16:28 ` Alexandru Elisei 2020-12-02 16:28 ` Alexandru Elisei 2020-10-27 17:26 ` [RFC PATCH v3 09/16] KVM: arm64: Use separate function for the mapping size in user_mem_abort() Alexandru Elisei 2020-10-27 17:26 ` Alexandru Elisei 2020-11-05 10:01 ` Haibo Xu 2020-11-05 10:01 ` Haibo Xu 2020-12-02 16:29 ` Alexandru Elisei 2020-12-02 16:29 ` Alexandru Elisei 2020-10-27 17:26 ` [RFC PATCH v3 10/16] KVM: arm64: Add a new VM device control group for SPE Alexandru Elisei 2020-10-27 17:26 ` Alexandru Elisei 2020-11-05 10:10 ` Haibo Xu 2020-11-05 10:10 ` Haibo Xu 2020-12-02 16:35 ` Alexandru Elisei 2020-12-02 16:35 ` Alexandru Elisei 2020-11-19 16:59 ` James Morse 2020-11-19 16:59 ` James Morse 2021-03-23 14:27 ` Alexandru Elisei 2021-03-23 14:27 ` Alexandru Elisei 2020-10-27 17:27 ` Alexandru Elisei [this message] 2020-10-27 17:27 ` [RFC PATCH v3 11/16] KVM: arm64: Add SPE system registers to VCPU context Alexandru Elisei 2020-10-27 17:27 ` [RFC PATCH v3 12/16] KVM: arm64: VHE: Clear MDCR_EL2.E2PB in vcpu_put() Alexandru Elisei 2020-10-27 17:27 ` Alexandru Elisei 2020-10-27 17:27 ` [RFC PATCH v3 13/16] KVM: arm64: Switch SPE context on VM entry/exit Alexandru Elisei 2020-10-27 17:27 ` Alexandru Elisei 2020-10-27 17:27 ` [RFC PATCH v3 14/16] KVM: arm64: Emulate SPE buffer management interrupt Alexandru Elisei 2020-10-27 17:27 ` Alexandru Elisei 2020-10-27 17:27 ` [RFC PATCH v3 15/16] KVM: arm64: Enable SPE for guests Alexandru Elisei 2020-10-27 17:27 ` Alexandru Elisei 2020-10-27 17:27 ` [RFC PATCH v3 16/16] Documentation: arm64: Document ARM Neoverse-N1 erratum #1688567 Alexandru Elisei 2020-10-27 17:27 ` Alexandru Elisei
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=20201027172705.15181-12-alexandru.elisei@arm.com \ --to=alexandru.elisei@arm.com \ --cc=kvmarm@lists.cs.columbia.edu \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=maz@kernel.org \ --cc=will@kernel.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 an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.