Skip to content

Commit 245a732

Browse files
binbinwu1acrnsi
authored andcommitted
hv: sgx: add basic support to init sgx resource for vm
Get the platform EPC resource and partiton the EPC resource for VMs according to VM configurations. Don't support sgx capability in SOS VM. init_sgx is called during platform bsp initialization. If init_sgx() fails, consider it as configuration error, panic the system. init_sgx() fails if one of the following happens when at least one VM requests EPC resource if no enough EPC resource for all VMs. No further check if sgx is not supported by platform or not opted-in in BIOS, just disable SGX support for VMs. Tracked-On: #3179 Signed-off-by: Binbin Wu <binbin.wu@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
1 parent c5cfd7c commit 245a732

File tree

5 files changed

+228
-0
lines changed

5 files changed

+228
-0
lines changed

hypervisor/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ C_SRCS += arch/x86/guest/trusty.c
215215
C_SRCS += arch/x86/guest/vm_reset.c
216216
C_SRCS += arch/x86/cat.c
217217
C_SRCS += arch/x86/lib/memory.c
218+
C_SRCS += arch/x86/sgx.c
218219
C_SRCS += lib/string.c
219220
C_SRCS += lib/crypto/crypto_api.c
220221
C_SRCS += lib/crypto/mbedtls/hkdf.c

hypervisor/arch/x86/cpu.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <logmsg.h>
2727
#include <cat.h>
2828
#include <vboot.h>
29+
#include <sgx.h>
2930

3031
#define CPU_UP_TIMEOUT 100U /* millisecond */
3132
#define CPU_DOWN_TIMEOUT 100U /* millisecond */
@@ -231,6 +232,10 @@ void init_pcpu_post(uint16_t pcpu_id)
231232

232233
ptdev_init();
233234

