PCIe总线-事物层之TLP路由介绍(七)

1.概述

下图是一个PCIe总线系统示意图。此时RC发出一个TLP,经过Switch访问EP,TLP的路径为红色箭头所示。首先TLP从RC的下行OUT端口发出,Switch的上行IN端口接收到该TLP后,根据其路由信息,将其转发到Switch的下行OUT端口,随后TLP达到EP的IN端口,最后TLP到达EP设备。TLP从RC到EP的转发过程被称为TLP的路由过程。PCIe总线总共定义了三种路由方式,分别是基于地址(Address)路由、基于ID(BDF)路由和隐式(Implicit)路由。

TLP路由过程

TLP使用的路由方式和TLP的类型有关,具体如下表所示,PCIe桥就是根据这些信息转发TLP。

TLP TypeRouting Method Used
Memory Read [Lock], Memory Write, AtomicOpAddress Routing
IO Read and WriteAddress Routing
Configuration Read and WriteID Routing
Message, Message With DataAddress Routing, ID Routing, or Implicit routing
Completion, Completion With DataID Routing

2.地址路由(Address Routing)

存储器请求、原子操作、IO请求和某些消息请求使用地址路由。对于桥设备,地址路由和桥中设置的地址范围相关。对于EP设备,地址路由和BAR中保存的地址相关。根据传输方向,地址路由可以分为三种情况。第一种是RC Outbound,即RC访问其下游的桥或者EP设备,此时若访问地址在桥定义的地址范围内时,则桥会将该报文向下行口转发。第二种是RC Inbound,即EP(通常是使用DMA)访问RC,此时是下行口访问上行口,和第一种情况相反,只有访问地址不在桥定义的地址范围内时,桥才会将该报文向上行口转发。第三种是Peer-to-Peer,即EP之间相互访问,此时桥的处理方法综合第一种和第二种情况。

桥的地址范围

下图是一个PCIe总线,RC下面接了一个Switch,Switch两个下行口各接了一个EP。RC和Switch的每个Port都包含一个虚拟的PCI-toPCI(P2P)桥。该PCIe总线已枚举完成,分配的地址如下图所示。

建立地址路由环境

IO地址、非预取存储器地址和预取存储器地址路由规则都一样,下面以预取存储器地址路由为例,介绍TLP的传输过程。下图包含了一个RC、一个Swtich和2个EP,Swtich有一个上行口和两个下行口。RC中的P2P0桥地址范围为0x240000000 – 0x243FFFFFF,大小为64MB。Swtich上行口P2P1桥地址范围为0x240000000 – 0x243FFFFFF,大小为64MB。Swtich下行口P2P2桥地址范围为0x240000000 – 0x241FFFFFF,大小为32MB。Swtich下行口P2P3桥地址范围为0x242000000 – 0x243FFFFFF,大小为32MB。EP0的BAR0和BAR1表示的地址范围为0x240000000 – 0x241FFFFFF,大小为32MB。EP1的BAR0和BAR1表示的地址范围为0x242000000 – 0x243FFFFFF,大小为32MB。下面将分别介绍TLP0、TLP1和TLP2的路由过程。

RC Outbound:TLP0由RC发出,访问EP0。流程如下:

  1. Host Bridge生成TLP0,目的地址为0x240008000,然后通过Bus0发送到RC内部的P2P0。
  2. P2P0解析TLP0的目的地址为0x240008000,在其0x240000000 – 0x243FFFFFF地址范围内,则会接收这个TLP,然后将TLP0转发到Swtich的上行口。
  3. TLP0通过Swtich的上行口到达P2P1,P2P1解析TLP0的目的地址为0x240008000,在其0x240000000 – 0x243FFFFFF地址范围内,则会将TLP0转发到Bus2上。若TLP0的目的地址不在P2P1的地址范围内时,则TLP0会被作为不支持的请求(Unsupported Request)处理,如果需要完成报文,则Swtich会发送完成状态为UR(Unsupported Request)的完成报文给RC。
  4. P2P2和P2P3都会收到TLP0,由于TLP0的目的地址在P2P2的地址范围内,因此P2P2会接收TLP0,然后将其转发到Bus3上,P2P3不会接收TLP0。
  5. EP0发现TLP0目的地址在BAR0和BAR1表示的地址范围内,则会接收该TLP0,反之则不会接收。

