pmap_install() needs to be atomic WRT to context switching. Protect

switching user regions (region 0-4) with schedlock. Avoid unnecessary
recursion on schedlock by moving the core functionality to another
function (pmap_switch()) where we assert schedlock is held. Turn
pmap_install() into a wrapper that grabs schedlock. This minimizes
the number of callsites that need to be changed.
Since we already have schedlock in cpu_switch() and cpu_throw(),
have them call pmap_switch() directly. These were also the only two
calls to pmap_install() outside pmap.c, so make pmap_install() static
and remove its prototype from pmap.h

Approved by: re (blanket)
This commit is contained in:
Marcel Moolenaar 2003-05-19 04:16:30 +00:00
parent 4555a3de62
commit dc0bde0f18
3 changed files with 38 additions and 36 deletions

View file

@ -217,18 +217,21 @@ cpu_switch(struct thread *old, struct thread *new)
struct pcb *oldpcb, *newpcb;
oldpcb = old->td_pcb;
oldpcb->pcb_current_pmap = PCPU_GET(current_pmap);
#if IA32
ia32_savectx(oldpcb);
#endif
if (!savectx(oldpcb)) {
newpcb = new->td_pcb;
pmap_install(newpcb->pcb_current_pmap);
oldpcb->pcb_current_pmap =
pmap_switch(newpcb->pcb_current_pmap);
PCPU_SET(curthread, new);
#if IA32
ia32_restorectx(newpcb);
#endif
restorectx(newpcb);
/* We should not get here. */
panic("cpu_switch: restorectx() returned");
/* NOTREACHED */
}
}
@ -238,7 +241,7 @@ cpu_throw(struct thread *old __unused, struct thread *new)
struct pcb *newpcb;
newpcb = new->td_pcb;
pmap_install(newpcb->pcb_current_pmap);
(void)pmap_switch(newpcb->pcb_current_pmap);
PCPU_SET(curthread, new);
#if IA32
ia32_restorectx(newpcb);

View file

@ -264,6 +264,7 @@ static PMAP_INLINE void free_pv_entry(pv_entry_t pv);
static pv_entry_t get_pv_entry(void);
static void ia64_protection_init(void);
static pmap_t pmap_install(pmap_t);
static void pmap_invalidate_all(pmap_t pmap);
static void pmap_enter_quick(pmap_t pmap, vm_offset_t va, vm_page_t m);
@ -2534,45 +2535,43 @@ pmap_activate(struct thread *td)
}
pmap_t
pmap_install(pmap_t pmap)
pmap_switch(pmap_t pm)
{
pmap_t oldpmap;
pmap_t prevpm;
int i;
critical_enter();
mtx_assert(&sched_lock, MA_OWNED);
oldpmap = PCPU_GET(current_pmap);
if (oldpmap == pmap) {
critical_exit();
return (oldpmap);
prevpm = PCPU_GET(current_pmap);
if (prevpm == pm)
return (prevpm);
if (prevpm != NULL)
atomic_clear_32(&prevpm->pm_active, PCPU_GET(cpumask));
if (pm == NULL) {
for (i = 0; i < 5; i++) {
ia64_set_rr(IA64_RR_BASE(i),
(i << 8)|(PAGE_SHIFT << 2)|1);
}
} else {
for (i = 0; i < 5; i++) {
ia64_set_rr(IA64_RR_BASE(i),
(pm->pm_rid[i] << 8)|(PAGE_SHIFT << 2)|1);
}
atomic_set_32(&pm->pm_active, PCPU_GET(cpumask));
PCPU_SET(current_pmap, pm);
}
return (prevpm);
}
if (oldpmap != NULL)
atomic_clear_32(&oldpmap->pm_active, PCPU_GET(cpumask));
static pmap_t
pmap_install(pmap_t pm)
{
pmap_t prevpm;
PCPU_SET(current_pmap, pmap);
if (pmap == NULL) {
/* Invalidate regions 0-4. */
ia64_set_rr(IA64_RR_BASE(0), (0 << 8)|(PAGE_SHIFT << 2)|1);
ia64_set_rr(IA64_RR_BASE(1), (1 << 8)|(PAGE_SHIFT << 2)|1);
ia64_set_rr(IA64_RR_BASE(2), (2 << 8)|(PAGE_SHIFT << 2)|1);
ia64_set_rr(IA64_RR_BASE(3), (3 << 8)|(PAGE_SHIFT << 2)|1);
ia64_set_rr(IA64_RR_BASE(4), (4 << 8)|(PAGE_SHIFT << 2)|1);
critical_exit();
return (oldpmap);
}
atomic_set_32(&pmap->pm_active, PCPU_GET(cpumask));
for (i = 0; i < 5; i++) {
ia64_set_rr(IA64_RR_BASE(i),
(pmap->pm_rid[i] << 8)|(PAGE_SHIFT << 2)|1);
}
critical_exit();
return (oldpmap);
mtx_lock_spin(&sched_lock);
prevpm = pmap_switch(pm);
mtx_unlock_spin(&sched_lock);
return (prevpm);
}
vm_offset_t

View file

@ -128,7 +128,7 @@ void pmap_unmapdev(vm_offset_t, vm_size_t);
unsigned *pmap_pte(pmap_t, vm_offset_t) __pure2;
void pmap_set_opt (unsigned *);
void pmap_set_opt_bsp (void);
struct pmap *pmap_install(struct pmap *pmap);
struct pmap *pmap_switch(struct pmap *pmap);
#endif /* _KERNEL */