Program Status Word

From OSDev Wiki
Jump to navigation Jump to search

The Program Status Word (PSW) on IBM Mainframe architectures (s390x / z/Architecture and ESA/390) is the central execution context register of the CPU. It controls the instruction address, execution state (supervisor vs. user/problem state, wait state), DAT (paging), interrupt masks, condition code, arithmetic exception masks, storage protection keys, and addressing modes.

Depending on the operational mode and the instruction used, the CPU works with three distinct PSW formats:

  1. Extended PSW (16 bytes / 128 bits): The standard native format in 64-bit z/Architecture, commonly referred to as a current PSW.
  2. Short PSW (8 bytes / 64 bits): An 8-byte format used within z/Architecture when executing legacy instructions like LPSW or processing certain I/O/interruption structures.
  3. ESA/390 PSW (8 bytes / 64 bits): The native 31-bit format used when the CPU is running in ESA/390 mode (e.g., before switching to z/Architecture or in 31-bit guest partitions).

Bit Numbering Convention

In standard IBM Principles of Operation (PoP) documentation and hardware specifications, Bit 0 is the Most Significant Bit (MSB 0).

  • In a 64-bit doubleword: Bit 0 is 0x8000000000000000ULL, Bit 63 is 0x0000000000000001ULL.
  • In a 32-bit word: Bit 0 is 0x80000000U, Bit 31 is 0x00000001U.

1. Extended PSW (16-Byte z/Architecture Format)

The native z/Architecture format consists of two 64-bit doublewords (16 bytes total, 8-byte aligned) loaded via LPSWE.

Doubleword 0: PSW Mask (Bits 0–63)

Bits (MSB 0) Bitmask (64-bit) Short Name Description
0 Reserved Must be 0; otherwise triggers a Specification Exception (`PGM_SPECIFICATION`).
1 0x4000000000000000ULL R Program Event Recording (PER) 1 = PER enabled (hardware debugging/trace traps).
2–4 Reserved Must be 0.
5 0x0400000000000000ULL T Dynamic Address Translation (DAT) 1 = DAT enabled (virtual addressing). 0 = Real/Absolute addressing.
6 0x0200000000000000ULL IO I/O Interrupt Mask 1 = Input/Output interruptions unmasked.
7 0x0100000000000000ULL EX External Interrupt Mask 1 = External interruptions (timers, inter-CPU signals) unmasked.
8–11 0x00F0000000000000ULL Key PSW Storage Key 4-bit storage access key (0 = master key).
12 Architecture Mode Must be 0 in z/Architecture.
13 0x0004000000000000ULL M Machine-Check Mask 1 = Machine-check interruptions unmasked.
14 0x0002000000000000ULL W Wait State 1 = CPU is halted in wait state.
15 0x0001000000000000ULL P Problem State 0 = Supervisor state (Privileged), 1 = Problem state (User mode).
16–17 0x0000C00000000000ULL AS Address-Space Control (ASC) Determines the active translation table register (CR1, CR7, or CR13).
18–19 0x0000300000000000ULL CC Condition Code Condition code (0, 1, 2, or 3).
20–23 0x00000F0000000000ULL PM Program Mask Arithmetic exception masks (Fixed-point overflow, Decimal overflow, HFP underflow, HFP significance).
24–30 Reserved Must be 0.
31 0x0000000100000000ULL EA Extended Addressing Mode Extended addressing mode bit.
32 0x0000000080000000ULL BA Basic Addressing Mode Basic addressing mode bit.
33–63 Reserved Must be 0 in the 16-byte PSW mask.

Doubleword 1: Instruction Address (Bits 64–127)

  • Holds the 64-bit virtual/absolute instruction address.
  • Bit 127 must be 0 (all s390x instructions are aligned to 2-byte halfwords).

2. Short PSW (8-Byte z/Architecture Format)

In z/Architecture mode, an 8-byte (64-bit) Short PSW format exists primarily to maintain compatibility with software or instructions that only pass 64-bit descriptors (such as LPSW, legacy channel programs, and certain diagnostics).

Unlike the 16-byte PSW, the Short PSW packs both the control flags and a 31-bit instruction address into a single 64-bit word.

Short PSW Layout

