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

897 lines
23 KiB
ArmAsm

# @(#)03 1.4.1.12 src/bos/kernel/ml/POWER/misc_init.s, sysml, bos41J, 9511A_all 3/7/95 13:12:47
#*****************************************************************************
#
# COMPONENT_NAME: (SYSML) Kernel Assembler Code
#
# FUNCTIONS: misc. functions
#
# ORIGINS: 27, 83
#
# IBM CONFIDENTIAL -- (IBM Confidential Restricted when
# combined with the aggregated modules for this product)
# SOURCE MATERIALS
# (C) COPYRIGHT International Business Machines Corp. 1992,1995
# 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
#
#
# NOTE:
# Many of these functions are overlays, with addresses and sizes
# assigned in overlay.h. Do not update this file without checking
# overlay.h
#
# Overlays are required to be position independent
#
#****************************************************************************
#
# Contains assembler functions that are only used during system
# initialization. The text for these functions is discared after
# system initialization is complete
#
.file "misc_init.s"
include(macros.m4)
#**********************************************************************
#
# NAME: ldsr/mtsr
#
# FUNCTION: load segment register
# mtsr(segreg,segreg_value)
# ldsr(segreg,segreg_value)
#
# INPUT STATE:
# r3 = segment register number
# r4 = segment register value
#
# NOTES:
# Do not change register usage without updating inline.h
#
# OUTPUT STATE:
# The specified segment register is loaded with the input value.
#
# EXECUTION ENVIRONMENT:
# Overlay data for PowerRS machines and 601
#
#**********************************************************************
.csect mtsr_sect_pwr[RO]
DATA(mtsr_pwr):
.globl DATA(mtsr_pwr)
rlinm r3, r3, 28, 0xF0000000 # generate an effective address
mtsri r4, 0, r3
br
ifdef(`_POWER_RS',`
.machine "pwr"
#**********************************************************************
#
# NAME: chgsr
#
# FUNCTION: change segment register
# chgsr(segreg,segreg_value)
#
# INPUT STATE:
# r3 = segment register number
# r4 = segment register value
#
# NOTES:
# Do not change register usage without updating inline.h
#
# OUTPUT STATE:
# The specified segment register is loaded with the input value.
# The old segement register is returned
#
# EXECUTION ENVIRONMENT:
# Overlay data for PowerRS
#
#**********************************************************************
.csect chgsr_sect_pwr[RO]
DATA(chgsr_pwr):
.globl DATA(chgsr_pwr)
rlinm r5, r3, 28, 0xF0000000 # generate an effective address
mfsri r3, 0, r5
mtsri r4, 0, r5
br
#******************************************************************************
#
# NAME: mfsri_pwr
#
# FUNCTION:
# Move from segment register indirect.
#
# NOTES:
# Do not change register usage without updating inline.h
#
# EXECUTION ENVIRONMENT:
# Overlay data
#
# INPUT:
# r3 - address whose bits 0-3 form the segment to save
#
# RETURNS:
# r3 - contents of segment reg.
#
#******************************************************************************
.csect mfsri_pwr_overlay[RO]
DATA(mfsri_pwr):
.globl DATA(mfsri_pwr)
mfsri r3,r0,r3
br
#******************************************************************************
#
# NAME: mfsr_pwr
#
# FUNCTION:
# Move from segment register indirect.
#
# EXECUTION ENVIRONMENT:
# Overlay data
#
# NOTES:
# Do not change register usage without updating inline.h
#
# INPUT:
# r3 - segreg number to read
#
# RETURNS:
# r3 - contents of segment reg.
#
#******************************************************************************
.csect mfsr_pwr_overlay[RO]
DATA(mfsr_pwr):
.globl DATA(mfsr_pwr)
rlinm r3, r3, 28, 0xF0000000 # generate effective address
mfsri r3,r0,r3
br
#******************************************************************************
#
# NAME: sc_front_pwr
#
# FUNCTION:
# This overlay is placed at 0x1fe0 on Power machines. It simply
# calls the sc_flih (common sc handler).
#
#*****************************************************************************
.csect sc_flih_pwr_overlay[PR]
DATA(sc_front_pwr):
.globl DATA(sc_front_pwr)
ba ENTRY(sc_flih)
.extern ENTRY(sc_flih)
#******************************************************************************
#
# NAME: cs_pwr
#
# FUNCTION:
# The 4.1 cs() implementation is an exported kernel entry
# point. The entry point lies in the machine-dependent
# overlay area. The Power version uses a fast SVC to
# implement an atomic load/store sequence. There is a hook in
# the ds_flih() to handle page faults during cs(). The Power
# PC version uses lwarx/stwcx to perform the the atomic op,
# provided the cs() address is word aligned. Unaligned Power
# PC cs() operations are passed to the cmp_swap() system call.
# This is called through the standards SC handler using a
# system call index (r2) loaded into a global variable at SI
# time. The cmp_swap() system call is serialize access by use
# of a lock.
#
# The cs() system call is not available to kernel extensions.
# This is because it must backup and fabricate a problem state
# MSR when a page fault occurs. The ds_flih must assume the
# cs() caller was in problem state when fabricating the MSR
# (else there is a security hole). This problem is solvable
# with enough work, but it is not felt to be a requirement.
#
#******************************************************************************
.csect cs_pwr_sect[PR]
DATA(cs_pwr):
.globl DATA(cs_pwr)
cror 0,0,0 # a noop because of machine bug
svc 1,0,0 # svc 1 link-reg unchanged
#*******************************************************************************
#
# NAME: cs_svc_pwr
#
# FUNCTION:
# This code is overlayed to 0x1020 (SVC(1) vector).
# if a page-fault occurs on load or store we back-track
# to .cs in dsis_flih. a wild-branch to the middle of the
# code will either take a program exception on the rfsvc
# or look like a storage exception at the beginning of .cs.
#
#*******************************************************************************
.csect cs_sc_pwr_overlay[PR]
DATA(cs_svc_pwr):
.globl DATA(cs_svc_pwr)
l r6,0(r3) # load the word
cmp 0,r4,r6 # compare the word
bne 0,noswap # branch if different
st r5,0(r3) # swap word
cal r3,0(r0) # r3 = equal retcode
rfsvc # return
noswap:
cal r3,1(r0) # r3 = noswap retcode
rfsvc # return
#******************************************************************************
#
# NAME: al_pwr
#
# CALL: None
#
# FUNCTION: This sequence is copied to 0x600 at system initialization time
# when running on a Power machine.
#
# NOTES:
# Do not change this function without updating overlay.h
#
# RETURNS : None
#
#******************************************************************************
.csect al_ppc_overlay[PR]
DATA(al_prolog_pwr):
.globl DATA(al_prolog_pwr)
st r15, ra_save(0) # save original contents of r15
ifdef(`_POWER_MP',`
l r15, proc_arr_addr(0) # load address of ppda
',`
cal r15, ppda(0) # get ppda address
')
stm r25, SAVE_R25(r15) # save off 25-31
cal r25, SAVE_WORK0(r15) # point r25 at start of al flih
l r15, ra_save(0) # load up original contents of r15
xor r26,r26,r26 # zero r26
st r26, ra_save(0) # zero out ra_save
ba ENTRY(al_flih) # branch to common alignment code
#*****************************************************************************
#
# NAME: dc_line_size
#
# CALL: int dc_line_size()
#
# FUNCTION: gets the L1 data cache line size
#
# RETURNS:
# data cache line size in bytes
#
#*****************************************************************************
S_PROLOG(dc_line_size)
clcs r3, 0xd # get data cache line size
br
#*****************************************************************************
#
# NAME: ic_line_size
#
# CALL: int ic_line_size()
#
# FUNCTION: gets the L1 instruction cache line size
#
# RETURNS:
# instruction cache line size in bytes
#
#*****************************************************************************
S_PROLOG(ic_line_size)
clcs r3, 0xC # get instruction cache line size
br
#******************************************************************************
#
# NAME: flih_prolog_pwr
#
# CALL: None
#
# FUNCTION: contains the instruction sequence to be placed at interrupt
# vectors on Power machines
#
# NOTES:
# Do not update without changing mc_prolog_pwr
#
# RETURNS: None
#
#******************************************************************************
.csect flih_pwr[PR]
DATA(flih_prolog_pwr): # address exported to C code
.globl DATA(flih_prolog_pwr)
st r15, ra_save(0) # save the value of r15
ifdef(`_POWER_MP',`
l r15, proc_arr_addr(0) # get ppda address
',`
cal r15, ppda(0) # get ppda address
')
st r0, ppda_save0(r15) # save a register
ba 0 # branch to flih
#******************************************************************************
#
# NAME: noop_instr_pwr
#
# CALL: None
#
# FUNCTION: contains the overlay data for no-op instructions used no-op
# instructions on Power
#
# RETURNS: None
#
#*******************************************************************************
.csect noop_inst_pwr[RO]
.globl noop_inst_pwr[RO]
cror 30,30,30
#*******************************************************************************
#
# NAME: mc_flih_prolog
#
# FUNCTION:
# Instruction sequence overlayed at flih to fix bug in RS1
# processor machine check handling.
#
# NOTES:
# Do not change without updating flih_prolog_pwr
#
# Size of routine is in overlay.h
#
# RETURNS: None
#
#*******************************************************************************
.csect mc_pwr[PR]
DATA(mc_prolog_pwr):
.globl DATA(mc_prolog_pwr)
dcs # invalidate icache line to prevent
bl mc_next_pwr # checkstop
mc_next_pwr:
mflr r1
ai r1, r1, 12
cli 0, r1
ics
# standard power prolog
st r15, ra_save(0) # save the value of r15
ifdef(`_POWER_MP',`
l r15, proc_arr_addr(0) # get ppda address
',`
cal r15, ppda(0) # get ppda address
')
st r0, ppda_save0(r15) # save a register
ba DATA(mc_flih) # branch to flih
.globl DATA(mc_flih)
#*******************************************************************************
#
# FUNCTION: Set Current interrupt level for the processor
#
# CALL: void i_cil_set(level)
# int level; /* 0-63. level to set to */
#
# RETURNS:
# None
#
#*******************************************************************************
S_PROLOG(i_cil_set)
rlinm r3, r3, 8, 0xFF00 # move it over to CIL byte
# Byte 0 implied 0 for CIL write
mtspr ILCR, r3 # set CIL
br
#*******************************************************************************
#
# NAME: ds_prolog
#
# FUNCTION:
# overlay for dsi flih prolog. The ds/is flihs need a prolog
# that does not alter the save[0] field in the ppda
#
# NOTES:
# Do not change without updating overlay.h
#
# RETUNRS: None
#
#*******************************************************************************
.csect ds_sect_pwr[PR]
DATA(ds_prolog_pwr):
.globl DATA(ds_prolog_pwr)
st r15, ra_save(0) # save the value of r15
ifdef(`_POWER_MP',`
l r15, proc_arr_addr(0) # get ppda address
',`
cal r15, ppda(0) # get ppda address
')
ba DATA(ds_flih) # branch to flih
#*******************************************************************************
#
# NAME: is_prolog
#
# FUNCTION:
# overlay for dsi flih prolog. The ds/is flihs need a prolog
# that does not alter the save[0] field in the ppda
#
# NOTES:
# Do not change without updating overlay.h
#
# RETUNRS: None
#
#*******************************************************************************
.csect is_sect_pwr[PR]
DATA(is_prolog_pwr):
.globl DATA(is_prolog_pwr)
st r15, ra_save(0) # save the value of r15
ifdef(`_POWER_MP',`
l r15, proc_arr_addr(0) # get ppda address
',`
cal r15, ppda(0) # get ppda address
')
ba DATA(is_flih) # branch to flih
',)
_DF(_DF_NOFRAME)
ifdef(`_POWER_PC',`
.machine "ppc"
#**********************************************************************
#
# NAME: chgsr
#
# FUNCTION: change segment register
# chgsr(segreg,segreg_value)
#
# INPUT STATE:
# r3 = segment register number
# r4 = segment register value
#
# NOTES:
# Do not change register usage without updating inline.h
#
# OUTPUT STATE:
# The specified segment register is loaded with the input value.
# The old segement register is returned
#
# EXECUTION ENVIRONMENT:
# Overlay data for 601
#
#**********************************************************************
.csect chgsr_sect_601[RO]
DATA(chgsr_601):
.globl DATA(chgsr_601)
rlinm r5, r3, 28, 0xF0000000 # generate an effective address
mfsrin r3, r5 # read segment value
mtsri r4, r0, r5 # write new value
br
#**********************************************************************
#
# NAME: ldsr/mtsr
#
# FUNCTION: load segment register
# mtsr(segreg,segreg_value)
# ldsr(segreg,segreg_value)
#
# NOTES:
# Do not change register usage without updating inline.h
#
# INPUT STATE:
# r3 = segment register number
# r4 = segment register value
#
# OUTPUT STATE:
# The specified segment register is loaded with the input value.
#
# EXECUTION ENVIRONMENT:
# Overlay data for PowerPC
#
#**********************************************************************
.csect mtsr_sect_ppc[RO]
DATA(mtsr_ppc):
.globl DATA(mtsr_ppc)
rlinm r3, r3, 28, 0xF0000000 # generate an effective address
isync
mtsri r4,r0,r3
isync
br
#**********************************************************************
#
# NAME: chgsr_ppc
#
# FUNCTION: change segment register
# chgsr(segreg,segreg_value)
#
# INPUT STATE:
# r3 = segment register number
# r4 = segment register value
#
# NOTES:
# Do not change register usage without updating inline.h
#
# OUTPUT STATE:
# The specified segment register is loaded with the input value.
# The old segement register is returned
#
# EXECUTION ENVIRONMENT:
# Overlay data for PowerPC
#
#**********************************************************************
.csect chgsr_sect_ppc[RO]
DATA(chgsr_ppc):
.globl DATA(chgsr_ppc)
rlinm r5, r3, 28, 0xF0000000 # generate an effective address
mfsrin r3, r5 # read old value
isync
mtsri r4, 0, r5 # write new value
isync
br
#******************************************************************************
#
# NAME: mfsri_ppc
#
# FUNCTION:
# Move from segment register indirect.
#
# NOTES:
# Do not change register usage without updating inline.h
#
# EXECUTION ENVIRONMENT:
# Called though the branch table
#
# INPUT:
# r3 - address whose bits 0-3 form the segment to save
#
# RETURNS:
# r3 - contents of segment reg.
#
#******************************************************************************
.csect mfsri_ppc_overlay[RO]
DATA(mfsri_ppc):
.globl DATA(mfsri_ppc)
mfsrin r3, r3
br
#******************************************************************************
#
# NAME: mfsr_ppc
#
# FUNCTION:
# Move from segment register indirect.
#
# EXECUTION ENVIRONMENT:
# Called though the branch table
#
# NOTES:
# Do not change register usage without updating inline.h
#
# INPUT:
# r3 - seg reg number to read
#
# RETURNS:
# r3 - contents of segment reg.
#
#******************************************************************************
.csect mfsr_ppc_overlay[RO]
DATA(mfsr_ppc):
.globl DATA(mfsr_ppc)
rlinm r3, r3, 28, 0xF0000000 # generate effective address
mfsrin r3, r3
br
#******************************************************************************
#
# NAME: noop_instr_ppc
#
# CALL: None
#
# FUNCTION: contains the overlay data for no-op instructions used no-op
# instructions on Power PC
#
# RETURNS: None
#
#*******************************************************************************
.csect noop_inst_ppc[RO]
.globl noop_inst_ppc[RO]
oriu r0, r0, r0
#*******************************************************************************
#
# NAME: sc_front (PPC Version)
#
# FUNCTION:
# There is one common SVC handler with a machine-dependent
# front end for each architecture. The Power SC vector is
# simply a branch to the common handler. The Power PC SC
# vector must move the move SRR1 to the CTR, and turn
# on translation before branching to the common handler. The
# front ends are overlays set up at system initialization
# time.
#
#*******************************************************************************
.csect sc_front_ppc_overlay[PR]
DATA(sc_front_ppc):
.globl DATA(sc_front_ppc)
lil r12, DISABLED_MSR # disabled msr xlate on
mfspr r11, SRR1 # get old msr value
mtmsr r12 # xlate on
mtctr r11 # put it here for SC flih
ba ENTRY(sc_flih) # common SC handler
.extern ENTRY(sc_flih)
#*******************************************************************************
#
# NAME: cs (PPC version)
#
# FUNCTION:
# The 4.1 cs() implementation is an exported kernel entry
# point. The entry point lies in the machine-dependent
# overlay area. The Power version uses a fast SVC to
# implement an atomic load/store sequence. There is a hook in
# the ds_flih() to handle page faults during cs(). The Power
# PC version uses lwarx/stwcx to perform the the atomic op,
# provided the cs() address is word aligned. Unaligned Power
# PC cs() operations are passed to the cmp_swap() system call.
# This is called through the standards SC handler using a
# system call index (r2) loaded into a global variable at SI
# time. The cmp_swap() system call is serialize access by use
# of a lock.
#
# The cs() system call is not available to kernel extensions.
# This is because it must backup and fabricate a problem state
# MSR when a page fault occurs. The ds_flih must assume the
# cs() caller was in problem state when fabricating the MSR
# (else there is a security hole). This problem is solvable
# with enough work, but it is not felt to be a requirement.
#
# NOTES:
# Do not change without updating overlay.h
#
#*******************************************************************************
.csect cs_ppc_overlay[PR]
DATA(cs_ppc):
.globl DATA(cs_ppc)
andil. r6, r3, 0x3 # check for work aligned address
bne cr0, cs_unalign # branch if not word aligned
cs_again:
lwarx r6, 0, r3 # load word
cmp cr1, r6, r4 # check value
bne cr1, cs_fail # if wrong value then fail
stwcx. r5, 0, r3 # store new value
bne cr0, cs_again # try again
lil r3, 0 # good return code
br # return
cs_fail:
stwcx. r6, 0, r3 # clear reservation
lil r3, 1 # bad return code
br # return
cs_unalign:
l r2, DATA(cmp_swap_index)(0) # sc index
ba ENTRY(svc_instr) # do standard system call
.extern ENTRY(svc_instr)
#******************************************************************************
#
# NAME: al_ppc
#
# CALL: None
#
# FUNCTION: This sequence is copied to 0x600 at system initialization time
# when running on a PPC machine.
#
# NOTES:
# Do not change this function without updating overlay.h
#
# RETURNS : None
#
#******************************************************************************
.csect al_ppc_overlay[PR]
DATA(al_prolog_ppc):
.globl DATA(al_prolog_ppc)
mtspr SPRG1,r15 # save original contents of r15
mfspr r15, SPRG0 # load address of ppda
stm r25, SAVE_R25(r15) # save off 25-31
or r25,r15,r15 # move save address to r25
mfspr r15, SPRG1 # load up original contents of r15
ba ENTRY(al_flih)
.extern ENTRY(al_flih)
#******************************************************************************
#
# NAME: flih_prolog_ppc
#
# CALL: None
#
# FUNCTION: contains the instruction sequence to be placed at interrupt
# vectors on Power machines
#
# RETURNS: None
#
#******************************************************************************
.csect flih_ppc[PR]
DATA(flih_prolog_ppc): # address exported to C code
.globl DATA(flih_prolog_ppc)
mtspr SPRG1, r15 # save a working version
mfspr r15, SPRG0 # get ppda pointer
st r0, ppda_save0(r15) # save a register
ba 0 # branch to flih
#*******************************************************************************
#
# NAME: mtsprgs()
#
# CALL: void mtsprgs(value0, value2, value3)
# int value0; /* value to load into SPRG0 - ppda */
# int value2; /* value to load into SPRG2 - curthread */
# int value3; /* value to load into SPRG3 - csa */
#
# FUNCTION: load sprg0, sprg2 and sprg3
#
# RETURNS: None
#
#*******************************************************************************
S_PROLOG(mtsprgs)
mtspr SPRG0, r3
mtspr SPRG2, r4
mtspr SPRG3, r5
br
#*******************************************************************************
#
# NAME: writedec_vec
#
# FUNCTION:
# write the decrementer interrupt vector and invalidate cache
#
# input:
# r3=data
#
# output: the decrementer interrupt vector is changed.
#
# EXECUTION ENVIRONMENT:
# called by tinit() to allow decrementer interrupts
#
#*******************************************************************************
S_PROLOG(writedec_vec)
#
# DRBIT, 0x10
mfmsr r6 # get current msr
rlinm r7, r6, 0, ~MSR_DR # unset data relocate bit
mtmsr r7 # put it back in msr
isync
lil r4, 0x900 # address of vector
st r3,0(r4) # store word
dcbf 0, r4 # flush/invalidate cache
sync
icbi 0, r4
mtmsr r6 # reset msr to the way it was
isync
br
#*******************************************************************************
#
# NAME: ds_prolog
#
# FUNCTION:
# overlay for dsi flih prolog. The ds/is flihs need a prolog
# that does not alter the save[0] field in the ppda
#
# NOTES:
# Do not change without updating overlay.h
#
# RETUNRS: None
#
#*******************************************************************************
.csect ds_sect_ppc[PR]
DATA(ds_prolog_ppc):
.globl DATA(ds_prolog_ppc)
mtspr SPRG1, r15 # save the value of r15
mfspr r15, SPRG0 # get ppda pointer
ba DATA(ds_flih) # branch to flih
#*******************************************************************************
#
# NAME: is_prolog
#
# FUNCTION:
# overlay for dsi flih prolog. The ds/is flihs need a prolog
# that does not alter the save[0] field in the ppda
#
# NOTES:
# Do not change without updating overlay.h
#
# RETUNRS: None
#
#*******************************************************************************
.csect is_sect_ppc[PR]
DATA(is_prolog_ppc):
.globl DATA(is_prolog_ppc)
mtspr SPRG1, r15 # save the value of r15
mfspr r15, SPRG0
ba DATA(is_flih) # branch to flih
#*******************************************************************************
#
# NAME: dse_prolog
#
# FUNCTION:
# overlay for dsi flih prolog. The DSE flih needs a prolog
# that does not alter the save[0] field in the ppda
#
# NOTES:
# Do not change without updating overlay.h
#
# RETUNRS: None
#
#*******************************************************************************
.csect dse_sect_ppc[PR]
DATA(dse_prolog_ppc):
.globl DATA(dse_prolog_ppc)
ba DATA(dse_flih) # branch to flih
.extern DATA(dse_flih)
',)
.extern DATA(is_flih)
.extern DATA(ds_flih)
include(scrs.m4)
include(low_dsect.m4)
include(machine.m4)
include(systemcfg.m4)