Message ID | 20240801-rseq-abi-v11-split-v12-14-0e87479dddc0@efficios.com |
---|---|
State | New |
Headers | show |
Series | Add rseq extensible ABI support | expand |
* Michael Jeanson: > diff --git a/sysdeps/nptl/tcb-access.h b/sysdeps/nptl/tcb-access.h > index 600433766f..9532f30022 100644 > --- a/sysdeps/nptl/tcb-access.h > +++ b/sysdeps/nptl/tcb-access.h > @@ -30,3 +30,8 @@ > descr->member = (value) > #define THREAD_SETMEM_NC(descr, member, idx, value) \ > descr->member[idx] = (value) > + > +#define RSEQ_GETMEM_VOLATILE(descr, member) \ > + THREAD_GETMEM_VOLATILE(descr, member) > +#define RSEQ_SETMEM(descr, member, value) \ > + THREAD_SETMEM(descr, member, value) Please add a comments to these macros to explain their use. I'm not sure if you should use THREAD_GETMEM if you don't use it with THREAD_SELF. I assume you instead of passing struct pthread *, you are going to pass a struct rseq_abi * here. This is a bit too bit magic. Maybe use __thread_pointer? THREAD_GETMEM is only expected to be used in the context of the thread whose data is being accessed. Thanks, Florian
On 2024-09-14 13:19, Florian Weimer wrote: > * Michael Jeanson: > >> diff --git a/sysdeps/nptl/tcb-access.h b/sysdeps/nptl/tcb-access.h >> index 600433766f..9532f30022 100644 >> --- a/sysdeps/nptl/tcb-access.h >> +++ b/sysdeps/nptl/tcb-access.h >> @@ -30,3 +30,8 @@ >> descr->member = (value) >> #define THREAD_SETMEM_NC(descr, member, idx, value) \ >> descr->member[idx] = (value) >> + >> +#define RSEQ_GETMEM_VOLATILE(descr, member) \ >> + THREAD_GETMEM_VOLATILE(descr, member) >> +#define RSEQ_SETMEM(descr, member, value) \ >> + THREAD_SETMEM(descr, member, value) > > Please add a comments to these macros to explain their use. Ack. > > I'm not sure if you should use THREAD_GETMEM if you don't use it with > THREAD_SELF. I assume you instead of passing struct pthread *, you are > going to pass a struct rseq_abi * here. This is a bit too bit magic. > Maybe use __thread_pointer? THREAD_GETMEM is only expected to be used > in the context of the thread whose data is being accessed. Should I split these macros out of tcb-access.h in a new header with a generic version in 'sysdeps/nptl' and arch specific versions in 'sysdeps/ARCH/nptl' ?
* Michael Jeanson: > On 2024-09-14 13:19, Florian Weimer wrote: >> * Michael Jeanson: >> >>> diff --git a/sysdeps/nptl/tcb-access.h b/sysdeps/nptl/tcb-access.h >>> index 600433766f..9532f30022 100644 >>> --- a/sysdeps/nptl/tcb-access.h >>> +++ b/sysdeps/nptl/tcb-access.h >>> @@ -30,3 +30,8 @@ >>> descr->member = (value) >>> #define THREAD_SETMEM_NC(descr, member, idx, value) \ >>> descr->member[idx] = (value) >>> + >>> +#define RSEQ_GETMEM_VOLATILE(descr, member) \ >>> + THREAD_GETMEM_VOLATILE(descr, member) >>> +#define RSEQ_SETMEM(descr, member, value) \ >>> + THREAD_SETMEM(descr, member, value) >> >> Please add a comments to these macros to explain their use. > > Ack. > >> >> I'm not sure if you should use THREAD_GETMEM if you don't use it with >> THREAD_SELF. I assume you instead of passing struct pthread *, you are >> going to pass a struct rseq_abi * here. This is a bit too bit magic. >> Maybe use __thread_pointer? THREAD_GETMEM is only expected to be used >> in the context of the thread whose data is being accessed. > > Should I split these macros out of tcb-access.h in a new header with a > generic version in 'sysdeps/nptl' and arch specific versions in > 'sysdeps/ARCH/nptl' ? I don't think a new separate header is required if you can re-use an existing header. Maybe the generic version should just duplicate the definitions of THREAD_GETMEM_VOLATILE and THREAD_SETMEM? So that a port that changes only the THREAD_* functions does not accidentally use them for RSEQ_*MEM?
diff --git a/sysdeps/i386/nptl/tcb-access.h b/sysdeps/i386/nptl/tcb-access.h index 4b6221e103..eb40906c48 100644 --- a/sysdeps/i386/nptl/tcb-access.h +++ b/sysdeps/i386/nptl/tcb-access.h @@ -123,3 +123,64 @@ "i" (offsetof (struct pthread, member)), \ "r" (idx)); \ }}) + + +#if IS_IN (rtld) +/* Use the hidden symbol in ld.so. */ +# define rseq_offset_sym _rseq_offset +#else +# define rseq_offset_sym __rseq_offset +#endif + +/* Read member of the RSEQ area directly. */ +#define RSEQ_GETMEM_VOLATILE(descr, member) \ + ({ __typeof (descr->member) __value; \ + _Static_assert (sizeof (__value) == 1 \ + || sizeof (__value) == 4 \ + || sizeof (__value) == 8, \ + "size of per-thread data"); \ + if (sizeof (__value) == 1) \ + asm volatile ("movb %%gs:%P2(%3),%b0" \ + : "=q" (__value) \ + : "0" (0), "i" (offsetof (struct rseq_area, member)), \ + "r" (rseq_offset_sym)); \ + else if (sizeof (__value) == 4) \ + asm volatile ("movl %%gs:%P1(%2),%0" \ + : "=r" (__value) \ + : "i" (offsetof (struct rseq_area, member)), \ + "r" (rseq_offset_sym)); \ + else /* 8 */ \ + { \ + asm volatile ("movl %%gs:%P1(%2),%%eax\n\t" \ + "movl %%gs:4+%P1(%2),%%edx" \ + : "=&A" (__value) \ + : "i" (offsetof (struct rseq_area, member)), \ + "r" (rseq_offset_sym)); \ + } \ + __value; }) + +/* Set member of the RSEQ area directly. */ +#define RSEQ_SETMEM(descr, member, value) \ + ({ \ + _Static_assert (sizeof (descr->member) == 1 \ + || sizeof (descr->member) == 4 \ + || sizeof (descr->member) == 8, \ + "size of per-thread data"); \ + if (sizeof (descr->member) == 1) \ + asm volatile ("movb %b0,%%gs:%P1(%2)" : \ + : "iq" (value), \ + "i" (offsetof (struct rseq_area, member)), \ + "r" (rseq_offset_sym)); \ + else if (sizeof (descr->member) == 4) \ + asm volatile ("movl %0,%%gs:%P1(%2)" : \ + : "ir" (value), \ + "i" (offsetof (struct rseq_area, member)), \ + "r" (rseq_offset_sym)); \ + else /* 8 */ \ + { \ + asm volatile ("movl %%eax,%%gs:%P1(%2)\n\t" \ + "movl %%edx,%%gs:4+%P1(%2)" : \ + : "A" ((uint64_t) cast_to_integer (value)), \ + "i" (offsetof (struct rseq_area, member)), \ + "r" (rseq_offset_sym)); \ + }}) diff --git a/sysdeps/nptl/tcb-access.h b/sysdeps/nptl/tcb-access.h index 600433766f..9532f30022 100644 --- a/sysdeps/nptl/tcb-access.h +++ b/sysdeps/nptl/tcb-access.h @@ -30,3 +30,8 @@ descr->member = (value) #define THREAD_SETMEM_NC(descr, member, idx, value) \ descr->member[idx] = (value) + +#define RSEQ_GETMEM_VOLATILE(descr, member) \ + THREAD_GETMEM_VOLATILE(descr, member) +#define RSEQ_SETMEM(descr, member, value) \ + THREAD_SETMEM(descr, member, value) diff --git a/sysdeps/x86_64/nptl/tcb-access.h b/sysdeps/x86_64/nptl/tcb-access.h index d35948f111..2edead755e 100644 --- a/sysdeps/x86_64/nptl/tcb-access.h +++ b/sysdeps/x86_64/nptl/tcb-access.h @@ -130,3 +130,64 @@ "i" (offsetof (struct pthread, member[0])), \ "r" (idx)); \ }}) + +#if IS_IN (rtld) +/* Use the hidden symbol in ld.so. */ +# define rseq_offset_sym _rseq_offset +#else +# define rseq_offset_sym __rseq_offset +#endif + +/* Read member of the RSEQ area directly. */ +# define RSEQ_GETMEM_VOLATILE(descr, member) \ + ({ __typeof (descr->member) __value; \ + _Static_assert (sizeof (__value) == 1 \ + || sizeof (__value) == 4 \ + || sizeof (__value) == 8, \ + "size of per-thread data"); \ + if (sizeof (__value) == 1) \ + asm volatile ("movb %%fs:%P2(%q3),%b0" \ + : "=q" (__value) \ + : "0" (0), "i" (offsetof (struct rseq_area, member)), \ + "r" (rseq_offset_sym)); \ + else if (sizeof (__value) == 4) \ + asm volatile ("movl %%fs:%P1(%q2),%0" \ + : "=r" (__value) \ + : "i" (offsetof (struct rseq_area, member)), \ + "r" (rseq_offset_sym)); \ + else /* 8 */ \ + { \ + asm volatile ("movq %%fs:%P1(%q2),%q0" \ + : "=r" (__value) \ + : "i" (offsetof (struct rseq_area, member)), \ + "r" (rseq_offset_sym)); \ + } \ + __value; }) + +/* Set member of the RSEQ area directly. */ +# define RSEQ_SETMEM(descr, member, value) \ + ({ \ + _Static_assert (sizeof (descr->member) == 1 \ + || sizeof (descr->member) == 4 \ + || sizeof (descr->member) == 8, \ + "size of per-thread data"); \ + if (sizeof (descr->member) == 1) \ + asm volatile ("movb %b0,%%fs:%P1(%q2)" : \ + : "iq" (value), \ + "i" (offsetof (struct rseq_area, member)), \ + "r" (rseq_offset_sym)); \ + else if (sizeof (descr->member) == 4) \ + asm volatile ("movl %0,%%fs:%P1(%q2)" : \ + : IMM_MODE (value), \ + "i" (offsetof (struct rseq_area, member)), \ + "r" (rseq_offset_sym)); \ + else /* 8 */ \ + { \ + /* Since movq takes a signed 32-bit immediate or a register source \ + operand, use "er" constraint for 32-bit signed integer constant \ + or register. */ \ + asm volatile ("movq %q0,%%fs:%P1(%q2)" : \ + : "er" ((uint64_t) cast_to_integer (value)), \ + "i" (offsetof (struct rseq_area, member)), \ + "r" (rseq_offset_sym)); \ + }})
This will be used to access and write to the rseq area in the extra TLS block. Signed-off-by: Michael Jeanson <mjeanson@efficios.com> --- sysdeps/i386/nptl/tcb-access.h | 61 ++++++++++++++++++++++++++++++++++++++++ sysdeps/nptl/tcb-access.h | 5 ++++ sysdeps/x86_64/nptl/tcb-access.h | 61 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+)