]> Zhao Yanbai Git Server - minix.git/commitdiff
Early address space switch
authorTomas Hruby <tom@minix3.org>
Tue, 9 Feb 2010 15:13:52 +0000 (15:13 +0000)
committerTomas Hruby <tom@minix3.org>
Tue, 9 Feb 2010 15:13:52 +0000 (15:13 +0000)
- switch_address_space() implements a switch of the user address space
  for the destination process

- this makes memory of this process easily accessible, e.g. a pointer
  valid in the userspace can be used with a little complexity to
  access the process's memory

- the switch does not happed only just before we return to userspace,
  however, it happens right after we know which process we are going
  to schedule. This happens before we start processing the misc flags
  of this process so its memory is available

- if the process becomes not runnable while processing the mics flags
  we pick a new process and we switch the address space again which
  introduces possibly a little bit more overhead, however, it is
  hopefully hidden by reducing the overheads when we actually access
  the memory

kernel/arch/i386/klib386.S
kernel/arch/i386/mpx386.S
kernel/arch/i386/system.c
kernel/proc.c
kernel/proto.h

index 6e136cc11911ff8c5a5383eda8077b890c011fb5..852fa6c8b50a4186d9200d4fa94c32684cd640bc 100644 (file)
@@ -692,3 +692,39 @@ idt_reload:
 reload_ds:
        RELOAD_SEG_REG(%ds)
        ret
+
+/*===========================================================================*/
+/*                           switch_address_space                           */
+/*===========================================================================*/
+/* PUBLIC void switch_address_space(struct proc *p)
+ *
+ * sets the %cr3 register to the supplied value if it is not already set to the
+ * same value in which case it would only result in an extra TLB flush which is
+ * not desirable
+ */
+ .balign 16
+.globl switch_address_space
+switch_address_space:
+
+       /* read the process pointer */
+       mov     4(%esp), %edx
+       /* enable process' segment descriptors  */
+       lldt    P_LDT_SEL(%edx)
+       /* get the new cr3 value */
+       movl    P_CR3(%edx), %eax
+       /* test if the new cr3 != NULL */
+       cmpl    $0, %eax
+       je      0f
+
+       /*
+        * test if the cr3 is loaded with the current value to avoid unnecessary
+        * TLB flushes
+        */
+       mov     %cr3, %ecx
+       cmp     %ecx, %eax
+       je      0f
+       mov     %eax, %cr3
+       mov     %edx, ptproc
+       movl    $0, dirtypde
+0:
+       ret
index d67ba0acc38d85c55a6c7f10483afa728433991a..321bc59a5cbb875d417b7b1f1710c35c491750c8 100644 (file)
@@ -470,22 +470,6 @@ restart:
        /* %eax is set by schedcheck() to the process to run */
        mov     %eax, %ebp      /* will assume P_STACKBASE == 0 */
 
-       cmpl    $0, P_CR3(%ebp)
-       jz      0f
-
-       /*
-        * test if the cr3 is loaded with the current value to avoid unnecessary
-        * TLB flushes
-        */
-       mov     P_CR3(%ebp), %eax
-       mov     %cr3, %ecx
-       cmp     %ecx, %eax
-       jz      0f
-       mov     %eax, %cr3
-       mov     %ebp, ptproc
-       movl    $0, dirtypde
-0:
-
        /* reconstruct the stack for iret */
        movl    SSREG(%ebp), %eax
        push    %eax
@@ -500,7 +484,6 @@ restart:
 
        RESTORE_GP_REGS(%ebp)
 
-       lldt    P_LDT_SEL(%ebp) /* enable process' segment descriptors  */
        RESTORE_SEGS(%ebp)
 
        movl    %ss:BPREG(%ebp), %ebp
index 703056cc3e9ab2eab7a26d66c69379fc179079c5..d857eeece4992f6307a77bab04b100309265d353 100644 (file)
@@ -477,9 +477,6 @@ PUBLIC void arch_do_syscall(struct proc *proc)
   m_ptr = (message *) proc->p_reg.bx;
   bit_map = proc->p_reg.dx;
 
-  /* do_ipc() expects the given process's memory to be accessible. */
-  vm_set_cr3(proc);
-
   /* Make the system call, for real this time. */
   proc->p_reg.retreg = do_ipc(call_nr, src_dst_e, m_ptr, bit_map);
 }
index 99a2b202dad53fc27292ee66672508ed9d95c6cc..04062a105c8aafc2b5a75763d78e01cc3307ccba 100644 (file)
@@ -198,6 +198,8 @@ not_runnable_pick_new:
                idle();
        }
 
+       switch_address_space(proc_ptr);
+
 check_misc_flags:
 
        vmassert(proc_ptr);
index 69c4d9f07816754d5100793cf1709fb6b8915b87..5226727a48e55d7bfa3d07ddc420e5e53c7b173c 100644 (file)
@@ -171,4 +171,5 @@ _PROTOTYPE( int arch_phys_map, (int index, phys_bytes *addr,
 _PROTOTYPE( int arch_phys_map_reply, (int index, vir_bytes addr));
 _PROTOTYPE( int arch_enable_paging, (void));
 
+_PROTOTYPE(void switch_address_space, (struct proc * p));
 #endif /* PROTO_H */