Bits (MSB 0) Short Name Description
0 Reserved Must be 0.
1 R PER Mask Program Event Recording.
2–4 Reserved Must be 0.
5 T DAT Mode Dynamic Address Translation.
6 IO I/O Mask I/O Interrupt Enable.
7 EX External Mask External Interrupt Enable.
8–11 Key Storage Key 4-bit storage protection key.
12 Architecture Mode Must be 0 in z/Architecture.
13 M Machine Check Machine Check Interrupt Enable.
14 W Wait State CPU Wait State.
15 P Problem State Problem State (0 = Supervisor, 1 = User).
16–17 AS Address-Space Control Primary (00), Secondary (01), AR (10), Home (11).
18–19 CC Condition Code Condition code.
20–23 PM Program Mask Arithmetic masks.
24–30 Reserved Must be 0.
31 EA Extended Addressing Extended addressing mode bit.
32 BA Basic Addressing Basic addressing mode bit.
33–63 IA Instruction Address 31-bit instruction address (Target PC).

Behavior of LPSW in z/Architecture

When the LPSW (opcode `82`) instruction is executed in z/Architecture mode:

  1. Bits 0–32 of the 8-byte operand are loaded directly into bits 0–32 of the CPU's internal 64-bit PSW mask.
  2. Bits 33–63 of the internal PSW mask are set to 0.
  3. Bits 0–32 of the internal 64-bit instruction address are set to 0.
  4. Bits 33–63 of the 8-byte operand are loaded into bits 33–63 of the internal instruction address.

3. ESA/390 Mode PSW (8-Byte Legacy Format)

When the processor is running in ESA/390 mode (e.g. at initial IPL before sending a `SIGP` architecture-switch signal, or inside a 31-bit legacy virtual machine), the CPU uses the legacy 64-bit ESA/390 Extended Control (EC-mode) PSW.

ESA/390 PSW Layout

Bits (MSB 0) Short Name Description
0 Reserved Must be 0.
1 R PER Mask Program Event Recording.
2–4 Reserved Must be 0.
5 T DAT Mode Dynamic Address Translation.
6 IO I/O Mask I/O Interrupt Enable.
7 EX External Mask External Interrupt Enable.
8–11 Key Storage Key 4-bit storage key.
12 A Architecture Mode Must be 1 in ESA/390 EC-mode.
13 M Machine Check Machine Check Mask.
14 W Wait State Wait State flag.
15 P Problem State Problem State flag.
16–17 AS Address-Space Control Primary (00), Secondary (01), AR (10), Home (11).
18–19 CC Condition Code Condition code.
20–23 PM Program Mask Arithmetic masks.
24–31 Reserved Must be 0.
32 A Addressing Mode 0 = 24-bit AMODE, 1 = 31-bit AMODE.
33–63 IA Instruction Address 31-bit instruction address.

Differences Between Short PSW and ESA/390 PSW

While both formats are 8 bytes long:

  • Bit 12: Is 0 in z/Architecture Short PSW, but must be 1 in ESA/390 EC-mode.
  • Bit 31: Is EA (Extended Addressing) in z/Arch Short PSW, but is a reserved 0 bit in ESA/390.
  • Bit 32: Is BA (Basic Addressing) in z/Arch Short PSW, but represents the sole 31-bit addressing mode flag in ESA/390.

Addressing Modes (AMODE)

In z/Architecture (both 16-byte and Short PSW), addressing modes are controlled by the pair of bits EA (Bit 31) and BA (Bit 32):

EA (Bit 31) BA (Bit 32) Mode Address Bits Evaluated
0 0 24-bit addressing Lower 24 bits (Bits 40–63)
0 1 31-bit addressing Lower 31 bits (Bits 33–63)
1 1 64-bit addressing Full 64 bits (Bits 0–63)
1 0 Invalid Triggers a Specification Exception (`PGM_SPECIFICATION`).

Address Space Control (ASC) Modes

When DAT is enabled (Bit 5 = 1), bits 16–17 select the active translation mode:

Bits 16–17 Mode Active ASCE Source Usage
00 Primary-space mode Control Register 1 (CR1) Standard user/kernel virtual address space.
01 Secondary-space mode Control Register 7 (CR7) Cross-memory communication.
10 Access-register (AR) mode Access Registers (AR0–AR15) Fine-grained multi-space addressing via ALETs.
11 Home-space mode Control Register 13 (CR13) Kernel / system-wide execution space.

Interruption Lowcore Vectors

In 64-bit z/Architecture, interruptions automatically save the current 16-byte PSW to an Old PSW field in the Lowcore (the Prefix Page, real offset `0x0000`), and load the execution context from the corresponding 16-byte New PSW:

Interruption Class Old PSW Offset New PSW Offset
Restart 0x0120 0x01A0
External 0x0130 0x01B0
Supervisor Call (SVC) 0x0140 0x01C0
Program Check (Exception) 0x0150 0x01D0
Machine Check 0x0160 0x01E0
Input/Output (I/O) 0x0170 0x01F0

(Note: In legacy ESA/390 31-bit mode, Old and New PSWs are 8 bytes each and reside at offsets `0x0018`–`0x0078`).


