COCONUT-SVSM 协议请求处理
本文最后更新于 118 天前,其中的信息可能已经有所发展或是发生改变。

继上一篇 COCONUT-SVSM 代码初次阅读,这次来讲讲 COCONUT-SVSM 实现的相关协议,以及是怎么处理这些协议请求的。

阅读该文章之前,需要对 SEV-SNP 以及 SVSM 有一定了解:

COCONUT-SVSM 的开发计划是要支持 AMD 的 SEV-SNP、Intel 的 TDX 以及 Arm 的 CCA。但从目前的计划表来看,Intel 的 TDX 已经提上日程了;但是 Arm CCA 还没看到相关计划。

COCONUT-SVSM 计划实现三种执行模式:

  • 轻量操作系统模式 (Enlight OS Mode),仅提供 Hypervisor 不能提供的设备模拟服务。

  • Paravisor 模式,接管 VE/VC 异常以及管理私有和共享内存。(应该还在日程中,没实现

  • 服务虚拟机模式,SVSM 就是操作系统,Hypervisor 只是一个交互通道,向另一个 CVM 提供服务。

1 客户操作系统的启动

继续上一篇,startup_64 执行完成后,会跳转到 svsm_start() 函数,该函数也在 linux/src/svsm.rs 代码中实现。函数有两个参数,一个 KernelLaunchInfo 和 vb_addr。函数执行一下操作:

  1. 对 GDT 和 IDT 进行初始化。

  2. 解析 KernelLaunchInfo 参数,对全局变量 LAUNCH 进行初始化。

  3. 分配安全页面和一些系统寄存器如 cr0 和 cr4 的初始化。

  4. 初始化终端和相应的环境。

  5. 从 KernelLaunchInfo 中解析内核可链接执行文件的相关信息。

  6. 初始化分页,并为每个 CPU 设置页表和平台相关信息。

  7. 文件系统初始化。

  8. 设置每个 CPU 起始入口为 svsm_main() 函数,并设置调试接口。

当每个 CPU 启动之后,都会进入到 svsm_main() 函数中,该函数在 linux/src/svsm.rs 代码中实现。函数执行的操作如下:

  1. 设置 SVSM_PLATFORM 的相关环境。

  2. 从 LAUNCH 中读取启动相关信息。

  3. 设置 IGVM。

  4. 内存映射和内核文件系统的解包。

  5. 从配置中获取 CPU 的相关信息以及个数,启动全部 CPU。

  6. 准备固件和 vTPM,然后启动固件。

  7. 创建和启动内核任务,即 request_processing_main() 函数。这个函数非常的关键。

  8. 启动和加载用户任务 /init

  9. 进入到 request_loop() 函数中。

2 请求处理函数

request_processing_main() 函数用于处理和分发请求的,在 linux/src/requests.rs 中实现。函数进入后,就是一个死循环。循环中第一个调用的函数就是 wait_for_requests(),该函数将当前任务加入到等待任务队列 (waitqueue) 中,并进行调度。这就解释了在 中提到的第7步创建和启动内核任务后还能回到当前执行流的原因

当有请求回到当前内核任务的上下文后,就会执行死循环的内容。首先,从 RAX 寄存器中读取请求的功能对象编号,以及从 VMSA 中读取请求的参数。然后调用 request_loop_once() 函数,处理该请求。

根据 request_loop_once() 处理函数的返回结果,设置 RAX 的值,将请求的相关结果存储到 VMSA 中,回到死循环的开始位置。

3 请求循环函数

request_loop() 函数在 linux/src/requests.rs 代码中实现。其实,这个函数更像是 VMPL 的启动和恢复处理函数。

函数本身也是一个死循环。按照注释的描述,每次循环都是检查是否有客户机是可运行的,如果没有,就暂停并等待可以执行的客户机(该过程由 Hypervisor 进行调度)。如果有可以运行的客户机,则将该客户机的 VMSA 设置成激活状态,并进行 VMPL 切换。

image-20250104202715571

客户机执行时如果需要异常,会先退回到 Hypervisor,由 Hypervisor 交给 VMPL0 处理,即 SVSM。SVSM 恢复了进入 VMPL 时的上下文。读去 GUEST_VMPL 的 CPU 的 RAX 的值,获取请求相关信息。通过 check_requests() 函数检查请求的合法性。如果合法,调用 process_requests() 函数处理。

pub fn wait_for_requests() {
    let current_task = current_task();
    this_cpu()
        .request_waitqueue
        .borrow_mut()
        .wait_for_event(current_task);
    schedule();
}

pub fn process_requests() {
    let maybe_task = this_cpu().request_waitqueue.borrow_mut().wakeup();
    if let Some(task) = maybe_task {
        schedule_task(task);
    }
}

process_requests() 函数在 linux/src/cpu/percpu.rs 中实现,代码如上。从 waitqueue 中取出之前放入的内核任务,并调度,从而又回到 提到的 wait_for_requests() 的位置。

4 请求处理

request_loop_once() 函数在 linux/src/requests.rs 中实现。函数先检查了客户机的退出码是否是 VMGEXIT,如果是,在根据请求的协议类型进行分发。COCONUT-SVSM 已经实现了 SVSM 白皮书中提到的三个协议:

  • 核心 (core) 协议:交给 core_protocol_request() 函数处理。

  • vTPM 协议:交给 vtpm_protocol_request() 函数处理。

  • APIC 协议:交给 apic_protocol_request() 函数处理。

  • 其他都是不支持的协议。

4.1 核心协议

core_protocol_request() 函数在 linux/src/procotol/core.rs 中实现。对核心协议由进行了一次分发:

match request {
    SVSM_REQ_CORE_REMAP_CA => core_remap_ca(params),
    SVSM_REQ_CORE_PVALIDATE => core_pvalidate(params),
    SVSM_REQ_CORE_CREATE_VCPU => core_create_vcpu(params),
    SVSM_REQ_CORE_DELETE_VCPU => core_delete_vcpu(params),
    SVSM_REQ_CORE_DEPOSIT_MEM => core_deposit_mem(params),
    SVSM_REQ_CORE_WITHDRAW_MEM => core_withdraw_mem(params),
    SVSM_REQ_CORE_QUERY_PROTOCOL => core_query_protocol(params),
    SVSM_REQ_CORE_CONFIGURE_VTOM => core_configure_vtom(params),
    _ => Err(SvsmReqError::unsupported_call()),
}

4.2 vTPM 协议

vtpm_protocol_request() 函数在 linux/src/procotol/vtpm.rs 中实现。对 vTPM 协议由进行了一次分发:

match request {
    SVSM_VTPM_QUERY => vtpm_query_request(params),
    SVSM_VTPM_COMMAND => vtpm_command_request(params),
    _ => Err(SvsmReqError::unsupported_call()),
}

4.3 APIC 协议

apic_protocol_request() 函数在 linux/src/procotol/apic.rs 中实现。函数开始会检查是否使用 APIC 的模拟,如果不是,返回错误信息;如果是,对 APIC 协议由进行了一次分发:

match request {
    SVSM_REQ_APIC_QUERY_FEATURES => apic_query_features(params),
    SVSM_REQ_APIC_CONFIGURE => apic_configure(params),
    SVSM_REQ_APIC_READ_REGISTER => apic_read_register(params),
    SVSM_REQ_APIC_WRITE_REGISTER => apic_write_register(params),
    SVSM_REQ_APIC_CONFIGURE_VECTOR => apic_configure_vector(params),

    _ => Err(SvsmReqError::unsupported_call()),
}

各个协议的实现请看后续。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