2017-09-03 122 views
-1

我正在构建一个32位操作系统的程序集。
我已经安装了IDT,并通过int指令处理程序interruptus。OsDev系统调用/ sysret和sysenter/sysexit指令启用

如何启用syscallsysenter指令,以及如何处理它们/返回?
确实syscall指令在英特尔处理器32位中不受支持,因此我无法使用它? 是不是说sysret指令不安全? 做某处存在一个教程吗?

编辑:我的主要问题是如何启用syscallsysenter说明! (没有重复)

+2

您是否尝试过在手动或在线资源中查看?你发现了什么? – fuz

+0

可能重复[什么是更好的“int 0x80”或“系统调用”?](https://stackoverflow.com/questions/12806584/what-is-better-int-0x80-or-syscall) –

+1

@BoPersson问题似乎不相关:另一个问题只关注Linux;这个问题关注于一个自编写的内核。 –

回答

0

是真的,系统调用指令不支持在32位由英特尔处理器,所以我不能使用它?

至少有维基百科对此置评。

更重要的是:系统调用似乎甚至不被任何32位CPU(即使不是AMD)支持,但仅在32位模式的64位AMD CPU中才支持。

我在构建一个32位的操作系统。

那么,为什么要使用系统调用或sysenter?

几乎所有的32位x86操作系统使用任何中断(如Linux)或致电栅极(例如Solaris)上进入内核...

+1

大量的32位AMD cpus支持'syscall'从1998年开始使用K6-2。因为它们更快,所以使用'syscall' /'sysenter'。 Linux已经使用它们十多年了,即使在32位模式下也是如此。中断只是遗留的后备。 – Jester

2

syscall不能在x86上使用,只在x86_64(可移植至少)。话虽这么说,在x86_64,指令通过加载用户模式和内核模式的正确CS选择到IA32_STAR具体型号寄存器启用,那么无论地址要在syscall执行到IA32_LSTAR打电话。您还需要仔细处理这些指令的执行上下文,因为它们会摧毁一些寄存器等。

我建议您在手册中阅读 - 英特尔手册本身和AMD64手册第2卷都是开始的好地方。

4

查看OSdev wiki for details on sysenter,包括关于如何避免安全/安全问题的说明。另请参阅英特尔/ AMD手册。它们涉及操作系统开发人员所需的大量细节。有关链接,请参阅标记wiki。


的各种系统调用指令概述:

  • int:可用自永远(8086)
  • 通过执行一个无效的指令陷阱,显然是the fastest way to enter the kernel on 80386。 (但情况不再如此)。
  • call gate(即,far call)。请参阅OSdev链接以获取有关该细节和陷阱的详细信息。
  • sysenter:(http://wiki.osdev.org/Sysenter)英特尔在x86-64之前推出,不久之后被AMD采用(多年前)。适用于所有现代x86 CPU。非常简约的设计需要用户空间合作才能使内核能够返回,因为它不会将EIP,ESP或EFLAGS保存在任何地方

    Linux仅在32位和64位内核中支持32位进程的系统调用。 IDK,如果你可以设计一个用于64位系统调用的内核。 (我知道这不是问题,但它是相关的。)

    使用sysenter需要用户空间合作来提供返回地址并保存它自己的ESP和EFLAGS。在Linux中,内核会导出一个代码页面,其中包含跳舞的用户空间。用户空间预计call这个代码,而不是直接使用sysenter,但随意设计你的操作系统,但你想要的。如果你在其他地方找不到示例,那么查看Linux的代码可能对此舞蹈的双方都有用。

  • 从64位用户空间syscall:随处可见,因为英特尔实现了它与AMD64的其余一起。精心设计的接口在进入内核之前会屏蔽RFLAGS(带有可配置的掩码),因此您可以避免竞争窗口(如果必须使用cli手动禁用中断)。与swapgs一起用于内核访问其堆栈等。

    在主流x86操作系统(如Linux)上,syscall是进行64位系统调用的唯一方法。

  • syscall从32位用户空间:从长模式syscall仅在AMD处理器可用一个完全不同的指令。对于32位内核(传统模式)与运行32位用户空间(compat模式)的64位内核,内核端接口不同。

    Linux内核有它的一些有用的意见:

entry_64_compat.S 32-bit SYSCALL entry(32位syscall入口点到64位内核)

/* ... 
* - Most programmers do not directly target AMD CPUs, and the 32-bit 
* SYSCALL instruction does not exist on Intel CPUs. Even on AMD 
* CPUs, Linux disables the SYSCALL instruction on 32-bit kernels 
* because the SYSCALL instruction in legacy/native 32-bit mode (as 
* opposed to compat mode) is sufficiently poorly designed as to be 
* essentially unusable. 

也许玩具操作系统可以使用它,而不必担心任何问题使其不适用于Linux,IDK。但除非你只是好奇,否则不要浪费时间。 OTOH,如果你对CPU设计感兴趣,找出ISA设计的问题可能会很有趣。

顺便说一句,当AMD在设计AMD64,他们得到了来自Linux内核开发者认为改善64位syscall设计的AMD64邮件列表上的一些反馈(以可配置掩盖RFLAGS),因为他们最初的设计本来问题适用于Linux 。链接到那些已存档的邮件列表帖子in this answer


建议:使用sysenter为32位内核。它应该可以在任何地方使用,包括在AMD CPU上使用多年。不支持它的古代CPU可以使用int 0x80 ABI(或者您为操作系统挑选的任何数字),如果您想添加第二个兼容性ABI。

Linux内核入口点的注释很好,写得相当易读。在编写What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?时,我很容易地通过使用syscall(原生64位系统调用)或int 0x80sysenter(32位系统调用,通常来自compat)来确定在64位内核的入口点发生了什么。模式,但int 0x80是支持64位的进程。但它仍然调用32位ABI!)有复杂的东西的情况下,要在一堆各种跟踪/调试启用,但其他部分是相当容易跟随。查看这个答案,了解一些Linux的系统调用处理内部。

arch/x86/entry,这些都是利益的主要文件:

  • entry_32.S:从用户空间进入32位内核代码。 (遗留模式)
  • entry_64_compat.S:用于从32位用户空间(compat模式 - >长模式)输入的64位内核代码。
  • entry_64.S:用于从64位用户空间(长模式 - >长模式)进入的64位内核代码。

你应该能够找到的sysenter舞蹈是传递内核,它需要返回到用户空间的值的用户空间侧的Linux的VDSO代码。 (What is better "int 0x80" or "syscall"?)。相关:What is better "int 0x80" or "syscall"?The Definitive Guide to Linux System Calls将提供有关Linux所做设计选择的一些有用信息。


是真的,sysret指令是不是安全?

当返回到64位用户空间时,英特尔和AMD都有与非规范RIP分离的错误。例如英特尔,Linux's entry_64.S这样描述:

/* 
* On Intel CPUs, SYSRET with non-canonical RCX/RIP will #GP 
* in kernel space. This essentially lets the user take over 
* the kernel, since userspace controls RSP. 

如果ptrace系统调用(例如,通过一个调试器中进行)改变了进程的RIP的保存价值,非规范的地址,可以发生。 Linux检查是否可以使用sysret,如果不使用它的iret返回路径。 (sysret路径速度足够快,因此值得做更多的工作来检查它是否安全)。

注意,如果一个系统调用块/睡眠状态时,“主副本”用户空间的整数寄存器状态的是它的内核堆栈,系统调用入口点推它。 (在Linux中,其他设计是可能的!)但是,无论如何,这就是为什么最终会出现奇怪的保存状态,用户空间不能运行syscall(因为它将在jmp上违反非规范地址)或saved_rcx != saved_RIP(64位syscall设置RCX = RIP,和R11 = RFLAGS(屏蔽之前),所以它则会覆盖RCX和R11,但允许内核恢复RIP和RFLAGS。)

我不知道该怎么32位syscall作品,对不起,我在这里得到话题。但是我怀疑你可能读到的有关sysret不安全的内容是关于64位内核的。

IDK如果在32位内核sysret或64位内核sysret -to-compat-mode中有任何类似的错误。