util/inteltool: Add support for SGX status
Add support for dumping Intel Software Guard Extension (SGX) status. --sgx or -x is the command line switch to get SGX status. The code iterates through all cores and reads MSRs to check if SGX is supported, enabled and the feature is locked. Change-Id: I1f5046c1f6703f5429c8717053ffe9c981cedf6f Signed-off-by: Pratik Prajapati <pratikkumar.v.prajapati@intel.com> Reviewed-on: https://review.coreboot.org/20758 Reviewed-by: Philipp Deppenwiese <zaolin.daisuki@gmail.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
This commit is contained in:
parent
a1af090002
commit
91664d4d6f
|
@ -28,6 +28,13 @@
|
|||
# define BREG "%%ebx"
|
||||
#endif
|
||||
|
||||
#define IA32_FEATURE_CONTROL 0x3a
|
||||
#define SGX_GLOBAL_ENABLED (1 << 18)
|
||||
#define FEATURE_CONTROL_LOCKED (1)
|
||||
#define MTRR_CAP_MSR 0xfe
|
||||
#define PRMRR_SUPPORTED (1 << 12)
|
||||
#define SGX_SUPPORTED (1 << 2)
|
||||
|
||||
int fd_msr;
|
||||
|
||||
unsigned int cpuid(unsigned int op)
|
||||
|
@ -48,6 +55,26 @@ unsigned int cpuid(unsigned int op)
|
|||
return ret;
|
||||
}
|
||||
|
||||
inline cpuid_result_t cpuid_ext(int op, unsigned int ecx)
|
||||
{
|
||||
cpuid_result_t result;
|
||||
|
||||
#ifndef __DARWIN__
|
||||
asm volatile (
|
||||
"mov %%ebx, %%edi;"
|
||||
"cpuid;"
|
||||
"mov %%ebx, %%esi;"
|
||||
"mov %%edi, %%ebx;"
|
||||
: "=a" (result.eax),
|
||||
"=S" (result.ebx),
|
||||
"=c" (result.ecx),
|
||||
"=d" (result.edx)
|
||||
: "0" (op), "2" (ecx)
|
||||
: "edi");
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifndef __DARWIN__
|
||||
int msr_readerror = 0;
|
||||
|
||||
|
@ -80,8 +107,120 @@ msr_t rdmsr(int addr)
|
|||
|
||||
return msr;
|
||||
}
|
||||
|
||||
static int open_and_seek(int cpu, unsigned long msr, int mode, int *fd)
|
||||
{
|
||||
char dev[512];
|
||||
char temp_string[50];
|
||||
|
||||
snprintf(dev, sizeof(dev), "/dev/cpu/%d/msr", cpu);
|
||||
*fd = open(dev, mode);
|
||||
|
||||
if (*fd < 0) {
|
||||
sprintf(temp_string,
|
||||
"open(\"%s\"): %s\n", dev, strerror(errno));
|
||||
perror(temp_string);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (lseek(*fd, msr, SEEK_SET) == (off_t)-1) {
|
||||
sprintf(temp_string, "lseek(%lu): %s\n", msr, strerror(errno));
|
||||
perror(temp_string);
|
||||
close(*fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
msr_t rdmsr_from_cpu(int cpu, unsigned long addr)
|
||||
{
|
||||
int fd;
|
||||
msr_t msr = { 0xffffffff, 0xffffffff };
|
||||
uint32_t buf[2];
|
||||
char temp_string[50];
|
||||
|
||||
if (open_and_seek(cpu, addr, O_RDONLY, &fd) < 0) {
|
||||
sprintf(temp_string, "Could not read MSR for CPU#%d", cpu);
|
||||
perror(temp_string);
|
||||
}
|
||||
|
||||
if (read(fd, buf, 8) == 8) {
|
||||
msr.lo = buf[0];
|
||||
msr.hi = buf[1];
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
return msr;
|
||||
}
|
||||
|
||||
int get_number_of_cpus(void)
|
||||
{
|
||||
return sysconf(_SC_NPROCESSORS_ONLN);
|
||||
}
|
||||
|
||||
int is_sgx_supported(int cpunum)
|
||||
{
|
||||
cpuid_result_t cpuid_regs;
|
||||
msr_t msr;
|
||||
|
||||
/* CPUID leaf 0x7 subleaf 0x0 to detect SGX support
|
||||
details are mentioned in Intel SDM Chap.36- section 36.7 */
|
||||
cpuid_regs = cpuid_ext(0x7, 0x0);
|
||||
msr = rdmsr_from_cpu(cpunum, MTRR_CAP_MSR);
|
||||
return ((cpuid_regs.ebx & SGX_SUPPORTED) && (msr.lo & PRMRR_SUPPORTED));
|
||||
}
|
||||
|
||||
int is_sgx_enabled(int cpunum)
|
||||
{
|
||||
msr_t data;
|
||||
data = rdmsr_from_cpu(cpunum, IA32_FEATURE_CONTROL);
|
||||
return (data.lo & SGX_GLOBAL_ENABLED);
|
||||
}
|
||||
|
||||
int is_sgx_locked(int cpunum)
|
||||
{
|
||||
msr_t data;
|
||||
data = rdmsr_from_cpu(cpunum, IA32_FEATURE_CONTROL);
|
||||
return (data.lo & FEATURE_CONTROL_LOCKED);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int print_sgx(void)
|
||||
{
|
||||
int error = -1;
|
||||
#ifndef __DARWIN__
|
||||
int ncpus = get_number_of_cpus();
|
||||
int i = 0;
|
||||
char temp_string[50];
|
||||
|
||||
printf("\n============= Dumping INTEL SGX status =============");
|
||||
|
||||
if (ncpus < 1) {
|
||||
sprintf(temp_string, "Failed to get number of CPUs\n");
|
||||
perror(temp_string);
|
||||
error = -1;
|
||||
} else {
|
||||
printf("\nNumber of CPUs = %d\n", ncpus);
|
||||
for (i = 0; i < ncpus ; i++) {
|
||||
|
||||
printf("------------- CPU %d ----------------\n", i);
|
||||
printf("SGX supported : %s\n",
|
||||
is_sgx_supported(i) ? "YES" : "NO");
|
||||
printf("SGX enabled : %s\n",
|
||||
is_sgx_enabled(i) ? "YES" : "NO");
|
||||
printf("Feature Control locked : %s\n",
|
||||
is_sgx_locked(i) ? "YES" : "NO");
|
||||
}
|
||||
error = 0;
|
||||
}
|
||||
printf("====================================================\n");
|
||||
#endif
|
||||
return error;
|
||||
}
|
||||
|
||||
int print_intel_core_msrs(void)
|
||||
{
|
||||
unsigned int i, core, id;
|
||||
|
|
|
@ -244,7 +244,7 @@ void print_version(void)
|
|||
|
||||
void print_usage(const char *name)
|
||||
{
|
||||
printf("usage: %s [-vh?gGrpmedPMaAsfSR]\n", name);
|
||||
printf("usage: %s [-vh?gGrpmedPMaAsfSRx]\n", name);
|
||||
printf("\n"
|
||||
" -v | --version: print the version\n"
|
||||
" -h | --help: print this help\n\n"
|
||||
|
@ -262,6 +262,7 @@ void print_usage(const char *name)
|
|||
" -P | --pciexpress: dump northbridge PCIEXBAR registers\n\n"
|
||||
" -M | --msrs: dump CPU MSRs\n"
|
||||
" -A | --ambs: dump AMB registers\n"
|
||||
" -x | --sgx: dump SGX status\n"
|
||||
" -a | --all: dump all known (safe) registers\n"
|
||||
"\n");
|
||||
exit(1);
|
||||
|
@ -280,7 +281,7 @@ int main(int argc, char *argv[])
|
|||
int dump_gpios = 0, dump_mchbar = 0, dump_rcba = 0;
|
||||
int dump_pmbase = 0, dump_epbar = 0, dump_dmibar = 0;
|
||||
int dump_pciexbar = 0, dump_coremsrs = 0, dump_ambs = 0;
|
||||
int dump_spi = 0, dump_gfx = 0, dump_ahci = 0;
|
||||
int dump_spi = 0, dump_gfx = 0, dump_ahci = 0, dump_sgx = 0;
|
||||
int show_gpio_diffs = 0;
|
||||
|
||||
static struct option long_options[] = {
|
||||
|
@ -301,10 +302,11 @@ int main(int argc, char *argv[])
|
|||
{"all", 0, 0, 'a'},
|
||||
{"gfx", 0, 0, 'f'},
|
||||
{"ahci", 0, 0, 'R'},
|
||||
{"sgx", 0, 0, 'x'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "vh?gGrpmedPMaAsfRS:",
|
||||
while ((opt = getopt_long(argc, argv, "vh?gGrpmedPMaAsfRS:x",
|
||||
long_options, &option_index)) != EOF) {
|
||||
switch (opt) {
|
||||
case 'v':
|
||||
|
@ -361,6 +363,7 @@ int main(int argc, char *argv[])
|
|||
dump_ambs = 1;
|
||||
dump_spi = 1;
|
||||
dump_ahci = 1;
|
||||
dump_sgx = 1;
|
||||
break;
|
||||
case 'A':
|
||||
dump_ambs = 1;
|
||||
|
@ -368,6 +371,9 @@ int main(int argc, char *argv[])
|
|||
case 's':
|
||||
dump_spi = 1;
|
||||
break;
|
||||
case 'x':
|
||||
dump_sgx = 1;
|
||||
break;
|
||||
case 'h':
|
||||
case '?':
|
||||
default:
|
||||
|
@ -575,6 +581,9 @@ int main(int argc, char *argv[])
|
|||
print_ahci(ahci);
|
||||
}
|
||||
|
||||
if (dump_sgx)
|
||||
print_sgx();
|
||||
|
||||
/* Clean up */
|
||||
if (ahci)
|
||||
pci_free_dev(ahci);
|
||||
|
|
|
@ -224,6 +224,12 @@ msr_t freebsd_rdmsr(int addr);
|
|||
int freebsd_wrmsr(int addr, msr_t msr);
|
||||
#endif
|
||||
typedef struct { uint16_t addr; int size; char *name; } io_register_t;
|
||||
typedef struct {
|
||||
uint32_t eax;
|
||||
uint32_t ebx;
|
||||
uint32_t ecx;
|
||||
uint32_t edx;
|
||||
} cpuid_result_t;
|
||||
|
||||
void *map_physical(uint64_t phys_addr, size_t len);
|
||||
void unmap_physical(void *virt_addr, size_t len);
|
||||
|
@ -241,4 +247,5 @@ int print_ambs(struct pci_dev *nb, struct pci_access *pacc);
|
|||
int print_spi(struct pci_dev *sb);
|
||||
int print_gfx(struct pci_dev *gfx);
|
||||
int print_ahci(struct pci_dev *ahci);
|
||||
int print_sgx(void);
|
||||
void ivybridge_dump_timings(const char *dump_spd_file);
|
||||
|
|
Loading…
Reference in New Issue