All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andre Przywara <andre.przywara@arm.com>
To: Eric Auger <eric.auger@linaro.org>
Cc: "kvm@vger.kernel.org" <kvm@vger.kernel.org>,
	Marc Zyngier <Marc.Zyngier@arm.com>,
	Pavel Fedin <p.fedin@samsung.com>,
	"linux-arm-kernel@lists.infradead.org"
	<linux-arm-kernel@lists.infradead.org>,
	"kvmarm@lists.cs.columbia.edu" <kvmarm@lists.cs.columbia.edu>,
	"christoffer.dall@linaro.org" <christoffer.dall@linaro.org>
Subject: Re: [PATCH v2 09/15] KVM: arm64: implement basic ITS register handlers
Date: Tue, 25 Aug 2015 11:23:01 +0100	[thread overview]
Message-ID: <55DC4205.5030806@arm.com> (raw)
In-Reply-To: <55CCB6EC.50609@linaro.org>

Hi Eric,

....

>> diff --git a/virt/kvm/arm/its-emul.c b/virt/kvm/arm/its-emul.c
>> index 659dd39..b498f06 100644
>> --- a/virt/kvm/arm/its-emul.c
>> +++ b/virt/kvm/arm/its-emul.c
>> @@ -32,10 +32,62 @@
>>  #include "vgic.h"
>>  #include "its-emul.h"
>>
>> +#define BASER_BASE_ADDRESS(x) ((x) & 0xfffffffff000ULL)
>> +
>> +/* The distributor lock is held by the VGIC MMIO handler. */
>>  static bool handle_mmio_misc_gits(struct kvm_vcpu *vcpu,
>>                                 struct kvm_exit_mmio *mmio,
>>                                 phys_addr_t offset)
>>  {
>> +     struct vgic_its *its = &vcpu->kvm->arch.vgic.its;
>> +     u32 reg;
>> +     bool was_enabled;
>> +
>> +     switch (offset & ~3) {
>> +     case 0x00:              /* GITS_CTLR */
>> +             /* We never defer any command execution. */
>> +             reg = GITS_CTLR_QUIESCENT;
>> +             if (its->enabled)
>> +                     reg |= GITS_CTLR_ENABLE;
>> +             was_enabled = its->enabled;
>> +             vgic_reg_access(mmio, &reg, offset & 3,
>> +                             ACCESS_READ_VALUE | ACCESS_WRITE_VALUE);
>> +             its->enabled = !!(reg & GITS_CTLR_ENABLE);
>> +             return !was_enabled && its->enabled;
>> +     case 0x04:              /* GITS_IIDR */
>> +             reg = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
>> +             vgic_reg_access(mmio, &reg, offset & 3,
>> +                             ACCESS_READ_VALUE | ACCESS_WRITE_IGNORED);
>> +             break;
>> +     case 0x08:              /* GITS_TYPER */
>> +             /*
>> +              * We use linear CPU numbers for redistributor addressing,
>> +              * so GITS_TYPER.PTA is 0.
>> +              * To avoid memory waste on the guest side, we keep the
>> +              * number of IDBits and DevBits low for the time being.
>> +              * This could later be made configurable by userland.
>> +              * Since we have all collections in linked list, we claim
>> +              * that we can hold all of the collection tables in our
>> +              * own memory and that the ITT entry size is 1 byte (the
>> +              * smallest possible one).
>> +              */
>> +             reg = GITS_TYPER_PLPIS;
>> +             reg |= 0xff << GITS_TYPER_HWCOLLCNT_SHIFT;
>> +             reg |= 0x0f << GITS_TYPER_DEVBITS_SHIFT;
>> +             reg |= 0x0f << GITS_TYPER_IDBITS_SHIFT;
>> +             vgic_reg_access(mmio, &reg, offset & 3,
>> +                             ACCESS_READ_VALUE | ACCESS_WRITE_IGNORED);
>> +             break;
>> +     case 0x0c:
>> +             /* The upper 32bits of TYPER are all 0 for the time being.
>> +              * Should we need more than 256 collections, we can enable
>> +              * some bits in here.
>> +              */
>> +             vgic_reg_access(mmio, NULL, offset & 3,
>> +                             ACCESS_READ_RAZ | ACCESS_WRITE_IGNORED);
>> +             break;
>> +     }
>> +
>>       return false;
>>  }
>>
>> @@ -43,20 +95,142 @@ static bool handle_mmio_gits_idregs(struct kvm_vcpu *vcpu,
>>                                   struct kvm_exit_mmio *mmio,
>>                                   phys_addr_t offset)
>>  {
>> +     u32 reg = 0;
>> +     int idreg = (offset & ~3) + GITS_IDREGS_BASE;
>> +
>> +     switch (idreg) {
>> +     case GITS_PIDR2:
>> +             reg = GIC_PIDR2_ARCH_GICv3;
>> +             break;
>> +     case GITS_PIDR4:
>> +             /* This is a 64K software visible page */
>> +             reg = 0x40;
>> +             break;
>> +     /* Those are the ID registers for (any) GIC. */
>> +     case GITS_CIDR0:
>> +             reg = 0x0d;
>> +             break;
>> +     case GITS_CIDR1:
>> +             reg = 0xf0;
>> +             break;
>> +     case GITS_CIDR2:
>> +             reg = 0x05;
>> +             break;
>> +     case GITS_CIDR3:
>> +             reg = 0xb1;
>> +             break;
>> +     }
>> +     vgic_reg_access(mmio, &reg, offset & 3,
>> +                     ACCESS_READ_VALUE | ACCESS_WRITE_IGNORED);
>>       return false;
>>  }
>>
>> +static int vits_handle_command(struct kvm_vcpu *vcpu, u64 *its_cmd)
>> +{
>> +     return -ENODEV;
>> +}
>> +
>>  static bool handle_mmio_gits_cbaser(struct kvm_vcpu *vcpu,
>>                                   struct kvm_exit_mmio *mmio,
>>                                   phys_addr_t offset)
>>  {
>> +     struct vgic_its *its = &vcpu->kvm->arch.vgic.its;
>> +     int mode = ACCESS_READ_VALUE;
>> +
>> +     mode |= its->enabled ? ACCESS_WRITE_IGNORED : ACCESS_WRITE_VALUE;
>> +
>> +     vgic_handle_base_register(vcpu, mmio, offset, &its->cbaser, mode);
>> +
>> +     /* Writing CBASER resets the read pointer. */
>> +     if (mmio->is_write)
>> +             its->creadr = 0;
>> +
>>       return false;
>>  }
>>
>> +static int its_cmd_buffer_size(struct kvm *kvm)
>> +{
>> +     struct vgic_its *its = &kvm->arch.vgic.its;
>> +
>> +     return ((its->cbaser & 0xff) + 1) << 12;
>> +}
>> +
>> +static gpa_t its_cmd_buffer_base(struct kvm *kvm)
>> +{
>> +     struct vgic_its *its = &kvm->arch.vgic.its;
>> +
>> +     return BASER_BASE_ADDRESS(its->cbaser);
>> +}
>> +
>> +/*
>> + * By writing to CWRITER the guest announces new commands to be processed.
>> + * Since we cannot read from guest memory inside the ITS spinlock, we
>> + * iterate over the command buffer (with the lock dropped) until the read
>> + * pointer matches the write pointer. Other VCPUs writing this register in the
>> + * meantime will just update the write pointer, leaving the command
>> + * processing to the first instance of the function.
>> + */
> I am lost, isn't the dist lock hold by vgic_handle_mmio_access before
> calling call_range_handler/range->handle_mmio ?

