diff options
author | kib <kib@FreeBSD.org> | 2014-12-27 23:19:08 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2014-12-27 23:19:08 +0000 |
commit | d0d6e7c817bec5a1c5f2c25cd4762b908bed2ffc (patch) | |
tree | 1132f4d5e9ee4767f431ad299e1c5015a8fd6833 /sys/amd64/ia32/ia32_syscall.c | |
parent | 509ff4169be0d36eecfc6a58cf0cb6b8a18b86e5 (diff) | |
download | FreeBSD-src-d0d6e7c817bec5a1c5f2c25cd4762b908bed2ffc.zip FreeBSD-src-d0d6e7c817bec5a1c5f2c25cd4762b908bed2ffc.tar.gz |
Change the way the lcall $7,$0 is reflected to usermode. Instead of
setting call gate, which must be 64 bit, put a code segment descriptor
into ldt slot 0.
This way, syscall shim does not switch temporary to 64bit trampoline,
and does not create a window where signal delivery interrupts 64 bit
mode (signal handler cannot return). The cost is shim running with
non-zero based segment in %cs, which requires vfork() handling make
more assumptions.
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Diffstat (limited to 'sys/amd64/ia32/ia32_syscall.c')
-rw-r--r-- | sys/amd64/ia32/ia32_syscall.c | 39 |
1 files changed, 14 insertions, 25 deletions
diff --git a/sys/amd64/ia32/ia32_syscall.c b/sys/amd64/ia32/ia32_syscall.c index 92249f9..6e96edd 100644 --- a/sys/amd64/ia32/ia32_syscall.c +++ b/sys/amd64/ia32/ia32_syscall.c @@ -223,39 +223,28 @@ int setup_lcall_gate(void) { struct i386_ldt_args uap; - struct user_segment_descriptor descs[2]; - struct gate_descriptor *ssd; + struct user_segment_descriptor desc; uint32_t lcall_addr; int error; bzero(&uap, sizeof(uap)); uap.start = 0; - uap.num = 2; - - /* - * This is the easiest way to cut the space for system - * descriptor in ldt. Manually adjust the descriptor type to - * the call gate later. - */ - bzero(&descs[0], sizeof(descs)); - descs[0].sd_type = SDT_SYSNULL; - descs[1].sd_type = SDT_SYSNULL; - error = amd64_set_ldt(curthread, &uap, descs); + uap.num = 1; + lcall_addr = curproc->p_sysent->sv_psstrings - sz_lcall_tramp; + bzero(&desc, sizeof(desc)); + desc.sd_type = SDT_MEMERA; + desc.sd_dpl = SEL_UPL; + desc.sd_p = 1; + desc.sd_def32 = 1; + desc.sd_gran = 1; + desc.sd_lolimit = 0xffff; + desc.sd_hilimit = 0xf; + desc.sd_lobase = lcall_addr; + desc.sd_hibase = lcall_addr >> 24; + error = amd64_set_ldt(curthread, &uap, &desc); if (error != 0) return (error); - lcall_addr = curproc->p_sysent->sv_psstrings - sz_lcall_tramp; - mtx_lock(&dt_lock); - ssd = (struct gate_descriptor *)(curproc->p_md.md_ldt->ldt_base); - bzero(ssd, sizeof(*ssd)); - ssd->gd_looffset = lcall_addr; - ssd->gd_hioffset = lcall_addr >> 16; - ssd->gd_selector = _ucodesel; - ssd->gd_type = SDT_SYSCGT; - ssd->gd_dpl = SEL_UPL; - ssd->gd_p = 1; - mtx_unlock(&dt_lock); - return (0); } #endif |