【问题标题】:If there are two processors in one system, could the second processor be controlled if it has a different architecture?如果一个系统中有两个处理器,如果第二个处理器具有不同的架构,是否可以控制它?
【发布时间】:2016-11-02 15:10:04
【问题描述】:

假设我有一台有 2 个处理器的计算机,一个使用 x64,另一个使用 ARM。 x64 Linux 内核能否控制第二个 (ARM) 处理器?

【问题讨论】:

  • 定义“控制”。
  • 即使不考虑 AMD 的安全处理器之类的东西,您的 x64 机器也可能已经控制了大量的 ARM 处理器 - 在您的磁盘驱动器、网络芯片等中。或者您是专门询问共享内存通信而不是比专用接口另一端的东西? (在这种情况下,既然您提到了 Linux,请查看 remoteproc 框架)
  • 控制,我的意思是向处理器发送指令。我觉得没必要这么说,但就我而言,我想知道 Kali Linux 是否可以控制新 macbooks(T1?) 中的 ARM 处理器来控制触摸栏。
  • 定义“发送指令”。在“通过它所呈现的任何接口向它发送它期望的命令以使其执行其固件设计要做的事情”的意义上,那么显然这是可能的,因为 macOS 做到了。从概念上讲,它在这方面与现代三星 SSD 中的三核 ARM CPU 没有什么不同。如果您的意思是“用可以执行任意代码的东西替换整个固件”,请考虑有多少 Apple 产品允许您为主应用处理器执行此操作,更不用说外围处理器了。
  • 我不确定触控栏是如何工作的,所以我不确定它是哪一个,但我猜它必须是第二个,因为 Kali 没有触控驱动程序酒吧。我知道 Apple 默认不这样做,但由于操作系统可能能够发现额外的 CPU,它可能能够发送低级处理器指令,而不是通过 Apple 的接口发送指令。

标签: x86 arm 64-bit cpu-architecture arm64


【解决方案1】:

我认为(有大量的软件工程繁忙工作,但我认为没有不可逾越的障碍)您可以在混合了 ARM + x86 内核的假设缓存一致机器上运行单个 ARM + x86 Linux 内核,例如。

这些不存在;同一系统中不同架构的多个 CPU 总是在做不同的工作,并连接到不同的 RAM,并通过某些总线(如 SATA 或 PCIe)进行通信。 我正在回答这个问题,因为它是唯一有趣/不平凡的问题。

整个系统将共享一个共享内存池,因此内存本质上将在 ARM 和 x86 进程之间竞争共享,而不必对其进行静态分区。页面缓存(又名磁盘缓存)也将与其他缓存(如 VFS 目录条目/inode)一起共享。

内核中的大多数 CPU 内部交互只是通过写入内存并等待另一个内核上的内核代码注意到它来完成。 (例如,如果一个进程启动一个新线程并继续运行,内核只是将该新任务放在任务列表中,另一个正在运行调度程序的内核会注意到它。启动一个新线程不会导致当前内核寻找一个线程运行的核心,而不是核心查看任务列表并选择下一步要做的事情。)

所以只要缓存一致的共享内存正常工作,并且 x86 和 ARM 进程可以通过内存屏障等相互同步,我不明白为什么理论上不可能。

驱动程序已经必须在 SMP 系统上工作,所以只要锁定正常工作以排除其他线程(无论它们是 ARM 还是 x86),一切都应该工作。

