Browse Source

Implement sched_getaffinity system call (#209)

* implement sched_getaffinity system call

* add sched_getaffinity1~8 to the passed list

* adding PAL regression test for CPU info
Chia-Che Tsai 5 years ago
parent
commit
00c4ed0253

+ 2 - 0
LibOS/shim/include/shim_table.h

@@ -453,6 +453,8 @@ int shim_do_tkill (int pid, int sig);
 time_t shim_do_time (time_t * tloc);
 int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime,
                    unsigned int * uaddr2, int val3);
+int shim_do_sched_getaffinity (pid_t pid, size_t len,
+                               __kernel_cpu_set_t * user_mask_ptr);
 int shim_do_set_tid_address (int * tidptr);
 int shim_do_semtimedop (int semid, struct sembuf * sops, unsigned int nsops,
                         const struct timespec * timeout);

+ 3 - 2
LibOS/shim/src/shim_syscalls.c

@@ -804,8 +804,9 @@ DEFINE_SHIM_SYSCALL (futex, 6, shim_do_futex, int, unsigned int *, uaddr,
 SHIM_SYSCALL_PASSTHROUGH (sched_setaffinity, 3, int, pid_t, pid, size_t, len,
                           __kernel_cpu_set_t *, user_mask_ptr)
 
-SHIM_SYSCALL_PASSTHROUGH (sched_getaffinity, 3, int, pid_t, pid, size_t, len,
-                          __kernel_cpu_set_t *, user_mask_ptr)
+DEFINE_SHIM_SYSCALL (sched_getaffinity, 3, shim_do_sched_getaffinity, int,
+                     pid_t, pid, size_t, len,
+                     __kernel_cpu_set_t *, user_mask_ptr)
 
 SHIM_SYSCALL_PASSTHROUGH (set_thread_area, 1, int, struct user_desc *, u_info)
 

+ 11 - 1
LibOS/shim/src/sys/shim_sched.c

@@ -25,7 +25,7 @@
 
 #include <shim_internal.h>
 #include <shim_table.h>
-
+#include <api.h>
 #include <pal.h>
 
 #include <errno.h>
@@ -35,3 +35,13 @@ int shim_do_sched_yield (void)
     DkThreadYieldExecution();
     return 0;
 }
+
+int shim_do_sched_getaffinity (pid_t pid, size_t len,
+                               __kernel_cpu_set_t * user_mask_ptr)
+{
+    int ncpus = PAL_CB(cpu_info.cpu_num);
+    memset(user_mask_ptr, 0, len);
+    for (int i = 0 ; i < ncpus ; i++)
+        ((uint8_t *) user_mask_ptr)[i / 8] |= 1 << (i % 8);
+    return ncpus;
+}

+ 6 - 0
LibOS/shim/test/apps/ltp/PASSED

@@ -728,8 +728,14 @@ rt_sigsuspend01,1
 sbrk01,1
 sbrk01,2
 sbrk02,1
+sched_getaffinity01,1
 sched_getaffinity01,2
 sched_getaffinity01,3
+sched_getaffinity01,4
+sched_getaffinity01,5
+sched_getaffinity01,6
+sched_getaffinity01,7
+sched_getaffinity01,8
 sched_yield01,1
 select01,1
 select02,1

+ 41 - 0
Pal/regression/00_Bootstrap.py

@@ -46,6 +46,47 @@ regression.add_check(name="Control Block: Allocation Alignment",
 regression.add_check(name="Control Block: Executable Range",
     check=lambda res: "Executable Range OK" in res[0].log)
 
+def check_cpu_info(res):
+    cpu_num = cpu_model = cpu_family = cpu_stepping = 0
+    cpu_vendor = cpu_brand = cpu_flags = None
+
+    f = open("/proc/cpuinfo", "r")
+    for line in f:
+        line = line.strip()
+        pos = line.find(":")
+        if pos == -1:
+            continue
+
+        key = line[:pos].strip()
+        val = line[pos+1:].strip()
+        if key == "processor":  cpu_num += 1
+        if key == "vendor_id":  cpu_vendor = val
+        if key == "cpu family": cpu_family = int(val)
+        if key == "model":      cpu_model = int(val)
+        if key == "model name": cpu_brand = val
+        if key == "stepping":   cpu_stepping = int(val)
+        if key == "flags":
+            cpu_flags = []
+            for flag in val.split(" "):
+                if flag in ["fpu", "vme", "de", "pse", "tsc", "msr", "pae",
+                        "mce", "cx8", "apic", "sep", "mtrr", "pge", "mca",
+                        "cmov", "pat", "pse36", "pn", "clflush", "dts", "acpi",
+                        "mmx", "fxsr", "sse", "sse2", "ss", "ht", "tm",
+                        "ia64", "pbe"]:
+                    cpu_flags.append(flag)
+            cpu_flags = " ".join(cpu_flags)
+
+    return ("CPU num: %d"      % cpu_num)      in res[0].log and \
+           ("CPU vendor: %s"   % cpu_vendor)   in res[0].log and \
+           ("CPU brand: %s"    % cpu_brand)    in res[0].log and \
+           ("CPU family: %d"   % cpu_family)   in res[0].log and \
+           ("CPU model: %d"    % cpu_model)    in res[0].log and \
+           ("CPU stepping: %d" % cpu_stepping) in res[0].log and \
+           ("CPU flags: %s"    % cpu_flags)    in res[0].log
+
+regression.add_check(name="Control Block: CPU Info",
+    check=check_cpu_info)
+
 rv = regression.run_checks()
 if rv: sys.exit(rv)
 

+ 8 - 0
Pal/regression/Bootstrap.c

@@ -67,5 +67,13 @@ int main (int argc, char ** argv, char ** envp)
         (void *) &test_func < pal_control.executable_range.end)
         pal_printf("Executable Range OK\n");
 
