如果一个系统中有两个处理器,如果第二个处理器具有不同的架构,是否可以控制它?

If there are two processors in one system, could the second processor be controlled if it has a different architecture?

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

我认为(有大量的软件工程繁忙工作,但没有我能看到的table障碍)你可以运行一个单一的ARM + x86 Linux内核例如,混合了 ARM + x86 内核的假想缓存一致性机器。

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

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

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

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

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

你需要:

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

    或者也许如果你疯了,你可以设置内存映射和二进制布局,这样 x86 内核在相同的虚拟地址看到函数的 x86 版本ARM 内核看到该函数的 ARM 版本。您只需要为已获取其地址的函数使用它,但这听起来很疯狂,并且需要大量操作才能使链接器留下足够的填充,因为不同的体系结构将具有不同的机器代码大小同样的功能。

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

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

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

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

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

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

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

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

  • 内存屏障宏等必须以与代码同步的方式实现 运行ning 在其他架构的核心上。据推测,x86 内核仍将遵循 x86 内存模型,其中存储在程序顺序等方面变得全局可见(有关 x86 内存模型的更多信息,请参见 标签 wiki 的链接)。

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

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

    所以问题是任何同步习惯用法是否依赖于对另一个线程的假设,如果它使用不同的内存模型,这可能不是真的。 例如ARM 内核获取的锁需要从临界区中排除 x86 线程,反之亦然。我认为这应该是最有效的,但这是迄今为止我不确定的一个领域。它可能需要调整一些 Linux inline-asm 宏。 Linux 抽象了很多这样的东西供内核的架构独立部分使用,因此它设置得很好,可以在需要时使 smp_wmb()(写内存屏障)更强大,例如。