summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2003-05-19 04:16:30 +0000
committermarcel <marcel@FreeBSD.org>2003-05-19 04:16:30 +0000
commitcd7086c532d7fcc9f4b3277152396924b3dea95d (patch)
tree0570d3a0fa5ef89dbacda5db8279ceacd93bdeab /sys
parent487ef7f7cbd53c22f36b29ac35905579ef1b7ae9 (diff)
downloadFreeBSD-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.c9
-rw-r--r--sys/ia64/ia64/pmap.c65
-rw-r--r--sys/ia64/include/pmap.h2
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 */
OpenPOWER on IntegriCloud