RC Inbound:TLP1由EP1发出,访问RC。流程如下:

  1. EP1生成TLP1,目的地址为0x24600C000,然后通过Bus4发送给Swtich的下行口。
  2. P2P3解析TLP1的目的地址为0x24600C000,不在其0x240000000 – 0x243FFFFFF地址范围内,则P2P3会接收TLP1并将其向Bus2上转发。
  3. 当TLP1到达Bus2时,P2P2发现TLP1的目的地址不在其地址范围内,此时不会接收TLP1,随后TLP1会被P2P1转发到Bus1。
  4. P2P0发现TLP1的目的地址也不在其地址范围内,则会继续向Bus0上转发,此时Host Bridge会接收这个TLP,从而完成RC的访问。

Peer-to-Peer:TLP2由EP1发出,访问EP0。流程如下:

  1. EP1生成TLP2,目的地址为0x240004000,然后通过Bus4发送给Swtich的下行口。
  2. P2P3解析TLP1的目的地址为0x240004000,不在其0x240000000 – 0x243FFFFFF地址范围内,则P2P3会接收TLP2并将其向Bus2上转发。
  3. 当TLP2到达Bus2时,P2P2发现TLP2的目的地址在其地址范围内,则会接收TLP2,然后将TLP2转发到Bus3上。当P2P1发现TLP2已被P2P2接收了,则不会再转发TLP2。
  4. EP0发现TLP2目的地址在BAR0和BAR1表示的地址范围内,则会接收该TLP2,反之则不会接收。

地址路由

3.ID路由(ID Routing)

配置请求、完成报文和Vendor Defined消息报文使用ID路由。与地址路由不同,ID路由使用Bus Number、Device Number和Function Number组成的16位BDF进行寻址。

如下图所示,桥的配置空间中有三个和总线编号相关的寄存器。Primary Bus Number表示与桥相连的上游总线编号,Secondary Bus Number表示桥下游第一个总线编号,即桥下游最小的总线编号,Subordinate Bus Number表示桥下游最后一个总线编号,即桥下游最大的总线编号。这三个寄存器定义了桥的上游总线和下游总线编号范围,桥就是根据这些信息,进行ID路由。

总线范围

下图是一个已经枚举完成的PCIe总线。Pri表示Primary Bus Number,Sec表示Secondary Bus Number,Sub表示Subordinate Bus Number,Device x表示Device Number,Function x表示Function Number。实质上,Device Number和Function Number已经由硬件确定。比如下图中3个Port的Swtich,上行口为Device 0,下行口从左到右依次为Device 1和Device 2,对于EP,由于只有一个设备,因此Device Number固定为0。设备有几个Function,则Function Number从0开始依次递增。

如下图所示,CPU通过RC访问Bus Number=3,Device Number=0,Function Number=0的设备。TLP通过Host Bridge被转发Bus0上,此时RC的两个下行口都会收到TLP,左边的P2P发现目的设备的总线号3在其下游总线编号1-4的范围内,因此会接收,并将其向下游总线转发,右边的P2P发现目的设备的总线号3不在其下游总线编号5-9的范围内,因此不会接收该TLP。与之类似,TLP最终会穿越左边的Swtich,到达要访问的设备。

ID路由

4.隐式路由(Implicit routing)

某些消息请求使用隐式路由,如INTx中断消息、电源管理消息和错误消息等。这些消息要么直接发向RC,要么是来自RC的广播报文,要么是Local: terminate at receiver。这些报文不使用地址或ID路由,而是使用Msg或MsgD报文中的Routing(Type[2:0])字段进行路由,这种路由方式称为隐式路由。如果桥收到一条使用隐式路由的TLP时,将根据Routing(Type[2:0])字段的不同而分别处理。若是收到了一条来自RC的广播消息,则会向下游转发,若是收到了一条发向RC的消息报文,则会向上游转发,若式收到了一条Local: terminate at receiver消息报文,则会接收并终结此消息报文,不会向上游或下游转发。

