Alioth Code Coverage

sev.rs0.00%

1// Copyright 2026 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::os::fd::{AsFd, AsRawFd};
16
17use snafu::ResultExt;
18
19use crate::arch::sev::{SevPolicy, SevStatus, SnpPageType, SnpPolicy};
20use crate::hv::kvm::KvmVm;
21use crate::hv::{Result, error};
22use crate::sys::kvm::{KvmCap, KvmHypercall, kvm_memory_encrypt_op};
23use crate::sys::sev::{
24 KvmSevCmd, KvmSevCmdId, KvmSevInit, KvmSevLaunchMeasure, KvmSevLaunchStart,
25 KvmSevLaunchUpdateData, KvmSevSnpLaunchFinish, KvmSevSnpLaunchStart, KvmSevSnpLaunchUpdate,
26};
27
28impl KvmVm {
29 fn sev_op<T>(&self, cmd: KvmSevCmdId, data: Option<&mut T>) -> Result<()> {
30 let Some(sev_fd) = &self.vm.arch.sev_fd else {
31 unreachable!("SevFd is not initialized")
32 };
33 let mut req = KvmSevCmd {
34 sev_fd: sev_fd.as_fd().as_raw_fd() as u32,
35 data: match data {
36 Some(p) => p as *mut T as _,
37 None => 0,
38 },
39 id: cmd,
40 error: SevStatus::SUCCESS,
41 };
42 unsafe { kvm_memory_encrypt_op(&self.vm.fd, &mut req) }.context(error::MemEncrypt)?;
43 if req.error != SevStatus::SUCCESS {
44 return error::SevErr { code: req.error }.fail();
45 }
46 Ok(())
47 }
48
49 pub fn sev_init(&self, policy: SevPolicy) -> Result<()> {
50 if policy.es() {
51 self.sev_op::<()>(KvmSevCmdId::ES_INIT, None)
52 } else {
53 self.sev_op::<()>(KvmSevCmdId::INIT, None)
54 }
55 }
56
57 pub fn snp_init(&self) -> Result<()> {
58 let map_gpa_range = 1 << KvmHypercall::MAP_GPA_RANGE.raw();
59 self.vm.enable_cap(KvmCap::EXIT_HYPERCALL, map_gpa_range)?;
60 let mut init = KvmSevInit::default();
61 self.sev_op(KvmSevCmdId::INIT2, Some(&mut init))
62 }
63
64 pub fn sev_launch_start(&self, policy: SevPolicy) -> Result<()> {
65 let mut start = KvmSevLaunchStart {
66 policy,
67 ..Default::default()
68 };
69 self.sev_op(KvmSevCmdId::LAUNCH_START, Some(&mut start))?;
70 Ok(())
71 }
72
73 pub fn sev_launch_update_data(&self, range: &mut [u8]) -> Result<()> {
74 let mut update_data = KvmSevLaunchUpdateData {
75 uaddr: range.as_mut_ptr() as u64,
76 len: range.len() as u32,
77 };
78 self.sev_op(KvmSevCmdId::LAUNCH_UPDATE_DATA, Some(&mut update_data))?;
79 Ok(())
80 }
81
82 pub fn sev_launch_update_vmsa(&self) -> Result<()> {
83 self.sev_op::<()>(KvmSevCmdId::LAUNCH_UPDATE_VMSA, None)?;
84 Ok(())
85 }
86
87 pub fn sev_launch_measure(&self) -> Result<Vec<u8>> {
88 let mut empty = KvmSevLaunchMeasure { uaddr: 0, len: 0 };
89 let _ = self.sev_op(KvmSevCmdId::LAUNCH_MEASURE, Some(&mut empty));
90 assert_ne!(empty.len, 0);
91 let mut buf = vec![0u8; empty.len as usize];
92 let mut measure = KvmSevLaunchMeasure {
93 uaddr: buf.as_mut_ptr() as u64,
94 len: buf.len() as u32,
95 };
96 self.sev_op(KvmSevCmdId::LAUNCH_MEASURE, Some(&mut measure))?;
97 Ok(buf)
98 }
99
100 pub fn sev_launch_finish(&self) -> Result<()> {
101 self.sev_op::<()>(KvmSevCmdId::LAUNCH_FINISH, None)?;
102 Ok(())
103 }
104
105 pub fn snp_launch_start(&self, policy: SnpPolicy) -> Result<()> {
106 let mut start = KvmSevSnpLaunchStart {
107 policy,
108 ..Default::default()
109 };
110 self.sev_op(KvmSevCmdId::SNP_LAUNCH_START, Some(&mut start))?;
111 Ok(())
112 }
113
114 pub fn snp_launch_update(&self, range: &mut [u8], gpa: u64, type_: SnpPageType) -> Result<()> {
115 let mut update = KvmSevSnpLaunchUpdate {
116 uaddr: range.as_mut_ptr() as _,
117 len: range.len() as _,
118 gfn_start: gpa >> 12,
119 type_,
120 ..Default::default()
121 };
122 self.sev_op(KvmSevCmdId::SNP_LAUNCH_UPDATE, Some(&mut update))?;
123 Ok(())
124 }
125
126 pub fn snp_launch_finish(&self) -> Result<()> {
127 let mut finish = KvmSevSnpLaunchFinish::default();
128 self.sev_op(KvmSevCmdId::SNP_LAUNCH_FINISH, Some(&mut finish))?;
129 Ok(())
130 }
131}
132