Skip to content

Fix Windows binary crashing (STATUS_ILLEGAL_INSTRUCTION) on CPUs without AVX-512 - #829

Merged
michaelneale merged 2 commits into
mainfrom
fix/windows-ggml-native-avx512-crash
Jun 12, 2026
Merged

Fix Windows binary crashing (STATUS_ILLEGAL_INSTRUCTION) on CPUs without AVX-512#829
michaelneale merged 2 commits into
mainfrom
fix/windows-ggml-native-avx512-crash

Conversation

@michaelneale

@michaelneale michaelneale commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

What this fixes

Windows users on CPUs without AVX-512 — which includes all Intel consumer
desktops from 11th–14th gen (Alder/Raptor Lake), e.g. the i5/i7-12xxx/13xxx

got an immediate hard crash (STATUS_ILLEGAL_INSTRUCTION, 0xC000001D) the
moment inference actually ran. The binary would load a model, then die at
compute-graph / KV-cache allocation. After this change the Windows release
binaries run on those machines.

Root cause

scripts/build-windows.ps1 did not set GGML_NATIVE, while the Linux/macOS
path in scripts/build-llama.sh does set GGML_NATIVE=OFF. With GGML_NATIVE
unset and the build not cross-compiling, llama.cpp defaults GGML_NATIVE=ON,
so ggml-cpu was compiled for the build runner's CPU. The windows-2025
runners expose AVX-512, so the shipped binary contained AVX-512 instructions
with no runtime CPU-feature guard. Disassembly of the released
mesh-llm.exe showed 8,257 AVX-512 (zmm) instructions baked into the
compute path.

