// 16(FP) siginfo
// 20(FP) context
TEXT sigtramp(SB),7,$40
- // Darwin sets GS to 0x37 on entry.
- // The original GS is at 0x70(FP).
- MOVL oldgs+0x70(FP), BX
- MOVW BX, GS
-
// g = m->gsignal
get_tls(CX)
MOVL m(CX), BP
MOVL $bsdthread_start(SB), 4(SP) // threadstart
MOVL $0, 8(SP) // wqthread, not used by us
MOVL $0, 12(SP) // pthsize, not used by us
- MOVL $0, 16(SP) // paranoia
- MOVL $0, 20(SP)
- MOVL $0, 24(SP)
+ MOVL $0, 16(SP) // dummy_value [sic]
+ MOVL $0, 20(SP) // targetconc_ptr
+ MOVL $0, 24(SP) // dispatchqueue_offset
INT $0x80
JAE 2(PC)
CALL notok(SB)
CALL sysenter(SB)
RET
-/*
-descriptor entry format for system call
-is the native machine format, ugly as it is:
-
- 2-byte limit
- 3-byte base
- 1-byte: 0x80=present, 0x60=dpl<<5, 0x1F=type
- 1-byte: 0x80=limit is *4k, 0x40=32-bit operand size,
- 0x0F=4 more bits of limit
- 1 byte: 8 more bits of base
-
-int i386_get_ldt(int, union ldt_entry *, int);
-int i386_set_ldt(int, const union ldt_entry *, int);
-
-*/
-
// setldt(int entry, int address, int limit)
+// entry and limit are ignored.
TEXT setldt(SB),7,$32
MOVL address+4(FP), BX // aka base
- MOVL limit+8(FP), CX
/*
* When linking against the system libraries,
* of the constant.
*/
SUBL $0x468, BX
- ADDL $0x468, CX
-
- // set up data_desc
- LEAL 16(SP), AX // struct data_desc
- MOVL $0, 0(AX)
- MOVL $0, 4(AX)
-
- MOVW BX, 2(AX)
- SHRL $16, BX
- MOVB BX, 4(AX)
- SHRL $8, BX
- MOVB BX, 7(AX)
-
- MOVW CX, 0(AX)
- SHRL $16, CX
- ANDL $0x0F, CX
- ORL $0x40, CX // 32-bit operand size
- MOVB CX, 6(AX)
-
- MOVB $0xF2, 5(AX) // r/w data descriptor, dpl=3, present
- // call i386_set_ldt(entry, desc, 1)
- MOVL $0xffffffff, 0(SP) // auto-allocate entry and return in AX
- MOVL AX, 4(SP)
- MOVL $1, 8(SP)
- CALL i386_set_ldt(SB)
-
- // compute segment selector - (entry*8+7)
- SHLL $3, AX
- ADDL $7, AX
- MOVW AX, GS
- RET
+ /*
+ * Must set up as USER_CTHREAD segment because
+ * Darwin forces that value into %gs for signal handlers,
+ * and if we don't set one up, we'll get a recursive
+ * fault trying to get into the signal handler.
+ * Since we have to set one up anyway, it might as
+ * well be the value we want. So don't bother with
+ * i386_set_ldt.
+ */
+ MOVL BX, 4(SP)
+ MOVL $3, AX // thread_fast_set_cthread_self - machdep call #3
+ INT $0x82 // sic: 0x82, not 0x80, for machdep call
-TEXT i386_set_ldt(SB),7,$0
- MOVL $5, AX
- INT $0x82 // sic
- JAE 2(PC)
- CALL notok(SB)
+ XORL AX, AX
+ MOVW GS, AX
RET
-
-GLOBL tlsoffset(SB),$4
MOVQ gg+24(SP), R10 // "pthread"
// TODO(rsc): why do we get away with 0 flags here but not on 386?
MOVQ $0, R8 // flags
+ MOVQ $0, R9 // paranoia
MOVQ $(0x2000000+360), AX // bsdthread_create
SYSCALL
JCC 2(PC)
MOVQ $bsdthread_start(SB), DI // threadstart
MOVQ $0, SI // wqthread, not used by us
MOVQ $0, DX // pthsize, not used by us
+ MOVQ $0, R10 // dummy_value [sic]
+ MOVQ $0, R8 // targetconc_ptr
+ MOVQ $0, R9 // dispatchqueue_offset
MOVQ $(0x2000000+366), AX // bsdthread_register
SYSCALL
JCC 2(PC)