Indeed, I was so focussed on the ITS lock...

> if confirmed we need to move the command enumeration + execution
> somewhere else.

I think we get away with dropping the dist lock after doing the actual
register access. Just before returning we then take it again to make the
caller happy.
I will give this a try. Thanks for spotting this!

> Besides that piece of code may deserve to be
> encaspulated in a function. what do you think?

Makes some sense, yes.

Cheers,
André

WARNING: multiple messages have this Message-ID (diff)
From: andre.przywara@arm.com (Andre Przywara)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v2 09/15] KVM: arm64: implement basic ITS register handlers
Date: Tue, 25 Aug 2015 11:23:01 +0100	[thread overview]
Message-ID: <55DC4205.5030806@arm.com> (raw)
In-Reply-To: <55CCB6EC.50609@linaro.org>

Hi Eric,

....

>> diff --git a/virt/kvm/arm/its-emul.c b/virt/kvm/arm/its-emul.c
>> index 659dd39..b498f06 100644
>> --- a/virt/kvm/arm/its-emul.c
>> +++ b/virt/kvm/arm/its-emul.c
>> @@ -32,10 +32,62 @@
>>  #include "vgic.h"
>>  #include "its-emul.h"
>>
>> +#define BASER_BASE_ADDRESS(x) ((x) & 0xfffffffff000ULL)
>> +
>> +/* The distributor lock is held by the VGIC MMIO handler. */
>>  static bool handle_mmio_misc_gits(struct kvm_vcpu *vcpu,
>>                                 struct kvm_exit_mmio *mmio,
>>                                 phys_addr_t offset)
>>  {
>> +     struct vgic_its *its = &vcpu->kvm->arch.vgic.its;
>> +     u32 reg;
>> +     bool was_enabled;
>> +
>> +     switch (offset & ~3) {
>> +     case 0x00:              /* GITS_CTLR */
>> +             /* We never defer any command execution. */
>> +             reg = GITS_CTLR_QUIESCENT;
>> +             if (its->enabled)
>> +                     reg |= GITS_CTLR_ENABLE;
>> +             was_enabled = its->enabled;
>> +             vgic_reg_access(mmio, &reg, offset & 3,
>> +                             ACCESS_READ_VALUE | ACCESS_WRITE_VALUE);
>> +             its->enabled = !!(reg & GITS_CTLR_ENABLE);
>> +             return !was_enabled && its->enabled;
>> +     case 0x04:              /* GITS_IIDR */
>> +             reg = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
>> +             vgic_reg_access(mmio, &reg, offset & 3,
>> +                             ACCESS_READ_VALUE | ACCESS_WRITE_IGNORED);
>> +             break;
>> +     case 0x08:              /* GITS_TYPER */
>> +             /*
>> +              * We use linear CPU numbers for redistributor addressing,
>> +              * so GITS_TYPER.PTA is 0.
>> +              * To avoid memory waste on the guest side, we keep the
>> +              * number of IDBits and DevBits low for the time being.
>> +              * This could later be made configurable by userland.
>> +              * Since we have all collections in linked list, we claim
>> +              * that we can hold all of the collection tables in our
>> +              * own memory and that the ITT entry size is 1 byte (the
>> +              * smallest possible one).
>> +              */
>> +             reg = GITS_TYPER_PLPIS;
>> +             reg |= 0xff << GITS_TYPER_HWCOLLCNT_SHIFT;
>> +             reg |= 0x0f << GITS_TYPER_DEVBITS_SHIFT;
>> +             reg |= 0x0f << GITS_TYPER_IDBITS_SHIFT;
>> +             vgic_reg_access(mmio, &reg, offset & 3,
>> +                             ACCESS_READ_VALUE | ACCESS_WRITE_IGNORED);
>> +             break;
>> +     case 0x0c:
>> +             /* The upper 32bits of TYPER are all 0 for the time being.
>> +              * Should we need more than 256 collections, we can enable
>> +              * some bits in here.
>> +              */
>> +             vgic_reg_access(mmio, NULL, offset & 3,
>> +                             ACCESS_READ_RAZ | ACCESS_WRITE_IGNORED);
>> +             break;
>> +     }
>> +
>>       return false;
>>  }
>>
>> @@ -43,20 +95,142 @@ static bool handle_mmio_gits_idregs(struct kvm_vcpu *vcpu,
>>                                   struct kvm_exit_mmio *mmio,
>>                                   phys_addr_t offset)
>>  {
>> +     u32 reg = 0;
>> +     int idreg = (offset & ~3) + GITS_IDREGS_BASE;
>> +
>> +     switch (idreg) {
>> +     case GITS_PIDR2:
>> +             reg = GIC_PIDR2_ARCH_GICv3;
>> +             break;
>> +     case GITS_PIDR4:
>> +             /* This is a 64K software visible page */
>> +             reg = 0x40;
>> +             break;
>> +     /* Those are the ID registers for (any) GIC. */
>> +     case GITS_CIDR0:
>> +             reg = 0x0d;
>> +             break;
>> +     case GITS_CIDR1:
>> +             reg = 0xf0;
>> +             break;
>> +     case GITS_CIDR2:
>> +             reg = 0x05;
>> +             break;
>> +     case GITS_CIDR3:
>> +             reg = 0xb1;
>> +             break;
>> +     }
>> +     vgic_reg_access(mmio, &reg, offset & 3,
>> +                     ACCESS_READ_VALUE | ACCESS_WRITE_IGNORED);
>>       return false;
>>  }
>>
>> +static int vits_handle_command(struct kvm_vcpu *vcpu, u64 *its_cmd)
>> +{
>> +     return -ENODEV;
>> +}
>> +
>>  static bool handle_mmio_gits_cbaser(struct kvm_vcpu *vcpu,
>>                                   struct kvm_exit_mmio *mmio,
>>                                   phys_addr_t offset)
>>  {
>> +     struct vgic_its *its = &vcpu->kvm->arch.vgic.its;
>> +     int mode = ACCESS_READ_VALUE;
>> +
>> +     mode |= its->enabled ? ACCESS_WRITE_IGNORED : ACCESS_WRITE_VALUE;
>> +
>> +     vgic_handle_base_register(vcpu, mmio, offset, &its->cbaser, mode);
>> +
>> +     /* Writing CBASER resets the read pointer. */
>> +     if (mmio->is_write)
>> +             its->creadr = 0;
>> +
>>       return false;
>>  }
>>
>> +static int its_cmd_buffer_size(struct kvm *kvm)
>> +{
>> +     struct vgic_its *its = &kvm->arch.vgic.its;
>> +
>> +     return ((its->cbaser & 0xff) + 1) << 12;
>> +}
>> +
>> +static gpa_t its_cmd_buffer_base(struct kvm *kvm)
>> +{
>> +     struct vgic_its *its = &kvm->arch.vgic.its;
>> +
>> +     return BASER_BASE_ADDRESS(its->cbaser);
>> +}
>> +
>> +/*
>> + * By writing to CWRITER the guest announces new commands to be processed.
>> + * Since we cannot read from guest memory inside the ITS spinlock, we
>> + * iterate over the command buffer (with the lock dropped) until the read
>> + * pointer matches the write pointer. Other VCPUs writing this register in the
>> + * meantime will just update the write pointer, leaving the command
>> + * processing to the first instance of the function.
>> + */
> I am lost, isn't the dist lock hold by vgic_handle_mmio_access before
> calling call_range_handler/range->handle_mmio ?

