mirror of
https://github.com/google/alioth.git
synced 2024-11-28 09:26:21 +00:00
feat(kvm)!: enable hypercall for SNP guests
Signed-off-by: Changyuan Lyu <changyuanl@google.com>
This commit is contained in:
parent
efbddfea39
commit
8e43412a2a
8 changed files with 99 additions and 15 deletions
|
@ -214,6 +214,7 @@ where
|
|||
_ => VmEntry::None,
|
||||
}
|
||||
}
|
||||
VmExit::ConvertMemory { .. } => unimplemented!(),
|
||||
VmExit::Unknown(msg) => break Err(Error::VmExit(msg)),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -277,6 +277,11 @@ pub enum VmExit {
|
|||
write: Option<u64>,
|
||||
size: u8,
|
||||
},
|
||||
ConvertMemory {
|
||||
gpa: u64,
|
||||
size: u64,
|
||||
private: bool,
|
||||
},
|
||||
Shutdown,
|
||||
Reboot,
|
||||
Unknown(String),
|
||||
|
|
|
@ -230,6 +230,7 @@ pub struct KvmRun {
|
|||
pub union KvmExit {
|
||||
pub mmio: KvmExitMmio,
|
||||
pub io: KvmExitIo,
|
||||
pub hypercall: KvmRunExitHypercall,
|
||||
pub padding: [u8; 256],
|
||||
}
|
||||
|
||||
|
@ -252,6 +253,15 @@ pub struct KvmExitIo {
|
|||
pub data_offset: u64,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct KvmRunExitHypercall {
|
||||
pub nr: u64,
|
||||
pub args: [u64; 6],
|
||||
pub ret: u64,
|
||||
pub flags: u64,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub union KvmSyncRegsBlock {
|
||||
|
@ -259,6 +269,7 @@ pub union KvmSyncRegsBlock {
|
|||
}
|
||||
|
||||
pub const KVM_EXIT_IO: u32 = 2;
|
||||
pub const KVM_EXIT_HYPERCALL: u32 = 3;
|
||||
pub const KVM_EXIT_MMIO: u32 = 6;
|
||||
pub const KVM_EXIT_SHUTDOWN: u32 = 8;
|
||||
|
||||
|
@ -384,11 +395,23 @@ pub struct KvmMsi {
|
|||
pub pad: [u8; 12usize],
|
||||
}
|
||||
|
||||
pub const KVM_CAP_NR_MEMSLOTS: u64 = 10;
|
||||
pub const KVM_CAP_IRQFD: u64 = 32;
|
||||
pub const KVM_CAP_SIGNAL_MSI: u64 = 77;
|
||||
pub const KVM_CAP_GUEST_MEMFD: u64 = 234;
|
||||
pub const KVM_CAP_VM_TYPES: u64 = 235;
|
||||
pub const KVM_CAP_NR_MEMSLOTS: u32 = 10;
|
||||
pub const KVM_CAP_IRQFD: u32 = 32;
|
||||
pub const KVM_CAP_SIGNAL_MSI: u32 = 77;
|
||||
pub const KVM_CAP_EXIT_HYPERCALL: u32 = 201;
|
||||
// pub const KVM_CAP_GUEST_MEMFD: u32 = 234;
|
||||
// pub const KVM_CAP_VM_TYPES: u32 = 235;
|
||||
|
||||
pub const KVM_HC_MAP_GPA_RANGE: u64 = 12;
|
||||
|
||||
bitflags! {
|
||||
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct KvmMapGpaRangeFlag: u64 {
|
||||
const PAGE_2M = 1 << 0;
|
||||
const PAGE_1G = 1 << 1;
|
||||
const ENCRYPTED = 1 << 4;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
|
@ -416,3 +439,12 @@ pub struct KvmEncRegion {
|
|||
pub addr: u64,
|
||||
pub size: u64,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct KvmEnableCap {
|
||||
pub cap: u32,
|
||||
pub flags: u32,
|
||||
pub args: [u64; 4],
|
||||
pub pad: [u8; 64],
|
||||
}
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
// limitations under the License.
|
||||
|
||||
use crate::hv::kvm::bindings::{
|
||||
KvmCpuid2, KvmCreateGuestMemfd, KvmEncRegion, KvmIoEventFd, KvmIrqRouting, KvmIrqfd,
|
||||
KvmMemoryAttributes, KvmMsi, KvmRegs, KvmSregs, KvmSregs2, KvmUserspaceMemoryRegion,
|
||||
KvmCpuid2, KvmCreateGuestMemfd, KvmEnableCap, KvmEncRegion, KvmIoEventFd, KvmIrqRouting,
|
||||
KvmIrqfd, KvmMemoryAttributes, KvmMsi, KvmRegs, KvmSregs, KvmSregs2, KvmUserspaceMemoryRegion,
|
||||
KvmUserspaceMemoryRegion2, KVMIO,
|
||||
};
|
||||
use crate::utils::ioctls::{ioctl_io, ioctl_ior, ioctl_iowr};
|
||||
|
@ -25,7 +25,7 @@ use crate::{
|
|||
|
||||
ioctl_none!(kvm_get_api_version, KVMIO, 0x00, 0);
|
||||
ioctl_write_val!(kvm_create_vm, ioctl_io(KVMIO, 0x01));
|
||||
ioctl_write_val!(kvm_check_extension, ioctl_io(KVMIO, 0x03));
|
||||
ioctl_write_val!(kvm_check_extension, ioctl_io(KVMIO, 0x03), u32);
|
||||
ioctl_none!(kvm_get_vcpu_mmap_size, KVMIO, 0x04, 0);
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
ioctl_writeread_buf!(kvm_get_supported_cpuid, KVMIO, 0x05, KvmCpuid2);
|
||||
|
@ -65,6 +65,7 @@ ioctl_write_ptr!(kvm_set_sregs, KVMIO, 0x84, KvmSregs);
|
|||
#[cfg(target_arch = "x86_64")]
|
||||
ioctl_write_buf!(kvm_set_cpuid2, KVMIO, 0x90, KvmCpuid2);
|
||||
|
||||
ioctl_write_ptr!(kvm_enable_cap, KVMIO, 0xa3, KvmEnableCap);
|
||||
ioctl_write_ptr!(kvm_signal_msi, KVMIO, 0xa5, KvmMsi);
|
||||
|
||||
ioctl_writeread!(kvm_memory_encrypt_op, ioctl_iowr::<u64>(KVMIO, 0xba));
|
||||
|
|
|
@ -43,12 +43,12 @@ use crate::hv::Cpuid;
|
|||
use crate::hv::{error, Coco, Hypervisor, MemMapOption, Result, VmConfig};
|
||||
|
||||
use bindings::{
|
||||
KvmCpuid2, KvmCpuid2Flag, KvmCpuidEntry2, KvmCreateGuestMemfd, KVM_API_VERSION,
|
||||
KVM_MAX_CPUID_ENTRIES, KVM_X86_DEFAULT_VM, KVM_X86_SNP_VM,
|
||||
KvmCpuid2, KvmCpuid2Flag, KvmCpuidEntry2, KvmCreateGuestMemfd, KvmEnableCap, KVM_API_VERSION,
|
||||
KVM_CAP_EXIT_HYPERCALL, KVM_MAX_CPUID_ENTRIES, KVM_X86_DEFAULT_VM, KVM_X86_SNP_VM,
|
||||
};
|
||||
use ioctls::{
|
||||
kvm_create_guest_memfd, kvm_create_irqchip, kvm_create_vm, kvm_get_api_version,
|
||||
kvm_get_vcpu_mmap_size,
|
||||
kvm_check_extension, kvm_create_guest_memfd, kvm_create_irqchip, kvm_create_vm, kvm_enable_cap,
|
||||
kvm_get_api_version, kvm_get_vcpu_mmap_size,
|
||||
};
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use ioctls::{kvm_get_supported_cpuid, kvm_set_identity_map_addr, kvm_set_tss_addr};
|
||||
|
@ -82,6 +82,16 @@ pub enum KvmError {
|
|||
MmapOption { option: MemMapOption },
|
||||
#[snafu(display("Failed to mmap a VCPU fd"))]
|
||||
MmapVcpuFd { error: std::io::Error },
|
||||
#[snafu(display("Failed to check extension {ext}"))]
|
||||
CheckExtension {
|
||||
ext: &'static str,
|
||||
error: std::io::Error,
|
||||
},
|
||||
#[snafu(display("Failed to enable capability {cap}"))]
|
||||
EnableCap {
|
||||
cap: &'static str,
|
||||
error: std::io::Error,
|
||||
},
|
||||
#[snafu(display("Failed to create guest memfd"))]
|
||||
GuestMemfd { error: std::io::Error },
|
||||
}
|
||||
|
@ -184,6 +194,23 @@ impl Hypervisor for Kvm {
|
|||
}
|
||||
}
|
||||
Coco::AmdSnp { .. } => {
|
||||
let bitmap = unsafe { kvm_check_extension(&kvm_vm.vm, KVM_CAP_EXIT_HYPERCALL) }
|
||||
.context(kvm_error::CheckExtension {
|
||||
ext: "KVM_CAP_EXIT_HYPERCALL",
|
||||
})?;
|
||||
if bitmap != 0 {
|
||||
let request = KvmEnableCap {
|
||||
cap: KVM_CAP_EXIT_HYPERCALL,
|
||||
args: [bitmap as _, 0, 0, 0],
|
||||
flags: 0,
|
||||
pad: [0; 64],
|
||||
};
|
||||
unsafe { kvm_enable_cap(&kvm_vm.vm, &request) }.context(
|
||||
kvm_error::EnableCap {
|
||||
cap: "KVM_CAP_EXIT_HYPERCALL",
|
||||
},
|
||||
)?;
|
||||
}
|
||||
let mut init = KvmSevInit::default();
|
||||
kvm_vm.sev_op(KVM_SEV_INIT2, Some(&mut init))?;
|
||||
log::debug!("vm-{}: snp init: {init:#x?}", kvm_vm.vm.as_raw_fd());
|
||||
|
|
|
@ -32,7 +32,7 @@ use crate::hv::{error, Error, Vcpu, VmEntry, VmExit};
|
|||
#[cfg(target_arch = "x86_64")]
|
||||
use crate::hv::{Cpuid, DtReg, DtRegVal, SReg, SegReg, SegRegVal};
|
||||
|
||||
use super::bindings::KVM_EXIT_SHUTDOWN;
|
||||
use super::bindings::{KVM_EXIT_HYPERCALL, KVM_EXIT_SHUTDOWN};
|
||||
|
||||
pub(super) struct KvmRunBlock {
|
||||
addr: usize,
|
||||
|
@ -147,6 +147,7 @@ impl Vcpu for KvmVcpu {
|
|||
},
|
||||
Ok(_) => match self.kvm_run.exit_reason {
|
||||
KVM_EXIT_IO => self.handle_io(),
|
||||
KVM_EXIT_HYPERCALL => self.handle_hypercall(),
|
||||
KVM_EXIT_MMIO => self.handle_mmio(),
|
||||
KVM_EXIT_SHUTDOWN => Ok(VmExit::Shutdown),
|
||||
reason => Ok(VmExit::Unknown(format!("unkown kvm exit: {:#x}", reason))),
|
||||
|
|
|
@ -106,7 +106,7 @@ impl VmInner {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn check_extension(&self, id: u64) -> Result<i32, Error> {
|
||||
fn check_extension(&self, id: u32) -> Result<i32, Error> {
|
||||
let ret = unsafe { kvm_check_extension(self, id) };
|
||||
match ret {
|
||||
Ok(num) => Ok(num),
|
||||
|
|
|
@ -12,7 +12,9 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::hv::kvm::bindings::{KVM_EXIT_IO_IN, KVM_EXIT_IO_OUT};
|
||||
use crate::hv::kvm::bindings::{
|
||||
KvmMapGpaRangeFlag, KVM_EXIT_IO_IN, KVM_EXIT_IO_OUT, KVM_HC_MAP_GPA_RANGE,
|
||||
};
|
||||
use crate::hv::{Error, VmExit};
|
||||
|
||||
use super::vcpu::KvmVcpu;
|
||||
|
@ -60,4 +62,19 @@ impl KvmVcpu {
|
|||
size: kvm_io.size,
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn handle_hypercall(&mut self) -> Result<VmExit, Error> {
|
||||
let hypercall = unsafe { self.kvm_run.exit.hypercall };
|
||||
match hypercall.nr {
|
||||
KVM_HC_MAP_GPA_RANGE => {
|
||||
let flag = KvmMapGpaRangeFlag::from_bits_retain(hypercall.args[2]);
|
||||
Ok(VmExit::ConvertMemory {
|
||||
gpa: hypercall.args[0],
|
||||
size: hypercall.args[1] << 12,
|
||||
private: flag.contains(KvmMapGpaRangeFlag::ENCRYPTED),
|
||||
})
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue