linux_machdep.c (332315) | linux_machdep.c (346812) |
---|---|
1/*- 2 * Copyright (c) 2000 Marcel Moolenaar 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 13 unchanged lines hidden (view full) --- 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2000 Marcel Moolenaar 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 13 unchanged lines hidden (view full) --- 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h> |
30__FBSDID("$FreeBSD: stable/11/sys/i386/linux/linux_machdep.c 332315 2018-04-09 01:07:47Z emaste $"); | 30__FBSDID("$FreeBSD: stable/11/sys/i386/linux/linux_machdep.c 346812 2019-04-28 09:53:08Z dchagin $"); |
31 32#include <sys/param.h> 33#include <sys/capsicum.h> 34#include <sys/fcntl.h> 35#include <sys/file.h> 36#include <sys/imgact.h> 37#include <sys/lock.h> 38#include <sys/malloc.h> --- 236 unchanged lines hidden (view full) --- 275 int a[2]; 276 277 error = copyin(desc, &info, sizeof(struct l_user_desc)); 278 if (error) { 279 printf(LMSG("copyin failed!")); 280 } else { 281 idx = info.entry_number; 282 | 31 32#include <sys/param.h> 33#include <sys/capsicum.h> 34#include <sys/fcntl.h> 35#include <sys/file.h> 36#include <sys/imgact.h> 37#include <sys/lock.h> 38#include <sys/malloc.h> --- 236 unchanged lines hidden (view full) --- 275 int a[2]; 276 277 error = copyin(desc, &info, sizeof(struct l_user_desc)); 278 if (error) { 279 printf(LMSG("copyin failed!")); 280 } else { 281 idx = info.entry_number; 282 |
283 /* | 283 /* |
284 * looks like we're getting the idx we returned 285 * in the set_thread_area() syscall 286 */ 287 if (idx != 6 && idx != 3) { 288 printf(LMSG("resetting idx!")); 289 idx = 3; 290 } 291 292 /* this doesnt happen in practice */ 293 if (idx == 6) { | 284 * looks like we're getting the idx we returned 285 * in the set_thread_area() syscall 286 */ 287 if (idx != 6 && idx != 3) { 288 printf(LMSG("resetting idx!")); 289 idx = 3; 290 } 291 292 /* this doesnt happen in practice */ 293 if (idx == 6) { |
294 /* we might copy out the entry_number as 3 */ 295 info.entry_number = 3; | 294 /* we might copy out the entry_number as 3 */ 295 info.entry_number = 3; |
296 error = copyout(&info, desc, sizeof(struct l_user_desc)); 297 if (error) 298 printf(LMSG("copyout failed!")); 299 } 300 301 a[0] = LINUX_LDT_entry_a(&info); 302 a[1] = LINUX_LDT_entry_b(&info); 303 --- 327 unchanged lines hidden (view full) --- 631 struct segment_descriptor sd; 632 633 error = copyin(args->desc, &info, sizeof(struct l_user_desc)); 634 if (error) 635 return (error); 636 637#ifdef DEBUG 638 if (ldebug(set_thread_area)) | 296 error = copyout(&info, desc, sizeof(struct l_user_desc)); 297 if (error) 298 printf(LMSG("copyout failed!")); 299 } 300 301 a[0] = LINUX_LDT_entry_a(&info); 302 a[1] = LINUX_LDT_entry_b(&info); 303 --- 327 unchanged lines hidden (view full) --- 631 struct segment_descriptor sd; 632 633 error = copyin(args->desc, &info, sizeof(struct l_user_desc)); 634 if (error) 635 return (error); 636 637#ifdef DEBUG 638 if (ldebug(set_thread_area)) |
639 printf(ARGS(set_thread_area, "%i, %x, %x, %i, %i, %i, %i, %i, %i\n"), | 639 printf(ARGS(set_thread_area, "%i, %x, %x, %i, %i, %i, %i, %i, %i\n"), |
640 info.entry_number, | 640 info.entry_number, |
641 info.base_addr, 642 info.limit, 643 info.seg_32bit, | 641 info.base_addr, 642 info.limit, 643 info.seg_32bit, |
644 info.contents, | 644 info.contents, |
645 info.read_exec_only, 646 info.limit_in_pages, 647 info.seg_not_present, 648 info.useable); | 645 info.read_exec_only, 646 info.limit_in_pages, 647 info.seg_not_present, 648 info.useable); |
649#endif 650 651 idx = info.entry_number; | 649#endif 650 651 idx = info.entry_number; |
652 /* | 652 /* |
653 * Semantics of linux version: every thread in the system has array of | 653 * Semantics of linux version: every thread in the system has array of |
654 * 3 tls descriptors. 1st is GLIBC TLS, 2nd is WINE, 3rd unknown. This | 654 * 3 tls descriptors. 1st is GLIBC TLS, 2nd is WINE, 3rd unknown. This |
655 * syscall loads one of the selected tls decriptors with a value and 656 * also loads GDT descriptors 6, 7 and 8 with the content of the 657 * per-thread descriptors. 658 * | 655 * syscall loads one of the selected tls decriptors with a value and 656 * also loads GDT descriptors 6, 7 and 8 with the content of the 657 * per-thread descriptors. 658 * |
659 * Semantics of fbsd version: I think we can ignore that linux has 3 | 659 * Semantics of fbsd version: I think we can ignore that linux has 3 |
660 * per-thread descriptors and use just the 1st one. The tls_array[] 661 * is used only in set/get-thread_area() syscalls and for loading the 662 * GDT descriptors. In fbsd we use just one GDT descriptor for TLS so | 660 * per-thread descriptors and use just the 1st one. The tls_array[] 661 * is used only in set/get-thread_area() syscalls and for loading the 662 * GDT descriptors. In fbsd we use just one GDT descriptor for TLS so |
663 * we will load just one. | 663 * we will load just one. |
664 * 665 * XXX: this doesn't work when a user space process tries to use more 666 * than 1 TLS segment. Comment in the linux sources says wine might do 667 * this. 668 */ 669 | 664 * 665 * XXX: this doesn't work when a user space process tries to use more 666 * than 1 TLS segment. Comment in the linux sources says wine might do 667 * this. 668 */ 669 |
670 /* 671 * we support just GLIBC TLS now | 670 /* 671 * we support just GLIBC TLS now |
672 * we should let 3 proceed as well because we use this segment so 673 * if code does two subsequent calls it should succeed 674 */ 675 if (idx != 6 && idx != -1 && idx != 3) 676 return (EINVAL); 677 | 672 * we should let 3 proceed as well because we use this segment so 673 * if code does two subsequent calls it should succeed 674 */ 675 if (idx != 6 && idx != -1 && idx != 3) 676 return (EINVAL); 677 |
678 /* | 678 /* |
679 * we have to copy out the GDT entry we use 680 * FreeBSD uses GDT entry #3 for storing %gs so load that 681 * 682 * XXX: what if a user space program doesn't check this value and tries | 679 * we have to copy out the GDT entry we use 680 * FreeBSD uses GDT entry #3 for storing %gs so load that 681 * 682 * XXX: what if a user space program doesn't check this value and tries |
683 * to use 6, 7 or 8? | 683 * to use 6, 7 or 8? |
684 */ 685 idx = info.entry_number = 3; 686 error = copyout(&info, args->desc, sizeof(struct l_user_desc)); 687 if (error) 688 return (error); 689 690 if (LINUX_LDT_empty(&info)) { 691 a[0] = 0; 692 a[1] = 0; 693 } else { 694 a[0] = LINUX_LDT_entry_a(&info); 695 a[1] = LINUX_LDT_entry_b(&info); 696 } 697 698 memcpy(&sd, &a, sizeof(a)); 699#ifdef DEBUG 700 if (ldebug(set_thread_area)) | 684 */ 685 idx = info.entry_number = 3; 686 error = copyout(&info, args->desc, sizeof(struct l_user_desc)); 687 if (error) 688 return (error); 689 690 if (LINUX_LDT_empty(&info)) { 691 a[0] = 0; 692 a[1] = 0; 693 } else { 694 a[0] = LINUX_LDT_entry_a(&info); 695 a[1] = LINUX_LDT_entry_b(&info); 696 } 697 698 memcpy(&sd, &a, sizeof(a)); 699#ifdef DEBUG 700 if (ldebug(set_thread_area)) |
701 printf("Segment created in set_thread_area: lobase: %x, hibase: %x, lolimit: %x, hilimit: %x, type: %i, dpl: %i, p: %i, xx: %i, def32: %i, gran: %i\n", sd.sd_lobase, | 701 printf("Segment created in set_thread_area: lobase: %x, hibase: %x, lolimit: %x, hilimit: %x, type: %i, dpl: %i, p: %i, xx: %i, def32: %i, gran: %i\n", sd.sd_lobase, |
702 sd.sd_hibase, 703 sd.sd_lolimit, 704 sd.sd_hilimit, 705 sd.sd_type, 706 sd.sd_dpl, 707 sd.sd_p, 708 sd.sd_xx, 709 sd.sd_def32, 710 sd.sd_gran); 711#endif 712 713 /* this is taken from i386 version of cpu_set_user_tls() */ 714 critical_enter(); 715 /* set %gs */ 716 td->td_pcb->pcb_gsd = sd; 717 PCPU_GET(fsgs_gdt)[1] = sd; 718 load_gs(GSEL(GUGS_SEL, SEL_UPL)); 719 critical_exit(); | 702 sd.sd_hibase, 703 sd.sd_lolimit, 704 sd.sd_hilimit, 705 sd.sd_type, 706 sd.sd_dpl, 707 sd.sd_p, 708 sd.sd_xx, 709 sd.sd_def32, 710 sd.sd_gran); 711#endif 712 713 /* this is taken from i386 version of cpu_set_user_tls() */ 714 critical_enter(); 715 /* set %gs */ 716 td->td_pcb->pcb_gsd = sd; 717 PCPU_GET(fsgs_gdt)[1] = sd; 718 load_gs(GSEL(GUGS_SEL, SEL_UPL)); 719 critical_exit(); |
720 | 720 |
721 return (0); 722} 723 724int 725linux_get_thread_area(struct thread *td, struct linux_get_thread_area_args *args) 726{ | 721 return (0); 722} 723 724int 725linux_get_thread_area(struct thread *td, struct linux_get_thread_area_args *args) 726{ |
727 | 727 |
728 struct l_user_desc info; 729 int error; 730 int idx; 731 struct l_desc_struct desc; 732 struct segment_descriptor sd; 733 734#ifdef DEBUG 735 if (ldebug(get_thread_area)) --- 24 unchanged lines hidden (view full) --- 760 info.contents = LINUX_GET_CONTENTS(&desc); 761 info.read_exec_only = !LINUX_GET_WRITABLE(&desc); 762 info.limit_in_pages = LINUX_GET_LIMIT_PAGES(&desc); 763 info.seg_not_present = !LINUX_GET_PRESENT(&desc); 764 info.useable = LINUX_GET_USEABLE(&desc); 765 766 error = copyout(&info, args->desc, sizeof(struct l_user_desc)); 767 if (error) | 728 struct l_user_desc info; 729 int error; 730 int idx; 731 struct l_desc_struct desc; 732 struct segment_descriptor sd; 733 734#ifdef DEBUG 735 if (ldebug(get_thread_area)) --- 24 unchanged lines hidden (view full) --- 760 info.contents = LINUX_GET_CONTENTS(&desc); 761 info.read_exec_only = !LINUX_GET_WRITABLE(&desc); 762 info.limit_in_pages = LINUX_GET_LIMIT_PAGES(&desc); 763 info.seg_not_present = !LINUX_GET_PRESENT(&desc); 764 info.useable = LINUX_GET_USEABLE(&desc); 765 766 error = copyout(&info, args->desc, sizeof(struct l_user_desc)); 767 if (error) |
768 return (EFAULT); | 768 return (EFAULT); |
769 770 return (0); 771} 772 773/* XXX: this wont work with module - convert it */ 774int 775linux_mq_open(struct thread *td, struct linux_mq_open_args *args) 776{ 777#ifdef P1003_1B_MQUEUE | 769 770 return (0); 771} 772 773/* XXX: this wont work with module - convert it */ 774int 775linux_mq_open(struct thread *td, struct linux_mq_open_args *args) 776{ 777#ifdef P1003_1B_MQUEUE |
778 return sys_kmq_open(td, (struct kmq_open_args *) args); | 778 return sys_kmq_open(td, (struct kmq_open_args *) args); |
779#else 780 return (ENOSYS); 781#endif 782} 783 784int 785linux_mq_unlink(struct thread *td, struct linux_mq_unlink_args *args) 786{ 787#ifdef P1003_1B_MQUEUE | 779#else 780 return (ENOSYS); 781#endif 782} 783 784int 785linux_mq_unlink(struct thread *td, struct linux_mq_unlink_args *args) 786{ 787#ifdef P1003_1B_MQUEUE |
788 return sys_kmq_unlink(td, (struct kmq_unlink_args *) args); | 788 return sys_kmq_unlink(td, (struct kmq_unlink_args *) args); |
789#else 790 return (ENOSYS); 791#endif 792} 793 794int 795linux_mq_timedsend(struct thread *td, struct linux_mq_timedsend_args *args) 796{ 797#ifdef P1003_1B_MQUEUE | 789#else 790 return (ENOSYS); 791#endif 792} 793 794int 795linux_mq_timedsend(struct thread *td, struct linux_mq_timedsend_args *args) 796{ 797#ifdef P1003_1B_MQUEUE |
798 return sys_kmq_timedsend(td, (struct kmq_timedsend_args *) args); | 798 return sys_kmq_timedsend(td, (struct kmq_timedsend_args *) args); |
799#else 800 return (ENOSYS); 801#endif 802} 803 804int 805linux_mq_timedreceive(struct thread *td, struct linux_mq_timedreceive_args *args) 806{ 807#ifdef P1003_1B_MQUEUE | 799#else 800 return (ENOSYS); 801#endif 802} 803 804int 805linux_mq_timedreceive(struct thread *td, struct linux_mq_timedreceive_args *args) 806{ 807#ifdef P1003_1B_MQUEUE |
808 return sys_kmq_timedreceive(td, (struct kmq_timedreceive_args *) args); | 808 return sys_kmq_timedreceive(td, (struct kmq_timedreceive_args *) args); |
809#else 810 return (ENOSYS); 811#endif 812} 813 814int 815linux_mq_notify(struct thread *td, struct linux_mq_notify_args *args) 816{ 817#ifdef P1003_1B_MQUEUE 818 return sys_kmq_notify(td, (struct kmq_notify_args *) args); 819#else 820 return (ENOSYS); 821#endif 822} 823 824int 825linux_mq_getsetattr(struct thread *td, struct linux_mq_getsetattr_args *args) 826{ 827#ifdef P1003_1B_MQUEUE | 809#else 810 return (ENOSYS); 811#endif 812} 813 814int 815linux_mq_notify(struct thread *td, struct linux_mq_notify_args *args) 816{ 817#ifdef P1003_1B_MQUEUE 818 return sys_kmq_notify(td, (struct kmq_notify_args *) args); 819#else 820 return (ENOSYS); 821#endif 822} 823 824int 825linux_mq_getsetattr(struct thread *td, struct linux_mq_getsetattr_args *args) 826{ 827#ifdef P1003_1B_MQUEUE |
828 return sys_kmq_setattr(td, (struct kmq_setattr_args *) args); | 828 return sys_kmq_setattr(td, (struct kmq_setattr_args *) args); |
829#else 830 return (ENOSYS); 831#endif 832} | 829#else 830 return (ENOSYS); 831#endif 832} |