acrn-hypervisor/hypervisor/arch/x86/sgx.c
Geoffroy Van Cutsem 8b16be9185 Remove "All rights reserved" string headers
Many of the license and Intel copyright headers include the "All rights
reserved" string. It is not relevant in the context of the BSD-3-Clause
license that the code is released under. This patch removes those strings
throughout the code (hypervisor, devicemodel and misc).

Tracked-On: #7254
Signed-off-by: Geoffroy Van Cutsem <geoffroy.vancutsem@intel.com>
2022-04-06 13:21:02 +08:00

130 lines
3.5 KiB
C

/*
* Copyright (C) 2019 Intel Corporation.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <types.h>
#include <errno.h>
#include <asm/cpufeatures.h>
#include <asm/cpu_caps.h>
#include <asm/sgx.h>
#include <asm/cpuid.h>
#include <asm/guest/vm.h>
#include <logmsg.h>
#define SGX_OPTED_IN (MSR_IA32_FEATURE_CONTROL_SGX_GE | MSR_IA32_FEATURE_CONTROL_LOCK)
/* For the static variables, which are not explicitly initialzed will be inited to 0 */
static int32_t init_sgx_ret = 0;
static struct epc_section pepc_sections[MAX_EPC_SECTIONS]; /* physcial epc sections */
static struct epc_map vm_epc_maps[MAX_EPC_SECTIONS][CONFIG_MAX_VM_NUM]; /* epc resource mapping for VMs */
static int32_t get_epc_section(uint32_t sec_id, uint64_t* base, uint64_t* size)
{
uint32_t eax = 0U, ebx = 0U, ecx = 0U, edx = 0U, type;
int32_t ret = 0;
cpuid_subleaf(CPUID_SGX_LEAF, sec_id + CPUID_SGX_EPC_SUBLEAF_BASE, &eax, &ebx, &ecx, &edx);
type = eax & CPUID_SGX_EPC_TYPE_MASK;
if (type == CPUID_SGX_EPC_TYPE_VALID) {
*base = (((uint64_t)ebx & CPUID_SGX_EPC_HIGH_MASK) << 32U) |
((uint64_t)eax & CPUID_SGX_EPC_LOW_MASK);
*size = (((uint64_t)edx & CPUID_SGX_EPC_HIGH_MASK) << 32U) |
((uint64_t)ecx & CPUID_SGX_EPC_LOW_MASK);
if (*size != 0UL) {
pepc_sections[sec_id].base = *base;
pepc_sections[sec_id].size = *size;
} else {
ret = -EINVAL;
}
} else if (type == CPUID_SGX_EPC_TYPE_INVALID) {
/* indicate the end of epc enumeration */
} else {
pr_err("%s: unsupport EPC type %u", __func__, type);
ret = -EINVAL;
}
return ret;
}
/* Enumerate physcial EPC resource and partition it according to VM configurations.
* Build the mappings between HPA and GPA for EPT mapping later.
* EPC resource partition and mapping relationship will stay unchanged after sgx init.
*/
static int32_t partition_epc(void)
{
uint16_t vm_id = 0U;
uint32_t psec_id = 0U, mid = 0U;
uint64_t psec_addr = 0UL, psec_size = 0UL;
uint64_t vm_request_size = 0UL, free_size = 0UL, alloc_size;
struct acrn_vm_config *vm_config;
int32_t ret = 0;
while ((psec_id < MAX_EPC_SECTIONS) && (vm_id < CONFIG_MAX_VM_NUM)) {
if (vm_request_size == 0U) {
mid = 0U;
vm_config = get_vm_config(vm_id);
vm_request_size = vm_config->epc.size;
}
if ((free_size == 0UL) && (vm_request_size != 0UL)) {
ret = get_epc_section(psec_id, &psec_addr, &psec_size);
free_size = psec_size;
if ((ret != 0) || (free_size == 0UL)) {
break;
}
psec_id++;
}
if (vm_request_size != 0UL) {
if (vm_request_size <= free_size) {
alloc_size = vm_request_size;
} else {
alloc_size = free_size;
}
vm_epc_maps[mid][vm_id].size = alloc_size;
vm_epc_maps[mid][vm_id].hpa = psec_addr + psec_size - free_size;
vm_epc_maps[mid][vm_id].gpa = vm_config->epc.base + vm_config->epc.size - vm_request_size;
vm_request_size -= alloc_size;
free_size -= alloc_size;
mid++;
}
if (vm_request_size == 0UL) {
vm_id++;
}
}
if (vm_request_size != 0UL) {
ret = -ENOMEM;
}
return ret;
}
struct epc_section* get_phys_epc(void)
{
return pepc_sections;
}
struct epc_map* get_epc_mapping(uint16_t vm_id)
{
return &vm_epc_maps[0][vm_id];
}
int32_t init_sgx(void)
{
if (pcpu_has_cap(X86_FEATURE_SGX)) {
if ((msr_read(MSR_IA32_FEATURE_CONTROL) & SGX_OPTED_IN) == SGX_OPTED_IN){
init_sgx_ret = partition_epc();
if (init_sgx_ret != 0) {
pr_err("Please change SGX/PRM setting in BIOS or EPC setting in VM config");
}
}
}
return init_sgx_ret;
}
bool is_vsgx_supported(uint16_t vm_id)
{
return ((init_sgx_ret == 0) && (vm_epc_maps[0][vm_id].size != 0U));
}