요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. SPDX-License-Identifier: GPL-2.0
===========
TPH Support
===========
:Copyright: 2024 Advanced Micro Devices, Inc.
:Authors: - Eric van Tassell <eric.vantassell@amd.com>
- Wei Huang <wei.huang2@amd.com>
Overview
========
TPH (TLP Processing Hints) is a PCIe feature that allows endpoint devices
to provide optimization hints for requests that target memory space.
These hints, in a format called Steering Tags (STs), are embedded in the
requester's TLP headers, enabling the system hardware, such as the Root
Complex, to better manage platform resources for these requests.
For example, on platforms with TPH-based direct data cache injection
support, an endpoint device can include appropriate STs in its DMA
traffic to specify which cache the data should be written to. This allows
the CPU core to have a higher probability of getting data from cache,
potentially improving performance and reducing latency in data
processing.
How to Use TPH
==============
TPH is presented as an optional extended capability in PCIe. The Linux
kernel handles TPH discovery during boot, but it is up to the device
driver to request TPH enablement if it is to be utilized. Once enabled,
the driver uses the provided API to obtain the Steering Tag for the
target memory and to program the ST into the device's ST table.
Enable TPH support in Linux
---------------------------
To support TPH, the kernel must be built with the CONFIG_PCIE_TPH option
enabled.
Manage TPH
----------
To enable TPH for a device, use the following function::
int pcie_enable_tph(struct pci_dev *pdev, int mode);
This function enables TPH support for device with a specific ST mode.
Current supported modes include:
* PCI_TPH_ST_NS_MODE - NO ST Mode
* PCI_TPH_ST_IV_MODE - Interrupt Vector Mode
* PCI_TPH_ST_DS_MODE - Device Specific Mode
`pcie_enable_tph()` checks whether the requested mode is actually
supported by the device before enabling. The device driver can figure out
which TPH mode is supported and can be properly enabled based on the
return value of `pcie_enable_tph()`.
To disable TPH, use the following function::
void pcie_disable_tph(struct pci_dev *pdev);
Manage ST
---------
Steering Tags are platform specific. PCIe spec does not specify where STs
are from. Instead PCI Firmware Specification defines an ACPI _DSM method
(see the `Revised _DSM for Cache Locality TPH Features ECN
<https://members.pcisig.com/wg/PCI-SIG/document/15470>`_) for retrieving
STs for a target memory of various properties. This method is what is
supported in this implementation.
To retrieve a Steering Tag for a target memory associated with a specific
CPU, use the following function::
int pcie_tph_get_cpu_st(struct pci_dev *pdev, enum tph_mem_type type,
unsigned int cpu_uid, u16 *tag);
The `type` argument is used to specify the memory type, either volatile
or persistent, of the target memory. The `cpu_uid` argument specifies the
CPU where the memory is associated to.
After the ST value is retrieved, the device driver can use the following
function to write the ST into the device::
int pcie_tph_set_st_entry(struct pci_dev *pdev, unsigned int index,
u16 tag);
The `index` argument is the ST table entry index the ST tag will be
written into. `pcie_tph_set_st_entry()` will figure out the proper
location of ST table, either in the MSI-X table or in the TPH Extended
Capability space, and write the Steering Tag into the ST entry pointed by
the `index` argument.
It is completely up to the driver to decide how to use these TPH
functions. For example a network device driver can use the TPH APIs above
to update the Steering Tag when interrupt affinity of a RX/TX queue has
been changed. Here is a sample code for IRQ affinity notifier:
.. code-block:: c
static void irq_affinity_notified(struct irq_affinity_notify *notify,
const cpumask_t *mask)
{
struct drv_irq *irq;
unsigned int cpu_id;
u16 tag;
irq = container_of(notify, struct drv_irq, affinity_notify);
cpumask_copy(irq->cpu_mask, mask);
/* Pick a right CPU as the target - here is just an example */
cpu_id = cpumask_first(irq->cpu_mask);
if (pcie_tph_get_cpu_st(irq->pdev, TPH_MEM_TYPE_VM, cpu_id,
&tag))
return;
if (pcie_tph_set_st_entry(irq->pdev, irq->msix_nr, tag))
return;
}
Disable TPH system-wide
-----------------------
There is a kernel command line option available to control TPH feature:
* "notph": TPH will be disabled for all endpoint devices.
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
TPH와 Steering Tag 개요
1-29이 문서는 2024년 Advanced Micro Devices, Inc. 저작물이며 저자는 Eric van Tassell과 Wei Huang입니다.
TPH(TLP Processing Hints)는 Endpoint device가 memory space를 대상으로 하는 request에 최적화 hint를 제공할 수 있게 하는 PCIe 기능입니다.
이 hint는 Steering Tag(ST) 형식으로 requester의 TLP header에 삽입됩니다. Root Complex 같은 system hardware는 이 tag를 이용해 해당 request에 필요한 platform resource를 더 적절히 관리합니다.
예를 들어 TPH 기반 direct data cache injection을 지원하는 platform에서 Endpoint는 DMA traffic에 적절한 ST를 넣어 data를 어느 cache에 쓸지 지정할 수 있습니다. 그러면 CPU core가 cache에서 data를 얻을 가능성이 높아져 processing 성능이 향상되고 latency가 줄어들 수 있습니다.
Request TLP에 포함된 Steering Tag가 memory target의 locality를 hardware에 전달합니다.
Hint 생성자와 소비자, 기대 효과를 구분합니다.
.. SPDX-License-Identifier: GPL-2.0
===========
TPH Support
===========
:Copyright: 2024 Advanced Micro Devices, Inc.
:Authors: - Eric van Tassell <eric.vantassell@amd.com>
- Wei Huang <wei.huang2@amd.com>
Overview
========
TPH (TLP Processing Hints) is a PCIe feature that allows endpoint devices
to provide optimization hints for requests that target memory space.
These hints, in a format called Steering Tags (STs), are embedded in the
requester's TLP headers, enabling the system hardware, such as the Root
Complex, to better manage platform resources for these requests.
For example, on platforms with TPH-based direct data cache injection
support, an endpoint device can include appropriate STs in its DMA
traffic to specify which cache the data should be written to. This allows
the CPU core to have a higher probability of getting data from cache,
potentially improving performance and reducing latency in data
processing.
Linux에서 TPH 사용 준비
30-44TPH는 PCIe의 선택적 extended capability로 제공됩니다. Linux kernel은 boot 중 TPH capability를 발견하지만 실제 사용을 위해 enable을 요청하는 책임은 device driver에 있습니다.
TPH가 enable되면 driver는 제공된 API로 target memory의 Steering Tag를 얻고 device의 ST table에 program합니다.
Kernel은 `CONFIG_PCIE_TPH` option을 활성화하여 build해야 TPH를 지원합니다.
Discovery는 PCI core가, 정책과 device programming은 driver가 담당합니다.
How to Use TPH
==============
TPH is presented as an optional extended capability in PCIe. The Linux
kernel handles TPH discovery during boot, but it is up to the device
driver to request TPH enablement if it is to be utilized. Once enabled,
the driver uses the provided API to obtain the Steering Tag for the
target memory and to program the ST into the device's ST table.
Enable TPH support in Linux
---------------------------
To support TPH, the kernel must be built with the CONFIG_PCIE_TPH option
enabled.
TPH enable mode와 disable
45-67`pcie_enable_tph()`는 지정한 ST mode로 device의 TPH 지원을 enable합니다.
int pcie_enable_tph(struct pci_dev *pdev, int mode);
현재 지원 mode는 No ST Mode인 `PCI_TPH_ST_NS_MODE`, Interrupt Vector Mode인 `PCI_TPH_ST_IV_MODE`, Device Specific Mode인 `PCI_TPH_ST_DS_MODE`입니다.
Driver가 device 기능과 사용 방식에 맞춰 요청할 mode입니다.
`pcie_enable_tph()`는 enable하기 전에 요청한 mode를 device가 실제로 지원하는지 확인합니다. Device driver는 함수 반환값으로 어떤 TPH mode가 지원되고 올바르게 enable됐는지 판단할 수 있습니다.
TPH를 disable하려면 `pcie_disable_tph()`를 사용합니다.
void pcie_disable_tph(struct pci_dev *pdev);
요청 mode를 capability와 대조한 뒤 성공한 mode만 활성화합니다.
Manage TPH
----------
To enable TPH for a device, use the following function::
int pcie_enable_tph(struct pci_dev *pdev, int mode);
This function enables TPH support for device with a specific ST mode.
Current supported modes include:
* PCI_TPH_ST_NS_MODE - NO ST Mode
* PCI_TPH_ST_IV_MODE - Interrupt Vector Mode
* PCI_TPH_ST_DS_MODE - Device Specific Mode
`pcie_enable_tph()` checks whether the requested mode is actually
supported by the device before enabling. The device driver can figure out
which TPH mode is supported and can be properly enabled based on the
return value of `pcie_enable_tph()`.
To disable TPH, use the following function::
void pcie_disable_tph(struct pci_dev *pdev);
CPU와 memory type에 맞는 ST 조회
68-87Steering Tag는 platform-specific이며 PCIe specification은 ST의 출처를 규정하지 않습니다.
대신 PCI Firmware Specification은 여러 속성의 target memory에 사용할 ST를 조회하는 ACPI `_DSM` method를 정의합니다. 이 구현은 `Revised _DSM for Cache Locality TPH Features ECN`에 정의된 method를 지원합니다.
특정 CPU와 연결된 target memory의 Steering Tag는 `pcie_tph_get_cpu_st()`로 조회합니다.
int pcie_tph_get_cpu_st(struct pci_dev *pdev, enum tph_mem_type type,
unsigned int cpu_uid, u16 *tag);
`type`은 target memory가 volatile인지 persistent인지 지정하는 memory type입니다. `cpu_uid`는 해당 memory와 연결된 CPU를 지정하고, 성공하면 `tag`가 Steering Tag를 받습니다.
Platform firmware에서 올바른 locality tag를 선택하는 입력과 출력입니다.
PCIe가 출처를 정하지 않으므로 firmware `_DSM`이 platform-specific tag를 제공합니다.
Manage ST
---------
Steering Tags are platform specific. PCIe spec does not specify where STs
are from. Instead PCI Firmware Specification defines an ACPI _DSM method
(see the `Revised _DSM for Cache Locality TPH Features ECN
<https://members.pcisig.com/wg/PCI-SIG/document/15470>`_) for retrieving
STs for a target memory of various properties. This method is what is
supported in this implementation.
To retrieve a Steering Tag for a target memory associated with a specific
CPU, use the following function::
int pcie_tph_get_cpu_st(struct pci_dev *pdev, enum tph_mem_type type,
unsigned int cpu_uid, u16 *tag);
The `type` argument is used to specify the memory type, either volatile
or persistent, of the target memory. The `cpu_uid` argument specifies the
CPU where the memory is associated to.
ST table 기록과 IRQ affinity 예제
88-127ST 값을 조회한 뒤 device driver는 `pcie_tph_set_st_entry()`로 device의 ST table entry에 기록합니다.
int pcie_tph_set_st_entry(struct pci_dev *pdev, unsigned int index,
u16 tag);
`index`는 tag를 기록할 ST table entry index입니다. 함수는 ST table이 MSI-X table에 있는지 TPH Extended Capability space에 있는지 판단하고 해당 `index` entry에 Steering Tag를 씁니다.
동일 API가 device capability에 맞는 실제 저장 위치를 선택합니다.
TPH 함수를 언제 어떻게 사용할지는 전적으로 driver가 결정합니다. 예를 들어 network driver는 RX/TX queue의 interrupt affinity가 바뀔 때 새 target CPU의 Steering Tag를 구해 갱신할 수 있습니다.
예제 IRQ affinity notifier는 새 mask를 `irq->cpu_mask`에 복사하고 첫 CPU를 target으로 선택합니다. `TPH_MEM_TYPE_VM`과 CPU ID로 tag를 조회한 뒤 MSI-X vector number인 `irq->msix_nr` index에 tag를 기록합니다. 두 API 중 하나라도 실패하면 즉시 반환합니다.
static void irq_affinity_notified(struct irq_affinity_notify *notify,
const cpumask_t *mask)
{
struct drv_irq *irq;
unsigned int cpu_id;
u16 tag;
irq = container_of(notify, struct drv_irq, affinity_notify);
cpumask_copy(irq->cpu_mask, mask);
/* Pick a right CPU as the target - here is just an example */
cpu_id = cpumask_first(irq->cpu_mask);
if (pcie_tph_get_cpu_st(irq->pdev, TPH_MEM_TYPE_VM, cpu_id,
&tag))
return;
if (pcie_tph_set_st_entry(irq->pdev, irq->msix_nr, tag))
return;
}
Queue를 처리할 CPU가 바뀌면 locality hint도 같은 CPU에 맞춰 바꿉니다.
After the ST value is retrieved, the device driver can use the following
function to write the ST into the device::
int pcie_tph_set_st_entry(struct pci_dev *pdev, unsigned int index,
u16 tag);
The `index` argument is the ST table entry index the ST tag will be
written into. `pcie_tph_set_st_entry()` will figure out the proper
location of ST table, either in the MSI-X table or in the TPH Extended
Capability space, and write the Steering Tag into the ST entry pointed by
the `index` argument.
It is completely up to the driver to decide how to use these TPH
functions. For example a network device driver can use the TPH APIs above
to update the Steering Tag when interrupt affinity of a RX/TX queue has
been changed. Here is a sample code for IRQ affinity notifier:
.. code-block:: c
static void irq_affinity_notified(struct irq_affinity_notify *notify,
const cpumask_t *mask)
{
struct drv_irq *irq;
unsigned int cpu_id;
u16 tag;
irq = container_of(notify, struct drv_irq, affinity_notify);
cpumask_copy(irq->cpu_mask, mask);
/* Pick a right CPU as the target - here is just an example */
cpu_id = cpumask_first(irq->cpu_mask);
if (pcie_tph_get_cpu_st(irq->pdev, TPH_MEM_TYPE_VM, cpu_id,
&tag))
return;
if (pcie_tph_set_st_entry(irq->pdev, irq->msix_nr, tag))
return;
}
System 전체 TPH 비활성화
128-132Kernel command line의 `notph` option으로 TPH 기능을 system 전체에서 제어할 수 있습니다.
`notph`를 지정하면 모든 Endpoint device에서 TPH가 disable됩니다.
개별 driver 요청보다 앞서 system-wide TPH 사용을 차단합니다.
Disable TPH system-wide
-----------------------
There is a kernel command line option available to control TPH feature:
* "notph": TPH will be disabled for all endpoint devices.
요약·해설
tph.rst:1-132TPH는 Endpoint의 memory request TLP에 Steering Tag를 넣어 Root Complex가 target CPU의 cache locality에 맞게 resource를 관리하도록 돕습니다.
Driver는 device가 지원하는 ST mode로 TPH를 enable하고 ACPI `_DSM`을 통해 memory type·CPU별 tag를 얻어 MSI-X table 또는 TPH Extended Capability의 entry에 기록합니다.
Network queue의 IRQ affinity가 바뀌면 새 CPU에 맞춰 ST도 갱신할 수 있으며, `notph` kernel option은 모든 Endpoint의 TPH를 비활성화합니다.