Skip to content

Commit bda2ea7

Browse files
committed
qoder
1 parent d0cb6fd commit bda2ea7

34 files changed

+6262
-0
lines changed
Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
# API参考
2+
3+
<cite>
4+
**本文档中引用的文件**
5+
- [src/lib.rs](file://src/lib.rs)
6+
- [src/vmx/vcpu.rs](file://src/vmx/vcpu.rs)
7+
- [src/vmx/vmcs.rs](file://src/vmx/vmcs.rs)
8+
- [src/vmx/percpu.rs](file://src/vmx/percpu.rs)
9+
- [src/msr.rs](file://src/msr.rs)
10+
- [src/regs/accessors.rs](file://src/regs/accessors.rs)
11+
</cite>
12+
13+
## 目录
14+
1. [简介](#简介)
15+
2. [导出的类型与trait](#导出的类型与trait)
16+
3. [VmxVcpu结构体方法](#vmxvcpu结构体方法)
17+
4. [Vmcs结构体字段读写方法](#vmcs结构体字段读写方法)
18+
5. [VmxPerCpuState方法](#vmxpercpustate方法)
19+
6. [MSR寄存器操作API](#msr寄存器操作api)
20+
7. [通用寄存器访问API](#通用寄存器访问api)
21+
22+
## 简介
23+
`x86_vcpu`库为基于Intel VMX(虚拟机扩展)技术的虚拟CPU提供了底层支持。该库封装了VMX相关的硬件接口,包括虚拟机控制结构(VMCS)、模型特定寄存器(MSR)操作、以及虚拟CPU的状态管理。其主要功能是允许创建和管理运行在VMX非根模式下的虚拟CPU实例,并处理由虚拟化事件触发的VM退出(VM-exit)。本参考文档详细描述了所有公共API,重点关注`VmxVcpu``Vmcs`等核心组件。
24+
25+
## 导出的类型与trait
26+
`src/lib.rs`作为入口点,该库通过条件编译(`#[cfg(feature = "vmx")]`)导出了以下公共类型和trait:
27+
28+
- **类型 (Types)**:
29+
- `VmxExitInfo`: 包含VM退出的基本信息,如退出原因、指令长度和RIP。
30+
- `VmxExitReason`: 枚举了所有可能的VM退出原因(例如,外部中断、I/O指令、CR访问等)。
31+
- `VmxInterruptInfo`: 描述了用于注入或报告中断/异常的信息。
32+
- `VmxIoExitInfo`: 提供了因执行I/O指令而发生VM退出时的详细信息。
33+
- `GuestPageWalkInfo`: 在EPT违例时,提供页表遍历所需的信息。
34+
- `GeneralRegisters`: 表示x86_64架构下的一组通用寄存器。
35+
- `VmxArchVCpu`: `VmxVcpu<H>`的类型别名,代表一个VMX架构的虚拟CPU。
36+
- `VmxArchPerCpuState`: `VmxPerCpuState<H>`的类型别名,代表每个逻辑处理器的VMX状态。
37+
38+
- **Trait**:
39+
- `has_hardware_support()`: 一个函数,用于检测当前平台是否支持VMX硬件扩展。
40+
41+
这些导出项构成了库的公共接口,使调用者能够创建虚拟CPU、配置其行为并响应虚拟化事件。
42+
43+
**Section sources**
44+
- [src/lib.rs](file://src/lib.rs#L0-L31)
45+
46+
## VmxVcpu结构体方法
47+
`VmxVcpu`是表示单个虚拟CPU的核心结构体。它封装了VMCS、I/O位图、MSR位图以及虚拟CPU的运行时状态。
48+
49+
### new()
50+
创建一个新的`VmxVcpu`实例。
51+
52+
- **函数签名**: `pub fn new(vm_id: VMId, vcpu_id: VCpuId) -> AxResult<Self>`
53+
- **参数说明**:
54+
- `vm_id`: 虚拟机的唯一标识符。
55+
- `vcpu_id`: 此虚拟CPU在其所属虚拟机内的唯一标识符。
56+
- **返回值定义**: 成功时返回`AxResult<Self>`,其中包含新创建的`VmxVcpu`实例;失败时返回`AxError`
57+
- **错误码**: 可能因内存分配失败等原因返回错误。
58+
- **调用上下文限制**: 无特定CPU限制,但后续的`bind_to_current_processor`必须在目标CPU上执行。
59+
- **使用示例**:
60+
```rust
61+
let vm_id = VMId::new(1);
62+
let vcpu_id = VCpuId::new(0);
63+
let mut vcpu = VmxVcpu::new(vm_id, vcpu_id).unwrap();
64+
```
65+
66+
### setup()
67+
为虚拟CPU设置初始上下文,包括EPT根地址和入口点。
68+
69+
- **函数签名**: `pub fn setup(&mut self, ept_root: HostPhysAddr, entry: GuestPhysAddr) -> AxResult`
70+
- **参数说明**:
71+
- `ept_root`: 指向嵌套分页(EPT)PML4表的主机物理地址。
72+
- `entry`: 虚拟机操作系统的入口点物理地址。
73+
- **返回值定义**: `AxResult<()>`,表示操作成功或失败。
74+
- **错误码**: 可能因VMCS配置失败而返回错误。
75+
- **调用上下文限制**: 必须在调用`bind_to_current_processor`之后调用。
76+
- **使用示例**:
77+
```rust
78+
let ept_root_paddr = HostPhysAddr::from(0x100000);
79+
let guest_entry = GuestPhysAddr::from(0x1000);
80+
vcpu.setup(ept_root_paddr, guest_entry).unwrap();
81+
```
82+
83+
### run()
84+
启动或恢复虚拟CPU的执行。此方法会阻塞直到发生VM退出。
85+
86+
- **函数签名**: `pub fn inner_run(&mut self) -> Option<VmxExitInfo>`
87+
- **参数说明**: 无。
88+
- **返回值定义**: 返回`Option<VmxExitInfo>`。如果VM退出是由虚拟CPU自身处理的(如内部事件),则返回`None`;否则返回`Some(VmxExitInfo)`,其中包含了退出原因、指令长度等信息。
89+
- **错误码**: 内部处理失败会导致panic。
90+
- **调用上下文限制**: 必须在调用`bind_to_current_processor`之后调用。
91+
- **使用示例**:
92+
```rust
93+
loop {
94+
match vcpu.inner_run() {
95+
Some(exit_info) => {
96+
// 处理未被内部处理的VM退出
97+
handle_vm_exit(exit_info);
98+
}
99+
None => continue,
100+
}
101+
}
102+
```
103+
104+
### register_accessors()
105+
`VmxVcpu`提供了多种方法来访问和修改虚拟CPU的寄存器状态。
106+
107+
- **`regs()``regs_mut()`**: 分别返回对`guest_regs``GeneralRegisters`)的不可变和可变引用,用于直接访问所有通用寄存器。
108+
- **`stack_pointer()``set_stack_pointer()`**: 获取和设置虚拟CPU的栈指针(RSP)。
109+
- **`rip()`**: 获取虚拟CPU的指令指针(RIP)。
110+
- **`advance_rip()`**: 将RIP向前推进指定的字节数,通常在模拟指令后调用。
111+
- **`get_cpu_mode()`**: 推断当前虚拟CPU的运行模式(实模式、保护模式、兼容模式或64位模式)。
112+
113+
**Section sources**
114+
- [src/vmx/vcpu.rs](file://src/vmx/vcpu.rs#L150-L900)
115+
116+
## Vmcs结构体字段读写方法
117+
`Vmcs`模块通过一系列枚举(如`VmcsGuestNW`, `VmcsControl32`等)安全地封装了对VMCS字段的读写操作,避免了直接使用不安全的`vmread`/`vmwrite`指令。
118+
119+
### read_field / write_field 安全封装
120+
这些方法通过为每个VMCS字段定义一个枚举变体来实现类型安全。
121+
122+
- **函数签名**:
123+
- `impl VmcsFieldEnum { pub fn read(self) -> AxResult<T> }`
124+
- `impl VmcsFieldEnum { pub fn write(self, value: T) -> AxResult }`
125+
- **参数说明**: `self``VmcsControl32``VmcsGuest64`等枚举的一个实例,代表一个具体的VMCS字段。
126+
- **返回值定义**: `AxResult<T>`,其中`T`是该字段的数据类型(如`u32`, `u64`, `usize`)。读取成功返回字段值,写入成功返回`Ok(())`
127+
- **错误码**: 如果`vmread``vmwrite`指令失败(例如,由于无效的VMCS指针或尝试写入只读字段),将返回`AxError`。具体错误信息可通过`vmcs::instruction_error()`获取。
128+
- **调用上下文限制**: 必须在`VMPTRLD`指令加载了有效的VMCS之后才能调用。
129+
- **使用示例**:
130+
```rust
131+
// 读取VMCS中的GUEST_RIP
132+
let guest_rip = VmcsGuestNW::RIP.read().unwrap();
133+
// 写入新的GUEST_RIP
134+
VmcsGuestNW::RIP.write(new_rip_value).unwrap();
135+
```
136+
137+
**Section sources**
138+
- [src/vmx/vmcs.rs](file://src/vmx/vmcs.rs#L100-L500)
139+
140+
## VmxPerCpuState方法
141+
`VmxPerCpuState`管理每个逻辑处理器上的全局VMX状态,负责启用和禁用VMX操作。
142+
143+
### create()
144+
创建一个新的`VmxPerCpuState`实例。
145+
146+
- **函数签名**: `fn new(_cpu_id: usize) -> AxResult<Self>`
147+
- **参数说明**: `_cpu_id`: 逻辑处理器的ID。
148+
- **返回值定义**: `AxResult<Self>`,成功时返回新实例。
149+
- **错误码**: 通常不会在此阶段失败。
150+
- **调用上下文限制**: 无。
151+
152+
### enable_vmxe()
153+
协同完成VMX的全局与局部启用。此方法首先检查硬件支持,然后配置必要的控制寄存器和MSR,最后执行`VMXON`指令。
154+
155+
- **函数签名**: `fn hardware_enable(&mut self) -> AxResult`
156+
- **参数说明**: 无。
157+
- **返回值定义**: `AxResult<()>`
158+
- **错误码**:
159+
- `Unsupported`: CPU不支持VMX,或BIOS禁用了VMX。
160+
- `ResourceBusy`: VMX已在当前处理器上启用。
161+
- `BadState`: 主机的CR0或CR4寄存器状态不符合VMX要求。
162+
- **调用上下文限制**: 必须在单个逻辑处理器上执行,且不能在中断上下文中调用。
163+
- **使用示例**:
164+
```rust
165+
let mut per_cpu_state = VmxPerCpuState::new(0).unwrap();
166+
per_cpu_state.hardware_enable().unwrap(); // 启用VMX
167+
// ... 创建和运行VmxVcpu ...
168+
per_cpu_state.hardware_disable().unwrap(); // 禁用VMX
169+
```
170+
171+
**Section sources**
172+
- [src/vmx/percpu.rs](file://src/vmx/percpu.rs#L50-L200)
173+
174+
## MSR寄存器操作API
175+
`msr.rs`模块提供了对模型特定寄存器(MSR)的安全访问。
176+
177+
### Msr 枚举
178+
定义了一个`Msr`枚举,列出了所有受支持的MSR,例如:
179+
- `IA32_VMX_BASIC`: 报告基本的VMX能力。
180+
- `IA32_VMX_PINBASED_CTLS`: 针脚为基础的VM执行控制。
181+
- `IA32_EFER`: 扩展功能启用寄存器。
182+
183+
### read() 和 write()
184+
`Msr`枚举实现了`read``write`方法。
185+
186+
- **函数签名**:
187+
- `pub fn read(self) -> u64`
188+
- `pub unsafe fn write(self, value: u64)`
189+
- **参数说明**: `value`: 要写入MSR的64位值。
190+
- **返回值定义**: `read`返回64位的MSR值。
191+
- **错误码**: 无显式错误码,但`write``unsafe`的,调用者需确保操作的安全性。
192+
- **调用上下文限制**: `read`可在任何特权级调用;`write`通常需要在ring 0执行。
193+
- **使用示例**:
194+
```rust
195+
let vmx_basic = Msr::IA32_VMX_BASIC.read();
196+
let revision_id = vmx_basic as u32;
197+
```
198+
199+
**Section sources**
200+
- [src/msr.rs](file://src/msr.rs#L50-L150)
201+
202+
## 通用寄存器访问API
203+
`regs`模块提供了对通用寄存器的高级访问接口。
204+
205+
### GeneralRegisters 结构体
206+
`GeneralRegisters`是一个包含所有x86_64通用寄存器(rax, rbx, ..., r15)的结构体。
207+
208+
### 访问器方法
209+
通过宏生成了一系列getter和setter方法,以支持不同大小的寄存器访问。
210+
211+
- **函数签名示例**:
212+
- `pub fn eax(&self) -> u32`
213+
- `pub fn set_eax(&mut self, value: u32)`
214+
- `pub fn al(&self) -> u8`
215+
- `pub fn set_al(&mut self, value: u8)`
216+
- **参数说明**: `value`: 要设置的寄存器值。
217+
- **返回值定义**: 返回指定大小的寄存器值。
218+
- **错误码**: 无。
219+
- **调用上下文限制**: 无。
220+
- **使用示例**:
221+
```rust
222+
let mut regs = GeneralRegisters::default();
223+
regs.set_rax(0x123456789ABCDEF0);
224+
assert_eq!(regs.eax(), 0x9ABCDEF0); // 获取低32位
225+
assert_eq!(regs.al(), 0xF0); // 获取低8位
226+
```
227+
228+
**Section sources**
229+
- [src/regs/accessors.rs](file://src/regs/accessors.rs#L50-L200)

0 commit comments

Comments
 (0)