Skip to content

Commit

Permalink
[Pal] Move x86_64-specific CPUID into cpu.h, pal-arch.h, db_main-x86_…
Browse files Browse the repository at this point in the history
…64.c
  • Loading branch information
stefanberger authored and Dmitrii Kuvaiskii committed Jun 18, 2020
1 parent 91c97f6 commit 0831193
Show file tree
Hide file tree
Showing 12 changed files with 378 additions and 363 deletions.
2 changes: 1 addition & 1 deletion Documentation/Doxyfile-pal
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ INPUT = ../Pal/include/arch/x86_64 ../Pal/include/pal ../Pal/src
EXCLUDE = ../Pal/src/host
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
PREDEFINED = noreturn=
PREDEFINED = noreturn= __x86_64__=1
26 changes: 22 additions & 4 deletions Pal/include/arch/x86_64/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,30 @@ static inline void cpu_pause(void) {
__asm__ volatile("pause");
}

enum PAL_CPUID_WORD {
PAL_CPUID_WORD_EAX = 0,
PAL_CPUID_WORD_EBX = 1,
PAL_CPUID_WORD_ECX = 2,
PAL_CPUID_WORD_EDX = 3,
PAL_CPUID_WORD_NUM = 4,
};

#define INTEL_SGX_LEAF 0x12 /* Intel SGX Capabilities: CPUID Leaf 12H */

static inline void cpuid(unsigned int leaf, unsigned int subleaf, unsigned int words[]) {
__asm__ ("cpuid"
: "=a" (words[PAL_CPUID_WORD_EAX]),
"=b" (words[PAL_CPUID_WORD_EBX]),
"=c" (words[PAL_CPUID_WORD_ECX]),
"=d" (words[PAL_CPUID_WORD_EDX])
: "a" (leaf),
"c" (subleaf));
}


#define CPU_RELAX() __asm__ __volatile__("rep; nop" ::: "memory")

/*
* Some non-Intel clones support out of order store. WMB() ceases to be a
* nop for these.
*/
/* some non-Intel clones support out of order store; WMB() ceases to be a nop for these */
# define MB() __asm__ __volatile__ ("mfence" ::: "memory")
# define RMB() __asm__ __volatile__ ("lfence" ::: "memory")
# define WMB() __asm__ __volatile__ ("sfence" ::: "memory")
Expand Down
14 changes: 14 additions & 0 deletions Pal/include/arch/x86_64/pal-arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

#include <stdint.h>

#include "cpu.h"

#define PAGE_SIZE (1 << 12)
#define PRESET_PAGESIZE PAGE_SIZE

Expand Down Expand Up @@ -182,4 +184,16 @@ static inline bool pal_context_has_user_pagefault(PAL_CONTEXT* context) {
return !!(context->err & 4);
}

/* PAL_CPU_INFO holds /proc/cpuinfo data */
typedef struct PAL_CPU_INFO_ {
PAL_NUM cpu_num;
PAL_STR cpu_vendor;
PAL_STR cpu_brand;
PAL_NUM cpu_family;
PAL_NUM cpu_model;
PAL_NUM cpu_stepping;
double cpu_bogomips;
PAL_STR cpu_flags;
} PAL_CPU_INFO;

#endif /* PAL_ARCH_H */
40 changes: 13 additions & 27 deletions Pal/include/pal/pal.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
#include <stdint.h>
#include <stdnoreturn.h>

#if defined(__i386__) || defined(__x86_64__)
#include "cpu.h"
#endif

