Early address space switch

- 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
This commit is contained in:
Tomas Hruby 2010-02-09 15:13:52 +00:00
parent b14a86ca5c
commit ad9ba944d1
5 changed files with 39 additions and 20 deletions

View 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

View 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

View 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);
}

View file

@ -198,6 +198,8 @@ not_runnable_pick_new:
idle();
}
switch_address_space(proc_ptr);
check_misc_flags:
vmassert(proc_ptr);

View 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 */