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:
parent
b14a86ca5c
commit
ad9ba944d1
5 changed files with 39 additions and 20 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -198,6 +198,8 @@ not_runnable_pick_new:
|
|||
idle();
|
||||
}
|
||||
|
||||
switch_address_space(proc_ptr);
|
||||
|
||||
check_misc_flags:
|
||||
|
||||
vmassert(proc_ptr);
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue