commit-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

gnumach/i386/i386 pcb.c thread.h user_ldt.c


From: Roland McGrath
Subject: gnumach/i386/i386 pcb.c thread.h user_ldt.c
Date: Thu, 03 Oct 2002 22:45:04 -0400

CVSROOT:        /cvsroot/hurd
Module name:    gnumach
Changes by:     Roland McGrath <address@hidden> 02/10/03 22:45:04

Modified files:
        i386/i386      : pcb.c thread.h user_ldt.c 

Log message:
        2002-10-03  Roland McGrath  <address@hidden>
        
        * i386/include/mach/i386/mach_i386.defs (i386_set_gdt, i386_get_gdt):
        New routines.
        * i386/i386/user_ldt.c (i386_set_gdt, i386_get_gdt): New functions.
        * i386/i386/gdt.h (USER_GDT, USER_GDT_SLOTS): New macros.
        * i386/i386/thread.h (struct i386_machine_state): New member user_gdt.
        * i386/i386/pcb.c (switch_ktss): Copy those slots into the GDT.
        Remove magic %gs:0 pseudo-register support.
        * i386/i386/ldt.h (USER_GS): Macro removed.
        * i386/i386/pcb.c (pcb_init): Set gs to USER_DS, not USER_GS.
        (thread_setstatus): Likewise.
        * i386/i386/mp_desc.h (struct mp_desc_table): Remove member
        `user_thread_register'.
        * i386/i386/thread.h (struct i386_machine_state): Likewise.
        * i386/i386/mp_desc.c (mp_desc_init): Don't set up USER_GS in LDT.
        * i386/i386/ldt.c (ldt_init): Likewise.
        * i386/intel/pmap.c (pmap_bootstrap): Don't give users access to
        direct-mapped pages.
        * i386/i386/user_ldt.c (i386_set_ldt): Don't cap segment limits.

CVSWeb URLs:
http://savannah.gnu.org/cgi-bin/viewcvs/gnumach/gnumach/i386/i386/pcb.c.diff?tr1=1.3&tr2=1.4&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnumach/gnumach/i386/i386/thread.h.diff?tr1=1.4&tr2=1.5&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnumach/gnumach/i386/i386/user_ldt.c.diff?tr1=1.3&tr2=1.4&r1=text&r2=text

Patches:
Index: gnumach/i386/i386/pcb.c
diff -u gnumach/i386/i386/pcb.c:1.3 gnumach/i386/i386/pcb.c:1.4
--- gnumach/i386/i386/pcb.c:1.3 Mon May 27 19:01:50 2002
+++ gnumach/i386/i386/pcb.c     Thu Oct  3 22:45:04 2002
@@ -126,13 +126,9 @@
 #if    NCPUS > 1
 #define        curr_gdt(mycpu)         (mp_gdt[mycpu])
 #define        curr_ktss(mycpu)        (mp_ktss[mycpu])
-#define curr_user_thread_reg(mycpu)    \
-  (mp_desc_table[mycpu].user_thread_register)
 #else
 #define        curr_gdt(mycpu)         (gdt)
 #define        curr_ktss(mycpu)        ((struct task_tss *)&base_tss)
-#define curr_user_thread_reg(mycpu) (user_thread_register)
-natural_t user_thread_register;
 #endif
 
 #define        gdt_desc_p(mycpu,sel) \
@@ -182,9 +178,11 @@
        }
       }
 
-    if (old_pcb)
-      old_pcb->ims.user_thread_register = curr_user_thread_reg(mycpu);
-    curr_user_thread_reg(mycpu) = pcb->ims.user_thread_register;
+       /* Copy in the per-thread GDT slots.  No reloading is necessary
+          because just restoring the segment registers on the way back to
+          user mode reloads the shadow registers from the in-memory GDT.  */
+       memcpy (gdt_desc_p (mycpu, USER_GDT),
+               pcb->ims.user_gdt, sizeof pcb->ims.user_gdt);
 
        /*
         * Load the floating-point context, if necessary.
@@ -363,7 +361,7 @@
        pcb->iss.ds = USER_DS;
        pcb->iss.es = USER_DS;
        pcb->iss.fs = USER_DS;
-       pcb->iss.gs = USER_GS;
+       pcb->iss.gs = USER_DS;
        pcb->iss.eflags = EFL_USER_SET;
 
        thread->pcb = pcb;
@@ -497,7 +495,7 @@
                    saved_state->ds = USER_DS;
                    saved_state->es = USER_DS;
                    saved_state->fs = USER_DS;
-                   saved_state->gs = USER_GS;
+                   saved_state->gs = USER_DS;
                }
                else {
                    /*
Index: gnumach/i386/i386/thread.h
diff -u gnumach/i386/i386/thread.h:1.4 gnumach/i386/i386/thread.h:1.5
--- gnumach/i386/i386/thread.h:1.4      Mon May 27 19:01:51 2002
+++ gnumach/i386/i386/thread.h  Thu Oct  3 22:45:04 2002
@@ -36,6 +36,7 @@
 #include <mach/boolean.h>
 #include <mach/machine/vm_types.h>
 #include <mach/machine/fp_reg.h>
+#include "gdt.h"
 
 #include <kern/lock.h>
 
@@ -130,7 +131,7 @@
        struct user_ldt *       ldt;
        struct i386_fpsave_state *ifps;
        struct v86_assist_state v86s;
-       natural_t user_thread_register;
+       struct x86_desc user_gdt[USER_GDT_SLOTS];
 };
 
 typedef struct pcb {
Index: gnumach/i386/i386/user_ldt.c
diff -u gnumach/i386/i386/user_ldt.c:1.3 gnumach/i386/i386/user_ldt.c:1.4
--- gnumach/i386/i386/user_ldt.c:1.3    Mon May 27 19:01:51 2002
+++ gnumach/i386/i386/user_ldt.c        Thu Oct  3 22:45:04 2002
@@ -170,23 +170,6 @@
                case ACC_P | ACC_PL_U | ACC_CODE_CR:
                case ACC_P | ACC_PL_U | ACC_CALL_GATE_16:
                case ACC_P | ACC_PL_U | ACC_CALL_GATE:
-                 /* Silently cap the segment's limit at VM_MAX_ADDRESS. */
-                 {
-                   unsigned base = ((dp->base_high << 24)
-                                    | (dp->base_med << 16) | dp->base_low);
-                   unsigned limit
-                     = ((dp->limit_high << 16) | dp->limit_low);
-                   if (dp->granularity & SZ_G)
-                     limit <<= 12;
-                   if (base > VM_MAX_ADDRESS)
-                     {
-                       fill_descriptor_base(dp, 0);
-                       fill_descriptor_limit(dp, 0);
-                     }
-                   else if (base + limit > VM_MAX_ADDRESS
-                            || base + limit < base)
-                     fill_descriptor_limit(dp, VM_MAX_ADDRESS - base);
-                 }
                  break;
                default:
                    return KERN_INVALID_ARGUMENT;
@@ -415,4 +398,59 @@
        kfree((vm_offset_t)user_ldt,
                user_ldt->desc.limit_low + 1
                + sizeof(struct x86_desc));
+}
+
+
+kern_return_t
+i386_set_gdt (thread_t thread, int *selector, struct x86_desc *desc)
+{
+  int idx;
+
+  if (thread == THREAD_NULL)
+    return KERN_INVALID_ARGUMENT;
+
+  if (*selector == -1)
+    {
+      for (idx = sel_idx (USER_GDT); idx < sel_idx (USER_GDT) + USER_GDT_SLOTS;
+          ++idx)
+       if ((thread->pcb->ims.user_gdt[idx].access & ACC_P) == 0)
+         {
+           *selector = (idx << 3) | SEL_PL_U;
+           break;
+         }
+      if (idx == sel_idx (USER_GDT) + USER_GDT_SLOTS)
+       return KERN_NO_SPACE;   /* ? */
+    }
+  else if ((*selector & (SEL_LDT|SEL_PL)) != SEL_PL_U
+          || sel_idx (*selector) < USER_GDT
+          || sel_idx (*selector) >= USER_GDT + USER_GDT_SLOTS)
+    return KERN_INVALID_ARGUMENT;
+  else
+    idx = sel_idx (*selector);
+
+  if ((desc->access & ACC_P) == 0)
+    memset (&thread->pcb->ims.user_gdt[idx], 0,
+           sizeof thread->pcb->ims.user_gdt[idx]);
+  else if ((desc->access & (ACC_TYPE|ACC_PL)) != (ACC_TYPE_USER|ACC_PL_U))
+    return KERN_INVALID_ARGUMENT;
+  else
+    thread->pcb->ims.user_gdt[idx] = *desc;
+
+  return KERN_SUCCESS;
+}
+
+kern_return_t
+i386_get_gdt (thread_t thread, int selector, struct x86_desc *desc)
+{
+  if (thread == THREAD_NULL)
+    return KERN_INVALID_ARGUMENT;
+
+  if ((selector & (SEL_LDT|SEL_PL)) != SEL_PL_U
+      || sel_idx (selector) < USER_GDT
+      || sel_idx (selector) >= USER_GDT + USER_GDT_SLOTS)
+    return KERN_INVALID_ARGUMENT;
+
+  *desc = thread->pcb->ims.user_gdt[sel_idx (selector)];
+
+  return KERN_SUCCESS;
 }




reply via email to

[Prev in Thread] Current Thread [Next in Thread]