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

292 lines
11 KiB
Plaintext

# @(#)25 1.15 src/bos/kernel/ml/POWER/start.m4, sysml, bos411, 9428A410j 5/31/94 10:25:57
#*****************************************************************************
#
# COMPONENT_NAME: (SYSML) Kernel Assembler Code
#
# FUNCTIONS: start
#
# 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. 1989, 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
#
#****************************************************************************
################################################################################
## ##
## NAME: start ##
## ##
## FUNCTION: Entry point from ROS IPL code ##
## ##
## This routine gains control via a branch from the ROS IPL ##
## code, which passes in GPR 3 a pointer to the IPL Control ##
## block. ##
## This program MUST appear first in the kernel, because its ##
## job is to copy the memory image of the kernel into ##
## its proper place starting at address zero, overlaying the ##
## module header which preceeds the actual executable code. ##
## This header is present because the kernel is just an ordinary ##
## load module built by the ordinary AIX tools; when the ROS IPL ##
## code reads it from disk or diskette into address 0, the header ##
## is at address zero and the code (which logically belongs ##
## at 0) follows it. The header is copied into a kernel data ##
## structure, and the entire kernel image is shifted down to ##
## start at 0. This shift is accomplished by the code at ##
## label "start", below. ##
## ##
## This job is not exactly a trivial ##
## task given that the executing routine must copy itself ##
## as well and make sure that the instruction cache and data ##
## don't get in each other's way while the self-modifying ##
## code is running. ##
## ##
## Here's the plan of attack: ##
## 1) Branch-and-link to discover the actual address at ##
## which "start" begins executing. This will NOT be the ##
## address shown in the assembly listing or load map, ##
## because the code is offset by the length of the header. ##
## 2) Copy the module header into a data structure further ##
## on in the kernel. ##
## 3) Copy the FIRST PART of this routine down to location 0, ##
## using a loop which is located in higher addresses and ##
## thus doesn't get copied yet. ##
## 4) Flush the caches and branch to the newly-moved routine. ##
## 5) Copy the rest of the kernel to the proper place, and ##
## flush the caches again. ##
## 6) Set the front panel LEDs to blanks. ##
## 7) Branch to "start1", which creates a C environment for ##
## the rest of kernel initialization. ##
## ##
################################################################################
.machine "com"
include(iplcb.m4)
start:
# N.B. Do NOT use "ENTRY(start)" because
# the string "start" is the one that
# the kernel build utility will match.
bl start10 # Find out where we are, and branch
# to move loop in SECOND part
# of this routine
start25:
# N.B. this label used at start10 -
# do not move
#*******************************************************************#
# Move latter part of kernel down; this loop gains control #
# AFTER it has been copied down to its final position. #
#*******************************************************************#
start30:
lu r6,4(r2) # Get next 4 bytes to move
stu r6,4(r1) # Move to proper loction
cmp cr0,r2,r0 # Check if all data moved
blt start30
# Now must insure the dcache is stored in memory
andiu. r6,r17,PPC_MODEL
bne cr0,start42 # PPC model
ifdef(`_KDB',`
# nop first(power-pc) branches to millicode routines for early calls
# to millicode. Patch out the PowerPC branch, and allow fall through
# to the Power branch case for Power machines.
# This code depends on the subsequent cache flushes to cover it.
lis r8,0x6000 # NOP instruction (ori 0,0,0)
stw r8,mulh_addr
stw r8,mull_addr
stw r8,divss_addr
stw r8,divus_addr
stw r8,quoss_addr
stw r8,quous_addr
') #endif _KDB
.machine "pwr"
clcs r5,0xe # Get minimum cache line size
.machine "com"
cal r8,imove(0) # Start at end of move routine
sf r8,r5,r8 # Back up one cache line worth
start40:
.machine "pwr"
clf r8,r5 # Flush line containing byte at
# r8+r5, update r8
.machine "com"
cmp cr0,r8,r0 # Check if done
blt start40
dcs # Wait for memory to be updated
ics # Also instruction cache
b start48
# PPC model
# Use one loop to flush dcache, another one to invalidate icache.
# This is necessary because cache line sizes of these two caches may differ
start42:
cal r8,imove(0)
start43: # begin flushing dcache
.machine "ppc"
dcbf 0,r8
.machine "com"
cmp cr0,r8,r0
a r8,r8,r16
blt start43
sync
cal r8,imove(0)
start46: # begin invalidating icache
.machine "ppc"
icbi 0,r8
.machine "com"
cmp cr0,r8,r0
a r8,r8,r15
blt start46
sync
isync
# Branch to "start1"
start48:
.extern ENTRY(start1[PR])
ba ENTRY(start1[PR])
#*******************************************************************#
# N.B. This first loop FOLLOWS the second so the first half of #
# the move never clobbers itself! #
#*******************************************************************#
imove:
.long low_com_start # force a reference to low_com
startakh:
.extern DATA(kernel_header)
.long DATA(kernel_header)
startalkh:
.extern DATA(kernel_header_length)
.long DATA(kernel_header_length)
start10:
mfspr r13,LR # LR contains address of start10
#
# Fix up IPL controll block pointers. Two defined states:
# ROS:
# r3 - iplcb
# ROS EMULATION:
# r3 - -1
# r4 - iplcb
# r5 - extended iplcb
#
# Change to:
# r3 = iplcb
# r4 = extended iplcb or 0 if not present
cmpi cr0, r3, -1 # check for ROS emulation flag
beq cr0, ros_emul # branch if called from ROS emulation
lil r4, 0 # clear extended IPLCB pointer
b ros_done # continue
ros_emul:
mr r3, r4 # r3 = iplcb pointer
mr r4, r5 # r4 = extended iplcb pointer
ros_done:
ai r13,r13,real0-start25 # r13 contains real address of low 0
include(memcheck.m4)
# Set up to move header into kernel_header in loader - we just move
# a lot of bytes so we always get it right!
l r1,startakh(r13) # address of kernel_header
l r2,startalkh(r13) # address of length of kernel_header
lx r2,r2,r13 # length - note use of r13 to relocate
a r1,r1,r13 # relocate kernel_header address
a r2,r1,r2 # compute stopping address
cal r5,-4(r0) # initialize from pointer at -4
start11:
lu r8,4(r5)
st r8,0(r1)
cal r1,4(r1)
cmp cr0,r1,r2
blt start11
# Determine machine model.
# If it is a PPC machine, determine instruction cache line and data cache
# line sizes from iplcb.
# r15: icache line size
# r16: dcache line size
# r17: machine model
l r5,IPLINFO(r3) # offset of ipl_info structure
a r5,r5,r3 # addr of ipl_info structure
l r17,MODEL(r5) # model field in ipl_info structure
andiu. r5,r17,PPC_MODEL # test if PPC model
beq cr0,start12 # not a PPC model
l r5,PROCINFO(r3) # offset of proc_info structure
a r5,r5,r3 # addr of proc_info structure
l r15,ICACHEBK(r5) # icache block size
l r16,DCACHEBK(r5) # dcache block size
# Compute how many bytes to move in order to overlay the header at 0
start12:
l r1,DATA(lowcore_ram_disk_start)(r13) # addr of start of RAM disk
cal r0,-4(r1) # less 4 so we stop in time
cal r1,-4(0) # put -4 in r1; first "stu" will go to 0
ai r2,r13,-4 # set from address -4 to r2
cal r14,imove-real0(0) # compute number of bytes for
# first (short) move
# First move this routine so that we can guarantee the integrity of cache
andiu. r5,r17,PPC_MODEL # test if PPC model
bne cr0,start22 # PPC model
start20:
lu r6,4(r2) # get next 4 bytes to move
stu r6,4(r1) # move to proper location
.machine "pwr"
clf 0,r1 # we can afford to flush every
# store for short move
.machine "com"
cmp cr0,r1,r14 # check if all data moved
blt start20
# If here, the size of the TOC/XCOFF header in bytes has been moved to
# location 0. The kernel remains unchanged above this.
dcs # following example from Appendix C
# of architecture
ics # make sure we get the new values
# just moved above
ba start25 # this instruction will branch to
# the absolute location of start25
start22:
lu r6,4(r2) # get next 4 bytes to move
stu r6,4(r1) # move to proper location
.machine "ppc"
dcbf 0,r1 # flush dcache block
sync
icbi 0,r1 # invalidate icache block
.machine "com"
cmp cr0,r1,r14 # check if all data moved
blt start22
sync
isync
ba start25