Files
seta75D d6fe8fe829 Init
2021-10-11 22:19:34 -03:00

495 lines
11 KiB
ArmAsm

# @(#)94 1.3 src/bos/kernel/ml/POWER/forkstack.s, sysml, bos411, 9428A410j 3/22/94 15:57:19
#
# COMPONENT_NAME: SYSML
#
# FUNCTIONS: execve
# fork
# kexit
# kfork
# kload
# _load
# loadbind
# unload
#
# ORIGINS: 27, 83
#
#
# This module contains IBM CONFIDENTIAL code. -- (IBM
# Confidential Restricted when combined with the aggregated
# modules for this product)
# SOURCE MATERIALS
#
# (C) COPYRIGHT International Business Machines Corp. 1993, 1994
# All Rights Reserved
# US Government Users Restricted Rights - Use, duplication or
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
#
#****************************************************************************
#
# LEVEL 1, 5 Years Bull Confidential Information
#
#****************************************************************************
.file "forkstack.s"
.machine "com"
#*******************************************************************************
#
# The routines included in this file are system call wrapper to execute on
# the special fork stack.
#
# On entry from SVC the following registers are set :
# r1 - stack pointer to only one stack frame on own kstack
# r3-r10 - parameters
# r24 - u
# r25 - ut (csa)
# r26 - user lr
# r27 - user cr
# r28 - curproc
# r29 - curthread
# r30 - scratch (used to save return code)
# r31 - scratch (used to save return address)
#
# On exit to SVC, r1 and r24-r29 must still hold accurate values, therefore
# some are updated (r1, r25, r28, r29 for fork; r1, r25 for exec). r3 must
# hold the SVC return code.
#
#*******************************************************************************
#*******************************************************************************
#
# NAME: fork
#
# FUNCTION: binary compatibility for app. statically linked with old fork() sc
#
#*******************************************************************************
S_PROLOG(fork)
b ENTRY(kfork)
.extern ENTRY(kfork)
S_EPILOG
FCNDES(fork)
#*******************************************************************************
#
# NAME: kfork
#
# FUNCTION: system call wrapper to execute on the fork stack
#
# ASSUMPTION: fork has no parameter
#
#*******************************************************************************
S_PROLOG(kfork)
# Save current return address
mflr r31
# Acquire special fork stack
mr r3, r28 # current proc pointer
bl ENTRY(acquire_forkstack)# returns forkstack address
.extern ENTRY(acquire_forkstack)
# Switch to the fork stack
cal r1, -stkmin(r3) # buy one stack frame on forkstack
ifdef(`_KDB',`
l r12, t_stackp(r29) # user stack pointer
st r12, stkback(r1) # back chain to old stack
')
# Invoke real function
bl ENTRY(kforkx)
.extern ENTRY(kforkx)
# Save return code
mr r30, r3
# When the child returns, curproc, curthread and csa/ut are no longer
# valid. They are refetched thanks to u which is still valid and
# thanks to the assumption that the child is single-threaded.
cmpi cr0, r3, 0
bne cr0, fork_no_refetch # not returning as child
l r28, u_procp(r24) # refetch curproc
l r29, p_thrdlist(r28) # refetch curthread
l r25, t_uthreadp(r29) # refetch csa/ut
fork_no_refetch:
# Switch back to normal stack
l r11, ut_kstack(r25) # kernel stack pointer
cal r1, -stkmin(r11) # buy one stack frame on normal stack
ifdef(`_KDB',`
l r12, t_stackp(r29) # user stack pointer
st r12, stkback(r1) # back chain to old stack
')
# Release special fork stack
mr r3, r28 # current proc pointer
bl ENTRY(release_forkstack)
.extern ENTRY(release_forkstack)
# Restore return address and return code
mtlr r31 # return address
mr r3, r30 # return code
S_EPILOG
FCNDES(kfork)
#*******************************************************************************
#
# NAME: execve
#
# FUNCTION: system call wrapper to execute on the fork stack
#
# ASSUMPTION: exec has three parameters
#
#*******************************************************************************
S_PROLOG(execve)
# Save current return address
mflr r31
# Buy a stack frame in order to save parameters in the current one
st r3, stkp1+0*4(r1)
st r4, stkp1+1*4(r1)
st r5, stkp1+2*4(r1)
st r31, stklink(r1)
stu r1, -stkmin(r1)
# Acquire special fork stack
mr r3, r28 # current proc pointer
bl ENTRY(acquire_forkstack)# returns forkstack address
.extern ENTRY(acquire_forkstack)
# Restore parameters
l r0, stkmin+stkp1+0*4(r1)# cannot lose r3 yet
l r4, stkmin+stkp1+1*4(r1)
l r5, stkmin+stkp1+2*4(r1)
# Switch to the fork stack
cal r1, -stkmin(r3) # buy one stack frame on forkstack
mr r3, r0 # get r3 parameter back for good
ifdef(`_KDB',`
l r12, t_stackp(r29) # user stack pointer
st r12, stkback(r1) # back chain to old stack
')
# Invoke real function
bl ENTRY(execvex)
.extern ENTRY(execvex)
# Save return code
mr r30, r3
# When unsuccessful, csa/ut is no longer valid because the process
# has lost all its thread but this one which has been moved in the
# default location. It is refetched thanks to curthread which is
# still valid.
# When successful, never returns here, execexit() is used instead.
l r25, t_uthreadp(r29) # refetch csa/ut
# Switch back to normal stack
l r11, ut_kstack(r25) # kernel stack pointer
cal r1, -stkmin(r11) # buy one stack frame on normal stack
ifdef(`_KDB',`
l r12, t_stackp(r29) # user stack pointer
st r12, stkback(r1) # back chain to user stack
')
# Release special fork stack
mr r3, r28 # current proc pointer
bl ENTRY(release_forkstack)
.extern ENTRY(release_forkstack)
# Restore return address and return code
mtlr r31 # return address
mr r3, r30 # return code
S_EPILOG
FCNDES(execve)
#*******************************************************************************
#
# NAME: kexit
#
# FUNCTION: system call wrapper to execute on the fork stack
#
# ASSUMPTION: exit has one parameter
#
# NOTE: Not always called as a system call, therefore we only assume the
# following to be available on entry:
# r1 - caller's normal stack pointer
# r3 - parameter
#
# never returns therefore no need to save any registers we may trash
#
#*******************************************************************************
S_PROLOG(kexit)
# Save current return address
mflr r31
# Save parameter
mr r30, r3
# Acquire special fork stack
LTOC(r11, __ublock, data) # address of ublock
l r28,u_procp+(ub_user-ublock)(r11) # current proc pointer
mr r3, r28
bl ENTRY(acquire_forkstack)# returns forkstack address
.extern ENTRY(acquire_forkstack)
# Switch to the fork stack if not a kproc and not already on it
# (Note: we assume the fork stack is the only stack in segment 2)
l r11, p_flag(r28) # process flags
mr r12, r1 # current stack pointer
rlinm. r11, r11, 0, SKPROC # check kproc flag
rlinm r10, r12, 4, 0x0000000F # get segment number for stack
bne cr0, exit_no_forkstack
cmpi cr0, r10, 2 # compare to PRIVSEG
beq cr0, exit_no_forkstack
cal r1, -stkmin(r3) # buy one stack frame on forkstack
st r31, stklink(r12) # save old lr
st r12, stkback(r1) # back chain to old stack
exit_no_forkstack:
# Restore parameter
mr r3, r30
# Invoke real function
bl ENTRY(kexitx)
.extern ENTRY(kexitx)
# Does not return
S_EPILOG
FCNDES(kexit)
#*******************************************************************************
#
# NAME: kload
#
# FUNCTION: system call wrapper to execute on the fork stack
#
# ASSUMPTION: kload has three parameters
# (max. of the number of parameters for load, unload and loadbind)
#
# NOTE: a fourth parameter containing the address of the real function is added
#
#*******************************************************************************
S_PROLOG(kload)
# Save current return address
mflr r31
# Buy a stack frame in order to save parameters in the current one
st r3, stkp1+0*4(r1)
st r4, stkp1+1*4(r1)
st r5, stkp1+2*4(r1)
st r6, stkp1+3*4(r1)
st r31, stklink(r1)
stu r1, -stkmin(r1)
# Acquire special fork stack
mr r3, r28 # current proc pointer
bl ENTRY(acquire_forkstack)# returns forkstack address
.extern ENTRY(acquire_forkstack)
# Restore parameters
l r0, stkmin+stkp1+0*4(r1)# cannot lose r3 yet
l r4, stkmin+stkp1+1*4(r1)
l r5, stkmin+stkp1+2*4(r1)
l r6, stkmin+stkp1+3*4(r1)
# Switch to the fork stack
cal r1, -stkmin(r3) # buy one stack frame on forkstack
mr r3, r0 # get r3 parameter back for good
ifdef(`_KDB',`
l r12, t_stackp(r29) # user stack pointer
st r12, stkback(r1) # back chain to old stack
')
# Reload SR1 with TEXTSEG
l r0, u_adspace_sr+1*4(r24)
mtsr sr1, r0
isync
# Invoke real function
mtctr r6
bctrl
# Reload SR1 with KSTACKSEG
l r0, p_kstackseg(r28)
mtsr sr1, r0
isync
# Save return code
mr r30, r3
# Switch back to normal stack
l r11, ut_kstack(r25) # kernel stack pointer
cal r1, -stkmin(r11) # buy one stack frame on normal stack
ifdef(`_KDB',`
l r12, t_stackp(r29) # user stack pointer
st r12, stkback(r1) # back chain to user stack
')
# Release special fork stack
mr r3, r28 # current proc pointer
bl ENTRY(release_forkstack)
.extern ENTRY(release_forkstack)
# Restore return address and return code
mtlr r31 # return address
mr r3, r30 # return code
S_EPILOG
FCNDES(kload)
#*******************************************************************************
#
# NAME: _load
#
# FUNCTION: system call wrapper to execute on the fork stack
#
# ASSUMPTION: _load has no more than three parameters
#
#*******************************************************************************
S_PROLOG(_load)
# Get the address of loadx has a fourth parameter
LTOC(r6, loadx, entry)
# Branch to common code
b ENTRY(kload)
.extern ENTRY(kload)
S_EPILOG
FCNDES(_load)
#*******************************************************************************
#
# NAME: unload
#
# FUNCTION: system call wrapper to execute on the fork stack
#
# ASSUMPTION: unload has no more than three parameters
#
#*******************************************************************************
S_PROLOG(unload)
# Get the address of unloadx has a fourth parameter
LTOC(r6, unloadx, entry)
# Branch to common code
b ENTRY(kload)
.extern ENTRY(kload)
S_EPILOG
FCNDES(unload)
#*******************************************************************************
#
# NAME: loadbind
#
# FUNCTION: system call wrapper to execute on the fork stack
#
# ASSUMPTION: loadbind has no more than three parameters
#
#*******************************************************************************
S_PROLOG(loadbind)
# Get the address of loadbindx has a fourth parameter
LTOC(r6, loadbindx, entry)
# Branch to common code
b ENTRY(kload)
.extern ENTRY(kload)
S_EPILOG
FCNDES(loadbind)
.toc
TOCE(__ublock, data)
TOCE(loadx, entry)
TOCE(loadbindx, entry)
TOCE(unloadx, entry)
include(proc.m4)
include(mstsave.m4)
include(user.m4)
include(low_dsect.m4)