Fixed TLS on i386
authorAndrew Waterman <waterman@ros-dev.(none)>
Tue, 30 Mar 2010 23:45:52 +0000 (16:45 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:35:39 +0000 (17:35 -0700)
A static initialization variable was living in two places (ld.so
and crt0), causing double-initialization of the LDT when a hart
comes in, crashing the first core.

Had to reorganize files so they could be included by the vastly-
included tls.h file in glibc.

17 files changed:
kern/arch/i686/arch.h
kern/arch/i686/ros/arch.h [new file with mode: 0644]
kern/arch/i686/ros/bits/syscall.h [new file with mode: 0644]
kern/arch/i686/ros/syscall.h
kern/arch/sparc/arch.h
kern/arch/sparc/ros/arch.h [new file with mode: 0644]
kern/include/env.h
kern/include/ros/bits/syscall.h [new file with mode: 0644]
kern/include/ros/procdata.h
kern/include/ros/syscall.h
kern/src/syscall.c
tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/i386/dl-load.c [deleted file]
tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/i386/start.c [deleted file]
tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/i386/tls.c [deleted file]
tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/i386/tls.h
user/parlib/hart.c
user/parlib/pthread.c

index 77d6d4f..52c0541 100644 (file)
@@ -1,13 +1,13 @@
 #ifndef ROS_INC_ARCH_H
 #define ROS_INC_ARCH_H
 
+#include <ros/arch/arch.h>
 #include <ros/common.h>
 #include <arch/x86.h>
 #include <arch/trap.h>
 #include <arch/apic.h>
 
 /* Arch Constants */
-#define MAX_NUM_CPUS                           255
 #define HW_CACHE_ALIGN                          64
 
 static __inline void breakpoint(void) __attribute__((always_inline));
diff --git a/kern/arch/i686/ros/arch.h b/kern/arch/i686/ros/arch.h
new file mode 100644 (file)
index 0000000..73e7e5d
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _ROS_ARCH_ARCH_H
+#define _ROS_ARCH_ARCH_H
+
+#define MAX_NUM_CPUS                           255
+
+#endif
diff --git a/kern/arch/i686/ros/bits/syscall.h b/kern/arch/i686/ros/bits/syscall.h
new file mode 100644 (file)
index 0000000..878ea0b
--- /dev/null
@@ -0,0 +1,91 @@
+#ifndef _ROS_ARCH_BITS_SYSCALL_H
+#define _ROS_ARCH_BITS_SYSCALL_H
+
+#define T_SYSCALL      0x80
+
+#ifndef ROS_KERNEL
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <ros/common.h>
+
+// TODO: fix sysenter to take all 5 params
+static inline intreg_t __syscall_sysenter(uint16_t num, intreg_t a1,
+                                    intreg_t a2, intreg_t a3,
+                                    intreg_t a4, intreg_t a5, intreg_t* err_loc)
+{
+       // The kernel clobbers ecx and edx => put them in clobber list.
+       // ebx is handled specially because of a glibc register
+       // allocation problem (not enough registers).
+       intreg_t ret = 0;
+       intreg_t err = 0;
+       asm volatile (""
+                     "  pushl %%ebx;        "
+                     "  movl %5, %%ebx;     "
+                     "  pushl %%ecx;        "
+                     "  pushl %%edx;        "
+                     "  pushl %%esi;        "
+                     "  pushl %%ebp;        "
+                     "  movl %%esp, %%ebp;  "
+                     "  leal 1f, %%edx;     "
+                     "  sysenter;           "
+                     "1:                    "
+                     "  popl %%ebp;         "
+                     "  movl %%esi, %1;     "
+                     "  popl %%esi;         "
+                     "  popl %%edx;         "
+                     "  popl %%ecx;         "
+                     "  popl %%ebx;         "
+                     : "=a" (ret),
+                       "=m" (err)
+                     : "a" (num),
+                       "S" (a1),
+                       "c" (a2),
+                       "r" (a3),
+                       "D" (a4)
+                     : "cc", "memory");
+       if(err != 0 && err_loc != NULL)
+               *err_loc = err;
+       return ret;
+}
+
+static inline intreg_t __syscall_trap(uint16_t num, intreg_t a1,
+                             intreg_t a2, intreg_t a3,
+                             intreg_t a4, intreg_t a5, intreg_t* err_loc)
+{
+       intreg_t ret;
+       intreg_t err;
+
+       // Generic system call: pass system call number in AX,
+       // up to five parameters in DX, CX, BX, DI, SI.
+       // Interrupt kernel with T_SYSCALL.
+       //
+       // The "volatile" tells the assembler not to optimize
+       // this instruction away just because we don't use the
+       // return value.
+       //
+       // The last clause tells the assembler that this can
+       // potentially change the condition codes and arbitrary
+       // memory locations.
+
+       asm volatile(""
+                    " int %1"
+                    : "=a" (ret),
+                      "=S" (err)
+                    : "i" (T_SYSCALL),
+                      "a" (num),
+                      "d" (a1),
+                      "c" (a2),
+                      "b" (a3),
+                      "D" (a4),
+                      "S" (a5)
+                    : "cc", "memory");
+       if(err != 0 && err_loc != NULL)
+               *err_loc = err;
+       return ret;
+}
+
+#endif
+
+#endif
+
index 13d2aa8..aa64297 100644 (file)
@@ -5,94 +5,15 @@
 
 #ifndef ROS_KERNEL
 
-#include <sys/types.h>
-#include <stdint.h>
-#include <ros/common.h>
+#include <ros/arch/bits/syscall.h>
 #include <errno.h>
 
-// TODO: fix sysenter to take all 5 params
-static inline intreg_t __syscall_sysenter(uint16_t num, intreg_t a1,
-                                    intreg_t a2, intreg_t a3,
-                                    intreg_t a4, intreg_t a5, intreg_t* err_loc)
-{
-       // The kernel clobbers ecx and edx => put them in clobber list.
-       // ebx is handled specially because of a glibc register
-       // allocation problem (not enough registers).
-       intreg_t ret = 0;
-       intreg_t err = 0;
-       asm volatile (""
-                     "  pushl %%ebx;        "
-                     "  movl %5, %%ebx;     "
-                     "  pushl %%ecx;        "
-                     "  pushl %%edx;        "
-                     "  pushl %%esi;        "
-                     "  pushl %%ebp;        "
-                     "  movl %%esp, %%ebp;  "
-                     "  leal 1f, %%edx;     "
-                     "  sysenter;           "
-                     "1:                    "
-                     "  popl %%ebp;         "
-                     "  movl %%esi, %1;     "
-                     "  popl %%esi;         "
-                     "  popl %%edx;         "
-                     "  popl %%ecx;         "
-                     "  popl %%ebx;         "
-                     : "=a" (ret),
-                       "=m" (err)
-                     : "a" (num),
-                       "S" (a1),
-                       "c" (a2),
-                       "r" (a3),
-                       "D" (a4)
-                     : "cc", "memory");
-       if(err != 0 && err_loc != NULL)
-               *err_loc = err;
-       return ret;
-}
-
 static inline intreg_t syscall_sysenter(uint16_t num, intreg_t a1,
                                   intreg_t a2, intreg_t a3,
                                   intreg_t a4, intreg_t a5)
 {
        return __syscall_sysenter(num, a1, a2, a3, a4, a5, &errno);
 }
-
-static inline intreg_t __syscall_trap(uint16_t num, intreg_t a1,
-                             intreg_t a2, intreg_t a3,
-                             intreg_t a4, intreg_t a5, intreg_t* err_loc)
-{
-       intreg_t ret;
-       intreg_t err;
-
-       // Generic system call: pass system call number in AX,
-       // up to five parameters in DX, CX, BX, DI, SI.
-       // Interrupt kernel with T_SYSCALL.
-       //
-       // The "volatile" tells the assembler not to optimize
-       // this instruction away just because we don't use the
-       // return value.
-       //
-       // The last clause tells the assembler that this can
-       // potentially change the condition codes and arbitrary
-       // memory locations.
-
-       asm volatile(""
-                    " int %1"
-                    : "=a" (ret),
-                      "=S" (err)
-                    : "i" (T_SYSCALL),
-                      "a" (num),
-                      "d" (a1),
-                      "c" (a2),
-                      "b" (a3),
-                      "D" (a4),
-                      "S" (a5)
-                    : "cc", "memory");
-       if(err != 0 && err_loc != NULL)
-               *err_loc = err;
-       return ret;
-}
-
 static inline intreg_t syscall_trap(uint16_t num, intreg_t a1,
                                   intreg_t a2, intreg_t a3,
                                   intreg_t a4, intreg_t a5)
index 840c710..5edf7c8 100644 (file)
@@ -1,8 +1,9 @@
 #ifndef ROS_INC_ARCH_H
 #define ROS_INC_ARCH_H
 
+#include <ros/arch/arch.h>
+
 /* Arch Constants */
-#define MAX_NUM_CPUS           64
 #define HW_CACHE_ALIGN         64
 #define IOAPIC_BASE            0xFEC00000 // max virtual address
 
diff --git a/kern/arch/sparc/ros/arch.h b/kern/arch/sparc/ros/arch.h
new file mode 100644 (file)
index 0000000..6c32ea5
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _ROS_ARCH_ARCH_H
+#define _ROS_ARCH_ARCH_H
+
+#define MAX_NUM_CPUS                           64
+
+#endif
index 0097836..68124b2 100644 (file)
@@ -9,6 +9,7 @@
 #include <ros/sysevent.h>
 #include <error.h>
 #include <ros/procdata.h>
+#include <ros/procinfo.h>
 #include <ros/resource.h>
 #include <arch/trap.h>
 #include <ros/common.h>
diff --git a/kern/include/ros/bits/syscall.h b/kern/include/ros/bits/syscall.h
new file mode 100644 (file)
index 0000000..62908d9
--- /dev/null
@@ -0,0 +1,73 @@
+#ifndef ROS_INCLUDE_BITS_SYSCALL_H
+#define ROS_INCLUDE_BITS_SYSCALL_H
+
+/* system call numbers.  need to #def them for use in assembly. */
+#define SYS_null                                        1
+#define SYS_cache_buster                        2
+#define SYS_cache_invalidate            3
+#define SYS_reboot                                      4
+#define SYS_cputs                                       5
+#define SYS_cgetc                                       6
+#define SYS_getcpuid                            7
+#define SYS_getvcoreid                          8
+#define SYS_getpid                                      9
+#define SYS_proc_create                                10
+#define SYS_proc_run                           11
+#define SYS_proc_destroy                       12
+#define SYS_yield                                      13
+#define SYS_run_binary                         14
+#define SYS_fork                                       15
+#define SYS_exec                                       16
+#define SYS_trywait                                    17
+#define SYS_mmap                                       18
+#define SYS_munmap                                     19
+#define SYS_mprotect                           20
+/* // these are the other mmap related calls, some of which we'll implement
+#define SYS_mincore // can read page tables instead
+#define SYS_madvise
+#define SYS_mlock
+#define SYS_msync
+*/
+#define SYS_brk                                                21
+#define SYS_shared_page_alloc          22
+#define SYS_shared_page_free           23
+#define SYS_resource_req                       24
+/* Platform specific syscalls */
+#define SYS_serial_read                                25
+#define SYS_serial_write                       26
+#define SYS_eth_read                           27
+#define SYS_eth_write                          28
+#define SYS_eth_get_mac_addr                   29
+#define SYS_eth_recv_check                     30
+
+#define SYS_read                               100
+#define SYS_write                              101
+#define SYS_open                               102
+#define SYS_close                              103
+#define SYS_fstat                              104
+#define SYS_stat                               105
+#define SYS_lstat                              106
+#define SYS_fcntl                              107
+#define SYS_access                             108
+#define SYS_umask                              109
+#define SYS_chmod                              110
+#define SYS_lseek                              111
+#define SYS_link                               112
+#define SYS_unlink                             113
+#define SYS_chdir                              114
+#define SYS_getcwd                             115
+#define SYS_gettimeofday               116
+#define SYS_tcgetattr                  117
+#define SYS_tcsetattr                  118
+
+/* For Buster Measurement Flags */
+#define BUSTER_SHARED                  0x0001
+#define BUSTER_STRIDED                 0x0002
+#define BUSTER_LOCKED                  0x0004
+#define BUSTER_PRINT_TICKS             0x0008
+#define BUSTER_JUST_LOCKS              0x0010 // unimplemented
+
+// for system calls that pass filenames
+#define MAX_PATH_LEN 256
+
+#endif /* !ROS_INCLUDE_SYSCALL_H */
index a76c689..1509566 100644 (file)
@@ -4,12 +4,9 @@
 #define ROS_PROCDATA_H
 
 #include <ros/memlayout.h>
-#include <ros/syscall.h>
 #include <ros/ring_syscall.h>
-#include <ros/common.h>
-#include <ros/procinfo.h>
 #include <arch/mmu.h>
-#include <arch/arch.h>
+#include <ros/arch/arch.h>
 
 typedef struct procdata {
        // The actual ring buffers for communicating with user space
index fbcf46e..0a9dc75 100644 (file)
@@ -1,74 +1,7 @@
 #ifndef ROS_INCLUDE_SYSCALL_H
 #define ROS_INCLUDE_SYSCALL_H
 
-/* system call numbers.  need to #def them for use in assembly. */
-#define SYS_null                                        1
-#define SYS_cache_buster                        2
-#define SYS_cache_invalidate            3
-#define SYS_reboot                                      4
-#define SYS_cputs                                       5
-#define SYS_cgetc                                       6
-#define SYS_getcpuid                            7
-#define SYS_getvcoreid                          8
-#define SYS_getpid                                      9
-#define SYS_proc_create                                10
-#define SYS_proc_run                           11
-#define SYS_proc_destroy                       12
-#define SYS_yield                                      13
-#define SYS_run_binary                         14
-#define SYS_fork                                       15
-#define SYS_exec                                       16
-#define SYS_trywait                                    17
-#define SYS_mmap                                       18
-#define SYS_munmap                                     19
-#define SYS_mprotect                           20
-/* // these are the other mmap related calls, some of which we'll implement
-#define SYS_mincore // can read page tables instead
-#define SYS_madvise
-#define SYS_mlock
-#define SYS_msync
-*/
-#define SYS_brk                                                21
-#define SYS_shared_page_alloc          22
-#define SYS_shared_page_free           23
-#define SYS_resource_req                       24
-/* Platform specific syscalls */
-#define SYS_serial_read                                25
-#define SYS_serial_write                       26
-#define SYS_eth_read                           27
-#define SYS_eth_write                          28
-#define SYS_eth_get_mac_addr                   29
-#define SYS_eth_recv_check                     30
-
-#define SYS_read                               100
-#define SYS_write                              101
-#define SYS_open                               102
-#define SYS_close                              103
-#define SYS_fstat                              104
-#define SYS_stat                               105
-#define SYS_lstat                              106
-#define SYS_fcntl                              107
-#define SYS_access                             108
-#define SYS_umask                              109
-#define SYS_chmod                              110
-#define SYS_lseek                              111
-#define SYS_link                               112
-#define SYS_unlink                             113
-#define SYS_chdir                              114
-#define SYS_getcwd                             115
-#define SYS_gettimeofday               116
-#define SYS_tcgetattr                  117
-#define SYS_tcsetattr                  118
-
-/* For Buster Measurement Flags */
-#define BUSTER_SHARED                  0x0001
-#define BUSTER_STRIDED                 0x0002
-#define BUSTER_LOCKED                  0x0004
-#define BUSTER_PRINT_TICKS             0x0008
-#define BUSTER_JUST_LOCKS              0x0010 // unimplemented
-
-// for system calls that pass filenames
-#define MAX_PATH_LEN 256
+#include <ros/bits/syscall.h>
 
 // convenience wrapper for __ros_syscall
 #define ros_syscall(which,a0,a1,a2,a3,a4) \
index 6dbe1f4..ba9447e 100644 (file)
@@ -401,6 +401,7 @@ intreg_t sys_exec(struct proc* p, int fd, procinfo_t* pi)
                goto out;
        }
        proc_init_procinfo(p);
+       memset(p->env_procdata, 0, sizeof(procdata_t));
 
        env_user_mem_free(p,0,USTACKTOP);
 
diff --git a/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/i386/dl-load.c b/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/i386/dl-load.c
deleted file mode 100644 (file)
index 5d58953..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#include <elf/dl-load.c>
-
-#ifdef SHARED
-# include <sysdeps/ros/i386/tls.c>
-#endif
diff --git a/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/i386/start.c b/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/i386/start.c
deleted file mode 100644 (file)
index 319ff39..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#include <sysdeps/ros/start.c>
-
-#ifndef SHARED
-# include <sysdeps/ros/i386/tls.c>
-#endif
diff --git a/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/i386/tls.c b/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/i386/tls.c
deleted file mode 100644 (file)
index 331619f..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-#include <tls.h>
-#include <sys/mman.h>
-#include <ros/arch/hart.h>
-#include <ros/syscall.h>
-#include <ros/procinfo.h>
-#include <ros/procdata.h>
-#include <arch/mmu.h>
-#include <assert.h>
-
-const char* tls_init_tp(void* thrdescr)
-{
-  int core_id = __syscall_sysenter(SYS_getvcoreid,0,0,0,0,0,NULL);
-
-  static int initialized = 0;
-  if(!initialized)
-  {
-    initialized = 1;
-
-    size_t sz= (sizeof(segdesc_t)*__procinfo.max_harts+PGSIZE-1)/PGSIZE*PGSIZE;
-    
-    intreg_t params[3] = { MAP_ANONYMOUS | MAP_FIXED, -1, 0 };
-    __procdata.ldt  = (void*) __syscall_sysenter(SYS_mmap,
-                                                 (void*)USTACKBOT - LDT_SIZE, 
-                                                 sz, PROT_READ | PROT_WRITE, 
-                                                 params, 0, NULL);
-
-    // force kernel crossing
-    __syscall_sysenter(SYS_getpid,0,0,0,0,0,NULL);
-    if(__procdata.ldt == MAP_FAILED)
-      return "tls couldn't allocate memory\n";
-  }
-
-  // Build the segment
-  segdesc_t tmp = SEG(STA_W, (uint32_t)thrdescr, (uint32_t)thrdescr + 4, 3);
-
-  // Setup the correct LDT entry for this hart
-  __procdata.ldt[core_id] = tmp;
-
-  // Create the GS register.
-  uint32_t gs = (core_id << 3) | 0x07;
-
-  // Set the GS register.
-  asm volatile("movl %0,%%gs" : : "r" (gs));
-
-  return NULL;
-}
index 3dae1e8..4b8e585 100644 (file)
 //# include <list.h>
 # include <sysdep.h>
 # include <kernel-features.h>
+#include <sys/mman.h>
+#include <ros/bits/syscall.h>
+#include <ros/arch/bits/syscall.h>
+#include <ros/procinfo.h>
+#include <ros/procdata.h>
+#include <arch/mmu.h>
+
 
 /* Type for the dtv.  */
 typedef union dtv
@@ -201,7 +208,6 @@ union user_desc_init
 /* Code to initially initialize the thread pointer.  This might need
    special attention since 'errno' is not yet available and if the
    operation can cause a failure 'errno' must not be touched.  */
-const char* tls_init_tp(void* thrdescr);
 # define TLS_INIT_TP(thrdescr, secondcall) tls_init_tp(thrdescr)
 
 /* Return the address of the dtv for the current thread.  */
@@ -425,6 +431,41 @@ const char* tls_init_tp(void* thrdescr);
 #define THREAD_GSCOPE_WAIT() \
   GL(dl_wait_lookup_done) ()
 
+static const char* tls_init_tp(void* thrdescr)
+{
+  int core_id = __syscall_sysenter(SYS_getvcoreid,0,0,0,0,0,NULL);
+
+  if(__procdata.ldt == NULL)
+  {
+    size_t sz= (sizeof(segdesc_t)*__procinfo.max_harts+PGSIZE-1)/PGSIZE*PGSIZE;
+    
+    intreg_t params[3] = { MAP_ANONYMOUS | MAP_POPULATE, -1, 0 };
+    void* ldt = (void*) __syscall_sysenter(SYS_mmap, 0,
+                                           sz, PROT_READ | PROT_WRITE, 
+                                           (intreg_t)params, 0, NULL);
+    if(ldt == MAP_FAILED)
+      return "tls couldn't allocate memory\n";
+
+    __procdata.ldt = ldt;
+    // force kernel crossing
+    __syscall_sysenter(SYS_getpid,0,0,0,0,0,NULL);
+  }
+
+  // Build the segment
+  segdesc_t tmp = SEG(STA_W, (uint32_t)thrdescr, (uint32_t)thrdescr + 4, 3);
+
+  // Setup the correct LDT entry for this hart
+  __procdata.ldt[core_id] = tmp;
+
+  // Create the GS register.
+  uint32_t gs = (core_id << 3) | 0x07;
+
+  // Set the GS register.
+  asm volatile("movl %0,%%gs" : : "r" (gs));
+
+  return NULL;
+}
+
 #endif /* __ASSEMBLER__ */
 
 #endif /* tls.h */
index 3598631..7983580 100644 (file)
@@ -5,6 +5,7 @@
 #include <unistd.h>
 #include <stdlib.h>
 #include <sys/mman.h>
+#include <debug.h>
 
 // Only need in this file because _dl_allocate and friends are
 //  internal functions in glibc
index e0a6bc4..bda3ab3 100644 (file)
@@ -6,6 +6,7 @@
 #include <stdio.h>
 #include <errno.h>
 
+#include <debug.h>
 int threads_active = 1;
 hart_lock_t work_queue_lock = HART_LOCK_INIT;
 pthread_t work_queue_head = 0;
@@ -79,7 +80,6 @@ int pthread_create(pthread_t* thread, const pthread_attr_t* attr,
   (*thread)->next = 0;
   (*thread)->finished = 0;
   (*thread)->detached = 0;
-
   hart_lock_lock(&work_queue_lock);
   {
     threads_active++;