diff options
author | Kip Macy <kmacy@FreeBSD.org> | 2008-08-15 20:51:31 +0000 |
---|---|---|
committer | Kip Macy <kmacy@FreeBSD.org> | 2008-08-15 20:51:31 +0000 |
commit | 93ee134a24fa25fde49b66da24f4262f37bf3249 (patch) | |
tree | 01c30bdd7553d9c3ff945b2422e697cffe0f9b20 /sys/i386/i386/sys_machdep.c | |
parent | 66f8d384cf1352e7269973271766595f12b2e2c1 (diff) | |
download | src-93ee134a24fa25fde49b66da24f4262f37bf3249.tar.gz src-93ee134a24fa25fde49b66da24f4262f37bf3249.zip |
Integrate support for xen in to i386 common code.
MFC after: 1 month
Notes
Notes:
svn path=/head/; revision=181775
Diffstat (limited to 'sys/i386/i386/sys_machdep.c')
-rw-r--r-- | sys/i386/i386/sys_machdep.c | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/sys/i386/i386/sys_machdep.c b/sys/i386/i386/sys_machdep.c index 97ebe3477be4..f792f2a5d2a6 100644 --- a/sys/i386/i386/sys_machdep.c +++ b/sys/i386/i386/sys_machdep.c @@ -58,6 +58,20 @@ __FBSDID("$FreeBSD$"); #include <security/audit/audit.h> +#ifdef XEN +#include <machine/xen/xenfunc.h> + +void i386_reset_ldt(struct proc_ldt *pldt); + +void +i386_reset_ldt(struct proc_ldt *pldt) +{ + xen_set_ldt((vm_offset_t)pldt->ldt_base, pldt->ldt_len); +} +#else +#define i386_reset_ldt(x) +#endif + #include <vm/vm_kern.h> /* for kernel_map */ #define MAX_LD 8192 @@ -164,7 +178,12 @@ sysarch(td, uap) */ sd.sd_lobase = base & 0xffffff; sd.sd_hibase = (base >> 24) & 0xff; +#ifdef XEN + /* need to do nosegneg like Linux */ + sd.sd_lolimit = (HYPERVISOR_VIRT_START >> 12) & 0xffff; +#else sd.sd_lolimit = 0xffff; /* 4GB limit, wraps around */ +#endif sd.sd_hilimit = 0xf; sd.sd_type = SDT_MEMRWA; sd.sd_dpl = SEL_UPL; @@ -174,7 +193,12 @@ sysarch(td, uap) sd.sd_gran = 1; critical_enter(); td->td_pcb->pcb_fsd = sd; +#ifdef XEN + HYPERVISOR_update_descriptor(vtomach(&PCPU_GET(fsgs_gdt)[0]), + *(uint64_t *)&sd); +#else PCPU_GET(fsgs_gdt)[0] = sd; +#endif critical_exit(); td->td_frame->tf_fs = GSEL(GUFS_SEL, SEL_UPL); } @@ -194,7 +218,13 @@ sysarch(td, uap) */ sd.sd_lobase = base & 0xffffff; sd.sd_hibase = (base >> 24) & 0xff; + +#ifdef XEN + /* need to do nosegneg like Linux */ + sd.sd_lolimit = (HYPERVISOR_VIRT_START >> 12) & 0xffff; +#else sd.sd_lolimit = 0xffff; /* 4GB limit, wraps around */ +#endif sd.sd_hilimit = 0xf; sd.sd_type = SDT_MEMRWA; sd.sd_dpl = SEL_UPL; @@ -204,7 +234,12 @@ sysarch(td, uap) sd.sd_gran = 1; critical_enter(); td->td_pcb->pcb_gsd = sd; +#ifdef XEN + HYPERVISOR_update_descriptor(vtomach(&PCPU_GET(fsgs_gdt)[1]), + *(uint64_t *)&sd); +#else PCPU_GET(fsgs_gdt)[1] = sd; +#endif critical_exit(); load_gs(GSEL(GUGS_SEL, SEL_UPL)); } @@ -360,6 +395,10 @@ set_user_ldt(struct mdproc *mdp) } pldt = mdp->md_ldt; +#ifdef XEN + i386_reset_ldt(pldt); + PCPU_SET(currentldt, (int)pldt); +#else #ifdef SMP gdt[PCPU_GET(cpuid) * NGDT + GUSERLDT_SEL].sd = pldt->ldt_sd; #else @@ -367,6 +406,7 @@ set_user_ldt(struct mdproc *mdp) #endif lldt(GSEL(GUSERLDT_SEL, SEL_KPL)); PCPU_SET(currentldt, GSEL(GUSERLDT_SEL, SEL_KPL)); +#endif /* XEN */ if (dtlocked) mtx_unlock_spin(&dt_lock); } @@ -385,6 +425,44 @@ set_user_ldt_rv(struct vmspace *vmsp) } #endif +#ifdef XEN + +/* + * dt_lock must be held. Returns with dt_lock held. + */ +struct proc_ldt * +user_ldt_alloc(struct mdproc *mdp, int len) +{ + struct proc_ldt *pldt, *new_ldt; + + mtx_assert(&dt_lock, MA_OWNED); + mtx_unlock_spin(&dt_lock); + MALLOC(new_ldt, struct proc_ldt *, sizeof(struct proc_ldt), + M_SUBPROC, M_WAITOK); + + new_ldt->ldt_len = len = NEW_MAX_LD(len); + new_ldt->ldt_base = (caddr_t)kmem_alloc(kernel_map, + round_page(len * sizeof(union descriptor))); + if (new_ldt->ldt_base == NULL) { + FREE(new_ldt, M_SUBPROC); + return NULL; + } + new_ldt->ldt_refcnt = 1; + new_ldt->ldt_active = 0; + + if ((pldt = mdp->md_ldt)) { + if (len > pldt->ldt_len) + len = pldt->ldt_len; + bcopy(pldt->ldt_base, new_ldt->ldt_base, + len * sizeof(union descriptor)); + } else { + bcopy(ldt, new_ldt->ldt_base, PAGE_SIZE); + } + pmap_map_readonly(kernel_pmap, (vm_offset_t)new_ldt->ldt_base, + new_ldt->ldt_len*sizeof(union descriptor)); + return new_ldt; +} +#else /* * dt_lock must be held. Returns with dt_lock held. */ @@ -423,6 +501,7 @@ user_ldt_alloc(struct mdproc *mdp, int len) return (new_ldt); } +#endif /* !XEN */ /* * Must be called with dt_lock held. Returns with dt_lock unheld. @@ -667,7 +746,23 @@ again: td->td_retval[0] = uap->start; return (error); } +#ifdef XEN +static int +i386_set_ldt_data(struct thread *td, int start, int num, + union descriptor *descs) +{ + struct mdproc *mdp = &td->td_proc->p_md; + struct proc_ldt *pldt = mdp->md_ldt; + mtx_assert(&dt_lock, MA_OWNED); + + /* Fill in range */ + bcopy(descs, + &((union descriptor *)(pldt->ldt_base))[start], + num * sizeof(union descriptor)); + return (0); +} +#else static int i386_set_ldt_data(struct thread *td, int start, int num, union descriptor *descs) @@ -683,6 +778,7 @@ i386_set_ldt_data(struct thread *td, int start, int num, num * sizeof(union descriptor)); return (0); } +#endif /* !XEN */ static int i386_ldt_grow(struct thread *td, int len) |