x86 thread local storage tweaks
authorBarret Rhoden <brho@cs.berkeley.edu>
Sat, 9 Jan 2010 01:25:22 +0000 (17:25 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Sat, 9 Jan 2010 01:46:36 +0000 (17:46 -0800)
Pulls the actual LDT out of procdata, since the kernel doesn't need to
read/write the LDT, and allows userspace to mmap() only what it needs
based on the number of potential vcores.

kern/arch/i386/env.c
kern/arch/i386/mmu.h
kern/include/ros/procdata.h
user/apps/parlib/mhello.c
user/parlib/inc/parlib.h
user/parlib/src/i386/ldt.c
user/parlib/src/syscall.c

index 83c05bc..aa5ce87 100644 (file)
@@ -17,10 +17,11 @@ void env_pop_tf(trapframe_t *tf)
 {
        /* Load the LDT for this process.  Slightly ghetto doing it here. */
        segdesc_t *my_gdt = per_cpu_info[core_id()].gdt;
-       /* using local space so we can use this macro */
-       segdesc_t ldt_temp = SEG_SYS(STS_LDT, (uint32_t)current->env_procdata->ldt,
-                                    8192, 3);
-
+       /* copy-in and check the LDT location.  the segmentation hardware write the
+        * accessed bit, so we want the memory to be in the user-writeable area. */
+       segdesc_t *ldt = current->env_procdata->ldt;
+       ldt = (segdesc_t*)MIN((uintptr_t)ldt, UTOP - LDT_SIZE);
+       segdesc_t ldt_temp = SEG_SYS(STS_LDT, (uint32_t)ldt, LDT_SIZE, 3);
        my_gdt[GD_LDT >> 3] = ldt_temp;
        asm volatile("lldt %%ax" :: "a"(GD_LDT));
 
index 869a3e8..784d590 100644 (file)
@@ -261,7 +261,8 @@ typedef struct Segdesc {
 #define STS_IG32       0xE         // 32-bit Interrupt Gate
 #define STS_TG32       0xF         // 32-bit Trap Gate
 
-#define SEG_COUNT      7               // Number of segments in the steady state
+#define SEG_COUNT      7               // Number of segments in the steady state
+#define LDT_SIZE       (8192 * sizeof(segdesc_t))
 
 /*
  *
index c430003..2bdeec2 100644 (file)
@@ -25,7 +25,7 @@ typedef struct procinfo {
 
 typedef struct procdata {
 #ifdef __i386__
-       segdesc_t ldt[8192];
+       segdesc_t *ldt;
 #endif
        // The actual ring buffers for communicating with user space
        syscall_sring_t  syscallring;  // Per-process ring buffer for async syscalls
index 51d5ef2..bf79fd8 100644 (file)
@@ -24,7 +24,6 @@ __thread int temp;
 
 int main(int argc, char** argv)
 {
-
        uint32_t vcoreid;
        error_t retval;
 
index b0fc8c4..fe23b42 100644 (file)
@@ -18,6 +18,7 @@
 #include <ros/procdata.h>
 #include <sys/time.h>
 #include <errno.h>
+#include <debug.h>
 
 enum {
        PG_RDONLY = 4,
@@ -50,6 +51,8 @@ ssize_t     sys_resource_req(int type, size_t amount, uint32_t flags);
 void        sys_reboot();
 void        sys_yield();
 int         gettimeofday(struct timeval* tp, void* tzp);
+void *COUNT(length) sys_mmap(void *SNT addr, size_t length, int prot, int flags,
+                             int fd, size_t offset);
 
 #endif // !ASSEMBLER
 
index 790155e..0d67a8b 100644 (file)
  * the memory at %gs:0x0 to hold the address of the top of the TLS.
  *
  * @author Paul Pearce <pearce@eecs.berkeley.edu>
- *
+ * @author Barret Rhoden <brho@eecs.berkeley.edu>
  */
 
-
 #include <ros/common.h>
-#include <parlib.h>
+#include <ros/mman.h>
 #include <arch/mmu.h>
-
-void* core0_tls_top_ptr;
+#include <parlib.h>
+#include <hart.h>
+#include <stdlib.h>
+#include <assert.h>
 
 void ldt_init(uint32_t core_id) {
 
        extern void **tls_array;
        extern char core0_tls[];
 
+       static void *core0_tls_top_ptr;
+       static bool initialized = 0;
        void **tls_handle;
-       
+
+       /* mmap in only the LDT that we need.  once the kernel supports un-FIXED
+        * mmap(), we can stop hardcoding the location (USTACKBOT - LDTSIZE) */
+       if (!initialized++) {
+               procdata.ldt = sys_mmap((void*)USTACKBOT - LDT_SIZE,
+                                       sizeof(segdesc_t) * hart_max_harts(),
+                                       PROT_READ | PROT_WRITE,
+                                       MAP_ANONYMOUS | MAP_FIXED | MAP_POPULATE, 0, 0);
+               sys_getpid(); // force a kernel crossing to reload the LDT
+               if (!procdata.ldt) {
+                       debug("Unable to mmap() an LDT!  Exiting...\n");
+                       exit(-EFAIL);
+               }
+       }
+
        core0_tls_top_ptr = core0_tls + PARLIB_TLS_SIZE;
 
        // Get a handle to this core's tls
index fd371f4..af020b5 100644 (file)
@@ -98,3 +98,24 @@ void sys_yield()
 {
        syscall(SYS_yield,0,0,0,0,0);
 }
+
+/* We need to do some hackery to pass 6 arguments.  Arg4 pts to the real arg4,
+ * arg5, and arg6.  Keep this in sync with kern/src/syscall.c.
+ * TODO: consider a syscall_multi that can take more args, and keep it in sync
+ * with the kernel.  Maybe wait til we fix sysenter to have 5 or 6 args. */
+void *CT(length) sys_mmap(void *SNT addr, size_t length, int prot, int flags,
+                          int fd, size_t offset)
+{
+       struct args {
+               int _flags;
+               int _fd;
+               size_t _offset;
+       } extra_args;
+       extra_args._flags = flags;
+       extra_args._fd = fd;
+       extra_args._offset = offset;
+       // TODO: deputy bitches about this
+       return (void*CT(length))TC(syscall(SYS_mmap, (uint32_t)addr, length, prot,
+                             (int32_t)&extra_args, 0));
+}
+