C Structures & Code Examples

C Definitions for All Three PSW Types

#include <stdint.h>

/* 1. Standard 16-byte z/Architecture Extended PSW */
typedef struct __attribute__((packed, aligned(8))) {
    uint64_t mask;
    uint64_t addr;
} zpsw_t;

/* 2. 8-byte z/Architecture Short PSW (used by LPSW under z/Arch) */
typedef struct __attribute__((packed, aligned(8))) {
    uint32_t mask_flags; /* Bits 0..32: Control flags + EA/BA */
    uint32_t addr_31;    /* Bits 33..63: 31-bit address */
} short_psw_t;

/* 3. 8-byte legacy ESA/390 Mode PSW */
typedef struct __attribute__((packed, aligned(8))) {
    uint32_t mask_flags; /* Bits 0..31: Includes Bit 12 (EC mode = 1) */
    uint32_t addr_31;    /* Bit 32 = AMODE31 flag, Bits 33..63 = 31-bit address */
} esa390_psw_t;

/* Extended PSW Mask Constants (MSB 0) */
#define PSW_MASK_PER         (0x4000000000000000ULL)
#define PSW_MASK_DAT         (0x0400000000000000ULL)
#define PSW_MASK_IO          (0x0200000000000000ULL)
#define PSW_MASK_EXT         (0x0100000000000000ULL)
#define PSW_MASK_KEY(k)      (((uint64_t)((k) & 0x0F)) << 52)
#define PSW_MASK_MCHECK      (0x0004000000000000ULL)
#define PSW_MASK_WAIT        (0x0002000000000000ULL)
#define PSW_MASK_PROBLEM     (0x0001000000000000ULL)

/* Address Space Control Modes */
#define PSW_ASC_PRIMARY      (0x0000000000000000ULL)
#define PSW_ASC_SECONDARY    (0x0000800000000000ULL)
#define PSW_ASC_ACCREG       (0x0000400000000000ULL)
#define PSW_ASC_HOME         (0x0000C00000000000ULL)

/* 64-bit Addressing Mode (EA=1 | BA=1) */
#define PSW_MASK_EA          (0x0000000100000000ULL)
#define PSW_MASK_BA          (0x0000000080000000ULL)
#define PSW_MASK_AMODE64     (PSW_MASK_EA | PSW_MASK_BA)

/* Standard Pre-composed 64-bit Kernel Masks */
#define PSW_KERNEL_BOOT \
    (PSW_MASK_AMODE64 | PSW_ASC_PRIMARY)

#define PSW_KERNEL_RUNNING \
    (PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | PSW_MASK_AMODE64 | PSW_ASC_HOME)

#define PSW_USER_RUNNING \
    (PSW_MASK_PROBLEM | PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | PSW_MASK_AMODE64 | PSW_ASC_PRIMARY)

Loading PSWs

Loading a 16-Byte Extended PSW (LPSWE)

static inline __attribute__((noreturn)) void lpswe(const zpsw_t *psw) {
    __asm__ volatile (
        "lpswe %0\n"
        :
        : "Q" (*psw)
        : "cc", "memory"
    );
    __builtin_unreachable();
}

Loading an 8-Byte Short PSW (LPSW)

static inline __attribute__((noreturn)) void lpsw(const short_psw_t *psw) {
    __asm__ volatile (
        "lpsw %0\n"
        :
        : "Q" (*psw)
        : "cc", "memory"
    );
    __builtin_unreachable();
}

Extracting Current PSW Mask (EPSW)

static inline uint64_t epsw(void) {
    uint32_t hi, lo;
    __asm__ volatile (
        "epsw %0, %1\n"
        : "=d" (hi), "=d" (lo)
    );
    return ((uint64_t)hi << 32) | (uint64_t)lo;
}

CPU Idle & Panic Idioms

Enabled Wait (Idle Loop)

void cpu_idle(void) {
    zpsw_t wait_pswrest = {
        .mask direct = PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | 
                       PSW_MASK_MCHECK | PSW_MASK_WAIT | PSW_MASK_AMODE64 | PSW_ASC_HOME,
        .addr = (uint64_t)&&wake_up
    };

    lpswe(&wait_pswrest);

wake_up:
    return;
}

Disabled Wait (Panic / Halt)

__attribute__((noreturn)) void cpu_halt(uint64_t panic_code) {
    zpsw_t halt_psw = {
        .mask = PSW_MASK_WAIT | PSW_MASK_AMODE64,
        .addr地理 = (panic_code != 0) ? panic_code : 0x0000000000DEAD00ULL
    };

    lpswe(&halt_psw);
}

See Also