Indeed, I was so focussed on the ITS lock...

> if confirmed we need to move the command enumeration + execution
> somewhere else.

I think we get away with dropping the dist lock after doing the actual
register access. Just before returning we then take it again to make the
caller happy.
I will give this a try. Thanks for spotting this!

> Besides that piece of code may deserve to be
> encaspulated in a function. what do you think?

Makes some sense, yes.

Cheers,
Andr?

  reply	other threads:[~2015-08-25 10:23 UTC|newest]

Thread overview: 138+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-10 14:21 [PATCH v2 00/15] KVM: arm64: GICv3 ITS emulation Andre Przywara
2015-07-10 14:21 ` Andre Przywara
2015-07-10 14:21 ` [PATCH v2 01/15] KVM: arm/arm64: VGIC: don't track used LRs in the distributor Andre Przywara
2015-07-10 14:21   ` Andre Przywara
2015-08-12  9:01   ` Eric Auger
2015-08-12  9:01     ` Eric Auger
2015-08-24 16:33     ` Andre Przywara
2015-08-24 16:33       ` Andre Przywara
2015-08-31  8:42       ` Eric Auger
2015-08-31  8:42         ` Eric Auger
2015-09-02  9:00         ` Andre Przywara
2015-09-02  9:00           ` Andre Przywara
2015-10-02  9:55   ` Pavel Fedin
2015-10-02  9:55     ` Pavel Fedin
2015-10-02 10:32     ` Andre Przywara
2015-10-02 10:32       ` Andre Przywara
2015-10-02 10:39       ` Pavel Fedin
2015-10-02 10:39         ` Pavel Fedin
2015-10-02 12:39       ` Pavel Fedin
2015-10-02 12:39         ` Pavel Fedin
2015-10-02 12:49         ` Andre Przywara
2015-10-02 12:49           ` Andre Przywara
2015-07-10 14:21 ` [PATCH v2 02/15] KVM: extend struct kvm_msi to hold a 32-bit device ID Andre Przywara
2015-07-10 14:21   ` Andre Przywara
2015-07-10 14:21 ` [PATCH v2 03/15] KVM: arm/arm64: add emulation model specific destroy function Andre Przywara
2015-07-10 14:21   ` Andre Przywara
2015-07-10 14:21 ` [PATCH v2 04/15] KVM: arm/arm64: extend arch CAP checks to allow per-VM capabilities Andre Przywara
2015-07-10 14:21   ` Andre Przywara
2015-08-12 12:26   ` Eric Auger
2015-08-12 12:26     ` Eric Auger
2015-07-10 14:21 ` [PATCH v2 05/15] KVM: arm/arm64: make GIC frame address initialization model specific Andre Przywara
2015-07-10 14:21   ` Andre Przywara
2015-08-12 13:02   ` Eric Auger
2015-08-12 13:02     ` Eric Auger
2015-08-24 17:24     ` Andre Przywara
2015-08-24 17:24       ` Andre Przywara
2015-08-31  9:31       ` Eric Auger
2015-08-31  9:31         ` Eric Auger
2015-07-10 14:21 ` [PATCH v2 06/15] KVM: arm64: Introduce new MMIO region for the ITS base address Andre Przywara
2015-07-10 14:21   ` Andre Przywara
2015-08-13 12:17   ` Eric Auger
2015-08-13 12:17     ` Eric Auger
2015-07-10 14:21 ` [PATCH v2 07/15] KVM: arm64: handle ITS related GICv3 redistributor registers Andre Przywara
2015-07-10 14:21   ` Andre Przywara
2015-08-13 12:17   ` Eric Auger
2015-08-13 12:17     ` Eric Auger
2015-08-24 18:08     ` Andre Przywara
2015-08-24 18:08       ` Andre Przywara
2015-07-10 14:21 ` [PATCH v2 08/15] KVM: arm64: introduce ITS emulation file with stub functions Andre Przywara
2015-07-10 14:21   ` Andre Przywara
2015-08-13 12:48   ` Eric Auger
2015-08-13 12:48     ` Eric Auger
2015-08-25  9:39     ` Andre Przywara
2015-08-25  9:39       ` Andre Przywara
2015-07-10 14:21 ` [PATCH v2 09/15] KVM: arm64: implement basic ITS register handlers Andre Przywara
2015-07-10 14:21   ` Andre Przywara
2015-08-13 15:25   ` Eric Auger
2015-08-13 15:25     ` Eric Auger
2015-08-25 10:23     ` Andre Przywara [this message]
2015-08-25 10:23       ` Andre Przywara
2015-10-02  7:51   ` Pavel Fedin
2015-10-02  7:51     ` Pavel Fedin
2015-07-10 14:21 ` [PATCH v2 10/15] KVM: arm64: add data structures to model ITS interrupt translation Andre Przywara
2015-07-10 14:21   ` Andre Przywara
2015-08-13 15:46   ` Eric Auger
2015-08-13 15:46     ` Eric Auger
2015-08-25 11:15     ` Andre Przywara
2015-08-25 11:15       ` Andre Przywara
2015-08-27 14:16       ` Eric Auger
2015-08-27 14:16         ` Eric Auger
2015-07-10 14:21 ` [PATCH v2 11/15] KVM: arm64: handle pending bit for LPIs in ITS emulation Andre Przywara
2015-07-10 14:21   ` Andre Przywara
2015-08-14 11:58   ` Eric Auger
2015-08-14 11:58     ` Eric Auger
2015-08-25 14:34     ` Andre Przywara
2015-08-25 14:34       ` Andre Przywara
2015-08-31  9:45       ` Eric Auger
2015-08-31  9:45         ` Eric Auger
2015-10-07  8:39   ` Pavel Fedin
2015-10-07  8:39     ` Pavel Fedin
2015-10-07 19:53     ` Christoffer Dall
2015-10-07 19:53       ` Christoffer Dall
2015-07-10 14:21 ` [PATCH v2 12/15] KVM: arm64: sync LPI configuration and pending tables Andre Przywara
2015-07-10 14:21   ` Andre Przywara
2015-08-14 11:58   ` Eric Auger
2015-08-14 11:58     ` Eric Auger
2015-08-14 12:35     ` Eric Auger
2015-08-14 12:35       ` Eric Auger
2015-08-25 15:47       ` Andre Przywara
2015-08-25 15:47         ` Andre Przywara
2015-08-31  9:51         ` Eric Auger
2015-08-31  9:51           ` Eric Auger
2015-08-25 15:27     ` Andre Przywara
2015-08-25 15:27       ` Andre Przywara
2015-08-31  9:47       ` Eric Auger
2015-08-31  9:47         ` Eric Auger
2015-07-10 14:21 ` [PATCH v2 13/15] KVM: arm64: implement ITS command queue command handlers Andre Przywara
2015-07-10 14:21   ` Andre Przywara
2015-08-17 13:33   ` Eric Auger
2015-08-17 13:33     ` Eric Auger
2015-10-07 14:54     ` Andre Przywara
2015-10-07 14:54       ` Andre Przywara
2015-07-10 14:21 ` [PATCH v2 14/15] KVM: arm64: implement MSI injection in ITS emulation Andre Przywara
2015-07-10 14:21   ` Andre Przywara
2015-07-31 13:22   ` Eric Auger
2015-07-31 13:22     ` Eric Auger
2015-08-02 20:20     ` Andre Przywara
2015-08-02 20:20       ` Andre Przywara
2015-08-03  6:41       ` Pavel Fedin
2015-08-03  6:41         ` Pavel Fedin
2015-08-03  9:07         ` Eric Auger
2015-08-03  9:07           ` Eric Auger
2015-08-03  9:16           ` Pavel Fedin
2015-08-03  9:16             ` Pavel Fedin
2015-08-03 15:37             ` Eric Auger
2015-08-03 15:37               ` Eric Auger
2015-08-03 17:06               ` Marc Zyngier
2015-08-03 17:06                 ` Marc Zyngier
2015-08-04  6:53                 ` Pavel Fedin
2015-08-04  6:53                   ` Pavel Fedin
2015-08-24 14:14                 ` Andre Przywara
2015-08-24 14:14                   ` Andre Przywara
2015-08-17 13:44   ` Eric Auger
2015-08-17 13:44     ` Eric Auger
2015-07-10 14:21 ` [PATCH v2 15/15] KVM: arm64: enable ITS emulation as a virtual MSI controller Andre Przywara
2015-07-10 14:21   ` Andre Przywara
2015-07-15  9:10   ` Pavel Fedin
2015-07-15  9:10     ` Pavel Fedin
2015-07-15  9:52     ` Andre Przywara
2015-07-15  9:52       ` Andre Przywara
2015-07-15 10:01       ` Pavel Fedin
2015-07-15 10:01         ` Pavel Fedin
2015-07-15 12:02 ` [PATCH v2 00/15] KVM: arm64: GICv3 ITS emulation Pavel Fedin
2015-07-15 12:02   ` Pavel Fedin
2015-09-24 11:18 ` Pavel Fedin
2015-09-24 11:18   ` Pavel Fedin
2015-09-24 11:35   ` Andre Przywara
2015-09-24 11:35     ` Andre Przywara

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=55DC4205.5030806@arm.com \
    --to=andre.przywara@arm.com \
    --cc=Marc.Zyngier@arm.com \
    --cc=christoffer.dall@linaro.org \
    --cc=eric.auger@linaro.org \
    --cc=kvm@vger.kernel.org \
    --cc=kvmarm@lists.cs.columbia.edu \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=p.fedin@samsung.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 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.