typedef uint64_t PAL_NUM; /*!< a number */
typedef const char * PAL_STR; /*!< a pointer to a C-string */
typedef void * PAL_PTR; /*!< a pointer to memory or buffer (something other than string) */
Expand Down Expand Up @@ -114,17 +118,6 @@ enum {

typedef struct PAL_PTR_RANGE_ { PAL_PTR start, end; } PAL_PTR_RANGE;

typedef struct PAL_CPU_INFO_ {
PAL_NUM cpu_num;
PAL_STR cpu_vendor;
PAL_STR cpu_brand;
PAL_NUM cpu_family;
PAL_NUM cpu_model;
PAL_NUM cpu_stepping;
double cpu_bogomips;
PAL_STR cpu_flags;
} PAL_CPU_INFO;

typedef struct PAL_MEM_INFO_ {
PAL_NUM mem_total;
} PAL_MEM_INFO;
Expand Down Expand Up @@ -741,22 +734,6 @@ PAL_PTR DkSegmentRegister(PAL_FLG reg, PAL_PTR addr);
*/
PAL_NUM DkMemoryAvailableQuota(void);

enum PAL_CPUID_WORD {
PAL_CPUID_WORD_EAX = 0,
PAL_CPUID_WORD_EBX = 1,
PAL_CPUID_WORD_ECX = 2,
PAL_CPUID_WORD_EDX = 3,
PAL_CPUID_WORD_NUM = 4,
};

/*!
* \brief Return CPUID information, based on the leaf/subleaf.
*
* \param[out] values the array of the results
*/
PAL_BOL
DkCpuIdRetrieve(PAL_IDX leaf, PAL_IDX subleaf, PAL_IDX values[PAL_CPUID_WORD_NUM]);

/*!
* \brief Obtain the attestation report (local) with `user_report_data` embedded into it.
*
Expand Down Expand Up @@ -816,4 +793,13 @@ PAL_BOL DkAttestationQuote(PAL_PTR user_report_data, PAL_NUM user_report_data_si
# define symbol_version_default(real, name, version)
#endif

#if defined(__i386__) || defined(__x86_64__)
/*!
* \brief Return CPUID information, based on the leaf/subleaf.
*
* \param[out] values the array of the results
*/
PAL_BOL DkCpuIdRetrieve(PAL_IDX leaf, PAL_IDX subleaf, PAL_IDX values[PAL_CPUID_WORD_NUM]);
#endif

#endif /* PAL_H */
1 change: 1 addition & 0 deletions Pal/src/host/Linux-SGX/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ enclave-objs = \
db_exception.o \
db_files.o \
db_main.o \
db_main-$(ARCH).o \
db_memory.o \
db_misc.o \
db_mutex.o \
Expand Down
166 changes: 166 additions & 0 deletions Pal/src/host/Linux-SGX/db_main-x86_64.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
/* SPDX-License-Identifier: LGPL-3.0-or-later */
/* Copyright (C) 2014 Stony Brook University */

/*
* db_main-x86_64.c
*
* This file contains x86_64-specific functions of the PAL loader.
*/

#include "api.h"
#include "bogomips.h"
#include "pal.h"
#include "pal_debug.h"
#include "pal_internal.h"
#include "pal_linux.h"
#include "pal_security.h"

#define FOUR_CHARS_VALUE(s, w) \
(s)[0] = (w) & 0xff; \
(s)[1] = ((w) >> 8) & 0xff; \
(s)[2] = ((w) >> 16) & 0xff; \
(s)[3] = ((w) >> 24) & 0xff;

#define BPI 32
#define POWER2(power) \
(1ULL << (power))
#define RIGHTMASK(width) \
(((unsigned long)(width) >= BPI) ? ~0ULL : POWER2(width) - 1ULL)

#define BIT_EXTRACT_LE(value, start, after) \
(((unsigned long)(value) & RIGHTMASK(after)) >> start)

static char* cpu_flags[] = {
"fpu", // "x87 FPU on chip"
"vme", // "virtual-8086 mode enhancement"
"de", // "debugging extensions"
"pse", // "page size extensions"
"tsc", // "time stamp counter"
"msr", // "RDMSR and WRMSR support"
"pae", // "physical address extensions"
"mce", // "machine check exception"
"cx8", // "CMPXCHG8B inst."
"apic", // "APIC on chip"
NULL,
"sep", // "SYSENTER and SYSEXIT"
"mtrr", // "memory type range registers"
"pge", // "PTE global bit"
"mca", // "machine check architecture"
"cmov", // "conditional move/compare instruction"
"pat", // "page attribute table"
"pse36", // "page size extension"
"pn", // "processor serial number"
"clflush", // "CLFLUSH instruction"
NULL,
"dts", // "debug store"
"acpi", // "Onboard thermal control"
"mmx", // "MMX Technology"
"fxsr", // "FXSAVE/FXRSTOR"
"sse", // "SSE extensions"
"sse2", // "SSE2 extensions"
"ss", // "self snoop"
"ht", // "hyper-threading / multi-core supported"
"tm", // "therm. monitor"
"ia64", // "IA64"
"pbe", // "pending break event"
};

static ssize_t read_file_buffer(const char* filename, char* buf, size_t buf_size) {
int fd;

fd = ocall_open(filename, O_RDONLY, 0);
if (fd < 0)
return fd;

/* Although the whole file might not fit in this size, the first cpu description should. */
ssize_t n = ocall_read(fd, buf, buf_size);
ocall_close(fd);

return n;
}

static double get_bogomips(void) {
char buf[2048];
ssize_t len;

len = read_file_buffer("/proc/cpuinfo", buf, sizeof(buf) - 1);
if (len < 0)
return 0.0;
buf[len] = 0;

return sanitize_bogomips_value(get_bogomips_from_cpuinfo_buf(buf));
}

int _DkGetCPUInfo (PAL_CPU_INFO* ci) {
unsigned int words[PAL_CPUID_WORD_NUM];
int rv = 0;

const size_t VENDOR_ID_SIZE = 13;
char* vendor_id = malloc(VENDOR_ID_SIZE);
_DkCpuIdRetrieve(0, 0, words);

FOUR_CHARS_VALUE(&vendor_id[0], words[PAL_CPUID_WORD_EBX]);
FOUR_CHARS_VALUE(&vendor_id[4], words[PAL_CPUID_WORD_EDX]);
FOUR_CHARS_VALUE(&vendor_id[8], words[PAL_CPUID_WORD_ECX]);
vendor_id[VENDOR_ID_SIZE - 1] = '\0';
ci->cpu_vendor = vendor_id;
// Must be an Intel CPU
if (memcmp(vendor_id, "GenuineIntel", 12)) {
free(vendor_id);
return -PAL_ERROR_INVAL;
}

const size_t BRAND_SIZE = 49;
char* brand = malloc(BRAND_SIZE);
_DkCpuIdRetrieve(0x80000002, 0, words);
memcpy(&brand[ 0], words, sizeof(unsigned int) * PAL_CPUID_WORD_NUM);
_DkCpuIdRetrieve(0x80000003, 0, words);
memcpy(&brand[16], words, sizeof(unsigned int) * PAL_CPUID_WORD_NUM);
_DkCpuIdRetrieve(0x80000004, 0, words);
memcpy(&brand[32], words, sizeof(unsigned int) * PAL_CPUID_WORD_NUM);
brand[BRAND_SIZE - 1] = '\0';
ci->cpu_brand = brand;

/* we cannot use CPUID(0xb) because it counts even disabled-by-BIOS cores (e.g. HT cores);
* instead, this is passed in via pal_sec at start-up time. */
ci->cpu_num = pal_sec.num_cpus;

_DkCpuIdRetrieve(1, 0, words);
ci->cpu_family = BIT_EXTRACT_LE(words[PAL_CPUID_WORD_EAX], 8, 12) +
BIT_EXTRACT_LE(words[PAL_CPUID_WORD_EAX], 20, 28);
ci->cpu_model = BIT_EXTRACT_LE(words[PAL_CPUID_WORD_EAX], 4, 8) +
(BIT_EXTRACT_LE(words[PAL_CPUID_WORD_EAX], 16, 20) << 4);
ci->cpu_stepping = BIT_EXTRACT_LE(words[PAL_CPUID_WORD_EAX], 0, 4);

int flen = 0, fmax = 80;
char* flags = malloc(fmax);

for (int i = 0 ; i < 32 ; i++) {
if (!cpu_flags[i])
continue;

if (BIT_EXTRACT_LE(words[PAL_CPUID_WORD_EDX], i, i + 1)) {
int len = strlen(cpu_flags[i]);
if (flen + len + 1 > fmax) {
char* new_flags = malloc(fmax * 2);
memcpy(new_flags, flags, flen);
free(flags);
fmax *= 2;
flags = new_flags;
}
memcpy(flags + flen, cpu_flags[i], len);
flen += len;
flags[flen++] = ' ';
}
}

flags[flen ? flen - 1 : 0] = 0;
ci->cpu_flags = flags;

ci->cpu_bogomips = get_bogomips();
if (ci->cpu_bogomips == 0.0) {
SGX_DBG(DBG_E, "Warning: bogomips could not be retrieved, passing 0.0 to the application\n");
}

return rv;
}
Loading

0 comments on commit 0831193

Please sign in to comment.