sgxutils.c 2.0 KB
Newer Older
1 2 3 4 5 6 7 8 9
#include <unistd.h>
#include <stdint.h>
#include <stdbool.h>
#include "sgx.h"

static inline void cpuid(int *eax, int *ebx, int *ecx, int *edx)
{
#if defined(__x86_64__)
	asm volatile ("cpuid"
10 11 12
		      : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
		      : "0" (*eax), "2" (*ecx)
		      : "memory");
13
#else
14
	/* on 32bit, ebx can NOT be used as PIC code */
15
	asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1"
16 17 18
		      : "=a" (*eax), "=r" (*ebx), "=c" (*ecx), "=d" (*edx)
		      : "0" (*eax), "2" (*ecx)
		      : "memory");
19 20 21 22 23
#endif
}

static inline void __cpuid(int a[4], int b)
{
24 25 26
	a[0] = b;
	a[2] = 0;
	cpuid(&a[0], &a[1], &a[2], &a[3]);
27 28 29 30
}

static inline void __cpuidex(int a[4], int b, int c)
{
31 32 33
	a[0] = b;
	a[2] = c;
	cpuid(&a[0], &a[1], &a[2], &a[3]);
34 35 36 37
}

static inline uint64_t xgetbv(uint32_t index)
{
38
	uint32_t eax, edx;
39

40 41 42
	asm volatile(".byte 0x0f,0x01,0xd0" /* xgetbv */
		     : "=a" (eax), "=d" (edx)
		     : "c" (index));
43

44
	return eax + ((uint64_t)edx << 32);
45 46 47 48
}

static inline uint64_t get_xcr0()
{
49
	return xgetbv(0);
50 51
}

52
static uint64_t try_get_xcr0()
53
{
54
	int cpu_info[4] = {0, 0, 0, 0};
55

56
	// Check if xgetbv instruction is supported.
57
	__cpuid(cpu_info, 1);
58 59 60
	// ecx[27:26] indicate whether support xsave/xrstor, and whether enable xgetbv, xsetbv.
	if (!(cpu_info[2] & (1 << OSXSAVE_SHIFT)))
		return SGX_XFRM_LEGACY;
61

62 63
	// If XSAVE is supported, while XSAVEC is not supported,
	// set xfrm to legacy, because skeleton requires XSAVEC feature available on the path of enclave-exit.
64
	__cpuidex(cpu_info, 0xD, 1);
65 66
	if (!(cpu_info[0] & (1 << XSAVEC_SHIFT)))
		return SGX_XFRM_LEGACY;
67

68 69 70
	// If x-feature is supported and enabled by OS, we need make sure it is also supported in enclave.
	__cpuidex(cpu_info, SGX_LEAF, 1);
	return (get_xcr0() & (((uint64_t)cpu_info[3] << 32) | cpu_info[2]));
71 72 73 74
}

void get_sgx_xfrm_by_cpuid(uint64_t *xfrm)
{
75
	*xfrm = try_get_xcr0();
76
}
77 78 79 80 81 82 83 84 85

bool is_launch_control_supported(void)
{
	int cpu_info[4] = {0, 0, 0, 0};

	__cpuidex(cpu_info, CPUIID_EXTENDED_FEATURE_FLAGS, 0);

	return !!(cpu_info[2] & 0x40000000);
}