+    pal_printf("CPU num: %d\n",      pal_control.cpu_info.cpu_num);
+    pal_printf("CPU vendor: %s\n",   pal_control.cpu_info.cpu_vendor);
+    pal_printf("CPU brand: %s\n",    pal_control.cpu_info.cpu_brand);
+    pal_printf("CPU family: %d\n",   pal_control.cpu_info.cpu_family);
+    pal_printf("CPU model: %d\n",    pal_control.cpu_info.cpu_model);
+    pal_printf("CPU stepping: %d\n", pal_control.cpu_info.cpu_stepping);
+    pal_printf("CPU flags: %s\n",    pal_control.cpu_info.cpu_flags);
+
     return 0;
 }

+ 12 - 6
Pal/src/host/Linux-SGX/db_main.c

@@ -272,8 +272,8 @@ static char * cpu_flags[]
           "pn",     // "processor serial number"
           "clflush",    // "CLFLUSH instruction"
           NULL,
-          "dts"     // "debug store"
-          "tm",     // "thermal monitor and clock ctrl"
+          "dts",    // "debug store"
+          "acpi",   // "Onboard thermal control"
           "mmx",    // "MMX Technology"
           "fxsr",   // "FXSAVE/FXRSTOR"
           "sse",    // "SSE extensions"
@@ -296,6 +296,8 @@ void _DkGetCPUInfo (PAL_CPU_INFO * ci)
     FOUR_CHARS_VALUE(&vendor_id[4], words[WORD_EDX]);
     FOUR_CHARS_VALUE(&vendor_id[8], words[WORD_ECX]);
     ci->cpu_vendor = vendor_id;
+    // Must be an Intel CPU
+    assert(!memcmp(vendor_id, "GenuineIntel", 12));
 
     char * brand = malloc(48);
     cpuid(0x80000002, 0, words);
@@ -306,10 +308,14 @@ void _DkGetCPUInfo (PAL_CPU_INFO * ci)
     memcpy(&brand[32], words, sizeof(unsigned int) * WORD_NUM);
     ci->cpu_brand = brand;
 
+    cpuid(4, 0, words);
+    ci->cpu_num      = BIT_EXTRACT_LE(words[WORD_EAX], 26, 32) + 1;
+
     cpuid(1, 0, words);
-    ci->cpu_num      = BIT_EXTRACT_LE(words[WORD_EBX], 16, 24);
-    ci->cpu_family   = BIT_EXTRACT_LE(words[WORD_EAX],  8, 12);
-    ci->cpu_model    = BIT_EXTRACT_LE(words[WORD_EAX],  4,  8);
+    ci->cpu_family   = BIT_EXTRACT_LE(words[WORD_EAX],  8, 12) +
+                       BIT_EXTRACT_LE(words[WORD_EAX], 20, 28);
+    ci->cpu_model    = BIT_EXTRACT_LE(words[WORD_EAX],  4,  8) +
+                      (BIT_EXTRACT_LE(words[WORD_EAX], 16, 20) << 4);
     ci->cpu_stepping = BIT_EXTRACT_LE(words[WORD_EAX],  0,  4);
 
     int flen = 0, fmax = 80;
