diff options
author | marcel <marcel@FreeBSD.org> | 2003-05-19 04:16:30 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2003-05-19 04:16:30 +0000 |
commit | cd7086c532d7fcc9f4b3277152396924b3dea95d (patch) | |
tree | 0570d3a0fa5ef89dbacda5db8279ceacd93bdeab /sys | |
parent | 487ef7f7cbd53c22f36b29ac35905579ef1b7ae9 (diff) | |
download | FreeBSD-src-cd7086c532d7fcc9f4b3277152396924b3dea95d.zip FreeBSD-src-cd7086c532d7fcc9f4b3277152396924b3dea95d.tar.gz |
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)
Diffstat (limited to 'sys')
-rw-r--r-- | sys/ia64/ia64/machdep.c | 9 | ||||
-rw-r--r-- | sys/ia64/ia64/pmap.c | 65 | ||||
-rw-r--r-- | sys/ia64/include/pmap.h | 2 |
3 files changed, 39 insertions, 37 deletions
diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c index 18d2083..fab204a 100644 --- a/sys/ia64/ia64/machdep.c +++ b/sys/ia64/ia64/machdep.c @@ -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); diff --git a/sys/ia64/ia64/pmap.c b/sys/ia64/ia64/pmap.c index 998d49f..94003f3 100644 --- a/sys/ia64/ia64/pmap.c +++ b/sys/ia64/ia64/pmap.c @@ -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(); - - oldpmap = PCPU_GET(current_pmap); - if (oldpmap == pmap) { - critical_exit(); - return (oldpmap); - } - - if (oldpmap != NULL) - atomic_clear_32(&oldpmap->pm_active, PCPU_GET(cpumask)); - - 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); + mtx_assert(&sched_lock, MA_OWNED); + + 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); +} - critical_exit(); +static pmap_t +pmap_install(pmap_t pm) +{ + pmap_t prevpm; - return (oldpmap); + mtx_lock_spin(&sched_lock); + prevpm = pmap_switch(pm); + mtx_unlock_spin(&sched_lock); + return (prevpm); } vm_offset_t diff --git a/sys/ia64/include/pmap.h b/sys/ia64/include/pmap.h index 4ee712d..d14e4b8 100644 --- a/sys/ia64/include/pmap.h +++ b/sys/ia64/include/pmap.h @@ -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 */ |