hv: vcpuid: present sgx capabilities to guest

If sgx is supported in guest, present SGX capabilities to guest.
There will be only one EPC section presented to guest, even if EPC
memory for a guest is from muiltiple physcial EPC sections.

Tracked-On: #3179
Signed-off-by: Binbin Wu <binbin.wu@intel.com>
Reviewed-by: Yan, Like <like.yan@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Binbin Wu 2019-05-22 15:30:05 +08:00 committed by ACRN System Integration
parent 65d437283e
commit 1724996bc5
2 changed files with 89 additions and 29 deletions

View File

@ -12,6 +12,7 @@
#include <cpuid.h> #include <cpuid.h>
#include <cpufeatures.h> #include <cpufeatures.h>
#include <vmx.h> #include <vmx.h>
#include <sgx.h>
#include <logmsg.h> #include <logmsg.h>
static inline const struct vcpuid_entry *local_find_vcpuid_entry(const struct acrn_vcpu *vcpu, static inline const struct vcpuid_entry *local_find_vcpuid_entry(const struct acrn_vcpu *vcpu,
@ -193,6 +194,80 @@ static void init_vcpuid_entry(uint32_t leaf, uint32_t subleaf,
} }
} }
static int32_t set_vcpuid_sgx(struct acrn_vm *vm)
{
int32_t result = 0;
if (is_vsgx_supported(vm->vm_id)) {
struct vcpuid_entry entry;
struct epc_map* maps;
uint32_t mid;
uint64_t size = 0;
/* init cpuid.12h.0h */
init_vcpuid_entry(CPUID_SGX_LEAF, 0U, CPUID_CHECK_SUBLEAF, &entry);
result = set_vcpuid_entry(vm, &entry);
/* init cpuid.12h.1h */
if (result == 0) {
init_vcpuid_entry(CPUID_SGX_LEAF, 1U, CPUID_CHECK_SUBLEAF, &entry);
/* MPX not present to guest */
entry.ecx &= ~XCR0_BNDREGS;
entry.ecx &= ~XCR0_BNDCSR;
result = set_vcpuid_entry(vm, &entry);
}
if (result == 0) {
maps = get_epc_mapping(vm->vm_id);
/* init cpuid.12h.2h, only build one EPC section for a VM */
for (mid = 0U; mid <= MAX_EPC_SECTIONS; mid++) {
size += maps[mid].size;
}
entry.leaf = CPUID_SGX_LEAF;
entry.subleaf = CPUID_SGX_EPC_SUBLEAF_BASE;
entry.flags = CPUID_CHECK_SUBLEAF;
entry.eax = CPUID_SGX_EPC_TYPE_VALID;
entry.eax |= (uint32_t)maps[0].gpa & CPUID_SGX_EPC_LOW_MASK;
entry.ebx = (uint32_t)(maps[0].gpa >> 32U) & CPUID_SGX_EPC_HIGH_MASK;
entry.ecx = (uint32_t)size & CPUID_SGX_EPC_LOW_MASK;
entry.edx = (uint32_t)(size >> 32U) & CPUID_SGX_EPC_HIGH_MASK;
result = set_vcpuid_entry(vm, &entry);
}
}
return result;
}
static int32_t set_vcpuid_extended_function(struct acrn_vm *vm)
{
uint32_t i, limit;
struct vcpuid_entry entry;
int32_t result;
init_vcpuid_entry(0x40000000U, 0U, 0U, &entry);
result = set_vcpuid_entry(vm, &entry);
if (result == 0) {
init_vcpuid_entry(0x40000010U, 0U, 0U, &entry);
result = set_vcpuid_entry(vm, &entry);
}
if (result == 0) {
init_vcpuid_entry(0x80000000U, 0U, 0U, &entry);
result = set_vcpuid_entry(vm, &entry);
}
if (result == 0) {
limit = entry.eax;
vm->vcpuid_xlevel = limit;
for (i = 0x80000002U; i <= limit; i++) {
init_vcpuid_entry(i, 0U, 0U, &entry);
result = set_vcpuid_entry(vm, &entry);
if (result != 0) {
break;
}
}
}
return result;
}
int32_t set_vcpuid_entries(struct acrn_vm *vm) int32_t set_vcpuid_entries(struct acrn_vm *vm)
{ {
int32_t result; int32_t result;
@ -237,17 +312,20 @@ int32_t set_vcpuid_entries(struct acrn_vm *vm)
pr_warn("vcpuid: only support subleaf 0 for cpu leaf 07h"); pr_warn("vcpuid: only support subleaf 0 for cpu leaf 07h");
entry.eax = 0U; entry.eax = 0U;
} }
if (is_vsgx_supported(vm->vm_id)) {
entry.ebx |= CPUID_EBX_SGX;
}
result = set_vcpuid_entry(vm, &entry); result = set_vcpuid_entry(vm, &entry);
break; break;
case 0x12U:
result = set_vcpuid_sgx(vm);
break;
/* These features are disabled */ /* These features are disabled */
/* PMU is not supported */ /* PMU is not supported */
case 0x0aU: case 0x0aU:
/* Intel RDT */ /* Intel RDT */
case 0x0fU: case 0x0fU:
case 0x10U: case 0x10U:
/* Intel SGX */
case 0x12U:
/* Intel Processor Trace */ /* Intel Processor Trace */
case 0x14U: case 0x14U:
break; break;
@ -265,29 +343,7 @@ int32_t set_vcpuid_entries(struct acrn_vm *vm)
} }
if (result == 0) { if (result == 0) {
init_vcpuid_entry(0x40000000U, 0U, 0U, &entry); result = set_vcpuid_extended_function(vm);
result = set_vcpuid_entry(vm, &entry);
if (result == 0) {
init_vcpuid_entry(0x40000010U, 0U, 0U, &entry);
result = set_vcpuid_entry(vm, &entry);
}
if (result == 0) {
init_vcpuid_entry(0x80000000U, 0U, 0U, &entry);
result = set_vcpuid_entry(vm, &entry);
}
if (result == 0) {
limit = entry.eax;
vm->vcpuid_xlevel = limit;
for (i = 0x80000002U; i <= limit; i++) {
init_vcpuid_entry(i, 0U, 0U, &entry);
result = set_vcpuid_entry(vm, &entry);
if (result != 0) {
break;
}
}
}
} }
} }

