gpt4 book ai didi

windows - 如何在同一系统上发送 nmi

转载 作者:可可西里 更新时间:2023-11-01 11:21:41 25 4
gpt4 key购买 nike

我需要在我正在使用的系统上发送一个 nmi。我想测试我已经实现的一些东西。是否有任何 Windows 驱动程序例程允许我们这样做?我想我可以使用 __outword 写入端口。还有其他方法吗?

我还有一个问题。是否有任何特定情况会导致 NMI? (但是,我不希望系统出现 BSOD 或三重故障。)

谢谢

最佳答案

来自 Intel's Software Development Manual: System Programming Guide :

The nonmaskable interrupt (NMI) can be generated in either of two ways:

  • External hardware asserts the NMI pin.
  • The processor receives a message on the system bus (Pentium 4, Intel Core Duo, Intel Core 2, Intel Atom, and Intel Xeon processors) or the APIC serial bus (P6 family and Pentium processors) with a delivery mode NMI.

It is possible to issue a maskable hardware interrupt (through the INTR pin) to vector 2 to invoke the NMI interrupt handler; however, this interrupt will not truly be an NMI interrupt. A true NMI interrupt that activates the processors NMI-handling hardware can only be delivered through one of the mechanisms listed above.

因此,如果您只想触发 NMI 处理程序,您可以简单地使用 int $2(Intel 语法中的 int 02h)。但是,如果您需要确保它不被屏蔽,您将需要外部硬件来触发它,或者使用 APIC。


如果您选择使用 APIC 发送 NMI,最简单的方法是发送处理器间中断。为此,您需要访问本地 APIC 的寄存器,这些寄存器映射到物理内存,默认地址为 0xFEE00000,但可以更改。您将需要找到包含 APIC 寄存器的物理页面并将其映射到虚拟内存中,以便您可以访问它们。

为了发送一个IPI,你需要写入中断配置寄存器。 ICR 的低 32 位位于 APIC 页内的 0x300,高 32 位位于 0x310。要发送 NMI,您需要:

  1. 获取要将 NMI 发送到的处理器的 APIC ID。如果您想将它发送到您正在运行的处理器,这很简单,因为您可以从 APIC 的 0x20 位 24-31 中读取它。
  2. 将 APIC ID 写入目标字段,高位 ICR 寄存器的第 24-31 位。
  3. 将值 0x4400 写入低位 ICR 寄存器。该值的第 8-10 位表示您正在发送 NMI,第 14 位表示您正在使用断言触发模式。

写入 APIC 寄存器时,必须写入完整的 32 位值。此外,ICR 中的第 13、16-17 和 20-55 位是保留的,因此您不应更改它们的值。您还必须在低位之前写入 ICR 的高位,因为 IPI 是由写入低位触发的。

下面是一个用 C 语言向当前处理器发送 NMI 的例子。

#define APIC_ID_OFFSET 0x20
#define ICR_LOW_OFFSET 0x300
#define ICR_HIGH_OFFSET 0x310
// Convenience macro used to access APIC registers
#define APIC_REG(offset) (*(unsigned int*)(apicAddress + offset))

void *apicAddress; // This should contain the virtual address that the APIC registers are mapped to

// Get the current APIC ID. Leave it in the high 8 bits since that is where it needs to be written anyway
unsigned int apicID = APIC_REG(APIC_ID_OFFSET) & 0xFF000000;
unsigned int high = APIC_REG(ICR_HIGH_OFFSET) & 0x00FFFFFF;
high |= apicID;
unsigned int low = APIC_REG(ICR_LOW_OFFSET) & 0xFFF32000;
low |= 0x4400;
APIC_REG(ICR_HIGH_OFFSET) = high;
APIC_REG(ICR_LOW_OFFSET) = low;

关于windows - 如何在同一系统上发送 nmi,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7422708/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com