2017-09-03 155 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中有任何類似的錯誤。