summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--util/inteltool/cpu.c139
-rw-r--r--util/inteltool/inteltool.c15
-rw-r--r--util/inteltool/inteltool.h7
3 files changed, 158 insertions, 3 deletions
diff --git a/util/inteltool/cpu.c b/util/inteltool/cpu.c
index afafc63647..7b2e503757 100644
--- a/util/inteltool/cpu.c
+++ b/util/inteltool/cpu.c
@@ -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;
diff --git a/util/inteltool/inteltool.c b/util/inteltool/inteltool.c
index ccb8facfa0..b997ee1b45 100644
--- a/util/inteltool/inteltool.c
+++ b/util/inteltool/inteltool.c
@@ -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);
diff --git a/util/inteltool/inteltool.h b/util/inteltool/inteltool.h
index e463260a43..d4aa96fc60 100644
--- a/util/inteltool/inteltool.h
+++ b/util/inteltool/inteltool.h
@@ -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);