The figure shows a high-level architecture of the OS 2200 system identifying major hardware and software components. The majority of the Unisys software is included in the subsystems and applications area of the model. For example, the database managers are subsystems and the compilers are applications.

System basics

The details of the system architecture are covered in Unisys publication 3850 7802 Instruction Processor Programming Reference Manual. Also see UNIVAC 1100/2200 series.

The 1100 Series has used a 36-bit word with 6-bit characters since 1962. 36-bit computing was driven by a desire to process 10-digit positive and negative numbers. Also the military needed to be able to calculate accurate trajectories, design bridges, and perform other engineering and scientific calculations, they needed more than 32 bits of precision. A 32-bit floating point number only provided about 6 digits of accuracy while a 36 bit number provided the 8 digits of accuracy that were accepted as the minimum requirement. Since memory and storage space and costs drove the system, going to 64 bits was simply not acceptable in general. These systems use ones' complement arithmetic, which was not unusual at the time. Almost all computer manufacturers of the time delivered 36-bit systems with 6-bit characters including IBM, DEC, General Electric, and Sylvania.

The 6-bit character set used by the 1100 Series is also a DoD mandated set. It was defined by the Army Signal Corps and called Fieldata (data returned from the field).Watts S. Humphrey, "MOBIDIC and Fieldata," IEEE Annals of the History of Computing, vol. 9, no. 2, pp. 137-182, Apr.-June 1987, . http://doi.ieeecomputersociety.org/10.1109/MAHC.1987.10018 The 1108 provided a 9-bit character format in order to support ASCII and later the ISO 8-bit sets, but they were not extensively used until the 1980s again because of space constraints.

The 2200 Series architecture provides many registers. Base registers logically contain a virtual address that points to a word in a code or data bank (segment). They may point to the beginning of the bank or to any word within the bank. Index registers are used by instructions to modify the offset of the specified or assumed base register. Simple arithmetic (add, subtract) may be performed on all index registers. In addition, index registers consist of a lower offset portion and an upper increment portion. An instruction may both use the offset value in an index register as part of an address and specify that the increment is to be added to the offset. This allows loops to be accomplished with fewer instructions as incrementing the index by the step size can be accomplished without a separate instruction. Arithmetic registers allow the full set of computational instructions including all floating point operations. Some of those instructions work on adjacent pairs of registers to perform double-precision operations. There are no even-odd constraints. Any two registers may be used as a double-precision value. Four of the arithmetic registers are also index registers (the sets overlap – index register X12 is arithmetic register A0). This allows the full range of calculations to be performed on indexes without having to move the results. The rest of the registers, known as R registers, are used as fast temporary storage and for certain special functions. R1 holds the repeat count for those instructions that may be repeated (block transfer, execute repeated, etc.). R2 holds a bit mask for a few instructions that perform a bitwise logical operation in addition to some other functions (e.g., masked load upper)

There are two full sets of registers (A, X, R, and B). One set, the user registers, is used by all applications and most portions of the operating system. It is saved and restored as part of activity (thread) state. The other set, the Exec registers, is used by interrupt processing routines and some other portions of the operating system that want to avoid having to save and restore user registers. The Exec registers are not writable by user applications although some user code can read them. As a result, the Exec is carefully designed never to leave private, secure, or confidential information in registers. Instruction interpretation chooses the appropriate register set to use based on a bit in the Processor State Register. This bit is always set (changed to privileged) on an interrupt. All registers are also visible in the address space, but the Exec portion is protected and a reference by non-privileged code will result in a fault interrupt.

The 2200 Series uses a 36-bit segmented virtual address space. We’ll look later at the addressing architecture.

The 2200 Series is a CISC architecture system. Not only are there a large number of instructions (current count is about 245) but many of them have addressing variants. Some of the variants are encoded directly in the instruction format (partial word references) and some are dependent on Processor State Register settings. Many instructions also perform very complex functions such as one that implements a large part of the COBOL EDIT verb.

The above figure shows some of the building blocks of the architecture. "Data" and "COMM" are two of the primary examples of software subsystems that live in a protection ring between that of a user application and the Exec. There are many other such subsystems and users write their own.

Memory and addressing

Level