The fix

  • scripts/build-windows.ps1: pin GGML_NATIVE=OFF (matching Linux/macOS) and
    select a portable AVX2 baseline (GGML_AVX2=ON, GGML_AVX512=OFF,
    GGML_BMI2=OFF). AVX2/FMA/F16C are supported by every x86-64 CPU since ~2013.
  • scripts/package-release.ps1: compute release-archive SHA-256 checksums via
    the .NET SHA256 API instead of Get-FileHash. Under powershell -NoProfile
    on the runners, Get-FileHash failed to autoload (CommandNotFoundException),
    which broke release bundling and prevented .sha256 sidecars from being
    generated. (This is the same sidecar the installer fix in Fix Windows install on PowerShell 5.1 (irm | iex and missing checksum sidecar) #828 consumes.)

Validation

Built a canary CUDA bundle for sm_89 from this branch and ran it on a real
RTX 4060 + Intel i5-12400F (no AVX-512):

  • Original release binary: crashes 0xC000001D right after
    load_tensors: CPU_Mapped model buffer size.
  • This branch's binary: compiles ggml-cpu with /arch:AVX2
    (GGML_AVX2;GGML_FMA;GGML_F16C, no AVX-512), loads the model onto the GPU,
    reaches mesh-llm runtime ready, and returns a real chat completion
    ("Hello! How can I help you today?") with the process still alive after.
  • Checksum fix verified: release bundle builds and emits valid .sha256
    sidecars (digest matches the archive).

Notes

  • AVX-512 is intentionally fused off on consumer Alder/Raptor Lake, so this hit
    a large share of Windows desktops, not an edge case.
  • Follow-up worth filing separately: a CPU-only node reports
    local_capacity_gb=0.0 (VRAM-based) and refuses to run even a 0.5 GB model
    locally, forcing a split. CPU nodes should size local capacity from system RAM.

Summary by CodeRabbit

  • Bug Fixes

    • Enhanced Windows binary build compatibility by adjusting processor optimization settings to prevent illegal instruction exceptions on certain consumer CPU models while maintaining robust performance baselines for modern AVX2-compatible systems.
  • Chores

    • Streamlined release package creation process with updated checksum generation methodology for enhanced accuracy and distribution consistency.

The Windows native build configured llama.cpp/ggml without GGML_NATIVE=OFF,
unlike the Linux and macOS builds in scripts/build-llama.sh. On the
windows-2025 release runner GGML_NATIVE then defaults ON, so ggml is compiled
for the runner's CPU. Those runners can expose AVX-512, so the shipped binary
contains AVX-512 instructions. On consumer desktops without AVX-512 (e.g. Intel
Alder/Raptor Lake i5/i7) the process crashes with STATUS_ILLEGAL_INSTRUCTION
(0xC000001D) the moment a ggml compute kernel runs during inference.

Pin GGML_NATIVE=OFF and select a portable AVX2 baseline (AVX2 implies F16C and
FMA on MSVC), with AVX-512 and BMI2 explicitly off, so the emitted instruction
set is independent of the build host and runs on every x86-64 CPU since ~2013.

Confirmed against the current shipped release mesh-llm.exe: disassembly shows
8257 zmm-register and 820 opmask-register AVX-512 instructions baked into the
binary with no runtime guard, which is exactly what faults on a non-AVX-512
CPU. With GGML_AVX512=OFF and a fixed AVX2 baseline, ggml-cpu's CMake emits only
the AVX2/FMA/F16C codepaths, so no AVX-512 instructions are generated.
@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Pins GGML CPU feature flags for Windows builds to an AVX/AVX2 baseline (disables GGML_NATIVE, AVX-512, BMI2) and replaces PowerShell Get-FileHash usage with a new Get-Sha256Hex helper that computes SHA-256 via .NET for checksum sidecar files.

Changes

Windows Build Configuration

Layer / File(s) Summary
GGML CPU feature flag configuration
scripts/build-windows.ps1
CMake arguments disable GGML_NATIVE and pin the x86-64 baseline by enabling GGML_AVX and GGML_AVX2 while disabling GGML_AVX512 and GGML_BMI2. Comments explain avoiding illegal-instruction crashes on some consumer CPUs.

Packaging checksum

Layer / File(s) Summary
SHA-256 helper and sidecar update
scripts/package-release.ps1
Added Get-Sha256Hex(Path) which streams a file through .NET System.Security.Cryptography.SHA256 returning a lowercase hex string, and updated New-ChecksumSidecar(Path) to use it and emit .sha256 sidecars in "<hash> <filename>" format.

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title directly addresses the primary objective: fixing Windows binary crashes caused by AVX-512 instructions on incompatible CPUs. This matches the main change in scripts/build-windows.ps1.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/windows-ggml-native-avx512-crash

Comment @coderabbitai help to get the list of available commands and usage tips.

@michaelneale
michaelneale marked this pull request as draft June 11, 2026 11:24
@michaelneale

Copy link
Copy Markdown
Collaborator Author

this is still a WIP - I have a PC at home I will try this with

…Hash

The Windows release bundling step (package-release.ps1, invoked as
`powershell -NoProfile -File ...`) failed with CommandNotFoundException
for Get-FileHash on the windows-2025 runner, because module autoloading
of Microsoft.PowerShell.Utility does not reliably resolve under that
invocation. This aborted release-bundle-windows before the bundle and
its .sha256 sidecars were produced.

Compute the SHA-256 with the .NET System.Security.Cryptography API
directly, which is always available regardless of module autoloading.
Verified on Windows PowerShell 5.1 that the digest matches Get-FileHash.
@michaelneale
michaelneale force-pushed the fix/windows-ggml-native-avx512-crash branch from 088a043 to 5f478a2 Compare June 12, 2026 02:59
@michaelneale
michaelneale marked this pull request as ready for review June 12, 2026 03:03

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/package-release.ps1`:
- Around line 175-177: Set the checksum sidecar file to a deterministic ASCII
encoding to avoid BOM/leading bytes differences across PowerShell versions: when
writing the string composed of $hash and $name with Set-Content (the block using
Get-Sha256Hex, $hash, $Path, $name), add the explicit -Encoding ASCII (or
System.Text.Encoding::ASCII) parameter to Set-Content so the written file is
plain ASCII and Linux tools like awk '{print $1}' correctly extract the digest.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3ee6a479-27df-4a33-b45e-d4282cf8a398

📥 Commits

Reviewing files that changed from the base of the PR and between 4d9d2c8 and 5f478a2.

📒 Files selected for processing (1)
  • scripts/package-release.ps1

Comment on lines +175 to 177
$hash = Get-Sha256Hex $Path
$name = Split-Path -Leaf $Path
Set-Content -Path "$Path.sha256" -Value "$hash $name" -NoNewline

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Read-only verification: confirm sidecar writer has no explicit encoding
# and confirm downstream parser reads first whitespace token via awk.

set -euo pipefail

echo "== Sidecar write implementation =="
rg -n -C2 'Set-Content\s+-Path\s+"\$Path\.sha256"' scripts/package-release.ps1

echo
echo "== Downstream sidecar token parser =="
rg -n -C2 "awk '\\{print \\$1\\}'" scripts/verify-native-sdk-package.sh

echo
echo "== Linux sidecar formatting contract =="
rg -n -C3 "printf '%s  %s\\\\n'" scripts/package-release.sh

Repository: Mesh-LLM/mesh-llm

Length of output: 354


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Sidecar write implementation (package-release.ps1) =="
rg -n -C3 'function\s+New-ChecksumSidecar|Set-Content\s+-Path\s+"\$Path\.sha256"' scripts/package-release.ps1

echo
echo "== Downstream sidecar token parser (verify-native-sdk-package.sh) =="
rg -n -C3 'awk\s*\x27\{\s*print\s*\$1\s*\}\x27|awk\s*\x27\{print\s*\$1\s*\}\x27|awk\s*\x27\{print\s*\$1' scripts/verify-native-sdk-package.sh || true

echo
echo "== Downstream regex/consume sites (install.ps1) =="
rg -n -C3 '\.sha256|checksum|sha256' install.ps1

echo
echo "== Linux sidecar formatting contract (package-release.sh) =="
rg -n -C3 "printf\s+'%s\s+%s\\\\n'|printf\s+'%s  %s\\\\n'|\.sha256" scripts/package-release.sh

Repository: Mesh-LLM/mesh-llm

Length of output: 3053


🌐 Web query:

PowerShell Set-Content default encoding UTF-16LE BOM behavior -NoNewline

💡 Result:

The behavior of the Set-Content cmdlet, including the impact of the -NoNewline parameter and default encoding, depends significantly on whether you are using Windows PowerShell (v5.1 and earlier) or PowerShell (v6+). The -NoNewline parameter itself does not influence character encoding or the addition of a Byte Order Mark (BOM) [1][2]. It strictly instructs the cmdlet to omit the trailing newline (line break) that is otherwise appended to the output by default [1][2][3]. Regarding character encoding and BOM behavior: 1. PowerShell (v6 and higher): The default encoding for Set-Content is utf8NoBOM [1][2]. Because it defaults to a BOM-less encoding, it does not add a BOM unless you explicitly specify -Encoding utf8BOM [4][1][5]. 2. Windows PowerShell (v5.1 and earlier): Set-Content defaults to the system's active ANSI legacy code page (often referred to as Default) [4][6][7]. In this version, Windows PowerShell behaves differently with Unicode encodings: if you explicitly set -Encoding Unicode (which is UTF-16LE), it will include a BOM [4][8]. Notably, Windows PowerShell v5.1 does not provide a native -Encoding option to produce BOM-less UTF-8; specifying -Encoding UTF8 in these versions will always include a BOM [9][5]. In summary, the -NoNewline switch only affects the presence of the terminal line break [1]. The presence of a BOM is determined entirely by the -Encoding parameter and the version of PowerShell being used [4][10][11]. To ensure consistent behavior across all versions of PowerShell, it is recommended to specify the encoding explicitly—for example, using -Encoding utf8NoBOM in PowerShell 7+ [4][11].

Citations:


🌐 Web query:

GNU awk behavior when input file contains NUL bytes UTF-16LE

💡 Result:

GNU awk (gawk) does not support UTF-16LE input natively [1][2]. Because UTF-16LE encodes characters using two bytes (or more) and frequently includes NUL bytes (0x00) in the byte stream, it is incompatible with gawk's processing model [1][2]. Gawk operates on C-style strings internally, where the NUL byte is treated as a string terminator [3][4]. Consequently, when gawk encounters a NUL byte in the input, it effectively treats it as the end of the string or record, causing data corruption, truncated input, or failures in pattern matching and field splitting [3][4][1]. While you can force gawk to treat input as raw bytes using the --characters-as-bytes (-b) option or by setting the locale to "C", this does not resolve the encoding mismatch [5][6][7]. Even in "byte mode," gawk will see the UTF-16LE stream as a sequence of individual bytes, meaning standard field separators (like a comma or pipe) will not be recognized because they are encoded as two bytes (e.g., 0x2C 0x00) rather than a single byte [1][2]. The standard and most reliable way to process UTF-16LE files with gawk is to convert the input to a format gawk understands (such as UTF-8) before processing [1][2]. This is typically done using the iconv utility: iconv -f UTF-16LE -t UTF-8 input.file | gawk -F'|' '{... }' If you need to output the data back into UTF-16LE, you can pipe the result of your awk command back through iconv:... | iconv -f UTF-8 -t UTF-16LE > output.file [2]

Citations:


Specify checksum sidecar encoding for deterministic Linux verification (awk '{print $1}')

Set-Content in scripts/package-release.ps1 has no explicit -Encoding, so the output encoding/leading bytes vary by PowerShell version. The Linux verifier extracts the expected digest using the first whitespace-delimited token (awk '{print $1}'), so the sidecar should be written as plain ASCII (no BOM/extra leading bytes).

Suggested fix
 function New-ChecksumSidecar {
     param([string]$Path)

     $hash = Get-Sha256Hex $Path
     $name = Split-Path -Leaf $Path
-    Set-Content -Path "$Path.sha256" -Value "$hash  $name" -NoNewline
+    Set-Content -Path "$Path.sha256" -Value "$hash  $name" -NoNewline -Encoding Ascii
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/package-release.ps1` around lines 175 - 177, Set the checksum sidecar
file to a deterministic ASCII encoding to avoid BOM/leading bytes differences
across PowerShell versions: when writing the string composed of $hash and $name
with Set-Content (the block using Get-Sha256Hex, $hash, $Path, $name), add the
explicit -Encoding ASCII (or System.Text.Encoding::ASCII) parameter to
Set-Content so the written file is plain ASCII and Linux tools like awk '{print
$1}' correctly extract the digest.

@ndizazzo ndizazzo left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks clear! nothing out of whack to my eye

@michaelneale
michaelneale merged commit 9af668d into main Jun 12, 2026
115 of 136 checks passed
@michaelneale
michaelneale deleted the fix/windows-ggml-native-avx512-crash branch June 12, 2026 06:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants