Set md_ldt (pointer to the LDT) after md_ldt_sd (system segment

descriptor for the LDT) is populated. md_ldt is used by context-switch
code as indicator that LDT segment register shall be loaded with
GUSERLDT segment instead of 0, so context switch at the wrong time may
cause attempt to load non-populated descriptor.

Use store with the barrier to prevent other CPUs from seeing updated
md_ldt but not seeing updated md_ldt_sd. Multithreaded process may
context-switch to another thread of the process on another CPU and read
md_ldt.

MFC after:	1 week
This commit is contained in:
Konstantin Belousov 2010-01-09 11:28:01 +00:00
parent 5f9f9bd940
commit 293409233b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=201890

View File

@ -420,13 +420,14 @@ user_ldt_alloc(struct proc *p, int force)
return (pldt);
}
mdp->md_ldt = new_ldt;
if (pldt != NULL) {
bcopy(pldt->ldt_base, new_ldt->ldt_base, max_ldt_segment *
sizeof(struct user_segment_descriptor));
user_ldt_derefl(pldt);
}
ssdtosyssd(&sldt, &p->p_md.md_ldt_sd);
atomic_store_rel_ptr((volatile uintptr_t *)&mdp->md_ldt,
(uintptr_t)new_ldt);
if (p == curproc)
set_user_ldt(mdp);