mirror of
https://github.com/clearlinux/graphene.git
synced 2026-09-05 13:21:37 +00:00
[PAL] Fix cpuid parsing on a system with hyperthreads
This commit is contained in:
+4
-1
@@ -452,7 +452,9 @@ noreturn void pal_main (
|
||||
__pal_control.alloc_align = pal_state.alloc_align;
|
||||
__pal_control.broadcast_stream = _DkBroadcastStreamOpen();
|
||||
|
||||
_DkGetCPUInfo(&__pal_control.cpu_info);
|
||||
if (_DkGetCPUInfo(&__pal_control.cpu_info) < 0) {
|
||||
goto out_fail;
|
||||
}
|
||||
__pal_control.mem_info.mem_total = _DkMemoryQuota();
|
||||
|
||||
#if PROFILING == 1
|
||||
@@ -470,6 +472,7 @@ noreturn void pal_main (
|
||||
/* Now we will start the execution */
|
||||
start_execution(first_argument, arguments, environments);
|
||||
|
||||
out_fail:
|
||||
/* We wish we will never reached here */
|
||||
INIT_FAIL(PAL_ERROR_DENIED, "unexpected termination");
|
||||
}
|
||||
|
||||
@@ -331,7 +331,23 @@ static char * cpu_flags[]
|
||||
"pbe", // "pending break event"
|
||||
};
|
||||
|
||||
void _DkGetCPUInfo (PAL_CPU_INFO * ci)
|
||||
/*
|
||||
* Returns the number of online CPUs read from sysctl hw.ncpus, -errno on failure.
|
||||
*/
|
||||
int get_cpu_count(void) {
|
||||
int mib[2], cores;
|
||||
size_t len = sizeof(cores);
|
||||
mib[0] = CTL_HW;
|
||||
mib[1] = HW_NCPU;
|
||||
|
||||
int rv = sysctl(mib, 2, &cores, &len, NULL, 0);
|
||||
if (rv < 0)
|
||||
return unix_to_pal_error(ERRNO(rv));
|
||||
|
||||
return cores;
|
||||
}
|
||||
|
||||
int _DkGetCPUInfo (PAL_CPU_INFO * ci)
|
||||
{
|
||||
unsigned int words[PAL_CPUID_WORD_NUM];
|
||||
|
||||
@@ -361,14 +377,15 @@ void _DkGetCPUInfo (PAL_CPU_INFO * ci)
|
||||
ci->cpu_model = BIT_EXTRACT_LE(words[PAL_CPUID_WORD_EAX], 4, 8);
|
||||
ci->cpu_stepping = BIT_EXTRACT_LE(words[PAL_CPUID_WORD_EAX], 0, 4);
|
||||
|
||||
/* According to SDM: EBX[15:0] is to enumerate processor topology
|
||||
* of the system. However this value is intended for display/diagnostic
|
||||
* purposes. The actual number of logical processors available to
|
||||
* BIOS/OS/App may be different. We use this leaf for now as it's the
|
||||
* best option we have so far to get the cpu number */
|
||||
|
||||
cpuid(0xb, 1, words, 0);
|
||||
ci->cpu_num = BIT_EXTRACT_LE(words[WORD_EBX], 0, 16);
|
||||
/* we cannot use CPUID(0xb) because it counts even disabled-by-BIOS cores (e.g. HT cores);
|
||||
* instead we extract info on number of online CPUs by parsing sysfs pseudo-files */
|
||||
int cores = get_cpu_count();
|
||||
if (cores < 0) {
|
||||
free(brand);
|
||||
free(vendor_id);
|
||||
return cores;
|
||||
}
|
||||
ci->cpu_num = cores;
|
||||
|
||||
int flen = 0, fmax = 80;
|
||||
char * flags = malloc(fmax);
|
||||
|
||||
@@ -75,6 +75,7 @@ PAL_NUM _DkGetHostId (void)
|
||||
|
||||
#include "elf-x86_64.h"
|
||||
#include "dynamic_link.h"
|
||||
#include <asm/errno.h>
|
||||
|
||||
void setup_pal_map (struct link_map * map);
|
||||
static struct link_map pal_map;
|
||||
@@ -293,6 +294,12 @@ void pal_linux_main(char * uptr_args, uint64_t args_size,
|
||||
pal_sec.uid = sec_info.uid;
|
||||
pal_sec.gid = sec_info.gid;
|
||||
|
||||
int num_cpus = sec_info.num_cpus;
|
||||
if (num_cpus >= 1 && num_cpus <= (1 << 16)) {
|
||||
pal_sec.num_cpus = num_cpus;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
/* set up page allocator and slab manager */
|
||||
init_slab_mgr(pagesz);
|
||||
@@ -459,9 +466,11 @@ static char * cpu_flags[]
|
||||
"pbe", // "pending break event"
|
||||
};
|
||||
|
||||
void _DkGetCPUInfo (PAL_CPU_INFO * ci)
|
||||
|
||||
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);
|
||||
@@ -486,14 +495,9 @@ void _DkGetCPUInfo (PAL_CPU_INFO * ci)
|
||||
brand[BRAND_SIZE - 1] = '\0';
|
||||
ci->cpu_brand = brand;
|
||||
|
||||
/* According to SDM: EBX[15:0] is to enumerate processor topology
|
||||
* of the system. However this value is intended for display/diagnostic
|
||||
* purposes. The actual number of logical processors available to
|
||||
* BIOS/OS/App may be different. We use this leaf for now as it's the
|
||||
* best option we have so far to get the cpu number */
|
||||
|
||||
cpuid(0xb, 1, words);
|
||||
ci->cpu_num = BIT_EXTRACT_LE(words[PAL_CPUID_WORD_EBX], 0, 16);
|
||||
/* 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;
|
||||
|
||||
cpuid(1, 0, words);
|
||||
ci->cpu_family = BIT_EXTRACT_LE(words[PAL_CPUID_WORD_EAX], 8, 12) +
|
||||
@@ -526,4 +530,5 @@ void _DkGetCPUInfo (PAL_CPU_INFO * ci)
|
||||
|
||||
flags[flen ? flen - 1 : 0] = 0;
|
||||
ci->cpu_flags = flags;
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -49,6 +49,9 @@ struct pal_sec {
|
||||
PAL_SEC_STR pipe_prefix;
|
||||
PAL_IDX mcast_port, mcast_srv, mcast_cli;
|
||||
|
||||
/* Need to pass in the number of cores */
|
||||
PAL_NUM num_cpus;
|
||||
|
||||
#ifdef DEBUG
|
||||
PAL_BOL in_gdb;
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <pal_linux.h>
|
||||
#include <pal_linux_error.h>
|
||||
#include <pal_rtld.h>
|
||||
#include "sgx_internal.h"
|
||||
#include "sgx_tls.h"
|
||||
@@ -707,6 +708,54 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the number of online CPUs read from /sys/devices/system/cpu/online, -errno on failure.
|
||||
* Understands complex formats like "1,3-5,6".
|
||||
*/
|
||||
int get_cpu_count(void) {
|
||||
int fd = INLINE_SYSCALL(open, 3, "/sys/devices/system/cpu/online", O_RDONLY|O_CLOEXEC, 0);
|
||||
if (fd < 0)
|
||||
return unix_to_pal_error(ERRNO(fd));
|
||||
|
||||
char buf[64];
|
||||
int ret = INLINE_SYSCALL(read, 3, fd, buf, sizeof(buf) - 1);
|
||||
if (ret < 0) {
|
||||
INLINE_SYSCALL(close, 1, fd);
|
||||
return unix_to_pal_error(ERRNO(ret));
|
||||
}
|
||||
|
||||
buf[ret] = '\0'; /* ensure null-terminated buf even in partial read */
|
||||
|
||||
char* end;
|
||||
char* ptr = buf;
|
||||
int cpu_count = 0;
|
||||
while (*ptr) {
|
||||
while (*ptr == ' ' || *ptr == '\t' || *ptr == ',')
|
||||
ptr++;
|
||||
|
||||
int firstint = (int)strtol(ptr, &end, 10);
|
||||
if (ptr == end)
|
||||
break;
|
||||
|
||||
if (*end == '\0' || *end == ',') {
|
||||
/* single CPU index, count as one more CPU */
|
||||
cpu_count++;
|
||||
} else if (*end == '-') {
|
||||
/* CPU range, count how many CPUs in range */
|
||||
ptr = end + 1;
|
||||
int secondint = (int)strtol(ptr, &end, 10);
|
||||
if (secondint > firstint)
|
||||
cpu_count += secondint - firstint + 1; // inclusive (e.g., 0-7, or 8-16)
|
||||
}
|
||||
ptr = end;
|
||||
}
|
||||
|
||||
INLINE_SYSCALL(close, 1, fd);
|
||||
if (cpu_count == 0)
|
||||
return -PAL_ERROR_STREAMNOTEXIST;
|
||||
return cpu_count;
|
||||
}
|
||||
|
||||
static int load_enclave (struct pal_enclave * enclave,
|
||||
char * manifest_uri,
|
||||
char * exec_uri,
|
||||
@@ -737,6 +786,11 @@ static int load_enclave (struct pal_enclave * enclave,
|
||||
pal_sec->pid = INLINE_SYSCALL(getpid, 0);
|
||||
pal_sec->uid = INLINE_SYSCALL(getuid, 0);
|
||||
pal_sec->gid = INLINE_SYSCALL(getgid, 0);
|
||||
int num_cpus = get_cpu_count();
|
||||
if (num_cpus < 0) {
|
||||
return num_cpus;
|
||||
}
|
||||
pal_sec->num_cpus = num_cpus;
|
||||
|
||||
#ifdef DEBUG
|
||||
size_t env_i = 0;
|
||||
|
||||
@@ -35,8 +35,6 @@
|
||||
typedef __kernel_pid_t pid_t;
|
||||
#include <asm/errno.h>
|
||||
#include <asm/fcntl.h>
|
||||
#include <asm/stat.h>
|
||||
#include <linux/stat.h>
|
||||
|
||||
#define DEVICE_OPS(handle) \
|
||||
({ \
|
||||
|
||||
@@ -35,8 +35,6 @@
|
||||
typedef __kernel_pid_t pid_t;
|
||||
#undef __GLIBC__
|
||||
#include <linux/stat.h>
|
||||
#include <asm/stat.h>
|
||||
#include <asm/fcntl.h>
|
||||
#include <asm/errno.h>
|
||||
|
||||
/* 'open' operation for file streams */
|
||||
|
||||
@@ -383,9 +383,57 @@ static char * cpu_flags[]
|
||||
"pbe", // "pending break event"
|
||||
};
|
||||
|
||||
void _DkGetCPUInfo (PAL_CPU_INFO * ci)
|
||||
/*
|
||||
* Returns the number of online CPUs read from /sys/devices/system/cpu/online, -errno on failure.
|
||||
* Understands complex formats like "1,3-5,6".
|
||||
*/
|
||||
int get_cpu_count(void) {
|
||||
int fd = INLINE_SYSCALL(open, 3, "/sys/devices/system/cpu/online", O_RDONLY|O_CLOEXEC, 0);
|
||||
if (fd < 0)
|
||||
return unix_to_pal_error(ERRNO(fd));
|
||||
|
||||
char buf[64];
|
||||
int ret = INLINE_SYSCALL(read, 3, fd, buf, sizeof(buf) - 1);
|
||||
INLINE_SYSCALL(close, 1, fd);
|
||||
if (ret < 0) {
|
||||
return unix_to_pal_error(ERRNO(ret));
|
||||
}
|
||||
|
||||
buf[ret] = '\0'; /* ensure null-terminated buf even in partial read */
|
||||
|
||||
char* end;
|
||||
char* ptr = buf;
|
||||
int cpu_count = 0;
|
||||
while (*ptr) {
|
||||
while (*ptr == ' ' || *ptr == '\t' || *ptr == ',')
|
||||
ptr++;
|
||||
|
||||
int firstint = (int)strtol(ptr, &end, 10);
|
||||
if (ptr == end)
|
||||
break;
|
||||
|
||||
if (*end == '\0' || *end == ',') {
|
||||
/* single CPU index, count as one more CPU */
|
||||
cpu_count++;
|
||||
} else if (*end == '-') {
|
||||
/* CPU range, count how many CPUs in range */
|
||||
ptr = end + 1;
|
||||
int secondint = (int)strtol(ptr, &end, 10);
|
||||
if (secondint > firstint)
|
||||
cpu_count += secondint - firstint + 1; // inclusive (e.g., 0-7, or 8-16)
|
||||
}
|
||||
ptr = end;
|
||||
}
|
||||
|
||||
if (cpu_count == 0)
|
||||
return -PAL_ERROR_STREAMNOTEXIST;
|
||||
return cpu_count;
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -408,22 +456,15 @@ void _DkGetCPUInfo (PAL_CPU_INFO * ci)
|
||||
brand[BRAND_SIZE - 1] = '\0';
|
||||
ci->cpu_brand = brand;
|
||||
|
||||
if (!memcmp(vendor_id, "GenuineIntel", 12)) {
|
||||
|
||||
/* According to SDM: EBX[15:0] is to enumerate processor topology
|
||||
* of the system. However this value is intended for display/diagnostic
|
||||
* purposes. The actual number of logical processors available to
|
||||
* BIOS/OS/App may be different. We use this leaf for now as it's the
|
||||
* best option we have so far to get the cpu number */
|
||||
|
||||
cpuid(0xb, 1, words);
|
||||
ci->cpu_num = BIT_EXTRACT_LE(words[PAL_CPUID_WORD_EBX], 0, 16);
|
||||
} else if (!memcmp(vendor_id, "AuthenticAMD", 12)) {
|
||||
cpuid(0x8000008, 0, words);
|
||||
ci->cpu_num = BIT_EXTRACT_LE(words[PAL_CPUID_WORD_EAX], 0, 8) + 1;
|
||||
} else {
|
||||
ci->cpu_num = 1;
|
||||
/* we cannot use CPUID(0xb) because it counts even disabled-by-BIOS cores (e.g. HT cores);
|
||||
* instead we extract info on number of online CPUs by parsing sysfs pseudo-files */
|
||||
int cores = get_cpu_count();
|
||||
if (cores < 0) {
|
||||
free(vendor_id);
|
||||
free(brand);
|
||||
return cores;
|
||||
}
|
||||
ci->cpu_num = cores;
|
||||
|
||||
cpuid(1, 0, words);
|
||||
ci->cpu_family = BIT_EXTRACT_LE(words[PAL_CPUID_WORD_EAX], 8, 12);
|
||||
@@ -460,4 +501,5 @@ void _DkGetCPUInfo (PAL_CPU_INFO * ci)
|
||||
|
||||
flags[flen ? flen - 1 : 0] = 0;
|
||||
ci->cpu_flags = flags;
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -32,12 +32,10 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
typedef __kernel_pid_t pid_t;
|
||||
#include <linux/stat.h>
|
||||
#include <linux/msg.h>
|
||||
#include <linux/socket.h>
|
||||
#include <linux/wait.h>
|
||||
#include <asm/fcntl.h>
|
||||
#include <asm/stat.h>
|
||||
#include <asm/socket.h>
|
||||
#include <asm/poll.h>
|
||||
#include <sys/signal.h>
|
||||
|
||||
@@ -30,6 +30,11 @@
|
||||
#include <sys/syscall.h>
|
||||
#include <sigset.h>
|
||||
|
||||
#include <asm/fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef __x86_64__
|
||||
# include "sysdep-x86_64.h"
|
||||
#endif
|
||||
@@ -74,7 +79,7 @@ extern struct pal_linux_state {
|
||||
#endif
|
||||
} linux_state;
|
||||
|
||||
#include <asm/fcntl.h>
|
||||
|
||||
#include <asm/mman.h>
|
||||
|
||||
#ifdef INLINE_SYSCALL
|
||||
@@ -153,7 +158,6 @@ int handle_deserialize (PAL_HANDLE * handle, const void * data, int size);
|
||||
#define ACCESS_W 2
|
||||
#define ACCESS_X 1
|
||||
|
||||
struct stat;
|
||||
bool stataccess (struct stat * stats, int acc);
|
||||
|
||||
void init_child_process (PAL_HANDLE * parent, PAL_HANDLE * exec,
|
||||
|
||||
@@ -269,7 +269,8 @@ PAL_NUM _DkGetProcessId (void);
|
||||
PAL_NUM _DkGetHostId (void);
|
||||
unsigned long _DkMemoryQuota (void);
|
||||
unsigned long _DkMemoryAvailableQuota (void);
|
||||
void _DkGetCPUInfo (PAL_CPU_INFO * info);
|
||||
// Returns 0 on success, negative PAL code on failure
|
||||
int _DkGetCPUInfo (PAL_CPU_INFO * info);
|
||||
|
||||
/* Internal DK calls, in case any of the internal routines needs to use them */
|
||||
/* DkStream calls */
|
||||
|
||||
Reference in New Issue
Block a user