从零开始讲PCIe(4)——PCI总线的地址空间分配

news2024/10/4 16:25:44

一、概述

        PCI架构支持三种地址空间,如图1-10所示:内存地址空间(Memory Map)I/O地址空间(I/O Map)配置地址空间(PCI Configure Space)。在x86处理器中,处理器可以直接访问内存I/O空间。PCI设备可以映射到处理器的内存地址空间,支持32位或64位内存寻址。在I/O地址空间中,PCI支持32位地址,但由于x86 CPU只使用16位I/O地址空间,许多平台将I/O空间限制为64KB(16位地址的容量)。

        此外,PCI引入了第三种地址空间,称为配置空间,该空间只能通过间接方式访问。每个功能包含内部寄存器,用于配置空间的管理。这些寄存器为软件提供了标准化的地址和资源控制,使得PC真正实现了“即插即用”环境。每个PCI功能最多有256字节的配置地址空间。PCI支持每个设备最多8个功能、每条总线最多32个设备、每个系统最多256条总线,因此系统的总配置空间量为:
256 Bytes/function x 8 functions/device x 32 devices/bus x 256 buses/system = 16MB

        由于x86 CPU无法直接访问配置空间,必须通过I/O寄存器间接访问。传统模型中,如图1-10所示,使用位于地址CF8h-CFBh的I/O端口,称为配置地址端口,以及映射到地址CFCh-CFFh的配置数据端口

        需要注意的是,在PCI Express中,引入了一种新的方法,通过将配置空间映射到内存地址空间来访问配置空间,从而简化了访问过程。

二、PCI内存地址空间

        内存地址空间是最常用的地址空间之一,PCI设备可以将其资源(如设备寄存器、缓冲区等)映射到处理器的内存地址空间中,使CPU可以通过标准的内存读写指令访问PCI设备。PCI设备可以支持32位或64位内存寻址,这意味着它们可以使用32位或64位地址来映射设备资源。

        在这种情况下,PCI设备的内存区域会映射到处理器的内存空间,CPU可以通过访问这些内存地址与PCI设备交互。例如,显卡或网络接口卡(NIC)等设备会将其寄存器或内存缓冲区映射到系统内存地址空间中,CPU可以直接读写这些地址来控制设备或传输数据。

三、PCI I/O地址空间

        I/O地址空间是专门为I/O设备保留的空间,用于与外部设备通信。在x86系统中,CPU可以直接访问I/O地址空间,并使用特殊的INOUT指令与设备进行交互。PCI支持32位I/O地址空间,但由于x86 CPU的I/O空间通常限制为16位,这导致许多平台上的I/O地址空间被限制为64KB(即16位地址范围)。

        I/O空间通常用于较小的外围设备,例如串口、并口等传统设备,它们只需要少量的I/O寄存器。由于I/O空间有限,现代的大多数PCI设备倾向于使用内存映射的方式,而不是依赖于有限的I/O地址空间。

四、PCI配置地址空间

        每个PCI功能都有一个256字节的配置空间,用于存储设备的配置信息,如设备ID、供应商ID、状态、命令寄存器等。为了访问这个配置空间,操作系统和驱动程序会通过I/O地址0xCF8~0xCFF与PCI设备进行交互。

2.1 地址和数据寄存器

2.1.1 地址寄存器

        0xCF8~0xCFB(地址寄存器):总共4个字节(32位),用于指定要访问的PCI设备的配置空间的地址。这个地址寄存器会包含PCI总线号、设备号、功能号和配置空间中的寄存器偏移。

  • 第31位:启用位,必须设置为1。
  • 第30~24位:保留,通常为0。
  • 第23~16位:总线号,用于指定哪个PCI总线上的设备。
  • 第15~11位:设备号,用于指定总线上的设备(一个PCI总线上最多可以有32个设备)。
  • 第10~8位:功能号,用于选择设备的不同功能(每个设备最多有8个功能)。
  • 第7~2位:寄存器号,指定配置空间中的寄存器(以4字节为单位,每个寄存器占用4个字节)。
  • 第1~0位:保留位,必须为0。

