发送到未处于等待SIPI状态的活动AP的启动IPI会发生什么情况 [英] What happens to a Startup IPI sent to an Active AP that is not in a Wait-for-SIPI state

查看:155
本文介绍了发送到未处于等待SIPI状态的活动AP的启动IPI会发生什么情况的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在先前的 Stackoverflow答案中玛格丽特·布鲁姆(Margaret Bloom)说:

In a previous Stackoverflow answer Margaret Bloom says:

唤醒AP

这是通过向所有AP插入INIT-SIPI-SIPI(ISS)序列来实现的.

This is achieved by inssuing a INIT-SIPI-SIPI (ISS) sequence to the all the APs.

将发送ISS序列作为目的地的BSP 简写全部排除自我,从而针对所有AP.

The BSP that will send the ISS sequence using as destination the shorthand All excluding self, thereby targeting all the APs.

所有CPU都会忽略SIPI(启动处理器间中断) 它们在收到时被唤醒,因此第二个SIPI是 如果第一个足以唤醒目标处理器,则忽略.它 出于兼容性原因,英特尔建议您这样做.

A SIPI (Startup Inter Processor Interrupt) is ignored by all the CPUs that are waked by the time they receive it, thus the second SIPI is ignored if the first one suffices to wake up the target processors. It is advised by Intel for compatibility reason.

