public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Jeremy Linton <jeremy.linton@arm.com>
To: "Huangming (Mark)" <huangming23@huawei.com>,
	Ming Huang <heyi.guo@linaro.org>,
	leif.lindholm@linaro.org, linaro-uefi@lists.linaro.org,
	edk2-devel@lists.01.org, graeme.gregory@linaro.org
Cc: ard.biesheuvel@linaro.org, zhangjinsong2@huawei.com,
	wanghuiqiang@huawei.com, guoheyi@huawei.com, waip23@126.com,
	mengfanrong@huawei.com
Subject: Re: [PATCH edk2-platforms v1 01/14] Hisilicon/D05: Add PPTT support
Date: Thu, 25 Jan 2018 09:27:29 -0600	[thread overview]
Message-ID: <9ce45b7b-959e-1fd1-039b-437dbb982c61@arm.com> (raw)
In-Reply-To: <8a157f0d-27d0-5d1a-1645-772d77d82518@huawei.com>

Hi,

On 01/24/2018 11:56 PM, Huangming (Mark) wrote:
> 
> 
> On 2018/1/24 5:29, Jeremy Linton wrote:
>> Hi,
>>
>>
>> On 01/18/2018 09:01 AM, Ming Huang wrote:
>>> From: Jason Zhang <zhangjinsong2@huawei.com>
>>>
>>> Contributed-under: TianoCore Contribution Agreement 1.1
>>> Signed-off-by: Jason Zhang <zhangjinsong2@huawei.com>
>>> Signed-off-by: Ming Huang <huangming23@huawei.com>
>>> Signed-off-by: Heyi Guo <heyi.guo@linaro.org>
>>> ---
>>>    Platform/Hisilicon/D05/D05.dsc                          |   1 +
>>>    Platform/Hisilicon/D05/D05.fdf                          |   1 +
>>>    Silicon/Hisilicon/Hi1616/D05AcpiTables/Hi1616Platform.h |  27 ++
>>>    Silicon/Hisilicon/Hi1616/D05AcpiTables/MadtHi1616.aslc  |  31 +-
>>>    Silicon/Hisilicon/Hi1616/Pptt/Pptt.c                    | 447 ++++++++++++++++++++
>>>    Silicon/Hisilicon/Hi1616/Pptt/Pptt.h                    | 142 +++++++
>>>    Silicon/Hisilicon/Hi1616/Pptt/Pptt.inf                  |  55 +++
>>>    7 files changed, 677 insertions(+), 27 deletions(-)
>>>
>>> diff --git a/Platform/Hisilicon/D05/D05.dsc b/Platform/Hisilicon/D05/D05.dsc
>>> index 77a89fd..710339c 100644
>>> --- a/Platform/Hisilicon/D05/D05.dsc
>>> +++ b/Platform/Hisilicon/D05/D05.dsc
>>> @@ -506,6 +506,7 @@
>>>      MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
>>>        Silicon/Hisilicon/Hi1616/D05AcpiTables/AcpiTablesHi1616.inf
>>> +  Silicon/Hisilicon/Hi1616/Pptt/Pptt.inf
>>>      Silicon/Hisilicon/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf
>>>        #
>>> diff --git a/Platform/Hisilicon/D05/D05.fdf b/Platform/Hisilicon/D05/D05.fdf
>>> index 78ab0c8..97de4d2 100644
>>> --- a/Platform/Hisilicon/D05/D05.fdf
>>> +++ b/Platform/Hisilicon/D05/D05.fdf
>>> @@ -241,6 +241,7 @@ READ_LOCK_STATUS   = TRUE
>>>      INF Silicon/Hisilicon/Drivers/HisiAcpiPlatformDxe/AcpiPlatformDxe.inf
>>>        INF RuleOverride=ACPITABLE Silicon/Hisilicon/Hi1616/D05AcpiTables/AcpiTablesHi1616.inf
>>> +  INF Silicon/Hisilicon/Hi1616/Pptt/Pptt.inf
>>>      INF Silicon/Hisilicon/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf
>>>        #
>>> diff --git a/Silicon/Hisilicon/Hi1616/D05AcpiTables/Hi1616Platform.h b/Silicon/Hisilicon/Hi1616/D05AcpiTables/Hi1616Platform.h
>>> index 808219a..f1927e8 100644
>>> --- a/Silicon/Hisilicon/Hi1616/D05AcpiTables/Hi1616Platform.h
>>> +++ b/Silicon/Hisilicon/Hi1616/D05AcpiTables/Hi1616Platform.h
>>> @@ -19,6 +19,7 @@
>>>      #ifndef _HI1610_PLATFORM_H_
>>>    #define _HI1610_PLATFORM_H_
>>> +#include <IndustryStandard/Acpi.h>
>>>      //
>>>    // ACPI table information used to initialize tables.
>>> @@ -44,5 +45,31 @@
>>>      }
>>>      #define HI1616_WATCHDOG_COUNT  2
>>> +#define HI1616_GIC_STRUCTURE_COUNT  64
>>> +
>>> +#define HI1616_MPID_TA_BASE  0x10000
>>> +#define HI1616_MPID_TB_BASE  0x30000
>>> +#define HI1616_MPID_TA_2_BASE  0x50000
>>> +#define HI1616_MPID_TB_2_BASE  0x70000
>>> +
>>> +// Differs from Juno, we have another affinity level beyond cluster and core
>>> +#define PLATFORM_GET_MPID_TA(ClusterId, CoreId)   (HI1616_MPID_TA_BASE | ((ClusterId) << 8) | (CoreId))
>>> +#define PLATFORM_GET_MPID_TB(ClusterId, CoreId)   (HI1616_MPID_TB_BASE | ((ClusterId) << 8) | (CoreId))
>>> +#define PLATFORM_GET_MPID_TA_2(ClusterId, CoreId)   (HI1616_MPID_TA_2_BASE | ((ClusterId) << 8) | (CoreId))
>>> +#define PLATFORM_GET_MPID_TB_2(ClusterId, CoreId)   (HI1616_MPID_TB_2_BASE | ((ClusterId) << 8) | (CoreId))
>>> +
>>> +//
>>> +// Multiple APIC Description Table
>>> +//
>>> +#pragma pack (1)
>>> +
>>> +typedef struct {
>>> +  EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER   Header;
>>> +  EFI_ACPI_6_1_GIC_STRUCTURE                            GicInterfaces[HI1616_GIC_STRUCTURE_COUNT];
>>> +  EFI_ACPI_6_1_GIC_DISTRIBUTOR_STRUCTURE                GicDistributor;
>>> +  EFI_ACPI_6_1_GIC_ITS_STRUCTURE                        GicITS[8];
>>> +} EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE;
>>> +
>>> +#pragma pack ()
>>>      #endif
>>> diff --git a/Silicon/Hisilicon/Hi1616/D05AcpiTables/MadtHi1616.aslc b/Silicon/Hisilicon/Hi1616/D05AcpiTables/MadtHi1616.aslc
>>> index 169ee72..33dca03 100644
>>> --- a/Silicon/Hisilicon/Hi1616/D05AcpiTables/MadtHi1616.aslc
>>> +++ b/Silicon/Hisilicon/Hi1616/D05AcpiTables/MadtHi1616.aslc
>>> @@ -1,9 +1,9 @@
>>>    /** @file
>>>    *  Multiple APIC Description Table (MADT)
>>>    *
>>> -*  Copyright (c) 2012 - 2014, ARM Limited. All rights reserved.
>>> -*  Copyright (c) 2015 - 2016, Hisilicon Limited. All rights reserved.
>>> -*  Copyright (c) 2015 - 2016, Linaro Limited. All rights reserved.
>>> +*  Copyright (c) 2012 - 2018, ARM Limited. All rights reserved.
>>> +*  Copyright (c) 2015 - 2018, Hisilicon Limited. All rights reserved.
>>> +*  Copyright (c) 2015 - 2018, Linaro Limited. All rights reserved.
>>>    *
>>>    *  This program and the accompanying materials
>>>    *
>>> @@ -19,34 +19,11 @@
>>>    *
>>>    **/
>>>    -
>>> -#include <IndustryStandard/Acpi.h>
>>> +#include "Hi1616Platform.h"
>>>    #include <Library/AcpiLib.h>
>>>    #include <Library/AcpiNextLib.h>
>>>    #include <Library/ArmLib.h>
>>>    #include <Library/PcdLib.h>
>>> -#include "Hi1616Platform.h"
>>> -
>>> -// Differs from Juno, we have another affinity level beyond cluster and core
>>> -// 0x20000 is only for socket 0
>>> -#define PLATFORM_GET_MPID_TA(ClusterId, CoreId)   (0x10000 | ((ClusterId) << 8) | (CoreId))
>>> -#define PLATFORM_GET_MPID_TB(ClusterId, CoreId)   (0x30000 | ((ClusterId) << 8) | (CoreId))
>>> -#define PLATFORM_GET_MPID_TA_2(ClusterId, CoreId)   (0x50000 | ((ClusterId) << 8) | (CoreId))
>>> -#define PLATFORM_GET_MPID_TB_2(ClusterId, CoreId)   (0x70000 | ((ClusterId) << 8) | (CoreId))
>>> -
>>> -//
>>> -// Multiple APIC Description Table
>>> -//
>>> -#pragma pack (1)
>>> -
>>> -typedef struct {
>>> -  EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER   Header;
>>> -  EFI_ACPI_6_1_GIC_STRUCTURE                            GicInterfaces[64];
>>> -  EFI_ACPI_6_1_GIC_DISTRIBUTOR_STRUCTURE                GicDistributor;
>>> -  EFI_ACPI_6_1_GIC_ITS_STRUCTURE                      GicITS[8];
>>> -} EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE;
>>> -
>>> -#pragma pack ()
>>>      EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE Madt = {
>>>      {
>>> diff --git a/Silicon/Hisilicon/Hi1616/Pptt/Pptt.c b/Silicon/Hisilicon/Hi1616/Pptt/Pptt.c
>>> new file mode 100644
>>> index 0000000..eac4736
>>> --- /dev/null
>>> +++ b/Silicon/Hisilicon/Hi1616/Pptt/Pptt.c
>>> @@ -0,0 +1,447 @@
>>> +/** @file
>>> +*
>>> +*  Copyright (c) 2017, Hisilicon Limited. All rights reserved.
>>> +*  Copyright (c) 2017, Linaro Limited. All rights reserved.
>>> +*
>>> +*  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.
>>> +*
>>> +*  Based on the files under ArmPlatformPkg/ArmJunoPkg/AcpiTables/
>>> +*
>>> +**/
>>> +
>>> +#include "Pptt.h"
>>> +
>>> +EFI_ACPI_TABLE_PROTOCOL       *mAcpiTableProtocol = NULL;
>>> +EFI_ACPI_SDT_PROTOCOL         *mAcpiSdtProtocol   = NULL;
>>> +
>>> +EFI_ACPI_DESCRIPTION_HEADER mPpttHeader =
>>> +  ARM_ACPI_HEADER (
>>> +    EFI_ACPI_6_2_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_SIGNATURE,
>>> +    EFI_ACPI_DESCRIPTION_HEADER,
>>> +    EFI_ACPI_6_2_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_REVISION
>>> +  );
>>> +
>>> +EFI_ACPI_6_2_PPTT_TYPE2 mPpttSocketType2[PPTT_SOCKET_COMPONENT_NO] =
>>> +{
>>> +  {2, sizeof(EFI_ACPI_6_2_PPTT_TYPE2), 0, 0, 0, 0, 0, 0, 0}
>>> +};
>>> +
>>> +EFI_ACPI_6_2_PPTT_TYPE1 mPpttCacheType1[PPTT_CACHE_NO] =
>>> +{
>>> +  {1, sizeof(EFI_ACPI_6_2_PPTT_TYPE1), 0, 0, 0, 0, 0, 0, 0, 0},                      //L1I 48K 0xC000    CacheAssociativity8Way
>>> +  {1, sizeof(EFI_ACPI_6_2_PPTT_TYPE1), 0, 0, 0, 0, 0, 0, 0, 0},                      //L1D 32k 0x8000    CacheAssociativity8Way
>>> +  {1, sizeof(EFI_ACPI_6_2_PPTT_TYPE1), 0, 0, 0, 0, 0, 0, 0, 0},                      //L2  1M  0x100000  CacheAssociativity8Way
>>> +  {1, sizeof(EFI_ACPI_6_2_PPTT_TYPE1), 0, 0, 0, 0x1000000, 0x2000, 0x10, 0x0A, 0x80} //L3  16M 0x1000000 CacheAssociativity16Way Linesize-128byte
>>> +};
>>> +
>>> +EFI_STATUS
>>> +InitCacheInfo(
>>> +  )
>>> +{
>>> +  UINT8                                   Index;
>>> +  PPTT_TYPE1_ATTRIBUTES                   Type1Attributes;
>>> +  CSSELR_DATA                             CsselrData;
>>> +  CCSIDR_DATA                             CcsidrData;
>>> +
>>> +  for (Index = 0; Index < PPTT_CACHE_NO - 1; Index++) {
>>> +    CsselrData.Data = 0;
>>> +    CcsidrData.Data = 0;
>>> +    Type1Attributes.Data = 0;
>>> +
>>> +    if (Index == 0) { //L1I
>>> +      CsselrData.Bits.InD = 1;
>>> +      CsselrData.Bits.Level = 0;
>>> +      Type1Attributes.Bits.CacheType  = 1;
>>> +    } else if (Index == 1) {
>>> +      Type1Attributes.Bits.CacheType  = 0;
>>> +      CsselrData.Bits.Level = Index -1;
>>> +    } else {
>>> +      Type1Attributes.Bits.CacheType  = 2;
>>> +      CsselrData.Bits.Level = Index -1;
>>> +    }
>>> +
>>> +    CcsidrData.Data = ReadCCSIDR (CsselrData.Data);
>>> +
>>> +    if (CcsidrData.Bits.Wa == 1) {
>>> +      Type1Attributes.Bits.AllocateType  = 1;
>>> +      if (CcsidrData.Bits.Ra == 1) {
>>> +        Type1Attributes.Bits.AllocateType++;
>>> +      }
>>> +    }
>>> +
>>> +    if (CcsidrData.Bits.Wt == 1) {
>>> +      Type1Attributes.Bits.WritePolicy  = 1;
>>> +    }
>>> +    DEBUG ((DEBUG_INFO, "[Acpi PPTT] Level = %x!CcsidrData = %x!\n",CsselrData.Bits.Level, CcsidrData.Data));
>>> +
>>> +    mPpttCacheType1[Index].NumberOfSets = (UINT16)CcsidrData.Bits.NumSets + 1;
>>> +    mPpttCacheType1[Index].Associativity = (UINT16)CcsidrData.Bits.Associativity + 1;
>>> +    mPpttCacheType1[Index].LineSize = (UINT16)( 1 << (CcsidrData.Bits.LineSize + 4));
>>> +    mPpttCacheType1[Index].Size = mPpttCacheType1[Index].LineSize *      \
>>> +                                  mPpttCacheType1[Index].Associativity * \
>>> +                                  mPpttCacheType1[Index].NumberOfSets;
>>> +    mPpttCacheType1[Index].Attributes = Type1Attributes.Data;
>>> +    mPpttCacheType1[Index].Flags = PPTT_TYPE1_SIZE_VALID | PPTT_TYPE1_NUMBER_OF_SETS_VALID | PPTT_TYPE1_ASSOCIATIVITY_VALID |       \
>>> +                                   PPTT_TYPE1_ALLOCATION_TYPE_VALID | PPTT_TYPE1_CACHE_TYPE_VALID | PPTT_TYPE1_WRITE_POLICY_VALID | \
>>> +                                   PPTT_TYPE1_LINE_SIZE_VALID;
>>> +
>>> +  }
>>> +
>>> +  // L3
>>> +  mPpttCacheType1[3].Flags = PPTT_TYPE1_SIZE_VALID | PPTT_TYPE1_NUMBER_OF_SETS_VALID | PPTT_TYPE1_ASSOCIATIVITY_VALID |       \
>>> +                             PPTT_TYPE1_ALLOCATION_TYPE_VALID | PPTT_TYPE1_CACHE_TYPE_VALID | PPTT_TYPE1_WRITE_POLICY_VALID | \
>>> +                             PPTT_TYPE1_LINE_SIZE_VALID;
>>> +
>>> +  return EFI_SUCCESS;
>>> +}
>>> +
>>> +EFI_STATUS
>>> +AddCoreTable(
>>> +  IN VOID     *PpttTable,
>>> +  IN OUT VOID *PpttTableLengthRemain,
>>> +  IN UINT32   Flags,
>>> +  IN UINT32   Parent,
>>> +  IN UINT32   ResourceNo,
>>> +  IN UINT32   ProcessorId
>>> +  )
>>> +{
>>> +  EFI_ACPI_6_2_PPTT_TYPE0 *PpttType0;
>>> +  EFI_ACPI_6_2_PPTT_TYPE1 *PpttType1;
>>> +  UINT32                  *PrivateResource;
>>> +  UINT8                   Index;
>>> +
>>> +  if (*(UINT32 *)PpttTableLengthRemain < sizeof(EFI_ACPI_6_2_PPTT_TYPE0) + ResourceNo * 4) {
>>> +    return EFI_OUT_OF_RESOURCES;
>>> +  }
>>> +  PpttType0 = (EFI_ACPI_6_2_PPTT_TYPE0 *)(PpttTable + ((EFI_ACPI_DESCRIPTION_HEADER *)PpttTable)->Length);
>>> +  PpttType0->Type = 0;
>>> +  PpttType0->Flags = Flags;
>>> +  PpttType0->Parent= Parent;
>>> +  PpttType0->AcpiProcessorId = ProcessorId;
>>> +  PpttType0->PrivateResourceNo = ResourceNo;
>>> +  PpttType0->Length = sizeof(EFI_ACPI_6_2_PPTT_TYPE0) + ResourceNo * 4;
>>> +
>>> +  *(UINT32 *)PpttTableLengthRemain  -= (UINTN)PpttType0->Length;
>>> +  ((EFI_ACPI_DESCRIPTION_HEADER *)PpttTable)->Length += PpttType0->Length;
>>> +  PrivateResource = (UINT32 *)((UINT8 *)PpttType0 + sizeof(EFI_ACPI_6_2_PPTT_TYPE0));
>>> +
>>> +  // Add cache type structure
>>> +  for (Index = 0; Index < ResourceNo; Index++, PrivateResource++) {
>>> +    if (*(UINT32 *)PpttTableLengthRemain < sizeof(EFI_ACPI_6_2_PPTT_TYPE1)) {
>>> +      return EFI_OUT_OF_RESOURCES;
>>> +    }
>>> +    *PrivateResource = ((EFI_ACPI_DESCRIPTION_HEADER *)PpttTable)->Length;
>>> +    PpttType1 = (EFI_ACPI_6_2_PPTT_TYPE1 *)(PpttTable + ((EFI_ACPI_DESCRIPTION_HEADER *)PpttTable)->Length);
>>> +    gBS->CopyMem (PpttType1, &mPpttCacheType1[Index], sizeof(EFI_ACPI_6_2_PPTT_TYPE1));
>>> +    *(UINT32 *)PpttTableLengthRemain -= PpttType1->Length;
>>> +    ((EFI_ACPI_DESCRIPTION_HEADER *)PpttTable)->Length += PpttType1->Length;
>>> +  }
>>> +
>>> +  return EFI_SUCCESS;
>>> +}
>>> +
>>> +EFI_STATUS
>>> +AddClusterTable (
>>> +  IN VOID     *PpttTable,
>>> +  IN OUT VOID *PpttTableLengthRemain,
>>> +  IN UINT32   Flags,
>>> +  IN UINT32   Parent,
>>> +  IN UINT32   ResourceNo
>>> +  )
>>> +{
>>> +  EFI_ACPI_6_2_PPTT_TYPE0 *PpttType0;
>>> +  EFI_ACPI_6_2_PPTT_TYPE1 *PpttType1;
>>> +  UINT32                  *PrivateResource;
>>> +
>>> +  if ((*(UINT32 *)PpttTableLengthRemain) < (sizeof(EFI_ACPI_6_2_PPTT_TYPE0) + ResourceNo * 4)) {
>>> +    return EFI_OUT_OF_RESOURCES;
>>> +  }
>>> +  PpttType0 = (EFI_ACPI_6_2_PPTT_TYPE0 *)(PpttTable + ((EFI_ACPI_DESCRIPTION_HEADER *)PpttTable)->Length);
>>> +  PpttType0->Type = 0;
>>> +  PpttType0->Flags = Flags;
>>> +  PpttType0->Parent= Parent;
>>> +  PpttType0->PrivateResourceNo = ResourceNo;
>>> +  PpttType0->Length = sizeof(EFI_ACPI_6_2_PPTT_TYPE0) + ResourceNo * 4;
>>> +
>>> +  *(UINT32 *)PpttTableLengthRemain -= PpttType0->Length;
>>> +  ((EFI_ACPI_DESCRIPTION_HEADER *)PpttTable)->Length += PpttType0->Length;
>>> +  PrivateResource = (UINT32 *)((UINT8 *)PpttType0 + sizeof(EFI_ACPI_6_2_PPTT_TYPE0));
>>> +
>>> +  // Add cache type structure
>>> +  if (*(UINT32 *)PpttTableLengthRemain < sizeof(EFI_ACPI_6_2_PPTT_TYPE1)) {
>>> +    return EFI_OUT_OF_RESOURCES;
>>> +  }
>>> +  *PrivateResource = ((EFI_ACPI_DESCRIPTION_HEADER *)PpttTable)->Length;
>>> +  PpttType1 = (EFI_ACPI_6_2_PPTT_TYPE1 *)(PpttTable + ((EFI_ACPI_DESCRIPTION_HEADER *)PpttTable)->Length);
>>> +  gBS->CopyMem (PpttType1, &mPpttCacheType1[2], sizeof(EFI_ACPI_6_2_PPTT_TYPE1));
>>> +  *(UINT32 *)PpttTableLengthRemain -= PpttType1->Length;
>>> +  ((EFI_ACPI_DESCRIPTION_HEADER *)PpttTable)->Length += PpttType1->Length;
>>> +
>>> +  return EFI_SUCCESS;
>>> +}
>>> +
>>> +EFI_STATUS
>>> +AddScclTable(
>>> +  IN VOID     *PpttTable,
>>> +  IN OUT VOID *PpttTableLengthRemain,
>>> +  IN UINT32   Flags,
>>> +  IN UINT32   Parent,
>>> +  IN UINT32   ResourceNo
>>> +  )
>>> +{
>>> +  EFI_ACPI_6_2_PPTT_TYPE0 *PpttType0;
>>> +  EFI_ACPI_6_2_PPTT_TYPE1 *PpttType1;
>>> +  UINT32                  *PrivateResource;
>>> +
>>> +  if (*(UINT32 *)PpttTableLengthRemain < sizeof(EFI_ACPI_6_2_PPTT_TYPE0) + ResourceNo * 4) {
>>> +    return EFI_OUT_OF_RESOURCES;
>>> +  }
>>> +  PpttType0 = (EFI_ACPI_6_2_PPTT_TYPE0 *)(PpttTable + ((EFI_ACPI_DESCRIPTION_HEADER *)PpttTable)->Length);
>>> +  PpttType0->Type = 0;
>>> +  PpttType0->Flags = Flags;
>>> +  PpttType0->Parent= Parent;
>>> +  PpttType0->PrivateResourceNo = ResourceNo;
>>> +  PpttType0->Length = sizeof(EFI_ACPI_6_2_PPTT_TYPE0) + ResourceNo * 4;
>>> +
>>> +  *(UINT32 *)PpttTableLengthRemain -= PpttType0->Length;
>>> +  ((EFI_ACPI_DESCRIPTION_HEADER *)PpttTable)->Length += PpttType0->Length;
>>> +  PrivateResource = (UINT32 *)((UINT8 *)PpttType0 + sizeof(EFI_ACPI_6_2_PPTT_TYPE0));
>>> +
>>> +  // Add cache type structure
>>> +  if (*(UINT32 *)PpttTableLengthRemain < sizeof(EFI_ACPI_6_2_PPTT_TYPE1)) {
>>> +    return EFI_OUT_OF_RESOURCES;
>>> +  }
>>> +  *PrivateResource = ((EFI_ACPI_DESCRIPTION_HEADER *)PpttTable)->Length;
>>> +  PpttType1 = (EFI_ACPI_6_2_PPTT_TYPE1 *)(PpttTable + ((EFI_ACPI_DESCRIPTION_HEADER *)PpttTable)->Length);
>>> +  gBS->CopyMem (PpttType1, &mPpttCacheType1[3], sizeof(EFI_ACPI_6_2_PPTT_TYPE1));
>>> +  *(UINT32 *)PpttTableLengthRemain -= PpttType1->Length;
>>> +  ((EFI_ACPI_DESCRIPTION_HEADER *)PpttTable)->Length += PpttType1->Length;
>>> +
>>> +  return EFI_SUCCESS;
>>> +}
>>> +
>>> +EFI_STATUS
>>> +AddSocketTable(
>>> +  IN VOID     *PpttTable,
>>> +  IN OUT VOID *PpttTableLengthRemain,
>>> +  IN UINT32   Flags,
>>> +  IN UINT32   Parent,
>>> +  IN UINT32   ResourceNo
>>> +  )
>>> +{
>>> +  EFI_ACPI_6_2_PPTT_TYPE0 *PpttType0;
>>> +  EFI_ACPI_6_2_PPTT_TYPE2 *PpttType2;
>>> +  UINT32         *PrivateResource;
>>> +  UINT8           Index;
>>> +
>>> +  if (*(UINT32 *)PpttTableLengthRemain < sizeof(EFI_ACPI_6_2_PPTT_TYPE0)) {
>>> +    return EFI_OUT_OF_RESOURCES;
>>> +  }
>>> +  PpttType0 = (EFI_ACPI_6_2_PPTT_TYPE0 *)(PpttTable + ((EFI_ACPI_DESCRIPTION_HEADER *)PpttTable)->Length);
>>> +  PpttType0->Type = 0;
>>> +  PpttType0->Flags = Flags;
>>> +  PpttType0->Parent= Parent;
>>> +  PpttType0->PrivateResourceNo = ResourceNo;
>>> +  PpttType0->Length = sizeof(EFI_ACPI_6_2_PPTT_TYPE0) + ResourceNo * 4;
>>> +  ((EFI_ACPI_DESCRIPTION_HEADER *)PpttTable)->Length += PpttType0->Length;
>>> +
>>> +  *(UINT32 *)PpttTableLengthRemain -= PpttType0->Length;
>>> +  if (*(UINT32 *)PpttTableLengthRemain < ResourceNo * 4) {
>>> +    return EFI_OUT_OF_RESOURCES;
>>> +  }
>>> +  PrivateResource = (UINT32 *)((UINT8 *)PpttType0 + sizeof(EFI_ACPI_6_2_PPTT_TYPE0));
>>> +  DEBUG ((DEBUG_INFO, "[Acpi PPTT]  sizeof(EFI_ACPI_6_2_PPTT_TYPE2) = %x!\n", sizeof(EFI_ACPI_6_2_PPTT_TYPE2)));
>>> +
>>> +  for (Index = 0; Index < ResourceNo; Index++, PrivateResource++) {
>>> +    if (*(UINT32 *)PpttTableLengthRemain < sizeof(EFI_ACPI_6_2_PPTT_TYPE2)) {
>>> +      return EFI_OUT_OF_RESOURCES;
>>> +    }
>>> +    *PrivateResource = ((EFI_ACPI_DESCRIPTION_HEADER *)PpttTable)->Length;
>>> +    PpttType2 = (EFI_ACPI_6_2_PPTT_TYPE2 *)(PpttTable + ((EFI_ACPI_DESCRIPTION_HEADER *)PpttTable)->Length);
>>> +    gBS->CopyMem (PpttType2, &mPpttSocketType2[Index], sizeof(EFI_ACPI_6_2_PPTT_TYPE2));
>>> +    *(UINT32 *)PpttTableLengthRemain -= PpttType2->Length;
>>> +    ((EFI_ACPI_DESCRIPTION_HEADER *)PpttTable)->Length += PpttType2->Length;
>>> +  }
>>> +
>>> +  return EFI_SUCCESS;
>>> +}
>>> +
>>> +VOID
>>> +GetApic(
>>> +EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE  *ApicTable,
>>> +VOID                                          *PpttTable,
>>> +IN UINT32                                     PpttTableLengthRemain,
>>> +IN UINT32                                     Index1
>>> +)
>>> +{
>>> +  UINT32 IndexSocket, IndexSccl, IndexCulster, IndexCore;
>>> +  UINT32 SocketOffset, ScclOffset, ClusterOffset;
>>> +  UINT32 Parent = 0;
>>> +  UINT32 Flags = 0;
>>> +  UINT32 ResourceNo = 0;
>>> +  //Get APIC data
>>> +  for (IndexSocket = 0; IndexSocket < PPTT_SOCKET_NO; IndexSocket++) {
>>> +    SocketOffset = 0;
>>> +    for (IndexSccl = 0; IndexSccl < PPTT_DIE_NO; IndexSccl++) {
>>> +      ScclOffset = 0;
>>> +      for (IndexCulster = 0; IndexCulster < PPTT_CULSTER_NO; IndexCulster++) {
>>> +        ClusterOffset = 0;
>>> +        for (IndexCore = 0; IndexCore < PPTT_CORE_NO; IndexCore++) {
>>> +
>>> +          DEBUG ((DEBUG_INFO, "[Acpi PPTT] IndexSocket:%x, IndexSccl:%x, IndexCulster:%x, IndexCore:%x!\n",IndexSocket,IndexSccl ,IndexCulster,IndexCore));
>>> +
>>> +          if (ApicTable->GicInterfaces[Index1].AcpiProcessorUid != Index1) {
>>> +            //This processor is unusable
>>> +            DEBUG ((DEBUG_ERROR, "[Acpi PPTT] Please check MADT table for UID!\n"));
>>> +            return;
>>> +          }
>>> +          if ((ApicTable->GicInterfaces[Index1].Flags & BIT0) == 0 ) {
>>> +            //This processor is unusable
>>> +            Index1++;
>>> +            continue;
>>> +          }
>>> +
>>> +          if (SocketOffset == 0) {
>>> +          //Add socket0 for type0 table
>>> +            ResourceNo = PPTT_SOCKET_COMPONENT_NO;
>>> +            SocketOffset = ((EFI_ACPI_DESCRIPTION_HEADER *)PpttTable)->Length;
>>> +            Parent = 0;
>>> +            Flags = PPTT_TYPE0_SOCKET_FLAG;
>>> +            AddSocketTable (PpttTable, &PpttTableLengthRemain, Flags, Parent, ResourceNo);
>>> +          }
>>> +          if (ScclOffset == 0) {
>>> +          //Add socket0die0 for type0 table
>>> +            ResourceNo = 1;
>>> +            ScclOffset =  ((EFI_ACPI_DESCRIPTION_HEADER *)PpttTable)->Length ;
>>> +            Parent = SocketOffset;
>>> +            Flags = PPTT_TYPE0_DIE_FLAG;
>>> +            AddScclTable (PpttTable, &PpttTableLengthRemain, Flags, Parent, ResourceNo);
>>> +          }
>>> +          if (ClusterOffset == 0) {
>>> +          //Add socket0die0ClusterId for type0 table
>>> +            ResourceNo = 1;
>>> +            ClusterOffset =  ((EFI_ACPI_DESCRIPTION_HEADER *)PpttTable)->Length ;
>>> +            Parent = ScclOffset;
>>> +            Flags = PPTT_TYPE0_CLUSTER_FLAG;
>>> +            AddClusterTable (PpttTable, &PpttTableLengthRemain, Flags, Parent, ResourceNo);
>>> +          }
>>> +
>>> +          //Add socket0die0ClusterIdCoreId for type0 table
>>> +          ResourceNo = 2;
>>> +          Parent = ClusterOffset;
>>> +          Flags = PPTT_TYPE0_CORE_FLAG;
>>> +          AddCoreTable (PpttTable, &PpttTableLengthRemain, Flags, Parent, ResourceNo, Index1);
>>> +
>>> +          Index1++;
>>> +        }
>>> +      }
>>> +    }
>>> +  }
>>> +  return ;
>>> +}
>>> +
>>> +VOID
>>> +PpttSetAcpiTable(
>>> +  IN EFI_EVENT    Event,
>>> +  IN VOID         *Context
>>> +  )
>>> +{
>>> +  UINTN                                         AcpiTableHandle;
>>> +  EFI_STATUS                                    Status;
>>> +  UINT8                                         Checksum;
>>> +  EFI_ACPI_SDT_HEADER                           *Table;
>>> +  EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE  *ApicTable;
>>> +  EFI_ACPI_TABLE_VERSION                        TableVersion;
>>> +  VOID                                          *PpttTable;
>>> +  UINTN                                         TableKey;
>>> +  UINT32                                        Index0, Index1;
>>> +  UINT32                                        PpttTableLengthRemain = 0;
>>> +
>>> +  gBS->CloseEvent (Event);
>>> +
>>> +  InitCacheInfo ();
>>> +
>>> +  PpttTable = AllocateZeroPool (PPTT_TABLE_MAX_LEN);
>>> +  gBS->CopyMem (PpttTable, &mPpttHeader, sizeof(EFI_ACPI_DESCRIPTION_HEADER));
>>> +  PpttTableLengthRemain = PPTT_TABLE_MAX_LEN - sizeof(EFI_ACPI_DESCRIPTION_HEADER);
>>> +
>>> +  for (Index0 = 0; Index0 < EFI_ACPI_MAX_NUM_TABLES; Index0++) {
>>> +    Status = mAcpiSdtProtocol->GetAcpiTable (Index0, &Table, &TableVersion, &TableKey);
>>> +    if (EFI_ERROR (Status)) {
>>> +      break;
>>> +    }
>>> +    //Find APIC table
>>> +    if (Table->Signature != EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE) {
>>> +      continue;
>>> +    }
>>> +
>>> +    ApicTable = (EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE *)Table;
>>> +    Index1 = 0;
>>> +
>>> +    GetApic (ApicTable, PpttTable, PpttTableLengthRemain, Index1);
>>> +    break;
>>> +  }
>>> +
>>> +  if (EFI_ERROR (Status)) {
>>> +    DEBUG ((DEBUG_ERROR,"%a:%d Status=%r\n",__FILE__,__LINE__,Status));
>>> +  }
>>> +
>>> +  Checksum = CalculateCheckSum8 ((UINT8 *)(PpttTable), ((EFI_ACPI_DESCRIPTION_HEADER *)PpttTable)->Length);
>>> +  ((EFI_ACPI_DESCRIPTION_HEADER *)PpttTable)->Checksum= Checksum;
>>> +
>>> +  AcpiTableHandle = 0;
>>> +  Status = mAcpiTableProtocol->InstallAcpiTable (mAcpiTableProtocol, PpttTable, ((EFI_ACPI_DESCRIPTION_HEADER *)PpttTable)->Length, &AcpiTableHandle);
>>> +
>>> +  FreePool (PpttTable);
>>> +  return ;
>>> +}
>>> +
>>> +EFI_STATUS
>>> +InitPpttTable(
>>> +  )
>>> +{
>>> +  EFI_STATUS                Status;
>>> +  EFI_EVENT                 ReadyToBootEvent;
>>> +
>>> +  Status = EfiCreateEventReadyToBootEx (
>>> +            TPL_NOTIFY,
>>> +            PpttSetAcpiTable,
>>> +            NULL,
>>> +            &ReadyToBootEvent
>>> +            );
>>> +  ASSERT_EFI_ERROR (Status);
>>> +
>>> +  return Status;
>>> +}
>>> +
>>> +EFI_STATUS
>>> +EFIAPI
>>> +PpttEntryPoint(
>>> +  IN EFI_HANDLE         ImageHandle,
>>> +  IN EFI_SYSTEM_TABLE   *SystemTable
>>> +  )
>>> +{
>>> +  EFI_STATUS              Status;
>>> +
>>> +  Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL,  (VOID**)&mAcpiTableProtocol);
>>> +  if (EFI_ERROR (Status)) {
>>> +    return EFI_ABORTED;
>>> +  }
>>> +
>>> +  Status = gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (VOID**) &mAcpiSdtProtocol);
>>> +  if (EFI_ERROR (Status)) {
>>> +    return EFI_ABORTED;
>>> +  }
>>> +
>>> +  InitPpttTable ();
>>> +
>>> +  DEBUG ((DEBUG_INFO, "Acpi Pptt init done.\n"));
>>> +
>>> +  return EFI_SUCCESS;
>>> +}
>>> diff --git a/Silicon/Hisilicon/Hi1616/Pptt/Pptt.h b/Silicon/Hisilicon/Hi1616/Pptt/Pptt.h
>>> new file mode 100644
>>> index 0000000..5dc635f
>>> --- /dev/null
>>> +++ b/Silicon/Hisilicon/Hi1616/Pptt/Pptt.h
>>> @@ -0,0 +1,142 @@
>>> +/** @file
>>> +*
>>> +*  Copyright (c) 2017, Hisilicon Limited. All rights reserved.
>>> +*  Copyright (c) 2017, Linaro Limited. All rights reserved.
>>> +*
>>> +*  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.
>>> +*
>>> +*  Based on the files under ArmPlatformPkg/ArmJunoPkg/AcpiTables/
>>> +*
>>> +**/
>>> +
>>> +#ifndef _PPTT_H_
>>> +#define _PPTT_H_
>>> +
>>> +#include <IndustryStandard/Acpi.h>
>>> +#include <Library/ArmLib/ArmLibPrivate.h>
>>> +#include <Library/BaseMemoryLib.h>
>>> +#include <Library/DebugLib.h>
>>> +#include <Library/MemoryAllocationLib.h>
>>> +#include <Library/UefiBootServicesTableLib.h>
>>> +#include <Library/UefiLib.h>
>>> +#include <Protocol/AcpiSystemDescriptionTable.h>
>>> +#include <Protocol/AcpiTable.h>
>>> +#include "../D05AcpiTables/Hi1616Platform.h"
>>> +
>>> +///
>>> +/// "PPTT"  Processor Properties Topology Table
>>> +///
>>> +#define EFI_ACPI_6_2_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_SIGNATURE  SIGNATURE_32('P', 'P', 'T', 'T')
>>> +#define EFI_ACPI_6_2_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_REVISION   0x01
>>> +#define EFI_ACPI_MAX_NUM_TABLES                                     20
>>> +
>>> +#define PPTT_TABLE_MAX_LEN         0x6000
>>> +#define PPTT_SOCKET_NO             0x2
>>> +#define PPTT_DIE_NO                0x2
>>> +#define PPTT_CULSTER_NO            0x4
>>> +#define PPTT_CORE_NO               0x4
>>> +#define PPTT_SOCKET_COMPONENT_NO   0x1
>>> +#define PPTT_CACHE_NO              0x4
>>> +
>>> +#define PPTT_TYPE0_PHYSICAL_PKG        BIT0
>>> +#define PPTT_TYPE0_PROCESSORID_VALID   BIT1
>>> +#define PPTT_TYPE0_SOCKET_FLAG         PPTT_TYPE0_PHYSICAL_PKG
>>> +#define PPTT_TYPE0_DIE_FLAG            PPTT_TYPE0_PHYSICAL_PKG
>>
>> First most of these definitions should be in the common acpi 6.2 header.. I actually have a patch for that sitting around (along with the juno table) but you have basically the same thing here..
>>
>> For the parts not defined by ACPI I would leave them in this file (SOCKET & DIE flag).
>>
>> That said, I think DIE_FLAG here should be 0. You will mess up the topology view if you put that on the DIE. Further, while the spec doesn't ban marking every node in the tree with that flag, I'm trying to clarify the spec so it says that the flag can only be set once between a given processor node and the root.
>>
>> I understand why you probably did this, but it should be under user control (via a HII option). The SRAT domains need to start basically where the die flag is set at the moment. Hopefully in the future we will have an actual flag (that to is in the works) to put here but until that is the case it should default to 0 (unless you allow the user to shift the physical socket from the actual socket to the die). Either way that will be HiSi specific behavior and not in the general header.
>>
>>
>> Thanks,
>>
>>
> 
> I found a difference in Acpi62.h and ACPI 6.2 specification:
> Acpi62.h:
> ///
> /// Processor hierarchy node structure
> ///
> typedef struct {
>    UINT32                                        Type;      // UINT32 ?
>    UINT8                                         Length;
>    ...
> } EFI_ACPI_6_2_PPTT_STRUCTURE_PROCESSOR;
> 
> ACPI 6.2 specification:
> Table 5-150 Processor Hierarchy Node Structure
> Type is UINT8
> 
> Which one is right?