2.1.2 数据寄存器

        0xCFC~0xCFF(数据寄存器):同样是4个字节(32位),用于读取或写入之前通过地址寄存器指定的PCI配置空间的数据。用于读取或写入通过地址寄存器(0xCF8)指定的PCI配置空间数据。读取或写入时,数据会被放置到这里。

        虽然在0xCF8~0xCFF范围内确实只有4个字节用作地址寄存器和4个字节用作数据寄存器,但它们是用于与设备的整个PCI配置空间交互的“窗口”,通过改变地址寄存器中的内容,可以访问PCI设备的256字节配置空间的任何部分。

2.2 工作机制

        由于I/O地址空间有限,传统模型在使用地址时非常保守。常见的做法是使用两个寄存器:一个用于指向设备内部的位置,另一个用于读取或写入数据。在PCI配置过程中,这涉及到两个步骤:

第一步:通过I/O写入配置地址

        CPU生成一次I/O写操作,将数据写入北桥的地址端口(I/O地址CF8h),以提供要访问的配置寄存器地址。这个地址包含三个主要部分,用于在PCI拓扑中定位特定的PCI功能(function):除此之外,还需要指定要访问该功能的配置空间中的哪一个64个双字(256字节)寄存器。

  • 总线号(Bus Number):用于访问256条可能的总线中的一条。
  • 设备号(Device Number):用于选择该总线上32个设备中的一个。
  • 功能号(Function Number):用于选择该设备中的8个功能中的一个。

第二步:通过I/O读或写访问数据

        CPU生成一个I/O读或I/O写操作,指向北桥的数据端口(I/O地址CFCh)。根据这一操作,北桥将生成一个配置读取或配置写入事务,发送到在地址端口中指定的PCI总线上。

        这种两步访问方法允许CPU通过I/O地址空间与PCI设备的配置空间进行交互。虽然I/O地址空间有限,但通过这种机制,系统可以有效地管理和配置多达256条总线、每条总线32个设备、每个设备最多8个功能的复杂系统。

2.3 举例说明

        假设我们要读取PCI总线0上的设备5的功能0的供应商ID(Vendor ID),它位于配置空间的偏移地址0x00~0x01

2.3.1 计算地址寄存器的值

        根据PCI配置空间的地址格式,我们需要构造要写入0xCF8的地址:

        将这些位组合起来,我们得到地址寄存器的值为:

  • 启用位:第31位 = 1
  • 总线号:总线0,所以第23~16位 = 0x00
  • 设备号:设备5,所以第15~11位 = 0x05
  • 功能号:功能0,所以第10~8位 = 0x00
  • 寄存器号:我们要读取供应商ID,它在寄存器偏移0x00,所以第7~2位 = 0x00
  • 保留位:第1~0位 = 0
0x80000000 | (0x00 << 16) | (0x05 << 11) | (0x00 << 8) | (0x00 << 2) = 0x80002000

2.3.2 向地址寄存器写入地址

        使用outl指令将0x80002000写入0xCF8,指定要访问的PCI设备地址:

outl(0x80002000, 0xCF8);

2.3.3 从数据寄存器读取数据

        供应商ID占用配置空间的前两个字节,因此我们可以从0xCFC读取前两字节:

uint16_t vendor_id = inl(0xCFC) & 0xFFFF;

        这个操作会从PCI配置空间的偏移地址0x00读取4字节数据,但我们只需要前两字节,所以我们通过& 0xFFFF只获取低16位,这就是供应商ID。

        假设读取到的数据是0x8086,那么供应商ID就是0x8086,这表明该设备由Intel制造,因为0x8086是Intel的供应商ID。

2.4 总结

        通过上述操作,我们成功从PCI总线0、设备5、功能0的配置空间读取了供应商ID。类似地,我们可以访问其他配置空间寄存器,比如设备ID、命令寄存器等。每次访问不同的寄存器时,只需调整地址寄存器中的寄存器号和其他位。

        这个机制使得操作系统和驱动程序能够方便地与PCI设备交互,从而进行设备初始化、配置和控制。

