gpt4 book ai didi

assembly - 我应该在哪里使用 "swapgs"指令

转载 作者:行者123 更新时间:2023-12-03 23:11:45 31 4
gpt4 key购买 nike

您好,我是一名内核学习者,有一些关于 swapgs 的问题。
根据 AMD 的文档,它交换了 gs.base隐藏寄存器和 KernelGSBase MSR。
此外,“gs:XXXX”的寻址计算为“gs.base + base + (scale*index) +位移”

现在我的第一个问题是:

  • gs.base 是段寄存器的隐藏部分
  • 位移是“gs:XXXX”的“XXXX”部分
  • index 可能是 gs 中的选择器索引

  • 那么我应该在哪里存储“基础”和“比例”?

    此外,我应该在哪里使用它,我当前的项目将虚拟内存空间的上半部分作为内核,并且编译器通常不会添加“gs:XXXX”作为寻址引用。
    所以,特别是在哪里,我应该使用 swapgs操作说明。

    最佳答案

    没有隐藏的“基数和尺度”,只有隐藏的gs.base与正常寻址模式一起使用。 (以及 GS 寄存器本身的隐藏值。这是一个选择器值,如果您确实做了 mov gs, eax 而不是仅通过 MSR 或通过 wrgsbase 修改 GS 基数,它将充当 GDT 的索引。但是这与完整 gs:[base + index*scale] 寻址模式中偏移量的索引部分无关)。
    您使用 swapgs在内核的 syscall入口点处理程序,然后像线程本地存储一样在某些加载和存储上使用 GS 段覆盖,因此以前隐藏的 gs.base[base + idx*scale] 一起使用您在每个加载或存储指令中使用的寻址模式。例如类似 mov [gs:0x10], rsp保存用户空间堆栈指针和 mov rsp, [gs:0x18]加载内核堆栈指针。
    swapgs存在是因为 syscall不会将 RSP 更改为指向内核堆栈 (并且不会在任何地方保存用户空间 RSP)。因此,您需要某种线程本地(或实际上是内核本地)存储,以便每个内核都可以为在该内核上运行的任务获取正确的内核堆栈指针。隐藏的 GS 基是那个隐藏指针的存储,是一种在不破坏任何架构寄存器值的情况下使用它的方法。
    您不能只使用常规全局变量(绝对地址),因为它只能有一个所有内核都可以读取的值。您也没有任何备用寄存器(它们都包含您稍后需要恢复的宝贵用户空间状态),并且您没有内核堆栈来插入它们。并且您不能使用用户空间 RSP;运行 push在内核模式下,使用用户空间 RSP 会使用户空间在运行之前将 RSP 指向无效的某个地方,从而使内核崩溃 syscall .

    当最初设计 x86-64 时(早在 2000 年,第一个硅片出现之前的几年),this mailing list message解释了 swapgs 的预期目的.它是 revised a day later在操作系统开发人员注意到 AMD 对其指定方式存在问题后,但原始电子邮件包含一个仍然适用的简单示例:

    Example usage
    At a kernel entry point the OS can use SwapGS to obtain a pointer to kernel data structures and simultaneously save theuser's GS base. Upon exit it can use SwapGS to restore the user's GSbase:

      SystemCallEntryPoint:
    SwapGS ; set up kernel pointer, save user's GS base
    mov gs:[SavedUserRSP], rsp ; save user's stack pointer
    mov rsp, gs:[KernelStackPtr] ; set up kernel stack
    push rax ; now that we have a stack, save user's GPRs
    mov rax, gs:[CPUnumber] ; get CPU number < or whatever >
    . ; perform system service
    .
    SwapGS ; restore user's GS, save kernel pointer

    您可能还想查看 Linux 内核如何在其 syscall 中使用它。入口点,最好在 Spectre/Meltdown 缓解使一切复杂化之前的旧内核中。例如 Linux 4.12's entry_64.S 有它的 ENTRY(entry_SYSCALL_64)swapgs 开始,很像 AMD 的例子。
    (另请参阅 Why does Windows64 use a different calling convention from all other OSes on x86-64? 以了解其他 Linux 内核入口点中发生的情况,来自 int 0x80 )。
    Linux 内核源代码中的一些注释指出,确保 swapgs 可能不方便。沿着内核之外的每条执行路径只运行一次。如果有两个操作码,一个用于“交换到用户 gs”,另一个用于“交换到内核 gs”,则更容易确保不会意外交换额外的时间。该错误会使下一个内核条目出现在错误的位置。 (并为用户空间提供错误的 gs,但在 GNU/Linux 中 fs 用于线程本地存储。)

    关于assembly - 我应该在哪里使用 "swapgs"指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62546189/

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