Path: blob/master/tools/testing/selftests/kvm/include/x86/sev.h
50058 views
/* SPDX-License-Identifier: GPL-2.0-only */1/*2* Helpers used for SEV guests3*4*/5#ifndef SELFTEST_KVM_SEV_H6#define SELFTEST_KVM_SEV_H78#include <stdint.h>9#include <stdbool.h>1011#include "linux/psp-sev.h"1213#include "kvm_util.h"14#include "svm_util.h"15#include "processor.h"1617enum sev_guest_state {18SEV_GUEST_STATE_UNINITIALIZED = 0,19SEV_GUEST_STATE_LAUNCH_UPDATE,20SEV_GUEST_STATE_LAUNCH_SECRET,21SEV_GUEST_STATE_RUNNING,22};2324#define SEV_POLICY_NO_DBG (1UL << 0)25#define SEV_POLICY_ES (1UL << 2)2627#define SNP_POLICY_SMT (1ULL << 16)28#define SNP_POLICY_RSVD_MBO (1ULL << 17)29#define SNP_POLICY_DBG (1ULL << 19)3031#define GHCB_MSR_TERM_REQ 0x1003233static inline bool is_sev_snp_vm(struct kvm_vm *vm)34{35return vm->type == KVM_X86_SNP_VM;36}3738static inline bool is_sev_es_vm(struct kvm_vm *vm)39{40return is_sev_snp_vm(vm) || vm->type == KVM_X86_SEV_ES_VM;41}4243static inline bool is_sev_vm(struct kvm_vm *vm)44{45return is_sev_es_vm(vm) || vm->type == KVM_X86_SEV_VM;46}4748void sev_vm_launch(struct kvm_vm *vm, uint32_t policy);49void sev_vm_launch_measure(struct kvm_vm *vm, uint8_t *measurement);50void sev_vm_launch_finish(struct kvm_vm *vm);51void snp_vm_launch_start(struct kvm_vm *vm, uint64_t policy);52void snp_vm_launch_update(struct kvm_vm *vm);53void snp_vm_launch_finish(struct kvm_vm *vm);5455struct kvm_vm *vm_sev_create_with_one_vcpu(uint32_t type, void *guest_code,56struct kvm_vcpu **cpu);57void vm_sev_launch(struct kvm_vm *vm, uint64_t policy, uint8_t *measurement);5859kvm_static_assert(SEV_RET_SUCCESS == 0);6061/*62* A SEV-SNP VM requires the policy reserved bit to always be set.63* The SMT policy bit is also required to be set based on SMT being64* available and active on the system.65*/66static inline u64 snp_default_policy(void)67{68return SNP_POLICY_RSVD_MBO | (is_smt_on() ? SNP_POLICY_SMT : 0);69}7071/*72* The KVM_MEMORY_ENCRYPT_OP uAPI is utter garbage and takes an "unsigned long"73* instead of a proper struct. The size of the parameter is embedded in the74* ioctl number, i.e. is ABI and thus immutable. Hack around the mess by75* creating an overlay to pass in an "unsigned long" without a cast (casting76* will make the compiler unhappy due to dereferencing an aliased pointer).77*/78#define __vm_sev_ioctl(vm, cmd, arg) \79({ \80int r; \81\82union { \83struct kvm_sev_cmd c; \84unsigned long raw; \85} sev_cmd = { .c = { \86.id = (cmd), \87.data = (uint64_t)(arg), \88.sev_fd = (vm)->arch.sev_fd, \89} }; \90\91r = __vm_ioctl(vm, KVM_MEMORY_ENCRYPT_OP, &sev_cmd.raw); \92r ?: sev_cmd.c.error; \93})9495#define vm_sev_ioctl(vm, cmd, arg) \96({ \97int ret = __vm_sev_ioctl(vm, cmd, arg); \98\99__TEST_ASSERT_VM_VCPU_IOCTL(!ret, #cmd, ret, vm); \100})101102void sev_vm_init(struct kvm_vm *vm);103void sev_es_vm_init(struct kvm_vm *vm);104void snp_vm_init(struct kvm_vm *vm);105106static inline void vmgexit(void)107{108__asm__ __volatile__("rep; vmmcall");109}110111static inline void sev_register_encrypted_memory(struct kvm_vm *vm,112struct userspace_mem_region *region)113{114struct kvm_enc_region range = {115.addr = region->region.userspace_addr,116.size = region->region.memory_size,117};118119vm_ioctl(vm, KVM_MEMORY_ENCRYPT_REG_REGION, &range);120}121122static inline void sev_launch_update_data(struct kvm_vm *vm, vm_paddr_t gpa,123uint64_t size)124{125struct kvm_sev_launch_update_data update_data = {126.uaddr = (unsigned long)addr_gpa2hva(vm, gpa),127.len = size,128};129130vm_sev_ioctl(vm, KVM_SEV_LAUNCH_UPDATE_DATA, &update_data);131}132133static inline void snp_launch_update_data(struct kvm_vm *vm, vm_paddr_t gpa,134uint64_t hva, uint64_t size, uint8_t type)135{136struct kvm_sev_snp_launch_update update_data = {137.uaddr = hva,138.gfn_start = gpa >> PAGE_SHIFT,139.len = size,140.type = type,141};142143vm_sev_ioctl(vm, KVM_SEV_SNP_LAUNCH_UPDATE, &update_data);144}145146#endif /* SELFTEST_KVM_SEV_H */147148149