SMP - Cpu local variables
- most global variables carry information which is specific to the local CPU and each CPU must have its own copy - cpu local variable must be declared in cpulocal.h between DECLARE_CPULOCAL_START and DECLARE_CPULOCAL_END markers using DECLARE_CPULOCAL macro - to access the cpu local data the provided macros must be used get_cpu_var(cpu, name) get_cpu_var_ptr(cpu, name) get_cpulocal_var(name) get_cpulocal_var_ptr(name) - using this macros makes future changes in the implementation possible - switching to ELF will make the declaration of cpu local data much simpler, e.g. CPULOCAL int blah; anywhere in the kernel source code
This commit is contained in:
@@ -30,7 +30,7 @@ struct proc *p;
|
||||
p->p_seg.p_cr3 = m_ptr->SVMCTL_PTROOT;
|
||||
p->p_seg.p_cr3_v = (u32_t *) m_ptr->SVMCTL_PTROOT_V;
|
||||
p->p_misc_flags |= MF_FULLVM;
|
||||
if(p == ptproc) {
|
||||
if(p == get_cpulocal_var(ptproc)) {
|
||||
write_cr3(p->p_seg.p_cr3);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -81,8 +81,8 @@ PUBLIC __dead void arch_shutdown(int how)
|
||||
/* We're panicing? Then retrieve and decode currently
|
||||
* loaded segment selectors.
|
||||
*/
|
||||
printseg("cs: ", 1, proc_ptr, read_cs());
|
||||
printseg("ds: ", 0, proc_ptr, read_ds());
|
||||
printseg("cs: ", 1, get_cpulocal_var(proc_ptr), read_cs());
|
||||
printseg("ds: ", 0, get_cpulocal_var(proc_ptr), read_ds());
|
||||
if(read_ds() != read_ss()) {
|
||||
printseg("ss: ", 0, NULL, read_ss());
|
||||
}
|
||||
@@ -536,7 +536,7 @@ PUBLIC int arch_set_params(char *params, int size)
|
||||
PUBLIC void arch_do_syscall(struct proc *proc)
|
||||
{
|
||||
/* do_ipc assumes that it's running because of the current process */
|
||||
assert(proc == proc_ptr);
|
||||
assert(proc == get_cpulocal_var(proc_ptr));
|
||||
/* Make the system call, for real this time. */
|
||||
proc->p_reg.retreg =
|
||||
do_ipc(proc->p_reg.cx, proc->p_reg.retreg, proc->p_reg.bx);
|
||||
@@ -545,11 +545,13 @@ PUBLIC void arch_do_syscall(struct proc *proc)
|
||||
PUBLIC struct proc * arch_finish_switch_to_user(void)
|
||||
{
|
||||
char * stk;
|
||||
struct proc * p;
|
||||
|
||||
stk = (char *)tss.sp0;
|
||||
/* set pointer to the process to run on the stack */
|
||||
*((reg_t *)stk) = (reg_t) proc_ptr;
|
||||
|
||||
return proc_ptr;
|
||||
p = get_cpulocal_var(proc_ptr);
|
||||
*((reg_t *)stk) = (reg_t) p;
|
||||
return p;
|
||||
}
|
||||
|
||||
PUBLIC void fpu_sigcontext(struct proc *pr, struct sigframe *fr, struct sigcontext *sc)
|
||||
|
||||
@@ -136,7 +136,7 @@ PUBLIC void exception_handler(int is_nested, struct exception_frame * frame)
|
||||
struct proc *saved_proc;
|
||||
|
||||
/* Save proc_ptr, because it may be changed by debug statements. */
|
||||
saved_proc = proc_ptr;
|
||||
saved_proc = get_cpulocal_var(proc_ptr);
|
||||
|
||||
ep = &ex_data[frame->vector];
|
||||
|
||||
|
||||
@@ -95,6 +95,11 @@ _PROTOTYPE( void frstor, (void *));
|
||||
_PROTOTYPE( unsigned short fnstsw, (void));
|
||||
_PROTOTYPE( void fnstcw, (unsigned short* cw));
|
||||
|
||||
_PROTOTYPE(void __switch_address_space, (struct proc * p,
|
||||
struct proc ** __ptproc));
|
||||
#define switch_address_space(proc) \
|
||||
__switch_address_space(proc, get_cpulocal_var_ptr(ptproc))
|
||||
|
||||
/* protect.c */
|
||||
struct tss_s {
|
||||
reg_t backlink;
|
||||
|
||||
@@ -812,15 +812,15 @@ ENTRY(reload_ds)
|
||||
ret
|
||||
|
||||
/*===========================================================================*/
|
||||
/* switch_address_space */
|
||||
/* __switch_address_space */
|
||||
/*===========================================================================*/
|
||||
/* PUBLIC void switch_address_space(struct proc *p)
|
||||
/* PUBLIC void __switch_address_space(struct proc *p, struct ** ptproc)
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
ENTRY(switch_address_space)
|
||||
ENTRY(__switch_address_space)
|
||||
/* read the process pointer */
|
||||
mov 4(%esp), %edx
|
||||
/* enable process' segment descriptors */
|
||||
@@ -839,7 +839,9 @@ ENTRY(switch_address_space)
|
||||
cmp %ecx, %eax
|
||||
je 0f
|
||||
mov %eax, %cr3
|
||||
mov %edx, _C_LABEL(ptproc)
|
||||
/* get ptproc */
|
||||
mov 8(%esp), %eax
|
||||
mov %edx, (%eax)
|
||||
0:
|
||||
ret
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ PRIVATE phys_bytes createpde(
|
||||
pde = freepdes[free_pde_idx];
|
||||
assert(pde >= 0 && pde < 1024);
|
||||
|
||||
if(pr && ((pr == ptproc) || !HASPT(pr))) {
|
||||
if(pr && ((pr == get_cpulocal_var(ptproc)) || !HASPT(pr))) {
|
||||
/* Process memory is requested, and
|
||||
* it's a process that is already in current page table, or
|
||||
* a process that is in every page table.
|
||||
@@ -109,9 +109,9 @@ PRIVATE phys_bytes createpde(
|
||||
* can access, into the currently loaded page table so it becomes
|
||||
* visible.
|
||||
*/
|
||||
assert(ptproc->p_seg.p_cr3_v);
|
||||
if(ptproc->p_seg.p_cr3_v[pde] != pdeval) {
|
||||
ptproc->p_seg.p_cr3_v[pde] = pdeval;
|
||||
assert(get_cpulocal_var(ptproc)->p_seg.p_cr3_v);
|
||||
if(get_cpulocal_var(ptproc)->p_seg.p_cr3_v[pde] != pdeval) {
|
||||
get_cpulocal_var(ptproc)->p_seg.p_cr3_v[pde] = pdeval;
|
||||
*changed = 1;
|
||||
}
|
||||
|
||||
@@ -139,18 +139,18 @@ PRIVATE int lin_lin_copy(const struct proc *srcproc, vir_bytes srclinaddr,
|
||||
assert(vm_running);
|
||||
assert(nfreepdes >= 3);
|
||||
|
||||
assert(ptproc);
|
||||
assert(proc_ptr);
|
||||
assert(read_cr3() == ptproc->p_seg.p_cr3);
|
||||
assert(get_cpulocal_var(ptproc));
|
||||
assert(get_cpulocal_var(proc_ptr));
|
||||
assert(read_cr3() == get_cpulocal_var(ptproc)->p_seg.p_cr3);
|
||||
|
||||
procslot = ptproc->p_nr;
|
||||
procslot = get_cpulocal_var(ptproc)->p_nr;
|
||||
|
||||
assert(procslot >= 0 && procslot < I386_VM_DIR_ENTRIES);
|
||||
|
||||
if(srcproc) assert(!RTS_ISSET(srcproc, RTS_SLOT_FREE));
|
||||
if(dstproc) assert(!RTS_ISSET(dstproc, RTS_SLOT_FREE));
|
||||
assert(!RTS_ISSET(ptproc, RTS_SLOT_FREE));
|
||||
assert(ptproc->p_seg.p_cr3_v);
|
||||
assert(!RTS_ISSET(get_cpulocal_var(ptproc), RTS_SLOT_FREE));
|
||||
assert(get_cpulocal_var(ptproc)->p_seg.p_cr3_v);
|
||||
|
||||
while(bytes > 0) {
|
||||
phys_bytes srcptr, dstptr;
|
||||
@@ -190,8 +190,8 @@ PRIVATE int lin_lin_copy(const struct proc *srcproc, vir_bytes srclinaddr,
|
||||
|
||||
if(srcproc) assert(!RTS_ISSET(srcproc, RTS_SLOT_FREE));
|
||||
if(dstproc) assert(!RTS_ISSET(dstproc, RTS_SLOT_FREE));
|
||||
assert(!RTS_ISSET(ptproc, RTS_SLOT_FREE));
|
||||
assert(ptproc->p_seg.p_cr3_v);
|
||||
assert(!RTS_ISSET(get_cpulocal_var(ptproc), RTS_SLOT_FREE));
|
||||
assert(get_cpulocal_var(ptproc)->p_seg.p_cr3_v);
|
||||
|
||||
return OK;
|
||||
}
|
||||
@@ -682,7 +682,7 @@ int vm_phys_memset(phys_bytes ph, const u8_t c, phys_bytes bytes)
|
||||
|
||||
assert(nfreepdes >= 3);
|
||||
|
||||
assert(ptproc->p_seg.p_cr3_v);
|
||||
assert(get_cpulocal_var(ptproc)->p_seg.p_cr3_v);
|
||||
|
||||
/* With VM, we have to map in the physical memory.
|
||||
* We can do this 4MB at a time.
|
||||
@@ -702,7 +702,7 @@ int vm_phys_memset(phys_bytes ph, const u8_t c, phys_bytes bytes)
|
||||
ph += chunk;
|
||||
}
|
||||
|
||||
assert(ptproc->p_seg.p_cr3_v);
|
||||
assert(get_cpulocal_var(ptproc)->p_seg.p_cr3_v);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user