x86下Linux内核如何进入supervisor模式? [英] How does the Linux kernel enter supervisor mode in x86?

查看:39
本文介绍了x86下Linux内核如何进入supervisor模式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试在模式切换发生时(用户->内核模式)探测事件,结果,我需要找到发生转换时将触发哪个函数.

I tried to probe the event when the mode switch happens (user->kernel mode), as a result, I need to find which function will be triggered when the transition happens.

似乎SBI 是为 RISC-V 做转换的地方.我想知道为 x86 处理此问题的代码在哪里?

It seems that SBI is the placed doing transition for RISC-V. I'm wondering where is the code to handle this for x86?

推荐答案

事情没那么简单.在 x86 中,有 4 个不同的特权级别:0(操作系统内核)、1、2 和 3(应用程序).Linux 中不使用权限级别 1 和 2:内核以权限级别 0 运行,而用户空间代码以权限级别 3 运行.当前权限级别 (CPL) 存储在 CS(代码段)的位 0 和 1 中注册.

It's not that simple. In x86, there are 4 different privilege levels: 0 (operating system kernel), 1, 2, and 3 (applications). Privilege levels 1 and 2 aren't used in Linux: the kernel runs at privilege level 0 while user space code runs at privilege level 3. The current privilege level (CPL) is stored in bits 0 and 1 of the CS (code segment) register.

从用户到内核的转换可以通过多种方式发生:

There are multiple ways in which the transition from user to kernel can happen:

  • 通过硬件中断:页面错误、一般保护错误、设备、硬件计时器等.
  • 通过软件中断:int 指令引发软件中断.Linux 中最常见的是 int 0x80,它被配置为用于从用户空间到内核空间的系统调用.
  • 通过诸如 sysentersyscall 之类的专门指令.
  • Through hardware interrupts: page faults, general protection faults, devices, hardware timer, and so on.
  • Through software interrupts: the int instruction raises a software interrupt. The most common in Linux is int 0x80, which is configured to be used for system calls from user space to kernel space.
  • Through specialized instructions like sysenter and syscall.

在任何情况下,都没有执行转换的实际代码:它是由处理器本身完成的,它从一个特权级别切换到另一个特权级别,并根据以下内容设置段选择器、指令指针、堆栈指针等内核在启动后立即设置的信息.

In any case, there is no actual code that does the transition: it is done by the processor itself, which switches from one privilege level to the other, and sets up segment selectors, instruction pointer, stack pointer and more according to the information that was set up by the kernel right after booting.

在中断的情况下,中断描述符表 (IDT) 的条目是用过的.请参阅这个有用的文档页面,了解中断Linux,它解释了有关 IDT 的更多信息.如果您想了解详细信息,请查看 Intel 64 和 IA-32 架构软件开发人员手册,第 3 卷.

In the case of interrupts, the entries of the Interrupt Descriptor Table (IDT) are used. See this useful documentation page about interrupts in Linux which explains more about the IDT. If you want to get into the details, check out Chapter 5 of the Intel 64 and IA-32 architectures software developer's manual, Volume 3.

简而言之,每个 IDT 条目指定一个描述符特权级别 (DPL) 和一个新的代码段和偏移量.在软件中断的情况下,处理器进行一些特权级别检查(其中之一是 CPL <= DPL)以确定发出中断的代码是否具有这样做的特权.然后,中断处理程序被执行,它隐式地将新的 CS 寄存器设置为特权级别位设置为 0.这就是 x86 32 位的规范 int 0x80 系统调用是如何进行的.

In short, each IDT entry specifies a descriptor privilege level (DPL) and a new code segment and offset. In case of software interrupts, some privilege level checks are made by the processor (one of which is CPL <= DPL) to determine whether the code that issued the interrupt has the privilege to do so. Then, the interrupt handler is executed, which implicitly sets the new CS register with the privilege level bits set to 0. This is how the canonical int 0x80 syscall for x86 32bit is made.

对于像sysentersyscall这样的专用指令,细节有所不同,但概念是相似的:CPU检查权限,然后从专用的模型特定寄存器 (MSR),之前由内核在启动后设置.

In case of specialized instructions like sysenter and syscall, the details differ, but the concept is similar: the CPU checks privileges and then retrieves the information from dedicated Model Specific Registers (MSR) that were previously set up by the kernel after boot.

对于系统调用,结果总是相同的:用户代码切换到权限级别 0 并开始执行内核代码,在内核定义的不同系统调用入口点之一的开头结束.

For system calls the result is always the same: user code switches to privilege level 0 and starts executing kernel code, ending up right at the beginning of one of the different syscall entry points defined by the kernel.

可能的系统调用入口点是:

Possible syscall entry points are:

  • entry_INT80_32 for 32-bit int 0x80
  • entry_INT80_compat for 32-bit int 0x80 on a 64-bit kernel
  • entry_SYSENTER_32 for 32-bit sysenter
  • entry_SYSENTER_compat for 32-bit sysenter on a 64-bit kernel
  • entry_SYSCALL_64 for 64-bit syscall
  • entry_SYSCALL_compat for 32-bit syscall on 64-bit kernel (special entry point which is not used by user code, in theory syscall is also a valid 32-bit instruction on AMD CPUs, but Linux only uses it for 64-bit because of its weird semantics)

这篇关于x86下Linux内核如何进入supervisor模式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