diff options
-rw-r--r-- | util/inteltool/cpu.c | 139 | ||||
-rw-r--r-- | util/inteltool/inteltool.c | 15 | ||||
-rw-r--r-- | util/inteltool/inteltool.h | 7 |
3 files changed, 158 insertions, 3 deletions
diff --git a/util/inteltool/cpu.c b/util/inteltool/cpu.c index afafc636474b..7b2e50375787 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 ccb8facfa087..b997ee1b4508 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 e463260a43e8..d4aa96fc6002 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); |