[PATCH AUTOSEL 6.18-5.10] arm64: fixmap: Allow 256K early_ioremap() at any offset

Sasha Levin sashal at kernel.org
Mon Aug 31 06:20:37 PDT 2026


From: Yu Peng <pengyu at kylinos.cn>

[ Upstream commit 21fc7ec93f8b633b60d5bddef2f1529ff6b36185 ]

NR_FIX_BTMAPS is the per-slot page limit for early_ioremap(). Since
__early_ioremap() maps the page-aligned physical range, a 256K request
can require one extra page when the physical address is not page-aligned.

Reserve one extra page per slot so the 256K mapping budget is usable
regardless of the initial page offset.

Link: https://lore.kernel.org/r/08fd96fa-ee3a-4904-bd11-bb08bd90436f@kylinos.cn
Signed-off-by: Yu Peng <pengyu at kylinos.cn>
Signed-off-by: Will Deacon <will at kernel.org>
Signed-off-by: Sasha Levin <sashal at kernel.org>
---

LLM Generated explanations, may be completely bogus:

# Stable Backport Analysis: `arm64: fixmap: Allow 256K early_ioremap()
at any offset`

**Local tree:** `v6.18.44-2-g1b9e1abadee04` (detached from
`stable/linux-6.18.y`, kernel version **6.18.44**)

---

## PHASE 1: COMMIT MESSAGE FORENSICS

### Step 1.1: PARSE THE SUBJECT LINE
**Record:** `[arm64: fixmap]` `[Allow]` — fix boot-time fixmap slot
sizing so a full 256K `early_ioremap()` works at any physical page
offset.

### Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
**Record:**
- **Link:** `https://lore.kernel.org/r/08fd96fa-
  ee3a-4904-bd11-bb08bd90436f at kylinos.cn`
- **Signed-off-by:** Yu Peng `<pengyu at kylinos.cn>` (author)
- **Signed-off-by:** Will Deacon `<will at kernel.org>` (arm64 maintainer,
  committer on mainline)
- **No** Fixes:, Reported-by:, Tested-by:, Reviewed-by:, Acked-by:, Cc:
  stable@
- Notable: maintainer commit/sign-off on mainline (`21fc7ec93f8b6`); no
  syzbot or user bug report

### Step 1.3: ANALYZE THE COMMIT BODY TEXT
**Record:**
- **Bug:** `NR_FIX_BTMAPS` is the per-slot page budget for
  `early_ioremap()`. `__early_ioremap()` page-aligns the physical range,
  so a 256K request at a non-page-aligned address can require **one
  extra page** (65 pages on 4K kernels).
- **Symptom:** `WARN_ON(nrpages > NR_FIX_BTMAPS)` in `__early_ioremap()`
  → returns `NULL` → early-boot mapping failure.
- **Root cause:** `NR_FIX_BTMAPS` was defined as exactly `SZ_256K /
  PAGE_SIZE` (64 on 4K pages), without room for alignment slop.
- **No** explicit kernel version range in the message.

### Step 1.4: DETECT HIDDEN BUG FIXES
**Record:** Not disguised — this is an explicit correctness fix for
fixmap slot sizing, not style cleanup.

---

## PHASE 2: DIFF ANALYSIS

### Step 2.1: INVENTORY THE CHANGES
**Record:**
- **Files:** `arch/arm64/include/asm/fixmap.h` (+5 / -1 lines, ~6 lines
  changed)
- **Scope:** Single-header, surgical change
- **Modified:** `NR_FIX_BTMAPS` macro and comment block in `enum
  fixed_addresses`

### Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
**Record:**
- **Before:** `NR_FIX_BTMAPS = SZ_256K / PAGE_SIZE` (64 pages @ 4K)
- **After:** `NR_FIX_BTMAPS = (SZ_256K / PAGE_SIZE) + 1` (65 pages @ 4K)
- **Affected path:** `__early_ioremap()` in `mm/early_ioremap.c` — early
  boot only (`WARN_ON(system_state >= SYSTEM_RUNNING)`)

Relevant existing logic:

```131:140:mm/early_ioremap.c
        offset = offset_in_page(phys_addr);
        phys_addr &= PAGE_MASK;
        size = PAGE_ALIGN(last_addr + 1) - phys_addr;
        // ...
        nrpages = size >> PAGE_SHIFT;
        if (WARN_ON(nrpages > NR_FIX_BTMAPS))
                return NULL;