As mentioned above, the 2200 Series uses a 36-bit segmented virtual address. The original notion of a segmented space came from the earliest implementation that emphasized code and data separation for performance and the use of shared code banks. Over the years, this expanded to provide greater flexibility of levels of sharing and far greater protection for security and reliability. Controlled access to shared data was also introduced.

A virtual address consists of three parts. The high-order 3 bits define the sharing level. This is the heart of the entire addressing and protection scheme. Every thread has eight Bank Descriptor Tables (Segment Descriptor Tables in the industry) based on B16-B23. The tables are indexed by level – level 0 refers to the Bank Descriptor Table (BDT) based on B16, level 2 the BDT based on B18, etc. The level 0 and level 2 BDTs are common to all threads in the system. Every run (process) has its own level 4 BDT, and that BDT is common to all threads in the run. Every user thread has its own unshared level 6 BDT.

Activity

Each extended-mode activity (thread) always has six banks, segments, which are totally unique to it. One is the Return Control Stack, which holds information about the calling structure, including any security relevant privilege and state changes. It is not accessible by the thread except through the use of the CALL, RETURN, and similar instructions. This is a major part of the protection and reliability mechanism. Applications cannot cause bad effects by changing the return addresses or overwriting the return control stack.Unisys Corporation (2013). Exec System Software Executive Requests Programming Reference Manual. (Unisys publication 7830 7899). Roseville, MN. http://public.support.unisys.com/2200/docs/cp14.0/pdf/78307899-022.pdf

Another unique bank is the automatic storage bank (Activity Local Store stack). This is used by the compilers to hold local variables created within a block. It is also used to hold all parameter lists passed on a call. One of the checks made by the operating system both on its own behalf and when a call is made to a protected subsystem is to ensure that the operands are on the thread-local stack and that the thread has the right to access the memory region referenced by any parameters. Because the parameters are kept in thread-local space, there is no chance that some other thread may change them during or after validation. It is the responsibility of the called procedure to perform similar checks on any secondary parameters that may exist in shared space (i.e., the primary parameter points to a structure that contains pointers). The procedure is expected to copy any such pointers to its own local space before validating them and then to use only that internally held validated pointer.

Activities may create additional segments up to the limit of the available address space (233 words = 8GW or about 36GB). This is a convenient way for multi-threaded applications to get large amounts of memory space knowing that it is totally thread-safe and that they are not taking any space away from the rest of what is available to the program. Each activity in a program has its own independent space, meaning an application with 100 activities (for example) is able to use over 800GW (>3TB) of virtual space.

Basic-mode activities do not start out with any such banks, as basic-mode programs are not aware of the virtual address space, but any calls to extended-mode subsystems will cause those banks to be created.

Programs

OS 2200 does not implement programs in exactly the same way that UNIX, Linux, and Windows implement processes, but that is the closest analogy. The most obvious difference is that OS 2200 only permits a single program per Run (Job, Session) to be executing at a time. A program may have hundreds of threads, but cannot spawn other programs to run concurrently.

There are several banks at the Program level that contain a mixture of Run (job, session) information and program information. These are control structures for the operating system. They have no access or read-only access for the program. Programs may retrieve information from some of these structures for debugging purposes or to retrieve things like the user-id and terminal-id without the overhead of a system call. They cannot be written by the program. They contain things like the thread state save areas, file control blocks, and accounting information.

The rest of the banks are used by the program. When a program object file is executed, the operating system obtains the bank information from the file and creates banks as needed and loads the bank initial state from the file. The simplest program has a single bank containing code and data. This is considered very bad form, but is permitted for compatibility with old applications. You can only create such an application with assembly language. The standard compilers create one or more code banks and one or more data banks. Normally the code banks are marked as read-only as a debugging and reliability aid. There are no security concerns either way. The program can only affect itself.

Each program thus has its own address space distinct from all other programs in the system. Nothing a program can do can change the contents of any other program’s memory. The OS and shared subsystems are protected by other mechanisms which are discussed below. Even read access is prohibited to OS and subsystem memory in almost all cases from code in a program. It is possible to create a shared subsystem which is generally readable, or even writable, by multiple programs, but it must be explicitly installed that way by a privileged system administrator. Programs are initially created with only the banks specified in the object file and with a single activity. They may use system calls to create additional banks within their own program level and additional activities.

Subsystems