1 | /* Machine dependent pthreads code. Hurd/i386 version. |
2 | Copyright (C) 2000-2024 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. |
4 | |
5 | The GNU C Library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2.1 of the License, or (at your option) any later version. |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Lesser General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, see |
17 | <https://www.gnu.org/licenses/>. */ |
18 | |
19 | #include <errno.h> |
20 | |
21 | #include <mach.h> |
22 | #include <mach/machine/thread_status.h> |
23 | #include <mach/i386/mach_i386.h> |
24 | #include <mach/mig_errors.h> |
25 | #include <mach/thread_status.h> |
26 | |
27 | #define HURD_TLS_DESC_DECL(desc, tcb) \ |
28 | struct descriptor desc = \ |
29 | { /* low word: */ \ |
30 | 0xffff /* limit 0..15 */ \ |
31 | | (((unsigned int) (tcb)) << 16) /* base 0..15 */ \ |
32 | , /* high word: */ \ |
33 | ((((unsigned int) (tcb)) >> 16) & 0xff) /* base 16..23 */ \ |
34 | | ((0x12 | 0x60 | 0x80) << 8) /* access = ACC_DATA_W|ACC_PL_U|ACC_P */ \ |
35 | | (0xf << 16) /* limit 16..19 */ \ |
36 | | ((4 | 8) << 20) /* granularity = SZ_32|SZ_G */ \ |
37 | | (((unsigned int) (tcb)) & 0xff000000) /* base 24..31 */ \ |
38 | } |
39 | |
40 | int |
41 | __thread_set_pcsptp (thread_t thread, |
42 | int set_ip, void *ip, |
43 | int set_sp, void *sp, |
44 | int set_tp, void *tp) |
45 | { |
46 | error_t err; |
47 | struct i386_thread_state state; |
48 | mach_msg_type_number_t state_count; |
49 | |
50 | state_count = i386_THREAD_STATE_COUNT; |
51 | |
52 | err = __thread_get_state (thread, i386_REGS_SEGS_STATE, |
53 | (thread_state_t) &state, &state_count); |
54 | if (err) |
55 | return err; |
56 | |
57 | if (set_sp) |
58 | state.uesp = (unsigned int) sp; |
59 | if (set_ip) |
60 | state.eip = (unsigned int) ip; |
61 | if (set_tp) |
62 | { |
63 | HURD_TLS_DESC_DECL (desc, tp); |
64 | int sel; |
65 | |
66 | asm ("mov %%gs, %w0" : "=q" (sel):"0" (0)); |
67 | if (__builtin_expect (sel, 0x48) & 4) /* LDT selector */ |
68 | err = __i386_set_ldt (thread, sel, &desc, 1); |
69 | else |
70 | err = __i386_set_gdt (thread, &sel, desc); |
71 | if (err) |
72 | return err; |
73 | state.gs = sel; |
74 | } |
75 | |
76 | err = __thread_set_state (thread, i386_REGS_SEGS_STATE, |
77 | (thread_state_t) &state, i386_THREAD_STATE_COUNT); |
78 | if (err) |
79 | return err; |
80 | |
81 | return 0; |
82 | } |
83 | |