五、PCI Function配置寄存器空间

        每个PCI功能包含最多256字节的配置空间。在这256字节中,前64字节包含一个称为Header的结构体,而剩下的192字节用于支持可选功能。系统的配置首先由Boot ROM固件完成。当操作系统加载后,它可能会重新配置系统并重新分配资源,因此系统配置过程可能会被执行两次。

        根据Header类型的不同,PCI功能可以分为两大类:

  • Type 1 Header:用于标识一个桥接设备(bridge),这种功能创建了拓扑中的另一条总线,如图1-12所示。
  • Type 0 Header:用于标识一个非桥接设备(non-bridge function),如图1-13所示。

 

        这种Header类型信息存储在dword 3字节2中,是软件在系统中发现功能时(即进行枚举的过程)首先要检查的字段之一。枚举过程帮助操作系统或固件识别系统中存在的所有PCI功能,并根据其类型进行进一步的资源分配和管理。

        通过这种区分,系统可以识别出哪些设备是普通的I/O设备,哪些设备是桥接器,从而构建完整的总线拓扑结构并有效地进行设备配置。

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

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

相关文章

PHP代码审计方法与套路

PHP代码审计方法与套路 01&#xff0c;审计前的准备&#xff08;1&#xff09;获取源码&#xff08;2&#xff09;安装网站 02&#xff0c;把握大局&#xff08;1&#xff09;网站结构&#xff08;2&#xff09;入口文件&#xff08;3&#xff09;配置文件&#xff08;4&#x…

Elasticsearch学习记录

阅读前须知 本文通过安装elasticsearch-7.17.0为基础&#xff0c;使用 kibana-7.17.0 对 elasticsearch 进行操作&#xff0c;本文中 es 是对 elasticsearch 的简写。 下载地址&#xff1a;elasticsearch_免费高速下载|百度网盘-分享无限制 (baidu.com) 1 初识Elasticsearch …

vue3 + ts + cesium:绘制、更新圆 ellipse

本文主要实现基础的绘制圆形&#xff0c;并且可以通过拖动圆心更新圆的位置&#xff0c;拖动圆上的边缘点改变圆的半径。 实现效果&#xff1a; &#xff08;1&#xff09;单击鼠标左键开始绘制&#xff0c;确定圆的圆心&#xff0c;移动鼠标&#xff0c;改变圆的半径&#xff…

CodeFormer模型构建指南

一、介绍 在 NeurIPS 2022 上&#xff0c;南洋理工大学-商汤科技联合研究中心 S-Lab 提出了一种基于 VQGANTransformer的人脸复原模型 CodeFormer。基于CodeFormer模型实现面部复原、增强旧照片/修复AI艺术、面部颜色增强和修复、面部修复四个功能。 二、特点 CodeFormer 是…

常用组件详解(九):学习率更新策略

文章目录 1.StepLR2.MultiStepLR3.ExponentialLR4.LinearLR5.PloyLR 适合的学习率能够更好地训练模型&#xff0c;为此衍生出多种学习率调整策略。一般来说&#xff0c;在训练初期希望学习率大一些&#xff0c;使得网络收敛迅速&#xff0c;在训练后期希望学习率小一些&#xf…

jmeter学习(4)提取器

同线程组https://blog.csdn.net/vikeyyyy/article/details/80437530 不同线程组 在JMeter中&#xff0c;正则表达式提取的参数可以跨线程组使用。 通过使用Beanshell后置处理器和属性设置函数&#xff0c;可以将提取的参数设置为全局变量&#xff0c;从而在多个线程组之间共享…

Spring Boot新闻推荐系统设计与实现

3系统分析 3.1可行性分析 通过对本新闻推荐系统实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本新闻推荐系统采用JAVA作为开发语言&#xff0c;Spring Boot框…

Go语言实现长连接并发框架 - 开篇

文章目录 前言初步设计思路初步架构图项目地址最后 前言 你好&#xff0c;我是醉墨居士&#xff0c;国庆假期闲来无事&#xff0c;准备使用Go语言开发一个轻量级的长连接并发框架&#xff0c;希望能够帮助大家掌握这类框架的心脏与内核&#xff0c;也希望能给大伙带来灵感与启…

【微服务】负载均衡 - LoadBalance(day4)

下述所有代码都是在订单服务中修改的&#xff0c;商品服务并不需要修改&#xff0c;只需要启动多个实例即可。 引入 在介绍Eureka组件的最后&#xff0c;留下了一个问题就是&#xff0c;无论启动多少个实例&#xff0c;只能调用第一个。原因是因为服务调用时获取的是一个实例…

