public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Jeff Fan <jeff.fan@intel.com>
To: edk2-devel@lists.01.org
Cc: Feng Tian <feng.tian@intel.com>,
	Michael Kinney <michael.d.kinney@intel.com>
Subject: [PATCH v4 08/11] UefiCpuPkg/Include/Library: Add Register CPU Features Library
Date: Fri, 17 Mar 2017 13:49:20 +0800	[thread overview]
Message-ID: <20170317054921.12204-3-jeff.fan@intel.com> (raw)
In-Reply-To: <20170317054921.12204-1-jeff.fan@intel.com>

Register CPU Features Library is used to register/manage/program CPU features.
NULL CPU features library instance could consume it register CPU features
functions.
CPU Feature module could consume this library to detect/analysis/program CPU
features on BSP/APs.

v4:
  Fix GCC build issue.

Cc: Feng Tian <feng.tian@intel.com>
Cc: Michael Kinney <michael.d.kinney@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jeff Fan <jeff.fan@intel.com>
---
 .../Include/Library/RegisterCpuFeaturesLib.h       | 516 +++++++++++++++++++++
 UefiCpuPkg/UefiCpuPkg.dec                          |   5 +
 2 files changed, 521 insertions(+)
 create mode 100644 UefiCpuPkg/Include/Library/RegisterCpuFeaturesLib.h

