启动流程分析

主要来看下当前内核中,相较于之前的部分,多了哪些东西,已经分析下他们的作用。

Makefile分析

首先来分析一下执行make qemu 后,对于网络部分,做了哪些工作。

在Makefile文件中,我们可以找到关于网络的一些特有qemu虚拟配置,代码如下:

ifeq ($(LAB),net)
QEMUOPTS += -netdev user,id=net0,hostfwd=udp::$(FWDPORT)-:2000 -object filter-dump,id=net0,netdev=net0,file=packets.pcap
QEMUOPTS += -device e1000,netdev=net0,bus=pcie.0
endif

查找qemu的手册,找到了关于其配置的讲解,其中qemu有设备前端和后端的概念,简单来说前端指的是模拟的硬件设备,后端指的是前端的数据应该被如何处理。前端通过-device来指定设备,后端通过-xxxdev来指定数据的处理方式。
在这里,

  • -device e1000 指定了前端设备是e1000网卡,它的后端设备是net0,在总线pcie.0上;

  • -netdev user 配置了不需要管理员权限即可运行的用户模式主机网络后端。

    • id 指定了可以在监视器命令中使用的符号名称,也就是net0。

    • hostfwd 表示将传入的 TCP 或 UDP 的数据从主机hostaddr的端口 hostport 转发到 访客 IP 地址为guestaddr的guestport 端口上的。如果未指定 guestaddr,则其值为 xxx15(内置 DHCP 服务器默认提供的第一个地址)。通过指定 hostaddr,可以将规则绑定到特定的主机接口。如果未设置连接类型,则使用 TCP。

      那么在这里,指定了将传入的UDP数据包从主机FWDPORT端口上转发到访客端口2000上。

  • -object filter-dump 表示将 netdev net0 上的网络流量转储到 packets.pcap文件中。每个数据包存储64k个字节(默认)。

main函数分析

在main函数中,添加了两个初始化的方法,如下所示

#ifdef LAB_NETpci_init();sockinit();
#endif

pci_init 方法是对pcie.0总线上的网卡设备的初始化,代码如下:

void
pci_init()
{// we'll place the e1000 registers at this address.// vm.c maps this range.uint64 e1000_regs = 0x40000000L;// qemu -machine virt puts PCIe config space here.// vm.c maps this range.uint32  *ecam = (uint32 *) 0x30000000L;// look at each possible PCI device on bus 0.for(int dev = 0; dev < 32; dev++){int bus = 0;int func = 0;int offset = 0;uint32 off = (bus << 16) | (dev << 11) | (func << 8) | (offset);volatile uint32 *base = ecam + off;uint32 id = base[0];// 100e:8086 is an e1000if(id == 0x100e8086){// command and status register.// bit 0 : I/O access enable// bit 1 : memory access enable// bit 2 : enable masteringbase[1] = 7;__sync_synchronize();for(int i = 0; i < 6; i++){uint32 old = base[4+i];// writing all 1's to the BAR causes it to be// replaced with its size.base[4+i] = 0xffffffff;__sync_synchronize();base[4+i] = old;}// tell the e1000 to reveal its registers at// physical address 0x40000000.base[4+0] = e1000_regs;e1000_init((uint32*)e1000_regs);}}
}

在了解pci_init函数的功能之前,需要知道的储备知识是pci设备的配置空间,每个pic设备都有一个配置空间,大小为256B,实际上是一组连续的寄存器,其中头部64字节是PCI标准规定的,格式如下(图片来自维基百科)

剩余的部分是PCI设备自定义的。
其中DeviceID寄存器和VendorID寄存器标识设备ID和供应商ID;Status寄存器用于标识支持哪些功能以及是否发生了某些类型的错误。命令寄存器包含可以单独启用和禁用的功能的位掩码。

另外PCI配置空间头部有6个BAR(Base Address Registers),BAR记录了设备所需要的地址空间的类型(memory space或者I/O space),基址以及其他属性。PCI配置空间的初始值是由厂商预设在设备中的,于是设备需要哪些地址空间都是其自己定的,可能造成不同的PCI设备所映射的地址空间冲突,因此在PCI设备枚举(也叫总线枚举,由BIOS或者OS在启动时完成)的过程中,会重新为其分配地址空间,然后写入PCI配置空间中。

所以不难看出pci_init的前半部分功能是枚举总线上设备的配置空间,读取Device ID和Vendor ID从而确定e1000网卡设备,设置命令寄存器从而开启了设备可以响应I/O空间的访问,可以响应内存空间的访问,以及设备可以充当总线主控。
重点来讲一下对每个BAR设置0xffffffff的作用,这部分,查阅了很多,都没有讲,最后在维基百科中找到了答案,如下

也就是说,为了完成对BAR的配置,需要:

  • 对BAR[x]写入全1
  • 再从BAR[x]读出值,假设为y,通过~(0xffffff00 & y) + 1就是该BAR映射地址空间的大小
  • 确定完大小后写入地址空间的起始地址就完成了对BAR的配置

我们来验证一下这个过程,在确定每个BAR大小的for循环中加入对大小的输出语句

再次执行 make qemu 得到输出

其中0x20000就是BAR0的大小,0x100就是BAR1的大小,在这里我们只需要使用BAR0,也就是e1000_regs,就只在BAR0写入了起始地址,并且可以在vm.c的kvmmake中得到验证