@@ -317,7 +323,7 @@ void _DkGetCPUInfo (PAL_CPU_INFO * ci)
 
     for (int i = 0 ; i < 32 ; i++) {
         if (!cpu_flags[i])
-            break;
+            continue;
 
         if (BIT_EXTRACT_LE(words[WORD_EDX], i, i + 1)) {
             int len = strlen(cpu_flags[i]);

+ 28 - 13
Pal/src/host/Linux/db_main.c

@@ -305,16 +305,16 @@ done_init:
 #define WORD_EDX  3
 #define WORD_NUM  4
 
-static void cpuid (int cpuid_fd, unsigned int reg,
-                   unsigned int words[], unsigned int ecx)
+static void cpuid (unsigned int leaf, unsigned int subleaf,
+                   unsigned int words[])
 {
   asm("cpuid"
       : "=a" (words[WORD_EAX]),
         "=b" (words[WORD_EBX]),
         "=c" (words[WORD_ECX]),
         "=d" (words[WORD_EDX])
-      : "a" (reg),
-        "c" (ecx));
+      : "a" (leaf),
+        "c" (subleaf));
 }
 
 #define FOUR_CHARS_VALUE(s, w)      \
@@ -354,8 +354,8 @@ static char * cpu_flags[]
           "pn",     // "processor serial number"
           "clflush",    // "CLFLUSH instruction"
           NULL,
-          "dts"     // "debug store"
-          "tm",     // "thermal monitor and clock ctrl"
+          "dts",    // "debug store"
+          "acpi",   // "Onboard thermal control"
           "mmx",    // "MMX Technology"
           "fxsr",   // "FXSAVE/FXRSTOR"
           "sse",    // "SSE extensions"
@@ -372,7 +372,7 @@ void _DkGetCPUInfo (PAL_CPU_INFO * ci)
     unsigned int words[WORD_NUM];
 
     char * vendor_id = malloc(12);
-    cpuid(2, 0, words, 0);
+    cpuid(0, 0, words);
 
     FOUR_CHARS_VALUE(&vendor_id[0], words[WORD_EBX]);
     FOUR_CHARS_VALUE(&vendor_id[4], words[WORD_EDX]);
@@ -380,26 +380,41 @@ void _DkGetCPUInfo (PAL_CPU_INFO * ci)
     ci->cpu_vendor = vendor_id;
 
     char * brand = malloc(48);
-    cpuid(-2, 0x80000002, words, 0);
+    cpuid(0x80000002, 0, words);
     memcpy(&brand[ 0], words, sizeof(unsigned int) * WORD_NUM);
-    cpuid(-2, 0x80000003, words, 0);
+    cpuid(0x80000003, 0, words);
     memcpy(&brand[16], words, sizeof(unsigned int) * WORD_NUM);
-    cpuid(-2, 0x80000004, words, 0);
+    cpuid(0x80000004, 0, words);
     memcpy(&brand[32], words, sizeof(unsigned int) * WORD_NUM);
     ci->cpu_brand = brand;
 
-    cpuid(2, 1, words, 0);
-    ci->cpu_num      = BIT_EXTRACT_LE(words[WORD_EBX], 16, 24);
+    if (!memcmp(vendor_id, "GenuineIntel", 12)) {
+        cpuid(4, 0, words);
+        ci->cpu_num  = BIT_EXTRACT_LE(words[WORD_EAX], 26, 32) + 1;
+    } else if (!memcmp(vendor_id, "AuthenticAMD", 12)) {
+        cpuid(0x8000008, 0, words);
+        ci->cpu_num  = BIT_EXTRACT_LE(words[WORD_EAX], 0, 8) + 1;
+    } else {
+        ci->cpu_num  = 1;
+    }
+
+    cpuid(1, 0, words);
     ci->cpu_family   = BIT_EXTRACT_LE(words[WORD_EAX],  8, 12);
     ci->cpu_model    = BIT_EXTRACT_LE(words[WORD_EAX],  4,  8);
     ci->cpu_stepping = BIT_EXTRACT_LE(words[WORD_EAX],  0,  4);
 
+    if (!memcmp(vendor_id, "GenuineIntel", 12) ||
+        !memcmp(vendor_id, "AuthenticAMD", 12)) {
+        ci->cpu_family += BIT_EXTRACT_LE(words[WORD_EAX], 20, 28);
+        ci->cpu_model  += BIT_EXTRACT_LE(words[WORD_EAX], 16, 20) << 4;
+    }
+
     int flen = 0, fmax = 80;
     char * flags = malloc(fmax);
 
     for (int i = 0 ; i < 32 ; i++) {
         if (!cpu_flags[i])
-            break;
+            continue;
 
         if (BIT_EXTRACT_LE(words[WORD_EDX], i, i + 1)) {
             int len = strlen(cpu_flags[i]);