消息报文隐式路由

参考资料

  1. PCIEXPRESS体系结构导读
  2. PCI Express technology 3.0
  3. PCI Express® Base Specification Revision 5.0 Version 1.0

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/846641.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Google力作 | Infini-attention无限长序列处理Transformer

更多文章,请关注微信公众号:NLP分享汇 原文链接:Google力作 | Infini-attention无限长序列处理Transformerhttps://mp.weixin.qq.com/s?__bizMzU1ODk1NDUzMw&mid2247485000&idx1&sne44a7256bcb178df0d2cc9b33c6882a1&chksm…

Linux的shell脚本:如何用bash脚本从mysql数据库中直接读取用户数据,并直接显示出来(一条命令查看数据库信息)

目录 一、要求 二、脚本和解释 三、脚本执行 1、 脚本保存为sh文件 2、给脚本赋予执行权限 3、运行脚本 四、Bash脚本中,可以使用哪些MySQL语句 1、连接到MySQL数据库 2、执行SQL语句 3、查询并显示结果 4、脚本中执行SQL文件 5、数据库操作 …

Vue.js 动态组件与异步组件

title: Vue.js 动态组件与异步组件 date: 2024/6/2 下午9:08:50 updated: 2024/6/2 下午9:08:50 categories: 前端开发 tags:Vue概览动态组件异步加载性能提升路由管理状态控制工具生态 第1章 Vue.js 简介 1.1 Vue.js 概述 Vue.js 是一个渐进式的JavaScript框架,…

《论文阅读》通过顺序不敏感的表示正则化实现稳健的个性化对话生成 ACL 2023

《论文阅读》通过顺序不敏感的表示正则化实现稳健的个性化对话生成 ACL 2023 前言 相关个性化生成论文推荐简介问题定义方法损失函数实验结果 前言 亲身阅读感受分享,细节画图解释,再也不用担心看不懂论文啦~ 无抄袭,无复制,纯手…

中间件模版引擎

文章目录 中间件1.自定义中间件1)全局2)局部中间件 2.内置中间件(静态资源目录) Art-template1.模板语法1)输出2)原文输出3)条件判断4)循环5)子模版6)模版继承7&#xff…

vue-Dialog 自定义title样式

展示结果 vue代码 <el-dialog :title"title" :visible.sync"classifyOpen" width"500px" :showClose"false" class"aboutDialog"> <el-form :model"classifyForm" :rules"classifyRules">…

【OJ】C++ | 二叉树进阶 · 合集(2)

摘要&#xff1a;根据二叉树创建字符串、二叉树的最近公共祖先、二叉树的层序遍历 前言&#xff1a;承接上文&#xff0c;本文继续提供二叉树进阶有关题目的解法。如有错误&#xff0c;烦请指正。 目录 1. 根据二叉树创建字符串 题解及代码 2. 二叉树的最近公共祖先 题解及…

Java | Leetcode Java题解之第121题买卖股票的最佳时机

题目&#xff1a; 题解&#xff1a; public class Solution {public int maxProfit(int prices[]) {int minprice Integer.MAX_VALUE;int maxprofit 0;for (int i 0; i < prices.length; i) {if (prices[i] < minprice) {minprice prices[i];} else if (prices[i] -…

用幻灯片讲解C++中的C语言风格数组

用幻灯片讲解C中的C语言风格数组 1.栈内存中的C风格数组 糟糕的可用性&#xff0c;但你将在遗留代码中看到它们。相同类型的对象块。大小必须是常量表达式。第一个元素的索引为0&#xff0c;即数组索引从0开始。 注意一下数组的初始化&#xff0c;使用了C11标准之后的统一初始…

数学建模--特殊的图

