Skip to content
Merged
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
20 changes: 15 additions & 5 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ jobs:
sudo apt-get update -q
sudo apt-get install -qy --no-install-recommends gcc-14 flex bison bc libelf-dev libssl-dev \
cpio "$QEMU" busybox-static libcap-dev libnuma-dev rsync libaio-dev libacl1-dev \
libkeyutils-dev
libkeyutils-dev dwarves
env:
QEMU: ${{ inputs.row == 'A64' && 'qemu-system-arm' || 'qemu-system-x86' }}
- name: let the runner user open /dev/kvm
Expand Down Expand Up @@ -212,6 +212,16 @@ jobs:
> "$RUNNER_TEMP/checks/frames.md"; then verdict=clean; else verdict=findings; fi
echo "$verdict" > "$RUNNER_TEMP/checks/frames.status"
cat "$RUNNER_TEMP/checks/frames.md"
- name: rk btf
if: always() && steps.test.outcome != 'skipped'
run: |
mkdir -p "$RUNNER_TEMP/checks"
rc=0
target/release/rk btf --reference "$RUNNER_TEMP/gcc" --other "$RUNNER_TEMP/rucc" \
> "$RUNNER_TEMP/checks/btf.md" || rc=$?
case $rc in 0) verdict=clean ;; 1) verdict=findings ;; *) verdict="not run" ;; esac
echo "$verdict" > "$RUNNER_TEMP/checks/btf.status"
cat "$RUNNER_TEMP/checks/btf.md"
- name: rk mixed on the first failed unit
if: failure() && steps.test.outcome == 'failure'
timeout-minutes: 180
Expand Down Expand Up @@ -265,23 +275,23 @@ jobs:
run: |
import json, os, pathlib
row = os.environ["ROW"]
lines = [f"### nightly, {row}", "", "| version | graded | failed | splats | verdict | objtool | frames |", "|---|---|---|---|---|---|---|"]
lines = [f"### nightly, {row}", "", "| version | graded | failed | splats | verdict | objtool | frames | btf |", "|---|---|---|---|---|---|---|---|"]
for record in sorted(pathlib.Path("records").iterdir()):
version = record.name.removeprefix("nightly-").removesuffix(f"-{row}")
path = record / "test" / "test.json"
checks = []
for name in ("objtool", "frames"):
for name in ("objtool", "frames", "btf"):
status = record / "checks" / f"{name}.status"
checks.append(status.read_text().strip() if status.exists() else "not run")
if not path.exists():
lines.append(f"| {version} | | | | not run | {checks[0]} | {checks[1]} |")
lines.append(f"| {version} | | | | not run | {checks[0]} | {checks[1]} | {checks[2]} |")
continue
t = json.loads(path.read_text())
graded = [u for u in t["units"] if u["graded"]]
failed = [u["name"] for u in graded if not u["passed"]]
splats = len(t["splats"].get("other-only", []))
verdict = "green" if not failed and not splats else "red"
lines.append(f"| {version} | {len(graded)} | {len(failed)} | {splats} | {verdict} | {checks[0]} | {checks[1]} |")
lines.append(f"| {version} | {len(graded)} | {len(failed)} | {splats} | {verdict} | {checks[0]} | {checks[1]} | {checks[2]} |")
for record in sorted(pathlib.Path("records").iterdir()):
summary = record / "mixed" / "summary.md"
if summary.exists():
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ The reference compilers live in era containers built from `provision/eras` and p

`rk config-diff`, `rk probes`, `rk flags-diff`, `rk demands` and `rk asm-inventory` read build directories and write markdown tables: the `.config` differences, the compiler probes the two compilers answered differently, the flags each unit was compiled with on one side only (read from the `.cmd` files kbuild writes), the failed units by error, and the instructions the kernel writes itself. `rk config-diff --why` also names the Kconfig expressions behind each difference and the probe that decided them, and needs the kernel tree, which it finds through `build.json` or `--source`. `rk syntax --build DIR --cc rucc` replays every unit of a reference build through rucc's front end with the reference's own command lines, `-fsyntax-only` for C and `-E` for assembly, and writes the failing units grouped by their first error. Units listed with an issue in `syntax-known.toml` are known failures, so the command fails only on new ones.