235+
if (init_sgx() != 0) {
236+
panic("failed to initialize sgx!");
237+
}
238+
234239
/* Start all secondary cores */
235240
startup_paddr = prepare_trampoline();
236241
if (!start_pcpus(AP_MASK)) {

hypervisor/arch/x86/sgx.c

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/*
2+
* Copyright (C) 2019 Intel Corporation. All rights reserved.
3+
*
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*/
6+
7+
#include <types.h>
8+
#include <errno.h>
9+
#include <cpufeatures.h>
10+
#include <cpu_caps.h>
11+
#include <sgx.h>
12+
#include <cpuid.h>
13+
#include <vm.h>
14+
#include <logmsg.h>
15+
16+
#define SGX_OPTED_IN (MSR_IA32_FEATURE_CONTROL_SGX_GE | MSR_IA32_FEATURE_CONTROL_LOCK)
17+
18+
/* For the static variables, which are not explicitly initialzed will be inited to 0 */
19+
static int32_t init_sgx_ret = 0;
20+
static struct epc_section pepc_sections[MAX_EPC_SECTIONS]; /* physcial epc sections */
21+
static struct epc_map vm_epc_maps[MAX_EPC_SECTIONS][CONFIG_MAX_VM_NUM]; /* epc resource mapping for VMs */
22+
23+
static int32_t get_epc_section(uint32_t sec_id, uint64_t* base, uint64_t* size)
24+
{
25+
uint32_t eax = 0U, ebx = 0U, ecx = 0U, edx = 0U, type;
26+
int32_t ret = 0;
27+
28+
cpuid_subleaf(CPUID_SGX_LEAF, sec_id + CPUID_SGX_EPC_SUBLEAF_BASE, &eax, &ebx, &ecx, &edx);
29+
type = eax & CPUID_SGX_EPC_TYPE_MASK;
30+
if (type == CPUID_SGX_EPC_TYPE_VALID) {
31+
*base = (((uint64_t)ebx & CPUID_SGX_EPC_HIGH_MASK) << 32U) |
32+
((uint64_t)eax & CPUID_SGX_EPC_LOW_MASK);
33+
*size = (((uint64_t)edx & CPUID_SGX_EPC_HIGH_MASK) << 32U) |
34+
((uint64_t)ecx & CPUID_SGX_EPC_LOW_MASK);
35+
if (*size != 0UL) {
36+
pepc_sections[sec_id].base = *base;
37+
pepc_sections[sec_id].size = *size;
38+
} else {
39+
ret = -EINVAL;
40+
}
41+
} else if (type == CPUID_SGX_EPC_TYPE_INVALID) {
42+
/* indicate the end of epc enumeration */
43+
} else {
44+
pr_err("%s: unsupport EPC type %u", __func__, type);
45+
ret = -EINVAL;
46+
}
47+
48+
return ret;
49+
}
50+
51+
/* Enumerate physcial EPC resource and partition it according to VM configurations.
52+
* Build the mappings between HPA and GPA for EPT mapping later.
53+
* EPC resource partition and mapping relationship will stay unchanged after sgx init.
54+
*/
55+
static int32_t partition_epc(void)
56+
{
57+
uint16_t vm_id = 0U;
58+
uint32_t psec_id = 0U, mid = 0U;
59+
uint64_t psec_addr = 0UL, psec_size = 0UL;
60+
uint64_t vm_request_size = 0UL, free_size = 0UL, alloc_size;
61+
struct acrn_vm_config *vm_config;
62+
int32_t ret = 0;
63+
64+
while ((psec_id < MAX_EPC_SECTIONS) && (vm_id < CONFIG_MAX_VM_NUM)) {
65+
if (vm_request_size == 0U) {
66+
mid = 0U;
67+
vm_config = get_vm_config(vm_id);
68+
vm_request_size = vm_config->epc.size;
69+
}
70+
if ((free_size == 0UL) && (vm_request_size != 0UL)) {
71+
ret = get_epc_section(psec_id, &psec_addr, &psec_size);
72+
free_size = psec_size;
73+
if ((ret != 0) || (free_size == 0UL)) {
74+
break;
75+
}
76+
psec_id++;
77+
}
78+
if (vm_request_size != 0UL) {
79+
if (vm_request_size <= free_size) {
80+
alloc_size = vm_request_size;
81+
} else {
82+
alloc_size = free_size;
83+
}
84+
vm_epc_maps[mid][vm_id].size = alloc_size;
85+
vm_epc_maps[mid][vm_id].hpa = psec_addr + psec_size - free_size;
86+
vm_epc_maps[mid][vm_id].gpa = vm_config->epc.base + vm_config->epc.size - vm_request_size;
87+
vm_request_size -= alloc_size;
88+
free_size -= alloc_size;
89+
mid++;
90+
}
91+
if (vm_request_size == 0UL) {
92+
vm_id++;
93+
}
94+
}
95+
if (vm_request_size != 0UL) {
96+
ret = -ENOMEM;
97+
}
98+
99+
return ret;
100+
}
101+
102+
struct epc_section* get_phys_epc(void)
103+
{
104+
return pepc_sections;
105+
}
106+
107+
struct epc_map* get_epc_mapping(uint16_t vm_id)
108+
{
109+
return &vm_epc_maps[0][vm_id];
110+
}
111+
112+
int32_t init_sgx(void)
113+
{
114+
if (pcpu_has_cap(X86_FEATURE_SGX)) {
115+
if ((msr_read(MSR_IA32_FEATURE_CONTROL) & SGX_OPTED_IN) == SGX_OPTED_IN){
116+
init_sgx_ret = partition_epc();
117+
if (init_sgx_ret != 0) {
118+
pr_err("Please change SGX/PRM setting in BIOS or EPC setting in VM config");
119+
}
120+
}
121+
}
122+
123+
return init_sgx_ret;
124+
}
125+
126+
bool is_vsgx_supported(uint16_t vm_id)
127+
{
128+
return ((init_sgx_ret == 0) && (vm_epc_maps[0][vm_id].size != 0U));
129+
}

hypervisor/include/arch/x86/cpufeatures.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070

7171
/* Intel-defined CPU features, CPUID level 0x00000007 (EBX)*/
7272
#define X86_FEATURE_TSC_ADJ ((FEAT_7_0_EBX << 5U) + 1U)
73+
#define X86_FEATURE_SGX ((FEAT_7_0_EBX << 5U) + 2U)
7374
#define X86_FEATURE_SMEP ((FEAT_7_0_EBX << 5U) + 7U)
7475
#define X86_FEATURE_ERMS ((FEAT_7_0_EBX << 5U) + 9U)
7576
#define X86_FEATURE_INVPCID ((FEAT_7_0_EBX << 5U) + 10U)

hypervisor/include/arch/x86/sgx.h

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* Copyright (C) 2019 Intel Corporation. All rights reserved.
3+
*
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*/
6+
7+
#ifndef SGX_H
8+
#define SGX_H
9+
10+
#define CPUID_SGX_LEAF 0x12U
11+
#define CPUID_SGX_EPC_SUBLEAF_BASE 0x2U
12+
#define CPUID_SGX_EPC_TYPE_MASK 0xFU
13+
#define CPUID_SGX_EPC_TYPE_INVALID 0x0U
14+
#define CPUID_SGX_EPC_TYPE_VALID 0x1U
15+
#define CPUID_SGX_EPC_HIGH_MASK 0x000FFFFFU
16+
#define CPUID_SGX_EPC_LOW_MASK 0xFFFFF000U
17+
18+
#define MAX_EPC_SECTIONS 4U
19+
/**
20+
* @file sgx.h
21+
*
22+
* @brief public APIs for SGX
23+
*/
24+
25+
/**
26+
* @brief SGX
27+
*
28+
* @defgroup acrn_sgx ACRN SGX
29+
* @{
30+
*/
31+
32+
struct epc_section
33+
{
34+
uint64_t base; /* EPC section base, must be page aligned */
35+
uint64_t size; /* EPC section size in byte, must be page aligned */
36+
};
37+
38+
struct epc_map
39+
{
40+
uint64_t hpa; /* EPC reource address in host, must be page aligned */
41+
uint64_t gpa; /* EPC reource address in guest, must be page aligned */
42+
uint64_t size; /* EPC reource size in byte, must be page aligned */
43+
};
44+
45+
/**
46+
* @brief Get physcial EPC sections of the platform.
47+
*
48+
* @retval Physical EPC sections of the platform
49+
*
50+
*/
51+
struct epc_section* get_phys_epc(void);
52+
53+
/**
54+
* @brief Get EPC resource information for a specific VM.
55+
*
56+
* @param[in] vm_id VM ID to specify a VM
57+
*
58+
* @retval EPC sections for a VM
59+
*
60+
* @pre vm_id < CONFIG_MAX_VM_NUM
61+
*
62+
*/
63+
struct epc_map* get_epc_mapping(uint16_t vm_id);
64+
65+
/**
66+
* @brief If SGX support is enabled or not for a specific VM.
67+
*
68+
* @param[in] vm_id VM ID to specify a VM
69+
*
70+
* @retval True when SGX is supported in the specific VM
71+
* @retval False When SGX is not supported in the specific VM
72+
*
73+
* @pre vm_id < CONFIG_MAX_VM_NUM
74+
*
75+
*/
76+
bool is_vsgx_supported(uint16_t vm_id);
77+
78+
/**
79+
* @brief SGX initialization.
80+
*
81+
* Init SGX and parition EPC resource for VMs.
82+
*
83+
* @retval 0 on success
84+
* @retval <0 on failure
85+
*
86+
*/
87+
int32_t init_sgx(void);
88+
/**
89+
* @}
90+
*/
91+
92+
#endif

0 commit comments

Comments
 (0)