C/C++/EasyX——入门图形编程(3)

【说明】上一篇讲了基础图形的绘制&#xff0c;那么这一篇就来讲一下如何在窗口上绘制文字吧&#xff0c;友友们一起学习吧。&#xff08;&#xff1e;&#xff59;&#xff1c;&#xff09;&#xff08;&#xff3e;&#xff56;&#xff3e;&#xff09; 一&#xff1a;文字…

jQuery——对象的过滤

在 jQuery 对象中的元素对象数组中过滤出一部分元素来 ① first&#xff08;&#xff09; ② last&#xff08;&#xff09; ③ eq&#xff08;index / -index&#xff09; ④ filter&#xff08;selector&#xff09;&#xff1a;对当前元素提要求 ⑤ not&#xff08;sel…

电脑IP地址怎么换成二进制:详解转换过程与应用

在电脑网络的世界里&#xff0c;IP地址是每台设备独一无二的身份标识。而我们日常所见的IP地址&#xff0c;大多是以点分十进制的形式呈现。然而&#xff0c;在电脑内部&#xff0c;IP地址实际上是以二进制的形式进行存储和处理的。那么&#xff0c;电脑IP地址怎么换成二进制呢…

pygame入门(千字详细版)

千字赘述&#xff0c;万字总结&#xff0c;就为博客点一赞吧&#xff01; 1.安装pygame pip install pygame 安装完成后在python中输入检验有没有问题&#xff0c;回车键应该不会报错。 >>>import pygame >>>2.pygame模块预览 3.项目实战 3.1.0 hello w…

一键开启高清录屏:盘点Windows最火四款录屏工具

嘿&#xff0c;朋友们&#xff0c;今天咱们来聊聊那些让我在电脑前忙活得热火朝天的录屏神器究竟怎么样。作为一个经常需要录制教程、分享游戏精彩瞬间的普通用户&#xff0c;我可是对这几款软件有着满满的体验心得&#xff0c;现在就给你们一一道来。 一、福昕录屏大师 网址…

编码与解码

文章目录 编码与解码一、字节 & 字符二、编码 & 解码三、字符集 & 字符编码四、ASCII五、ISO-8859-1六、GB七、Unicode1、概述2、发展3、UTF-8 编码4、UTF-16 编码 八、Base64 编码1、概述2、原理3、代码示例 九、十六进制编码 编码与解码 一、字节 & 字符 字…

kali下编译AOSP报错(libncurses.so.5: cannot open shared object file)

编译报错信息&#xff1a;libncurses.so.5: cannot open shared object file: No such file or directory /bin/bash -c "PWD/proc/self/cwd prebuilts/clang/host/linux-x86/clang-3289846/bin/clang -Ifr ameworks/rs/script_api/include -Iexternal/clang/lib/Headers …

【AI知识点】小世界网络(Small-World Networks)

小世界网络&#xff08;Small-World Networks&#xff09; 是一种具有独特拓扑结构的网络模型&#xff0c;广泛应用于研究社交网络、神经网络、互联网以及其他复杂系统中的节点间连接方式。小世界网络的特点是节点之间的平均路径长度较短&#xff0c;并且大多数节点的局部连接较…

世邦通信股份有限公司IP网络对讲广播系统RCE

漏洞描述 SPON世邦IP网络广播系统采用的IPAudio™技术, 将音频信号以数据包形式在局域网和广域网上进行传送&#xff0c;是一套纯数字传输的双向音频扩声系统。传统广播系统存在的音质不佳&#xff0c;传输距离有限&#xff0c;缺乏互动等问题。该系统设备使用简便&#xff0c…

知识图谱入门——7:阶段案例:使用 Protégé、Jupyter Notebook 中的 spaCy 和 Neo4j Desktop 搭建知识图谱

在 Windows 环境中结合使用 Protg、Jupyter Notebook 中的 spaCy 和 Neo4j Desktop&#xff0c;可以高效地实现从自然语言处理&#xff08;NLP&#xff09;到知识图谱构建的全过程。本案例将详细论述环境配置、步骤实现以及一些扩展和不足之处。 文章目录 1. 环境准备1.1 Neo4j…

webGL入门(六)图形旋转

效果&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</…