97 lines · c
1/* SPDX-License-Identifier: GPL-2.0-only */2/*3 * Helpers used for SEV guests4 *5 */6#ifndef SELFTEST_KVM_SEV_H7#define SELFTEST_KVM_SEV_H8 9#include <stdint.h>10#include <stdbool.h>11 12#include "linux/psp-sev.h"13 14#include "kvm_util.h"15#include "svm_util.h"16#include "processor.h"17 18enum sev_guest_state {19 SEV_GUEST_STATE_UNINITIALIZED = 0,20 SEV_GUEST_STATE_LAUNCH_UPDATE,21 SEV_GUEST_STATE_LAUNCH_SECRET,22 SEV_GUEST_STATE_RUNNING,23};24 25#define SEV_POLICY_NO_DBG (1UL << 0)26#define SEV_POLICY_ES (1UL << 2)27 28#define GHCB_MSR_TERM_REQ 0x10029 30void sev_vm_launch(struct kvm_vm *vm, uint32_t policy);31void sev_vm_launch_measure(struct kvm_vm *vm, uint8_t *measurement);32void sev_vm_launch_finish(struct kvm_vm *vm);33 34struct kvm_vm *vm_sev_create_with_one_vcpu(uint32_t type, void *guest_code,35 struct kvm_vcpu **cpu);36void vm_sev_launch(struct kvm_vm *vm, uint32_t policy, uint8_t *measurement);37 38kvm_static_assert(SEV_RET_SUCCESS == 0);39 40/*41 * The KVM_MEMORY_ENCRYPT_OP uAPI is utter garbage and takes an "unsigned long"42 * instead of a proper struct. The size of the parameter is embedded in the43 * ioctl number, i.e. is ABI and thus immutable. Hack around the mess by44 * creating an overlay to pass in an "unsigned long" without a cast (casting45 * will make the compiler unhappy due to dereferencing an aliased pointer).46 */47#define __vm_sev_ioctl(vm, cmd, arg) \48({ \49 int r; \50 \51 union { \52 struct kvm_sev_cmd c; \53 unsigned long raw; \54 } sev_cmd = { .c = { \55 .id = (cmd), \56 .data = (uint64_t)(arg), \57 .sev_fd = (vm)->arch.sev_fd, \58 } }; \59 \60 r = __vm_ioctl(vm, KVM_MEMORY_ENCRYPT_OP, &sev_cmd.raw); \61 r ?: sev_cmd.c.error; \62})63 64#define vm_sev_ioctl(vm, cmd, arg) \65({ \66 int ret = __vm_sev_ioctl(vm, cmd, arg); \67 \68 __TEST_ASSERT_VM_VCPU_IOCTL(!ret, #cmd, ret, vm); \69})70 71void sev_vm_init(struct kvm_vm *vm);72void sev_es_vm_init(struct kvm_vm *vm);73 74static inline void sev_register_encrypted_memory(struct kvm_vm *vm,75 struct userspace_mem_region *region)76{77 struct kvm_enc_region range = {78 .addr = region->region.userspace_addr,79 .size = region->region.memory_size,80 };81 82 vm_ioctl(vm, KVM_MEMORY_ENCRYPT_REG_REGION, &range);83}84 85static inline void sev_launch_update_data(struct kvm_vm *vm, vm_paddr_t gpa,86 uint64_t size)87{88 struct kvm_sev_launch_update_data update_data = {89 .uaddr = (unsigned long)addr_gpa2hva(vm, gpa),90 .len = size,91 };92 93 vm_sev_ioctl(vm, KVM_SEV_LAUNCH_UPDATE_DATA, &update_data);94}95 96#endif /* SELFTEST_KVM_SEV_H */97