aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Percival <cperciva@FreeBSD.org>2011-01-06 22:57:06 +0000
committerColin Percival <cperciva@FreeBSD.org>2011-01-06 22:57:06 +0000
commit734510f3bca4f1b5ea1ab71e6ea61128ae30939c (patch)
tree50b5a208d279829b837e21d61e4feb37cca16b42
parent002fe711ccbf70dbc21e9ecfd417defb89cd99a8 (diff)
downloadsrc-734510f3bca4f1b5ea1ab71e6ea61128ae30939c.tar.gz
src-734510f3bca4f1b5ea1ab71e6ea61128ae30939c.zip
MFS r217056: Make i386_set_ldt work (rather than panic) on i386/XEN.
Approved by: re (rwatson)
Notes
Notes: svn path=/releng/8.2/; revision=217084
-rw-r--r--sys/i386/i386/sys_machdep.c20
-rw-r--r--sys/i386/include/pmap.h1
-rw-r--r--sys/i386/include/segments.h1
-rw-r--r--sys/i386/xen/pmap.c4
4 files changed, 21 insertions, 5 deletions
diff --git a/sys/i386/i386/sys_machdep.c b/sys/i386/i386/sys_machdep.c
index 2e7abdde25a8..3fb231b7866c 100644
--- a/sys/i386/i386/sys_machdep.c
+++ b/sys/i386/i386/sys_machdep.c
@@ -450,6 +450,7 @@ user_ldt_alloc(struct mdproc *mdp, int len)
new_ldt->ldt_refcnt = 1;
new_ldt->ldt_active = 0;
+ mtx_lock_spin(&dt_lock);
if ((pldt = mdp->md_ldt)) {
if (len > pldt->ldt_len)
len = pldt->ldt_len;
@@ -458,8 +459,10 @@ user_ldt_alloc(struct mdproc *mdp, int len)
} else {
bcopy(ldt, new_ldt->ldt_base, PAGE_SIZE);
}
+ mtx_unlock_spin(&dt_lock); /* XXX kill once pmap locking fixed. */
pmap_map_readonly(kernel_pmap, (vm_offset_t)new_ldt->ldt_base,
new_ldt->ldt_len*sizeof(union descriptor));
+ mtx_lock_spin(&dt_lock); /* XXX kill once pmap locking fixed. */
return (new_ldt);
}
#else
@@ -520,8 +523,13 @@ user_ldt_free(struct thread *td)
}
if (td == PCPU_GET(curthread)) {
+#ifdef XEN
+ i386_reset_ldt(&default_proc_ldt);
+ PCPU_SET(currentldt, (int)&default_proc_ldt);
+#else
lldt(_default_ldt);
PCPU_SET(currentldt, _default_ldt);
+#endif
}
mdp->md_ldt = NULL;
@@ -758,10 +766,14 @@ i386_set_ldt_data(struct thread *td, int start, int num,
mtx_assert(&dt_lock, MA_OWNED);
- /* Fill in range */
- bcopy(descs,
- &((union descriptor *)(pldt->ldt_base))[start],
- num * sizeof(union descriptor));
+ while (num) {
+ xen_update_descriptor(
+ &((union descriptor *)(pldt->ldt_base))[start],
+ descs);
+ num--;
+ start++;
+ descs++;
+ }
return (0);
}
#else
diff --git a/sys/i386/include/pmap.h b/sys/i386/include/pmap.h
index 3d44d220f03e..7a45aab75f7a 100644
--- a/sys/i386/include/pmap.h
+++ b/sys/i386/include/pmap.h
@@ -251,7 +251,6 @@ pte_load_store(pt_entry_t *ptep, pt_entry_t v)
{
pt_entry_t r;
- v = xpmap_ptom(v);
r = *ptep;
PT_SET_VA(ptep, v, TRUE);
return (r);
diff --git a/sys/i386/include/segments.h b/sys/i386/include/segments.h
index 2edcc59073b4..bfc3bb9c82c7 100644
--- a/sys/i386/include/segments.h
+++ b/sys/i386/include/segments.h
@@ -249,6 +249,7 @@ struct region_descriptor {
#ifdef _KERNEL
extern int _default_ldt;
#ifdef XEN
+extern struct proc_ldt default_proc_ldt;
extern union descriptor *gdt;
extern union descriptor *ldt;
#else
diff --git a/sys/i386/xen/pmap.c b/sys/i386/xen/pmap.c
index 0d2450e234e8..ab4fe054b715 100644
--- a/sys/i386/xen/pmap.c
+++ b/sys/i386/xen/pmap.c
@@ -3710,7 +3710,9 @@ pmap_map_readonly(pmap_t pmap, vm_offset_t va, int len)
for (i = 0; i < npages; i++) {
pt_entry_t *pte;
pte = pmap_pte(pmap, (vm_offset_t)(va + i*PAGE_SIZE));
+ vm_page_lock_queues();
pte_store(pte, xpmap_mtop(*pte & ~(PG_RW|PG_M)));
+ vm_page_unlock_queues();
PMAP_MARK_PRIV(xpmap_mtop(*pte));
pmap_pte_release(pte);
}
@@ -3724,7 +3726,9 @@ pmap_map_readwrite(pmap_t pmap, vm_offset_t va, int len)
pt_entry_t *pte;
pte = pmap_pte(pmap, (vm_offset_t)(va + i*PAGE_SIZE));
PMAP_MARK_UNPRIV(xpmap_mtop(*pte));
+ vm_page_lock_queues();
pte_store(pte, xpmap_mtop(*pte) | (PG_RW|PG_M));
+ vm_page_unlock_queues();
pmap_pte_release(pte);
}
}