NUMA Profiles for systemd
=========================

This directory contains hardware-specific NUMA memory policy profiles for the
system manager (PID 1). When NUMAPolicy= is not explicitly configured in
system.conf or system.conf.d, systemd evaluates these profiles at startup and
on daemon-reload, and applies the best matching profile to the service manager
and all forked processes.


Configuration Paths
-------------------

Profiles are loaded from the following directories (in standard cascade order):

    /etc/systemd/numa-profiles.d/*.conf
    /run/systemd/numa-profiles.d/*.conf
    /usr/local/lib/systemd/numa-profiles.d/*.conf
    /usr/lib/systemd/numa-profiles.d/*.conf

Files must use the .conf suffix. To add a profile for a new platform, drop a
new file into one of these directories. To disable a vendor-shipped profile,
place an empty file or a profile with Disabled=yes at the same path under /etc/.


How It Works
------------

During startup and on `systemctl daemon-reload`, systemd:

  1. Parses system.conf and system.conf.d.
  2. If NUMAPolicy= is already explicitly configured, profile matching is
     skipped entirely.
  3. Otherwise, gathers hardware information (CPU, memory type, NUMA nodes).
  4. Loads and evaluates all profile files.
  5. Selects the best matching profile and applies its NUMA settings via
     set_mempolicy(2).

If no profile matches, the default NUMA policy is used and the system behaves
as if no profiles were installed.


Profile File Format
-------------------

Each file defines exactly one profile and contains three sections:

    [Profile]    Metadata (name, description, etc.)
    [Match]      Hardware matching conditions (at least one required)
    [NUMA]       NUMA policy to apply when matched


[Profile] Section
~~~~~~~~~~~~~~~~~

Name=
    Unique profile identifier used in logs and on the kernel command line.
    If omitted, derived from the file name by stripping a leading numeric
    prefix and the .conf suffix.
    Example: 10-zhaoxin-kx7000-ddr5.conf → zhaoxin-kx7000-ddr5

Description=
    Human-readable description (documentation only).

Disabled=
    When yes, the profile is ignored. Default: no


[Match] Section
~~~~~~~~~~~~~~~

All fields are optional; unspecified fields impose no restriction.

  - Values in the same field separated by | or whitespace: OR
  - Different fields: AND
  - At least one field must be specified

CPUVendor=
    Match CPU vendor from /proc/cpuinfo (vendor_id or vendor).
    Case-insensitive substring match.
    Example: centaurhauls|shanghai

CPUModel=
    Match numeric CPU model from /proc/cpuinfo. Exact match.
    Example: 107

CPUModelName=
    Match CPU model name from /proc/cpuinfo.
    Case-insensitive substring match.
    Example: KX-7000|ZHAOXIN

CPUArchitecture=
    Match machine architecture from uname(2).
    Exact match. Example: x86_64|aarch64

MemoryType=
    Match memory type detected from SMBIOS Type 17 (Memory Device) records.
    Only populated memory modules are considered. Case-insensitive substring
    match against the DMI type string (e.g. DDR5, DDR4, LPDDR5).
    Example: DDR5|DDR4

MinNUMANodes=
    Require at least this many online NUMA nodes.

MaxNUMANodes=
    Require at most this many online NUMA nodes.

ExactNUMANodes=
    Require exactly this many online NUMA nodes.
    When set, MinNUMANodes= and MaxNUMANodes= are ignored.


[NUMA] Section
~~~~~~~~~~~~~~

NUMAPolicy=
    Required. One of: default, preferred, bind, interleave, local

NUMAMask=
    NUMA node mask. Required for bind and interleave unless using a
    special value below.

    Supported forms:
      0-1         Range of nodes
      0,2,4       Explicit list
      all         All online NUMA nodes
      auto        Automatically 0 through (N-1), where N is the current
                  online NUMA node count


Profile Selection
-----------------

When multiple profiles match, the winner is chosen by:

  1. Source path: /etc/ > /run/ > /usr/local/ > /usr/lib/
  2. Lexicographically earlier file name (e.g. 10-foo.conf before 90-bar.conf)

Prefix profile files with a numeric ordering prefix such as 10-, 20-, 90-.
Lower numbers win when profiles live in the same directory.


Control and Override
--------------------

Explicit system.conf configuration (highest priority)
    If system.conf or system.conf.d sets NUMAPolicy=, profile matching is
    never performed.

Kernel command line: systemd.numa.auto=
    Boolean. When false, disables profile matching entirely.
    Default: enabled.

Kernel command line: systemd.numa.profile=<Name>
    Force a specific profile by name, skipping [Match] evaluation.
    Useful for debugging.

Local extension
    Add files under /etc/systemd/numa-profiles.d/ to extend or override
    vendor profiles without modifying /usr/lib/.


Examples
--------

Zhaoxin KX7000 + DDR5 + dual NUMA
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    # /etc/systemd/numa-profiles.d/10-zhaoxin-kx7000-ddr5.conf
    # (shipped by systemd-enhance-conf on Kylin)

    [Profile]
    Name=zhaoxin-kx7000-ddr5
    Description=Zhaoxin KX7000 with DDR5, dual NUMA interleave

    [Match]
    CPUVendor=centaurhauls|shanghai
    CPUModel=107
    CPUModelName=KX-7000
    MemoryType=DDR5
    ExactNUMANodes=2

    [NUMA]
    NUMAPolicy=interleave
    NUMAMask=0-1

Generic dual-NUMA fallback
~~~~~~~~~~~~~~~~~~~~~~~~~~

    # /usr/lib/systemd/numa-profiles.d/90-fallback-dual-node.conf

    [Profile]
    Name=fallback-dual-node
    Description=Generic fallback for any dual-NUMA platform

    [Match]
    ExactNUMANodes=2

    [NUMA]
    NUMAPolicy=interleave
    NUMAMask=auto

Phytium ARM dual-NUMA
~~~~~~~~~~~~~~~~~~~~~

    [Profile]
    Name=phytium-dual-node

    [Match]
    CPUArchitecture=aarch64
    CPUModelName=Phytium
    MinNUMANodes=2
    MaxNUMANodes=2

    [NUMA]
    NUMAPolicy=interleave
    NUMAMask=auto


Verification
------------

    # Inspect active NUMA policy
    systemctl show -p NUMAPolicy -p NUMAMask

    # View merged system.conf (explicit NUMA settings)
    systemd-analyze cat-config systemd/system.conf | grep NUMA

    # NUMA topology
    numactl -H

    # Check journal for profile match messages
    journalctl -b | grep "NUMA profile"


Adding a New Platform
---------------------

  1. Create a new .conf file in numa-profiles.d/
  2. Prefix the file name with a numeric ordering prefix (e.g. 10-, 20-)
  3. Set a unique Name=
  4. Define [Match] conditions specific to the hardware
  5. Set [NUMA] policy and mask
  6. Run systemctl daemon-reload (or reboot) to apply

No code changes are required for new platforms — only a new profile file.


See Also
--------

    systemd-system.conf(5)  — explicit NUMAPolicy= / NUMAMask= settings
    systemd.exec(5)         — per-unit NUMA policy overrides
    numactl(8)              — NUMA topology inspection
    set_mempolicy(2)        — kernel NUMA policy interface