View File

@ -97,11 +97,15 @@
/* CPUID.01H:ECX.PCID*/ /* CPUID.01H:ECX.PCID*/
#define CPUID_ECX_PCID (1U<<17U) #define CPUID_ECX_PCID (1U<<17U)
/* CPUID.0DH.EAX.XCR0_BNDREGS */ /* CPUID.0DH.EAX.XCR0_BNDREGS */
#define CPUID_EAX_XCR0_BNDREGS (1U<<3U) #define CPUID_EAX_XCR0_BNDREGS (1U<<3U)
/* CPUID.0DH.EAX.XCR0_BNDCSR */ /* CPUID.0DH.EAX.XCR0_BNDCSR */
#define CPUID_EAX_XCR0_BNDCSR (1U<<4U) #define CPUID_EAX_XCR0_BNDCSR (1U<<4U)
/* CPUID.12H.EAX.SGX1 */
#define CPUID_EAX_SGX1 (1U<<0U)
/* CPUID.12H.EAX.SGX2 */
#define CPUID_EAX_SGX2 (1U<<1U)
/* CPUID.80000001H.EDX.XD_BIT_AVAILABLE */ /* CPUID.80000001H.EDX.XD_BIT_AVAILABLE */
#define CPUID_EDX_XD_BIT_AVIL (1U<<20U) #define CPUID_EDX_XD_BIT_AVIL (1U<<20U)
/* CPUID source operands */ /* CPUID source operands */
#define CPUID_VENDORSTRING 0U #define CPUID_VENDORSTRING 0U