// pci.c maps the e1000's registers here.kvmmap(kpgtbl, 0x40000000L, 0x40000000L, 0x20000, PTE_R | PTE_W);

这样,大概就可以理解这个函数的功能了,也就是设置了网卡中的一些寄存器值,并确定了BAR的大小,以及BAR0中的基址。这个BAR0存储的就是设备所需要空间的内存基址,在这里,也就是e1000_init函数中,我们可以看到,这段空间被用来设置网卡的各个控制位。

XV6 Network解析-1相关推荐

  1. OpenStack ussuri 私有云平台搭建

    一.OpenStack简介 openstack是一个云操作系统,这个操作系统控制着数据中心中的计算,存储和网络资源.所有这些资源的管理都是通过API来来实现的,并且管理资源都有相应的认证机制. 在op ...

  2. GCN代码超详解析Two-stream adaptive graph convolutional network for Skeleton-Based Action Recognition(三)

    代码地址https://github.com/lshiwjx/2s-AGCN 本篇解析对应 2s-AGCN/graph/ntu_rgb_d.py ,用于创建NTURGB-D对应的图结构,以及2s-AG ...

  3. Cilium创建pod network源码解析

    01 Overview 我们生产K8s使用容器网络插件 Cilium 来创建 Pod network,下发 eBPF 程序实现 service 负载均衡来替换 kube-proxy,并且使用 BGP ...

  4. Graph Attention Network (GAT) 的Tensorflow版代码解析

    文章目录 代码结构 参数设置 数据加载 特征预处理 模型定义 GAT核心定义:layers.py gat.py base_gattn.py 关于GAT的基本原理解析可查看另一篇博客: Graph At ...

  5. 《Evaluate the Malignancy of Pulmonary Nodules Using the 3D Deep Leaky Noisy-or Network》论文解析

    本文解析的三维深度神经网络(3D deep neural network)是"grt123团队"在Kaggle举办的DSB2017中获得了第一名,若其代码公开于Github. 引言 ...

  6. 【Network Architecture】Densely Connected Convolutional Networks 论文解析

    [Network Architecture]Densely Connected Convolutional Networks 论文解析 目录 0. Paper link 1. Overview 2. ...

  7. DeepLearning | 图注意力网络Graph Attention Network(GAT)论文、模型、代码解析

    本篇博客是对论文 Velikovi, Petar, Cucurull, Guillem, Casanova, Arantxa,et al. Graph Attention Networks, 2018 ...

  8. 【OS xv6】1 万字详解shell源码解析命令(内含wsl+vscode调试xv6教程 文档第一章助读)

    现在前面的 嘻嘻几百年没写文了确实没时间,等搞完毕设可以一起重温重温.最近学os,读源码发现还挺多东西得整理的,尤其途中有必要找资料整理的时候,内容有点多有点乱,写在源码已经显得不现实了.用的vsco ...

  9. 场景解析--Pyramid Scene Parsing Network

    Pyramid Scene Parsing Network CVPR2017 语义分割 https://github.com/hszhao/PSPNet 针对 FCN 中没有 context 信息,本 ...

最新文章

  1. 多款eclipse黑色坏境任你选择,只要导入配置
  2. 中兴通讯已在多个国家和地区商用了安全领域的解决方案
  3. 第13讲nbsp;日期和时间nbsp;EXCEL2010…
  4. 【ABAP系列】SAP 面试 ABAPer的一些感想
  5. redis主从复制_技术干货分享:一文了解Redis主从复制
  6. vue 监听页面滚动事件:触发animate.min.css动画特效
  7. 演练 青春不常在 0915
  8. java报错信息怎么看_AE-E3D插件无效或提示OPENGL E3D Debug等错误报错信息怎么办?...
  9. js 按给定数组的顺序给数组排序_JavaScript中如何如何给数组以及数组对象根据value值进行排序。...
  10. 谈目标绩效的一种想象
  11. 网站项目打包成app
  12. 海康网络摄像头web端展示
  13. docker部署redis集群
  14. DebugView远程查看日志
  15. 蓝字冲销是什么意思_会计记账,贷方红字,贷方蓝字什么意思
  16. html sql 编辑器,【web】CodeMirror打造SQL在线编辑器
  17. word转pdf的几种方法
  18. 3、传输介质——同轴电缆
  19. IDA安卓动调 模拟器手机(详细)
  20. html图片自动滚动播放器,jQuery+css实现图片滚动效果(附源码)

热门文章

  1. 电脑蓝屏并提示错误代码0x000000ed怎么办?
  2. OpenStack Swift Account Reaper
  3. CAD螺纹lisp程序_CAD-LISP-程序
  4. 五模二十频4G通讯模块SLM651
  5. 计算机锁定不能强制选项无法关机,win7系统总需要强制关机怎么解决 win7电脑无法正常关机的解决方法...
  6. FLASK中利用javascript实现按钮点击事件
  7. html可变换的背景图片,HTML用ONMOUSEOVER,ONMOUSEOUT改变背景色或背景图片的方法_html/css_WEB-ITnose...
  8. ActivitiBpm6.0官方流程图绘制工具搭建-bpm
  9. C语言PTA题目:7-22 1022 利息
  10. redis安装与启动客户端(redis篇一)