-.L_kernel_syscall:
- neg r31, r0 /* Make number +ve and put in r31*/
-
- /* If out of range, call server with syscall exception */
- addis r29, 0, HIGH_CADDR(EXT(mach_trap_count))
- addi r29, r29, LOW_ADDR(EXT(mach_trap_count))
- lwz r29, 0(r29)
-
- cmp cr0, r31, r29
- bge- cr0, .L_call_server_syscall_exception
-
- addis r29, 0, HIGH_CADDR(EXT(mach_trap_table))
- addi r29, r29, LOW_ADDR(EXT(mach_trap_table))
-
- /* multiply the trap number to get offset into table */
- slwi r31, r31, MACH_TRAP_OFFSET_POW2
-
- /* r31 now holds offset into table of our trap entry,
- * add on the table base, and it then holds pointer to entry
- */
- add r31, r31, r29
-
- /* If the function is kern_invalid, prepare to send an exception.
- This is messy, but parallels the x86. We need it for task_by_pid,
- at least. */
- lis r29, HIGH_CADDR(EXT(kern_invalid))
- addi r29, r29, LOW_ADDR(EXT(kern_invalid))
- lwz r0, MACH_TRAP_FUNCTION(r31)
- cmp cr0, r0, r29
- beq- .L_call_server_syscall_exception
-
- /* get arg count. If argc > 8 then not all args were in regs,
- * so we must perform copyin.
- */
- lwz r29, MACH_TRAP_ARGC(r31)
- cmpwi cr0, r29, 8
- ble+ .L_syscall_got_args
-
-/* argc > 8 - perform a copyin */
-/* if the syscall came from kernel space, we can just copy */
-
- lwz r0,savesrr1(r30) /* Pick up exception time MSR */
- andi. r0,r0,MASK(MSR_PR) /* Check the priv bit */
- bne+ .L_syscall_arg_copyin /* We're not priviliged... */
-
-/* we came from a privilaged task, just do a copy */
-/* get user's stack pointer */
-
- lwz r28,saver1(r30) /* Get the stack pointer */
-
- subi r29,r29,8 /* Get the number of arguments to copy */
-
- addi r28,r28,COPYIN_ARG0_OFFSET-4 /* Point to source - 4 */
- addi r27,r1,FM_ARG0-4 /* Point to sink - 4 */
-
-.L_syscall_copy_word_loop:
- addic. r29,r29,-1 /* Count down the number of arguments left */
- lwz r0,4(r28) /* Pick up the argument from the stack */
- addi r28,r28,4 /* Point to the next source */
- stw r0,4(r27) /* Store the argument */
- addi r27,r27,4 /* Point to the next sink */
- bne+ .L_syscall_copy_word_loop /* Move all arguments... */
- b .L_syscall_got_args /* Go call it now... */
-
-
-/* we came from a user task, pay the price of a real copyin */
-/* set recovery point */
-
-.L_syscall_arg_copyin:
- lwz r8,ACT_VMMAP(r13) ; Get the vm_map for this activation
- lis r28,hi16(.L_syscall_copyin_recover)
- lwz r8,VMMAP_PMAP(r8) ; Get the pmap
- ori r28,r28,lo16(.L_syscall_copyin_recover)
- addi r8,r8,PMAP_SEGS ; Point to the pmap SR slots
- stw r28,THREAD_RECOVER(r16) /* R16 still holds thread ptr */
-
-/* We can manipulate the COPYIN segment register quite easily
- * here, but we've also got to make sure we don't go over a
- * segment boundary - hence some mess.
- * Registers from 12-29 are free for our use.
- */
-
-
- lwz r28,saver1(r30) /* Get the stack pointer */
- subi r29,r29,8 /* Get the number of arguments to copy */
- addi r28,r28,COPYIN_ARG0_OFFSET /* Set source in user land */
-
-/* set up SR_COPYIN to allow us to copy, we may need to loop
- * around if we change segments. We know that this previously
- * pointed to user space, so the sid doesn't need setting.
- */
-
- rlwinm r7,r28,6,26,29 ; Get index to the segment slot