- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在启动后环境(无操作系统)中,如何使用 BSP(第一核/处理器)为 AP(所有其他核/处理器)创建 IPI?本质上,当从一个内核开始时,如何唤醒并为其他内核设置指令指针?
最佳答案
警告:我在这里假设是 80x86。如果不是 80x86 那么我不知道 :-)
首先需要找出其他CPU的数量以及它们的APIC ID是什么,并确定本地APIC的物理地址。为此,您需要解析 ACPI 表(请参阅 ACPI 规范中的 MADT/APIC)。如果您找不到有效的 ACPI 表(例如计算机太旧),则有一个较旧的“多处理器规范”定义了自己的表,其中包含相同的信息。请注意,现在不推荐使用“多处理器规范”(并且有些计算机带有虚拟多处理器表),这就是您需要首先检查 ACPI 表的原因。
下一步是确定您拥有什么类型的本地 APIC。有 3 种情况 - 旧的外部“82489DX”本地 APIC(未内置于 CPU 本身)、xAPIC 和 x2APIC。
首先检查 CPUID 以确定本地 APIC 是否为 x2APIC。如果是,您有 2 个选择 - 您可以使用 x2APIC,或者您可以使用“xAPIC 兼容模式”。对于“xAPIC 兼容模式”,您只能使用 8 位 APIC ID,并且无法支持具有大量 CPU(例如 255 个或更多 CPU)的计算机。我建议使用 x2APIC(即使您不关心具有大量 CPU 的计算机),因为它的速度更快。如果您确实使用 x2APIC 模式,那么您需要将本地 APIC 切换到此模式。
否则,如果不是 x2APIC,则读取本地 APIC 的版本寄存器。如果本地 APIC 的版本是 0x10 或更高,则它的 xAPIC,如果它是 0x0F 或更低,那么它是外部“82489DX”本地 APIC。
旧的外部“82489DX”本地 APIC 用于 80486 和更旧的计算机,这些非常罕见(它们在 20 年前非常罕见,然后大多数都死了和/或被替换并丢弃了)。因为使用不同的序列来启动其他 CPU,并且因为具有这些本地 APIC 的计算机非常罕见(例如,您可能永远无法测试您的代码),所以不费心支持这些计算机是很有意义的。如果您完全支持这些旧计算机;如果本地 APIC 是“82489DX”,我建议将它们视为“仅单 CPU”,并且根本不启动任何其他 CPU。出于这个原因,我不会在这里描述用于启动它们的方法(如果你好奇的话,它在英特尔的“多进程规范”中有描述)。
对于 xAPIC 和 x2APIC,启动另一个 CPU 的顺序本质上是相同的(只是访问本地 APIC 的方式不同 - MSR 或内存映射)。我建议使用(例如)函数指针来隐藏这些差异;以便以后的代码可以通过调用“发送IPI”函数。函数指针而不关心本地 APIC 是 x2APIC 还是 xAPIC。
要真正启动另一个 CPU,您需要向它发送一系列 IPI(处理器间中断)。英特尔的方法是这样的:
Send an INIT IPI to the CPU you're starting
Wait for 10 ms
Send a STARTUP IPI to the CPU you're starting
Wait for 200 us
Send another STARTUP IPI to the CPU you're starting
Wait for 200 us
Wait for started CPU to set a flag (so you know it started)
If flag was set by other CPU, other CPU was started successfully
Else if time-out, other CPU failed to start
total_CPUs++;
的操作,那么每个 CPU 可能会执行两次。要避免此问题,您可以添加额外的同步(例如,其他 CPU 在继续之前等待第一个 CPU 设置“我知道您已启动”标志)。英特尔方法的第二个问题是测量这些延迟。通常,操作系统启动其他 CPU,然后计算弄清楚 CPU 支持哪些功能以及之后存在哪些硬件,并且没有精确的计时器设置来准确测量那些 200 us 的延迟。
Send an INIT IPI to the CPU you're starting
Wait for 10 ms
Send a STARTUP IPI to the CPU you're starting
Wait for started CPU to set a flag (so you know it started) with a short timeout (e.g. 1 ms)
If flag was set by other CPU, other CPU was started successfully
Else if time-out
Send another STARTUP IPI to the CPU you're starting
Wait for started CPU to set a flag with a long timeout (e.g. 200 ms)
If flag was set by other CPU, other CPU was started successfully
Else if time-out, other CPU failed to start
If CPU started successfully
Set flag to tell other CPU it can continue
CS = vector * 256
和
IP = 0
.矢量字段是 8 位的,因此您可以使用的最高起始地址是 0x000FF000(实模式下为 0xFF00:0x0000)。然而,这是传统的 ROM 区域(实际上起始地址必须更低)。通常,您会将一小段启动代码复制到合适的地址中;启动代码处理同步(例如设置另一个 CPU 可以看到的“我开始”标志并等待被告知可以继续),然后执行诸如启用保护/长模式和在跳转到条目之前设置堆栈之类的事情指向操作系统的正常代码。这段启动代码叫做“AP CPU启动蹦床”。这也是让“并行启动”有点复杂的原因;因为每个正在启动的 CPU 都需要自己/单独的同步标志和堆栈;并且因为这些东西通常是用蹦床中的变量实现的(例如
mov esp,[cs:stackTop]
),这意味着最终会有多个蹦床。
关于assembly - 如何使用 APIC 创建 IPI 以唤醒 x86 程序集中的 SMP 的 AP?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16364817/
前言: 有时候,一个数据库有多个帐号,包括数据库管理员,开发人员,运维支撑人员等,可能有很多帐号都有比较大的权限,例如DDL操作权限(创建,修改,删除存储过程,创建,修改,删除表等),账户多了,管理
所以我用 Create React App 创建并设置了一个大型 React 应用程序。最近我们开始使用 Storybook 来处理和创建组件。它很棒。但是,当我们尝试运行或构建应用程序时,我们不断遇
遵循我正在创建的控件的代码片段。这个控件用在不同的地方,变量也不同。 我正在尝试编写指令来清理代码,但在 {{}} 附近插入值时出现解析错误。 刚接触 Angular ,无法确定我错过了什么。请帮忙。
我正在尝试创建一个 image/jpeg jax-rs 提供程序类,它为我的基于 post rest 的 Web 服务创建一个图像。我无法制定请求来测试以下内容,最简单的测试方法是什么? @POST
我一直在 Windows 10 的模拟器中练习 c。后来我改用dev C++ IDE。当我在 C 中使用 FILE 时。创建的文件的名称为 test.txt ,而我给出了其他名称。请帮助解决它。 下面
当我们创建自定义 View 时,我们将 View 文件的所有者设置为自定义类,并使用 initWithFrame 或 initWithCode 对其进行实例化。 当我们创建 customUITable
我正在尝试为函数 * Producer 创建一个线程,但用于创建线程的行显示错误。我为这句话加了星标,但我无法弄清楚它出了什么问题...... #include #include #include
今天在做项目时,遇到了需要创建JavaScript对象的情况。所以Bing了一篇老外写的关于3种创建JavaScript对象的文章,看后跟着打了一遍代码。感觉方法挺好的,在这里与大家分享一下。 &
我正在阅读将查询字符串传递给 Amazon 的 S3 以进行身份验证的文档,但似乎无法理解 StringToSign 的创建和使用方式。我正在寻找一个具体示例来说明 (1) 如何构造 String
前言:我对 C# 中任务的底层实现不太了解,只了解它们的用法。为我在下面屠宰的任何东西道歉: 对于“我怎样才能开始一项任务但不等待它?”这个问题,我找不到一个好的答案。在 C# 中。更具体地说,即使任
我有一个由一些复杂的表达式生成的 ILookup。假设这是按姓氏查找人。 (在我们简单的世界模型中,姓氏在家庭中是唯一的) ILookup families; 现在我有两个对如何构建感兴趣的查询。 首
我试图创建一个 MSI,其中包含 和 exe。在 WIX 中使用了捆绑选项。这样做时出错。有人可以帮我解决这个问题。下面是代码: 错误 error LGH
在 Yii 中,Create 和 Update 通常使用相同的形式。因此,如果我在创建期间有电子邮件、密码、...other_fields...等字段,但我不想在更新期间专门显示电子邮件和密码字段,但
上周我一直在努力创建一个给定一行和一列的 QModelIndex。 或者,我会满足于在已经存在的 QModelIndex 中更改 row() 的值。 任何帮助,将不胜感激。 编辑: QModelInd
出于某种原因,这不起作用: const char * str_reset_command = "\r\nReset"; const char * str_config_command = "\r\nC
现在,我有以下由 original.df %.% group_by(Category) %.% tally() %.% arrange(desc(n)) 创建的 data.frame。 DF 5),
在今天之前,我使用/etc/vim/vimrc来配置我的vim设置。今天,我想到了创建.vimrc文件。所以,我用 touch .vimrc cat /etc/vim/vimrc > .vimrc 所
我可以创建一个 MKAnnotation,还是只读的?我有坐标,但我发现使用 setCooperative 手动创建 MKAnnotation 并不容易。 想法? 最佳答案 MKAnnotation
在以下代码中,第一个日志语句按预期显示小数,但第二个日志语句记录 NULL。我做错了什么? NSDictionary *entry = [[NSDictionary alloc] initWithOb
我正在使用与此类似的代码动态添加到数组; $arrayF[$f+1][$y][$x+1] = $value+1; 但是我在错误报告中收到了这个: undefined offset :1 问题:尝试创
我是一名优秀的程序员,十分优秀!