`rk sections-diff`, `rk symvers-diff`, `rk vec-audit`, `rk modules-audit` and `rk objtool-report` look at what the compilers produced. `rk sections-diff` compares the section names of every object two builds share, the size and relocation count of each kernel table (exports, jump labels, alternatives, exception fixups, initcalls and the rest), the call-site lists per function, and the `.modinfo` and `__ksymtab_strings` strings. A difference that `sections-divergences.toml` explains, such as a constant pool only gcc builds or a WARN check only one compiler could prove dead, is listed apart with its reason and does not fail the run. It lists the first 60 differences of each kind, and every one with `--all`. `rk symvers-diff` compares `Module.symvers`, CRCs and namespaces included, and the global symbols of `System.map`. `rk vec-audit` decodes the x86-64 code of every unit built with `-mno-sse` or `-mgeneral-regs-only` and lists the vector and x87 instructions it finds, only those above the reference's count when given `--reference`. `rk modules-audit` fails on any module relocation the loader rejects, a wrong `vermagic` or an imported CRC that does not match `Module.symvers`. `rk objtool-report` buckets the objtool warnings of two build logs by message and function shape. `rk frames` compares the stack frame of every function in two builds made with `rk build --stack-usage`, which passes `KCFLAGS=-fstack-usage` so that each compiler writes a `.su` file next to every object. It fails on a function over `CONFIG_FRAME_WARN` that the reference keeps under it, and on a run time stack high water mark more than 10% above the reference's when both build directories have a `boot.log` from a kernel with `CONFIG_DEBUG_STACK_USAGE`. `rk sections-diff`, `rk vec-audit` and `rk frames` take `--save FILE` to keep what they read as JSON, and accept such a file in place of a build directory, which is how CI compares builds without moving their objects.
`rk sections-diff`, `rk symvers-diff`, `rk vec-audit`, `rk modules-audit` and `rk objtool-report` look at what the compilers produced. `rk sections-diff` compares the section names of every object two builds share, the size and relocation count of each kernel table (exports, jump labels, alternatives, exception fixups, initcalls and the rest), the call-site lists per function, and the `.modinfo` and `__ksymtab_strings` strings. A difference that `sections-divergences.toml` explains, such as a constant pool only gcc builds or a WARN check only one compiler could prove dead, is listed apart with its reason and does not fail the run. It lists the first 60 differences of each kind, and every one with `--all`. `rk symvers-diff` compares `Module.symvers`, CRCs and namespaces included, and the global symbols of `System.map`. `rk vec-audit` decodes the x86-64 code of every unit built with `-mno-sse` or `-mgeneral-regs-only` and lists the vector and x87 instructions it finds, only those above the reference's count when given `--reference`. `rk modules-audit` fails on any module relocation the loader rejects, a wrong `vermagic` or an imported CRC that does not match `Module.symvers`. `rk objtool-report` buckets the objtool warnings of two build logs by message and function shape. `rk frames` compares the stack frame of every function in two builds made with `rk build --stack-usage`, which passes `KCFLAGS=-fstack-usage` so that each compiler writes a `.su` file next to every object. It fails on a function over `CONFIG_FRAME_WARN` that the reference keeps under it, and on a run time stack high water mark more than 10% above the reference's when both build directories have a `boot.log` from a kernel with `CONFIG_DEBUG_STACK_USAGE`. `rk btf` reads the `.BTF` section pahole put in each build's vmlinux and writes every named type and function prototype out by name, so that type IDs do not matter. It fails on a type the two builds describe differently or only one has, and on a function both have with different prototypes, and it lists functions only one build has without failing, since the compilers inline differently. `rk sections-diff`, `rk vec-audit`, `rk frames` and `rk btf` take `--save FILE` to keep what they read as JSON, and accept such a file in place of a build directory, which is how CI compares builds without moving their objects.

The nightly workflow builds every pin in the current set on X64 with gcc-14 and with rucc, from `tinyconfig` and the test fragment, and runs `rk test` on boot, smoke and KUnit. When the rucc kernel fails a unit, `rk mixed` runs on the first one in the same job. The run's summary has a line per version, green or red, whether `rk objtool-report` and `rk frames` came out clean, and what `rk mixed` found. A manual run takes a branch or commit of tamnd/rucc, another configuration target, the versions, the row and the QEMU CPU, so `row=A64 cpu=cortex-a57 config=debian-13-arm64` runs every test kind on arm64 under TCG on the arm runner.
The nightly workflow builds every pin in the current set on X64 with gcc-14 and with rucc, from `tinyconfig` and the test fragment, and runs `rk test` on boot, smoke and KUnit. When the rucc kernel fails a unit, `rk mixed` runs on the first one in the same job. The run's summary has a line per version, green or red, whether `rk objtool-report`, `rk frames` and `rk btf` came out clean (`rk btf` is not run when the configuration has no BTF, as `tinyconfig` does not), and what `rk mixed` found. A manual run takes a branch or commit of tamnd/rucc, another configuration target, the versions, the row and the QEMU CPU, so `row=A64 cpu=cortex-a57 config=debian-13-arm64` runs every test kind on arm64 under TCG on the arm runner.

The mixed workflow is run by hand. It builds the rucc kernel with `-fenable-inject-fault=time64_to_tm`, checks that the KUnit case for that function fails, and passes only when `rk mixed` traces the failure back to the `inject-fault` pass in that function.

Expand Down
Loading