多年来,我一直在进行多处理代码,对硬件的观察发现,在某些处理器上,它似乎与所陈述的有所不同.我很确定我观察到应用程序处理器(AP)在收到启动IPI时就对其指令指针进行了修改,即使它处于活动状态(不在等待启动IPI"中).

I've been doing multi processing code for years and my observation of hardware has been that on some processors it seems different than stated. I'm pretty sure I've observed Application Processors (AP) have their Instruction Pointer modified upon receipt of Startup IPI even when it was active (not in a Wait-for-Startup-IPI).

是否有任何Intel文档说明了AP在未处于等待启动IPI状态时对启动IPI的接收会做什么,或者记录了未定义的行为?我似乎在权威答案. >英特尔软件文档手册或补充英特尔文档最小引导加载程序用于英特尔®架构.

Is there any Intel documentation that states what an AP will do upon a receipt of a Startup IPI when not in a Wait-for-Startup-IPI state, or documents the behaviour as undefined? I can't seem to find a definitive answer in the Intel Software Documentation Manuals or the supplementary Intel document Minimal Boot Loader for Intel® Architecture.

通常,我会假设AP处于 active 状态(而非处于Wait-for-启动IPI状态).

Generally I write the initialization code to initialize and start an AP by assuming that the AP may get a SIPI and have its Instruction Pointer reset while in an active state (not in a Wait-for-Startup-IPI state).

我正在尝试确定玛格丽特·布鲁姆(Margaret Bloom)的声明的准确性,该声明先前被唤醒的AP将忽略第二个启动IPI.

I'm trying to determine the accuracy of Margaret Bloom's statement that a second Startup IPI will be ignored by an AP that has been previously awoken.

推荐答案

我认为我的陈述是正确的,最多可发现错误.

我并不是说越野车硬件应该被忽略,但是必须首先评估它们的影响.
我想提醒读者,尽管我对此事有自己的立场,但我希望这个答案尽可能保持中立.
为了完全满足此目的,我尝试为我的陈述提供资源.

I consider my statement correct, up to bugs.

I don't claim that buggy hardware should be ignored but that their impact must first evaluated.
I'd like the remind the reader that while I have an opinionated position on the matter, I wanted this answer to be as neutral as possible.
To full fill this purpose I tried to provide sources for my statements.

虽然我愿意相信其他用户的体验,但我不能仅仅依靠记忆(因为无法验证他们的信念) 1 ,我期待有人改正我引用的带有证明的声明.

While I do trust other users experiences I cannot base my belief on memories alone (for they cannot be verified)1 and I'm looking forward for someone to correct my quoted statement with proofs.

我理解这是一个不受欢迎的观点,我希望它不会完全被认为是错误的.

I understand this is an unpopular view, I hope it just won't pass as totally wrong.

首先,像往常一样,这一切都归结为标准.英特尔在手册中记录了其CPU的MP行为时,又走了一步,做出了适当的维基百科:

First of all, as usual with computers it all boils down to standards. While Intel documents the MP behaviour of their CPUs in the manuals, there went a step further and made a proper MultiProcessor specification.
The importance of this specification is its role in the industry, this is not how Intel's CPUs work, this is, as far as i known, the only x86 SMP industry reference.
AMD and Cyrix pushed the OpenPIC specification but quoting Wikipedia:

然而,OpenPIC尚未发布x86主板.[3] OpenPIC在x86市场上失败之后,AMD为其AMD Athlon和更高版本的处理器许可了Intel APIC体系结构.

No x86 motherboard was released with OpenPIC however.[3] After the OpenPIC's failure in the x86 market, AMD licensed the Intel APIC Architecture for its AMD Athlon and later processors.

在MP规范的附录B4中,出现该行

In the Appendix B4 of the MP-specification is present the line

如果 目标处理器在RESET或INIT后立即处于停止状态,STARTIP会导致它 离开该状态并开始执行.效果是将CS:IP设置为VV00:0000h.

If the target processor is in the halted state immediately after RESET or INIT, a STARTUP IPI causes it to leave that state and start executing. The effect is to set CS:IP to VV00:0000h.

如评论中所述,我将 if 解析为更强的* iif .

As noted in the comment I've parsed the if as a stronger *iif.

不幸的是,如前所述,引用的句子只是一个充分的条件.因此,它不能用于推断正在运行的CPU上SIPI的行为.

Unfortunately, the quoted sentence, as stated, is only a sufficient condition. So it cannot be used to deduce the behaviour of a SIPI on a running CPU.

但是我个人认为这是一个错误,该规范作者的意图是使用SIPI唤醒 wait-for-SIPI 状态.

However I personally believe this is a mistake, the intent of the authors of the specification is to use the SIPI to wake up a CPU in the wait-for-SIPI state.

SIPI是在集成APIC出现后专门引入的,并且对INIT IPI进行了修订,以管理AP的启动.
SIPI对BSP无效(根据Intel的手册,BSP永远不会进入 wait-for-SIPI 状态),很明显,应该对运行没有影响. CPU.
除了不可屏蔽并且不需要启用LAPIC之外,SIPI的有用之处在于,它避免了从复位向量运行以及避免AP的热启动标志的麻烦.

The SIPI was specifically introduced with the advent of integrated APICs, along with a revision of the INIT IPI, to manage the booting of the APs.
The SIPI has no effect on the BSP (which never enters the wait-for-SIPI state according to Intel's manuals) and it's clear that is should have no affect on a running CPU.
The usefulness of the SIPI, besides being non-maskeable and not requiring the LAPIC to be enabled, is that is avoid running from the reset vector and the need for the warm boot flag for APs.

从设计的角度来看,让SIPI在运行的CPU上起作用是没有意义的. CPU始终以INIT IPI作为第一个IPI重启.

It makes no sense, from a design perspective, to let SIPI act on running CPUs. CPUs are always restarted with an INIT IPI as the first IPI.

因此,我有信心将引用的陈述口语化为英语,并默示同意这也是必要条件.

So, I'm confident in parsing the quoted statement as colloquial English with the tacit agreement that it is also a necessary condition.

我相信这会在唤醒的CPU上设置SIPI的官方行为,即忽略它们.

I believe this sets the official behaviour of SIPI on a woke-up CPU, namely to ignore them.

事实1:所有主要的x86制造商都遵循行业标准的MP规范,尽管模棱两可,但其目的是设置SIPI的行为.

奔腾规格更新似乎证实了这一点,至少对于奔腾(可能是后来的英特尔世代来说,可能包括AMD,因为他们已经从英特尔那里购买了LAPIC的许可证):

Page 98 of the Pentium Spec Update seems to confirm that, at least for the Pentium (an presumably for later Intel generations, which may include AMDs since they have bought a license for the LAPIC from Intel):

如果随后将INIT IPI发送到停止的升级组件,它将被锁存并保持待处理状态,直到出现 收到启动IPI.从收到启动IPI的时间起,CPU将响应其他INIT IP1 但将忽略任何STARTUP IPls.直到RESET断言或一个新的启动IPl,它才会响应未来的STARTUP IPls. INIT断言(INIT引脚或INIT IPI)再次发生.

If an INIT IPI is then sent to the halted upgrade component, it will be latched and kept pending until a STARTUP IPI is received. From the time the STARTUP IPI is received the CPU will respond to further INIT IPls but will ignore any STARTUP IPls. It will not respond to future STARTUP IPls until a RESET assertion or an INIT assertion (INIT Pin or INIT IPI) happens again.

75、90和100 MHz奔腾处理器用作主处理器时,将永远不会响应 随时启动IPI.它将忽略启动IPI,但不起作用.

The 75-, 90, and 100-MHz Pentium processors, when used as a primary processor, will never respond to a STARTUP IPI at any time. It will ignore the STARTUP IPI with no effects.

要关闭处理器,操作系统应仅使用INIT IPI,而决不应使用STARTUP IPls. 在处理器运行后使用.

To shutdown the processors the operating system should only use the INIT IPI, STARTUP IPls should never be used once the processors are running.


这不会解决问题 ,如果存在不忽略后续IPI的CPU.
尽管这个问题仍有待解决,但到目前为止,我们已经将其变成了是否有笨重的 CPU ...?"这个问题.
这是一个巨大的飞跃,因为我们现在可以看到现有的操作系​​统是如何处理它的.


This doesn't settle the question if there are CPUs where subsequent IPIs are not ignored.
While this question is still to be addressed, we have, by now, turned it into the question "Are there buggy CPUs that ... ?".
This is an huge leap-forward because we can now see how existing OSes deal with it.

我不会讨论Windows,虽然我认识到这是一个很大的缺席,但我现在不打算研究Windows二进制文件.
我可以稍后再做.

I won't discuss Windows, while I recognise this is a big absence I'm not in the mood of digging into Windows binaries right now.
I may do it later.

Linux

Linux发送了两个SIPI,但在此循环中看不到任何反馈. 代码在smpboot.c ,我们清楚地看到num_starts设置为2.
我不会讨论LAPIC和82489DX APIC之间的区别,特别是后者没有SIPI 2 .

Linux sends two SIPIs and I don't see any feedback in this loop. The code is in smpboot.c where we clearly see that num_starts is set to 2.
I won't discuss the difference between the LAPIC and the 82489DX APIC, particularly that the latter didn't have SIPI2.

但是,我们可以看到Linux如何遵循Intel的算法,并且第二SIPI对此并不担心.
在循环中,在执行时间num_starts时,会将SIPI发送到目标AP.

We can however see how Linux follow the Intel's algorithm and it is not worried by the second SIPI.
In the loop, executed num_starts time, a SIPI is sent to the target AP.

在评论中指出,蹦床是幂等的,并且Linux是一种同步机制.
这与我的经验不符,Linux当然会在CPU之间同步代码,但是稍后会在AP运行之后的 引导中完成. 实际上,蹦床是AP执行的第一个C代码是

In the comments has been pointed out that the trampoline is idempotent and that Linux as a synchronisation mechanism.
That doesn't match with my experience, of course Linux synchronises code between CPUs but that's done later in the boot after the AP is running.
In fact the trampoline the first C code the AP executes is start_secondary and it doesn't seem idempotent (set_cpu_online is called later in the body, if that counts).

最后,如果程序员想防止出现双重SIPI,他们会尽早放置同步逻辑,以避免以后再处理复杂的情况.
蹦床可以处理中小企业和漏洞修复程序,为什么要在处理SIPI-SIPI问题之前 做到这一点?

Finally, if the programmers wanted to prevent a double SIPI they'd put the synchronisation logic as early as possible to avoid dealing with complex situations later.
The trampoline goes as far as dealing with SME and vulnerabilities fixes, why would one want to do that before dealing with the SIPI-SIPI issue?

这么晚才进行如此严格的检查对我来说是没有意义的.

It makes no sense to me to have such a critical check so late.

免费BSD
我想包括一个BSD操作系统,因为众所周知BSD代码非常干净和健壮.
我能够找到带有免费BSD源的GitHub(非官方)存储库,尽管我对该代码不太自信,但我

Free BSD
I wanted to include a BSD OS because BSD code is known to be very clean and robust.
I was able to found a GitHub (unofficial) repository with the Free BSD source and while I'm less confident with that code I've found the routine that starts an AP in mp_x86.c.

免费的BSD也使用Intel的算法. 令我高兴的是,消息人士还解释了为什么需要第二个SIPI:P5处理器(P54C Pentium系列?)由于存在错误而忽略了第一个SIPI:

Free BSD also uses the Intel's algorithm. To my amusement, the source also explains why there is the need for a second SIPI: the P5 processor (The P54C Pentium family?) did ignore the first SIPI due to a bug:

/*
*接下来,我们进行启动IPI:先前的INIT IPI可能仍然是
*已锁定,(此P5错误)第1次启动将终止
*立即执行,并且先前启动的INIT IPI将继续.或
*先前的INIT IPI已经运行.而此启动IPI将
* 跑.或先前的INIT IPI被忽略.而这个启动IPI
*将运行.
*/

/*
* next we do a STARTUP IPI: the previous INIT IPI might still be
* latched, (P5 bug) this 1st STARTUP would then terminate
* immediately, and the previously started INIT IPI would continue. OR
* the previous INIT IPI has already run. and this STARTUP IPI will
* run. OR the previous INIT IPI was ignored. and this STARTUP IPI
* will run.
*/

我找不到此声明的来源,我唯一的线索是勘误表 Linux似乎已经放弃了对那些老旧的LAPIC的支持.

I was unable to find the source for this statement, the only clue I have is the errata AP11 of the Pentium Specification Update found on an old android (i.e. Linux) kernel.
Today Linux seems to have dropped the support for those old buggy LAPICs.

考虑详细注释,我认为没有必要对代码的幂等性进行检查,直到进行假设性检查为止.
BSD代码的编写清楚地考虑了注释的假设.

Considering the detailed comments I don't see the need to check for the idempotency of the code up to an hypothetical check.
The BSD code is clearly written with the commented assumptions in mind.

事实2:两个主流操作系统并不认为SIPI错误的发生频率足以值得处理.

搜索Internet时,我在 gem5 模拟器中找到了一个标题为 .
显然,他们一开始弄错了,然后修复了它.

While searching the Internet I've found a commit in the gem5 simulator with the title X86: Only recognize the first startup IPI after INIT or reset.
Apparently, they got it wrong at first and then fixed it.

下一步是尝试查找一些在线文档.
我首先在Google Patents中搜索,然后弹出许多有趣的结果(包括APIC ID的分配方式),但关于SIPI,我仅在专利

Next step is trying to find some online documentation.
I first searched in Google Patents and while a lot of interesting results pop up (including how the APIC IDs are assigned), regarding SIPIs I only found this text in the patent Method and apparatus for initiating execution of an application processor in a clustered multiprocessor system:

STARTUP IPI不会引起目标处理器中状态的任何改变(指令指针的更改除外),并且只能在RESET之后,INIT IPI接收或引脚置位后发出一次.

STARTUP IPIs do not cause any change of State in the target processor (except for the change to the instruction pointer), and can be issued only one time after RESET or after an INIT IPI reception or pin assertion.

维基百科将VIA列为唯一仍存在的其他x86制造商..
我尝试查找VIA手册,但是看来它们不是公开的吗?

Wikipedia lists VIA as the only other x86 manufacturer still present..
I tried looking for VIA manuals, but it seems they are not public?

关于过去的制造商,我根本找不到任何生产过的MP CPU.例如. Cyrix 6x86MX 根本没有APIC,因此它们可能仅由外部APIC(不支持SIPI)放置在MP系统中.

About the past manufacturers, I was unable to find if any ever produced MP CPUs at all. E.g. Cyrix 6x86MX didn't have an APIC at all, so they may have been put in a MP system only by an external APIC (which couldn't support SIPIs).

下一步是查看AMD和Intel勘误的 all ,看看SIPI是否有问题.
但是,勘误表是bug,因此问题变成了寻找不存在(即是否存在bug的LAPIC?)证据的搜索,这很难找到(原因是:错误很难找到,并且有许多微架构).

Next step would be to look at all of the AMD and Intel errata and see if there's something about the SIPIs.
However, errata are bugs and so the question turns into a search for a proof of non-existence (i.e. do bugged LAPICs exist?) which is hard to find (simply because bugs are hard to find and there are many micro-architectures).

我的理解是 P54C ,我已经咨询了勘误表,但在处理SIPI方面一无所获.
但是,要了解勘误的全部后果并非易事.

My understanding is that the first integrated APIC (an LAPIC as known today) shipped with the P54C, I've consulting the errata but found nothing regarding the handling of SIPIs.
However understanding the errata in their full consequences is not trivial.

然后我转到了奔腾Pro勘误(这是下一个上一个P6),并发现对SIPI的处理不正确,尽管不完全是我们要查找的内容:

I've then moved to the Pentium Pro Errata (which is the next uarch, the P6) and found an incorrect handling of the SIPIs though not exactly what we are looking for:

3AP. STARTUP_IPI-STARTUP_IPI序列之后的INIT_IPI可能会导致

要在0h执行的AP **
问题:MP规范指出,要唤醒应用处理器(AP),即处理器 中断序列INIT_IPI,STARTUP_IPI,STARTUP_IPI应该发送到该处理器.在奔腾上 Pro处理器的INIT_IPI,STARTUP_IPI序列也将起作用.但是,如果INIT_IPI,STARTUP_IPI, STARTUP_IPI序列发送到AP,APIC逻辑中可能会发生内部竞争情况,从而导致 处理器处于错误状态.在这种状态下,操作将是正确的,但是如果将另一个INIT_IPI发送到 处理器,处理器将不会按预期停止执行,而是从线性地址开始执行 0小时为了使竞争条件导致此错误状态,系统的核心总线时钟比必须为5:2 或更高.

AP to Execute at 0h**
PROBLEM: The MP Specification states that to wake up an application processor (AP), the interprocessor interrupt sequence INIT_IPI, STARTUP_IPI, STARTUP_IPI should be sent to that processor. On the Pentium Pro processor, an INIT_IPI, STARTUP_IPI sequence will also work. However, if the INIT_IPI, STARTUP_IPI, STARTUP_IPI sequence is sent to an AP, an internal race condition may occur in the APIC logic which leaves the processor in an incorrect state. Operation will be correct in this state, but if another INIT_IPI is sent to the processor, the processor will not stop execution as expected, and will instead begin execution at linear address 0h. In order for the race condition to cause this incorrect state, the system’s core to bus clock ratio must be 5:2 or greater.

IMPLICATION :如果系统使用的核心总线时钟比为5:2或更高,并且序列为INIT_IPI, STARTUP_IPI,在APIC总线上生成STARTUP_IPI,以唤醒AP,然后在以后的某个时间 另一个INIT_IPI发送到处理器,该处理器可能尝试在线性地址0h执行,并且将 执行随机操作码.某些操作系统在尝试关闭操作系统时会生成此序列. 使系统停机,以及在多处理器系统中,使处理器脱机后可能会挂起.看到的效果会 如果退出后选择了关机并重新启动"或同等功能,则操作系统可能无法重新启动系统 操作系统.如果操作系统使用户能够使用INIT_IPI使AP脱机 (英特尔尚未确定当前具有此功能的任何操作系统),不应将此选项设置为 用过的.

IMPLICATION: If a system is using a core to bus clock ratio of 5:2 or greater, and the sequence INIT_IPI, STARTUP_IPI, STARTUP_IPI is generated on the APIC bus to wake up an AP, and then at some later time another INIT_IPI is sent to the processor, that processor may attempt to execute at linear address 0h, and will execute random opcodes. Some operating systems do generate this sequence when attempting to shut the system down, and in a multiprocessor system, may hang after taking the processors offline. The effect seen will be that the OS may not restart the system if ‘shutdown and restart’ or the equivalent is selected upon exiting the operating system. If an operating system gives the user the capability to take an AP offline using an INIT_IPI (Intel has not identified any operating systems which currently have this capability), this option should not be used.

WORKAROUND :BIOS代码应执行一个STARTUP_IPI以唤醒应用程序处理器. 但是,操作系统将按照建议发出INIT_IPI,STARTUP_IPI,STARTUP_IPI序列 在MP规范中.在以下情况下,BIOS代码可能包含针对此错误的解决方法: 奔腾Pro处理器芯片的C0或后续步骤.没有解决方法可用于B0步进 奔腾Pro处理器.

WORKAROUND: BIOS code should execute a single STARTUP_IPI to wake up an application processor. Operating systems, however, will issue an INIT_IPI, STARTUP_IPI, STARTUP_IPI sequence, as recommended in the MP specification. It is possible that BIOS code may contain a workaround for this erratum in systems with C0 or subsequent steppings of Pentium Pro processor silicon. No workaround is available for the B0 stepping of the Pentium Pro processor.

状态:有关受影响的步骤,请参阅本节开头的摘要更改表".

STATUS: For the steppings affected see the Summary Table of Changes at the beginning of this section.

此AP3勘误之所以有趣,是因为:

This AP3 erratum is interesting because:

  1. 它确认INIT-SIPI序列足以启动AP.从MP规范和Free BSD代码可以明显看出这一点.
  2. 这可能会导致类似于重新启动的行为.该错误将使 INIT IPI (在INIT-SIPI-SIPI序列之后)在0h(线性,大概在初始化之后)重新启动AP.
    如果BIOS使用INIT-SIPI-SIPI来使用AP,然后操作系统尝试再次使用该序列,则第一个INIT将启动AP.
    但是,除非LAPIC处于任何可以接受任何SIPI的损坏状态,否则这不会导致可预测的行为.
  1. It confirms that an INIT-SIPI sequence is enough to startup an AP. This was evident from the MP specification and from the Free BSD code.
  2. It may lead to a behaviour similar to a restart. The bug will make an INIT IPI (after the INIT-SIPI-SIPI sequence) restart the AP at 0h (linear, presumably after the initialisation).
    If the BIOS uses the INIT-SIPI-SIPI to use the APs and later the OS attempts to use that sequence again, the first INIT will start the AP.
    However, this won't lead to a predictable behaviour unless the LAPIC is left in a corrupted state where any SIPI will be accepted.

很有趣,在同一勘误表中甚至存在一个导致相反行为"的错误: 8AP.在INIT#或INIT_IPI之后,AP不响应STARTUP_IPI 在低功耗模式下

Funny enough, in the same errata there is even a bug causing "the opposite behaviour": 8AP. APs Do Not Respond to a STARTUP_IPI After an INIT# or INIT_IPI in Low Power Mode

我还检查了Pentium II,Pentium II Xeon,Pentium III,Pentium 4勘误表,没有发现关于SIPI的新知识.

I've also checked the Pentium II, Pentium II Xeon, Pentium III, Pentium 4 errata and found nothing new about SIPIs.

据我了解,首款支持SMP的AMD处理器是基于Palomino uarch的Athlon MP.
我检查了Athlon MP的修订指南,却一无所获,在此列表中检查了修订,并且一无所获.

To my understanding, the first AMD processor capable of SMP was the Athlon MP based on the Palomino uarch.
I've checked the revision guide for the Athlon MP and found nothing, checked the revisions in this list and found nothing.

不幸的是,我对非AMD非英特尔x86 CPU的经验很少.我找不到哪个二级制造商包括LAPIC.

Unfortunately I have little experience with non AMD non Intel x86 CPUs. I was unable to find which secondary manufactures included an LAPIC.

事实3:很难找到非AMD/Intel制造商的官方文档,而且勘误也不容易找到.没有勘误表包含与正在运行的处理器上接受SIPI有关的错误,但是存在大量的LAPIC错误,使这些错误的存在成为可能.

最后一步将是硬件测试.
尽管此测试不能排除其他行为的出现,但至少是有记录的(cr脚的)代码.
记录的代码之所以好,是因为它可以被其他研究人员用来重复实验,可以对其进行仔细检查以发现错误并构成证明.
简而言之,这是科学的.

Final step would be a hardware test.
While this test cannot rule out the presence of other behaviour, at least is documented (crappy) code.
Documented code is good because it can be used to repeat an experiment by other researchers, it can be scrutinised for bugs and constitute a proof.
In short, it is scientific.

从未见过一个随后的SIPI重新启动它的CPU,但这没关系,因为只有一个bugy CPU足以确认该bug的存在.
我太年轻,太贫穷,太人性了,无法对所有MP CPU进行广泛的,没有错误的分析.
因此,我做了一个测试并运行它.

I have never seen a CPU where subsequent SIPIs restarted it but this doesn't matter because it suffices to have a single buggy CPU to confirm the presence of the bug.
I'm too young, too poor and too human to have conducted an extensive, bug-free, analysis of all the MP CPUs.
So, instead, I made a test and run it.

事实4:威士忌湖,哈斯韦尔,卡比湖和常春藤桥都忽略了随后的SIPI.
欢迎其他人在AMD和更旧的CPU上进行测试.
同样,这并不构成证明,但正确地确定事件的状态很重要.
我们拥有的数据越多,我们所获得的错误的知识就越准确.

Fact 4: Whiskey lake, Haswell, Kaby lake and Ivy Bridge all ignore subsequent SIPIs.
Other people are welcome to test on AMD's and older CPUs.
Again this doesn't constitute a proof but it's important to frame the state of the matter correctly.
The more data we have the more accurate knowledge of the bug we get.

测试包括引导AP,并使它们递增计数器并进入无限循环(使用jmp $hlt,结果相同).
同时,BSP将每隔 n 秒发送一次SI​​PI,其中 n 至少为2(但由于计时机制非常不精确,所以可能更多),并打印计数器.

The test consist in bootstrapping the APs and making them increment a counter and enter an infinite loop (either with jmp $ or with hlt, the result is the same).
Meanwhile the BSP will send a SIPI each n seconds, where n is at least 2 (but it may be more due to the very imprecise timing mechanism), and print the counter.

如果计数器停留在 k -1,其中 k 是AP的数量,则次要SIPI将被忽略.

If the counter stays at k-1, where k is the number of APs, then the secondary SIPI are ignored.

有一些技术细节需要解决.

There are some technical details to address.

首先,引导加载程序是旧版(不是UEFI),我不想读取另一个扇区,因此我希望它适合512字节,因此我在BSP和AP之间共享了引导顺序.

First, the bootloader is legacy (not UEFI) and I didn't want to read another sector so I wanted it to fit in 512 bytes and so I shared the booting sequence between the BSP and the APs.

第二,某些代码必须仅由BSP执行,但是必须在进入保护模式(例如,视频模式设置)之前执行,因此我使用了标志(init)而不是检查IA32_APIC_BASE_MSR寄存器中的BSP标志(稍后完成以使AP与BSP分叉).

Second, some code must be executed only by the BSP but before entering in protected mode (e.g. video mode setting) so I used a flag (init) instead of checking the BSP flag in the IA32_APIC_BASE_MSR register (which is done later to diverge the APs from the BSP).

第三,我采取了一些捷径. SIPI在8000h引导CPU,因此我在这里远远跳到0000h:7c00h.定时是通过端口80h技巧完成的,虽然不十分精确,但足够了. GDT使用空条目.计数器的顶部下方印有几行,以避免被某些显示器裁切.

Third, I've took some shortcuts. The SIPI bootups the CPU at 8000h so I put a far jump there to 0000h:7c00h. The timing is done with the port 80h trick and it is very imprecise but should suffice. The GDT uses the null entry. The counter is printed a few lines below the top to avoid being cropped by some monitor.

如果将循环修改为包括INIT IPI,则计数器会定期递增.

If the loop is modified to include the INIT IPI, the counter is incremented regularly.

请注意,此代码不受支持.

Please note that this code is without support.

BITS 16
ORG 7c00h

%define IA32_APIC_BASE_MSR 1bh
%define SVR_REG 0f0h
%define ICRL_REG 0300h
%define ICRH_REG 0310h

xor ax, ax
mov ds, ax
mov ss, ax
xor sp, sp      ;This stack ought be enough

cmp BYTE [init], 0
je _get_pm

;Make the trampoline at 8000h
mov BYTE [8000h], 0eah
mov WORD [8001h], 7c00h
mov WORD [8003h], 0000h

mov ax, 0b800h
mov es, ax
mov ax, 0003h
int 10h
mov WORD [es:0000], 0941h

mov BYTE [init], 0

_get_pm:
;Mask interrupts
mov al, 0ffh
out 21h, al
out 0a1h, al

;THIS PART TO BE TESTED
;
;CAN BE REPLACED WITH A cli, SIPIs ARE NOT MASKEABLE
;THE cli REMOVES THE NEED FOR MASKING THE INTERRUPTS AND
;CAN BE PLACED ANYWHERE BEFORE ENTERING PM (BUT LEAVE xor ax, ax
;AS THE FIRST INSTRUCTION)

;Flush pending ones (See Michael Petch's comments)
sti
mov cx, 15
loop $   

lgdt [GDT]
mov eax, cr0
or al, 1
mov cr0, eax
sti

mov ax, 10h
mov es, ax
mov ds, ax
mov ss, ax
jmp 08h:DWORD __START32__

__START32__: 
 BITS 32

 mov ecx, IA32_APIC_BASE_MSR
 rdmsr
 or ax, (1<<11)          ;ENABLE LAPIC
 mov ecx, IA32_APIC_BASE_MSR
 wrmsr

 mov ebx, eax
 and ebx, 0ffff_f000h    ;APIC BASE

 or DWORD [ebx+SVR_REG], 100h

 test ax, 100h
 jnz __BSP__

__AP__: 
 lock inc BYTE [counter]

 jmp $            ;Don't use HLT just in case

__BSP__:
 xor edx, edx 
 mov DWORD [ebx+ICRH_REG], edx 
 mov DWORD [ebx+ICRL_REG], 000c4500h        ;INIT

 mov ecx, 10_000
.wait1:
 in al, 80h
 dec ecx
jnz .wait1 

.SIPI_loop:
 movzx eax, BYTE [counter]
 mov ecx, 100
 div ecx 
 add ax, 0930h
 mov WORD [0b8000h + 80*2*5], ax

 mov eax, edx 
 xor edx, edx
 mov ecx, 10
 div ecx
 add ax, 0930h
 mov WORD [0b8000h + 80*2*5 + 2], ax

 mov eax, edx
 xor edx, edx
 add ax, 0930h
 mov WORD [0b8000h + 80*2*5 + 4], ax

 xor edx, edx 
 mov DWORD [ebx+ICRH_REG], edx 
 mov DWORD [ebx+ICRL_REG], 000c4608h        ;SIPI at 8000h

 mov ecx, 2_000_000
.wait2:
 in al, 80h
 dec ecx
jnz .wait2

jmp .SIPI_loop


GDT dw 17h
    dd GDT
    dw 0

    dd 0000ffffh, 00cf9a00h
    dd 0000ffffh, 00cf9200h

counter db 0
init db 1

TIMES 510-($-$$) db 0
dw 0aa55h


结论

尚无定论,此事仍未解决.
向读者介绍了事实清单.


Conclusions

No definitive conclusion can be draw, the matter is still open.
The reader has been presented with a list of facts.

预期的行为是忽略后续的SIPI,由于"P5错误",因此需要两个SIPI.
Linux和Free BSD似乎不介意有错误的SIPI处理.
如果其他制造商自行生产,则似乎没有在其LAPIC上提供任何文档.
英特尔最近的硬件忽略了后续的SIPI.

The intended behaviour is to ignore subsequent SIPIs, the need for two SIPI is due to a "P5 bug".
Linux and Free BSD don't seem to mind about buggy SIPI handling.
Other manufacturers seems to provide no documentation on their LAPICs if they produce any on their own.
Recent Intel's hardware ignore subsequent SIPIs.

1 对所有参与人员给予应有的尊重,并且不损害任何人的信誉.我确实相信那里有错误的CPU,但是也存在错误的软件和错误的内存.由于我不相信自己过去的记忆,我认为我仍然处于尊重他人的范围之内,要求他人不要信任自己模糊的记忆.

1With due respect to all people involved and without attacking anyone credibility. I do believe there are buggy CPUs out there but there are also buggy software and buggy memories. As I don't trust my own old memories I think I'm still within the bounds of a respectful conversation to ask others to no trust their vague ones.

2 可能是因为当时的MP是将常规CPU打包在一起,并使用外部芯片(APIC)声明其INIT#是启动它们的唯一方法(以及设置热重置向量).但是,那些年我还很小,没有电脑.

2 Possibly because MP in those days was done with regular CPUs packed together and asserting their INIT# with an external chip (the APIC) was the only way to start them up (along with setting a warm reset vector). However in those years I was too young to have a computer.

根据我的测试,当SIPI不在 wait-for-SIPI 状态时,将被忽略. 我已经测试了

According to my testing, SIPIs are ignored when not in a wait-for-SIPI state. I've tested a Whiskey-lake 8565U, of course real-hardware test doesn't constitute a proof.
I'm confident that all the Intel's processors since the Pentium 4 also have the same behaviour but this is just my view.
In this answer I solely want to present the result of a test. Everyone will draw their own conclusions.

这篇关于发送到未处于等待SIPI状态的活动AP的启动IPI会发生什么情况的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