```

### Step 2.3: IDENTIFY THE BUG MECHANISM
**Record:** **Logic/correctness — off-by-one in fixmap page budget.**
Category: boot-time mapping failure / NULL return from
`early_ioremap()`.

Verified math: for `size = SZ_256K` and any `offset_in_page(phys) != 0`,
`nrpages = 65` while `NR_FIX_BTMAPS = 64` → failure.

### Step 2.4: ASSESS THE FIX QUALITY
**Record:**
- **Obviously correct:** Yes — standard fix for page-aligned mapping of
  unaligned ranges.
- **Minimal:** Yes — one macro change + comment.
- **Regression risk:** Very low — adds 7 extra fixmap pages total (7
  slots × 1 page). Cherry-pick auto-merges cleanly on this tree.
- **Side effect:** `MAX_MAP_CHUNK` / `MAP_CHUNK_SIZE` grow by one page,
  correctly reflecting usable mapping budget.

---

## PHASE 3: GIT HISTORY INVESTIGATION

### Step 3.1: BLAME THE CHANGED LINES
**Record:** Current `NR_FIX_BTMAPS` lines blame to `5d324e5159d9e`
(merge, Nov 2025) in this checkout. Value `SZ_256K / PAGE_SIZE` present
since at least **v5.10** through **v6.18.44** on arm64.

### Step 3.2: FOLLOW THE FIXES: TAG
**Record:** N/A — no `Fixes:` tag in commit message.

### Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
**Record:** Standalone 1-patch series (v1 only per `b4 dig -a`).
Mainline commit: `21fc7ec93f8b6`. Merged to master after `Linux 6.18.44`
(`1efe5d048a391`). No prerequisite commits.

### Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
**Record:** Yu Peng — not a regular arm64 maintainer; patch
reviewed/applied by Will Deacon (arm64 maintainer).

### Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
**Record:** None. Self-contained header change. Applies standalone.

---

## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH

### Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
**Record:**
- **URL:**
  https://patch.msgid.link/20260708023514.2445926-1-pengyu@kylinos.cn
- **Series:** v1 only (no v2/v3)
- **Will Deacon reply:** "Applied to arm64 (for-next/fixes), thanks!" —
  no NAKs, no stable nomination in thread

### Step 4.2: CHECK WHO REVIEWED THE PATCH
**Record:** CC'd: Catalin Marinas, Will Deacon, Thomas Huth, linux-arm-
kernel, linux-kernel. Applied directly by Will Deacon.

### Step 4.3: SEARCH FOR THE BUG REPORT
**Record:** No Reported-by, syzbot, or bugzilla link. Code-
analysis/maintainer-accepted fix.

### Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
**Record:** Single-patch series. RISC-V and powerpc use the same
`SZ_256K / PAGE_SIZE` pattern but are out of scope for this arm64-only
commit.

### Step 4.5: CHECK STABLE MAILING LIST HISTORY
**Record:** Not searched separately; no stable discussion found in patch
thread.

---

## PHASE 5: CODE SEMANTIC ANALYSIS

### Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
**Record:** Macro only — affects `__early_ioremap()`, `early_ioremap()`,
`early_memremap()`, `copy_from_early_mem()` (via `MAX_MAP_CHUNK`), ACPI
`MAP_CHUNK_SIZE`.

### Step 5.2: TRACE CALLERS
**Record:** On arm64, `__acpi_map_table()` → `early_memremap(phys,
size)` maps whole ACPI tables without chunking
(`arch/arm64/kernel/acpi.c`). Also EFI early paths, generic
`copy_from_early_mem()`. All early-boot, pre-`SYSTEM_RUNNING`.

Chunking helpers (`copy_from_early_mem`, `acpi_table_upgrade`) already
limit `clen + slop <= MAP_CHUNK_SIZE` with page-aligned `phys`, so they
stay within 64 pages today. **Direct** `early_memremap(phys, ~256K)` at
misaligned `phys` is the failure path.

### Step 5.3: TRACE CALLEES
**Record:** `__early_ioremap()` → `__early_set_fixmap()` /
`__late_set_fixmap()` per page.

### Step 5.4: FOLLOW THE CALL CHAIN
**Record:** Reachable during kernel boot on ACPI/EFI arm64 systems. Not
a post-boot userspace syscall path, but boot failure is severe.

### Step 5.5: SEARCH FOR SIMILAR PATTERNS
**Record:** Identical `SZ_256K / PAGE_SIZE` define in
`arch/riscv/include/asm/fixmap.h` and
`arch/powerpc/include/asm/fixmap.h` — same latent bug, different arch.

---

## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE

### Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
**Record:** **YES.** Current tree has:
```
#define NR_FIX_BTMAPS           (SZ_256K / PAGE_SIZE)
```
Bug present since at least v5.10 on arm64 (verified across tags
v5.10–v6.18.44). Fix **not** present on this 6.18.44 tree; **is** on
`master`.

### Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
**Record:** **Clean apply** — tested `git cherry-pick --no-commit
21fc7ec93f8b6`: auto-merged `arch/arm64/include/asm/fixmap.h` with no
conflicts.

### Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
**Record:** No equivalent fix in this tree. `master` has commit
`21fc7ec93f8b6`.

---

## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT

### Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
**Record:** **arm64 boot / fixmap / early_ioremap** — **CORE** for arm64
boot; affects all arm64 kernels using early MMIO/ACPI/EFI mappings.

### Step 7.2: ASSESS SUBSYSTEM ACTIVITY
**Record:** Active; fix landed in arm64-fixes for post-6.18 mainline.

---

## PHASE 8: IMPACT AND RISK ASSESSMENT

### Step 8.1: DETERMINE WHO IS AFFECTED
**Record:** **Platform-specific (arm64)** — all arm64 builds;
practically relevant for ACPI/EFI early-boot mapping when a ~256K region
is mapped at a non-page-aligned physical address.

### Step 8.2: DETERMINE THE TRIGGER CONDITIONS
**Record:**
- `early_ioremap()` / `early_memremap()` with `size` near `SZ_256K` and
  `phys % PAGE_SIZE != 0`
- Uncommon but deterministic; firmware-chosen ACPI table placement can
  satisfy this
- Not a post-boot unprivileged syscall trigger

### Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
**Record:** `WARN_ON` + `NULL` return from `__early_ioremap()` →
ACPI/EFI early mapping failure → **boot failure or ACPI broken**.
Severity: **HIGH** for affected configs (boot-time), though trigger
frequency is **LOW**.

### Step 8.4: CALCULATE RISK-BENEFIT RATIO
**Record:**
- **Benefit:** MEDIUM-HIGH — restores intended 256K early_ioremap
  budget; prevents deterministic boot failures in edge cases
- **Risk:** VERY LOW — 7 extra fixmap pages, no API change, maintainer-
  applied
- **Ratio:** Favorable for stable

---

## PHASE 9: FINAL SYNTHESIS

### Step 9.1: COMPILE THE EVIDENCE

**FOR backport:**
- Real, deterministic off-by-one bug in fixmap sizing
- Boot-time failure mode (NULL from `early_ioremap`)
- Tiny, obviously correct fix; arm64 maintainer signed off
- In mainline (`21fc7ec93f8b6`); cherry-picks cleanly to 6.18.44
- Bug present in this tree since at least v5.10
- Meets stable size rule (< 100 lines)

**AGAINST backport:**
- No user/syzbot report — edge-case trigger
- Most chunking callers already avoid the failure
- arm64-only (not a concern for this tree-specific verdict)

**UNRESOLVED:** No documented production incident; impact inferred from
code path analysis.

### Step 9.2: STABLE RULES CHECKLIST
1. Obviously correct and tested? **PASS** — mathematically correct;
   maintainer-applied to mainline (no explicit Tested-by)
2. Fixes a real bug? **PASS** — deterministic `nrpages > NR_FIX_BTMAPS`
   failure
3. Important issue? **PASS** — boot-time mapping failure (HIGH severity,
   lower frequency)
4. Small and contained? **PASS** — 6 lines, one file
5. No new features/APIs? **PASS** — sizing correction only
6. Can apply to local tree? **PASS** — clean cherry-pick verified

### Step 9.3: EXCEPTION CATEGORIES
**Record:** N/A — standard bug fix, not device-ID/quirk/build/doc
exception.

### Step 9.4: DECISION RATIONALE
For **this 6.18.44 arm64 stable tree**, the buggy `NR_FIX_BTMAPS`
definition exists and the fix is already in mainline. The patch is
minimal, maintainer-backed, and prevents real early-boot
`early_ioremap()` failures when the full 256K mapping budget is used at
a misaligned physical address. Risk is negligible.

---

## Verification

- [Phase 1] `git describe HEAD` → v6.18.44; parsed commit message tags
- [Phase 2] Read `mm/early_ioremap.c` lines 100–160; confirmed alignment
  → `nrpages` check
- [Phase 2] Python math: offset 1/2048/4095 + 256K → `nrpages=65`,
  `NR_FIX_BTMAPS=64`, `fail=True`
- [Phase 3] `git blame` on fixmap.h; tags v5.10–v6.18.44 all show
  `SZ_256K / PAGE_SIZE`
- [Phase 3] `git show 21fc7ec93f8b6` — mainline commit details
- [Phase 3] `git log 1efe5d048a391..master --grep='256K early_ioremap'`
  — fix after 6.18.44
- [Phase 4] `b4 dig -c 21fc7ec93f8b6` — lore URL found
- [Phase 4] `b4 dig -c 21fc7ec93f8b6 -w` — maintainers CC'd
- [Phase 4] `b4 dig -c 21fc7ec93f8b6 -a` — v1 only
- [Phase 4] `b4 dig -m /tmp/fixmap_thread.mbox` — Will Deacon "Applied"
  reply, no NAKs
- [Phase 5] Grep `early_memremap`/`__acpi_map_table` call paths on arm64
- [Phase 5] Read `arch/arm64/kernel/acpi.c` — direct
  `early_memremap(phys, size)` without chunking
- [Phase 6] `git show HEAD:arch/arm64/include/asm/fixmap.h` — buggy
  macro confirmed
- [Phase 6] `git show master:arch/arm64/include/asm/fixmap.h` — fixed
  macro on master
- [Phase 6] `git cherry-pick --no-commit 21fc7ec93f8b6` — clean auto-
  merge

---

**YES**Those background checks finished and line up with the earlier
analysis:

- **NR_FIX_BTMAPS history** — The `SZ_256K / PAGE_SIZE` definition has
  been in arm64 `fixmap.h` since at least v5.10 through v6.18.44, so the
  off-by-one bug is long-standing in this tree.
- **Branch check** — The fix is on `master` (`21fc7ec93f8b6`); the
  6.18.44 checkout still has the buggy `(SZ_256K / PAGE_SIZE)` define.
- **Release timing** — The fix landed in mainline after the `Linux
  6.18.44` tag, which is why it belongs as a stable backport.

**Verdict for 6.18.y: YES** — small, maintainer-applied fix for a real
early-boot `early_ioremap()` failure when mapping 256K at a misaligned
physical address; cherry-picks cleanly.

 arch/arm64/include/asm/fixmap.h | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/fixmap.h b/arch/arm64/include/asm/fixmap.h
index 635a43c4ec85b..9288021ba93b1 100644
--- a/arch/arm64/include/asm/fixmap.h
+++ b/arch/arm64/include/asm/fixmap.h
@@ -78,8 +78,12 @@ enum fixed_addresses {
 	/*
 	 * Temporary boot-time mappings, used by early_ioremap(),
 	 * before ioremap() is functional.
+	 *
+	 * Reserve one extra page so a 256K mapping may start at any
+	 * offset within a page. early_ioremap() maps the page-aligned
+	 * physical range, so the initial offset can consume an extra page.
 	 */
-#define NR_FIX_BTMAPS		(SZ_256K / PAGE_SIZE)
+#define NR_FIX_BTMAPS		((SZ_256K / PAGE_SIZE) + 1)
 #define FIX_BTMAPS_SLOTS	7
 #define TOTAL_FIX_BTMAPS	(NR_FIX_BTMAPS * FIX_BTMAPS_SLOTS)
 
-- 
2.53.0




More information about the linux-arm-kernel mailing list