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:
Tomas Hruby
2010-09-15 14:09:46 +00:00
parent 2a2a19e542
commit 13a0d5fa5e
17 changed files with 208 additions and 102 deletions

View File

@@ -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 {

View File

@@ -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)

View File

@@ -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];

View File

@@ -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;

View File

@@ -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

View File

@@ -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;
}