That is easy, the specification..

Thanks,


  reply	other threads:[~2018-01-25 15:22 UTC|newest]

Thread overview: 72+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-01-18 15:01 [PATCH edk2-platforms v1 00/14] Improve D0x platforms and bug fix Ming Huang
2018-01-18 15:01 ` [PATCH edk2-platforms v1 01/14] Hisilicon/D05: Add PPTT support Ming Huang
2018-01-20 10:16   ` Ard Biesheuvel
2018-01-22  9:16     ` Huangming (Mark)
2018-01-23  6:00     ` Huangming (Mark)
2018-01-22 13:53   ` Leif Lindholm
2018-01-22 14:15     ` Leif Lindholm
2018-01-24 13:49     ` graeme.gregory
2018-01-23 21:29   ` Jeremy Linton
2018-01-24  7:57     ` Huangming (Mark)
2018-01-25  5:56     ` Huangming (Mark)
2018-01-25 15:27       ` Jeremy Linton [this message]
2018-01-18 15:01 ` [PATCH edk2-platforms v1 02/14] Hisilicon D03/D05:Switch to Generic BDS driver Ming Huang
2018-01-20 10:27   ` Ard Biesheuvel
2018-01-22 18:38   ` Leif Lindholm
2018-01-23  6:03     ` Huangming (Mark)
2018-01-18 15:01 ` [PATCH edk2-platforms v1 03/14] Hisilicon D03/D05: Optimize the feature of BMC set boot option Ming Huang
2018-01-20 10:41   ` Ard Biesheuvel
2018-01-23  8:28     ` Huangming (Mark)
2018-01-23 10:28   ` Leif Lindholm
2018-01-23 10:51     ` Huangming (Mark)
2018-01-18 15:01 ` [PATCH edk2-platforms v1 04/14] Hisilicon D03/D05: Add capsule upgrade support Ming Huang
2018-01-20 10:50   ` Ard Biesheuvel
2018-01-23  8:53     ` Huangming (Mark)
2018-01-23  9:33       ` Ard Biesheuvel
2018-01-24 11:10     ` Huangming (Mark)
2018-01-24 11:21       ` Ard Biesheuvel
2018-01-25  0:53         ` Huangming (Mark)
2018-01-23 14:06   ` Leif Lindholm
2018-01-18 15:01 ` [PATCH edk2-platforms v1 05/14] Hisilicon D03/D05: Open SasPlatform source code Ming Huang
2018-01-20 10:57   ` Ard Biesheuvel
2018-01-23 11:01     ` Huangming (Mark)
2018-01-23 14:04   ` Leif Lindholm
2018-01-18 15:01 ` [PATCH edk2-platforms v1 06/14] Hisilicon D03/D05: Open SnpPlatform " Ming Huang
2018-01-20 11:00   ` Ard Biesheuvel
2018-01-23 11:01     ` Huangming (Mark)
2018-01-23 14:07   ` Leif Lindholm
2018-01-24 12:31     ` Huangming (Mark)
2018-01-24 13:47       ` Leif Lindholm
2018-01-18 15:01 ` [PATCH edk2-platforms v1 07/14] Hisilicon/Smbios: modify type 4 Ming Huang
2018-01-20 11:01   ` Ard Biesheuvel
2018-01-23 14:15   ` Leif Lindholm
2018-01-18 15:01 ` [PATCH edk2-platforms v1 08/14] Hisilicon/PCIe: Disable PCIe ASPM Ming Huang
2018-01-20 11:04   ` Ard Biesheuvel
2018-01-18 15:01 ` [PATCH edk2-platforms v1 09/14] Hisilicon/D05: Replace SP805Watchdog by WatchdogTimer driver Ming Huang
2018-01-20 11:05   ` Ard Biesheuvel
2018-01-23 14:21   ` Leif Lindholm
2018-01-18 15:01 ` [PATCH edk2-platforms v1 10/14] Hisilicon/D03: " Ming Huang
2018-01-20 11:05   ` Ard Biesheuvel
2018-01-23 14:21   ` Leif Lindholm
2018-01-18 15:01 ` [PATCH edk2-platforms v1 11/14] Hisilicon/D05/ACPI: Add ITS PXM Ming Huang
2018-01-20 11:06   ` Ard Biesheuvel
2018-01-18 15:01 ` [PATCH edk2-platforms v1 12/14] Hisilicon/D05/ACPI: Add Pcie, HNS and SAS PXM Ming Huang
2018-01-20 11:08   ` Ard Biesheuvel
2018-01-18 15:01 ` [PATCH edk2-platforms v1 13/14] Hisilicon/Library: Add OsBootLib Ming Huang
2018-01-20 11:11   ` Ard Biesheuvel
2018-01-23 10:23   ` Leif Lindholm
2018-01-27  1:47     ` Huangming (Mark)
2018-01-27 10:37       ` Ard Biesheuvel
2018-01-29  8:55         ` Huangming (Mark)
2018-01-29 10:19           ` Ard Biesheuvel
2018-01-29 11:16       ` Leif Lindholm
2018-02-07 21:16         ` Peter Jones
2018-02-11  6:03           ` Huangming (Mark)
2018-02-26  1:12           ` Guo Heyi
2018-01-18 15:01 ` [PATCH edk2-platforms v1 14/14] Hisilicon D03/D05: Update firmware version to 18.02 Ming Huang
2018-01-20 11:11   ` Ard Biesheuvel
2018-01-23 10:18   ` Leif Lindholm
2018-01-24  1:17     ` Huangming (Mark)
2018-01-24  7:54       ` Leif Lindholm
2018-01-22 13:26 ` [PATCH edk2-platforms v1 00/14] Improve D0x platforms and bug fix Leif Lindholm
2018-01-23 14:24 ` Leif Lindholm

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=9ce45b7b-959e-1fd1-039b-437dbb982c61@arm.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