0

全部。

当我分配一个新的物理页面时,我正在尝试打印当前的 PC 值。在linux内核源代码中,mm/memory.c负责分配页面,但它没有关于PC值的信息......有谁知道我在哪里可以找到这个PC值并在memory.c文件中使用它?

4

1 回答 1

2

将我的评论变成答案。

您要查找的不是当前 PC(一直在变化),而是触发页面错误的指令的 PC。要了解它的存储位置以及如何检索它,让我们再深入一点。

当x86 中发生异常(陷阱或中断)时,CPU 将执行以下操作:

  • 使用向量(陷阱号/中断号 - 这是硬件隐式和/或可通过对中断控制器进行编程来配置 - 是的,从技术上讲,您可以使网络中断触发页面错误......)作为中断描述符表的索引( IDT)
  • 它验证存储在那里的数据结构(所谓的门描述符
  • 如果无效...引发#GP故障(一般保护 [错误]);因为这本身就是一个例外...如果该门也无效... #DF(双重故障)...冲洗重复...如果无效-三重故障(硬重置CPU)。
  • 如果有效,门将指定目标上下文(通过代码段)和其中的处理程序地址。用外行的话来说,这就是“进入以下特权级别并调用此处理程序”(通过使目标%cs成为内核之一,并且处理程序是一些低级中断入口函数)。
  • 如果执行此操作涉及特权切换,则 CPU 更改为目标特权级别,并切换堆栈指针。
  • CPU 将中断返回信息写入该堆栈(请注意#DF这里的下一个机会……如果由于内核堆栈指针损坏或堆栈溢出到未映射的内存而失败,则会发生这种情况)。写入的信息包含:
    1. 发生故障时的代码段(起源“上下文”)
    2. 堆栈指针在故障发生时处于活动状态(即用户堆栈),它的堆栈被切换
    3. flags登记
    4. 错误地址/PC(不是所有类型的陷阱,但绝对是页面错误)
  • 只有这一切发生之后,才会调用实际的中断向量处理函数。从这里开始,软件 - 内核代码接管:
    1. 在汇编代码中,通用寄存器的其余部分和其他必要的“上下文”信息被保存到异常帧中,然后构造一个适合调用 C 代码的堆栈。
    2. 使用struct ptregs*作为参数调用 C 函数 - 这是异常帧,由陷阱条目保存的寄存器状态(部分由硬件/CPU 本身,部分由条目存根代码)。这是实际用于处理陷阱/异常/中断的内容。

当从陷阱/中断返回时,x86iret指令用于展开 CPU 压入内核堆栈的四/五个字,以便恢复/返回。

这样,内核中的每个异常条目都被赋予了相同的数据结构,struct ptregs *如前所述,对于大多数陷阱/中断,除其他信息外,它还包含程序计数器/指令指针,说明故障发生的位置。struct pt_regs.ip是您需要查看的字段。

特别是对于页面错误,请查看do_page_fault()并检查它的使用位置/方式。

于 2013-05-23T11:44:15.467 回答