diff --git a/UefiCpuPkg/Include/Library/RegisterCpuFeaturesLib.h b/UefiCpuPkg/Include/Library/RegisterCpuFeaturesLib.h
new file mode 100644
index 0000000..42eb3b2
--- /dev/null
+++ b/UefiCpuPkg/Include/Library/RegisterCpuFeaturesLib.h
@@ -0,0 +1,516 @@
+/** @file
+  Register CPU Features Library to register and manage CPU features.
+
+  Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __REGISTER_CPU_FEATURES_LIB_H__
+#define __REGISTER_CPU_FEATURES_LIB_H__
+
+#include <AcpiCpuData.h>
+#include <Register/Cpuid.h>
+#include <Protocol/MpService.h>
+
+///
+/// Defines used to identify a CPU feature.  The lower 16-bits are used to
+/// identify a unique CPU feature and the value represents a bit number in
+/// a bit mask.  The upper 16-bits are bit mask values that are used as
+/// modifiers of a CPU feature.  When used in a list, the define value
+/// CPU_FEATURE_END is used to terminate a list of CPU feature values.
+/// @{
+#define CPU_FEATURE_AESNI                           0
+#define CPU_FEATURE_TURBO_MODE                      1
+#define CPU_FEATURE_MWAIT                           2
+#define CPU_FEATURE_ACPI                            3
+#define CPU_FEATURE_EIST                            4
+#define CPU_FEATURE_XD                              5
+#define CPU_FEATURE_FASTSTRINGS                     6
+#define CPU_FEATURE_VMX                             7
+#define CPU_FEATURE_SMX                             8
+#define CPU_FEATURE_SENTER                          9
+#define CPU_FEATURE_LOCK_FEATURE_CONTROL_REGISTER   10
+#define CPU_FEATURE_LIMIT_CPUID_MAX_VAL             11
+#define CPU_FEATURE_MCE                             12
+#define CPU_FEATURE_MCA                             13
+#define CPU_FEATURE_MCG_CTL                         14
+#define CPU_FEATURE_PENDING_BREAK                   15
+#define CPU_FEATURE_C1E                             16
+#define CPU_FEATURE_C1_AUTO_DEMOTION                17
+#define CPU_FEATURE_C3_AUTO_DEMOTION                18
+#define CPU_FEATURE_C1_AUTO_UNDEMOTION              19
+#define CPU_FEATURE_C3_AUTO_UNDEMOTION              20
+#define CPU_FEATURE_C_STATE                         21
+#define CPU_FEATURE_TM                              22
+#define CPU_FEATURE_TM2                             23
+#define CPU_FEATURE_X2APIC                          24
+#define CPU_FEATURE_RESERVED_25                     25
+#define CPU_FEATURE_RESERVED_26                     26
+#define CPU_FEATURE_RESERVED_27                     27
+#define CPU_FEATURE_RESERVED_28                     28
+#define CPU_FEATURE_RESERVED_29                     29
+#define CPU_FEATURE_RESERVED_30                     30
+#define CPU_FEATURE_RESERVED_31                     31
+
+#define CPU_FEATURE_L2_PREFETCHER                   (32+0)
+#define CPU_FEATURE_L1_DATA_PREFETCHER              (32+1)
+#define CPU_FEATURE_HARDWARE_PREFETCHER             (32+2)
+#define CPU_FEATURE_ADJACENT_CACHE_LINE_PREFETCH    (32+3)
+#define CPU_FEATURE_DCU_PREFETCHER                  (32+4)
+#define CPU_FEATURE_IP_PREFETCHER                   (32+5)
+#define CPU_FEATURE_MLC_STREAMER_PREFETCHER         (32+6)
+#define CPU_FEATURE_MLC_SPATIAL_PREFETCHER          (32+7)
+#define CPU_FEATURE_THREE_STRICK_COUNTER            (32+8)
+#define CPU_FEATURE_APIC_TPR_UPDATE_MESSAGE         (32+9)
+#define CPU_FEATURE_ENERGY_PERFORMANCE_BIAS         (32+10)
+
+#define CPU_FEATURE_BEFORE_ALL                      BIT27
+#define CPU_FEATURE_AFTER_ALL                       BIT28
+#define CPU_FEATURE_BEFORE                          BIT29
+#define CPU_FEATURE_AFTER                           BIT30
+#define CPU_FEATURE_END                             MAX_UINT32
+/// @}
+
+///
+/// CPU Information passed into the SupportFunc and InitializeFunc of the
+/// RegisterCpuFeature() library function.  This structure contains information
+/// that is commonly used during CPU feature detection and initialization.
+///
+typedef struct {
+  ///
+  /// The package that the CPU resides
+  ///
+  EFI_PROCESSOR_INFORMATION            ProcessorInfo;
+  ///
+  /// The Display Family of the CPU computed from CPUID leaf CPUID_VERSION_INFO
+  ///
+  UINT32                               DisplayFamily;
+  ///
+  /// The Display Model of the CPU computed from CPUID leaf CPUID_VERSION_INFO
+  ///
+  UINT32                               DisplayModel;
+  ///
+  /// The Stepping ID of the CPU computed from CPUID leaf CPUID_VERSION_INFO
+  ///
+  UINT32                               SteppingId;
+  ///
+  /// The Processor Type of the CPU computed from CPUID leaf CPUID_VERSION_INFO
+  ///
+  UINT32                               ProcessorType;
+  ///
+  /// Bit field structured returned in ECX from CPUID leaf CPUID_VERSION_INFO
+  ///
+  CPUID_VERSION_INFO_ECX               CpuIdVersionInfoEcx;
+  ///
+  /// Bit field structured returned in EDX from CPUID leaf CPUID_VERSION_INFO
+  ///
+  CPUID_VERSION_INFO_EDX               CpuIdVersionInfoEdx;
+} REGISTER_CPU_FEATURE_INFORMATION;
+
+/**
+  Determines if a CPU feature is enabled in PcdCpuFeaturesSupport bit mask.
+  If a CPU feature is disabled in PcdCpuFeaturesSupport then all the code/data
+  associated with that feature should be optimized away if compiler
+  optimizations are enabled.
+
+  @param[in]  Feature  The bit number of the CPU feature to check in the PCD
+                       PcdCpuFeaturesSupport.
+
+  @retval  TRUE   The CPU feature is set in PcdCpuFeaturesSupport.
+  @retval  FALSE  The CPU feature is not set in PcdCpuFeaturesSupport.
+
+  @note This service could be called by BSP only.
+**/
+BOOLEAN
+EFIAPI
+IsCpuFeatureSupported (
+  IN UINT32              Feature
+  );
+
+/**
+  Determines if a CPU feature is set in PcdCpuFeaturesSetting bit mask.
+
+  @param[in]  Feature  The bit number of the CPU feature to check in the PCD
+                       PcdCpuFeaturesSetting.
+
+  @retval  TRUE   The CPU feature is set in PcdCpuFeaturesSetting.
+  @retval  FALSE  The CPU feature is not set in PcdCpuFeaturesSetting.
+
+  @note This service could be called by BSP only.
+**/
+BOOLEAN
+EFIAPI
+IsCpuFeatureInSetting (
+  IN UINT32              Feature
+  );
+
+/**
+  Determines if a CPU feature is set in PcdCpuFeaturesCapability bit mask.
+
+  @param[in]  Feature  The bit number of the CPU feature to check in the PCD
+                       PcdCpuFeaturesCapability.
+
+  @retval  TRUE   The CPU feature is set in PcdCpuFeaturesCapability.
+  @retval  FALSE  The CPU feature is not set in PcdCpuFeaturesCapability.
+
+  @note This service could be called by BSP only.
+**/
+BOOLEAN
+EFIAPI
+IsCpuFeatureCapability (
+  IN UINT32              Feature
+  );
+
+/**
+  Determines if a CPU feature is set in PcdCpuFeaturesUserConfiguration bit mask.
+
+  @param[in]  Feature  The bit number of the CPU feature to check in the PCD
+                       PcdCpuFeaturesUserConfiguration.
+
+  @retval  TRUE   The CPU feature is set in PcdCpuFeaturesUserConfiguration.
+  @retval  FALSE  The CPU feature is not set in PcdCpuFeaturesUserConfiguration.
+
+  @note This service could be called by BSP only.
+**/
+BOOLEAN
+EFIAPI
+IsCpuFeatureUserConfiguration (
+  IN UINT32              Feature
+  );
+
+/**
+  Prepares for the data used by CPU feature detection and initialization.
+
+  @param[in]  NumberOfProcessors  The number of CPUs in the platform.
+
+  @return  Pointer to a buffer of CPU related configuration data.
+
+  @note This service could be called by BSP only.
+**/
+typedef
+VOID *
+(EFIAPI *CPU_FEATURE_GET_CONFIG_DATA)(
+  IN UINTN               NumberOfProcessors
+  );
+
+/**
+  Detects if CPU feature supported on current processor.
+
+  @param[in]  ProcessorNumber  The index of the CPU executing this function.
+  @param[in]  CpuInfo          A pointer to the REGISTER_CPU_FEATURE_INFORMATION
+                               structure for the CPU executing this function.
+  @param[in]  ConfigData       A pointer to the configuration buffer returned
+                               by CPU_FEATURE_GET_CONFIG_DATA.  NULL if
+                               CPU_FEATURE_GET_CONFIG_DATA was not provided in
+                               RegisterCpuFeature().
+
+  @retval TRUE     CPU feature is supported.
+  @retval FALSE    CPU feature is not supported.
+
+  @note This service could be called by BSP/APs.
+**/
+typedef
+BOOLEAN
+(EFIAPI *CPU_FEATURE_SUPPORT)(
+  IN UINTN                             ProcessorNumber,
+  IN REGISTER_CPU_FEATURE_INFORMATION  *CpuInfo,
+  IN VOID                              *ConfigData  OPTIONAL
+  );
+
+/**
+  Initializes CPU feature to specific state.
+
+  This service does not initialize hardware and only produces entries in the
+  Register Table for specified processor. Hardware initialization on BSP/APs
+  will be done in CpuFeaturesInitialize().
+
+  @param[in]  ProcessorNumber  The index of the CPU executing this function.
+  @param[in]  CpuInfo          A pointer to the REGISTER_CPU_FEATURE_INFORMATION
+                               structure for the CPU executing this function.
+  @param[in]  ConfigData       A pointer to the configuration buffer returned
+                               by CPU_FEATURE_GET_CONFIG_DATA.  NULL if
+                               CPU_FEATURE_GET_CONFIG_DATA was not provided in
+                               RegisterCpuFeature().
+  @param[in]  State            If TRUE, then the CPU feature must be enabled.
+                               If FALSE, then the CPU feature must be disabled.
+
+  @retval RETURN_SUCCESS       CPU feature is initialized.
+
+  @note This service could be called by BSP only.
+**/
+typedef
+RETURN_STATUS
+(EFIAPI *CPU_FEATURE_INITIALIZE)(
+  IN UINTN                             ProcessorNumber,
+  IN REGISTER_CPU_FEATURE_INFORMATION  *CpuInfo,
+  IN VOID                              *ConfigData,  OPTIONAL
+  IN BOOLEAN                           State
+  );
+
+/**
+  Registers a CPU Feature.
+
+  @param  GetConfigDataFunc  CPU feature get configuration data function.  This
+                             is an optional parameter that may be NULL.  If NULL,
+                             then the most recently registered function for the
+                             CPU feature is used.  If no functions are registered
+                             for a CPU feature, then the CPU configuration data
+                             for the registered feature is NULL.
+  @param  SupportFunc        CPU feature support function.  This is an optional
+                             parameter that may be NULL.  If NULL, then the most
+                             recently registered function for the CPU feature is
+                             used. If no functions are registered for a CPU
+                             feature, then the CPU feature is assumed to be
+                             supported by all CPUs.
+  @param  InitializeFunc     CPU feature initialize function.  This is an optional
+                             parameter that may be NULL.  If NULL, then the most
+                             recently registered function for the CPU feature is
+                             used. If no functions are registered for a CPU
+                             feature, then the CPU feature initialization is
+                             skipped.
+  @param  ...                Variable argument list of UINT32 CPU feature value.
+                             Values with no modifiers are the features provided
+                             by the registered functions.
+                             Values with CPU_FEATURE_BEFORE modifier are features
+                             that must be initialized after the features provided
+                             by the registered functions are used.
+                             Values with CPU_FEATURE_AFTER modifier are features
+                             that must be initialized before the features provided
+                             by the registered functions are used.
+                             The last argument in this variable argument list must
+                             always be CPU_FEATURE_END.
+
+  @retval  RETURN_SUCCESS           The CPU feature was successfully registered.
+  @retval  RETURN_OUT_OF_RESOURCES  There are not enough resources to register
+                                    the CPU feature.
+  @retval  RETURN_UNSUPPORTED       Registration of the CPU feature is not
+                                    supported due to a circular dependency between
+                                    BEFORE and AFTER features.
+
+  @note This service could be called by BSP only.
+**/
+RETURN_STATUS
+EFIAPI
+RegisterCpuFeature (
+  IN CHAR8                             *FeatureName,       OPTIONAL
+  IN CPU_FEATURE_GET_CONFIG_DATA       GetConfigDataFunc,  OPTIONAL
+  IN CPU_FEATURE_SUPPORT               SupportFunc,        OPTIONAL
+  IN CPU_FEATURE_INITIALIZE            InitializeFunc,     OPTIONAL
+  ...
+  );
+
+/**
+  Performs CPU features detection.
+
+  This service will invoke MP service to check CPU features'
+  capabilities on BSP/APs.
+
+  @note This service could be called by BSP only.
+**/
+VOID
+EFIAPI
+CpuFeaturesDetect (
+  VOID
+  );
+
+/**
+  Performs CPU features Initialization.
+
+  This service will invoke MP service to perform CPU features
+  initialization on BSP/APs per user configuration.
+
+  @note This service could be called by BSP only.
+**/
+VOID
+EFIAPI
+CpuFeaturesInitialize (
+  VOID
+  );
+
+/**
+  Switches to assigned BSP after CPU features initialization.
+
+  @param[in]  ProcessorNumber  The index of the CPU executing this function.
+
+  @note This service could be called by BSP only.
+**/
+VOID
+EFIAPI
+SwitchBspAfterFeaturesInitialize (
+  IN UINTN               ProcessorNumber
+  );
+
+/**
+  Adds an entry in specified register table.
+
+  This function adds an entry in specified register table, with given register type,
+  register index, bit section and value.
+
+  @param[in]  ProcessorNumber  The index of the CPU to add a register table entry.
+  @param[in]  RegisterType     Type of the register to program
+  @param[in]  Index            Index of the register to program
+  @param[in]  ValueMask        Mask of bits in register to write
+  @param[in]  Value            Value to write
+
+  @note This service could be called by BSP only.
+**/
+VOID
+EFIAPI
+CpuRegisterTableWrite (
+  IN UINTN               ProcessorNumber,
+  IN REGISTER_TYPE       RegisterType,
+  IN UINT32              Index,
+  IN UINT64              ValueMask,
+  IN UINT64              Value
+  );
+
+/**
+  Adds an entry in specified Pre-SMM register table.
+
+  This function adds an entry in specified register table, with given register type,
+  register index, bit section and value.
+
+  @param[in]  ProcessorNumber  The index of the CPU to add a register table entry.
+  @param[in]  RegisterType     Type of the register to program
+  @param[in]  Index            Index of the register to program
+  @param[in]  ValueMask        Mask of bits in register to write
+  @param[in]  Value            Value to write
+
+  @note This service could be called by BSP only.
+**/
+VOID
+EFIAPI
+PreSmmCpuRegisterTableWrite (
+  IN UINTN               ProcessorNumber,
+  IN REGISTER_TYPE       RegisterType,
+  IN UINT32              Index,
+  IN UINT64              ValueMask,
+  IN UINT64              Value
+  );
+
+/**
+  Adds a 32-bit register write entry in specified register table.
+
+  This macro adds an entry in specified register table, with given register type,
+  register index, and value.
+
+  @param[in]  ProcessorNumber  The index of the CPU to add a register table entry.
+  @param[in]  RegisterType     Type of the register to program
+  @param[in]  Index            Index of the register to program
+  @param[in]  Value            Value to write
+
+  @note This service could be called by BSP only.
+**/
+#define CPU_REGISTER_TABLE_WRITE32(ProcessorNumber, RegisterType, Index, Value)       \
+  do {                                                                                \
+    CpuRegisterTableWrite (ProcessorNumber, RegisterType, Index, MAX_UINT32, Value);  \
+  } while(FALSE);
+
+/**
+  Adds a 64-bit register write entry in specified register table.
+
+  This macro adds an entry in specified register table, with given register type,
+  register index, and value.
+
+  @param[in]  ProcessorNumber  The index of the CPU to add a register table entry.
+  @param[in]  RegisterType     Type of the register to program
+  @param[in]  Index            Index of the register to program
+  @param[in]  Value            Value to write
+
+  @note This service could be called by BSP only.
+**/
+#define CPU_REGISTER_TABLE_WRITE64(ProcessorNumber, RegisterType, Index, Value)       \
+  do {                                                                                \
+    CpuRegisterTableWrite (ProcessorNumber, RegisterType, Index, MAX_UINT64, Value);  \
+  } while(FALSE);
+
+/**
+  Adds a bit field write entry in specified register table.
+
+  This macro adds an entry in specified register table, with given register type,
+  register index, bit field section, and value.
+
+  @param[in]  ProcessorNumber  The index of the CPU to add a register table entry.
+  @param[in]  RegisterType     Type of the register to program.
+  @param[in]  Index            Index of the register to program.
+  @param[in]  Type             The data type name of a register structure.
+  @param[in]  Field            The bit fiel name in register structure to write.
+  @param[in]  Value            Value to write to the bit field.
+
+  @note This service could be called by BSP only.
+**/
+#define CPU_REGISTER_TABLE_WRITE_FIELD(ProcessorNumber, RegisterType, Index, Type, Field, Value) \
+  do {                                                                                           \
+    UINT64  ValueMask;                                                                           \
+    ValueMask = MAX_UINT64;                                                                      \
+    ((Type *)(&ValueMask))->Field = 0;                                                           \
+    CpuRegisterTableWrite (ProcessorNumber, RegisterType, Index, ~ValueMask, Value);             \
+  } while(FALSE);
+
+/**
+  Adds a 32-bit register write entry in specified register table.
+
+  This macro adds an entry in specified register table, with given register type,
+  register index, and value.
+
+  @param[in]  ProcessorNumber  The index of the CPU to add a register table entry.
+  @param[in]  RegisterType     Type of the register to program
+  @param[in]  Index            Index of the register to program
+  @param[in]  Value            Value to write
+
+  @note This service could be called by BSP only.
+**/
+#define PRE_SMM_CPU_REGISTER_TABLE_WRITE32(ProcessorNumber, RegisterType, Index, Value)    \
+  do {                                                                                     \
+    PreSmmCpuRegisterTableWrite (ProcessorNumber, RegisterType, Index, MAX_UINT32, Value); \
+  } while(FALSE);
+
+/**
+  Adds a 64-bit register write entry in specified register table.
+
+  This macro adds an entry in specified register table, with given register type,
+  register index, and value.
+
+  @param[in]  ProcessorNumber  The index of the CPU to add a register table entry.
+  @param[in]  RegisterType     Type of the register to program
+  @param[in]  Index            Index of the register to program
+  @param[in]  Value            Value to write
+
+  @note This service could be called by BSP only.
+**/
+#define PRE_SMM_CPU_REGISTER_TABLE_WRITE64(ProcessorNumber, RegisterType, Index, Value)    \
+  do {                                                                                     \
+    PreSmmCpuRegisterTableWrite (ProcessorNumber, RegisterType, Index, MAX_UINT64, Value); \
+  } while(FALSE);
+
+/**
+  Adds a bit field write entry in specified register table.
+
+  This macro adds an entry in specified register table, with given register type,
+  register index, bit field section, and value.
+
+  @param[in]  ProcessorNumber  The index of the CPU to add a register table entry.
+  @param[in]  RegisterType     Type of the register to program.
+  @param[in]  Index            Index of the register to program.
+  @param[in]  Type             The data type name of a register structure.
+  @param[in]  Field            The bit fiel name in register structure to write.
+  @param[in]  Value            Value to write to the bit field.
+
+  @note This service could be called by BSP only.
+**/
+#define PRE_SMM_CPU_REGISTER_TABLE_WRITE_FIELD(ProcessorNumber, RegisterType, Index, Type, Field, Value) \
+  do {                                                                                                   \
+    UINT64  ValueMask;                                                                                   \
+    ValueMask = MAX_UINT64;                                                                              \
+    ((Type *)(&ValueMask))->Field = 0;                                                                   \
+    PreSmmCpuRegisterTableWrite (ProcessorNumber, RegisterType, Index, ~ValueMask, Value);                \
+  } while(FALSE);
+
+#endif
diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
index f7abe1c..04c7c1e 100644
--- a/UefiCpuPkg/UefiCpuPkg.dec
+++ b/UefiCpuPkg/UefiCpuPkg.dec
@@ -29,6 +29,11 @@
   ##
   UefiCpuLib|Include/Library/UefiCpuLib.h
 
+  ##  @libraryclass  Defines some routines that are used to register/manage/program
+  ##                 CPU features.
+  ##
+  UefiCpuLib|Include/Library/RegisterCpuFeaturesLib.h
+
 [LibraryClasses.IA32, LibraryClasses.X64]
   ##  @libraryclass  Provides functions to manage MTRR settings on IA32 and X64 CPUs.
   ##
-- 
2.9.3.windows.2



  parent reply	other threads:[~2017-03-17  5:49 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-17  5:49 [PATCH v4 00/11] Add CPU features driver Jeff Fan
2017-03-17  5:49 ` [PATCH v4 03/11] UefiCpuPkg/PiSmmCpuDxeSmm: Skip if AllocatedSize is 0 Jeff Fan
2017-03-17  5:49 ` Jeff Fan [this message]
2017-03-17  5:49 ` [PATCH v4 09/11] UefiCpuPkg: Add PEI/DXE Register CPU Features Library instances Jeff Fan

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-list 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=20170317054921.12204-3-jeff.fan@intel.com \
    --to=devel@edk2.groups.io \
    /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