用ZYNQ MPSoC玩DOOM
赛灵思和 DornerWorks 的系统软件团队在赛灵思的 Zynq® Ultrascale+™ MPSoC 上启动 Xen Project 管理程序时,我们发现可通过运行当年叱诧一时的流行电子游戏 Doom 来演示和测试系统。
本文引用地址://m.amcfsurvey.com/article/201808/385964.htm神马?!你不知道 DOOM??(CS 你总知道吧 -__-||)
如何针对 Zynq UltraScale+ MPSoC 通过 QEMU 在 Xen 上运行 Doom 呢,在详细介绍具体步骤之前,我们先来了解什么是管理程序,以及它们如何与 Zynq UltraScale+ MPSoC 上的处理器协同工作。
管理程序及其工作原理
管理程序是一种可虚拟化处理器的计算机程序。运行在虚拟化处理器上的应用程序和操作系统似乎完全拥有系统,但事实上管理程序负责管理虚拟处理器对物理机资源(例如存储器和处理内核)的访问。管理程序之所以流行,是因为能实现设计分区以及系统上运行的独立软件元素之间的隔离。
为了支持虚拟化,物理处理器必须提供一个供管理程序运行的特殊”模式”。因此,介绍处理器模式有助于理解管理程序如何完成处理器魔法。
所有处理器都有一些指令,这些指令可操作寄存器中存储的值,并可读写存储器。处理器的模式是指令和寄存器的集合,以及利用指令访问寄存器和存储器时要遵守的规则。为了便于解释,我们以通用处理器为例来介绍,并使用与结构无关的术语。在这个实例中,处理器具有特定的寄存器、指令和模式。寄存器包括 RegisterA、RegisterB、RegisterC、UserProgramCounter、Register-Super 和 SuperProgramCounter。指令包括以下内容。
· ADD Register3 Register1 Register2 将 Register1 与 Register2 相加,并把结果存入 Register3,即 Register3 = Register1 + Register2。
· MOVTO Register2 Register1 将 Register1 中地址所指向的存储器内容移动到 Register2。
· MOVFROM Register2 Register1 将 Register1 的内容移动到 Register2 中地址所指向的存储器。
· ENTERSUPER 进入处理器的 SUPER 模式。
· EXITSUPER 退出 SUPER 模式并进入 USER 模式。
在 USER 模式下,处理器的指令的功能受到限制。本例中,指令可对除 RegisterSuper 和 SuperProgramCounter 以外的所有寄存器进行读和写操作,处理器可执行除 EXITSUPER 以外的所有指令。
此外,在 USER 模式下,所有指令只能读和写一部分存储器,例如从地址 0x0000_0100 到 0x0FFF_FFFF。在 USER 模式下,如果程序尝试执行不应该执行的指令,或者访问无权访问的寄存器或存储器位置,那么处理器将暂停出错指令 (offending instruction)。
SUPER 模式下,处理器的指令可以读/写上述所有寄存器,包括 RegisterSuper 和 SuperProgramCounter。以上所列的所有指令,包括 EXITSUPER,都可以执行,另外,附加的指令 ENTERHYPER 也可执行(后面详细介绍该指令)。此外,在 SUPER 模式下,指令可以访问系统中的全部存储器(从 0x0000_0000 到 0x7FFF_ FFFF)。
采用带模式的处理器,使我们可以利用设计分区来更简单地解决软件工程设计问题。以上实例中,只有一种方法进入 SUPER 模式:执行 ENTERSUPER 指令。同样,只有一种方法退出 SUPER 模式:执行 EXITSUPER。此外,在 USER 模式下程序只能访问机器的部分存储器。有了这种方案,我们可编写一个程序让处理器同时运行多个 USER 模式程序。这个”操作系统”(OS) 程序运行在 SUPER 模式,并管理在 USER 模式中运行的程序。
当 OS 运行时,会查看需要运行的所有 USER 模式程序,选择一个运行,然后使用 EXITSUPER 这样的指令通知处理器切换到 USER 模式以运行程序。所选的程序会一直运行,直到有事件导致处理器切回 SUPER 模式。这类事件可以是来自 USER 模式程序的 ENTERSUPER 指令,或外部事件,例如定时器,它可以不提醒正在 USER 模式下运行的程序将处理器切换到 SUPER 模式。无论切换如何发生,每当事件发生时,我们都可构建 OS 以根据相应策略相继选择和运行程序。当切换快速进行时,用户认为 USER 程序同时运行。
USER HYPER 模式的用处是让很多 SUPER 程序运行。SUPER 模式下的每个程序都可以是 OS;这些 OS 本身会让很多 USER 程序并行运行。
SUPER 处理器模式还能防止 USER 程序干扰运行在 SUPER 模式的程序或其他 USER 模式程序。USER 模式程序的任何错误或违规都可被控制在该程序自身的实例中,不会破坏或干扰为 SUPER 模式操作保留的系统存储器和寄存器。
听起来很好,但能否用另一个模式实现一些功能?
对我们的机器稍加扩展,就可以引入 HYPER 模式。HYPER 模式可以读/写所有初始寄存器(RegisterA、RegisterB、RegisterC、UserProgramCounter、RegisterSuper 和 SuperProgramCounter)以及两个附加寄存器:RegisterHyper 和 HyperProgramCounter。HYPER 模式下的指令包括初始集以及下面的斜体字。
ADD Register3 Register1 Register2 将 Register1 与 Register2 相加并把结果放在 Register3 中,即 Register3 = Register1 + Register2。
· MOVTO Register2 Register1 将 Register1 中地址所指向的存储器内容移到 Register2。
· MOVFROM Register2 Register1 将 Register1 的内容移到 Register2 中地址所指向的存储器。
· MOVTOPHYS Register2 Register1 将 Register1 中物理地址指向的存储器内容移到 Register2。
· MOVFROMPHYS Register2 Register1 将 Register1 的内容移到 Register2 中地址指向的物理存储器。
· ENTERSUPER 进入处理器的 SUPER 模式。
· EXITSUPER 退出 SUPER 模式并进入 USER 模式。
· ENTERHYPER 进入处理器的 HYPER 模式。
· EXITHYPER 退出处理器的 HYPER 模式。
· SWITCHSUPER RegisterHyper 切换到 SUPER 程序,该程序将使用 RegisterHyper 中的值来执行下一个 SUPER 程序。
HYPER 模式中的附加指令和寄存器允许处理器切换哪个程序在 SUPER 模式中运行,就像 SUPER 模式允许处理器切换哪个程序在 USER 模式中运行一样。HYPER 模式的一个特性是能够切换哪个存储器 SUPER 模式能看到;当一个在 HYPER 模式中运行的程序执行 SWITCHSUPER RegisterHyper 时,底层存储器完全断开。这就是说当 HYPER 模式中的程序执行了 EXITHYPER 之后,下个 SUPER 程序运行之时,SUPER 模式看到的实际物理存储器与运行在 SUPER 模式中的另一个程序使用的物理存储器不同。SUPER 模式程序仍使用相同地址访问存储器,但是该地址指向不同的物理位置。图 1 显示了执行 SWITCHSUPER RegisterHyper 前后的处理器存储器视图。
HYPER 模式很有用,是因为它允许很多个 SUPER 程序运行。SUPER 模式中每个程序都可以是 OS;这些 OS 本身可以让很多 USER 程序并列运行.这意味着,我们可以在相同硬件上运行多个 OS,例如 Windows 和 Linux;在一个处理器上运行 20 个 Linux 实例;或者之间的任意组合。由于每个虚拟 OS 实例无法看到另一个 OS 实例,因此如果一个崩溃,不会使另一个实例也崩溃。HYPER 模式的特性还有其他应用:我们可以在多个 OS 之间对系统资源分区;监测 HYPER 模式下每个 OS 的执行,以在崩溃时重启;以及在虚拟 OS 运行时密切关注系统状态。
![](http://m.amcfsurvey.com/uphotos/fetch/20180719/385964_1_0.jpg)
图 1:HYPER 模式下执行 SWITCHSUPER RegisterHyper 的前后区别
随着处理器从 USER 切换到 SUPER 模式,再从 SUPER 切换到 HYPER 模式,机器会赋予执行代码更多特权。本例中,USER 模式程序只有权使用四个寄存器(RegisterA、RegisterB、RegisterC 和 UserProgramCounter)和四个指令:(ADD、MOVTO、MOVFROM和ENTER-SUPER)。此外,USER 程序只能读写 0x0000_0100 至 0x0FFF_ FFFF 的存储器。一旦进入 SUPER 模式,处理器允许指令与 RegisterSuper 和 SuperProgramCounter 对话,并允许执行 EXITSUPER 和 ENTERHYPER。此外,SUPER 程序可以访问从 0x0000_0000 至 0x7FFF_FFFF 的存储器。
最后,一旦处理器进入 HYPER 模式,其指令就可以操作 RegisterHyper 和 HyperProgramCounter,而且程序可执行 SWITCH-SUPER 和 EXITHYPER。
![](http://m.amcfsurvey.com/uphotos/fetch/20180719/385964_1_1.jpg)
图 2:各种模式如环形所示
HYPER 模式还允许处理器读写所有虚拟存储器,0x0000_0000 至 0xFFFF_FFFF,以及读写实际物理存储器。这些特权等级通常被直观地用环形来描述(图 2)。主环,即 HYPER 环为特权等级较低的环赋予权限,最终可控制整个系统。
理论结合实践
ARM® 创建处理器设计,供 ARM 合作伙伴构建芯片用。ARM 处理器包含一个或多个内核。每个内核实现一个 ARM 架构。例如,Zynq UltraScale+ MPSoC 包含一个 ARM Cortex™-A53 处理器及四个 ARMv8-A 物理内核(图 3)。
当查看 ARM 处理器的文档和代码时,这种区别很重要;为了全面理解具有一个 ARM 内核的”芯片”,可参考有关架构 (如 ARMv8-A) 和处理器 (如 Cortex-A53) 的文档。ARMv8 架构中有四个例外等级 (来源:ARM 架构参考手册,D1-1404):
1、例外等级 0 (EL0),无需特权即可执行;
2、例外等级 1 (EL1),执行 OS 以及任何执行特权指令的内容;
3、例外等级 2 (EL2),允许硬件被虚拟化;以及
4、例外等级 3 (EL3),允许在安全与非安全处理器状态之间切换。
以下程序通常在这些模式下运行,如ARM 架构参考手册 (D1–1404)中所述:EL0,应用程序;EL1,OS 内核以及通常所描述的相关特权函数;EL2,管理程序;EL3,安全监控器。我们的理论实例直接对应 ARMv8 执行模式 EL0 至 EL2:USER 对应 EL0,SUPER 对应 EL1,HYPER 对应 EL2。ARM 添加第四个特权等级,即 EL3;利用这个特权等级,我们可在安全与非安全环境之间切换 EL0 和 EL1。尽管 EL3 的使用是一个很重要的论题,能够为架构增加大量的功能,但是在本实例中我们将其忽略,并着重介绍 EL0-EL2(利用管理程序的虚拟化)。如果对计算机如何保护金融交易感兴趣,可以参阅 ARMv8 EL3 文档(免费提供,需注册)。这是非常好的参考文档,从中可以获得极为详细的介绍。
![](http://m.amcfsurvey.com/uphotos/fetch/20180719/385964_1_2.jpg)
图 3:Zynq UltraScale+ MPSoC 架构
进入和退出例外模式
在真实系统中,模式之间的切换比我们的实例更复杂一些。ARM 总结了 ARMv8-A 架构的行为并在参考手册中给出。手册中介绍,只有在接到例外或从例外返回时,才能改变执行所处的例外等级。在接到例外时,例外等级只能升高或保持不变;在从例外返回时,例外等级只能降低或保持不变。只有三个指令能生成针对下个例外等级的例外:SVC (Supervisor Call),生成针对 EL1 的例外;HVC (Hypervisor Call),生成针对 EL2 的例外;SMC (Secure Monitor Call),生成针对 EL3 的例外。这些指令取值范围为 0-65,555,允许每个例外等级有 216 个系统调用。这些指令针对下个例外等级,而且是唯一可供运行在较低例外等级的程序从运行在较高例外等级的程序请求某些内容的机制。在我们的理论实例中,SVC 是 SWITCHSUPER,HVC 是 SWITCHHYPER。
PetaLinux 工具包含一组命令,以供用户在赛灵思 FPGA 和 SoC 上轻松创建和扩展 Linux 系统。
在前一个部分,我们介绍了能够让运行在 USER 模式(EL0)的程序进入 SUPER 模式 (EL1) 的事件。大多数运行在 USER 模式的程序生成的事件是请求存储器。当运行在 EL0 中的用户空间程序从运行在 EL1 中的 OS 请求存储器时,这个用户空间程序的 C 代码可能调用函数 malloc(),再由该函数调用 mmap() 或 sbrk(),以从 OS 请求一个指向可用存储器的指针。在 ARMv8-A 架构中的 Linux 上,这个过程在幕后转化为 SVC 系统调用。该系统调用会把处理器转换为 EL1,从而将控制权送回 OS,后者会解读调用内容并提供正确的响应——本例中是指向所请求存储器区域的指针,或者是一个错误,用以指出没有可用存储器。
演示创建和工具
现在我们来介绍我们团队在 Zynq UltraScale+ QEMU Model 上运行 Doom 时所采用的步骤。这些步骤展示了如何获得和构建运行演示所需的每个组件,如何运行以及以什么顺序运行每个组件,以及如何与演示交互。成功完成该演示之后,你会获得一个环境,用来在上面进行实验,以了解 Xen 管理程序在仿真的 Zynq UltraScale+ MPSoC 上的运行情况。还需要将此迁移植 Zynq UltraScale+ MPSoC 芯片,这可作为练习由用户来完成。
想玩 DOOM 吗?
为了让过程更简单,赛灵思提供基础的根文件系统,这样用户就无需花时间和精力自己构建。此演示所需的所有下载内容在以下网址中均有提供: www.wiki.xil- inx.com/Doom+on+Xen+Demo。
该演示首先通过更新由赛灵思提供的预编译根文件系统 (rootFS),可包含所需的组件。然后,利用赛灵思的 PetaLinux 工具运行演示。rootFS 包含运行于 Linux 系统上的大部分程序——具体来说就是用来启动系统的一组脚本,以及用来实现系统的应用程序与函数库集。我们用来扩展演示中的基础 rootFS 所使用的两个工具分别是 Buildroot 和 PetaLinux。我们使用 Buildroot 为赛灵思提供的基础 rootFS 构建 Doom 二进制文件,同时使用 PetaLinux 创建 rootFS 的剩余部分并引导演示。
Buildroot
Buildroot 是一个简单的构建系统,用于为 Linux 系统创建 rootFS。它使用 make menuconfig 接口,这是一个用来配置 Linux 内核本身的常用方法。Buildroot 包含对 PrBoom 的默认支持,这对于本演示很有帮助。(PrBoom 是我们所使用的 Doom 游戏的 GNU 通用公共许可证 [GPL] 版本。这里我们会穿插使用 PrBoom 和 Doom 这两个术语。 )Buildroot 对 Xen 构建不提供本地支持(尽管它可创建用于构建 Xen 所需的所有库和工具链),因此赛灵思提供 Xen、Xen 工具和为用户预编译的 Xen 库以及其他一些所需的库,以让过程简单直观。
PetaLinux
PetaLinux 工具包含一个命令集,以便让用户在赛灵思 FPGA 和 SoC 上轻松创建和扩展 Linux 系统。该演示使用 petalinux-build 和 petalinux-boot 命令。petalinux-build 命令用于创建全部所需的组件。petalinux-boot 命令(外加几个变量)用于启动在 QEMU 仿真器上运行的所有组件。介绍 PetaLinux 工具中的所有命令超出了本文的范围,但是通过此演示系统应该很容易发掘这两个命令和其他命令的功能。参考PetaLinux 工具文档 — 参考指南 UG1144 (v2015.4) 了解更多信息。
项目先决条件
该项目需要一个运行 Linux 的工作站或虚拟机,具有满足 UG1144 (v2015.4) 中所列的 PetaLinux 工具安装要求的环境,而且环境中需要安装赛灵思 PetaLinux Tools v2015.4 版本。
一旦 Doom 启动,你就可以使用键盘和鼠标控制游戏。应记住,可能需要点击 ESC 键来开始游戏。开始游戏咯!
步骤 1:构建 ROOTFS
首先,我们需要构建 rootFS。从赛灵思下载 doom_demo.tar.gz,打开下载目录中的一个 terminal;你可在以下网址中找到全部所需文件: www.wiki.xilinx.com/Doom+on+Xen+Demo。我们将该目录称为 。
解压文档。
$ cd
$ tar -xzf doom_demo.tar.gz cd doom_demo
我们会看到一个文件夹,我们将把它存到根文件系统(一个用于 Dom0,另一个用于 DomU)。现在,我们需要构建 PrBoom,并复制到 rootFS。
评论