目录 1.二部图 &#xff08;1&#xff09;简单认识 &#xff08;2&#xff09;定义 &#xff08;3&#xff09;判定定理 &#xff08;4&#xff09;定理理解 2.匹配问题 &#xff08;1&#xff09;匹配 &#xff08;2&#xff09;完备&&完美匹配 &#xff08;3…

Python 入门教程详细版全集(两周速成)

一、初始Python 打开CMD&#xff08;命令提示符&#xff09;程序&#xff0c;输入Python并回车。然后&#xff0c;在里面输入代码回车即可立即执行。 Tip1:找不到“命令提示符”程序在哪里&#xff1f; 使用快捷键&#xff1a;win r;打开运行框&#xff0c;输入cmd后回车即可…

chat2-Client发送数据给Server

本文档描述了Client发送消息给Server&#xff0c; Server端打印接收的消息 一、Client 1.1.客户端的类Client.java中添加如下的start()方法 (表示启动客户端功能的方法)&#xff0c;并调用 /**start方法&#xff0c;作为客户端开始工作的方法*/ public void start(){ …

自然语言处理(NLP)—— 神经网络语言处理

1. 总体原则 1.1 深度神经网络&#xff08;Deep Neural Network&#xff09;的训练过程 下图展示了自然语言处理&#xff08;NLP&#xff09;领域内使用的深度神经网络&#xff08;Deep Neural Network&#xff09;的训练过程的简化图。 在神经网络的NLP领域&#xff1a; 语料…

深入解析Java中List和Map的多层嵌套与拆分

深入解析Java中List和Map的多层嵌套与拆分 深入解析Java中List和Map的多层嵌套与拆分技巧 &#x1f4dd;摘要引言正文内容什么是嵌套数据结构&#xff1f;例子&#xff1a; 遍历嵌套List和Map遍历嵌套List遍历嵌套Map 拆分嵌套数据结构拆分嵌套List拆分嵌套Map &#x1f914; Q…

排序-希尔排序

介绍 希尔排序属于那种没有了解过的直接看代码一脸懵逼的&#xff0c; 所以同学们尽量不要直接看代码&#xff0c;仔细阅读本篇博客内容。 插入排序本来算是一个低效排序&#xff0c; 一次只可以挪动一个数据&#xff0c; 但是&#xff0c;它的强来了&#xff01;&#xff01…

网吧|基于SprinBoot+vue的网吧管理系统(源码+数据库+文档)

网吧管理系统 目录 基于SprinBootvue的网吧管理系统 一、前言 二、系统设计 三、系统功能设计 1 管理员功能模块 2 网管功能模块 3 会员功能模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#…

Arduino 按钮及弹跳

所需元件 可插入面包板的按钮1个 220Ω电阻1个 10kΩ电阻1个 3mm或5mm LED 1个 面包板1块 Arduino Uno开发板1块 面包板连接线数条 使用外接电阻 将5V接到按钮&#xff0c;按钮的另一端串联1个10kΩ电阻再接地&#xff0c;这样的接法被称为下拉电阻(pull-down resistor)。若测…

【30天精通Prometheus:一站式监控实战指南】第14天:jmx_exporter从入门到实战:安装、配置详解与生产环境搭建指南,超详细

亲爱的读者们&#x1f44b;   欢迎加入【30天精通Prometheus】专栏&#xff01;&#x1f4da; 在这里&#xff0c;我们将探索Prometheus的强大功能&#xff0c;并将其应用于实际监控中。这个专栏都将为你提供宝贵的实战经验。&#x1f680;   Prometheus是云原生和DevOps的…

【LeetCode算法】第104题:二叉树的最大深度

目录 一、题目描述 二、初次解答 三、官方解法 四、总结 一、题目描述 二、初次解答 1. 思路&#xff1a;二叉树的先序遍历。首先判断根节点是否是空&#xff0c;其次判断根节点是否是叶子节点&#xff0c;再者递归获取左子树的深度、右子树的深度&#xff0c;最后返回左子…