From 551fd6827dc385f0fec721f50a0a924b46b5f07f Mon Sep 17 00:00:00 2001 From: kolja Date: Wed, 9 Sep 2026 13:47:38 +0200 Subject: [PATCH 1/2] fix(vmm): map full reservation in one segment on Windows hipMemCreate/hipMemMap on Windows/ROCm 7.2 (gfx1100) maps a second, later segment onto the SAME physical pages as the first: the repo's vmm_arena_smoke example panics at its boundary-growth assert after the 2nd map_next (segment 1 aliases segment 2's pages), while single-segment maps are correct. The KV cache grows in ~1900 small map_next steps, so every growth corrupts all prior KV on Windows -> token soup from every model (qwen3.8:27b, qwen3.5:0.8b). Map the full reservation in one map_next on Windows (cfg(windows) override of initial_mapped_bytes). Costs full VRAM up front instead of on-demand commit, but is correct; Linux behavior unchanged. Signed-off-by: kolja --- crates/rdna-compute/src/dispatch.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/crates/rdna-compute/src/dispatch.rs b/crates/rdna-compute/src/dispatch.rs index c91132d8b..ec1509c3a 100644 --- a/crates/rdna-compute/src/dispatch.rs +++ b/crates/rdna-compute/src/dispatch.rs @@ -3065,6 +3065,17 @@ impl Gpu { .checked_mul(dtype.size()) .ok_or_else(|| HipError::new(0, "VMM tensor byte size overflowed"))?; let mut arena = VmmArena::reserve(&self.hip, self.device_id, byte_size)?; + // WINDOWS FIX (2026-09-09): hipMemCreate/hipMemMap on Windows/ROCm 7.2 + // (gfx1100) maps a second, later segment onto the SAME physical pages as + // the first (vmm_arena_smoke boundary-growth assert fails; every + // subsequent KV growth corrupts all prior KV -> token soup). Single + // segment maps are proven correct. So on Windows, map the FULL + // reservation in one map_next up front instead of growing in small + // segments; grow_vmm_tensor then becomes a no-op (already fully + // mapped). Costs up-front VRAM for the whole reservation; correctness + // over on-demand commit on the platform whose driver breaks growth. + #[cfg(windows)] + let initial_mapped_bytes = byte_size; if initial_mapped_bytes > 0 { if let Err(err) = arena.map_next(&self.hip, initial_mapped_bytes, access_devices) { return Err(self.retain_failed_vmm_arena(arena, err)); From 5141b19e4e4ae294e1308ac435b64732f7a8c5be Mon Sep 17 00:00:00 2001 From: kolja Date: Wed, 9 Sep 2026 15:03:29 +0200 Subject: [PATCH 2/2] fix(vmm): round initial map size up to allocation granularity beta's map_next validates that the map size is a non-zero multiple of the allocation granularity (64 KiB), while master rounded silently. Map the full reservation rounded up to the granularity, keeping the single-segment Windows path correct on both branches. Signed-off-by: kolja --- crates/rdna-compute/src/dispatch.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/crates/rdna-compute/src/dispatch.rs b/crates/rdna-compute/src/dispatch.rs index ec1509c3a..e329190cc 100644 --- a/crates/rdna-compute/src/dispatch.rs +++ b/crates/rdna-compute/src/dispatch.rs @@ -3075,7 +3075,14 @@ impl Gpu { // mapped). Costs up-front VRAM for the whole reservation; correctness // over on-demand commit on the platform whose driver breaks growth. #[cfg(windows)] - let initial_mapped_bytes = byte_size; + let initial_mapped_bytes = { + // map_next requires a multiple of the allocation granularity + let granularity = arena.granularity(); + byte_size + .checked_add(granularity - 1) + .map(|v| v / granularity * granularity) + .unwrap_or(byte_size) + }; if initial_mapped_bytes > 0 { if let Err(err) = arena.map_next(&self.hip, initial_mapped_bytes, access_devices) { return Err(self.retain_failed_vmm_arena(arena, err));