Deleted Added
full compact
linux32_machdep.c (167157) linux32_machdep.c (168035)
1/*-
2 * Copyright (c) 2004 Tim J. Robbins
3 * Copyright (c) 2002 Doug Rabson
4 * Copyright (c) 2000 Marcel Moolenaar
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 15 unchanged lines hidden (view full) ---

24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2004 Tim J. Robbins
3 * Copyright (c) 2002 Doug Rabson
4 * Copyright (c) 2000 Marcel Moolenaar
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 15 unchanged lines hidden (view full) ---

24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: head/sys/amd64/linux32/linux32_machdep.c 167157 2007-03-02 00:08:47Z jkim $");
32__FBSDID("$FreeBSD: head/sys/amd64/linux32/linux32_machdep.c 168035 2007-03-30 00:06:21Z jkim $");
33
34#include <sys/param.h>
35#include <sys/kernel.h>
36#include <sys/systm.h>
37#include <sys/file.h>
38#include <sys/fcntl.h>
39#include <sys/clock.h>
40#include <sys/imgact.h>

--- 7 unchanged lines hidden (view full) ---

48#include <sys/resource.h>
49#include <sys/resourcevar.h>
50#include <sys/sched.h>
51#include <sys/syscallsubr.h>
52#include <sys/sysproto.h>
53#include <sys/unistd.h>
54
55#include <machine/frame.h>
33
34#include <sys/param.h>
35#include <sys/kernel.h>
36#include <sys/systm.h>
37#include <sys/file.h>
38#include <sys/fcntl.h>
39#include <sys/clock.h>
40#include <sys/imgact.h>

--- 7 unchanged lines hidden (view full) ---

48#include <sys/resource.h>
49#include <sys/resourcevar.h>
50#include <sys/sched.h>
51#include <sys/syscallsubr.h>
52#include <sys/sysproto.h>
53#include <sys/unistd.h>
54
55#include <machine/frame.h>
56#include <machine/pcb.h>
56#include <machine/psl.h>
57#include <machine/psl.h>
58#include <machine/segments.h>
59#include <machine/specialreg.h>
57
58#include <vm/vm.h>
59#include <vm/pmap.h>
60#include <vm/vm_extern.h>
61#include <vm/vm_kern.h>
62#include <vm/vm_map.h>
63
64#include <amd64/linux32/linux.h>

--- 586 unchanged lines hidden (view full) ---

651 /*
652 * in a case of stack = NULL we are supposed to COW calling process stack
653 * this is what normal fork() does so we just keep the tf_rsp arg intact
654 */
655 if (args->stack)
656 td2->td_frame->tf_rsp = PTROUT(args->stack);
657
658 if (args->flags & LINUX_CLONE_SETTLS) {
60
61#include <vm/vm.h>
62#include <vm/pmap.h>
63#include <vm/vm_extern.h>
64#include <vm/vm_kern.h>
65#include <vm/vm_map.h>
66
67#include <amd64/linux32/linux.h>

--- 586 unchanged lines hidden (view full) ---

654 /*
655 * in a case of stack = NULL we are supposed to COW calling process stack
656 * this is what normal fork() does so we just keep the tf_rsp arg intact
657 */
658 if (args->stack)
659 td2->td_frame->tf_rsp = PTROUT(args->stack);
660
661 if (args->flags & LINUX_CLONE_SETTLS) {
659 /* XXX: todo */
662 struct user_segment_descriptor sd;
663 struct l_user_desc info;
664 int a[2];
665
666 error = copyin((void *)td->td_frame->tf_rsi, &info,
667 sizeof(struct l_user_desc));
668 if (error) {
669 printf(LMSG("copyin failed!"));
670 } else {
671 /* We might copy out the entry_number as GUGS32_SEL. */
672 info.entry_number = GUGS32_SEL;
673 error = copyout(&info, (void *)td->td_frame->tf_rsi,
674 sizeof(struct l_user_desc));
675 if (error)
676 printf(LMSG("copyout failed!"));
677
678 a[0] = LINUX_LDT_entry_a(&info);
679 a[1] = LINUX_LDT_entry_b(&info);
680
681 memcpy(&sd, &a, sizeof(a));
682#ifdef DEBUG
683 if (ldebug(clone))
684 printf("Segment created in clone with "
685 "CLONE_SETTLS: lobase: %x, hibase: %x, "
686 "lolimit: %x, hilimit: %x, type: %i, "
687 "dpl: %i, p: %i, xx: %i, long: %i, "
688 "def32: %i, gran: %i\n", sd.sd_lobase,
689 sd.sd_hibase, sd.sd_lolimit, sd.sd_hilimit,
690 sd.sd_type, sd.sd_dpl, sd.sd_p, sd.sd_xx,
691 sd.sd_long, sd.sd_def32, sd.sd_gran);
692#endif
693 td2->td_pcb->pcb_gsbase = (register_t)info.base_addr;
694 td2->td_pcb->pcb_gs32sd = sd;
695 td2->td_pcb->pcb_gs32p = &gdt[GUGS32_SEL];
696 td2->td_pcb->pcb_gs = GSEL(GUGS32_SEL, SEL_UPL);
697 td2->td_pcb->pcb_flags |= PCB_32BIT;
698 }
660 }
661
662#ifdef DEBUG
663 if (ldebug(clone))
664 printf(LMSG("clone: successful rfork to %ld, stack %p sig = %d"),
665 (long)p2->p_pid, args->stack, exit_signal);
666#endif
667 if (args->flags & LINUX_CLONE_VFORK) {

--- 232 unchanged lines hidden (view full) ---

900 if (ldebug(mmap))
901 printf("-> %s() return: 0x%x (0x%08x)\n",
902 __func__, error, (u_int)td->td_retval[0]);
903#endif
904 return (error);
905}
906
907int
699 }
700
701#ifdef DEBUG
702 if (ldebug(clone))
703 printf(LMSG("clone: successful rfork to %ld, stack %p sig = %d"),
704 (long)p2->p_pid, args->stack, exit_signal);
705#endif
706 if (args->flags & LINUX_CLONE_VFORK) {

--- 232 unchanged lines hidden (view full) ---

939 if (ldebug(mmap))
940 printf("-> %s() return: 0x%x (0x%08x)\n",
941 __func__, error, (u_int)td->td_retval[0]);
942#endif
943 return (error);
944}
945
946int
947linux_mprotect(struct thread *td, struct linux_mprotect_args *uap)
948{
949 struct mprotect_args bsd_args;
950
951 bsd_args.addr = uap->addr;
952 bsd_args.len = uap->len;
953 bsd_args.prot = uap->prot;
954 if (bsd_args.prot & (PROT_READ | PROT_WRITE | PROT_EXEC))
955 bsd_args.prot |= PROT_READ | PROT_EXEC;
956 return (mprotect(td, &bsd_args));
957}
958
959int
908linux_iopl(struct thread *td, struct linux_iopl_args *args)
909{
910 int error;
911
912 if (args->level < 0 || args->level > 3)
913 return (EINVAL);
914 if ((error = priv_check(td, PRIV_IO)) != 0)
915 return (error);

--- 256 unchanged lines hidden (view full) ---

1172 if (error != 0)
1173 return (error);
1174 ts32.tv_sec = ts.tv_sec;
1175 ts32.tv_nsec = ts.tv_nsec;
1176 return (copyout(&ts32, uap->interval, sizeof(ts32)));
1177}
1178
1179int
960linux_iopl(struct thread *td, struct linux_iopl_args *args)
961{
962 int error;
963
964 if (args->level < 0 || args->level > 3)
965 return (EINVAL);
966 if ((error = priv_check(td, PRIV_IO)) != 0)
967 return (error);

--- 256 unchanged lines hidden (view full) ---

1224 if (error != 0)
1225 return (error);
1226 ts32.tv_sec = ts.tv_sec;
1227 ts32.tv_nsec = ts.tv_nsec;
1228 return (copyout(&ts32, uap->interval, sizeof(ts32)));
1229}
1230
1231int
1180linux_mprotect(struct thread *td, struct linux_mprotect_args *uap)
1232linux_set_thread_area(struct thread *td,
1233 struct linux_set_thread_area_args *args)
1181{
1234{
1182 struct mprotect_args bsd_args;
1235 struct l_user_desc info;
1236 struct user_segment_descriptor sd;
1237 int a[2];
1238 int error;
1183
1239
1184 bsd_args.addr = uap->addr;
1185 bsd_args.len = uap->len;
1186 bsd_args.prot = uap->prot;
1187 if (bsd_args.prot & (PROT_READ | PROT_WRITE | PROT_EXEC))
1188 bsd_args.prot |= PROT_READ | PROT_EXEC;
1189 return (mprotect(td, &bsd_args));
1240 error = copyin(args->desc, &info, sizeof(struct l_user_desc));
1241 if (error)
1242 return (error);
1243
1244#ifdef DEBUG
1245 if (ldebug(set_thread_area))
1246 printf(ARGS(set_thread_area, "%i, %x, %x, %i, %i, %i, "
1247 "%i, %i, %i"), info.entry_number, info.base_addr,
1248 info.limit, info.seg_32bit, info.contents,
1249 info.read_exec_only, info.limit_in_pages,
1250 info.seg_not_present, info.useable);
1251#endif
1252
1253 /*
1254 * Semantics of Linux version: every thread in the system has array
1255 * of three TLS descriptors. 1st is GLIBC TLS, 2nd is WINE, 3rd unknown.
1256 * This syscall loads one of the selected TLS decriptors with a value
1257 * and also loads GDT descriptors 6, 7 and 8 with the content of
1258 * the per-thread descriptors.
1259 *
1260 * Semantics of FreeBSD version: I think we can ignore that Linux has
1261 * three per-thread descriptors and use just the first one.
1262 * The tls_array[] is used only in [gs]et_thread_area() syscalls and
1263 * for loading the GDT descriptors. We use just one GDT descriptor
1264 * for TLS, so we will load just one.
1265 * XXX: This doesnt work when user-space process tries to use more
1266 * than one TLS segment. Comment in the Linux source says wine might
1267 * do that.
1268 */
1269
1270 /*
1271 * GLIBC reads current %gs and call set_thread_area() with it.
1272 * We should let GUDATA_SEL and GUGS32_SEL proceed as well because
1273 * we use these segments.
1274 */
1275 switch (info.entry_number) {
1276 case GUGS32_SEL:
1277 case GUDATA_SEL:
1278 case 6:
1279 case -1:
1280 info.entry_number = GUGS32_SEL;
1281 break;
1282 default:
1283 return (EINVAL);
1284 }
1285
1286 /*
1287 * We have to copy out the GDT entry we use.
1288 * XXX: What if userspace program does not check return value and
1289 * tries to use 6, 7 or 8?
1290 */
1291 error = copyout(&info, args->desc, sizeof(struct l_user_desc));
1292 if (error)
1293 return (error);
1294
1295 if (LINUX_LDT_empty(&info)) {
1296 a[0] = 0;
1297 a[1] = 0;
1298 } else {
1299 a[0] = LINUX_LDT_entry_a(&info);
1300 a[1] = LINUX_LDT_entry_b(&info);
1301 }
1302
1303 memcpy(&sd, &a, sizeof(a));
1304#ifdef DEBUG
1305 if (ldebug(set_thread_area))
1306 printf("Segment created in set_thread_area: "
1307 "lobase: %x, hibase: %x, lolimit: %x, hilimit: %x, "
1308 "type: %i, dpl: %i, p: %i, xx: %i, long: %i, "
1309 "def32: %i, gran: %i\n",
1310 sd.sd_lobase,
1311 sd.sd_hibase,
1312 sd.sd_lolimit,
1313 sd.sd_hilimit,
1314 sd.sd_type,
1315 sd.sd_dpl,
1316 sd.sd_p,
1317 sd.sd_xx,
1318 sd.sd_long,
1319 sd.sd_def32,
1320 sd.sd_gran);
1321#endif
1322
1323 critical_enter();
1324 td->td_pcb->pcb_gsbase = (register_t)info.base_addr;
1325 td->td_pcb->pcb_gs32sd = gdt[GUGS32_SEL] = sd;
1326 td->td_pcb->pcb_gs32p = &gdt[GUGS32_SEL];
1327 td->td_pcb->pcb_flags |= PCB_32BIT;
1328 wrmsr(MSR_KGSBASE, td->td_pcb->pcb_gsbase);
1329 critical_exit();
1330
1331 return (0);
1190}
1332}