/* Linux gateway page is aliased to virtual page 0 in the kernel *addressspace.Sinceitisagatewaypageitcannotbe *dereferenced,sonullpointerswillstillfault.Westart *theactualentrypointat0x100.Weputbreakinstructions *atthebeginningofthepagetotrapnullindirectfunction *pointers.
*/
/* ADDRESS 0xb0 to 0xb8, lws uses two insns for entry */ /* Light-weight-syscall entry must always be located at 0xb0 */ /* WARNING: Keep this number updated with table size changes */
#define __NR_lws_entries (5)
lws_entry:
gate lws_start, %r0 /* increase privilege */
depi PRIV_USER, 31, 2, %r31 /* Ensure we return into user mode. */
/* Fill from 0xb8 to 0xe0 */
.rept 10
KILL_INSN
.endr
/* This function MUST be located at 0xe0 for glibc's threading
mechanism to work. DO NOT MOVE THIS CODE EVER! */
set_thread_pointer:
gate .+8, %r0 /* increase privilege */
depi PRIV_USER, 31, 2, %r31 /* Ensure we return into user mode. */
be 0(%sr7,%r31) /* return to user space */
mtctl %r26, %cr27 /* move arg0 to the control register */
/* Increase the chance of trapping if random jumps occur to this
address, fill from 0xf0 to 0x100 */
.rept 4
KILL_INSN
.endr
/* This address must remain fixed at 0x100 for glibc's syscalls to work */
.align LINUX_GATEWAY_ADDR
linux_gateway_entry:
gate .+8, %r0 /* become privileged */
mtsp %r0,%sr4 /* get kernel space into sr4 */
mtsp %r0,%sr5 /* get kernel space into sr5 */
mtsp %r0,%sr6 /* get kernel space into sr6 */
#ifdef CONFIG_64BIT /* Store W bit on entry to the syscall in case it's a wide userland
* process. */
ssm PSW_SM_W, %r1
extrd,u %r1,PSW_W_BIT,1,%r1 /* sp must be aligned on 4, so deposit the W bit setting into
* the bottom of sp temporarily */
or,ev %r1,%r30,%r30
b,n 1f /* The top halves of argument registers must be cleared on syscall *entryfromnarrowexecutable.
*/
depdi 0, 31, 32, %r26
depdi 0, 31, 32, %r25
depdi 0, 31, 32, %r24
depdi 0, 31, 32, %r23
depdi 0, 31, 32, %r22
depdi 0, 31, 32, %r21 1:
#endif
/* We use a rsm/ssm pair to prevent sr3 from being clobbered *byexternalinterrupts.
*/
mfsp %sr7,%r1 /* save user sr7 */
rsm PSW_SM_I, %r0 /* disable interrupts */
mtsp %r1,%sr3 /* and store it in sr3 */
LDREG TASK_STACK(%r30),%r30 /* set up kernel stack */
ldo FRAME_SIZE(%r30),%r30 /* N.B.: It is critical that we don't set sr7 to 0 until r30 *containsavalidkernelstackpointer.Itisalso *criticalthatwedon'tstartusingthekernelstack *untilaftersr7hasbeensetto0.
*/
mtsp %r0,%sr7 /* get kernel space into sr7 */
ssm PSW_SM_I, %r0 /* enable interrupts */
STREGM %r1,FRAME_SIZE(%r30) /* save r1 (usp) here for now */
mfctl %cr30,%r1 /* get task ptr in %r1 */
/* Save some registers for sigcontext and potential task switch(seeentry.Sforthedetailsofwhichonesare saved/restored).TASK_PT_PSWiszeroedsowecanseewhether aprocessisonasyscallornot.Foraninterruptthereal
PSW value is stored. This is needed for gdb and sys_ptrace. */
STREG %r0, TASK_PT_PSW(%r1)
STREG %r2, TASK_PT_GR2(%r1) /* preserve rp */
STREG %r19, TASK_PT_GR19(%r1)
LDREGM -FRAME_SIZE(%r30), %r2 /* get users sp back */
#ifdef CONFIG_64BIT
extrd,u %r2,63,1,%r19 /* W hidden in bottom bit */
#if 0
xor %r19,%r2,%r2 /* clear bottom bit */
depd,z %r19,1,1,%r19
std %r19,TASK_PT_PSW(%r1)
#endif
#endif
STREG %r2, TASK_PT_GR30(%r1) /* ... and save it */
ldo TASK_PT_FR0(%r1), %r27 /* save fpregs from the kernel */
save_fp %r27 /* or potential task switch */
mfctl %cr11, %r27 /* i.e. SAR */
STREG %r27, TASK_PT_SAR(%r1)
loadgp
#ifdef CONFIG_64BIT
ldo -16(%r30),%r29 /* Reference param save area */
copy %r19,%r2 /* W bit back to r2 */
#else /* no need to save these on stack in wide mode because the first 8
* args are passed in registers */
stw %r22, -52(%r30) /* 5th argument */
stw %r21, -56(%r30) /* 6th argument */
#endif
/* Are we being ptraced? */
mfctl %cr30, %r1
LDREG TASK_TI_FLAGS(%r1),%r1
ldi _TIF_SYSCALL_TRACE_MASK, %r19
and,COND(=) %r1, %r19, %r0
b,n .Ltracesys
/* Note! We cannot use the syscall table that is mapped
nearby since the gateway page is mapped execute-only. */
/* If this is a sys_rt_sigreturn call, and the signal was received *whennotin_syscall,thenwewanttoreturnviasyscall_exit_rfi, *notsyscall_exit.Signalno.inr20,in_syscallinr25(see *trampolinecodeinsignal.c).
*/
ldi __NR_rt_sigreturn,%r2
comb,= %r2,%r20,.Lrt_sigreturn
.Lin_syscall:
ldil L%syscall_exit,%r2
be 0(%sr7,%r19)
ldo R%syscall_exit(%r2),%r2
.Lrt_sigreturn:
comib,<> 0,%r25,.Lin_syscall
ldil L%syscall_exit_rfi,%r2
be 0(%sr7,%r19)
ldo R%syscall_exit_rfi(%r2),%r2
/* Note! Because we are not running where we were linked, any callstofunctionsexternaltothisfilemustbeindirect.To besafe,weapplytheoppositeruletofunctionswithinthis
file, with local labels given to them to ensure correctness. */
.Lsyscall_nosys:
syscall_nosys:
ldil L%syscall_exit,%r1
be R%syscall_exit(%sr7,%r1)
ldo -ENOSYS(%r0),%r28 /* set errno */
/* Warning! This trace code is a virtual duplicate of the code above so be
* sure to maintain both! */
.Ltracesys:
tracesys: /* Need to save more registers so the debugger can see where we *are.Thissavesonlythelower8bitsofPSW,sothattheC *bitisstillclearonsyscalls,andtheDbitissetifthis *fullregistersavepathhasbeenexecuted.WechecktheD *bitonsyscall_return_rfitodeterminewhichregistersto *restore.AninterruptresultsinafullPSWsavedwiththe *Cbitset,anon-stracedsyscallentryresultsinCandDclear *inthesavedPSW.
*/
mfctl %cr30,%r1 /* get task ptr */
ssm 0,%r2
STREG %r2,TASK_PT_PSW(%r1) /* Lower 8 bits only!! */
mfsp %sr0,%r2
STREG %r2,TASK_PT_SR0(%r1)
mfsp %sr1,%r2
STREG %r2,TASK_PT_SR1(%r1)
mfsp %sr2,%r2
STREG %r2,TASK_PT_SR2(%r1)
mfsp %sr3,%r2
STREG %r2,TASK_PT_SR3(%r1)
STREG %r2,TASK_PT_SR4(%r1)
STREG %r2,TASK_PT_SR5(%r1)
STREG %r2,TASK_PT_SR6(%r1)
STREG %r2,TASK_PT_SR7(%r1)
STREG %r2,TASK_PT_IASQ0(%r1)
STREG %r2,TASK_PT_IASQ1(%r1)
LDREG TASK_PT_GR31(%r1),%r2
STREG %r2,TASK_PT_IAOQ0(%r1)
ldo 4(%r2),%r2
STREG %r2,TASK_PT_IAOQ1(%r1)
ldo TASK_REGS(%r1),%r2 /* reg_save %r2 */
STREG %r3,PT_GR3(%r2)
STREG %r4,PT_GR4(%r2)
STREG %r5,PT_GR5(%r2)
STREG %r6,PT_GR6(%r2)
STREG %r7,PT_GR7(%r2)
STREG %r8,PT_GR8(%r2)
STREG %r9,PT_GR9(%r2)
STREG %r10,PT_GR10(%r2)
STREG %r11,PT_GR11(%r2)
STREG %r12,PT_GR12(%r2)
STREG %r13,PT_GR13(%r2)
STREG %r14,PT_GR14(%r2)
STREG %r15,PT_GR15(%r2)
STREG %r16,PT_GR16(%r2)
STREG %r17,PT_GR17(%r2)
STREG %r18,PT_GR18(%r2) /* Finished saving things for the debugger */
copy %r2,%r26
ldil L%do_syscall_trace_enter,%r1
ldil L%tracesys_next,%r2
be R%do_syscall_trace_enter(%sr7,%r1)
ldo R%tracesys_next(%r2),%r2
tracesys_next: /* do_syscall_trace_enter either returned the syscallno, or -1L, *soweskiprestoringthePT_GR20below,sincewepulleditfrom *task->thread.regs.gr[20]above.
*/
copy %ret0,%r20
/* If this is a sys_rt_sigreturn call, and the signal was received *whennotin_syscall,thenwewanttoreturnviasyscall_exit_rfi, *notsyscall_exit.Signalno.inr20,in_syscallinr25(see *trampolinecodeinsignal.c).
*/
ldi __NR_rt_sigreturn,%r2
comb,= %r2,%r20,.Ltrace_rt_sigreturn
.Ltrace_in_syscall:
ldil L%tracesys_exit,%r2
be 0(%sr7,%r19)
ldo R%tracesys_exit(%r2),%r2
.Ltracesys_nosys:
ldo -ENOSYS(%r0),%r28 /* set errno */
/* Do *not* call this function on the gateway page, because it
makes a direct call to syscall_trace. */
tracesys_exit:
mfctl %cr30,%r1 /* get task ptr */
#ifdef CONFIG_64BIT
ldo -16(%r30),%r29 /* Reference param save area */
#endif
ldo TASK_REGS(%r1),%r26
BL do_syscall_trace_exit,%r2
STREG %r28,TASK_PT_GR28(%r1) /* save return value now */
mfctl %cr30,%r1 /* get task ptr */
LDREG TASK_PT_GR28(%r1), %r28 /* Restore return val. */
#ifdef CONFIG_64BIT
ssm PSW_SM_W, %r1
extrd,u %r1,PSW_W_BIT,1,%r1 /* sp must be aligned on 4, so deposit the W bit setting into
* the bottom of sp temporarily */
or,od %r1,%r30,%r30
/* Clip LWS number to a 32-bit value for 32-bit processes */
depdi 0, 31, 32, %r20
#endif
/* Is the lws entry number valid? */
comiclr,>> __NR_lws_entries, %r20, %r0
b,n lws_exit_nosys
/* Load table start */
ldil L%lws_table, %r1
ldo R%lws_table(%r1), %r28 /* Scratch use of r28 */
LDREGX %r20(%sr2,r28), %r21 /* Scratch use of r21 */
lws_fault:
ldo 1(%r0),%r28
b lws_exit
ldo -EFAULT(%r0),%r21
lws_exit_nosys:
ldo -ENOSYS(%r0),%r21 /* Fall through: Return to userspace */
lws_exit:
#ifdef CONFIG_64BIT /* decide whether to reset the wide mode bit * *Forasyscall,theWbitisstoredinthelowestbit
* of sp. Extract it and reset W if it is zero */
extrd,u,*<> %r30,63,1,%r1
rsm PSW_SM_W, %r0 /* now reset the lowest bit of sp if it was set */
xor %r30,%r1,%r30
#endif
be,n 0(%sr7, %r31)
/* ELF64 Process entry path */
lws_compare_and_swap64:
#ifdef CONFIG_64BIT
b,n lws_compare_and_swap
#else /* If we are not a 64-bit kernel, then we don't *have64-bitinputregisters,andcalling *the64-bitLWSCASreturnsENOSYS.
*/
b,n lws_exit_nosys
#endif
/* ELF32/ELF64 Process entry path */
lws_compare_and_swap32:
#ifdef CONFIG_64BIT /* Wide mode user process? */
bb,<,n %sp, 31, lws_compare_and_swap
/* Clip all the input registers for 32-bit processes */
depdi 0, 31, 32, %r26
depdi 0, 31, 32, %r25
depdi 0, 31, 32, %r24
#endif
lws_compare_and_swap: /* Trigger memory reference interruptions without writing to memory */ 1: ldw 0(%r26), %r28
proberi (%r26), PRIV_USER, %r28
comb,=,n %r28, %r0, lws_fault /* backwards, likely not taken */
nop 2: stbys,e %r0, 0(%r26)
/* Calculate 8-bit hash index from virtual address */
extru_safe %r26, 27, 8, %r20
/* Find lock to use, the hash index is one of 0 to 255,multipliedby16(keepit16-bytealigned)
and add to the lock table offset. */
shlw %r20, 4, %r20
add %r20, %r28, %r20
rsm PSW_SM_I, %r0 /* Disable interrupts */
/* Try to acquire the lock */
LDCW 0(%sr2,%r20), %r28
spinlock_check %r28, %r21
comclr,<> %r0, %r28, %r0
b,n lws_wouldblock
/* Disable page faults to prevent sleeping in critical region */
lws_pagefault_disable %r21,%r28
/* NOTES: Thisallworksbecauseintr_do_signal andschedulebothcheckthereturniasq andseethatweareonthekernelpage sothisprocessisneverscheduledoff oriseversentanysignalofanysort, thusitiswhollyatomicfromusrspace's perspective
*/ /* The load and store could fail */ 3: ldw 0(%r26), %r28 sub,<> %r28, %r25, %r0 4: stw %r24, 0(%r26)
b,n lws_exit_noerror
/* A fault occurred on load or stbys,e store */ 5: b,n lws_fault
ASM_EXCEPTIONTABLE_ENTRY(1b-linux_gateway_page, 5b-linux_gateway_page)
ASM_EXCEPTIONTABLE_ENTRY(2b-linux_gateway_page, 5b-linux_gateway_page)
/* A page fault occurred in critical region */ 6: b,n lws_pagefault
ASM_EXCEPTIONTABLE_ENTRY(3b-linux_gateway_page, 6b-linux_gateway_page)
ASM_EXCEPTIONTABLE_ENTRY(4b-linux_gateway_page, 6b-linux_gateway_page)
/* Clip the input registers for 32-bit processes. We don't
need to clip %r23 as we only use it for word operations */
depdi 0, 31, 32, %r26
depdi 0, 31, 32, %r25
depdi 0, 31, 32, %r24
#endif
cas2_begin: /* Check the validity of the size pointer */
subi,>>= 3, %r23, %r0
b,n lws_exit_nosys
/* Jump to the functions which will load the old and new values into
registers depending on the their size */
shlw %r23, 2, %r29
blr %r29, %r0
nop
/* Find lock to use, the hash index is one of 0 to 255,multipliedby16(keepit16-bytealigned)
and add to the lock table offset. */
shlw %r20, 4, %r20
add %r20, %r28, %r20
rsm PSW_SM_I, %r0 /* Disable interrupts */
/* Try to acquire the lock */
LDCW 0(%sr2,%r20), %r28
spinlock_check %r28, %r21
comclr,<> %r0, %r28, %r0
b,n lws_wouldblock
/* Disable page faults to prevent sleeping in critical region */
lws_pagefault_disable %r21,%r28
/* Clip the input registers for 32-bit processes. We don't
need to clip %r23 as we only use it for word operations */
depdi 0, 31, 32, %r26
depdi 0, 31, 32, %r25
depdi 0, 31, 32, %r24
depdi 0, 31, 32, %r23
#endif
atomic_xchg_begin: /* Check the validity of the size pointer */
subi,>>= 3, %r25, %r0
b,n lws_exit_nosys
/* Jump to the functions which will load the old and new values into
registers depending on the their size */
shlw %r25, 2, %r1
blr %r1, %r0
nop
/* Find lock to use, the hash index is one of 0 to 255,multipliedby16(keepit16-bytealigned)
and add to the lock table offset. */
shlw %r20, 4, %r20
add %r20, %r28, %r20
rsm PSW_SM_I, %r0 /* Disable interrupts */
/* Try to acquire the lock */
LDCW 0(%sr2,%r20), %r28
spinlock_check %r28, %r21
comclr,<> %r0, %r28, %r0
b,n lws_wouldblock
/* Disable page faults to prevent sleeping in critical region */
lws_pagefault_disable %r21,%r28
/* Clip the input registers for 32-bit processes. We don't
need to clip %r23 as we only use it for word operations */
depdi 0, 31, 32, %r26
depdi 0, 31, 32, %r25
depdi 0, 31, 32, %r24
#endif
atomic_store_begin: /* Check the validity of the size pointer */
subi,>>= 3, %r25, %r0
b,n lws_exit_nosys
/* Find lock to use, the hash index is one of 0 to 255,multipliedby16(keepit16-bytealigned)
and add to the lock table offset. */
shlw %r20, 4, %r20
add %r20, %r28, %r20
rsm PSW_SM_I, %r0 /* Disable interrupts */
/* Try to acquire the lock */
LDCW 0(%sr2,%r20), %r28
spinlock_check %r28, %r21
comclr,<> %r0, %r28, %r0
b,n lws_wouldblock
/* Disable page faults to prevent sleeping in critical region */
lws_pagefault_disable %r21,%r28
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.33Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-09-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.