# Strix Halo memory allocation: why ROCm sees a fraction of your 128 GB, and what to set instead

> The classic first failure on a Ryzen AI Max+ 395 box: the model does not fit, or the runtime reports a few gigabytes of VRAM on a 128 GB machine. The BIOS split is usually the wrong lever. Here is what our serving node actually reports, and the setting that matters.

- Published: 2026-08-21
- Evidence level: lab_single_run
- Funding: Self-funded internal research
- Canonical: https://agmind.ai/reports/strix-halo-memory-allocation/

The short version: on Linux you generally do not want to carve a large VRAM
slice in the BIOS. Our serving node leaves the dedicated slice tiny and lets
the GPU reach almost all of system memory through GTT — the kernel's
graphics translation table — and the ceiling that decides how much it can
reach is a TTM kernel parameter, not a firmware menu. Below is what that
machine reports right now, with two large models resident.

## The symptom

You buy a 128 GB Ryzen AI Max+ 395 box specifically to run big models, and
then the runtime announces a few gigabytes of usable device memory. Or a
model that should fit refuses to load. Or ROCm and Vulkan disagree with each
other about how much memory exists. The instinct is to reboot into the BIOS
and hand the GPU a bigger slice, which is where a lot of time gets lost:
the dedicated slice is not where a Linux box with unified memory keeps its
models.

## What our node reports

This is a Beelink GTR9 Pro serving llama.cpp, on a 7.0 kernel, read
straight from sysfs while two models are loaded:

```
mem_info_vram_total:    512 MiB      # the BIOS-dedicated slice
mem_info_gtt_total:  120266 MiB      # what the GPU can actually reach
mem_info_gtt_used:   108704 MiB      # two resident models, right now
```

Half a gigabyte of "VRAM" on a machine happily holding a hundred gigabytes
of weights. The dedicated slice is close to the minimum the firmware
offers, and it does not matter, because everything of consequence goes
through GTT.

## The setting that actually decides the ceiling

GTT lets the GPU map system memory, and how much it may map is bounded by
TTM, the kernel's memory manager for graphics devices. Its page limit is
what to check first:

```
# pages, at 4 KiB each
cat /sys/module/ttm/parameters/pages_limit
```

On our node the kernel command line carries `ttm.pages_limit=30788203`,
which is where the ~117 GiB ceiling above comes from. On many distributions
the default is a fraction of system memory, and that default — not the BIOS
— is what stops a large model from loading. Raise it, reboot, and re-read
both sysfs files before believing anything else.

Two things worth knowing while you are in there. First, verify from the
device, not from the tool: `mem_info_gtt_total` and `mem_info_gtt_used`
under `/sys/class/drm/card*/device/` are the ground truth, and runtimes
frequently report their own idea of "VRAM" that means something else
entirely. Second, leave headroom: on our node, with models resident, the
host had a few gigabytes of ordinary RAM left — GTT allocations come out of
the same physical memory your operating system is using, and a box that
swaps while serving is a box with a latency problem you will misdiagnose as
a model problem.

## Why the BIOS slice is the wrong lever

The dedicated slice is carved out of the same physical memory and then
becomes unavailable to everything else, including the GTT path the runtime
prefers. Handing the GPU a large fixed slice does not add capacity — it
converts flexible memory into inflexible memory. Windows behaves differently
here, and much of the advice circulating for this hardware silently assumes
Windows or an older kernel; check which platform an instruction was written
for before rebooting into the firmware menu.

None of this is a claim that a large slice never helps any workload. It is
an account of what one serving node, tuned for exactly one job, reports
while doing that job.

## What to check, in order

1. `cat /sys/module/ttm/parameters/pages_limit` — the real ceiling.
2. `/sys/class/drm/card*/device/mem_info_gtt_total` — what the GPU can
   reach.
3. `mem_info_gtt_used` while your model is loaded — whether it went where
   you think it went.
4. Free system memory under load — headroom, not just capacity.
5. Only then, the BIOS.

## Scope

One node, one kernel series, one distribution, tuned for llama.cpp serving.
Kernel and driver behavior on this hardware has been moving quickly; treat
the numbers above as what this machine reports today, not as a specification.
What the box does once the memory is sorted out is measured in
[the 128 GB report](https://agmind.ai/reports/what-128gb-unified-memory-runs/), and the
protocol for measuring your own is
[here](https://agmind.ai/reports/how-to-benchmark-local-llm/).

---

Machine-readable claim registry: https://agmind.ai/claims.json · llms.txt: https://agmind.ai/llms.txt
