Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/.ci/aosc/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ ARG DEPENDENCIES=" \
libglib2.0-dev \
libssl-dev \
make \
meson \
ninja \
pkg-config \
python3-setuptools \
Expand Down
1 change: 1 addition & 0 deletions .github/.ci/debian/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ ARG DEPENDENCIES=" \
libssl-dev \
lsb-release \
make \
meson \
ninja-build \
pkg-config \
python3-setuptools \
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build-docker-images.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ on:
jobs:
build:
runs-on: ${{ matrix.IMAGE.RUNNER }}
timeout-minutes: 10
timeout-minutes: 20
permissions:
contents: read
packages: write
Expand Down
62 changes: 27 additions & 35 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,46 +38,32 @@ permissions:

# Test registration and suite selection rules are documented in tests/README.md.
jobs:
latu-runtime-manager:
name: "latu runtime manager (${{ matrix.container.name }})"
meson-fast:
name: "test (${{ matrix.container.name }}, lat-pr-fast)"
runs-on: ubuntu-latest
timeout-minutes: 5
timeout-minutes: 40

strategy:
fail-fast: false
matrix:
container:
- { name: "latx-runner-aosc", tag: "loong64" }
- { name: "latx-runner-debian", tag: "loong64" }
- { name: "latx-runner-fedora", tag: "loongarch64" }

steps:
- uses: actions/checkout@v7
with:
persist-credentials: false

- name: Setup QEMU
uses: docker/setup-qemu-action@v4

- name: Run dual-translator status checks
run: |
docker run --rm \
--platform linux/loong64 \
--volume "$(pwd):/io" \
--workdir /io \
"ghcr.io/${{ github.repository_owner }}/${{ matrix.container.name }}:${{ matrix.container.tag }}" \
sh tests/runtime/test-latu-runtime-manager.sh

meson-fast:
name: "test (latx-runner-debian, lat-pr-fast)"
runs-on: ubuntu-latest
timeout-minutes: 25
- name: "latx-runner-aosc"
tag: "loong64"
sanitizers: false
prepare_meson: "command -v meson >/dev/null || oma install -y meson"
- name: "latx-runner-debian"
tag: "loong64"
sanitizers: true
prepare_meson: "command -v meson >/dev/null || { apt-get update && apt-get install -y meson; }"
- name: "latx-runner-fedora"
tag: "loongarch64"
sanitizers: false
prepare_meson: "command -v meson >/dev/null"

steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
submodules: true

- name: Setup QEMU
uses: docker/setup-qemu-action@v4
Expand All @@ -88,27 +74,33 @@ jobs:
--platform linux/loong64 \
--volume "$(pwd):/io" \
--workdir /io \
ghcr.io/lat-opensource/latx-runner-debian:loong64 \
"ghcr.io/${{ github.repository_owner }}/${{ matrix.container.name }}:${{ matrix.container.tag }}" \
sh -eux -c '
${{ matrix.container.prepare_meson }}
meson --version
export CFLAGS="-Wno-error=unused-but-set-variable -Wno-error=unused-function -Wformat -Werror=format-y2k"
mkdir -p build64-tests
cd build64-tests
sanitizer_flags=
if [ "${{ matrix.container.sanitizers }}" = true ]; then
sanitizer_flags="--enable-debug --enable-sanitizers"
fi
../configure \
--target-list=x86_64-linux-user \
--target-list=x86_64-linux-user,i386-linux-user \
--enable-latx \
--enable-debug \
--enable-tests \
--enable-sanitizers \
--disable-werror \
--optimize-O1 \
--extra-ldflags=-ldl \
--disable-docs \
--with-git-submodules=ignore
--meson=meson \
--with-git-submodules=ignore \
$sanitizer_flags
cd ..
export LATX_RUNTIME_TEST_SKIP_GUEST_EXECUTION=1
ASAN_OPTIONS=detect_leaks=0 \
UBSAN_OPTIONS=halt_on_error=1:print_stacktrace=1 \
python3 -B meson/meson.py test \
meson test \
-C build64-tests \
--suite lat-pr-fast \
--print-errorlogs
Expand Down
1 change: 1 addition & 0 deletions docs/tools/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Contents:
:maxdepth: 2

qemu-img
latu-runtime-manager
qemu-storage-daemon
qemu-nbd
qemu-pr-helper
Expand Down
140 changes: 140 additions & 0 deletions docs/tools/latu-runtime-manager.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
LATU guest runtime diagnostics
==============================

Synopsis
--------

| **latu-runtime-manager status** [**--root** *HOST_ROOT*]
| **latu-runtime-manager current** [**--abi** *ABI*]
[**--program** *PROGRAM*]
| **latu-runtime-manager list** [**--program** *PROGRAM*]
| **latu-runtime-manager inspect-root** [**--abi** *ABI*] [**--**] *ROOT*
| **latu-runtime-manager doctor** [**--abi** *ABI*]
[**--program** *PROGRAM*]

Description
-----------

``latu-runtime-manager`` reports whether the LATX translators and their
selected x86 guest runtimes are usable. It is a read-only diagnostic tool: it
does not download a runtime, change LATX configuration, register ``binfmt``,
or start a guest program.

The supported guest ABI names are ``x86_64`` and ``i386``. The default
commands report both ABIs, so users do not need to choose one for routine
diagnosis. ``--abi`` is an optional filter for scripts and targeted
troubleshooting. The manager still tracks the ABIs independently because one
translator may be absent and existing LATX configurations may select different
runtime roots. A single root containing both loader trees remains the simplest
layout when both translators are used.

Except for ``status``, command output is newline-delimited JSON with
``schema_version`` set to 1. Paths are JSON strings, so spaces, control
characters, and non-ASCII characters cannot change the record boundaries.

Commands
--------

``status``
Report whether ``latx-x86_64`` and ``latx-i386`` are present beside the
manager. The output is the stable two-line interface introduced with the
manager::

translator_x86_64=present
translator_i386=present

``--root`` inspects ``HOST_ROOT/usr/bin`` without executing a translator.
This is an offline host installation check; it does not inspect a guest
runtime root.

``current``
Ask the translators for their effective ``LAT_LD_PREFIX`` and the source
that selected it. By default both ABIs are reported; ``--abi`` limits the
query to one. Without ``--program``, only global configuration is applied.
With ``--program``, each translator also applies a matching per-program
configuration section. This command treats *PROGRAM* as a configuration
key and does not open or execute it. The manager consumes the translator's
versioned ``--runtime-info`` contract instead of reimplementing LATX
configuration precedence.

``list``
Query both translators and print one query result per ABI. This reports the
runtime roots currently selected by the installed translators; it does not
scan the filesystem or claim to enumerate every rootfs stored on the
machine. A later runtime store can add discoverable installed runtimes
without changing the meaning of these query results.

``inspect-root``
Inspect an explicit guest runtime root. Without ``--abi``, both ABI loader
paths are checked. The canonical loader paths are
``/lib64/ld-linux-x86-64.so.2`` for ``x86_64`` and
``/lib/ld-linux.so.2`` for ``i386``.

A ready loader must resolve inside the runtime root, be a regular readable
ELF file with the expected class and machine, and contain a loadable
segment. A symlink that resolves outside the runtime root is reported as
``unknown`` instead of being followed as a host file. Use ``--`` before a
root whose name begins with ``-``.

This self-contained-runtime check is intentionally stricter than LAT's host
path fallback: a loader found outside the selected root is never accepted as
proof that the root itself is ready.

``doctor``
Perform the complete read-only chain: find the translator, query its
effective runtime selection, and inspect the loader LAT would select.
Without ``--abi`` or ``--program``, both ABIs are checked independently.

With ``--program``, the manager opens the ELF file without executing it,
reads its ABI and ``PT_INTERP``, and checks only the matching translator. If
``--abi`` is also present, it must match the file. A static ELF needs no
interpreter and is reported ready once its translator query succeeds. If
the file cannot be inspected, the manager returns an ``unknown`` record with
``guest_abi`` set to null and a stable ``program_reason`` before exiting.

For a dynamic ELF, ``runtime_root_status`` describes the configured copy of
its actual ``PT_INTERP`` path. ``effective_loader_status`` and ``readiness``
describe the loader LAT would use: the configured-root copy when it exists,
otherwise LAT's absolute host-path fallback. An existing but invalid
configured loader blocks that fallback. The ``readiness`` field is one of:

``ready``
The translator selected a runtime with a valid loader.

``ready_with_host_fallback``
The configured root lacks the requested loader, but LAT's host-path
fallback resolves to a valid loader. This is executable according to the
current lookup rules, but is not a self-contained runtime root.

``unavailable``
This ABI's translator is not installed. When the other ABI is ready this
does not make the overall diagnosis fail.

``broken``
The selection was obtained, but the root or loader is missing or invalid.

``unknown``
The manager could not safely complete the query, for example because the
translator returned an unsupported runtime-information contract or a
loader escaped the root.

Exit status
-----------

``status`` keeps its compatibility behavior and returns zero after a
successful inspection even when a translator is absent. The JSON query
commands use the following statuses:

``0``
The requested query completed and is healthy. For default ``current`` and
``list`` queries, at least one ABI is selected and any other ABI is merely
unavailable. For the default dual-ABI ``doctor``, at least one ABI is ready
and any other ABI is merely unavailable. ``inspect-root`` remains a check
of every ABI requested, so use ``--abi`` for an intentionally single-ABI
root.

``1``
The result is known but unavailable, missing, or invalid.

``2``
The command line is invalid or the result cannot be determined safely.
2 changes: 1 addition & 1 deletion latxbuild/build-release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ package() {
mkdir -p $pkgdir/$pkgname-$pkgver/usr/{bin,lib/binfmt.d,lib/sysctl.d}
install -Dm755 -s $srcdir/build32/latx-i386 $pkgdir/$pkgname-$pkgver/usr/bin/latx-i386
install -Dm755 -s $srcdir/build64/latx-x86_64 $pkgdir/$pkgname-$pkgver/usr/bin/latx-x86_64
install -Dm755 $srcdir/runtime/latu-runtime-manager \
install -Dm755 -s $srcdir/build64/runtime/latu-runtime-manager \
$pkgdir/$pkgname-$pkgver/usr/bin/latu-runtime-manager
cat >$pkgdir/$pkgname-$pkgver/usr/lib/binfmt.d/latx-i386.conf <<EOF
:latx-i386:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00:\xff\xff\xff\xff\xff\xfe\xfe\x00\x00\x00\xf4\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/latx-i386:
Expand Down
32 changes: 32 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,38 @@ endif
subdir('scripts')
subdir('docs')
subdir('runtime')

if get_option('tests').enabled() and host_machine.system() == 'linux'
if 'latx-x86_64' in emulators and 'latx-i386' in emulators
test(
'test-latu-runtime-manager-real',
find_program('tests/runtime/test-latu-runtime-manager-real.sh'),
args: [python.full_path(), latu_runtime_manager.full_path(),
emulators['latx-x86_64'].full_path(),
emulators['latx-i386'].full_path()],
depends: [latu_runtime_manager, emulators['latx-x86_64'],
emulators['latx-i386']],
protocol: 'exitcode',
suite: 'lat-pr-fast',
timeout: 300,
)
endif

latu_install_depends = [latu_runtime_manager]
foreach name, emulator : emulators
latu_install_depends += emulator
endforeach

test(
'test-latu-install',
find_program('tests/runtime/test-latu-install.sh'),
args: [config_host['NINJA'], project_build_root, get_option('prefix')],
depends: latu_install_depends,
protocol: 'exitcode',
suite: 'lat-pr-fast',
)
endif

subdir('tests')

#########################
Expand Down
Loading