你需要:

  • 内核中的函数指针。每个内核函数指针都需要有 x86 和 ARM 版本。 Linux 大量使用函数指针来分派到正确的驱动程序,例如一个文件系统。废话,我在写完剩下的大部分答案后才想到这个,它可能是一个展示者。我可以想象使用 C++ 编译器来编译内核,因此您可以用模板包装器替换每个结构中的函数指针,该包装器可以容纳两个指针,并且取消引用为体系结构采用正确的指针。但是获取函数的地址来将函数指针存储到结构中意味着 ARM 代码需要知道要分配的正确 x86 指针是什么,反之亦然。

    或者也许如果你疯了,你可以设置内存映射和二进制布局,所以 x86 内核在 ARM 内核看到的相同虚拟地址上看到函数的 x86 版本该功能的ARM版本。您只需要它用于获取地址的函数,但这听起来很疯狂,并且考虑到不同的体系结构将具有不同的机器代码大小相同的功能。

    使用不太灵活的内核,没有将这么多函数指针放入不同文件系统的操作结构中,这会更容易。

    也许您可以拥有每个 ops 结构的 ARM 和 x86 版本,而编写者必须同时设置这两个版本,但读者只会阅读他们想要的那个。我认为它们不经常设置,主要是在安装新 FS 或插入新设备时。

  • 所有结构布局都必须兼容(可能需要大量工作才能实现,或者可能只是通过调整 ABI 获得一些编译器帮助)。

  • 调度程序需要知道它应该只在 ARM 内核上运行 ARM 进程,而在 x86 内核上运行 x86 进程。

  • 系统需要能够以某种方式启动,并将从相同源构建的两个内核映像加载到内存中。这将是主要挑战,因为可能存在关于内核所在物理/虚拟地址的假设。引导过程必须加载内核代码的两份副本,但只有一份只读数据和静态非- 恒定数据。 (而且这两段代码都必须有所有这些东西的正确地址)。

  • 内存管理:ARM 和 x86 使用不同的页表格式。读取 ARM 进程的/proc/<pid>/maps 的 x86 进程可能会导致内核查看页表以查找其他体系结构的进程。 (或者也许 Linux 以映射开始/长度格式以及实际页表中的格式保存此信息。)不过,我可以想象这是一个问题。

    如果由于加载了两个不同的版本而违反了关于内核代码所在位置的假设,那么管理系统范围内存池的内核也可能很棘手。

  • 线程:如果要将系统中的所有 x86 + ARM 内核用于共享内存任务,则必须使用映射某些共享内存的两个进程来完成。另一种方法是编写一个新的系统调用,让 x86 进程启动一个 ARM 线程,这与内核的工作方式相同,但 this 可能需要大量工作。这绝对是分离页表格式问题的困扰,因为进程中的所有线程通常共享同一个页表。

  • 内存屏障宏等必须以与运行在其他架构的内核上的代码同步的方式实现。大概 x86 内核仍将遵循 x86 内存模型,其中存储成为在程序顺序等方面全局可见(请参阅 标签 wiki 以获取有关 x86 内存模型的更多链接)。

    同样,ARM 内核将遵循通常的 ARM 内存模型,因此如果它们不使用屏障或获取负载,它们的负载可能会变得无序全局可见,无论生成数据的内核是 ARM 还是x86。

    内存排序是关于内核自己在其私有 L1 缓存上的操作的顺序(与系统中的所有其他数据缓存一致)。存储缓冲区允许不可见的重新排序,但是一旦将某些内容写入 L1 缓存,无论谁在读取它,它都是全局可见的。这就是缓存一致的含义。

    所以问题是任何同步习惯用法是否依赖于关于另一个线程的假设,如果它使用不同的内存模型,这可能不是真的。例如由 ARM 内核获取的锁需要从临界区中排除 x86 线程,反之亦然。我认为这应该主要工作,但这是我迄今为止想到的一个我不确定的领域。它可能需要对一些 Linux inline-asm 宏进行调整。 Linux 将其中的大部分抽象出来供内核的架构独立部分使用,因此它非常适合在需要时使smp_wmb()(写内存屏障)更强大。

【讨论】:

  • 所以真的不值得任何人花时间。
  • “只要缓存一致的共享内存正常工作……” - 呵呵……给定缓存架构、内存排序模型等,让仅是物理细节,如实际的一致性信令协议,要达到这一点,您基本上必须为此特定目的从头开始设计一个或两个 CPU 微架构。那时,如果你真的需要运行一些 ARM 代码,那么在更多的 x86 内核上模拟它可能更现实。不过,一个有趣的想法是,如果具有 Transmeta 风格 CPU 的系统可以在内核之间运行不同的翻译层......
  • @GabrielSouthern 有趣!有趣的是,如果您将 x86 排除在外,只想象 Thumb/Alpha ISA 组合,那么看看 ARMv8-A 并眯起眼睛……
猜你喜欢
  • 1970-01-01
  • 2017-08-20
  • 1970-01-01
  • 2012-03-25
  • 2015-08-19
  • 2021-02-12
  • 1970-01-01
  • 2015-04-16
  • 1970-01-01
相关资源
最近更新 更多