MULTICS TECHNICAL BULLETIN 652 page 1
To: Distribution
From: Keith Loepere
Date: March 15, 1984
Subject: New Initialization SDN
What appears here is a proposed rewrite of the
Initialization SDN (AN70). It contains a description of the way
in which Multics is initialized. As such, it contains a
description of the internal operation of bootload Multics, and
therefore, this MTB becomes a companion volume to the bootload
Multics MTB, MTB-651.
This SDN contains a great deal of information about the
process of initialization; it also contains information on what
is initialized, including descriptions of all major system data
bases.
This SDN is being provided in MTB form at this time for two
reasons. First, it contains the technical description of
bootload Multics that is not reproduced within the bootload
Multics MTB. Secondly, it is being provided so that people may
comment upon it, especially to provide technical corrections to
those descriptions for which my understanding was imperfect.
Comments on this MTB should be sent to the author:
Keith Loepere (Loepere.Multics)
or via the bootload_multics or hardcore forums.
________________________________________
Multics Project internal working documentation. Not to be
reproduced or distributed outside the Multics Project.
SYSTEM INITIALIZATION
SYSTEM DESIGNER'S NOTEBOOK
SUBJECT:
Internal Organization of Multics System Initialization
SPECIAL INSTRUCTIONS:
This document supersedes the previous edition of the manual,
order number AN70-00, dated February 1975.
This System Designers' Notebook describes certain internal
modules constituting the Multics System. It is intended as
a reference for only those who are thoroughly familiar with
the implementation details of the Multics operating system;
interfaces described herein should not be used by applica-
tion programmers or subsystem writers; such programmers and
writers are concerned with the external interfaces only.
The external interfaces are described in the Multics
Programmers' Manual, Commands and Active Functions (Order
No. AG92) and Subroutines (Order No. AG93).
As Multics evolves, Honeywell will add, delete, and modify
module descriptions in subsequent SDN updates. Honeywell
does not ensure that the internal functions and internal
module interfaces will remain compatible with previous
versions.
DATE:
03/15/84
ORDER NUMBER:
AN70-01
PREFACE
Multics System Designers' Notebooks (SDNs) are intended for
use by Multics system maintenance personnel, development person-
nel, and others who are thoroughly familiar with Multics internal
system operation. They are not intended for application
programmers or subsystem writers.
The SDNs contain descriptions of modules that serve as
internal interfaces and perform special system functions. These
documents do not describe external interfaces, which are used by
application and system programmers.
This SDN contains a description of the software that
initializes the Multics system. This description is by no means
complete in all its details; for a thorough understanding of
Multics initialization, or of any particular area within this
system, this SDN should be used for reference in conjunction with
the source of the relevant programs.
(C) Honeywell Information Systems Inc., 1984 File No.: 2L13
In addition to this manual, the volumes of the Multics
Programmers' Manual (MPM) should be referred to for details of
software concepts and organization, external interfaces, and for
specific usage of Multics Commands and subroutines. These
volumes are:
MPM Reference Guide, Order No. AG91
MPM Commands and Active Functions, Order No. AG92
MPM Subroutines, Order No. AG93
CONTENTS
Page
Section 1 Summary of Initialization . . . . . . . . 1-1
Hardware and PL/1 Environment
initialization . . . . . . . . . . . 1-2
Page Control initialization . . . . . 1-2
File System initialization . . . . . . 1-3
Outer ring Environment initialization 1-3
Bootload Command Environment (bce) . . 1-3
Crash Handler (toehold) . . . . . . . 1-4
Section 2 Collection 0 . . . . . . . . . . . . . . 2-1
Getting started . . . . . . . . . . . 2-1
Programming in Collection 0 . . . . . 2-2
Module Descriptions . . . . . . . . . 2-2
bootload_abs_mode.alm . . . . . . . 2-2
bootload_0.alm . . . . . . . . . . 2-3
The firmware collection. . . . . . 2-3
bootload_console.alm . . . . . . . 2-4
bootload_dseg.alm . . . . . . . . . 2-4
bootload_early_dump.alm . . . . . . 2-5
bootload_error.alm . . . . . . . . 2-5
bootload_faults.alm . . . . . . . . 2-5
bootload_flagbox.alm . . . . . . . 2-6
bootload_formline.alm . . . . . . . 2-6
bootload_info.cds . . . . . . . . . 2-6
bootload_io.alm . . . . . . . . . . 2-6
bootload_linker.alm . . . . . . . . 2-7
bootload_loader.alm . . . . . . . . 2-7
bootload_slt_manager.alm . . . . . 2-7
bootload_tape_fw.alm . . . . . . . 2-8
template_slt_.alm . . . . . . . . . 2-8
Section 3 Collection 1 . . . . . . . . . . . . . . 3-1
Summary of Collection 1 Passes . . . . 3-1
normal (boot) pass . . . . . . . . . . 3-2
service pass . . . . . . . . . . . . . 3-4
early pass . . . . . . . . . . . . . . 3-5
crash pass . . . . . . . . . . . . . . 3-7
re_early pass . . . . . . . . . . . . 3-7
bce_crash pass . . . . . . . . . . . . 3-7
shut pass . . . . . . . . . . . . . . 3-7
Module Descriptions . . . . . . . . . 3-8
CONTENTS (cont)
Page
announce_chwm.pl1 . . . . . . . . . 3-8
boot_rpv_subsystem.pl1 . . . . . . 3-8
boot_tape_io.pl1 . . . . . . . . . 3-8
bootload_1.alm . . . . . . . . . . 3-8
collect_free_core.pl1 . . . . . . . 3-9
create_rpv_partition.pl1 . . . . . 3-9
delete_segs.pl1 . . . . . . . . . . 3-9
disk_reader.pl1 . . . . . . . . . . 3-9
establish_config_deck.pl1 . . . . . 3-10
fill_vol_extents_.pl1 . . . . . . . 3-10
find_rpv_subsystem.pl1 . . . . . . 3-10
get_io_segs.pl1 . . . . . . . . . . 3-11
get_main.pl1 . . . . . . . . . . . 3-11
hc_load_mpc.pl1 . . . . . . . . . . 3-11
init_aste_pools.pl1 . . . . . . . . 3-12
init_clocks.pl1 . . . . . . . . . . 3-12
init_early_config.pl1 . . . . . . . 3-12
init_empty_root.pl1 . . . . . . . . 3-12
init_hc_part.pl1 . . . . . . . . . 3-13
init_partitions.pl1 . . . . . . . . 3-13
init_pvt.pl1 . . . . . . . . . . . 3-13
init_root_vols.pl1 . . . . . . . . 3-13
init_scu.pl1 . . . . . . . . . . . 3-13
init_sst.pl1 . . . . . . . . . . . 3-14
init_vol_header_.pl1 . . . . . . . 3-14
initial_error_handler.pl1 . . . . . 3-14
initialize_faults.pl1 . . . . . . . 3-15
initialize_faults_data.cds . . . . 3-15
initializer.pl1 . . . . . . . . . . 3-15
iom_data_init.pl1 . . . . . . . . . 3-16
load_disk_mpcs.pl1 . . . . . . . . 3-16
load_mst.pl1 . . . . . . . . . . . 3-16
make_sdw.pl1 . . . . . . . . . . . 3-16
make_segs_paged.pl1 . . . . . . . . 3-17
move_non_perm_wired_segs.pl1 . . . 3-17
ocdcm_.pl1 . . . . . . . . . . . . 3-18
prds_init.pl1 . . . . . . . . . . . 3-18
pre_link_hc.pl1 . . . . . . . . . . 3-18
read_disk.pl1 . . . . . . . . . . . 3-19
read_disk_label.pl1 . . . . . . . . 3-19
real_initializer.pl1.pmac . . . . . 3-19
scas_init.pl1 . . . . . . . . . . . 3-20
scs_and_clock_init.pl1 . . . . . . 3-20
segment_loader.pl1 . . . . . . . . 3-20
slt_manager.pl1 . . . . . . . . . . 3-21
sys_info.cds . . . . . . . . . . . 3-21
tape_reader.pl1 . . . . . . . . . . 3-21
tc_init.pl1 . . . . . . . . . . . . 3-21
CONTENTS (cont)
Page
Section 4 The Bootload Command Environment . . . . 4-1
Initialization . . . . . . . . . . . . 4-1
Environment and facilities . . . . . . 4-1
Restrictions . . . . . . . . . . . . . 4-3
Module descriptions . . . . . . . . . 4-4
bce_alert.pl1 . . . . . . . . . . . 4-4
bce_alm_die.alm . . . . . . . . . . 4-4
bce_appending_simulation.pl1 . . . 4-4
bce_check_abort.pl1 . . . . . . . . 4-5
bce_command_processor_.pl1 . . . . 4-6
bce_console_io.pl1 . . . . . . . . 4-6
bce_continue.pl1 . . . . . . . . . 4-7
bce_data.cds . . . . . . . . . . . 4-7
bce_die.pl1 . . . . . . . . . . . . 4-7
bce_display_instruction_.pl1 . . . 4-7
bce_display_scu_.pl1 . . . . . . . 4-7
bce_dump.pl1 . . . . . . . . . . . 4-7
bce_error.pl1 . . . . . . . . . . . 4-8
bce_esd.pl1 . . . . . . . . . . . . 4-8
bce_exec_com_.pl1 . . . . . . . . . 4-8
bce_exec_com_input.pl1 . . . . . . 4-9
bce_execute_command_.pl1 . . . . . 4-9
bce_fwload.pl1 . . . . . . . . . . 4-9
bce_get_flagbox.pl1 . . . . . . . . 4-10
bce_get_to_command_level.pl1 . . . 4-10
bce_inst_length_.pl1 . . . . . . . 4-10
bce_list_requests_.pl1 . . . . . . 4-10
bce_listen_.pl1 . . . . . . . . . . 4-11
bce_map_over_requests_.pl1 . . . . 4-11
bce_name_to_segnum_.pl1 . . . . . . 4-11
bce_probe.pl1.pmac . . . . . . . . 4-11
Request routines . . . . . . . . 4-12
Internal Routines . . . . . . . 4-13
bce_probe_data.cds . . . . . . . . 4-14
bce_probe_fetch_.pl1 . . . . . . . 4-14
bce_query.pl1 . . . . . . . . . . . 4-14
bce_ready.pl1 . . . . . . . . . . . 4-15
bce_relocate_instruction_.pl1 . . . 4-15
bce_request_table_.alm . . . . . . 4-15
bce_severity.pl1 . . . . . . . . . 4-15
bce_shutdown_state.pl1 . . . . . . 4-15
bootload_disk_post.pl1 . . . . . . 4-15
bootload_fs_.pl1 . . . . . . . . . 4-16
bootload_fs_cmds_.pl1 . . . . . . . 4-16
bootload_qedx.pl1 . . . . . . . . . 4-16
config_deck_data_.cds . . . . . . . 4-16
config_deck_edit_.pl1 . . . . . . . 4-17
establish_temp_segs.pl1 . . . . . . 4-17
CONTENTS (cont)
Page
find_file_partition.pl1 . . . . . . 4-17
init_bce.pl1 . . . . . . . . . . . 4-18
Section 5 Crash Handling . . . . . . . . . . . . . 5-1
Early Crashes . . . . . . . . . . . . 5-1
The toehold . . . . . . . . . . . . . 5-1
Module Descriptions . . . . . . . . . 5-2
fim.alm . . . . . . . . . . . . . . 5-2
init_toehold.pl1 . . . . . . . . . 5-2
save_handler_mc.alm . . . . . . . . 5-2
Section 6 Collection 2 . . . . . . . . . . . . . . 6-1
Order of execution . . . . . . . . . . 6-1
Module Descriptions . . . . . . . . . 6-3
accept_fs_disk.pl1 . . . . . . . . 6-3
accept_rpv.pl1 . . . . . . . . . . 6-3
create_root_dir.pl1 . . . . . . . . 6-4
create_root_vtoce.pl1 . . . . . . . 6-4
dbm_man.pl1 . . . . . . . . . . . . 6-4
dir_lock_init.pl1 . . . . . . . . . 6-4
fnp_init.pl1 . . . . . . . . . . . 6-4
getuid.alm . . . . . . . . . . . . 6-5
init_branches.pl1 . . . . . . . . . 6-5
init_dm_journal_seg.pl1 . . . . . . 6-6
init_hardcore_gates.pl1 . . . . . . 6-6
init_lvt.pl1 . . . . . . . . . . . 6-6
init_processor.alm . . . . . . . . 6-6
init_root_dir.pl1 . . . . . . . . . 6-7
init_scavenger_data.pl1 . . . . . . 6-7
init_sst_name_seg.pl1 . . . . . . . 6-7
init_stack_0.pl1 . . . . . . . . . 6-7
init_str_seg.pl1 . . . . . . . . . 6-8
init_sys_var.pl1 . . . . . . . . . 6-8
init_volmap_seg.pl1 . . . . . . . . 6-8
init_vtoc_man.pl1 . . . . . . . . . 6-9
initialize_faults.pl1 . . . . . . . 6-9
kst_util.pl1 . . . . . . . . . . . 6-9
start_cpu.pl1 . . . . . . . . . . . 6-9
syserr_log_init.pl1 . . . . . . . . 6-9
tc_init.pl1 . . . . . . . . . . . . 6-10
Section 7 Collection 3 . . . . . . . . . . . . . . 7-1
Order of Execution . . . . . . . . . . 7-1
Module Descriptions . . . . . . . . . 7-1
init_proc.pl1 . . . . . . . . . . . 7-1
ioi_init.pl1 . . . . . . . . . . . 7-2
ioi_page_table.pl1 . . . . . . . . 7-2
load_system.pl1 . . . . . . . . . . 7-2
CONTENTS (cont)
Page
tc_init.pl1 . . . . . . . . . . . . 7-2
Section 8 Mechanisms . . . . . . . . . . . . . . . 8-1
Hardcore Segment Creation . . . . . . 8-1
Page Control Initialization . . . . . 8-3
Segment and Directory Control
Initialization . . . . . . . . . . . 8-4
Segment Number Assignment . . . . . . 8-5
Traffic Control Initialization . . . . 8-6
Section 9 Shutdown and Emergency Shutdown . . . . . 9-1
Order of Execution of Shutdown . . . . 9-1
Order of Execution of Emergency
Shutdown . . . . . . . . . . . . . . 9-3
Module Descriptions . . . . . . . . . 9-4
deactivate_for_demount.pl1 . . . . 9-4
demount_pv.pl1 . . . . . . . . . . 9-5
disk_emergency.pl1 . . . . . . . . 9-5
emergency_shutdown.alm . . . . . . 9-5
fsout_vol.pl1 . . . . . . . . . . . 9-6
scavenger.pl1 . . . . . . . . . . . 9-6
shutdown.pl1 . . . . . . . . . . . 9-6
shutdown_file_system.pl1 . . . . . 9-7
switch_shutdown_file_system.alm . . 9-7
tc_shutdown.pl1 . . . . . . . . . . 9-7
wired_shutdown.pl1 . . . . . . . . 9-7
Appendix A Glossary . . . . . . . . . . . . . . . . A-1
Appendix B Initialization and Initialized Data Bases B-1
ai_linkage (active init linkage) . . . B-1
as_linkage (active supervisor linkage) B-1
bce_data (bootload command environment
data) . . . . . . . . . . . . . . . . B-1
bootload_info . . . . . . . . . . . . B-1
config_deck . . . . . . . . . . . . . B-2
core_map . . . . . . . . . . . . . . . B-2
dbm_seg (dumper bit map seg) . . . . . B-2
dir_lock_seg . . . . . . . . . . . . . B-3
disk_post_queue_seg . . . . . . . . . B-3
disk_seg . . . . . . . . . . . . . . . B-3
dm_journal_seg_ . . . . . . . . . . . B-4
dn355_data . . . . . . . . . . . . . . B-4
dn355_mailbox . . . . . . . . . . . . B-4
dseg (descriptor segment) . . . . . . B-4
fault_vector (fault and interrupt vec-
tors) . . . . . . . . . . . . . . . . B-5
flagbox . . . . . . . . . . . . . . . B-5
CONTENTS (cont)
Page
inzr_stk0 (initializer stack) . . . . B-5
int_unpaged_page_tables . . . . . . . B-6
io_page_tables . . . . . . . . . . . . B-6
ioi_data . . . . . . . . . . . . . . . B-6
iom_data . . . . . . . . . . . . . . . B-6
iom_mailbox . . . . . . . . . . . . . B-7
kst (known segment table) . . . . . . B-7
lvt (logical volume table) . . . . . . B-7
name_table . . . . . . . . . . . . . . B-8
oc_data . . . . . . . . . . . . . . . B-8
physical_record_buffer . . . . . . . . B-8
pvt (physical volume table) . . . . . B-8
scas (system controller addressing
segment) . . . . . . . . . . . . . . B-9
scavenger_data . . . . . . . . . . . . B-9
scs (system communications segment) . B-9
slt (segment loading table) . . . . . B-10
sst (system segment table) . . . . . . B-10
sst_names_ . . . . . . . . . . . . . . B-10
stack_0_data . . . . . . . . . . . . . B-11
stock_seg . . . . . . . . . . . . . . B-11
str_seg (system trailer segment) . . . B-11
sys_info . . . . . . . . . . . . . . . B-11
sys_boot_info . . . . . . . . . . . . B-12
syserr_data . . . . . . . . . . . . . B-12
syserr_log . . . . . . . . . . . . . . B-12
tc_data . . . . . . . . . . . . . . . B-12
tc_data_header . . . . . . . . . . . . B-13
toehold . . . . . . . . . . . . . . . B-13
tty_area . . . . . . . . . . . . . . . B-13
tty_buf . . . . . . . . . . . . . . . B-13
tty_tables . . . . . . . . . . . . . . B-14
unpaged_page_tables . . . . . . . . . B-14
vtoc_buffer_seg . . . . . . . . . . . B-14
wi_linkage (wired init linkage) . . . B-14
wired_hardcore_data . . . . . . . . . B-14
ws_linkage (wired supervisor linkage) B-15
Appendix C Memory Layout . . . . . . . . . . . . . . C-1
Index . . . . . . . . . . . . . . . . . . . . . i-1
SECTION 1
SUMMARY OF INITIALIZATION
Multics initialization, as described in this SDN, can be
thought of as divided into the following parts:
* Hardware and PL/1 Environment initialization (Collec-
tion 0)
* Page Control initialization (Collection 1 service pass)
* Bootload Command Environment (bce) (Collection 1 multi-
ple passes)
* Crash Handler (toehold)
* File System initialization (Collection 2)
* Outer ring Environment initialization (Collection 3)
The parts listed before collection 2 are collectively called
"Bootload Multics."
A collection is simply a set of initialization routines
that are read in and placed into operation as a unit to perform a
certain set, or a certain subset, of the tasks required to
initialize a portion of the Multics supervisor. Each collection
consists of a distinct set of programs for reasons discussed
throughout this SDN. Even though each collection mostly exists
to perform a particular set of functions, they are normally
referred to by their number (which have only historical signifi-
cance) rather than the name of their function.
Initialization may also be thought of as having three
separate functions:
Bringing up the system
This role is obvious. The description of this role
follows along the functions needed to perform it. Each
portion of initialization runs, utilizing the efforts
of the previous portions to build up more and more
mechanism until service Multics itself can run.
Providing a command environment before the file system is
activated from which to perform configuration and disk
maintenance functions
Providing an environment to which service Multics may crash
which is capable of taking a dump of Multics and
initiating recovery and reboot operations
These last two functions are the role of bootload Multics
(bce). They take advantage of the fact that during
initialization an environment is built that has certain
facilities that allow operations such as disk manipulation to
occur but it is an environment in which the disks themselves are
not yet active for storage system operations. This environment,
at an intermediate point in initialization, forms the bootload
command environment (bce).
The bootload command environment is saved before further
initialization operations occur. When service Multics crashes,
service Multics is saved and this bce "crash" environment is
restored. This safe environment can then examine or dump the
service Multics image and perform certain recovery and restart
operations without relying on the state of service Multics.
HARDWARE AND PL/1 ENVIRONMENT INITIALIZATION
The purpose of collection 0 is to set up the pl/1
environment and to start collection 1. It has a variety of
interesting things to perform in the process. First of all,
collection 0 must get itself running. When Multics is booted
from BOS, this is an easy matter, since BOS will read in the
beginning of collection 0, leaving the hardware in a known and
good state and providing a description of the configuration
(config_deck) around. When not booted from BOS, that is, when
booted via the IOM boot function, collection 0 has the task of
getting the hardware into a good and known state and finding out
on what hardware it is working. Once collection 0 has set up the
hardware, it can load collection 1 into memory. Collection 1
contains the modules needed to support programs written in pl/1;
thus, this loading activates the pl/1 environment. After this
time, more sensible programs can run and begin the true process
of initialization. The result of this collection is to provide
an environment in which pl/1 programs can run, within the
confines of memory.
PAGE CONTROL INITIALIZATION
The main task of collection 1 is to make page control
operative. This is necessary so that we may page the rest of the
initialization programs (initialization programs all have to fit
into memory until this is done). The initialization of page
control involves setting up all of the disk and page control data
bases. Also, the interrupt mechanism must be initialized. The
result of this collection is to provide an environment in which
i/o devices may be operated upon through normal mechanisms (i.e.,
via page faults or direct calls to the standard device control
modules) but in which the storage system is not active. At the
final end of collection 1, this environment becomes paged, using
a special region of the disks (the hardcore partition) so that
the storage system is not affected.
Collection 1 can be run multiple times. The effect of
making a pass through collection 1 is to set up the device tables
(and general configuration describing tables) to reflect a new
configuration. The various passes of collection 1 are the key to
the operation of bce. There are several times when the running
of collection 1 is necessary. It is necessary when we first
start up, to allow accessing the hardware units "discovered" by
collection 0. Once the correct configuration is determined via
bce activities, collection 1 must be re-run to allow all of the
devices to be accessible during the rest of initialization and
Multics service proper. Finally, when the crash environment is
restored (see below), another pass must be made to provide
accessibility to the devices given the state at the time of the
crash.
FILE SYSTEM INITIALIZATION
With paging active, collection 2 can be read into a paged
environment. Given this environment, the major portion of the
rest of initialization occurs. Segment, directory and traffic
control are initialized here, making the storage system accessi-
ble in the process. The result of this collection is an
environment that has active virtually all hardcore mechanisms
needed by the rest of Multics.
OUTER RING ENVIRONMENT INITIALIZATION
Collection 3 is basically a collection of those facilities
that are required to run in outer rings. In particular, it
contains the programs needed to provide the initializer's ring
one environment, especially the code to perform a reload of the
system (especially the executable libraries). After the execu-
tion of this collection, the Initializer enters into a ring one
command environment, ready to load the system (if necessary) and
start up the answering service. (Activities performed from ring
one onward are not covered in this SDN.)
BOOTLOAD COMMAND ENVIRONMENT (BCE)
The bootload command environment is an environment that can
perform configuration and disk management functions. It needs to
be able to support i/o to devices in a pl/1 environment. Also,
since bce must be able to operate on arbitrary disks, it must be
capable of running before the storage system is active. Thus, it
is equivalent to the collection 1 environment before the environ-
ment becomes paged. In this environment, built by a special run
of collection 1, a series of facilities provides a command
environment that allows pl/1 programs to run in a manner similar
to their operation in the normal Multics programming environment.
CRASH HANDLER (TOEHOLD)
When Multics has crashed, Multics is incapable of
performing the types of analysis and recovery operations desired
in its distressed state. Thus, a safe environment is invoked to
provide these facilities. Since bce is capable of accessing
memory and disks independently of the storage system (and the
hardcore partitions), it becomes the obvious choice for a crash
environment. When Multics crashes, bce is restored to operation.
Facilities within bce can perform a dump of Multics as well as
start recovery and reboot operations. The crash environment
consists of the mechanisms needed to save the state of Multics
upon a crash and to re-setup the bootload command environment.
These mechanisms must work in the face of varying types of system
failures; they must also work given the possibility of hardware
reconfiguration since the time the safe environment was saved.
SECTION 2
COLLECTION 0
Collection 0 in Bootload Multics is an ensemble of ALM
programs capable of being booted from BOS or the IOM, reading
themselves off of the boot tape, loading tape firmware if needed,
setting up an I/O and error handling environment, and loading
collection 1.
Collection 0 is organized into two modules:
bootload_tape_label, and bound_bootload_0. The first is an MST
label program designed to read the second into its correct memory
location, after being read in by the IOM bootload program. The
second is a bound collection of ALM programs. bound_bootload_0
takes extensive advantage of the binder's ability to simulate the
linker within a bound unit. The programs in bound_bootload_0 use
standard external references to make intermodule references, and
the binder, rather than any run-time linker or pre-linker,
resolves them to TSR-relative addresses. Any external references
(such as to the config deck) are made with explicit use of the
fact that segment numbers for collection 0 programs are fixed at
assembly time.
GETTING STARTED
bootload_tape_label is read in by one of two means. In
native mode, the IOM or IIOC reads it into absolute location 30,
leaving the PCW, DCW's, and other essentials in locations 0
through 5. The IIOC leaves an indication of its identity just
after this block of information.
In BOS compatibility mode, the BOS BOOT command simulates
the IOM, leaving the same information. However, it also leaves a
config deck and flagbox (although bce has its own flagbox) in the
usual locations. This allows Bootload Multics to return to BOS
if there is a BOS to return to. The presence of BOS is indicated
by the tape drive number being non-zero in the idcw in the "IOM"
provided information.
The label overlays the interrupt vectors for the first two
IOM's. Because the label is formatted as a Multics standard tape
record, it has a trailer that cannot be changed. This trailer
overlays the interrupt vectors for channels B9 and B10. Without
a change in the label format, the bootload tape controller cannot
use either of these channels as a base channel, because the label
record wipes out the vectors that the IOM bootload programs sets
up. This prevents control from transferring to the label
program.
The label program first initializes the processor by
loading the Mode Register and the Cache Mode Register, and
clearing and enabling the PTWAM and the SDWAM. It then reads all
of bound_bootload_0 off the tape. This action places the toehold
and bootload_early_dump into their correct places in memory, in
as much as these two modules are bound to be the first two
objects in bound_bootload_0. If this is successful, it transfers
to the beginning of bootload_abs_mode through an entry in the
toehold. (This entry contains the address of bootload_abs_mode,
via the linking performed by the binder.) This program copies
the template descriptor segment assembled into template_slt_ to
the appropriate location, copies int_unpaged_page_tables and
unpaged_page_tables to their correct locations, loads the DSBR
and the pointer registers, enters appending mode, and transfers
to bootload_0.
PROGRAMMING IN COLLECTION 0
Collection 0 programs are impure assembly language pro-
grams. The standard calling sequence is with the tsx2 instruc-
tion. A save stack of index register 2 values is maintained
using id and di modifiers, as in traffic control. Programs that
take arguments often have an argument list following the tsx2
instruction. Skip returns are used to indicate errors.
The segment bootload_info, a cds program, is the repository
of information that is needed in later stages of initialization.
This includes tape channel and device numbers and the like. The
information is copied into the collection 1 segment sys_boot_info
when collection 1 is read in.
MODULE DESCRIPTIONS
bootload_abs_mode.alm
As mentioned above, bootload_abs_mode is the first program
to run in bound_bootload_0. The label program locates it by
virtue of a tra instruction at a known place in the toehold
(whose address is fixed); the tra instruction having been fixed
by the binder. It first clears the memory used by the Collection
0 data segments, then copies the template descriptor segment,
int_unpaged_page_tables and unpaged_page_tables from
template_slt_. The DSBR is loaded with the descriptor segment
SDW, the pointer registers are filled in from the ITS pointers in
template_slt_, and appending mode is entered. bootload_abs_mode
then transfers control to bootload_0$begin, the basic driver of
collection zero initialization.
bootload_0.alm
bootload_0's contract is to set up the I/O, fault, and
console services, and then load and transfer control to collec-
tion 1. As part of setting up the I/O environment, it must load
tape firmware in the bootload tape MPC if BOS is not present.
bootload_0 makes a series of tsx2 calls to set up each of these
facilities in turn. It calls bootload_io$preinit to interpret
the bootload program left in low memory by the IOM/IIOC/IOX,
including checking for the presence of BOS;
bootload_flagbox$preinit to set flagbox flags according to the
presence of BOS; bootload_faults$init to fill in the fault
vector; bootload_slt_manager$init_slt to copy the data from
template_slt_ to the SLT and name_table; bootload_io$init to set
up the I/O environment; bootload_console$init to find a working
console and initialize the console package; bootload_loader$init
to initialize the MST loading package; bootload_tape_fw$boot to
read the tape firmware and load it into the bootload tape
controller; bootload_loader$load_collection to load Collection
1.0; bootload_loader$finish to copy the MST loader housekeeping
pointers to their permanent homes; and bootload_linker$prelink to
snap all links in Collection 1.0.
Finally, the contents of bootload_info are copied into
sys_boot_info. Control is then transferred to bootload_1.
The firmware collection.
As described below under the heading of
"bootload_tape_fw.alm", tape firmware must be present on the MST
as ordinary segments. It must reside in the low 256K, because
the MPC's do not implement extended addressing for firmware
loading. The tape firmware segments are not needed after the MPC
is loaded, so it is desired to recycle their storage. It is
desired to load the MPC before collection 1 is loaded, so that
backspace error recovery can be used when reading the tape. The
net result is that they need to be a separate collection. To
avoid destroying the old correspondence between collection num-
bers and sys_info$initialization_state values, this set exists as
a sub-collection. The tape firmware is collection 0.5, since it
is loaded before collection 1. The segments in collection 0.5
have a fixed naming convention. Each must include among its set
of names a name of the form "fwid.Tnnn", where "Tnnn" is a four
character controller type currently used by the BOS FWLOAD
facility. These short names are retained for two reasons.
First, they are the controller types used by Field Engineering.
Second, there is no erase and kill processing on input read in
this environment, so that short strings are advantageous. Note
that if the operator does make a typo and enters the wrong
string, the question is asked again.
bootload_console.alm
bootload_console uses bootload_io to do console I/O. Its
initialization entry, init, finds the console on the bootload
IOM. This is done by first looking in the config deck, if BOS
left us one, or, if not, by trying to perform a 51 (Write Alert)
comment to each channel in turn). Only console channels respond
to this command. When a console is found, a 57 (Read ID) command
is used to determine the model.
The working entrypoints are write, write_nl, write_alert,
and read_line. write_nl is provided as a convenience. All of
these take appropriate buffer pointers and lengths. Read_line
handles timeout and operator error statuses.
There are three types of console that bootload_console must
support. The first is the original EMC, CSU6001. It requires
all its device commands to be specified in the PCW, and ignores
IDCW's. The second is the LCC, CSU6601. It will accept commands
in either the PCW or IDCW's. The third type is the IPC-CONS-2.
In theory, it should be just like the LCC except that it does NOT
accept PCW device commands. Whether or not it actually meets
this specification has yet to be determined.
To handle the two different forms of I/O (PCW commands
versus IDCW's), bootload_console uses a table of indirect words
pointing to the appropriate PCW and DCW lists for each operation.
The indirect words are setup at initialization time. The LCC is
run with IDCW's to exercise the code that is expected to run on
the IPC-CONS-2.
bootload_dseg.alm
bootload_dseg's task is to prepare SDW's for segments
loaded by bootload_loader, the collection zero loader.
bootload_dseg$make_sdw takes as an argument an sdw_info structure
as used by sdw_util_, and constructs and installs the SDW. The
added entrypoint bootload_dseg$make_core_ptw is used by
bootload_loader to generate the page table words for the unpaged
segments that it creates.
bootload_early_dump.alm
When an error occurs during early initialization,
bootload_early_dump is called. It is called in three ways.
First, if bootload_error is called for an error (as opposed to a
warning), this routine is called. Secondly, if a crash should
occur later in initialization (after collection 0) but before the
toehold is set up (and bce running), the toehold will transfer
here. Third, the operator can force a transfer to this routine
through processor switches any time up until collect_free_core
runs. (This includes while bce is running.) This is done by
force executing a "tra 30000o" instruction.
bootload_early_dump starts by reestablishing the collection
0 environment (masked, pointer registers appropriately set,
etc.). It then uses bootload_console to ask for the number of a
tape drive on the bootload tape controller to use for the dump.
When it gets a satisfactory answer, it dumps the first 512k of
memory (that used by early initialization and bce), one record at
a time, with a couple of miscellaneous values used by
read_early_dump_tape (which constructs a normal format dump). If
an error occurs while writing a record, the write is simply
retried (no backspace or other error recovery). After 16
consecutive errors, the dump is aborted, a status message
printed, and a new drive number requested.
bootload_error.alm
bootload_error is responsible for all the error messages in
collection 0. It is similar in design to page_error.alm; there
is one entrypoint per message, and macros are used to construct
the calls to bootload_formline and bootload_console.
bootload_error also contains the code to transfer to
bootload_early_dump. There are two basic macros used: "error",
which causes a crash with message, and "warning", which prints
the message and returns. All the warnings and errors find their
parameters via external references rather than with call parame-
ters. This allows tra's to bootload_error to be put in error
return slots, like:
tsx2 read_word
tra bootload_error$console_error
" error, status in
" bootload_console$last_error_status
... " normal return
Warnings are called with tsx2 calls.
bootload_faults.alm
bootload_faults sets up the segment fault_vector. All
faults except timer runout are set to transfer to
bootload_error$unexpected_fault. All interrupts are set to
transfer control to bootload_error$unexpected_interrupt, since no
interrupts are used in the collection zero environment. The same
structure of transfers through indirect words that is used in the
service fault environment is used to allow individual faults to
be handled specially by changing a pointer rather than
constructing a different tra instruction (also, instructions do
not allow "its" pointers within them). The structure of the
scu/tra pairs (but not the values of the pointers) formed by
bootload_faults is that used by the rest of initialization and
service.
bootload_flagbox.alm
bootload_flagbox zeroes the bce flagbox. It also zeroes
the cold_disk_mpc flag when BOS is present for historical
reasons. Various values are placed in the flagbox that no one
looks at.
bootload_formline.alm
This program is a replacement for the BOS erpt facility.
It provides string substitutions with ioa_-like format controls.
It handles octal and decimal numbers, BCD characters, ascii in
units of words, and ACC strings. Its only client is
bootload_error, who uses it to format error message. The BCD
characters are used to print firmware ID's found in firmware
images. Its calling sequence is elaborate, and a macro,
"formline", is provided in bootload_formline.incl.alm
bootload_info.cds
The contents of this segment are described under data
bases.
bootload_io.alm
bootload_io is an io package designed to run on IOM's and
IIOC's. It has entrypoints to connect to channels with and
without timeouts. It always waits for status after a connection.
It runs completely using abs mode i/o, and its callers must fill
in their DCW lists with absolute addresses. This is done because
NSA IOM's do not support rel mode when set in PAGED mode, and
there is no known way to find out whether an IOM is in paged
mode. Under normal operation, the config card for the IOM is
available to indicate whether the IOM is in paged mode or not,
relieving this difficulty.
The preinit entrypoint is called as one of the first
operations in collection 0. Besides setting up for i/o, it
copies and determines from the IOM/IIOC/BOS provided boot info
the assume_config_deck (BOS present) flag and the system_type
value.
bootload_linker.alm
bootload_linker is responsible for snapping all links
between collection one segments. It walks down the LOT looking
for linkage sections to process. For each one, it considers each
link and snaps it. It uses bootload_slt_manager$get_seg_ptr to
find external segments and implements its own simple definitions
search.
bootload_loader.alm
bootload_loader is the collection zero loader (of collec-
tions 0.5 and 1). It has entrypoints to initialize the tape
loader (init), load a collection (load_collection), skip a
collection (skip_collection), and clean up (finish). The loader
is an alm implementation of segment_loader.pl1, the collection 1
loader. It reads records from the mst, analyzes them, splitting
them into slt entries, definitions and linkage sections, and
segment contents. Memory is obtained for the segment contents
using allocation pointers in the slt. Page tables are allocated
for the segment within the appropriate unpaged_page_tables seg-
ment. When proper, the breakpoint_page is added as another page
to the end of the segment. Definitions and linkage sections are
added to the end of the proper segments (ai_linkage, wi_linkage,
ws_linkage, as_linkage). The loader has a table of special
segments whose segment numbers (actually ITS pointers) are
recorded as they are read in off of the tape. These include the
hardcore linkage segments, needed to load linkage sections,
definitions_, and others. The loader maintains its current
allocation pointers for the linkage and definitions segments in
its text. bootload_loader$finish copies them into the headers of
the segments where segment_loader expects to find them.
bootload_slt_manager.alm
bootload_slt_manager is responsible for managing the Seg-
ment Loading Table (SLT) for collection zero. It has three
entries. bootload_slt_manager$init_slt copies the SLT and name
table templates from template_slt_ to the slt and name_table
segments. bootload_slt_manager$build_entry is called by
bootload_loader to allocate a segment number and fill in the SLT
and name table from the information on the MST.
bootload_slt_manager$get_seg_ptr is called by bootload_linker to
search the SLT for a given name. It has imbedded in it a copy of
hash_index_ used to maintain a hashed list of segment names
compatible with the list for slt_manager in further collections.
bootload_tape_fw.alm
bootload_tape_fw is responsible for loading the bootload
tape MPC. It begins by loading collection 0.5 into memory with a
call to bootload_loader$load_collection. By remembering the
value of slt.last_init_seg before this call, bootload_tape_fw can
tell the range in segment numbers of the firmware segments.
Firmware segments are assigned init_seg segment numbers by
bootload_loader, but are loaded low in memory, for reasons
described above. bootload_tape_fw then determines the correct
firmware type. If bootload_info specifies the controller type,
then it proceeds to search the SLTE names of the firmware
segments for the appropriate firmware. If bootload_info does not
specify the firmware type, then bootload_tape_fw must ask the
operator to supply a controller type. This is because there is
no way to get a controller to identify itself by model.
Each of the firmware segments has as one of its SLTE names
(specified in the MST header) the six character MPC type for
which it is to be used. bootload_tape_fw walks the slt looking
for a firmware segment with the correct name. If it cannot find
it, it re-queries (or queries for the first time) the operator
and tries again.
Having found the right firmware, the standard MPC bootload
sequence is initiated to boot the tape MPC. The firmware
segments' SDW's are zeroed, and the slt allocation pointers
restored to their pre-collection-0.5 values. bootload_tape_fw
then returns.
template_slt_.alm
This alm program consists of a group of involved macros
that generate the SLTE's for the segments of collection zero. It
is NOT an image of the segment slt, because that would include
many zero SLTE's between the last sup seg in collection zero and
the first init seg. Instead, the init seg SLTE's are packed in
just above the sup segs, and bootload_slt_manager$init_slt
unpacks them. It also contains the template descriptor segment,
packed in the same manner, and the template name table. The
initial contents of int_unpaged_page_tables and
unpaged_page_tables are also generated. Also present are the
absolute addresses, lengths, and pointers to each of the collec-
tion 0 segments for use elsewhere in bound_bootload_0.
SECTION 3
COLLECTION 1
The basic charter of collection 1 is to set up paging,
fault handling, as well as various data bases needed for paging
and other like activities. Collection 1 can run multiple times,
for various reasons.
SUMMARY OF COLLECTION 1 PASSES
The first run through collection 1 is known as the "early"
pass which is described below. It is a run in which we are
restricted to work within 512K and in which only the rpv is
known; in fact, it is this pass which finds the rpv and the
config deck. If BOS is present, this pass is not needed. The
end of this pass is the arrival at "early" command level, used to
fix up the config deck, in preparation for the "boot" pass.
The second pass, which is known as "bootload Multics
initialization", also runs only within 512K. It, however, has
knowledge of all disks and other peripherals through the config
deck supplied either by BOS or the early initialization pass.
This pass is made to generate a crash-to-able system that can be
saved onto disk for crash and shutdown purposes. After the crash
handler (this image) is saved, the bootload Multics "boot"
command level can be entered. This level allows the booting of
Multics service. After Multics has shut down, a slight variant
of this pass, the "shut" pass, is run in a manner similar to that
for the "crash" pass, described below.
The third pass (which actually comes after the fourth) is
another run of bootload Multics initialization performed after
Multics has crashed. This pass is made to re-generate various
tables to describe the possibly different configuration that now
exists after having run Multics. Bootload Multics "crash"
command level is then entered.
The fourth pass through collection 1 is called "service
initialization", which runs using all memory and devices. The
result of this pass is suitable for running the later collec-
tions, and bringing up service.
The "early" pass creates a safe environment consisting of a
set of programs in memory and a synthesized config deck that
describes known hardware. This is saved away to handle crashes
during the "boot" pass. If the "boot" pass fails, the toehold
restores this earlier saved environment which then runs a
"re_early" pass. This is really a normal pass, but using the
saved away config deck of known good hardware. The "re_early"
pass comes back to an "early" command level to allow the operator
to fix the deck or hardware.
When the "boot" pass succeeds, it also saves a good memory
image and the now confirmed site config deck. After the "boot"
pass saves this image, the "boot" command level is entered and
eventually it boots Multics, running the "service" pass. If this
fails, the toehold restores the saved image. A "bce_crash" pass
then runs. This is a normal pass but one in which the saved
config deck is used. This pass is run on the assumption that,
either a bce command died and the operator may now examine it, or
that the "service" pass found a problem. The "bce_crash" level
allows the operator to fix things.
Once the boot of service Multics completes collection 1, a
crash or shutdown will invoke the toehold to restore bce. This
time, however, the current config deck is used to utilize any
reconfigurations that have occured. bce will come to the "crash"
or "boot" command levels.
We'll start by looking at the basic initialization pass,
that used to come to the normal ("boot") bce command level.
NORMAL (BOOT) PASS
The sequence of events in a normal initialization pass is
given here. As of the time of the start of a normal
initialization pass, the config deck has been found, either by
BOS or the early initialization pass. All other data bases
besides sys_boot_info and sys_info set or created during previous
initialization passes have been deleted. The pass starts with
saving certain attributes, such as free core extents, for later
restoration at the end of the pass (before running another).
scs_and_clock_init fills in the initial scs (system config-
uration segment) data from the config deck. This is information
on the processors and the memory controllers.
get_io_segs, iom_data_init, ocdcm_$init_all_consoles, and
scas_init are run to set up the disk_seg, pvt, iom_data,
ioi_data, oc_data and the system controller addressing segment.
tc_init initializes tc_data's apte and itt lists.
init_sst generates the sst and core map appropriate for the
pass. This is the last real memory allocation. After this time,
allocation of memory based upon the data in the slt is
deactivated. The remaining tables either have memory already
allocated for them or are generated paged, once paging is
started. announce_chwm announces memory usage.
initialize_faults$interrupt_init initializes the interrupt
vector. With iom_data and oc_data set up, this permits ocdcm_ to
be used for console I/O. The interrupt mask is opened with a
call to pmut$set_mask.
The basic command environment facilities (I/O interfaces
and a free area) are set up in a call to init_bce. (BCE is an
acronym for Bootload Command Environment). This allows programs
that query the operator to do so in a more friendly fashion than
raw calls to ocdcm_. Further descriptions of bce facilities
follow later.
load_disk_mpcs runs (only during a "boot" pass and only
when we do not have BOS present) to make sure that all disk mpcs
have firmware active within them.
init_pvt, read_disk$init and init_root_vols together have
the net effect of setting up disk and page control. No segments
are paged at this time, though, except for rdisk_seg. Once we
reach here, we know that the config deck describes a set of
hardware sufficient (and valid) enough to reach command level and
so we save the config deck as safe_config_deck.
establish_config_deck reads the config_deck segment from
disk, if appropriate. This segment will become the first paged
segment.
establish_temp_segs maps the bootload paged temp segments
onto the reserved area for them in the "bce" partition.
find_file_partition maps the bce file system area
(bootload_file_partition) unto the "file" partition.
load_mst$init_commands maps the pagable bce programs onto
the areas of disk in which they were read by load_mst earlier.
If this is a "early" or "boot" pass, this environment is
saved and the toehold setup to invoke it. This is done by
init_toehold. The "early" pass saves the entire environment; the
"boot" pass simply saves the safe_config_deck so determined by
this pass.
bce_get_to_command_level can now be called to provide the
appropriate bce command level. At the "early" command level, the
config deck must be made to be correct. At the "boot" command
level, the mpcs (other than the bootload tape mpc and all of the
disk mpcs) need to be loaded.
When the pass is over, the states saved at the beginning of
the pass are restored, the system is masked, and we proceed to
perform another pass.
SERVICE PASS
The sequence of events in a service pass differs from the
normal pass in many ways.
After initialize_faults$fault_init_one runs,
move_non_perm_wired_segs is called to move the segments loaded by
collection 0 to their proper places, thereby utilizing all of the
bootload memory.
[Collection 0 assumes 512K of bootload memory, for two
reasons. First, if BOS and the config deck are not present,
there is no easy way of finding out how much memory there is, so
some assumption is needed. Second, the crash handler will have
to run in some amount of memory whose contents are saved on disk.
512K is a reasonable amount of space to reserve for a disk
partition. At current memory and disk prices it is hard to
imagine anyone with a bootload controller with less that 512K, or
a problem with the disk partition.
When setting up the service environment, though, it is
necessary to move the segments that have been allocated in the
512K limit. It is desirable to have sst_seg and core_map at the
high end of the bootload memory controller. (On the one hand,
the controller they reside in cannot be deconfigured. On the
other hand, only the low 256K of memory can be used for I/O
buffers on systems with IOM's not in paged mode. While we could
just start them at the 256K point, that might produce
fragmentation problems. So the top of the controller is best.)
If the controller really has 512K of memory, collection 1 paged
segments will be there. move_non_perm_wired_segs takes the
segments that the collection zero loader allocated high (paged
segments and init segments that are not firmware segments) and
moves them to the highest contiguously addressable memory,
hopefully leaving the top of the low controller for the sst_seg
and core_map.]
tc_init sets the number of aptes and itt entries on the
basis of the tcd card. A normal bce pass really needs no such
entries.
init_sst generates the sst and core map appropriate for all
of memory at the top of the bootload memory. A normal pass
allocates these tables through normal off-the-slt allocation
(because the top of the 512k area is filled with temp segs).
establish_config_deck maps the config_deck segment onto the
disk "conf" partition. It writes out the memory version in the
process.
Since the service pass does not come to bce command level,
establish_temp_segs, find_file_partition and
load_mst$init_commands are not run.
init_toehold is not run since upon a crash we want to
return to the bootload environment and not to a state in which we
are booting.
init_partitions checks the "part" config cards.
Now, the routine we've all been waiting for runs.
make_segs_paged causes all pagable segments to be paged into the
various hardcore partitions thereby no longer needing memory. We
can then run collect_free_core to regain the freed space.
delete_segs$temp deletes the segments temporary to collec-
tion 1. We can then load, link, and run collection 2 (performed
by segment_loader, pre_link_hc and beyond).
EARLY PASS
The early initialization pass is a pass through collection
1 whose job is to set up paging and obtain the config deck from
its disk partition so that a normal initialization pass may be
run which knows about the complete set of hardware.
It starts with init_early_config constructing a config deck
based on assumptions and information available in sys_boot_info.
This config deck describes the bootload CPU, the low 512K of
memory, the bootload IOM, the bootload tape controller and the
bootload console. Given this synthetic deck, we can proceed
through scs_and_clock_init, etc. to setup the environment for
paging. scs_and_clock_init$early fills the bootload CPU port
number into the config deck, which is how it differs from
scs_and_clock_init$normal.
scas_init and init_scu (called from scas_init) have special
cases for early initialization that ignore any discrepancy
between the 512K used for the bootload controller and any larger
size indicated by the CPU port logic.
During the early pass (or, actually during the first "boot"
pass, if an early pass is never run), init_bce$wired sets up
references in bce_data to wired objects. This allows
bce_console_io and other friendlier routines to run.
To locate the RPV subsystem, find_rpv_subsystem looks in
sys_boot_info. If the data is there, it will try to boot the RPV
subsystem firmware (if needed). If not, it queries the operator
for the data. If, later in initialization, the data should prove
suspect (e.g. RPV label does not describe the RPV), control
returns here to re-query the operator. The operator is first
asked for a command line specifying the RPV subsystem model and
base channel, and the RPV drive model and device number. The
operator may request that the system generate a query in detail
for each item. Cold boot is also requested in the
find_rpv_subsystem dialog. The simple command processor,
bce_command_processor_, is used to parse the "cold" and "rpv"
request lines described above.
The RPV data is filled into the config deck, and
initialization continues with init_pvt and friends.
init_root_vols is called through its early entrypoint so as to
allow for an error return. Errors occuring during the initing of
the rpv will cause a re-query of the rpv data by returning to the
call to get_io_segs.
Firmware is booted in the RPV controller by
boot_rpv_subsystem, called from find_rpv_subsystem, which finds
the appropriate firmware image and calls hc_load_mpc. A database
of device models and firmware types and other configuration
rules, config_data_.cds, is used to validate operator input and,
for example, translate the subsystem model into a firmware
segment name.
init_roots_vols checks for the presence of and creates
certain key partitions on the rpv. The "conf" partition, if not
present, is created by trimming 4 pages off of the hardcore
partition. The "bce" (bce crash handler, temporary area and MST
storage) and "file" (bootload file system) partitions are
created, if any is not found, by a call to create_rpv_partition.
This program shuffles the disk pages to find enough contiguous
space at the end of the disk for the partitions.
Once paging is available, and the RPV has been found valid
(or cold-initialized), the real service config deck is read from
the RPV conf partition by establish_config_deck unless this is a
cold boot.
After running establish_temp_segs and find_file_partition,
the rest of the MST is read. This step is performed during the
"early" pass or whatever is the first boot pass.
tape_reader$init sets up tape reading. load_mst reads in collec-
tion 1.2 (config deck sources and exec_coms) into bce file system
objects, collection 1.5 (bce paged programs and firmware images)
into mst area pages leaving around traces for
load_mst$init_commands (which maps them into the bce address
space) and saves collections 2 and 3 on disk for warm booting.
tape_reader$final shuts down the tape. load_mst$init_commands
then runs.
The early or the first boot pass then initializes bce_data
references to paged objects with init_bce$paged.
An early command level is now entered, using a subset of
the real bce command level commands. This level is entered to
allow editing of the config deck.
After leaving command level, init_clocks is called. This
is the time when the operator sets the clock. Up until this
time, the times shown were random. If the operator realizes at
this time that he must fix the config deck, or whatever, he has a
chance to return to the early command level. When the clock is
set, control proceeds.
At this point, early initialization's work is done. The
real config deck is available, and the system can rebuild the
wired databases to their real sizes. Interrupts are masked,
completion of pending console I/O is awaited, and the slt
allocation pointers are restored to their pre-collection-1 val-
ues. Control then moves to the "boot" pass.
CRASH PASS
The crash pass recreates a "boot" environment from which
dumps can be taken and emergency_shutdown can be invoked. It
differs from the "boot" pass only in the verbosity (to avoid
printing many messages at breakpoints) and in the command level
that is reached.
RE_EARLY PASS
A re_early pass is run to restore a safe environment
following a failure to boot to the "boot" command level. It is
identical to a "boot" pass except that it uses a saved config
deck known to be good and reaches a "early" command level.
BCE_CRASH PASS
The bce_crash pass is run to restore a safe environment
following a failure to boot the "service" pass. This may also be
the result of a failure of a bce utility invoked at the "boot"
command level. This pass is identical to the boot pass except
that it uses a saved config deck known to be good and reaches the
"bce_crash" command level.
SHUT PASS
The shut pass is run when Multics shuts down, as opposed to
crashing. It differs from the boot pass only in that
load_disk_mpcs is not run, because it shouldn't be ncessary
(Multics was using the mpcs okay) and because it would interfere
with possible auto exec_com operation.
MODULE DESCRIPTIONS
Bootload Command Environment modules are not included in
this section.
announce_chwm.pl1
The name of this program means
announce_Core_High_Water_Mark. It will announce the extent to
which memory is filled during the various passes of collection 1
when the "chwm" parameter appears on the "parm" card in the
config deck. Near the beginning of each pass, this program
announces the amount of memory used, based upon information in
the slt. At the end of service initialization, it walks down the
core map entries, looking for pages that are available to page
control and those that are wired. The difference between the
memory size and the total figure given here is the amount taken
up by non-page control pages, the sst for example. As a side
bonus, the before entrypoint announces the usage of
int_unpaged_page_tables; the after entrypoint announces the usage
for unpaged_page_tables.
boot_rpv_subsystem.pl1
boot_rpv_subsystem is the interface between
find_rpv_subsystem and hc_load_mpc, the hardcore firmware loading
utility. All that it really has to do is find the appropriate
firmware segment in collection 1. config_data_ is used to map
the controller model to a firmware segment name, of the usual
(T&D) form (fw.XXXnnn.Ymmm). The segment and base channel are
passed to hc_load_mpc, and the results (success or failure) are
returned to find_rpv_subsystem.
boot_tape_io.pl1
This is the program that performs reading of the MST by
collections 1 and beyond. It uses the physical record buffer as
an i/o area. io_manager is used to perform the i/o, with dcw
lists generated within this program.
bootload_1.alm
bootload_1 is the first collection 1 program, called
directly by collection 0. It fills in the stack headers of the
prds and inzr_stk0 to initialize the PL/1 environment. It then
calls initializer.pl1 which pushes the first stack frame.
collect_free_core.pl1
At the end of collection 1 service initialization, this
program is called to free the storage taken up by the previously
wired initialization segments. It does this by marking all core
map entries for pages still unpaged (judged from the address
field of the sdws of all segments) as wired and marking all of
the rest as free (available for paging). It special cases
breakpointable segments to avoid freeing references to
breakpoint_page.
create_rpv_partition.pl1
To save the effort of creating the new Bootload Multics
partitions by requiring all sites to perform a rebuild_disk of
their rpv, this program was created. It creates partitions on
rpv (high end) by shuffling pages about so as to vacate the
desired space. The pages to move are found from the vtoces. The
vtoces are updated to show the new page location and the volmap
is updated to show the new used pages. This program uses
read_disk to read and write the pages. No part of the file
system is active when this program runs.
delete_segs.pl1
delete_segs is called after the various collections to
delete the segments specific only to that collection (temp segs).
It is also called at the end of collection 3 to delete segments
belonging to all of initialization (init segs). It scans the ast
list for the appropriate segments, uses pc$truncate to free their
pages (in the hardcore partition) or pc$cleanup to free the core
frames for abs-segs and then threads the astes into the free
list. This program is careful not to truncate a breakpoint_page
threaded onto a segment.
disk_reader.pl1
disk_reader is used by the collection 1 loader (of collec-
tion 2), segment_loader, and by the collection 2 loader,
load_system, to read the mst area of disk. It operates by paging
disk through disk_mst_seg. The init entrypoint sets up
disk_mst_seg unto the first 256 pages of the mst area to be read.
As requests come in to read various words, they are paged from
this segment. When a request comes in that is longer than what
is left in this segment, the remainder is placed into the
caller's buffer, and disk_mst_seg re-mapped onto the next 256
pages. This continues as needed.
establish_config_deck.pl1
The config deck is stored in the "conf" partition on the
RPV in between bootloads. In service, the segment config_deck is
effectively an abs-seg onto this partition. This program
establishes the segment, by filling in the aste and page table
appropriately. During the service pass, this abs-seg becomes
config_deck, with the wired version copied therein. When called
in early initialization, (at the $early entrypoint), it copies
the abs-seg's contents into the wired segment. Otherwise, the
abs-seg is built so that routines that which to update the disk's
config deck (config_deck_edit_) may do so.
fill_vol_extents_.pl1
This is the ring 1 program that obtains, through the
infamous "init_vol loop", the desired parameters of a disk to
initialize. It is called in initialization by init_empty_root
when performing a cold boot to determine the desired partitions
and general layout desired for the rpv.
find_rpv_subsystem.pl1
find_rpv_subsystem initializes configuration and firmware
for the RPV disk subsystem. When available, it uses information
in sys_boot_info. When that information is not present, the
operator is queried. The basic query is for a request line of
the form:
rpv Icc MPC_model RPV_model RPV_device
or
cold Icc MPC_model RPV_model RPV_device
as described in the MOH.
If the operator makes a mistake, or types help, the
operator is offered the opportunity to enter into an extended,
item by item dialog to supply the data.
The information is checked for consistency against
config_data_, a cds program that describes all supported devices,
models, etc. The mpc is tested through
hc_load_mpc$test_controller, to see if firmware is running in it.
If the response is power off, then boot_rpv_subsystem is called
to load firmware. Then init_early_config$disk is called to fill
this data into the config deck. If a later stage of
initialization discovers an error that might be the result of an
incorrect specification at this stage, control is returned here
to give the operator another chance.
The operator is also allowed to enter "skip_load" or
"skip", as a request before entering the rpv data. This forces a
skip of the firmware loading, regardless of the apparent state of
the mpc.
get_io_segs.pl1
A scan through the config deck determines the sizes of the
various hardcore i/o databases which this program allocates.
This program also fills in some of the headers of these databases
as a courtesy for later initialization programs. The key
determiners of the sizes of the tables allocated are the number
of subsystems, the number of logical channels to devices, the
number of drives, the number of ioms, etc. get_main is used to
allocate the areas, using entries in the slt to find the memory.
Areas allocated are: the pvt, the stock_segs, the disk_seg,
ioi_data and iom_data.
get_main.pl1
get_main is used to create a segment that is to reside in
main memory. It runs in one of two ways, depending on whether
allocation off the slt (slt.free_core_start) is allowed. When
this is not allowed (later in initialization),
make_sdw$unthreaded is used to generate the segment/aste.
pc_abs$wire_abs_contig forces this segment to be in memory.
Earlier in initialization (before page control is active), the
segment is allocated from the free core values in the slt. These
values determine the placement in memory of the to be created
segment. get_main allocates a page table for this segment in
either int_unpaged_page_tables or unpaged_page_tables (depending
on whether the segment will eventually be made paged). The ptws
are filled in and an sdw made. The given_address entrypoint of
get_main can be used to utilize its unpaged segment page table
generation capabilities (as in init_sst).
hc_load_mpc.pl1
hc_load_mpc embodies the protocol for loading all MPC's.
It is an io_manager client. Since the firmware must be in the
low 256K, a workspace is allocated in free_area_1 and the
firmware image is copied out of the firmware segment and into
this buffer for the actual I/O. The urc entrypoint is used to
load urc mpcs. This entry accepts an array of firmware images to
load. It scans the list to determine to which channels each
overlay applies. The extra entrypoint test_controller, used by
find_rpv_subsystem and load_disk_mpcs, tests a controller by
executing a request status operation. The results of this are
used to see if the mpc seems to be running (has firmware in it).
init_aste_pools.pl1
This program is called exclusively from init_sst and really
does most of its work. It builds the four aste pools with empty
astes appropriately threaded. Each aste is filled in with ptws
indicating null pages.
init_clocks.pl1
This program performs the setting of the system clock. It
starts by providing the time and asking if it is correct. If it
is, fine. If the operator says it's not, the operator is
prompted for a time in the form:
yyyy mm dd hh mm {ss}
The time is repeated back in English, in the form "Monday,
November 15 1982". If the bootload memory is a SCU, the operator
is invited to type "yes" to set this time (when the time is met),
or "no" to enter another time. The time is set in all the
configured memories, to support future jumping clock error
recovery. On 6000 SC's, the program translates times to SC
switch settings. The program gives the operator time to set the
clock by waiting for an input line. At any time, the operator
may enter "abort", realizing that something is wrong.
init_clocks then returns. real_initializer will re-enter the
early command level in this case.
init_early_config.pl1
init_early_config fabricates a config deck based on the
information available after collection zero has completed. The
bootload CPU, IOM, console, and tape controller are described.
The port number of the bootload CPU is not filled in here, since
it is not easily determined. Instead, scs_and_clock_init$early
fills it in. Appropriate parm, sst, and tcd cards are
constructed, and placeholders are filled in for the RPV
subsystem, so that iom_data_init will reserve enough channel
slots. init_early_config$disk is used to fill in the real values
for the RPV subsystem once they are known.
init_empty_root.pl1
fill_vol_extents_, the subroutine used by the user ring
init_vol command, has been adapted to provide the main function
of this program. It provides a request loop in which the
operator can specify the number of vtoces, partition layout, etc.
The operator is provided with a default layout, including the
usual set of partitions and the default (2.0) average segment
length. If it is changed, the operator is required to define at
least the hardcore and bce required partitions and (for the
moment) the bos partition.
init_hc_part.pl1
init_hc_part builds the appropriate entries so that paging
and allocation may be done against the hardcore partition. It
builds a pseudo volmap (volmap_abs_seg) describing the hardcore
partition (which is withdrawn from the beginning thereof)
allowing withdrawing of pages from the partition. A record stock
is also created of appropriate size for the partitions.
init_partitions.pl1
This program makes sure that the partitions the operator
specified in the config deck are really there. It checks the
labels of the config deck specified disks for the specified
partitions. Disks that do have partitions so listed are listed
as un-demountable in their pvt entries.
init_pvt.pl1
The pvt contains relatively static data about each disk
drive (as opposed to dynamic information such as whether i/o is
in progress). init_pvt sets each entry to describe a disk. No
i/o is done at this time so logical volume information, etc. can
not be filled in. Each disk is presumed to be a storage system
disk, until otherwise determined later.
init_root_vols.pl1
init_root_vols finds the disks that will be used for
hardcore partitions. It mostly finds the disks from root cards
and finds the hardcore partitions from the labels. For the rpv,
it will also call init_empty_root, if a cold boot is desired,
call create_rpv_partition, if various required partitions are
missing (MR11 automatic upgrade), and set various pvt entries to
describe the rpv. During the service pass, init_hc_part is
called to establish paging (and allow withdrawing) against the
hardcore partition.
init_scu.pl1
This routine is used within scas_init to init a given scu.
It compares the scu configuration information (from its switches)
with the supplied size and requirements. When called for
bootload Multics purposes, the size of the scu may be larger than
that specified (generated) in the config deck without a warning
message. It generates ptws so it can address the scu registers
(see the description in the glossary for the scas). The execute
interrupt mask assignment and mask/port assignment on the
memories is checked here.
init_sst.pl1
init_sst starts by determining the size of the pools.
Normally, this is found in the sst config card (although init_sst
will generate one of 400 150 50 20 if one isn't found). For
early and bootload Multics initialization, though, the pools
sizes are determined from the current requirements given in
figures in bootload_info. The size of the core_map is determined
from the amount of configured memory for normal operation and is
set to describe 512K for early and bootload Multics operation.
The area for the sst is obtained, either from the top of the
bootload scu for normal operation, or from the slt allocation
method for early and bootload Multics operation. The headers of
the sst and core map are filled in. init_aste_pools actually
threads the astes generated. The pages of memory not used in low
order (or bootload (512k)) memory are added to the core_map as
free. For normal operation, the other scu's pages are also added
to the free list. collect_free_core will eventually add the
various pages of initialization segments that are later deleted.
init_vol_header_.pl1
init_empty_root uses this program to initialize the rpv.
This routine writes out the desired label (which describes the
partitions filled in by fill_vol_extents_), generates an empty
volmap and writes it out, and generates empty vtoces and writes
them out.
initial_error_handler.pl1
This any_other handler replaces the fault_vector "unexpect-
ed fault" assignments. It implements default_restart and
quiet_restart semantics for conditions signalled with info, and
crashes the system for all other circumstances.
initialize_faults.pl1
initialize_faults has two separate entries, one for setting
things up for collection 1, and one for collections 2 and beyond.
This description is for collection 1
(initialize_faults$fault_init_one). initialize_faults_data
describes which faults have their fault vectors set to
fim$primary_fault_entry (scu data to pds$fim_data),
fim$signal_entry (scu data to pds$signal_data),
fim$onc_start_shut_entry (scu data to pds$fim_data) or
wired_fim$unexp_fault (scu data to prpds$sys_trouble_data) (all
others). Special cases are: lockup and timer runout faults are
set to an entry that will effectively ignore them. Derails go to
fim$drl_entry to handle breakpoints and special drl traps.
Execute faults are set to wired_fim$xec_fault (scu data to
prds$sys_trouble_data). Page faults are set to pagefault$fault
(scu data to pds$page_fault_data). And connect faults are set to
prds$fast_connect_code (scu data to prds$fim_data). Write access
is forced to certain key programs to set values within them.
Access is reset afterwards. These are pointers which must be
known by certain programs when there will be no mechanism for the
programs themselves to find them. An example is the pointers
within wired_fim specifying where scu data is to be stored. The
last thing done is to set the signal_ and sct_ptr in the
inzr_stk0 stack header so that signalling can occur in collection
1.
initialize_faults_data.cds
This cds segment describes which faults go to where so that
initialize_faults can so set them. For collection 1, the major
faults set are: command and trouble to fim$primary_fault_entry
(scu data in pds$fim_data), access violation, store, mme, fault
tag 1, 2 and 3, derail, illegal procedure, overflow, divide,
directed faults 0, 2 and 3, mme2, mme3, mme4 to fim$signal_entry
(scu data to pds$signal_data), shutdown, op not complete and
startup to fim$onc_start_shut_entry (scu data to pds$fim_data)
and the rest to wired_fim$unexp_fault (scu data to
prds$sys_trouble_data).
initializer.pl1
initializer consists of only calls to real_initializer,
delete_segs$delete_segs_init, and init_proc. real_initializer is
the main driver for initialization. It is an init seg.
initializer exists as a separate program from real_initializer
because, after the call to delete init segs, there must still be
a program around that can call init_proc. This is the one.
iom_data_init.pl1
The function of this program is to set up the data bases
used by io_manager. These include iom_data and the actual
mailboxes used in communicating with the iom. The iom cards are
validated here. The overhead channel mailboxes are set for the
described channels.
load_disk_mpcs.pl1
During the "boot" pass, all disk mpcs must have firmware
loaded into them. This is done by load_disk_mpcs. This program
scans the config deck, searching for disk mpcs. It tests each
one (with hc_load_mpc$test_controller) to determine a list of
apparently non-loaded disk mpcs. If this list is not empty, it
prints the list and asks the operator for a sub-set of these to
load. bce_fwload is used to perform the actual loading.
load_mst.pl1
load_mst reads in the MST. It contains a routine which
understands the format of a MST. This routine is supplied with
various entry variables to do the right thing with the objects
read from the various collections. For collection 1.2, the
objects are placed into the bce file system through bootload_fs_.
For collection 1.5, the segments have linkages combined, etc.
just as in segment loader. The objects are placed on disk, in
locations recorded in a table. These are paged bce programs.
Collections 2 and 3 are simply read in as is, scrolling down the
mst area of the "bce" partition using the abs-seg disk_mst_seg.
The init_commands entrypoint uses the table built while reading
collection 1.5. The appropriate bce segments are mapped onto
disk using the locations therein.
make_sdw.pl1
make_sdw is the master sdw/aste creation program for
collection 1 and beyond. It contains many special cases to
handle the myriad types of segments used and generated in
initialization. It's first job is to determine the size of the
desired segment. The size used is the maximum of the slte's
current length, maximum length and the size given on a tbls card
(if the segment's name is in variable_tables). Also, an extra
page is added for breakpoints when needed. Given this size, an
appropriate size aste is found and threaded into the appropriate
list, either init segs, temp segs, or normal segs. Wired segs
aren't threaded; they are just listed as hardcore segments. The
page table words are initialized to null addresses. If the
segment is wired and is breakpointable, the last ptw is instead
set to point to breakpoint_page. For abs-segs, this is the end;
abs segs and other "funny" segs must build their own page tables
and a real sdw to describe them. For a normal segment, however,
the page table entries are filled as follows: an appropriate
hardcore partition to hold the pages is chosen. abs_seg's sdw is
set to indicate this null address page table. The various pages
are touched, causing page control to be invoked to withdraw an
appropriate page against the hardcore partition whose drive index
is in the aste. (abs_seg's sdw is then freed.) make_segs_paged
and segment_loader, the main clients of make_sdw, will then copy
the desired data (either from wired memory or from the tape) into
these new (pagable) pages.
make_segs_paged.pl1
make_segs_paged, that most famous of initialization pro-
grams, actually, in a way, has most of its work performed by
make_sdw. make_segs_paged examines all of the initialization
segments, looking for those it can page (i.e., not wired, not
already made paged, non-abs-segs, etc.). It walks down this list
of segments from the top of memory down, using make_sdw to
generate an aste, an sdw, and a page table full of disk pages for
it. The sdw is put into dseg, and the contents of the wired
segment is copied into the paged version. The pages of memory
are then added to page control's free pool The dseg is also
copied with a new dbr generated to describe it.
Breakpointable segments are special cased in two ways.
First of all, when the pages of the old segment are freed,
occurences of breakpoint_page are not. Also, when copying the
segment, breakpoints set within it must be copied. All of
breakpoint_page cannot be copied since it includes breakpoints in
other segments. Thus, we must copy each breakpoint, one at a
time by hand.
move_non_perm_wired_segs.pl1
This program takes the segments allocated high addresses by
collection 0 (paged segments and init segments that are not
firmware segments) which were put at the top of the 512K early
initialization memory, and moves them to the top of the
contiguously addressable memory, leaving the top of the low
controller for the sst_seg and core_map.
This program depends on the knowledge that the loader
assigns segment numbers in monotonically increasing order to
permanent supervisor and init segs, and that the high segments
are allocated from the top of memory down. Thus it can move the
highest segment (in memory address) first, and so on, by stepping
along the SLTE's.
The copying of the segment can be tricky, though, since not
only must the contents be moved but the page table must be
changed to reflect the new location. For this, we build abs_seg0
to point to the new location. The segment is copied into
abs_seg0. We now make the sdw for the segment equal to that for
abs_seg0. The segment is now moved, but we are using the page
table for abs_seg0 for it, not the one belonging to it. So, we
fix up the old page table to point to the new location, and swap
back the old sdw. This starts using the new ptws in the old
place.
Segments that were breakpointable (had breakpoint_page in
them) must be special cased not to move the breakpoint page.
ocdcm_.pl1
Within initialization, the init_all_consoles entrypoint of
ocdcm_ is called. This entrypoint sets up oc_data to a nice safe
(empty) state. The various console specific parms are found and
saved. The main loop examines all prph opc cards. They are
validated (and later listed if clst is specified). For each
console, a console entry is filled describing it. The bootload
console, when found, is specifically assigned as bootload con-
sole. As a last feature, the number of cpus is found. This is
because the longest lock time (meaningful for determining
time-outs) is a function of the number of processors that can be
waiting for an i/o.
ocdcm_ also provides for bce a special function. It
maintains wired_hardcore_data$abort_request, set to true whenever
the operator hits the request key when this was not solicited (no
read pending). This flag is used by bce_check_abort to
conditionally abort undesired bce operations.
prds_init.pl1
This program simply initializes certain header variables in
the prds. This includes inserting the fast_connect_code, the
processor tag, etc.
pre_link_hc.pl1
The linker for collection 2, this program performs a
function analogous to that performed by bootload_linker. It
walks down the linkage sections of the segments in question,
looking for links to snap. slt_manager is used to resolve
references to segments. A definition search is imbeded within
this program.
read_disk.pl1
read_disk is the routine used to read a page from or to
write a page to disk. The init entry point sets up rdisk_seg as
a one page paged abs segment for such purposes. Actual page
reading and writing consists of using disk_control to test the
drive (unless the no_test entrypoints were used), and then page
control to page the page. For reads, we construct a page table
word describing the page of disk. Touching rdisk_seg then reads
it in. For writing, we generate a null address page table entry.
When we write to it, a page of memory is obtained. By forcing
the core map entry to describe the desired page of disk, unwiring
the page and performing a pc$cleanup (force write), the page
makes it to disk.
read_disk_label.pl1
To read a disk label, we call read_disk_label. It uses
read_disk to preform the i/o. Several such reads will be
performed. if necessary. The label is validated through a
simple check of label.Multics, label.version and
label.time_registered.
real_initializer.pl1.pmac
real_initializer is the main driver for initialization. It
largely just calls other routines to set things up, in the proper
order.
There are many paths through real_initializer as described
above. All paths set an any_other handler of
initial_error_handler to catch unclaimed signals, which eventual-
ly causes a crash.
The main path through real_initializer calls collection_1
(an internal subroutine) multiple times and then passes through
to collections 2 and 3. Each call to collection_1, in the normal
case, "increments" sys_info$collection_1_phase, thus producing
the main set of collection 1 passes. Various deviations from
this exist. Aborting disk mpc loading resets the phase to
re_early and branches back to the "early" command level. A
failure when finding the rpv during the "early" pass retries the
"early" pass. The reinitialize command resets the phase to
"early" and then simulates the bce "boot" function, thus making
the next pass become a new "boot" pass.
When Multics crashes or shuts down, the toehold restores
the machine conditions of bce saved in the toehold. These return
the system to save_handler_mc, which quickly returns through
init_toehold to real_initializer. The routine collection_1
senses this and returns to the main collection_1 calling loop.
real_initializer keys off the memory_state (determines between
crashing and shutting down) and old_memory_state (state of
crashed memory - determines crashed collection 1 phase) in the
toehold to determine the pass to run next.
real_initializer includes a stop-on-switches facility.
pl1_macro is used to assign a unique number to each step in
initialization. This number can also be used in the future to
meter initialization. Before each step in initialization, a call
is made to the internal procedure check_stop. If the switches
contain "123"b3 || "PNNN"b6, where PNNN is the error number in
binary coded decimal (P is the collection 1 phase, NNN is the
stop number obtained from a listing), bce is called (if the
toehold is active).
scas_init.pl1
scas_init inits the scas (system controller addressing
segment). It is the keeper of things cpu and scu. The config
deck is searched for cpu and mem cards which are validated and
the boxes' switches validated against the cards. The scs$cow
(connect operand words) are filled in here with values so that we
may send connects to the various processors. init_scu is called
to set masks and such for the various scus. The port enables are
set for the ioms. The cpu system controller masks are checked.
Finally, if the cpus and ioms do not overlap in port numbers, the
cyclic priority switches are set on the scus.
scs_and_clock_init.pl1
This program initializes most of the data in the scs. In
previous systems, the scs was mostly filled in its cds source.
To support multiple initializations, though, the segment must be
reset for each pass. This program also has the task of setting
sys_info$clock_ to point to the bootload SCU. Finally, at its
$early entrypoint, it fills in the bootload SCU memory port
number in the config deck, since it used that data in scs
initialization. Initializing the scs consists of initiating data
about cpus and scus.
segment_loader.pl1
segment_loader is used to load collections 2.0 and beyond.
It uses disk_reader to read records from the MST of disk. The
various records from the MST are either collection marks, header
records (denoting a segment) or the data forming the segments.
Given information in the segment header, an appropriately sized
area in wi_linkage$, ws_linkage$, ai_linkage$ or as_linkage$ is
generated. slt_manager$build_entry chooses the next segment
number (either supervisor of initialization) for the segment and
creates the slt entry. make_sdw creates an sdw an the page table
and allocates disk space in the hardcore partition for the
segment. With read/write access forced for this new (pagable)
segment, the segment is read from disk. Access is then set as
desired in the header record. We loop in this manner until we
encounter a collection mark when we stop.
slt_manager.pl1
This is a relatively simple program.
slt_manager$build_entry looks at the header read from an MST and
builds a slt entry. The header defines whether this is a
supervisor or an initialization segment (which defines from which
set of segment numbers (supervisory start at 0, initialization
start at 400 octal) it is given), what names to add to the name
table, and whether this segment has a pathname which needs to be
added to the name table (so that init_branches can thread them
into the hierarchy). While it is building the entry, it hashes
the names in the same manner as bootload_slt_manager.
slt_manager$get_seg_ptr uses this hash list to search for the
segment name requested.
sys_info.cds
sys_info is described under data bases.
tape_reader.pl1
tape_reader uses boot_tape_io to read MST tape records. It
is capable of reading several tape records and packing them into
a user supplied buffer. It validates the tape records it reads
for Multics-ness, performing the (old) reading re-written record
error recovery mechanism.
tc_init.pl1
tc_init is run in two parts, the second called part_2 run
in collection 2. Part one, just called tc_init, allocates an
appropriately sized tc_data (see the description of
tc_data_header, above) given the supplied number of aptes and itt
entries. The workclass entries are initialized to their
defaults. Workclass 0 is set up for the initializer as realtime,
etc. Everyone else is put initially into workclass 1. The aptes
and itts are threaded into empty lists. Initial scheduling
parameters are obtained from the schd card. The length of the
prds is set (either default or from tbls card). The stack_0_data
segment (which keeps track of the ring 0 stacks given to
processes when they gain eligibility) is initialized. Apte
entries for the initializer and idle (bootload cpu) are created.
Finally, memory is allocated for the pds and dseg of the various
idle processes (which won't actually be started until
tc_init$part_2).
SECTION 4
THE BOOTLOAD COMMAND ENVIRONMENT
Bootload Multics must provide a certain number of
facilities when the storage system is not available. Examples
are system dumps to disk, disk saves and restores , interactive
hardcore debug (patch and dump), and automatic crash recovery.
INITIALIZATION
There are two ways that the command environment is entered.
When an existing system is booted from power-up (cool boot), the
command environment is entered to allow config deck maintenance
and the like. When the service system crashes, the command
environment becomes the crash recovery environment that oversees
dumping and automatic restart. A full cold boot is a special
case of a cool boot.
The heart of the bootload Multics command environment (bce)
runs mostly wired. The paged segments are paged temp segments,
managed by get_temp_segment_ and friends, for such purposes as
qedx buffers and active function expansion. The bce file system
is paged. Also, some bce command programs are paged, through the
grace of load_mst. These are mapped onto an area of the bce
partition. bce does not use the storage system, nor the hardcore
partition.
Certain special programs are run so as to initialize bce.
These are: init_bce to enable the basic facilities of switches
and areas and such; find_file_partition to enable the bootload
Multics file system; establish_temp_segs to provide paged temp
segments; and, load_mst$init_commands to allow references to
paged bce programs. load_mst was described under the bootload
Multics initialization pass in collection 1.
ENVIRONMENT AND FACILITIES
The basic facilities of the command environment are:
*
a free area. free_area_1 is initialized with define_area_,
and a pointer left in stack_header.user_free_area and
stack_header.system_free_area, so that allocate statements
with no "in" qualifiers work. get_system_free_area_ () will
return a pointer to this area. This area is used for global
data needed between commands. Each command normally finds
its own local area, normally on a paged temp segment.
* standard input, output and error entries that hide the
distinction between console and "exec_com" input. These are
entry variables in the cds program bce_data.cds. They are
hardly ever called directly, as more sophisticated
interfaces are defined atop them. The entry variables are
bce_data$get_line, bce_data$put_chars and
bce_data$error_put_chars. get_chars is not sensible in the
console environment, for the console will not transmit a
partial line. The module bce_console_io is the usual target
of the entry variables. It uses ocdcm_, oc_trans_input_ and
oc_trans_output_. bce_data also contains the pointers
get_line_data_ptr, put_chars_data_ptr and
error_put_chars_data_ptr which point to control information
needed by the target of the entry variable. The pair of
values of an entry variable followed by the data pointer is
what constitutes a bce switch. A pointer to this switch is
passed around much as an iocb pointer is passed around in
Multics. Both ioa_ and formline_ understand these bce
switches so that normal calls may be made.
* bce_query and bce_query$yes_no. Each takes a response
argument, ioa_ control string, and arguments, and asks the
question on the console. An active function interface is
provided.
* bce_error is the local surrogate for com_err_, used by
various non command level programs. It does not signal any
conditions in its current implementation. com_err_ and
active_fnc_err_ simply call bce_error appropriately when in
bce.
* a command processor. The standard command_processor_ is
used to provide a ssu_-like subsystem facility. The various
command programs are called with a pointer to
bce_subsystem_info_, of which the arg_list_ptr is the impor-
tant information.
* a request line processor. Any program that wants to parse
lines using standard syntax (without quotes, parentheses, or
active functions, for now) calls bce_command_processor_ with
the command line, a procedure that will find the command,
and a return code. find_rpv_subsystem, for example, calls
it with an internal procedure that checks that the command
is either "rpv", "cold", "help", or "?", and returns the
appropriate internal procedure to process the command.
These procedures use the usual cu_ entrypoints to access
their arguments.
* The paged temp segments bootload_temp_1 .. bootload_temp_N.
These are each of 128/N pages long, and mapped as abs-seg's
onto a part of the bce partition. N is established by the
number of such segments listed in the MST header (and
computed by establish_temp_segs). These segments are
managed by get_temp_segments_ and friends.
* A primitive file system. bootload_fs_ manages a simple file
system mapped onto the "file" partition on the rpv. This
file system can hold config files or exec_coms. It is
writable from within Multics service. The objects in the
file system have a max length of 128/N pages, matching that
of the temp segments, and have a single name.
* The standard active function set.
* Disk i/o facilities. Several exist. Some utilities call
(read write)_disk. If they do not need the disk test that
this routine performs (as when accessing the (already)
trusted rpv), they call the no_test versions of these
entrypoints. Another mechanism is to build a paged segment
onto the desired disk area, normally via map_onto_disk.
This mechanism trusts the built in mechanisms of page
control (and traffic control disk polling) to ensure that
the i/o is noticed. A final mechanism is to call
dctl$bootload_(read write), which allows the queueing of
multiple i/os to different disks. This is used for high
volume operations, such as pack copying.
RESTRICTIONS
Various Multics facilties are not present within bce. Some
are listed below.
* No operations upon the file system hierarchy are allowed
(except for indirect references by bce_probe to segments in
the Multics image).
* Normal segment truncation/deletion/creation is not allowed.
The ptws must be manually freed.
* Segments may not be grown (no withdrawing of pages is
allowed). They must be explicitly mapped onto the desired
free area of disk or memory.
* No iox_ operations are allowed. Pseudo-iocb's do exist,
though.
* Only a finite (and small) number of paged/wired work areas
can exist. They also have comparatively small lengths.
* Dynamic linking is not done. References to object names are
done with slt_manager$get_seg_ptr.
* Wakeups and waiting for wakeups can not be done. A program
must loop waiting for status or use pxss facilities.
* Timers (cput and alrm) may not be set. Programs must loop
waiting for the time.
* There are no ips signals so no masking is involved. The
real question is the masking of interrupts (pmut$set_mask).
MODULE DESCRIPTIONS
bce_alert.pl1
Console alert messages (mostly for bce exec_com's) are
produced by bce_alert. It simply appends its arguments,
separated by a space) into one string which it prints through
bce_data$console_alert_put_chars. This prints the message with
audible alarm.
bce_alm_die.alm
bce_alm_die wipes out the bce toehold and enters a "dis"
state.
bce_appending_simulation.pl1
All references to absolute and virtual addresses within the
saved Multics image are performed by bce_appending_simulation.
It has multiple entrypoints for its functions.
The "init" entrypoint must be called before all others. It
initializes certain purely internal variables, for later effi-
ciency. Also, it determines, from scs data, the valid range of
memory addresses so it can later validate addresses before
faulting. As an added bonus, it sets the initial dbr for the
appending simulation based on whether it is desired to examine
the crash image or bce itself.
The entrypoint "new_dbr" sets a new dbr for the simulation.
This entrypoint takes apart the dbr supplied. The main purpose
of this entrypoint is to find this new address space's dseg, so
it can evaluate virtual addresses. This fetching of the descrip-
tion (aste/page table/sdw) of dseg can be done using the absolute
fetching routines of bce_appending_simulation and by manually
disecting sdws and ptws. This entrypoint must also find the
core_map, if present, which is needed by the virtual entrypoints
to find out-of-service pages.
The "(get put)_(absolute virtual)" address entrypoints
actually perform the fetching or patching of data. They take the
input address and fetch or replace data in pieces, keeping each
piece within a page. This is done because different pages
desired may reside in totally different locations.
"get_absolute" and "put_absolute" work in relatively simple
ways. They examine the address to determine its location. Some
low memory pages will be in the image on disk and fetched through
the paged abs-segs multics_(low high)_mem. Other pages are in
memory (above 512k). These are fetched through the abs-seg
abs_seg0 which this program slides onto a 256k block as needed.
References to absolute locations in examine-bce mode always use
the abs_seg0 approach to fetch everything from memory.
Before virtual addresses may be fetched/patched, the
"new_segment" entrypoint must be called. The purpose of this
entrypoint is to fetch the sdw/aste/page table for the segment
for later ease of reference. This is done by using the
"get_virtual" entrypoint, referencing dseg data given the previ-
ously discovered description of dseg (in the "new_dbr"
entrypoint). For efficiency in fetching the sdw (meaningful for
the dump command which calls this entrypoint for every segment
number valid in a process and ends up fetching null sdws), a dseg
page is kept internal to this routine.
Virtual addresses are manipulated by the "(get
put)_virtual" entrypoints. These entrypoints break apart the
request into blocks that fit into pages. For each page of the
segment that it needs, it examines its ptw (found in the segment
description found and provided by the "new_segment" entrypoint)
to determine its location. Pages flagged as in memory are
obtained by the absolute entrypoint. Pages on disk can be easily
manipulated by mapping rdisk_seg onto the page and paging it. If
it is in neither catagories, something is either wrong or the
page is out of service. For out of service pages (pages with i/o
in progress upon them), the "correct" page is found (the page at
the source of the i/o) and this manipulated. If this is a put
operation, it is necessary to replace this page in both locations
(both memory and the disk page in use) to make sure that the
effect is felt. Also, for any put operation, the proper page
table word must have its modified bit set so page control notices
the modification.
bce_check_abort.pl1
bce_check_abort contains the logic for possibly aborting
bce functions upon operator request. When called, it checks
wired_hardcore_data$abort_request, which is set by ocdcm_ whenev-
er an unsolicited request is hit. If this bit is set,
bce_check_abort prompts the operator with "Abort?" to which the
response determines the degree of abort. Both this query and the
response i/o are performed through bce_data$console_[whatever] to
force them to appear on the console. A response of "no" simply
returns. "yes" and "request" signals sub_request_abort_, which
is intercepted by the bce_exec_com_ and bce_listen_, or by a bce
subsystem. Entering "command" signals request_abort_, handled by
bce_exec_com_ and bce_listen_ to abort a subsystem. Entering
"all" performs a non-local goto to <sub-sys info>.abort_label,
which returns to bce_listen_ at top level.
bce_check_abort is called on the output side of
bce_console_io and other output oriented bce i/o modules. Thus,
most operations will notice quickly the operator's intent to
abort. However, any program that can enter an infinite
computational loop (such as the exex_com processor trying to
follow an infinite &goto ... &label loop) must call
bce_check_abort within the loop to provide a way out.
bce_command_processor_.pl1
This routine is a scaled down version of
command_processor_. It does not support active functions or
iteration sets. Written as such, it does not need the various
work areas that command_processor_ needs and can run completely
wired. It separates the command line into the usual tokens,
forming an argument list of the various argument strings. It
uses a routine supplied in its call to find an entry variable to
perform the command found. It is used in various very early
initialization programs like init_clocks and find_rpv_subsystem
(which obviously cannot page) as well as some bootload Multics
programs that can deal with the simplicity and wish not to power
up command_processor_.
bce_console_io.pl1
bce_console_io is the interface to the console dim ocdcm_.
Its function is to perform translation appropriate to the console
(oc_trans_input_ and oc_trans_output_) and to call
ocdcm_$priority_io to perform the i/o. bce_console_io$get_line
is the routine normally found in the entry variable
bce_data$get_line and bce_console_io$put_chars is the routine
normally found in bce_data$put_chars and
bce_data$error_put_chars.
bce_continue.pl1
bce_continue restarts the interrupted image. It flushes
memory and uses pmut$special_bce_return to invoke the toehold.
As it passes, it resets all rtb flags in the flagbox except
ssenb. This is so that the next return to bce does not show the
current rtb flags.
Also present in this module is the bos command, which
flushes memory and uses pmut$special_bce_return to invoke the BOS
toehold.
bce_data.cds
This cds segment contains data pertinent to the command
environment activities of bce. It holds the entry and data
pointers used to perform i/o on the pseudo switches
bce_data$get_line, bce_data$put_chars, bce_data$error_put_chars
and bce_data$exec_com_get_line. It keeps track of the current
exec_com level, through bce_data$command_abs_data_ptr (part of
the exec_com_get_line switch). It also holds the top level
subsystem info for the command level in bce_data$subsys_info_ptr.
bce_die.pl1
This module just checks to see if it is okay to die, which
is actually performed by bce_alm_die.
bce_display_instruction_.pl1
One of the bce_probe support utilities,
bce_display_instruction_ displays one (possibly multi-word)
instruction. It uses op_mnemonic_ for its information. The
result is to print an instruction and to return the number of
words dumped.
bce_display_scu_.pl1
bce_display_scu_ is another bce_probe utility. It displays
the scu data found in machine conditions supplied to it.
bce_display_instruction_ is used to interpret the instruction
words from the data.
bce_dump.pl1
The disk dumping facility of bce is found in bce_dump. It
is actually a rather simple program but with a few tricky special
decisions made within it. After parsing the command line
arguments, it figures out the process and segment options to use.
These options are merged together in a hierarchical fashion; that
is, options applying to all processes apply to eligible; all that
apply to elgible apply to running, etc. The dump header is
filled in with machine state information from the toehold. The
dump header on disk is flagged as invalid. An abs-seg (dump_seg,
created by establish_temp_segs) is built to run down the dump
partition during segment placing. Given this out of the way,
dumping can start. Each apte is read from the saved image
(through bce_appending_simulation). For each, the segment
options applying to each are determined. Given the segment
limits in the dbr for this process, each segment is examined to
see if it meets the segment options. Most of the options are
self-explanatory. When it comes to dumping non-hardcore seg-
ments, though, it is desired to dump any hierarchy segment only
once. This is done by keeping a pseudo bit-map of the sst, where
each bit says that a segment has been dumped. (Since the
smallest possible aste in the sst is 16 words, there can be at
most 256K/16 astes. Given an address within the sst from a
segments' sdw, we assume that any aste that crosses the mod 16
boundary near this address describes the same segment as this and
need not be dumped again.) If a segment is to be dumped, we read
pages from its end, looking for the first non-null page. All
pages from the beginning of the segment up to and including this
page are appended to the dump. (The dump_seg abs-seg is adjusted
to indicate these pages.) When all is dumped, we update the
header and write it out.
bce_error.pl1
A simplified form of com_err_, bce_error simply fetches the
text of an error message from error_table_ and constructs an
error message which is printed through bce_data$error_put_chars.
The com_err entrypoint is used to format a com_err_ style
message, used by com_err_ when called during initialization.
bce_esd.pl1
An emergency shutdown of Multics is initiated by bce_esd.
It uses bce_continue to invoke the toehold to restart the image.
However, before doing this, it patches the machine conditions in
the toehold to force the image to transfer to
emergency_shutdown|0, to perform an esd.
bce_exec_com_.pl1
bce_exec_com_, along with bce_exec_com_input, form the bce
equivalent of version 1 exec_com's. bce_exec_com_ is a merging
of functions found in exec_com with those found in
abs_io_$attach. It finds the ec and builds an appropriate
ec_info and abs_data structure to describe it. The ec attachment
is made (bce_data$exec_com_get_line) is made to refer to this ec
invocation, after saving the previous level. Commands are read
from the ec through bce_exec_com_input and executed through
command_processor_$subsys_execute_line. Once bce_exec_com_info
returns a code for end of file, the ec attachment is reverted.
bce_exec_com_input.pl1
bce_exec_com_input performs the parsing of exec_coms. It
is a pseudo i/o module, in the style of bce_console_io$get_line.
It is called in two possible cases. The first is to fetch a
command line for execution by bce_exec_com_. In this case, the
switch is bce_data$exec_com_get_line. When an &attach appears in
an ec, bce_exec_com_input will have attached itself (by making
bce_data$get_line point to itself) and then calls to
bce_data$get_line will call bce_exec_com_input for a line where
the switch (bce_data$get_line) will point to the abs_data for the
ec that performed the &attach. The basic code is stolen from
abs_io_v1_get_line_. The major changes are to delete
non-meaningful operations like &ec_dir.
bce_execute_command_.pl1
This routine is the caller for the various bce command
programs. It is passed as an argument to, and is called, from
command_processor_$subsys_execute_line. It is given a pointer to
an argument list generated by command_processor_, as well as the
request name. bce_execute_command_ uses bce_map_over_requests_
to scan through bce_request_table_ to find the entry to call. It
understands the difference in calling between Multics routines
(like active functions stolen from Multics) and bce routines. It
also understands the flags indicating within which command levels
a command is valid.
bce_fwload.pl1
Firmware is loaded into various mpcs by bce_fwload. Its
objective is to find, for each mpc desired, the set of firmware
images needed for it. hc_load_mpc does the actual loading. For
a normal (disk, tape) mpc, this involves just finding the mpc
card which shows the model. The model implies the firmware
module needed (config_data_$mpc_x_names.fw_tag). The desired
module is found through slt_manager. (Firmware images for disk
were part of collection 1 and are wired (they needed to be in
memory to be able to load the rpv controller); other images were
part of paged collection 1.5.) For urc controllers, the main
firmware can also be derived from the mpc's mpc card. However,
it is necessary to check all prph cards to find peripherals
accessible through that urc. For each, and depending on the urc
channel it is attached to, the appropriate firmware overlay is
found and put in the correct slot in the list of firmware to
load.
bce_get_flagbox.pl1
This module performs the bce (get set)_flagbox
commands/active functions. It is basically a version of the
corresponding Multics routine, modified to make direct references
to the flagbox instead of a gated access.
bce_get_to_command_level.pl1
The routine to get from real_initializer into command level
is bce_get_to_command_level. It builds a bce_subsystem_info_
structure which it passes to bce_listen_. It examines the
current state to determine if the initial command should be null
(manual entry), the flagbox bce command (normal) or probe
(breakpoint entry). Since it is the routine below
real_initializer on the stack, it is the routine to which control
must return so that real_initializer can be returned to to
perform boot and re_initialize functions. Thus, boot and
re_initialize are entrypoints within this program. re_initialize
just returns, setting the collection_1_phase to "early" so that
real_initializer will end up running another boot pass. This
will cause bootload Multics to pick up any changes that have been
made to the config_deck. boot scans the arguments which are
inserted into the intk card. It then returns.
bce_inst_length_.pl1
Another bce_probe utility. This routine is used to deter-
mine the length of an instruction, so that it may be correctly
relocated. It differs from the real probe's version in that it
does not attempt to deal with xec instructions.
bce_list_requests_.pl1
This program implements the list_requests (lr) bootload
Multics command. It does a simple minded walk down the bootload
Multics request table, using bce_map_over_requests_, with a
printing routine to print the request names and the description
within the table. It understands the dont_list flag, as well as
understanding flags indicating at which levels a given command is
valid.
bce_listen_.pl1
bce_listen is a simple loop that reads a command line from
bce_data$get_line and executes it through command_processor_
(using bce_execute_command_ to actually execute the request). It
contains the sub_request_abort_ and request_abort_ handlers to
work with the operation of bce_check_abort.
bce_map_over_requests_.pl1
Programs that wish to walk down the bootload Multics
request table (bce_list_requests_ and bce_execute_command_) call
bce_map_over_requests_ with a routine that is called on each
entry in the table. As such, the format of the table itself is
known only to this routine.
bce_name_to_segnum_.pl1
This bce_probe utility maps segment numbers to names. It
searches the slt and name_tables from the saved image.
Entrypoints exists to convert a segment number to a hardcore
segment name (bce_segnum_to_name_), a segment pointer to a
virtual name (bce_segptr_to_name_), and a segment name to a
segment number (bce_name_to_segnum_).
bce_probe.pl1.pmac
The main portion of bce's probe support, bce_probe contains
the main drivers for most of probe's facilities. It contains the
request line parser, address and value parsers and most of the
functional routines.
bce_probe starts by examining its arguments and its envi-
ronment to determine its operating mode. It defaults to
examining the breakpoint image if the flagbox indicates a break,
to examining the crash image, when at bce_crash or crash command
levels or to examining bce otherwise. Given its operating mode,
it initializes the appending simulation package accordingly and
establishes a few initial constants. If in break mode, it
determines the point of break for operator information.
bce proceeds to read request lines from the console. The
first "string" in the line (or partial line left, if this is a
multiple request line) found by internal routine get_string
becomes the request name. This is looked up in a table and
dispatched through a "case" statement.
REQUEST ROUTINES
The before request finds the desired address. It is
validated to ensure that it is virtual and that the segment named
is breakpointable. Finding the breakpoint page for this segment,
this request looks for an empty break slot. The original
instruction is relocated there (bce_relocate_instruction_) and
replaced by a transfer to the break block. The break block
consists of a "drl -1" instruction, which causes the break,
followed by the relocated instruction, followed by a transfer
back to just after the original instruction in the code. This
break block and the transfer to the block are patched into the
segment such that failure at any time will not damage the
segment.
The continue request validates itself and calls
bce_continue.
The dbr request fetches its arguments. Constructing a new
dbr, it calls internal routine new_dbr.
The display request gets and validates its arguments. It
loops, fetching (through bce_probe_fetch_) at most a page at a
time to display (since we only allocate a one page buffer for the
fetch). The internal routine "display" displays the data in the
specified mode. Since data to be displayed may cross page
boundaries, any data "display" cannot display (because it would
need data from the next page to fill out a line) is "scrolled" in
front of the page buffer and a new page worth's of data fetched.
This continues until the last page is fetched.
The let request finds the address and sets up for patching
of same. It then loops, finding values from the request line,
converting them to binary. These are appended unto a word based
buffer. When all are fetched, they are patched into place.
The list_requests request simple prints a canned list of
requests.
The mc request gets its address and uses bce_display_scu_.
The name request uses bce_segnum_to_name_.
The proc request fetches the desired apte from tc_data in
the image. A new dbr value found therein is passed to internal
routine "new_dbr".
The quit request quits.
The reset request performs the inverse of the before
request. After validating its address (for virtualness,
breakpointability, etc.), it undoes the effect of before, in
reverse order to prevent damage to the segment.
The segno request uses bce_name_to_segnum_.
The stack request validates its argument. Given the word
offset therein, it decides whether to start from the specified
stack header or frame. The needed data is fetched and displayed
in interpreted form. Each stack pointer fetched is validated,
not only to insure that it is a valid pointer, but to insure that
stack frame loops do not cause bce probe loops.
The status request uses the internal routine "status" to
display breakpoints set. It simply validates its argument and
decides between listing breakpoints for a segment versus listing
breakpointed segments.
INTERNAL ROUTINES
check_no_more_args insures that no more arguments appear on
the request line; that is, that we are looking at a semi-colon or
new-line.
display displays data in a specified mode. It determines
the bit sizes to display, alignments, etc. Its only trick is
when processing the end of a buffer full that doesn't fill a
display line. This causes it to not finish its display. Its
caller (the display request) then appends what was not displayed
to the front of the next buffer full so that it may appear in the
next group.
function is used to parse functional references, such as
"reg(ralr)". function extracts the arguments to the function
(whose identity was determined by its caller), builds an argument
list from these strings, and calls the function.
get_address contains the logic to parse a bce probe
address. It fills in the structure, bce_probe_data$address to
define the current address. It special cases the dot (".")
forms, checks for virtual forms (those with a "|" in them),
notices absolute addresses (single octal number) and uses func-
tion for the pseudo-variable type of addresses (reg and disk).
Internal routines to get_address, called by function, build the
address structure for these types.
get_string finds the next "string" in the request line.
Its basic job is to pass whitespace and find string delimiters.
get_value finds a let request value. It looks for ascii
strings (values starting with a quote character), which it must
parse separately (since quoted strings confuse the notion of
string contained in get_string), finds virtual pointers (strings
containing "|"), and finds the various numeric types.
line_error is used to print error messages. Besides
printing the given message, optionally with or without the
current request line arg or error code, it also aborts the
current request line.
new_dbr is the counterpart to the new_dbr entrypoint to the
appending package. It exists to set up references to a few
popular segments (slt and name_table) whenever the dbr changes.
pass_white passes whitespace.
status displays breakpoint status. Since break blocks are
zeroed when not in use it is possible to find them easily. For
any segment listed in the image's slt as being breakpointable,
status fetches the last page (that which holds the breakpoints)
and examines each break block. Any with a valid
original_instr_ptr are displayed.
bce_probe_data.cds
Information communicated between probe and its support
routines is done so through bce_probe_data. This cds contains
the current value of "." (current address), as well as pointers
to bce_appending_seg_info structures describing key segments in
the image used by the support routines.
bce_probe_fetch_.pl1
This support utility to bce_probe fetches data, given a
length and the current address (in bce_probe_data$address). It
simply uses bce_appending_simulation for absolute and virtual
address and read_disk for disk addresses. Register addresses
must be specially handled by the caller.
bce_query.pl1
bce_query is a simple-minded counterpart to command_query_.
It uses bce_data$put_chars to print a question and
bce_data$get_line to read an answer. The main entrypoint accepts
any answer and bce_query$yes_no accepts only yes or no which it
returns as a bit. This routine is called with no prompt by some
routines who find its return result (char (*)) to be better that
the buffer and length and return length returned by
bce_data$get_line.
bce_ready.pl1
bce_ready prints the bce ready message:
bce (BCE_COMMAND_LEVEL) TIME:
It has a nnl entrypoint to print the message without new-line (as
a prompt), The normal entry prints the line (for ready message
within exec_com).
bce_relocate_instruction_.pl1
This is another support routine for bce_probe. It differs
from the standard Multics version in that it does not allow
relocation of "xec" instructions. (Service probe allows this by
attempting to examine the target of the xec, something bce_probe
does not attempt.)
bce_request_table_.alm
The bootload Multics request table is a normal ssu_ request
table built with ssu_request_macros. Each entry contains a
pointer to the routine that performs a request, the name and
short name of the request, and a short description of the
request. The actual threading of the entries is known only to
bce_map_over_requests_, which performs the walking down of this
table. The last three flags in each rq_data entry is used to
specify whether the command is valid at the three main bce
command level types: early, boot and crash.
bce_severity.pl1
This is the bce counterpart to the Multics severity
command/active function. It does not work as the Multics routine
does, however. Instead, it knows the set of programs that
recognize a severity indicator. For the desired one, it calls
the severity entrypoint thereof to find the severity.
bce_shutdown_state.pl1
The current shutdown state of the storage system (rpv
label.shutdown_state) is found by this routine. It uses
read_disk to find this information.
bootload_disk_post.pl1
This routine is used in conjunction with the high volume
disk facility of bce (dctl$bootload_(read write)). Whenever a
disk i/o queued through this means is posted for completion, it
is done so through bootload_disk_post, called by either dctl or
disk_control. The result is posted in a structure described by
bootload_post_area.incl.pl1. This area must be maintained by the
caller.
bootload_fs_.pl1
bootload_fs_ contains various routines to act upon the
bootload Multics file system. The format of the bootload Multics
file system is known only to this program. The file system is
kept in a single abs-seg (bootload_file_partition), mapped (and
paged) off the bce partition on the rpv. A two page header at
the start of the partition contains a directory of 174 entries
(max that fits) listing the name, size and placement of the file
within the segment. Also present is a free block map. Files are
allocated as a contiguous series of blocks (64 word blocks)
within the segment. The segment is automatically compacted by
this routine when necessary. Entrypoints to this routine are:
lookup (find the length of a file given its name), list
(allocates a list of file names and sizes within a user supplied
area), get (copies a file into a user supplied buffer), get_ptr
(returns a pointer and length to a given file (hcs_$initiate?)),
put (allocates area within the file system for a file and copies
a user supplied buffer into it), put_ptr (allocates an area
within the file system large enough for a given file and returns
a pointer to it) (both put and put_ptr take an argument allowing
for the deletion of a file with the same name as the one
desired), delete (deletes a directory entry and frees the space
used), rename (renames a file (does not allow name duplication)),
and init (clear out the bootload file system entirely).
bootload_fs_cmds_.pl1
This program simply calls bootload_fs_ to perform the
functions of the bootload Multics commands print, list, delete,
rename, and initialize. This routine supports the star and equal
conventions for most of its operations through match_star_name_
and get_equal_name_.
bootload_qedx.pl1
bootload_qedx is a modified version of qedx. It differs in
its use of file system operations (bootload_fs_) and its use of
temp segs.
config_deck_data_.cds
The config deck editor's source of config card descriptions
is found in config_deck_data_. This cds provides labels for the
fields, numbers and types of fields, etc.
config_deck_edit_.pl1
This is the program that edits config decks. It calls
qedx_ to perform text editing, specifying the caller_does_io
option. With this option, qedx_ calls config_deck_edit_ to
perform read and write operations on buffers. Any read/write not
to the config deck uses bootload_fs_. Reads/writes to <config
deck> (buffer 0) use the config deck conversion routines. This
program makes use of config_deck_parse_, the routine that can
convert from ascii (possibly labeled) form to and from binary
form. The conversions are performed using a set of tables
(config_deck_data_) that describe the names of the fields, the
required and optional number thereof, the data types of the
fields, etc. Also allowed by the conversion routines are cards
of types not recognizable starting with a dot (.) which are not
validated. This is to allow for future expansion and site
formatted cards.
When a command line argument is supplied, the file
specified is accessed (bootload_fs_$get_ptr) and the object
obtained is supplied to the internal routine write_config_deck
which sets this new deck.
establish_temp_segs.pl1
Whenever bce needs (paged) temp segments, it calls
get_temp_segments_. get_temp_segments_ gets these segments from
the pool of segments bootload_temp_1..N. establish_temp_segs
divides the temp seg pages allocated in the bce partition (128
pages) up into the N segments (N is determined from the number of
such segments listed in the mst header). The paged segments are
built as abs-seg's onto this area of the determined length. This
size is saved in sys_info$bce_max_seg_size. establish_temp_segs
also creates the bce segments multics_(low high)_mem, used to
access the saved image, and dump_seg, used to access the dump
partition.
find_file_partition.pl1
find_file_partition maps the bootload Multics file system
abs-seg (bootload_file_partition) onto the bce partition on the
rpv in much the same manner as establish_config_deck maps the
config deck. It also calls bootload_fs_$init to begin accessing
the segment. If bootload_fs_ states that the file system is bad,
find_file_partition will call bootload_fs_$init again, this time
to clear out the file system.
init_bce.pl1
init_bce initializes the bootload Multics command environ-
ment features required for future programs. It is called early
in initialization. At its wired entrypoint, it sets up
free_area_1 as an area, setting the inzr_stk0 stack header to
point to it so that allocates without an area work correctly and
so that get_system_free_area_ also works. This routine also
initially sets bce_data$get_line, bce_data$put_chars and
bce_data$error_put_chars to their appropriate entry values
(bce_console_io$get_line, bce_console_io$put_chars and
bce_console_io$put_chars, respectively) so that calls to
bce_query, bce_error and especially ioa_, will work. At its
paged entrypoint, it finishes up references to paged objects, in
particular, to the exec_com routines.
SECTION 5
CRASH HANDLING
Bootload Multics must be able to save the salient state of
a crashing system and set up the command environment for dumping
and other intervention.
EARLY CRASHES
Crashes in collection 0 or the early initialization pass of
collection one should be very rare. Since the system uses a
generated config deck, the set of possible operator inputs is
small, and it is possible to do a much more thorough job of
testing than can be done with BOS or service initialization.
However, hardware problems will happen, and software bugs will
sneak through. To cover these cases, collection 0 includes a
crash handler that can write a core image to tape, prompting the
operator for the drive number.
THE TOEHOLD
The toehold, toehold.alm, is an impure, wired, privileged
program that resides in a known location in absolute memory
(24000o). It has entrypoints at the beginning that can be
entered in one of two ways: with the execute switches processor
function, or by being copied into the fault vector. The toehold,
therefore, is entered in absolute mode. It must save the 512K
memory image off to disk, and then load in the crash handler.
The memory image includes the complete machine state. All
absolute addresses, channel programs, port and channel numbers,
and other configuration dependent information is stored into the
toehold by a PL/I program, init_toehold.pl1. Thus the alm code
does not have to know how to do any of these things, which
simplifies it considerably.
The toehold starts with the various entry sequences; one
for manual entry, one for Multics entry (which differs from
manual entry in that the means of entry is to execute the entry
through a fault vector entry; it is necessary to update the
machine conditions in this case to pass the instruction that
caused the fault vector execution) and one for restarting the
machine image. The crash entries save the entire machine state.
This is done under the protection of the memory_state so that the
machine state is not overwritten if the toehold is invoked again
after being invoked after a crash. An internal routine performs
i/o given a set of dcw lists (built by init_toehold). After the
memory is saved and the crash handler read in, the machine state
of bce is restored. (It was saved by save_handler_mc.) This
causes a return into save_handler_mc, which quickly returns to
init_toehold, which quickly returns to real_initializer who
quickly starts the appropriate crash initialization pass.
On the restore side, the system is masked and the internal
routine called to read back the saved image. The machine
conditions are restored from the toehold (which is not
saved/restored during the memory shuffle).
MODULE DESCRIPTIONS
fim.alm
fim is listed in the crashing set of modules in as much as
that it contains the bce breakpoint handler. A bce breakpoint
consists of a "drl -1" instruction. fim's drl handler special
cases these (in ring 0), saves the machine state in
breakpoint_page (after advancing the ic to pass the drl instruc-
tion) and calls pmut$bce_and_return. It also performs the
restart from a breakpoint.
init_toehold.pl1
This pl1 program constructs the channel programs to save
and restore the 512K memory image, and fills it and other data
into the text of toehold. After saving the bce image (crash
handler) on disk, it calls save_handler_mc to save the current
machine state of bce in the toehold. When bce is invoked upon a
crash, the bce restore operation will return to the return in
save_handler_mc which will return to this point in init_toehold.
init_toehold notices this and quickly returns to real_initializer
who will perform the desired crash initialization pass.
save_handler_mc.alm
The save_handler_mc program, called from init_toehold right
after it saves the crash handler to disk, saves in the toehold
the machine conditions appropriate for bce. Besides register
contents and such, it saves the return address to the return in
save_handler_mc.
SECTION 6
COLLECTION 2
The main task of collection 2 is to make the storage system
accessible. Along its way, it loads collection 3 into the
storage system and places the appropriate entities from collec-
tions 1 and 2 into the hierarchy. The sub-tasks are to enable
segment control and directory control. The real traffic control
is also started. Since collection 2 runs in a paged environment,
it does not have the memory restrictions that collection 1 had.
This is the reason why it is in a different collection from
collection 1.
ORDER OF EXECUTION
The operations performed in collection 2 are described
below.
initialize_faults$fault_init_two is called to change the
fault vectors into the desired values for normal service opera-
tion, now that the code for such has been loaded.
Initialization now runs performing several intermingled
functions. All hardcore segments must be created now, before
traffic control is fully initialized. This is so that the
address space inherited by the new processes (idle in particular)
encompasses all of hardcore.
tty_buf, tty_area and tty_tables are generated through a
call to fnp_init. They won't be needed at this time but must be
allocated before tc_init$part_2.
Unique id (uid) generation is initialized by a call to
getuid$init. This is required before segments in the hierarchy
(in particular, >sl1 and >pdd) can be created.
init_vtoc_man allocates and initializes the
vtoc_buffer_seg. We are therefore eligible to read and write
(and create) vtoces.
dbm_seg is allocated and initialized to an area by
dbm_man$init. init_scavenger_data allocates the scavenger_data
segment, used by the volume scavenger. The page control data
base, dm_journal_seg_, used to control synchronous page opera-
tions (data management), is initialized by init_dm_journal_seg.
dir_lock_seg, used to keep track of directory lockings and
waitings thereupon, is initialized by dir_lock_init. Again,
these are created before tc_init$part_2 is run.
After this point, changes to the hardcore descriptor
segment may not be reflected in idle process and hproc descriptor
segments. This is because init_sys_var, which sets various
system variables, uses the number of supervisor segments present
(which is the expected total set thereof) to set the stack base
segment number in various variables and in the dbr.
We can now run tc_init$part_2, which creates the idle
processes and starts multiprogramming. At this time, only the
bootload cpu will be running but the idle process will be enabled
to run on it.
With multiprogramming active, syserr_log_init can create
the syserr hproc (after it makes the syserr partition accessi-
ble). We then log a message to the effect that this was done.
The activation of segment control, which began with the
creation of the sst, continues now with the creation of the
system trailer seg (str_seg) by init_str_seg. If the astk (ast
track) parm was specified, init_sst_name_seg initializes the
sst_names_ segment with the names of paged hardcore segments.
The entrybounds of hardcore gates are set via a call to
init_hardcore_gates, which also stores linkage pointers into the
gates for a reason described under the description of the
program.
We can finally make the volumes of the rlv accessible for
storage system activity by a call to accept_rpv. This sets up
the volume and vtoc maps and stocks for the drives, allowing
vtoc_man and the page creation/destruction functions to work
against the paging region of the disks.
The logical volume table (lvt) is initialized to describe
the rlv by init_lvt.
bad_dir_ and seg_fault_handlers are now set up as we are
about to access our first directory. init_root_dir makes the
root directory known in the Initializer's process, creating it if
this is a cold boot. The functions performed here are those that
will allow future hierarchy segment references through segment
control (kst creation, in particular). kst_util$garbage_collect
is called just to make the kst neat. At this time, we can
consider segment control to be active. We can call upon it to
create, delete or whatever. The presence of the root will allow
these activities by virtue of the special casing performed by
segment control when it discovers a segment with no parent (the
root).
The hardcore entities which need to be placed into the
hierarchy (deciduous segments) are done so by init_branches,
which also creates >sl1 and >pdd appropriately. These entities
will be needed when we try to leave ring zero. Of course, other
required segments are needed; these are the contents of collec-
tion 3.
init_stack_0 then runs to create the various stack_0's to
be shared between eligible processes, now that it has a place to
put them.
delete_segs$temp can now run, deleting collection 2 tempo-
rary segments. This ends collection 2.
MODULE DESCRIPTIONS
accept_fs_disk.pl1
A disk is accepted into the file system by accept_fs_disk.
It validates the pvte for the disk. The label is read. (If this
is a pre-MR10 pack, salvage_pv is called to convert the vtoc
region for stock operations.) The pvid and lvid of this disk are
copied into the pvt, finally making this data valid. The volmap
and vtoc map are initialized and the stocks made active by
init_volmap_seg. If this fails, the volume salvager is called
and we try again. The partition map from the label is checked
against the volmap to make sure that no partition claims pages in
the paging region. The updated disk label is written out as we
exit.
accept_rpv.pl1
The volumes of the rlv are accepted for storage system use
by accept_rpv. First, the various disks that have hardcore
partitions are validated, from their labels, to be part of the
rlv. We then scan the intk card to see if the rpv or rlv desire
salvaging; these facts are stored in the pvt. If the rpv needs
salvaging, this is done now (salvager$volume_salvage). For
information purposes, we log (or print, if the hcpt parm was
specified), the amount of the hardcore partition used on the
various disks. accept_fs_disk is called to accept the rpv in the
normal way. wired_shutdown is enabled as the storage system is
considered to be enabled. Appropriately, make_sdw$reset_hcp is
called to prevent further attempts to allocate from the hardcore
partition. Contrary to the name (accept_rpv), the entire rlv is
accepted next by calling the salvager, if necessary, and
accept_fs_disk for the other rlv volumes. We can then clear
salv_data$rpv to keep the salvager from salvaging the rpv later.
create_root_dir.pl1
During a cold boot, the root is initialized by
create_root_dir. It locks the root, setting its uid to all ones.
The various dir header variables are set, pvid, master_dir flag,
etc. A directory style area is set up along with a directory
hash table. The dir is then unlocked and we exit.
create_root_vtoce.pl1
create_root_vtoce creates a vtoce for the root directory
during a cold boot. The vtoce created describes the root as a
master directory of appropriate length, maximum quota limit,
created as of the current time, primary name of ">", etc.
vtoc_man is used to allocate space in the vtoc map for this and
to write it out.
dbm_man.pl1
dbm_man manages the dbm_seg (dumper bit map) for the volume
dumper. The init entrypoint used during initialization allocates
and initializes the dbm_seg. Its size is determined from the
number of disk drives configured and allocated out of the
hardcore partition by make_sdw. This routine changes dbm_seg
from its MST status (an abs_seg) to being a real segment.
dir_lock_init.pl1
The segment used to keep track of directory lockings and
waitings thereupon, dir_lock_seg, is allocated and initialized by
dir_lock_init. The size of this segment is based upon
max_max_eligible (the maximum number of readers of a lock) and
sys_info$max_tree_depth (maximum lock depth one can hold). The
dir_lock_seg is converted from an abs_seg to a real seg, paged
out of the hardcore partition. Initially, ten dir_lock's are
allocated, threaded appropriately.
fnp_init.pl1
fnp_init initializes the data bases used in Multics-fnp
communication. tty_buf is allocated in wired memory either with
a default size or a size specified by the ttyb parm. Various
header variables are set up. If a tty trace table is called for
by a config parm, it is allocated in the tty_buf free_space area.
tty_area is initialized as an empty area. tty_tables also has
its header filled in and its table_area set to an empty area.
The config file is scanned for fnp cards; each one sets the
fnp_config_flags appropriate to it. The hardware fixed
dn355_mailbox for each fnp is zeroed. fnp_info is set. Finally,
io_manager$assign is called to assign each fnp with an interrupt
handler of dn355$interrupt.
getuid.alm
getuid is the generator of uid's (unique identifiers) for
storage system objects. It operates by effectively incrementing
tc_data$id under its own form of lock. The init entrypoint used
during initialization stores an initial uid "seed" in tc_data$id
generated from the clock value.
init_branches.pl1
The program that places the appropriate hardcore segments
into the hierarchy, creating >sl1 and >pdd as it goes, is
init_branches. To start with a clean slate, it renames the old
>process_dir_dir and >pdd to a screech name. append then creates
a new >process_dir_dir (added name of >pdd) which is then
initiated. The per_process sw is set on for this dir. It is
given the maximum quota possible. The old >system_library_1
(>sl1) is also renamed and a new one created and initiated.
Access is set to s for *.*.* on it. We then walk down the
various sst pools looking for segments to have branches created.
The sst entry leads us to the slt entry for the segment to be
placed in the hierarchy. create_branch is called (running
recursively) to create a branch for the segment (it creates all
necessary containing directories and a vtoce for the segment). A
pointer to the parent directory and its aste is found. The aste
for the hardcore segment is threaded into the parent entry. The
per_process sw, max_length and uid fields are set in the aste.
It is then threaded out of the hardcore lists and into the
appropriate segment list. The vtoc index provided for the
segment (found in its entry in the parent directory) is copied
into the aste so vtoc_man will work. The entrybound of the
segment is placed into the directory entry. If aste tracking is
going on, a sstnt entry is added. Its vtoce is updated, putting
the correct information from the initialization created aste into
the vtoce. The parent directory is then unlocked and terminated.
The per_process sw is turned on in the aste for >pdd so
that it can propogate down to sons activated off it. We walk
down >pdd to propogate this switch. The maximum length of the
slt and name_table are explicitly set, not trusting the slte
fields for them. A maximum quota is reset on >pdd. The default
acl term of sma *.SysDaemon is removed from >pdd and the acl term
of sma Initializer.SysDaemon.z is added. >dumps is created and
salvaged if needed. The hierarchy is now properly created and
active.
init_dm_journal_seg.pl1
init_dm_journal_seg initializes the page control data base
dm_journal_seg_ used to control synchronous page operations.
This routine parses the dbmj card. This card describes the sizes
of the various journals needed. Once the size of dm_journal_seg_
is found, its memory (wired) is obtained from make_sdw. Various
header parameters (pool thresholds, pages held, events) are
filled in. The various journal entries have their time stamp
initialized to tc_data$end_of_time. The various page_entry's are
threaded into a list. After this, sst$dm_enabled is set for the
world to know.
init_hardcore_gates.pl1
init_hardcore_gates performs a variety of functions to make
those things which are hardcore gates into future usable
entities. It recognizes anything in the slt with ring brackets
of 0, 0, n as a hardcore gate. It finds within the text (given
the definitions) the segdef .my_lp and stores there (having
forced write access) the linkage pointer for the gate. This is
done because, the gate, known in outer rings by a segment number
different from the hardcore number, would not be able to find its
linkage by indexing into the lot by its segment number as normal
outer ring programs do. Given the segdef .tv_end found for the
gate, the entrybound is set in the gate's sdw. Finally, the ring
brackets for restart_fault and return_to_ring_0_ are set from
their slt values so that these segments may be used in outer
rings with their hardcore segment numbers. (return_to_ring_0_
has a pointer to it stored as the return pointer in the stack
frame by signaller. return_to_ring_0_ finds restart_fault
through a text imbeded pointer.)
init_lvt.pl1
The logical volume table is initialized by init_lvt. It
sets up the header and then uses logical_volume_manager$add to
add the entry for the rlv.
init_processor.alm
A processor is inited by init_processor. The init
entrypoint stores the absolute address of various variables into
init_processor itself for execution within absolute mode when
started on other cpus. When run to start a cpu, it performs some
collection of tests, enters appending mode, fiddles with associa-
tive memories and cache, informs pxss that it is running (through
its apte), initializes pds and prds time values, sends out a
connect to preempt the processor and then opens the mask to allow
interrupts. (We will be interrupted at this time (by the connect
we sent). This will cause us to find our way back to pxss to
schedule something to run on this processor.) The idle loop for
a processor is contained within init_processor following this.
The idle loop flashes a moving pattern in the aq lights when it
is on the processor. At this time, x4 contains the number of
eligible processes, x5 the term processid and x6 the number of
ready processes for the sake of checking system operation.
init_root_dir.pl1
The root directory is made known by init_root_dir. We
start by checking to see if this is a cold boot. If so,
create_root_vtoce is called. The root vtoce is read. An aste is
obtained for the root dir (64 pages), which is initialized from
the data in this vtoce. pc is used to fill the page table.
search_ast hashes in this aste. We can now begin the process
that will allow future segment accessing activity through segment
control. The Initializer's kst is built, by initialize_kst. The
pathname "associative memory" used to map segment numbers to
pathnames is initialized by pathname_am$initialize. makeknown_
is called to make the root (uid of all ones) known (found in the
kst). If this is a cold boot, this segment just made known must
be initialized to a directory by create_root_dir. Finally, this
directory is salvaged, if necessary.
init_scavenger_data.pl1
The segment scavenger_data is initialized by
init_scavenger_data.
init_sst_name_seg.pl1
The sst_names_ segment is initialized by init_sst_name_seg
whenever the astk parm appears. It walks down the slt, looking
for segments that are paged with page tables in the sst. For
each, it copies the primary name into the sst_names_ segment.
init_stack_0.pl1
The various ring zero stacks (stack_0) are created by
init_stack_0. Since a process cannot lose eligibility while in
ring 0, the number of processes that can have frames down on ring
zero stacks is equal to the maximum possible number of eligible
processes (max_max_eligible). We thus create this many ring 0
stacks which are used by eligible processes. The various
stack_0.nnn segments are created in >sl1. They are, in turn,
initiated, truncated, and prewithdrawn to be 16k long. The vtoce
is updated accordingly. The stack header from the initializer's
ring zero stack is copied into the header of these stacks. The
stack is then terminated. The acl for Initializer is removed.
The first stack slot is claimed for the Initializer; the current
stack being put into the slot in stack_0_data.
init_str_seg.pl1
init_str_seg initializes the system trailer segment
(str_seg) into a list of free trailer entries.
init_sys_var.pl1
Now that all of the hardcore segments have either been read
in or created, we can now stand back and observe hardcore. The
next supervisor segment number (mod 8) becomes the ring 0 stack
segment number (stack base) which is stored in
active_all_rings_data$stack_base_segno and hcscnt. We make sure
that the dsegs for the idle processes will be big enough to
describe these segments. The stack base is stored in the dbr
value in the apte. Various other system variables are set:
sys_info$time_of_bootload, sst$pvhtp (physical volume hold table
pointer), sst$rqover (record quota overflow error code, which is
moved to this wired place from the paged error_table_), and
sst$checksum_filemap (depending on the nock parm).
init_volmap_seg.pl1
init_volmap_seg initializes a volmap and vtoc map segment
allowing us to reference such things on a given physical volume.
It starts by acquiring an aste for the volmap_seg (for the
segment abs_seg) and one for the vtoc header (for the segment
volmap_abs_seg) (vtoc map) which are then mapped onto the desired
areas of the disk. (This is done under the ast lock, of course.)
The free count of records is redetermined from the volmap. The
same is done for the vtoc map. If this is a member of the rlv
and volume inconsistencies were previously found and the number
of free vtoces or records is below a certain threshold, a volume
salvage is called for. If we will not salvage, we can accept the
disk. Use of the hardcore partition on the disk is terminated
through a call to init_hc_part$terminate_hc_part. Vtoc and
record stocks are allocated. The pointers in the pvte to these
stocks are set as are various other status and count fields. The
number of free records and the base address of the first record
in each stock page is computed. The dumper bit map from the disk
is allocated into the dbm_seg (previously created by
dbm_man$init_map). Finally, under the ast lock, we clean up the
abs_seg and volmap_abs_seg segments (free their sdws).
init_vtoc_man.pl1
The vtoc_buffer_seg is initialized by init_vtoc_man. This
routine acquires enough contiguous memory for the
vtoc_buffer_seg, determining the number of vtoc buffers either
from the config vtb parm or from a default. Various vtoc buffer
headers are initialized here.
initialize_faults.pl1
initialize_faults was described earlier, under collection
1. The entry point fault_init_two, used by collection 2, sets up
fault vectors for normal (file system) operations. It prevents
timer run-out faults during operation through a call to pmut$ldt.
initialize_faults_data is used to set the main faults. Faults
set are: command, trouble, segment and linkage to
fim$primary_fault_entry (scu data to pds$fim_data), store, mme,
ft1, lockup, ipr, overflow, divide, df3, mme2, mme3, mme4 and ft3
to fim$signal_entry (scu data to pds$signal_data), and fault
numbers 26 to 30 to wired_fim$unexp_fault (scu data to
prds$sys_trouble_data). Access violations are routed specially
to fim$access_violation_entry which maps the acv fault into our
sub-faults. Timer runouts are sent to wired_fim$timer_runout
(who normally calls pxss) with the scu data stored in
prds$fim_data. Parity goes to fim$parity_entry. Finally, we set
up the static handlers for the no_write_permission, isot_fault
and lot_fault conditions.
kst_util.pl1
kst_util performs utility functions with regard to
maintaining the kst. The garbage collect entrypoint cleans up
the kst by terminating any segment not known in any ring or a
directory with no active inferiors.
start_cpu.pl1
start_cpu might best be described as a reconfiguration
program. It is used during initialization to start a idle
process on each configured cpu (at the appropriate time). When
starting the bootload cpu in collection 2, it fills in the apte
entry for the idle process for the cpu in question. Some more
variables in init_processor are set (controller_data). A simple
call out to init_processor$start_bootload_cpu can be made.
syserr_log_init.pl1
The syserr logging mechanism is made operative by
syserr_log_init. It creates the segment syserr_log which it maps
onto the log partition, wherever it is. A consistency check is
made of the partition; if the check fails, the partition is
re-inited. The syserr hproc (SyserrLogger.Daemon.z)'s ring 0
stack (syserr_daemon_stack) is initialized. The hproc is created
by create_hproc$early_hproc with a stack of syserr_daemon_stack,
dseg of syserr_daemon_dseg, pds of syserr_daemon_pds, and proce-
dure of syserr_logger. A fast channel is defined for communica-
tion through syserr_data to the hproc. Logging is now enabled.
tc_init.pl1
tc_init was described earlier to set up and initialize
tc_data. tc_init$part_2, in collection 2, starts up
multiprogramming by creating the idle processes. This entry can
only be called once the initialzer's dseg is completely filled in
by all those who read or create hardcore segments. Various
variables in template_pds are filled in which are applicable to
the idle processes. For each configured processor, a copy of
template_pds and the initializer's dseg is made into appropriate
entries in idle_dsegs and idle_pdses. The stack_0 for these
processes is made to be the prds for the given processor. The
initial process for the bootload processor (the initializer
himself) is created by threading in an apte specifying
init_processor as an initial procedure. It is placed in work
class zero. tcm is initialized to indicate only this one process
running. Various polling times are set for when polling becomes
enabled as we start multiprogramming. init_processor$init sets
up the rest of the state. We can now call start_cpu to start the
bootload cpu idle process.
SECTION 7
COLLECTION 3
The main task of collection three is to read itself into
the hierarchy. Collection three consists of those programs that
are necessary to reach ring one in the initializer's process and
to be able to perform a reload function (and other maintenance
functions). A few extraneous functions are also performed in
collection three.
ORDER OF EXECUTION
Collection three starts with its main function:
load_system is called to read the remaining mst entities into the
hierarchy. At this time, the mst reading function is shut down.
ioi_init is called to prepare for outer ring usage of
physical devices.
tc_init$start_other_cpus starts up the other processors.
We now consider collection three done and set
sys_info$initialization_state to 4.
real_initializer finally finishes, returning to
initializer. initializer can then delete init segs through
delete_segs$init, real_initializer being part of one.
Initialization then finishes by a call to init_proc, to call out
to ring one command level.
MODULE DESCRIPTIONS
init_proc.pl1
init_proc is the first program run in ring zero in a normal
process. It calls out to the initial procedure for a process in
the outer ring. For the Initializer, the initial_proc is made to
be system_startup_. The setting of the working dir is skipped,
since we can't be sure it's there yet. The ring one stack is
created explicitly, by makestack. system_startup_ is initiated.
call_outer_ring_ is called to "return" out to ring one (outward
calls are not allowed) to transfer to system_startup_.
ioi_init.pl1
ioi_init sets up the various ioi_ data bases. It walks the
config deck, allocating group table entries for each channel
group. Each device whose channel is accessed through a control-
ler has its group entry flagged as a psia. The device table
entries and channel table entries are allocated from information
on the prph card. Then, for each chnl card, the group table
entry corresponding is found and the channel table entries
allocated from the information on the chnl card. The base
logical channel for each group is found. The group entries are
then traversed to find storage system disk channels. All
non-storage system disk channels are assigned to ioi_ through
io_manager. As a final gesture, the ioi_ page tables are setup
(ioi_page_table$init).
ioi_page_table.pl1
The init entrypoint of ioi_page_table is called during
initialization to set up the io_page_tables segment. It starts
by abs wiring the segment as one page (initially) and zeroing it.
The header is initialized. Sixty-four word page tables are
allocated and initialized within this page, as many as will fit.
load_system.pl1
Collection three is loaded into the hierarchy by
load_system. It reads the mst source (disk_reader) looking for
segments. For each, init_branches$branch is called to create the
branch (init_branches is described under collection two). The
appropriate acl is set up, given the mst information. The
segment contents are copied into the created branch. If the
Initializer does not have write access to the final segment, the
acl is cleared of this acl entry.
tc_init.pl1
tc_init was described earlier. The entrypoint
start_other_cpus, starts cpus other than the bootload cpu at the
end of collection three (after their interference won't matter).
A prds for the various non-bootload processors is created and
entry-held. The pds and dseg for the other cpu's idle processes
was already created so we can now call start_cpu on this new cpu
as we would normally during reconfiguration.
SECTION 8
MECHANISMS
This chapter describes certain tricky and not so tricky
mechanisms used within initialization to get things done. Also
included is a look at the mechanism by which the various parts of
the supervisor come into operation.
HARDCORE SEGMENT CREATION
There are various ways that segments come into being within
the hardcore. These mechanisms are usually quite distinct from
the normal method of creating a segment within the hierarchy
(append$foo).
The first group of segments that are created are those
needed by collection zero. Collection zero itself is read in in
absolute mode; no segments exist other than those hardware
supplied. To save collection zero the problem of generating
segments for its use in absolute mode, its segments are generated
by macros within template_slt_.alm. These macros generate not
only the slt entries for collection zero segments (and various
segments at fixed absolute memory addresses); they also generate
the page tables and the segment descriptor words for the
segments. A much simpler program in absolute mode moves these
page tables and sdws (the dseg) to appropriate places and loads
the dbr (also generated by template_slt_). Thus, these early
segments come quickly and magically into being. All of the
segments described by the template_slt_ are data segments with no
initial content except for bound_bootload_0 itself, which was
loaded into the correct memory address by the bootload tape
label, and toehold, by virtue of being the first part of
bound_bootload_0.
The second group of segments to come into being are the
collection one segments loaded by collection zero. These seg-
ments are created through a mechanism imbeded in bootload_loader
and bootload_dseg. When the segment header (actually a slt
entry) is read from the MST, the need for a segment of a certain
size is called for. Values in the slt header keep track of the
extent of memory allocated. The type of segment (permanent
"unpaged" or not) determines from what end of memory the space
will be obtained. A page table of appropriate size is
constructed in the proper area (either the segment
unpaged_page_tables for permanent "unpaged" segments or
int_unpaged_page_tables for temporary or to be made paged seg-
ments). A new sdw pointing to this page table is tacked onto the
appropriate end of dseg (low segment numbers for permanent
segments, high for temporary or init segs). With write access
set on in this sdw, the segment contents can be loaded from tape
into the memory area. Proper access is then set in the sdw. The
segment is now existent.
Collection one creates certain data segments that are wired
and contiguous. The most obvious is the sst. These are created
by the routine get_main. get_main might be considered the
counterpart of the collection zero segment creation mechanism
when called in collection one. It also allocates memory space
from values in the slt header. A page table of appropriate
length in one of the two unpaged page table segments is
constructed and a sdw fabricated to this page table. The caller
of get_main forces this sdw into dseg and performs the appropri-
ate associative memory clearing function.
The other type of segment created by collection one is a
paged segment. There are two cases of this. The first is a
paged segment that is to be mapped against a previously defined
area of disk. This is done when we want to access a partition or
part thereof, as when we want to read the config deck from disk.
To do this, make_sdw is called, specifying that we want an sdw
for an abs-seg. make_sdw finds us an aste of appropriate size
and threads it into the hardcore lists, but senses the abs-seg
switch and does not allocate pages or whatever. The caller of
make_sdw builds its own page table within the aste obtained by
calling ptw_util_$make_disk to make each page table word point to
the correct disk record. The pvtx of the desired disk is
inserted into the aste. Thus, references to this segment (whose
sdw points to the page table in this aste) will wake up page
control who will page in the proper pages. This mechanism
appears in several places; the desired way of generating such a
segment is to call map_onto_disk.
The second type of paged segment created by collection one
(or two for that matter) is a segment paged off the hardcore
partition. In this case, allocation of pages is done by page
control. make_sdw is called as before, but, this time, it not
only creates an aste for the segment, but it finds space for it.
A disk with a hardcore partition with enough free space to hold
the segment is selected. This pvtx is put into the aste. As an
added bonus, since such segments will not have trailer entries,
the trailer pointer in the aste is set to the hardcore segment
number (for those programs that need to map the hardcore aste
list entries to slt entries). The page table words are set to a
nulled state. make_sdw then touches each page, causing page
control, when the page fault occurs, to withdraw a page from the
partition. (init_hc_part created a vol map and record stock that
page control can use which describes only the hardcore parti-
tion.) With the segment now in existence, the caller of make_sdw
can now load the segment. For collection one or two, this
involves either initializing the data segment or copying in the
segment contents read from the mst.
When collection two needs a wired contiguous data space, it
calls get_main also. In this case, though, get_main calls
make_sdw$unthreaded which will obtain an aste and sdw and page
space. pc_abs$wire_abs_contig is then called to wire this
segment into contiguous memory pages. A paged segment to be
mapped onto a particular area of disk is created as described for
collection one.
Hardcore segments that need to be placed into the hierarchy
(deciduous segments) are so placed as follows. append is called
to create a branch. This creates a vtoce for the segment and
makes active, creating if necessary, all parent directories.
Normally, segment control activities would then create an aste
for this being created segment which would be threaded as a son
of the parent directory's aste. In this initialization case,
though, the aste for the new segment already exists. We hand
thread this aste into the normal segment lists and thread it as a
son of the parent directory's aste. The directory entry for this
segment created by append gives the vtoc index of the vtoce for
it. By placing this vtocx into the old aste for the new segment,
vtoc_man can make the vtoce for this now deciduous segment
reflect the placement of this segment in the hardcore partition
(where it was allocated during hardcore initialization). The
segment is now properly active and accessible from the hierarchy.
PAGE CONTROL INITIALIZATION
Page control initialization consists of a variety of
activities run during collection one. init_sst build the sst and
core_map. The sst is needed since we need to have an aste for
page control so that it can find what disk needs i/o (from the
pvtx within the aste). The core_map is needed since it shows the
status of memory pages (initially free between the groups of
initialization segments, currently wired). Page control needs
this information so it can find a free memory frame into which it
can read a desired page. init_pvt performs the function of
creating the pvt. It is the index into the pvt for the device
from which a page (or other i/o) is desired that is needed by
disk_control (dctl). read_disk$init is needed to initialize page
reading/writing through rdisk_seg. This routine builds the paged
segment rdisk_seg, which can be mapped onto the desired page of
disk to read. The aste for rdisk_seg contains the pvtx of the
disk to read. The page table word for rdisk_seg provides the
disk address. At this point, we can actually read or write a
page by touching rdisk_seg within read_disk. read_disk sets up
the aste and page table word, as described. When the page is
touched, a page fault will wake up page control. It will find a
free memory frame, read the page in, and resolve the page fault.
read_disk_label uses read_disk, then, to read a disk label.
init_root_vols uses read_disk_label to read the label of hardcore
partition volumes. Given the label, it finds the partition map
and finds the hardcore partition. A small volmap is built that
describes this partition and is mapped onto the beginning of the
partition. A small record stock is built to describe the volmap.
Given this initial stock, attempts to create or free pages on a
disk (within the hardcore partition) can succeed. Now, we can
create hardcore segments by building null page tables and taking
page faults. Page control will find a free page from the volmap
for the partition (whose pvtx is in the aste) and resolve our
page fault. At this point, all of the services we need of page
control are available. For the ease of later activities who need
various partitions to map paged areas onto, init_partitions is
called to validate the part information. We now page happily.
Later, in collection two, the real volmaps and record
stocks are set up by accept_rpv. After this point, page control
will simply shift its page creation/freeing activity to that
described by the paging region. All hardcore segments had their
pages pre-withdrawn from the hardcore partition, so no possibili-
ty exists that we will accidentally put a paging region page into
a hardcore segment.
SEGMENT AND DIRECTORY CONTROL INITIALIZATION
Segment and directory control are initialized in stages
throughout collections one and two. It started in collection one
when the sst was built. It continues into collection two with
getuid$init. This allows us to generate unique ids for newly
created segments and directories. init_vtoc_man paves the way
for vtoc_man to perform i/o on vtoces. Segment control's trailer
segment is created by init_str_seg. accept_rpv sets up the real
vtoc maps and vtoc stocks. Now vtoc_man can really read and
write vtoces, as well as create and free them. Now, if we were
to try a normal activation of a segment, given its pvtx/vtocx, we
could find the segment and thread the segment into the right
astes and trailers. init_lvt builds an initial rlv (in the lvt)
out of the disks listed as having hardcore partitions. This
allows segment control's disk selection algorithm to be able to
find a disk to use when segments try to be created. We now have
enough mechanism in place to utilize most of the facilities of
segment control, but we cannot yet access and activate hierarchy
segments.
The initialization of directory control is imbedded within
the initialization of segment control. It started with
dir_lock_init providing us with an initially empty list of locked
directories. The real start up of directory control, though,
occurs in init_root_dir. This builds the kst (used at segment
fault time to resolve segment numbers into an understanding of
what needs activation) and creates (if need be) and activates and
initiates by hand the root directory. Directory control can now
reference hierarchy objects with segment control's help. Any
attempt to create a hierarchy segment (append) can succeed by
selecting a disk (lvt lookup), vtoce creation (vtoc_man using
vtoc stock, vtoc map and vtoc buffers) and aste creation (using
sst and the trailer seg). Also, deactivation is possible since
the trailer is built to describe what to setfault and the kst is
present to be able to re-activate. At this point, we are able to
handle segment faults, given the information in the kst and by
recursively traveling down the hierarchy by virtue of the fact
that the root is now and always active.
SEGMENT NUMBER ASSIGNMENT
There are basically three classes of segments as far as
segment number assignment is concerned. The first is segments
that will be a permanent part of the supervisor. These are
assigned consecutive segment numbers, starting at 0. dseg is
always 0, of course.
The second class is initialization and collection temporary
segments. These are assigned consecutive numbers starting at 400
octal. Although temporary segments are deleted at the end of
each collection, their numbers are not re-used. We continue to
assign the next non-used number to the next temporary or
initialization segment.
The order of assignment of these numbers is purely
according to the order that the segments are encountered. The
first few segments are assigned numbers by template_slt_; but,
again, this is in order of encounterance. The only requirements
are that dseg must be segment 0 and that the slt must be segment
7 (assumed by all dump analyzers).
Normal hierarchy segments fall into the third class of
segments, as far as segment number assignment is concerned. As
for these, the sequence is as follows. The next higher mod 8
segment number after the last permanent supervisor segment is
chosen as the stack base (ring zero stack number). The next
seven numbers are assigned to the outer ring stacks, in order.
Since the root is made active after this, and the root becomes
the first real hierarchy segment initiated, it gets the segment
number after stack_7. Other segments are assigned progressively
higher segment numbers according to segment control's normal
rules. We do not need to worry about running into segment number
400 octal since these segments will be deleted before we ever get
that far. Only permanent supervisor segments will show up in
one's dseg.
Some supervisor segments (deciduous segments) get initiated
into the normal user's address space. Regular stacks are
initiated by special handling (makestack called from the segfault
handler) and are directly referred to by the reserved stack
segment numbers. A normal segment like bound_library_1_ is
activated through normal segment control means. Thus, it will
appear in two places in the user's address space; one in the
supervisor segment number range (with ring brackets of 0, 0, 0,
by the way) and once in the user ring segment number range
(greater than the root's segment number) (with ring brackets of
0, n, n).
This is a problem for hardcore gates, though, relative to
their linkages. A user ring call to bound_library_1_ will cause
modules within it to find their linkage section from the lot
entry for this segment. Any module called from bound_library_1_
will also be in the user ring, so the user ring linkage section
for the segment number corresponding to the user ring version of
bound_library_1_ will find the called module. Hardcore gates,
however, don't call hierarchy entities but instead call entities
that can only be found through the linkage section generated via
pre-linking during initialization which resides in the ring zero
linkage section corresponding to the hardcore segment number. To
make it possible to find this easily, init_hardcore_gates stored
into the hardcore gate segdef .my_lp the pointer to this linkage
section. Thus, when called from the outer ring with the outer
ring segment number, hardcore gates will quickly switch over to
the hardcore linkage section and function properly.
TRAFFIC CONTROL INITIALIZATION
All three collections contribute efforts toward enabling
traffic control. Collection one starts by building the tc_data
segment in tc_init, full of empty aptes to describe processes.
At this time, though, a flag in tc_data indicates that
mult-programming is not active. Any call to traffic control to
pxss$wait will simply loop for notification (which will come from
a call to pxss$notify in some interrupt routine). No polling
routines are run at this time. Other initialization activities
proceed to build the supervisor address space.
Collection two starts up multi-programming. It does this
through tc_init$part_2. Multi-programming requires
multi-processes; initially this is the Initializer and an idle
process, but it soon encompasses answering service created
processes and hardcore processes (hprocs). Creating an idle
process requires creating a pds, stack_0 (prds) and dseg for it.
The dseg and pds are simply copies of those for the Initializer,
now that they are filled in. apte entries for the Initializer
and for idle are created. We can now consider multi-programming
to be on. start_cpu is called to start the processor. For the
bootload processor, this means calling init_processor in a
special case environment (non-absolute mode, if nothing else).
init_processor (the idle loop) marks itself as a running
processor, sends itself a connect, and unmasks the processor.
The connect will go to traffic control, who will pre-empt idle
and return control to Initializer.
In collection three, start_cpu is called (from
tc_init$start_other_cpus) in the same manner as would be done for
adding a cpu during reconfiguration. This is somewhat described
in the reconfiguration manual.
SECTION 9
SHUTDOWN AND EMERGENCY SHUTDOWN
The goal of shutdown, obviously enough, is to provide an
orderly cessation to service. A normal shutdown is one in which
the system shuts itself down, following the direction of the
operator's "shut" command. An emergency shutdown is that opera-
tion invoked by bce which forces Multics to run
emergency_shutdown, which performs the clean up operations below.
One could consider the system to be shutdown if one simply
forced a return to bce, but this is not enough. Proper shutdown
involves, at first, the answering service function of logging out
all users. The answering service then shuts itself down,
updating final accounting figures. Now with just the Initializer
running, the task of shutdown described here follows.
The major goal of shutdown and emergency_shutdown is to
maintain consistency of the storage system. It is necessary to
move all updated pages of segments to disk, to update all
directories in question with new status information, to update
vtoces of segments referenced, and to clear up any effects caused
by the creation of supervisor segments.
These functions must be performed in several stages. Also,
the ordering of operations is such as to minimize the degree of
inconsistency within the storage system that would occur if a
failure were to occur at any point.
Since these same functions are performed for an emergency
shutdown, the operations are performed so as to assume as little
as possible from the information in memory.
ORDER OF EXECUTION OF SHUTDOWN
The module shutdown is called via hphcs_$shutdown. It
starts by removing the fact that we were called from an outer
ring, so we won't accidentally return. An any_other handler is
set up to flag any possible error, later. The first action of
shutdown is to force itself to run on the bootload cpu and to
stop the others (stop_cpu).
disk_emergency$test_all_drives checks out all of the stor-
age system drives at once to avoid errors later.
tc_shutdown destroys the remnants of any processes and
turns off multi-processing.
scavenger$shutdown cleans up any scavenges that were in
progress.
We then switch over to the stack inzr_stk0 for the rest of
shutdown. This is performed through the alm routine,
switch_shutdown_file_system, which starts the file system shut
down.
shutdown_file_system is the first program called on
inzr_stk0. It is a driver for the shutdown of the file system.
It starts by updating the rpv volmap, vtoc header (and vtoc map)
and label of the rpv to show the current state (in case problems
occur later).
The most important step, from the user's point of view, is
to flush all pages in memory (considered to be part one of
shutdown) with pc$flush. This is relatively easy and safe to
perform since it only requires walking down core map entries; sst
threads, etc. do not have to be trusted. This marks the
completion of (emergency) shutdown, part 1.
The stack zero segments are released so that demount_pv can
deactivate them.
deactivate_for_demount$shutdown deactivates all
non-hardcore segments and reverts deciduous segments (removes
from the hierarchy those supervisor segments put into the
hierarchy during initialization). This updates the directories
containing those segments that were active at shutdown time (and
their vtoces).
Our next task is to remove the pages of these updated
directories from memory. We start by demounting all operative
disks (other than the rpv) with demount_pv. After this, if any
locks remain set, we set the shutdown state to three; it is
normally four.
If any disks are inoperative, we just perform another
memory flush (to remove rpv directory pages), wait for console
i/o to finish (ocdcm_$drain_io) and return to bce.
If all was okay, we demount the rpv with demount_pv. The
storage system is now considered to be shut down. The ssenb flag
in the flagbox is reset to show this. We flush memory once more,
to get the last log messages out. The message "shutdown
complete" is printed; we wait for console completion. Shutdown
can now return to bce.
ORDER OF EXECUTION OF EMERGENCY SHUTDOWN
emergency_shutdown is called from bce. bce modified the
machine conditions of the time of return to bce to cause a return
to emergency_shutdown|0. This module initializes itself through
text imbeded pointers to its linkage section, etc. and enters
appending mode.
Multi-programming is forced off (tc_data$wait_enable).
The apt, metering and various apte locks are forced
unlocked.
The return to bce earlier stopped all of the other cpus.
scs$processor is set to show this fact.
The connect lock is forced unlocked.
Various trouble pending, etc. flags are reset in case of
another failure.
scs masks, etc. are set up for single (bootload) cpu
operation. We mask down to sys_level.
A switch is made to the idle process. This is done by
using scs$idle_aptep to find the idle's apte. Its dbr is loaded.
All other cpus are set to delete themselves, in case they
try to start.
The idle process has prds as its stack. A stack frame is
pushed onto this stack by hand.
The ast and reconfiguration locks are forcibly unlocked.
The first external module is called. ocdcm_$esd_reset
resets oc_data, and the console software.
syserr_real$syserr_reset resets the syserr logger and the
syserr_data segment and flags.
io_manager$reset resets iom_data status.
page$esd_reset resets its view of the disk dim.
pc_recover_sst recomputes the page control state.
page$time_out is called.
disk_emergency$test_all_drives_masked runs as for normal
shutdown, but in a masked state.
The prds is abandoned as a stack (it is reset) and the
stack pointer set to null (idle process). The first page of
template_pds is wired and the sdw for pds set to point to
template_pds (hopefully a good pds). The first page is touched,
hopefully successfully paging in the page. The stack pointers
are then set to inzr_stk0. We then call
wired_shutdown$wired_emergency.
wired_shutdown sets an any_other handler and unmasks the
processor. It makes a few checks to see if the storage system
was enabled. If a vtoc_buffer is in the unsafe state, its
physical volume has its trouble count incremented.
For each pvte, the scavenger data is reset as in a normal
shutdown. page$reset_pvte is called. Emergency shutdown part 1
is started.
fsout_vol updates the rpv information on disk as for
shutdown.
Pages of segments are flushed from information in the core
map entries (pc$flush). The rpv information is again written.
This ends part one of emergency shutdown.
vtoc_man$stablilize gets vtoc buffers into shape.
We can now call shutdown_file_system and let normal opera-
tions carefully try to update directories and vtoces, as for a
normal shutdown.
MODULE DESCRIPTIONS
deactivate_for_demount.pl1
Other than the flushing of pages themselves, the
deactivation of segments (updating their directory entries and
vtoces) performed by deactivate_for_demount is one of the most
important functions of shutdown. The deactivations are performed
by hand so as not to disturb aste threads. The operation
consists of walking down the ast hierarchy (tree)-wise,
recognizing that each active segment has all of its parent
directories also active. We start at the root. For each segment
to consider, we look down its inferior list. Each look at an
aste and an inferior element is performed with a variety of
validity checks on the aste (within pool boundaries, parent/son
pointers correct, etc). If inferiors exists, they are pushed
onto a stack (max hierarchy depth deep) of astes to consider.
When we push an aste with no inferiors, we consider it directly.
If it was a hardcore segment (deciduous), it is removed from the
aste list it is in and its vtoce freed. Non-hardcore segments
have their pages flushed (pc$cleanup) if they are not entry-held
(entry-held segments, such as pdses had their pages flushed
earlier and will be caught in the final flush) and their vtoces
updated (update_vtoce$deact). After a segment is considered, its
brothers are considered. When they are done, we return back to
their parent for consideration. We proceed in this manner until
we consider and pop the root aste off the stack. Segment control
is now no longer active.
demount_pv.pl1
demount_pv demounts a physical volume. It starts by
waiting for everyone to relinquish the drive; that is, no one can
be in the middle of a physical volume operation. All segments on
the volume are deactivated. For the shutdown case described
here, a special deactivation is performed to avoid possible
problems in the case of emergency shutdown. Each aste pool is
traversed (by numerical order, not link order because of possible
mis-linkings). All non-hardcore segments (except the root) are
deactivated in-line by calling pc$cleanup and update_vtoce$deact
on the segment. We then wait for all vtoc i/o to complete to the
disk. fsout_vol is called to update the volmap, vtoc header and
map and the label. Finishing, we clean up the pvt entry.
disk_emergency.pl1
To ease the burden on shutdown of drives being inoperative,
disk_emergency$test_all_drives is called. It tests all storage
system drives by first assuming that each one is good, then
running disk_control$test_drive. If the drive is declared inop-
erative this time, it is marked as such with an error report
printed. Shutdown of objects on this drive will be suspended.
emergency_shutdown.alm
bce, when crashed to, received the machine conditions at
the time of the call to bce. For an emergency shutdown (esd),
bce patches these to force a transfer to emergency_shutdown|0.
Multi-programming is forced off (tc_data$wait_enable). The apt,
metering and various apte locks are forced unlocked. The return
to bce earlier stopped all of the other cpus. scs$processor is
set to show this fact. The connect lock is forced unlocked.
Various trouble pending, etc. flags are reset in case of another
failure. scs masks, etc. are set up for single (bootload) cpu
operation. We mask down to sys_level. A switch is made to the
idle process. All other cpus are set to delete themselves, in
case they try to start. The idle process has prds as its stack.
A stack frame is pushed onto this stack. The ast and
reconfiguration locks are forcibly unlocked. ocdcm_$esd_reset
resets oc_data, and the console software.
syserr_real$syserr_reset resets the syserr logger and the
syserr_data segment and flags. io_manager$reset resets iom_data
status. page$esd_reset resets its view of the disk dim.
pc_recover_sst recomputes the page control state. page$time_out
is called. disk_emergency$test_all_drives_masked runs as for
normal shutdown, but in a masked state. The prds is abandoned as
a stack (it is reset) and the stack pointer set to null (idle
process). The first page of template_pds is wired and the sdw
for pds set to point to template_pds (hopefully a good pds). The
first page is touched, hopefully successfully paging in the page.
The stack pointers are then set to inzr_stk0. We then call
wired_shutdown$wired_emergency.
fsout_vol.pl1
fsout_vol is called whenever a volume is demounted. This
includes the shutdown equivalent function. It endeavors to
update the volume map, vtoc header and map and label for a
physical volume. It drains the vtoce stock for the disk
(vtoc_stock_man$drain_stock) to return those vtoces withdrawn
previously. The vtoc map is then forced out to disk. We can
then free the vtoc stock. We similarly drain, write out and free
the record stock/map. The dumper bit map is freed and updated to
disk. The time map updated and mounted is updated in the label.
If this is the root, this is the program that records in the
label such useful information as the disk_table_vtocx and uid and
the shutdown and esd state.
scavenger.pl1
The shutdown entrypoint to scavenger is called during
shutdown to clean up any scavenge operations in progress. It
walks down scavenger_data looking for live entries. For each, it
clears the corresponding pvte fields deposit_to_volmap,
scav_check_address and scavenger_block_rel which affects the
operation of page control.
shutdown.pl1
This is the starting driver for shutdown operations. It is
called from hphcs_$shutdown from the Initializer command
shutdown. It forces itself to run on the bootload cpu and it
stops the others. disk_emergency$test_all_drives test the drives
before use. tc_shutdown stops and destroys the other processes.
scavenges are stopped (scavenger$shutdown). We then switch
stacks back to inzr_stk0 and proceed through shutdown within
switch_shutdown_file_system.
shutdown_file_system.pl1
shutdown_file_system is the driver for the shutdown of the
file system. It runs on inzr_stk0. Its operations include:
fsout_vol updating of the rpv, flushing pages of segments,
releasing stack_0 segments for deactivation purposes, running
deactivate_for_demount$shutdown to deactivate non-hardcore seg-
ments and revert supervisor segments threaded into the hierarchy
at initialization (updating directories as a result) and then
flushing memory again (by calls to demount_pv for the various
disks). This module keeps track of the state of operativeness of
drives; if any are inoperative, we just perform a final flush and
quit; otherwise we can demount the rpv also. A final flush is
performed to get syserr log pages out. After console i/o has
drained, we can return to bce.
switch_shutdown_file_system.alm
switch_shutdown_file_system is the first program in a set
to shut down the file system. It moves us back to inzr_stk0, the
initialization stack for our processing. While it is fiddling
with stack pointers, it also sets pds$stack_0_ptr and
pds$stack_0_sdwp. On this new stack, it calls
shutdown_file_system.
tc_shutdown.pl1
Traffic control is shutdown by tc_shutdown. It flags the
system as being in a shutting down state
(tc_data$system_shutdown). It also sets wait_enable to 0,
disabling multi-programming. For each process in the apt,
deactivate_segs is called, destroying the process and finishing
our task.
wired_shutdown.pl1
The module wired_shutdown is the counterpart to shutdown in
the esd case. It starts by setting an any_other handler and
unmasking the processor. It makes a few checks to see if the
storage system was enabled. If a vtoc_buffer is in the unsafe
state, its physical volume has its trouble count incremented.
For each pvte, the scavenger data is reset as in a normal
shutdown. page$reset_pvte is called. Emergency shutdown part 1
is started. fsout_vol updates the rpv information on disk as for
shutdown. Pages of segments are flushed from information in the
core map entries (pc$flush). The rpv information is again
written. This ends part one of emergency shutdown.
vtoc_man$stablilize gets vtoc buffers into shape. We can now
call shutdown_file_system and let normal operations carefully try
to update directories and vtoces, as for a normal shutdown.
APPENDIX A
GLOSSARY
abs-seg
An abs-seg is a reserved segment number in the hardcore
address space used to access disk or memory outside of the
normal mechanisms. That is, they are not built by the
normal functions that append to the storage system nor are
they built by the functions that create segments out of the
hardcore partition or initialization memory. Examples of
abs-segs are segments mapped onto an area of disk to allow
paging to be used to read/write them (such a mechanism is
used to read the config deck from disk) or segments mapped
onto an area of memory for examination (page control does
this to examine pages being evicted). abs-segs are managed
(i.e., created and deleted), each in its own way, by a set
of software created for the purpose; One may not use the
standard system functions to operate upon them (such as
segment deletion). However, the contents of the segments
are addressed through normal mechanisms; that is, memory
mapped abs-segs are referencable via the hardware and
abs-segs built with an aste/page table pair in the sst are
allowed to have page faults taken against them.
bce
The Bootload Command Environment within bootload Multics,
that is, the collection of programs and facilities that make
up a command level that allows certain critical functions to
be performed before storage system activation occurs during
system initialization.
bootload Multics
Those early parts of initialization that are capable of
booting bce from a cold, bare machine, including bce itself.
cold boot
A bootload in which the state of all hardware and peripher-
als is unknown. In particular, the Multics file system is
either non-existant or has been destroyed. This is also
known as an initial boot.
collection
A "collection" is a set of programs read in as a unit that
together perform a function during initialization. Collec-
tions are referred to by number, starting with zero. Each
collection depends on the mechanisms initialized by the
collections that preceded it. As each collection finishes
its task, some of that collection is deleted and some is
kept, depending on the requirements of future collections.
There are also fractionally numbered collections, which
consist of support entities for the preceding collection.
The division of initialization into collections is done
based upon various restrictions imposed by the course of
initialization. For example, since the first few collec-
tions must run entirely within memory, restrictions on
available memory (and the amount that can be required of a
system) force unessential programs into later collections.
contiguous
A contiguous segment is one whose memory locations describe
contiguous absolute memory locations. Most segments do not
have this requirement; their pages may appear arbitrarily in
memory. Certain segments, though, such as the sst_seg must
have their locations in order, due to hardware requirements
for placement of their contents.
cool boot
A bootload in which the Multics file system is on disk and
believed to be good but in which the state of memory and
other peripherals is unknown. In particular, bootload
Multics is not running. The mpc's may or may not have
firmware running in them. The system is loaded from the MST
(tape) and initiated via iom switches.
crash
A failure of Multics. This may be the result of a hardware
or software failure that causes Multics to abort itself or
the result of an operator aborting it. A crash of Multics
during early initialization can produce a tape dump of
memory. Crashes after this time can be examined with bce
utilities or saved to disk by bce and analyzed later.
deciduous segments
These are segments generated or read in as part of
initialization which are given branches in the hierarchy (by
init_branches). Although they become part of the hierarchy,
their pages remain in the hardcore partition and are
therefore destroyed between bootloads. Examples are the
segments in >sl1 and the Initializer's pds. (The name
suggests the leaves of trees.)
deposit
A page control concept. It means to add an object to a list
of free objects.
dseg
descriptor segment (see data bases)
dump
A subset of Multics segments saved after a crash that can be
examined through various dump analysis tools to determine
the cause of the preceding crash. A dump is either a disk
dump, a dump performed to the dump partition of disk by the
dump facility of bce, or an "early dump", one performed to
tape during early initialization.
early initialization
Those parts of initialization needed to reach bootload
Multics command level. All activities after leaving
bootload Multics command level are referred to as service
initialization.
emergency shutdown
A Multics operation, invoked by bce, that runs a subset of
the hardcore facilities to shut down the file system (put
the storage system into a consistent state) after a crash.
esd
emergency shutdown
hardcore
The supervisor of Multics, loosely defined. This is a
collection of programs and segments generated or read in
during initialization.
hproc
A hardcore process. Such a process is created by a call to
create_hproc, as opposed to being created through the
answering service. Such hprocs (currently
SyserrLogger.Daemon and MCS_Timer_Daemon.SysDaemon) perform
activities integral to the system operation and must be
created prior to, and independent of, the answering service.
init segments
Segments needed only during the course of initialization.
These are deleted after the end of the last hardcore
collection.
initialization
The action of starting Multics. This consists of placing
the appropriate software modules in the appropriate places
and constructing the appropriate software tables such that
an event, such as someone trying to dial a login line, or a
page fault occuring, etc. will invoke the proper software
which will be in a position to perform the necessary
operation.
kst
known segment table (see data bases)
lvt
logical volume table (see data bases)
MST
Multics system tape
Multics system tape
The "tape" is the set of Multics programs that will make up
the supervisor in un-pre-linked form. This set of programs
originates on a tape; some of them spend part of their lives
in a disk partition.
nondeciduous
A hardcore segment not mapped into the hierarchy. These
segments live in the hardcore partition and are known only
by having sdw's in the hardcore address space.
partition
An area of a storage system disk, other than the label,
vtoc, volume map and paging area. These areas can be
accessed by paging mechanisms but are not used to hold pages
of storage system segments. Hardcore segments are mapped
onto the hardcore partition so that they may be used, and
early initialization can run, without touching the file
system proper.
pre-linking
As the Multics supervisor is read from the MST, the various
modules are linked together. This operation, called
pre-linking, is similar to linking (binding) that occurs
during normal service operation for user programs, except
that it consists of running through all segments and finding
all external references and resolving them. This is done
during initialization for efficiency, as well as for the
fact that the dynamic linker cannot be used to link itself.
ptw
page table word
ptwam
page table word associative memory
pvt
physical volume table (see data bases)
root physical volume
The main disk drive. It can never be deleted. This drive
is used to hold the original hardcore partition as well as
the partitions required by bce and is therefore required at
an early point in Multics initialization.
rpv
root physical volume
scas
system controller addressing segment (see data bases)
scs
system communications segment (see data bases)
sdw
segment descriptor word
sdwam
segment descriptor word associative memory
shutdown
The orderly cessation of Multics service, performed such as
to maintain consistency of the storage system.
slt
segment loading table (see data bases)
supervisor
A collection of software needed for operation of user's
software and support software provided for the user. This
would include software to make disk accessing possible, to
provide scheduling activity, etc. The supervisor in Multics
is referred to as "hardcore".
temp segments
Segments needed only during one collection. They are
deleted at the end of the major collection, before loading
the next collection.
uid
unique identifier (of a segment)
unpaged
A segment that is not paged under the auspices of page
control. Such a segment has its page table either in
unpaged_page_tables or int_unpaged_page_tables. Except for
the possible presence of the breakpoint_page, these segments
are contiguous. During early initialization, all segments
are generated to be of this type. The program
make_segs_paged forms paged segments that are copies of the
pagable initialization segments. Certain wired segments,
though, are left unpaged.
In previous releases, unpaged segments were literally
unpaged, that is, they had no page table and had the unpaged
flag set in their sdw. Currently only fault_vector,
iom_mailbox, dn355_mailbox, isolts_abs_seg, abs_seg and
abs_seg1 are of this type but will receive page tables in a
future release.
vtoc
The volume table of contents of a storage system volume.
The vtoc is divided into entries (vtoce), each of which
describes a hierarchy segment contained on that volume.
warm boot
A bootload in which the Multics file system is present on
disk and believed good, and in which bootload Multics is
running on the processor. This type of bootload of Multics
is performed from disk.
wired
A page, or set of pages, is wired if it cannot be moved from
memory by page control.
withdraw
A page control concept, said of records and vtoces. It
means to remove an object from a list of free objects.
APPENDIX B
INITIALIZATION AND INITIALIZED DATA BASES
This appendix describes various data bases kept by
initialization or that are generated by initialization. As such,
this list incorporates the most significant data bases within the
system.
AI_LINKAGE (ACTIVE INIT LINKAGE)
This initialization segment corresponds to area.linker for
initialization programs that will be paged. This area is built
by bootload_loader and segment_loader from linkage sections found
on the MST.
AS_LINKAGE (ACTIVE SUPERVISOR LINKAGE)
This hardcore segment corresponds to area.linker for paged
supervisor programs. It is shared across processes, and can
therefore contain only per-system static such as initialization
static variables (when only one process is running) or system
wide counters, etc. The linkage areas are formed in here by the
various MST loading programs.
BCE_DATA (BOOTLOAD COMMAND ENVIRONMENT DATA)
bce_data keeps information that pertains to the command
environment features of bootload Multics. It contains entries
that describe the main pseudo i/o switches (input, output and
error) as well as the state of exec_com and subsystem execution.
BOOTLOAD_INFO
bootload_info, generated initially from bootload_info.cds,
contains various information about the state and configuration of
early initialization. It contains: the location of the bootload
tape (iom, controller channel, drive number and drive and
controller type provided by the IOM boot function), status about
firmware loading into the bootload controller, the location of
the rpv (iom, controller, drive number and drive and controller
type provided in the find_rpv_subsystem dialog), the location of
the bootload console (and type), a variety of pointers to other
data bases, as well as the master flags indicating the presence
of BOS and the need for a cold boot. All of this data is copied
into sys_boot_info during generation and during system
initialization. Most references to this data are therefore to
sys_boot_info.
bootload_info.cds has provisions to contain site-supplied
configuration information. If these values are provided, no
operator queries will be needed to bring the system up. Only
cold site boots or disk problems would require operator interven-
tion during boot. It is intended that an interface will be
provided to fill in these values, such that generate_mst could
set the values into the segment and the checker could report
their settings in the checker listing.
CONFIG_DECK
Historically named, the config_deck contains the descrip-
tion of the configuration. It contains one entry (card) for each
iom, cpu, memory, peripheral subsystem, etc. in the configura-
tion. It also describes various software parameters. These
entries are referenced by programs too numerous to count. It is
built initially by init_early_config to describe enough of the
system to find the rpv and read in the real config_deck saved in
a partition thereon. (If this is a cold boot, in which there
would be no config_deck, the config_deck is entered manually or
from the MST through the config deck editor.) After this time,
it becomes an abs-seg on the "conf" partition. Various
reconfiguration programs modify the entries.
CORE_MAP
One of the page control data bases, the core_map describes
frames of memory available for paging. Each entry describes a
page frame. When a frame is used (it has a ptw describing it),
the disk address of the page occupying the frame is kept in the
core_map entry. init_sst initially builds the core_map. It is
updated to accurately describe the state of pagable memory by
make_segs_paged, which frees certain unpaged segments and
collect_free_core which works to find various holes between
segments. Page control maintains these entries.
DBM_SEG (DUMPER BIT MAP SEG)
dbm_seg holds the dumper bit maps used by the volume
dumper. It is paged off the hardcore partition. Its
initialization as an area was performed by dbm_man$init. Each
configured disk drive has two maps here, one for the incremental
dumper and one for the consolidated dumper. The segment starts
with the usual lock, control information, and meters. After this
comes an area in which the bit maps are allocated. Each bit map
consists of a bit corresponding to each vtoce on the volume in
question. The bits indicate the need to dump the various
segments.
DIR_LOCK_SEG
dir_lock_seg keeps track of lockings of directories and on
processes waiting thereupon. It has a header with a lock and
various status. Each dir_lock entry contains the uid of that
which is locked, various flags, threads to a more recently locked
entry, and the array of process ids for the various lockers (more
than one only for all readers).
DISK_POST_QUEUE_SEG
A part of page_control, disk_post_queue_seg is an obscure
data base used to keep track of disk i/o postings that could not
be made because the page table was locked at the time of i/o
completion.
DISK_SEG
The disk seg contains the various tables (except the pvt)
used by disk_control and dctl to perform i/o to disks. It is
split into the tables disk_data, disktab, chantab, devtab as well
as the queue of disk i/o requests. disk_data contains entries
giving the names and locations within disk_seg of the disktab
entry for each configured disk subsystem. The disktab entry
contains various subsystem meters, as well as holding the queue
entries for the subsystem. Also contained herein are the chantab
and devtab entries for the subsystem. Each chantab entry lists a
i/o channel to use to perform i/o to the subsystem, given as an
io_manager index. It also holds various per channel meters, and,
most importantly, the dcw list that performs i/o on the channel.
The devtab entries, one per subsystem drive, describe the drives.
This consists of status information (inoperative, etc.) as well
as per drive statistics.
DM_JOURNAL_SEG_
A page control data base, dm_journal_seg_ is used to keep
track of page synchronization operations for data management. It
is allocated and initialized by init_dm_journal_seg. It starts
with a lock for manipulating the journal entries as well as the
usual wait event information. Also present are information about
the number of pages held in memory, the maximum pages held, the
number of journals, etc. Corresponding to each aste pool is a
structure containing a threshold and number of active,
synchronized segments. Following this are various meters. Then
comes the journal entries and then the page entries. Each
journal entry contains the time stamp that determines when pages
of the segment being held can be written (when the journal was
written), the number of pages held, and a relative thread to the
list of page entries for the pages being held. A page entry
contains the threads that make up this list, a relative pointer
to the core map entry for the page, and a relative pointer to the
journal entry for the page.
DN355_DATA
This data seg, initialized by fnp_init, contains global
information on each configured fnp. Data for each fnp includes:
a pointer to the hardware mailbox, pointers to the dcw lists and
the physical channel blocks (pcb), the number of subchannels, the
iom/channel info, indexes into the pcb for lslas and hslas
(hmlcs), status of the delay queues, various flags about the
state of fnp operations, the lct (logical channel table) entry
pointer, status of bootloading, and various counts of free
blocks, input and output data and control transaction counts,
etc.
DN355_MAILBOX
The dn355_mailbox is a set of mailboxes at fixed hardware
addresses. They start with the fnp pcw. Also present are
various counts of requests and the fnp crash data. Following
this are 8 Multics initiated sub-mailboxes and 4 fnp initiated
sub-mailboxes. The sub-mailboxes describe the line for which the
operation is being performed along with the data for that
operation.
DSEG (DESCRIPTOR SEGMENT)
The descriptor segment is a hardware known data base. It
contains a sdw (segment descriptor word) for each segment within
a process' address space. The ultra important processor register
dsbr (descriptor segment base register), also called the dbr,
indicates the absolute address of the page table describing it.
The sdw of a segment indicates the address of the page table of
the segment (which contain the locations of the pages of the
segment) and other information, such as the length of the
segment, accesses allowed, etc. dseg must be segment 0. The
initial dseg is generated by template_slt_ and copied into dseg
by bootload_abs_mode. Entries are added by bootload_dseg,
get_main and make_sdw as segments are loaded from the MST. The
generation of sdws is integrated with the creation of slt
entries, and the allocation of memory/disk that the sdw/page
tables effectively describe.
FAULT_VECTOR (FAULT AND INTERRUPT VECTORS)
This is another hardware known data base, at a fixed
absolute memory address (0). It contains two words for each
possible fault and interrupt. Normally, each entry contains a
scu instruction, to store all machine conditions, and a tra
instruction, to transfer to the code that handles the
fault/interrupt. These two instructions are force executed in
absolute mode on the processor. The entries are filled in by
bootload_faults and initialize_faults. During some phases of
initialization, when a particular fault/interrupt is to be
ignored (such as a timer running out), the fault vector entry is
set to a scu/rcu pair, which stores machine conditions and then
reloads them, returning to the point of interruption. The scu
and tra instructions actually perform indirect references through
"its" pointers that are present following the interrupt vectors
within this segment. During normal operations, only these
pointers are changed.
FLAGBOX
The flagbox is an area of memory, at a known address, that
allows communication between Multics operation and bootload
Multics. This area contains information from Multics to bootload
Multics such as the fact that we are crashing, and here's what
exec_com to run. Bootload Multics can pass information up when
booting, such as being in unattended mode so that Multics will
know how to boot. The area is examined by various programs and
set through commands/active functions in both Multics and
bootload Multics operation. This area is within the bce toehold.
INZR_STK0 (INITIALIZER STACK)
This is the stack used by initialization and shutdown. The
name stands for initializer stack. Originally wired, it becomes
paged during initialization. Once the actual ring 0 stacks are
created and after collection 3, initialization will leave this
stack (in init_proc). Shutdown will return to this stack for
protection as the stack_0's are deleted.
INT_UNPAGED_PAGE_TABLES
The page tables for init and temp segments are kept here.
It gets an initial value through template_slt_ and is managed by
the various segment creation routines. Once make_segs_paged is
run, no unpaged segments exists whose page tables are here. So,
we delete this segment. The page table for this segment is
contained within it.
IO_PAGE_TABLES
The page tables referenced by a paged mode iom for ioi_
operations are found in io_page_tables. It is a abs-wired
segment, maintained by ioi_page_table. It starts with a lock and
indexes of the start of free page table lists. The header ends
with the size and in_use flags for each page table. The page
tables themselves are either 64 or 256 words long; each page
table of length N starts at a 0 mod N boundary and does not cross
a page boundary within the segment.
IOI_DATA
ioi_data contains information pertinent to ioi_ (the i/o
interfacer). It holds ioi's data itself (ioi_data), as well as
group channel and device entries for ioi handled devices.
ioi_data contains counts of groups, channels and devices,
reconfiguration lock, some flags, and then the channel, group and
device entries. A channel/device group entry describes a group
of devices available through a channel. It contains a lock,
subsystem identifier, various flags describing the device group,
the number of devices and some counters. A channel table entry
describes the state of a channel. It holds status flags, the
io_manager index for the channel, and a place for detailed
status. A device table entry holds the wired information for an
ioi device. Besides pointers linking it to the group and channel
entries, it contains various status bits, workspace pointer,
ring, process_id and event channels for communication with the
outer ring caller, timeout and other time limits, offsets into
the user's workspace for status storage, and the idcw, pcw, tdcw
and status areas.
IOM_DATA
iom_data describes data in use by io_manager. It starts
with lpw, dcw, scw and status area for stopping arbitrary
channels. This is followed by various meters, such as
invalid_interrupts. Following this, for each iom are various
pieces of state information, on-line, paged mode, etc. It
concludes with more meters and ending with devtab entry indices.
For each device, a status are is followed by various flags
(in_use), channel identification, pcw, lpw and scw, status queue
ptr, and various times and meters.
IOM_MAILBOX
This segment is another hardware known and fixed segment.
It is used for communication with the various ioms. The segment
is split into the imw area, which contains a bit per channel per
iom per interrupt level indicating the presence of an interrupt,
followed by the mailboxes for sending information to the ioms and
receiving status back.
KST (KNOWN SEGMENT TABLE)
The known segment table is a per-process segment that keeps
track of hierarchy segments known in a process. Hardcore
segments do not appear in the kst. The kst effectively provides
the mapping of segment number to pathname for a process. It is
the keeper of the description of segments that are initiated but
not active within a process (as well as those that are active).
The Initializer's kst is initialized by init_root_dir. It starts
with a header providing the limits of the kst, as well as
information such as the number of garbage collections, pointers
to the free list, what rings are pre-linked, the 256k segment
enable flag, a uid hash table, the kst entries and finally a
table of private logical volumes connected to this process. Each
kst entry contains a used list thread, the segment number of the
segment, usage count per ring, uid, access information, various
flags (directory, transparent usage, etc), an inferior count for
directories or the lv index for segments and the pointer to the
containing directory entry. It is this pointer that allows the
name of the segment to be found. Also, the segment number of the
directory entry pointer allows us to find the kst entry for the
containing directory, etc., allowing us to walk up the hierarchy
to find the pathname of a segment.
LVT (LOGICAL VOLUME TABLE)
The logical volume table consists of an array of entries
that describe the various logical volumes. It starts with a
count of entries as well as a maximum count limit. Following
this is a relative pointer to the first entry and a hash table
for hashing lvid (logical volume ids) into lvt entries. The
entries that follow, one per logical volume, contain a relative
pointer to the threaded list of pvt entries for the logical
volume, the lvid, access class info for the volumes and then
various flags like public and read_only. It is initialized by
init_lvt to describe the rlv and maintained by
logical_volume_manager.
NAME_TABLE
The name_table contains a list of all of the various names
by which the segments in the slt (see below) are known. This
table is used by the slt management routines but especially by
the various pre-linkers, who use it to resolve references to
initialization modules. It is generated from template_slt_ and
by the slt management routines, who read in the names from
entries on the system tape.
OC_DATA
oc_data describes data used by ocdcm_ to handle consoles.
It starts with the required lock, version, device counts, etc.
Various flags are kept, such as crash on recovery failure. The
prompt, discard notice are kept here. Status pointers, times,
etc. are followed by information on the process handling message
re-routing. Following this are indices into queues of entries
followed by the queues. An entry exists for priority i/o (syserr
output, which always forces a wait until complete), one for a
pending read, and 8 for queued writes. After this are meters of
obscure use. The segment ends with an entry for each configured
console followed by an entry for each element of a event tracing
queue. Each console entry provides its name, state, type,
channel, status, etc. Each i/o queue entry provides room for the
input or output text, time queued, flags (alert, input/output,
etc), and status.
PHYSICAL_RECORD_BUFFER
The physical_record_buffer is a wired area of memory used
by collection 0's and collection 1's MST tape reading routine for
i/o buffers.
PVT (PHYSICAL VOLUME TABLE)
One of the disk describing tables, the physical volume
table contains an entry for each configured disk drive. It can
in some ways be considered the master disk describing table in as
much as performing i/o to a disk drive requires the pvtx (pvt
index) of the drive (the index number of the entry in the pvt for
that drive). The pvt entry contains the physical and logical
volume id for the drive, various comparatively static flags about
the drive (such as storage_system, being_demounted,
device_inoperative, etc.), information for the volume dumper and
information about the size, fullness, volmaps and stocks (both
record and vtoc) of the drive. This table is allocated by
get_io_segs, and built by init_pvt. The various brothers in a
logical volume are chained together in a list by the
logical_volume_manager so that the vtoc_man can have a set of
disks from which to select a target for a new segment. During
initialization, make_sdw$thread_hcp (for init_root_vols) uses
these threads (before the disk_table is accessed) to form the
list of drives which contain hardcore partitions (those eligible
to contain hardcore segments).
SCAS (SYSTEM CONTROLLER ADDRESSING SEGMENT)
This is a very curious pseudo-segment, built by scas_init
out of page table words generated into scs. It contains one
pseudo-page for each memory controller (and another page for each
individual store other than the lowest). The address of the page
is the base address of the store/controller. This segment makes
references to it of the form n*1024 to form an absolute address
to controller n. Thus, instructions like rscr (read system
controller register) can use this segment (as indeed they do
inside privileged_mode_ut) to reference the desired system con-
troller registers.
SCAVENGER_DATA
scavenger_data contains information of interest to the
volume scavenger. Its header is initialized by
init_scavenger_data. The segment starts with the usual lock and
wait event. Following this is the pointer to the scavenger
process table. Then come the meters. The scavenger process
table, which follows, describes the processes performing
scavenging operations. Each entry contains a process id of a
scavenging process, the pvtx of the drive being scavenged, and
indices of scavenger blocks in use. Scavenger blocks contain
record and overflow blocks used to keep track of pages of a disk
(its claiming vtoce and its state).
SCS (SYSTEM COMMUNICATIONS SEGMENT)
The scs is a hodge-podge of information about configuration
and communication between active elements. It contains informa-
tion about the scus and the cpus. It contains the cow's (connect
operand words) needed to connect to any given cpu/iom, the
interrupt masks used to mask/unmask the system, the various smic
patterns (set memory interrupt cells), instructions to clear
associative memories and the cache, connect and reconfiguration
locks, various trouble flags/messages used for keeping track of
pending communication of faults to bce, cyclic priority switch
settings, port numbers for controllers, configuration data from
the controllers, processor data switch values/masks, controller
sizes, and the scas page table (see scas).
SLT (SEGMENT LOADING TABLE)
One of the most significant initialization data bases, the
slt describes each initialization segment. It is built initially
from template_slt_, an alm program that not only builds the
appropriate slt entries for collection 0 segments, but also
generates the dseg for collection 0. Each entry in the slt
contains: pointers into name_table of the names and the final
storage system pathname (and acl), if any, for the segment;
access modes, rings, etc. for the segment; various flags used
for generation/loading of the segment, such as
abs/init/temp/supervisor segment, wired/paged, etc.; the length
and bit_count, etc. It is maintained by bootload_slt_manager and
slt_manager, who build entries based on information on the MST.
These entries are maintained so that the various pre-linkers
(bootload_linker and pre_link_hc) can find the target segments of
the various references.
SST (SYSTEM SEGMENT TABLE)
The sst (which contains the active segment table) is one of
the most important tables in Multics. It is the keeper of active
segments. Each active segment has an entry describing it (its
aste). The aste contains information used by segment control and
communicated with page control on the state of a segment. The
most important part of the entry is the page table words (ptws)
describing the disk/memory location of each page. There are four
pools of astes of different lengths to hold page tables of four
possible maximum lengths: 4, 16, 64 and 256 ptws. The entries
are threaded into various lists. The free entries of the various
pools are threaded into lists. Active segments have their own
lists. Separate lists are generated for temp and init (supervi-
sor) segs. Aside from these threads, each aste also contains
threads used to link segments to their parents and their trailer
seg entry. Status information includes: the segment's uid, the
current length, maximum length and records used, the pvtx and
vtocx of the segment (which couple with the ptws to find the
pages of the segment), various status bits of more obscure use,
and finally the quota computation information. init_sst origi-
nally builds this table. The page table words are maintained by
page control. The entries themselves are maintained by segment
control.
SST_NAMES_
The sst_names_ segment contains the names of paged segments
described by the sst. It is initialized by init_sst_name_seg
during collection 2 and maintained by segment control only if the
astk parm appears. It starts with information describing the
four aste pools followed by the paged segment primary names.
STACK_0_DATA
stack_0_data contains information keeping track of the ring
0 stacks (stack_0.nnn) that are shared between processes (one per
eligible process). It is initialized by init_stack_0. It has a
lock used to control threading of a pool of such stacks. Each
entry contains a list thread, a relative pointer to the aste for
the segment, a relative pointer to the apte for the holding
process, and the sdw for the stack. When this stack is given to
a process, this sdw is forced into its dseg; the acl of the stack
is kept as a null acl.
STOCK_SEG
stock_seg contains the record and vtoce stocks, a part of
the reliable storage system. Whenever a new page or vtoce is
needed for a drive, it is obtained from these stocks. The stocks
are filled by pre-withdrawing a number of records or vtoces from
the drive. This mechanism is used so that, upon a crash, it is
guaranteed that any records or vtoces being created were marked
in the record or vtoc maps as in use. This prevents re-used
addresses.
STR_SEG (SYSTEM TRAILER SEGMENT)
The str_seg is a paged segment used by segment control to
perform setfault functions. It is initialized into a list of
free entries by init_str_seg. Each entry contains the usual
backward and forward threads forming a list of trailers for a
given segment (the list itself is found by a relative pointer in
the aste for the segment). When needing to fault a segment, this
list shows all processes containing the segment. The entry shows
the segment number, for a process with this segment active, of
the segment and a relative pointer to the aste for the dseg of
that process (which is where we need to fault the sdw).
SYS_INFO
sys_info is a keeper of all sorts of information about the
state of the system. The most important entries to
initialization are sys_info$initialization_state, which takes on
values of 1, 2, 3 and 4 corresponding to whether we are running
initialization collection 1, 2, 3 or whether we are running
service (beyond collection 3), and sys_info$collection_1_phase,
which takes on values defined in collection_1_phases.incl.pl1
corresponding to running early, re_early, boot, bce_crash, ser-
vice and crash passes through collection 1. Also included are
key things like: the scu keeping the current time, the current
time zone, various limits of the storage system, and some ips
signal names and masks. The variable "max_seg_size" records the
maximum length of a segment. This value is changed during bce
operation to describe the maximum length of a bce paged temp
segment. This allows various Multics routines to work without
overflowing segments. Also in sys_info is "bce_max_seg_size",
this bce maximum segment length. This is available for any user
ring programs who desire to limit the size of objects they
prepare for the bce file system.
SYS_BOOT_INFO
See bootload_info, above.
SYSERR_DATA
The syserr_data segment is part of the syserr logging
mechanism. syserr actually just writes messages into this
segment and not to the paged log to avoid problems of paging
during possible system trouble. It is up to the syserr hproc to
move these messages from syserr_data to the log.
SYSERR_LOG
The paged abs-seg syserr_log, which describes the log
partition of disk, is used to hold the syserr log. It is mapped
onto the log partition by syserr_log_init. The syserr mechanism
involves putting syserr messages into syserr_data (which are
possibly written to the console) and then waking up the syserr
hproc which copies them into the paged partition. This is done
so that page faults are taken by the hproc, not by the syserr
caller who may be in trouble at the time. It starts with a
header providing the length of the segment, a lock, relative
pointers to the first and last messages placed there and also
copied out (by the answering service), the threshold that shows
how full the partition can get before the answering service is
notified to copy out the messages, the event channel for
notification (of the answering service) and the event for
locking. Following this are entries for the various syserr
messages. Each message is threaded with the others; it has a
time stamp, id number, and the text and optional data portions of
the message.
TC_DATA
tc_data contains information for the traffic controller.
The most obvious entry list herein is the list of aptes (active
process table entries). There is one apte for every process.
The apte lists activation information for the process, such as
its dbr, its state (blocked/running/stopped/etc.), various
per-process meters (such as cpu usage), its work class, and other
per-process scheduling parameters. Following the apt is the itt
(inter-process transmission table), maintained by pxss (the
traffic controller) to hold wakeups not yet received by a target
process. The call to hcs_$wakeup (or its pxss equivalent) places
an entry in the itt containing the target process id, the event
channel, the message data, etc. The next call to
hcs_$read_events obtains the events waiting for the target
process. Also present in tc_data is various meters (tcm.incl)
and other flags. Imbeded within this is the wct (work class
table) which keeps track of the status of scheduling into work
classes. tc_init builds these tables (see tc_data_header).
TC_DATA_HEADER
This is a trick initialization segment. tc_data_header is
allocated wired storage by tc_init to hold the real tc_data.
tc_data, originally build just from a cds segment and therefore
just describing the header of tc_data, is copied in. The sdws
for tc_data and tc_data_header are then swapped. As such, the
initialization segment tc_data_header (which describes the read
in tc_data) is deleted, but tc_data (now mapped onto the
allocated tc_data_header area) remains.
TOEHOLD
The toehold is another area for Multics/bootload Multics
communication. (In particular, the flagbox is contained within
it.) The toehold is a small program capable of getting to
bootload Multics from a crashing/shuting down Multics service.
(Its name is meant to suggest holding on by one's toes, in this
case to bootload Multics.) init_toehold builds a dcw (device
control word) list that, when used by the toehold program, can
write the first 512k of memory (those used by bootload Multics)
out to the bce partition and read in bootload Multics (saved in
the bce partition by init_toehold). The program runs in absolute
mode. It is listed here because it contains the flagbox and the
all important dcw lists.
TTY_AREA
Terminal control blocks (tcb's) are allocated in tty_area.
It is initialized to an area by fnp_init and managed by the
various communication software.
TTY_BUF
The tty_buf segment contains, obviously enough, the tty
buffers used for manipulating data communicated with the fnp. It
contains various meters of characters processed, number of calls
to various operations, echo-negotiation, etc., trace control
information and timer information. Following this is the
tty_trace data, if present, and the tty_buffer_block's, split
into free blocks and blocks with various flags and characters in
chains. The layout of this segment into empty areas is done by
fnp_init.
TTY_TABLES
tty_tables is an area in which tables (conversion and the
like) are allocated. It has the usual lock and lock event. It
is initialized by fnp_init.
UNPAGED_PAGE_TABLES
All permanent non-per-process unpaged segments have their
page tables in unpaged_page_tables. The page table for this
segment is also within it. It is generated initially by
template_slt_ and added to by the various segment creation
routines. The header of unpaged_page_tables contains the abso-
lute address extents of all hardcore segments that contain page
tables; these are unpaged_page_tables, int_unpaged_page_tables
and sst_seg. Dump analyzers look here to resolve absolute
addresses from sdws into virtual addresses of page tables.
VTOC_BUFFER_SEG
vtoc buffers live in the vtoc_buffer_seg. The segment is
allocated and initialized by init_vtoc_man. It starts with the
usual global lock and wait event. Following this are various
parameters of the amount and usage of the vtoc buffers, including
information about the vtoc buffer hash table. Then comes the
vtoc_man meters. Finally comes the hash table, the vtoc buffer
descriptors (pvtx - vtocx info, etc.) and the vtoc buffers
themselves.
WI_LINKAGE (WIRED INIT LINKAGE)
This initialization segment corresponds to area.linker for
wired initialization segments. It is built by the MST loading
routines.
WIRED_HARDCORE_DATA
Another collection of data for hardcore use, this segment
is permanent. It contains the size of a page, the amount to wire
for temp-wiring applications, the history register control flag,
the trap_invalid_masked bit, a flag specifying the need for
contiguous i/o buffers (if a non-paged iom exists), the debg card
options, the fim fault_counters and the bce abort_request flag.
WS_LINKAGE (WIRED SUPERVISOR LINKAGE)
This wired hardcore segment, shared between processes,
corresponds to area.linker for wired hardcore programs. It is
built by the MST loading routines.
APPENDIX C
MEMORY LAYOUT
In the memory layout charts below, the starting absolute
address and length for each data area is given (in octal). When
a number appears in brackets ([]), this means that it is really a
part of the segment listed above it.
The memory layout after the running of collection 0 (the
loading of collection 1) follows.
start length contents
----- ------ --------
0 600 fault_vector
1200 2200 iom_mailbox
3400 3000 dn355_mailbox
10000 2000 bos_toehold
12000 10000 config_deck
24000 22000 bound_bootload_0
[24000] [4000] [(bootload Multics) toehold]
[24000] [2000] [flagbox (overlays the toehold)]
[30000] [n] [bootload_early_dump]
46000 4000 toehold_data
52000 2000 unpaged_page_tables
54000 2000 int_unpaged_page_tables
56000 2000 breakpoint_page
60000 6000 physical_record_buffer
66000 2000 dseg
70000 10000 name_table
100000 4000 slt
104000 2000 lot
106000 and up wired segments
fabricated segments
1777777 and down all other segments
The absolute addresses of most of these segments is
arbitrary. Hardware known data bases must be at their proper
places, though; also, the toeholds are placed at addresses known
to operators. Except for these exceptions, the segments may be
moved. Their addresses are contained in bootload_equs.incl.alm.
All programs refering to this include file must be reassembled if
these addresses are changed. Certain interdependencies exist
that one must be aware of. First of all, the toehold is placed
at a 0 mod 4 page address. physical_record_buffer must be the
last of the fixed memory address segments. The length of all
segments is an integral number of pages. The two unpaged page
tables segments must be large enough to meet the demands on them;
refer to announce_chwm. Also, the length given for
bound_bootload_0 must hold the text thereof.
After collection 1 has finished, segments have been made
paged and collection 1 temp segments have been deleted, the
memory layout is as follows.
start length contents
----- ------ --------
0 600 fault_vector
1200 2200 iom_mailbox
3400 3000 dn355_mailbox
10000 2000 bos_toehold
24000 4000 toehold (bootload Multics)
[24000] [2000] [flagbox (overlays the toehold)]
46000 4000 toehold_data
52000 2000 unpaged_page_tables
56000 2000 breakpoint_page
60000 and up paging area
high mem sst_seg
INDEX
A aste pools 3-12, B-10
as_linkage 2-7, 3-20, B-1
aborting bce requests
see bce, aborting requests
B
abs-seg 3-10, 3-13, 3-16,
3-17, 3-18, 3-19, 4-3,
4-5, 4-16, 4-17, 6-8, A-1, bce 1-3, A-1
B-2 aborting requests 3-18, 4-5,
4-11
absolute mode 2-2 alert messages 4-4
area usage 4-2
accept_fs_disk 6-3 command level 4-10, 4-15
bce_crash 3-2
accept_rpv 6-3, 8-4 boot 3-1
crash 3-1
active init linkage early 3-1
see ai_linkage command processing 4-2, 4-9,
4-11
active segment table communication with Multics
see sst B-5
config_deck manipulation
active supervisor linkage 4-17
see as_linkage data B-1
disk accessing 4-3, 4-15
ai_linkage 2-7, 3-20, B-1 error reporting 4-2, 4-8
exec_com 4-8
announce_chwm 3-8 facilities 4-1
file system 3-16, 4-3, 4-16,
appending simulation 4-4 4-17
see also bce_dump and firmware
bce_probe loading 4-9
i/o switches 4-2, 4-7, 4-18,
area.linker B-1
see linkage sections initialization 4-1, 4-18
invocation upon a crash
assume_config_deck 2-7 B-13
bce (cont) bce_exec_com_ 4-8
machine state 5-2
paged programs 3-16 bce_exec_com_input 4-9
partitions
creation 3-6, 3-9, 3-13 bce_fwload 3-16, 4-9
usage 3-16, 4-1, 4-3,
4-16, 4-17 bce_get_flagbox 4-10
probe 4-7, 4-10, 4-11, 4-14,
4-15 bce_get_to_command_level 4-10
current address 4-13,
4-14 bce_inst_length_ 4-10
question asking 4-2, 4-14
ready messages 4-15 bce_listen_ 4-11
reinitialize 4-10
request processing 4-2, 4-6 bce_list_requests_ 4-10
request table 4-15
restrictions 4-3 bce_map_over_requests_ 4-11
temp segments 4-3, 4-17
bce_name_to_segnum_ 4-11
bce_alert 4-4
bce_probe 4-11
bce_alm_die 4-4 see also bce, probe
bce_appending_simulation 4-4, bce_probe_data 4-14
4-8, 4-14
bce_query 4-14
bce_check_abort 4-5
bce_ready 4-15
bce_command_processor_ 4-6
bce_relocate_instruction_
bce_console_io 4-6 4-15
bce_continue 4-7 bce_request_table_ 4-15
bce_crash bce command level bce_severity 4-15
see bce, command level,
bce_crash bce_shutdown_state 4-15
bce_data 4-7, B-1 boot
cold 3-13, 6-4, 6-7, A-1
bce_die 4-7 cool A-2
from bce 4-10
bce_display_instruction_ 4-7 from BOS 2-1
from disk A-6
bce_display_scu_ 4-7 from iom 2-1
from tape A-2
bce_dump 4-7 initial A-1
warm A-6
bce_error 4-8
boot bce command level
bce_esd 4-8 see bce, command level, boot
bce_execute_command_ 4-9
bootload command environment boot_rpv_subsystem 3-8
see bce
boot_tape_io 3-8
bootload command environment
data BOS
see bce_data getting to from bce 4-7
presence of 2-7
bootload Multics 1-1, A-1
bound_bootload_0 2-1, 8-1
bootload_0 2-3
breakpoints 3-15, 3-16, 3-17,
bootload_1 3-8 4-12, 4-14, 5-2
see also breakpoint_page
bootload_abs_mode 2-2
breakpoint_page 2-7, 3-9,
bootload_console 2-4 3-16, 3-17, 3-18, A-5
see also breakpoints
bootload_disk_post 4-15
bootload_dseg 2-4, 8-1 C
bootload_early_dump 2-5
central processor
bootload_error 2-5 see cpu
bootload_faults 2-5 channel table entry 7-2, B-6
bootload_file_partition 4-16, chantab B-3
4-17
clock
bootload_flagbox 2-6 setting 3-12
bootload_formline 2-6 cold boot
see boot, cold
bootload_fs_ 4-16
collection 1-1, A-2
bootload_fs_cmds_ 4-16
collection 0 1-2, 2-1
bootload_info B-1 console support 2-4
data B-1
bootload_io 2-6 error handling 2-5
input/output 2-6
bootload_linker 2-7 interrupts 2-6
main driver 2-3
bootload_loader 2-7, 8-1 programming in 2-2
bootload_qedx 4-16 collection 1 1-2, 3-1
bce_crash pass 3-2, 3-7
bootload_slt_manager 2-7 boot pass
sequence 3-2
bootload_tape_fw 2-8 bootload Multics pass 3-1
crash pass 3-1, 3-7
bootload_tape_label 2-1, 8-1 early pass 3-1
collection 1 (cont) core_map 3-14, 3-17, 8-3, B-2
early pass
sequence 3-5 cow
passes summary 3-1 see connect operand words
re_early pass 3-2, 3-7
see also bce cpu
service pass 3-1 data B-9
sequence 3-4 initialization of data 3-20
shut pass 3-1, 3-7 starting 6-9, 7-2
collection 2 1-3 crash A-2
loading 3-20 early in initialization 5-1
pre-linking 3-18 handler 3-1, 3-3
sequence 6-1 handling 1-4, 5-1
image
collection 3 1-3, 7-1 access 4-4
restarting 4-7, 5-2
collection_1_phase B-11 machine state 5-1
memory saving 5-1
collect_free_core 3-9 memory state B-13
memory swapping B-13
conditions
signalling 3-15 crash bce command level
see bce, command level,
configuration crash
data
see config_deck and scs create_root_dir 6-4
config_deck 3-10, B-2 create_root_vtoce 6-4
changes to 4-10
editing 4-17 create_rpv_partition 3-9
initial generation 3-12
setup 3-5 cte
see channel table entry
config_deck_data_ 4-16
config_deck_edit_ 3-10, 4-17 D
connect operand words 3-20
data
console about active segments B-10
collection 0 2-4 about bce B-1
driver about bootload tape B-1
see ocdcm_ about collection 0 B-1
locating 2-4 about configuration
see config_deck and scs
contiguous A-2 about core frames B-2
about cpus B-9
cool boot about hardcore segments
see boot, cool B-10
about processes B-12
core high water mark 3-8 about rpv B-2
about storage system B-11
data (cont) disk_data B-3
about system controllers
B-9 disk_emergency 9-5
about system state B-11
disk_post_queue_seg B-3
data bases B-1
disk_reader 3-9
dbm_man 6-4
disk_seg 3-11, B-3
dbm_seg 6-4, B-2
dm_journal_seg_ 6-6, B-4
dbr B-4
dn355_data B-4
deactivate_for_demount 9-4
dn355_mailbox 6-5, B-4
deciduous segments
see segments, deciduous dseg 2-8, 3-17, A-3, B-4
delete_segs 3-9 dte
see device table entry
demount_pv 9-5
dump
deposit A-3 early 2-5, A-3
to disk 4-7, A-3
descriptor segment to tape A-3
see dseg
dumper bit map seg
descriptor segment base see dbm_seg
register
see dbr
E
device table entry 7-2, B-6
devtab B-3 early bce command level
see bce, command level,
directory early
locking B-3
early initialization
dir_lock_init 6-4, 8-5 dumps 2-5
see initialization, early
dir_lock_seg 6-4, B-3
emergency shutdown 4-8
disk see shutdown, emergency
accessing 3-19, A-1, B-8
i/o posting B-3 emergency_shutdown 9-5
storage system
acceptance 6-3 errors
demounting 9-5 handling
in bce 3-14
disk queue B-3 in collection 0 2-5
reporting
disktab B-3 bce 4-8
syserr B-12
errors (cont) G
see also failures
esd gates
see shutdown, emergency initialization 6-6
linkages 8-6
establish_config_deck 3-10
getuid 6-5, 8-4
establish_temp_segs 4-8, 4-17
get_io_segs 3-11
F get_main 3-11, 8-2
group table entry 7-2, B-6
failures
of boot initialization 3-2 gte
of Multics A-2 see group table entry
of service initialization
3-2
see also errors H
fast connect code 3-18
hardcore A-3, A-5
fault_vector 2-5 address space 6-1
see also vectors
hardcore partition
fill_vol_extents_ 3-10 accessing 3-13
allocation from 3-17, 6-3
fim 5-2 amount of utilization 6-3
locating 3-13
find_file_partition 4-17 usage 6-8, 8-2, A-2, A-4
find_rpv_subsystem 3-10 hardcore segments
creation 8-1
firmware numbering 6-8, 8-5
loading
general mpcs 3-11 hc_load_mpc 3-11
in bce 4-9
into boot tape controller hproc 6-10, A-3
2-8
non-bootload disk mpcs
3-3, 3-16 I
rpv disk mpc 3-6, 3-8
location 4-9
for boot tape mpc 2-3 idle loop 6-7
naming 2-3
idle process 6-9, 6-10, 8-6
flagbox B-5
management 2-6, 4-7, 4-10 init segments 3-9
see segments, init
fnp_init 6-4
initialization A-3
fsout_vol 9-6 bce 4-1, 4-18
initialization (cont) init_proc 7-1
boot failure 3-2
directory control 6-1, 8-4 init_processor 6-6, 8-7
disk control 3-3
early A-3 init_pvt 3-13, 8-3
file system 1-3
gates 6-6 init_root_dir 6-7, 8-5
linking of A-4
page control 1-2, 3-3, 8-3 init_root_vols 3-13, 8-4
pl/1 environment 1-2
rpv 3-14 init_scavenger_data 6-7
scu 3-13
segment control 6-1, 8-4 init_scu 3-13
service failure 3-2
storage system 6-1 init_sst 3-14, 8-3
summary 1-1
traffic control 3-21, 6-1, init_sst_name_seg 6-7
8-6
init_stack_0 6-7
initialization_state B-11
init_str_seg 6-8, 8-4
initializer 3-15
init_sys_var 6-8
initializer stack
see stack, initialization init_toehold 5-1, 5-2, B-13
initialize_faults 3-15, 6-9 init_volmap_seg 6-8
initialize_faults_data 3-15 init_vol_header 3-14
initial_error_handler 3-14 init_vtoc_man 6-9, 8-4
init_aste_pools 3-12 input/output
in collection 0 2-6
init_bce 4-18
inter-process transmission
init_branches 6-5, A-2 table
see itt
init_clocks 3-12
interrupt vectors
init_dm_journal_seg 6-6 see vectors, interrupt
init_early_config 3-12 interrupts
collection 0 2-6
init_empty_root 3-12
int_unpaged_page_tables
init_hardcore_gates 6-6 see segments, unpaged
init_hc_part 3-13 inzr_stk0
see stack, initialization
init_lvt 6-6, 8-4
ioi_ 7-2
init_partitions 3-13, 8-4
ioi_data 3-11, B-6 locking
directories 6-4
ioi_init 7-2
logical channel table
ioi_page_table 7-2 see lct
iom_data 3-11, 3-16, B-6 logical volume table
see lvt
iom_data_init 3-16
lvt 6-6, 8-4, A-4, B-7
iom_mailbox B-7
io_page_tables M
see page tables, paged mode
iom
mailboxes
itt B-12 datanets B-4
iom 3-16, B-7
K make_sdw 3-16, 3-21, 8-2
make_segs_paged 3-17, A-5,
known segment table B-6
see kst
memory
kst 6-9, 8-5, A-4, B-7 accessing A-1
allocation 3-11
kst_util 6-9 allocation from slt 3-3,
3-11, 8-2
extent of usage 3-9
L freeing 3-9, 3-17
layout A-2
after collection 0 C-1
lct B-4 after make_segs_paged C-2
announcing 3-8
linkage sections 2-7, 3-20, placement 3-17
B-1, B-14, B-15 required placement C-1
hardcore gates finding 6-6 paging use 3-9
requirements for bootload
linking 3-4
see pre-linking
move_non_perm_wired_segs 3-17
loading
of collection 0 2-1 MST 3-16, 3-20, A-4
of collection 1 2-7 disk reading 3-9
of collection 2 3-20 tape reading 3-8, 3-21
of collection 3 7-2
multi-programming 6-10
load_disk_mpcs 3-16
Multics system tape
load_mst 3-16 see MST
load_system 7-2
N physical volume table
see pvt
name_table 2-8, B-8 physical_record_buffer B-8
nondeciduous segments pl1 environment
see segments, nondeciduous setup 3-8
prds_init 3-18
O
pre-linking 2-1, A-4
initialization A-4
ocdcm_ 3-18, 4-6 of collection 0 2-1
data B-8 of collection 1 2-7
of collection 2 3-18
oc_data B-8
see also ocdcm_, data pre-withdrawing B-11
pre_link_hc 3-18
P
probe
see bce, probe 4-7
page table word
see ptw ptw A-4
page table word associative ptwam A-4, A-5
memory
see ptwam pvt 3-11, 3-13, 8-3, A-4, B-8
page tables
absolute to virtual R
addresses B-14
active segments B-10
paged mode iom 7-2, B-6 read_disk 3-19, 8-3
scas B-9
see also unpaged page tables read_disk_label 3-19, 8-4
unpaged segments
see segments, unpaged read_early_dump_tape 2-5
paging real_initializer 3-19
of bce segments 3-16, 4-1
of initialization segments reinitialize 4-10
3-17
reload 7-1
partition A-4
see bce, partitions request table
see hardcore partition see bce, request table
pathname associative memory ring 1 command level 7-1
6-7
root dir
physical volume activation 6-7
see disk creation 6-4, 6-7
root physical volume segments (cont)
see rpv hardcore
data B-10
rpv A-5 permanent
initialization 3-12 numbering 8-5
layout 3-10 hierarchy
locating 3-10 numbering 8-5
init 3-9, A-3
numbering 8-5
S nondeciduous A-4
numbering
fixed 8-5
safe_config_deck 3-3 outer ring B-7
synchronized 6-6, B-4
salvaging 6-3, 6-5, 6-8 temp 3-9, A-5
numbering 8-5
save_handler_mc 5-2 unpaged A-5, B-6, B-14
scas 3-20, A-5, B-9 segment_loader 3-20
scas_init 3-20 setfault B-11
scavenger 9-6 shutdown 9-1, 9-6, A-5
emergency 4-8, 9-3, 9-5,
scavenger_data 6-7, B-9 A-3
part 1 9-2
scs 3-20, A-5, B-9 normal 9-7
scs_and_clock_init 3-20 shutdown_file_system 9-7
scu shutdown_state 9-6
data B-9
initialization of data 3-20 slt 2-7, 2-8, 3-21, A-5, B-8,
register access B-9 B-10
memory allocation from
sdw 2-4, 8-2, A-5, B-4 see memory, allocation
creation 3-16 from slt
segment descriptor word slt_manager 3-21
see sdw
sst 3-14, 3-17, 8-3, 8-4,
segment descriptor word B-10
associative memory
see sdwam sst_names_ 6-7, B-10
segment loading table stack
see slt collection 0 2-2
initialization B-5
segments ring 0 6-7, B-11
activation information B-7 segment numbering 8-5
deactivation 9-4 shutdown 9-4, 9-6, 9-7, B-5
deciduous 6-5, 8-3, 8-6,
9-4, A-2 stack_0_data B-11
start_cpu 6-9, 8-7 sys_info$bce_max_seg_size
4-17
stocks 3-11, 8-4, 9-6, B-8,
B-11
T
stock_seg B-11
stop on switches 3-20 tape_reader 3-21
str_seg 6-8, B-11 tcb B-13
supervisor tc_data 3-21, B-12
see hardcore
tc_data_header B-13
switches
i/o tc_init 3-21, 6-10, 7-2, 8-6
see bce, i/o switches
tc_shutdown 9-7
switch_shutdown_file_system
9-7 temp segments 3-9
see segments, temp
synchronized segments
see segments, synchronized template_slt_ 2-8, 8-1, B-5,
B-6, B-8, B-10, B-14
syserr_data B-12
terminal control blocks
syserr_log 6-9, B-12 see tcb
syserr_log_init 6-9 toehold 2-5, 5-1, 8-1, B-13
entry points 5-1
system communications segment
see scs traffic control
data B-12
system controller initialization
see scu see initialization,
traffic control
system controller addressing shutdown 9-7
segment
see scas tty_area 6-4, B-13
system segment table tty_buf 6-4, B-13
see sst
tty_tables 6-5, B-14
system trailer segment
see str_seg
U
system_type 2-7
sys_boot_info B-1 uid 6-5, 8-4, A-5
sys_info B-11 unique identifier
see uid
unpaged page tables 2-7, 2-8, warm boot
3-8, 3-11, 8-2 see boot, warm
unpaged segments wired A-6
see segments, unpaged
wired init linkage
see wi_linkage
V
wired supervisor linkage
see ws_linkage
vectors
fault B-5 wired_hardcore_data B-14
initialization 3-15
collection 2 6-9 wired_shutdown 9-7
interrupt B-5
see also fault_vector withdraw A-6
setup 2-5
wi_linkage 2-7, 3-20, B-14
volmap_seg 6-8
ws_linkage 2-7, 3-20, B-15
volume table of contents
see vtoc
vtoc A-6
accessing 6-8
updating 9-5, 9-6
vtoce A-6
accessing 6-3, 6-9, 8-4
buffers 6-9, 9-7, B-14
creation
deciduous segments 6-5,
8-3
initial 3-14
root dir 6-4
deactivation 9-5
dumper bit B-3
scavenger B-9
specifying number 3-13
stock 9-6, B-8, B-11
updating 6-8, 9-1, 9-4
updating for partition
creation 3-9
vtoc_buffer_seg B-14
W
wakeups B-12