# DF-4856 verdict — certain in source, hardware-gated at runtime

## Root cause

sys/dev/agp/agp_amd64.c:454-463 (agp_amd64_via_init):

```c
459:	agp_amd64_apbase_fixup(dev);
460:	pci_cfgregwrite(0, 1, 0, AGP3_VIA_ATTBASE, sc->gatt->ag_physical, 4);
461:	pci_cfgregwrite(0, 1, 0, AGP3_VIA_GARTCTRL,
462:	    pci_cfgregread(0, 1, 0, AGP3_VIA_ATTBASE, 4) | 0x180, 4);
```

Line 462 reads AGP3_VIA_ATTBASE (0x98) as the preserve-mask source for the
AGP3_VIA_GARTCTRL (0x90) write. Every other GARTCTRL-style RMW in this driver
family reads the register it writes (compare agp_amd64.c:233-237, :306-308,
:362-364). The register addresses are adjacent defines (agpreg.h:98-100:
GARTCTRL 0x90, APSIZE 0x94, ATTBASE 0x98) — a transcription slip.

Effect: the VIA secondary bridge's GARTCTRL is loaded with
`sc->gatt->ag_physical | 0x180` — a 32-bit physical address of the GATT
(e.g. 0x3f000000-ish) OR 0x180 — instead of its prior configuration with
bits 0x180 set. GARTCTRL bits on VIA AGP3 control GART enable / queue /
size; an arbitrary address value can disable the secondary GART or program
nonsense sizes. On VIA K8T800/8385 boards where agp_amd64_via_match()
agp_amd64.c:130-142 accepts the host bridge, AGP GART translation through
the 0:1:0 bridge is misconfigured at attach. Boot-time hardware programming
only; no attacker-controlled input reaches these writes; no kernel memory
safety impact. Info severity.

## Upstream provenance (inherited, not DF-introduced)

Verified byte-identical in FreeBSD:

- freebsd-src release/9.0.0 sys/dev/agp/agp_amd64.c:467-469
  (`pci_cfgregread(0, 1, 0, AGP3_VIA_ATTBASE, 4) | 0x180`)
- freebsd-src stable/12 sys/dev/agp/agp_amd64.c:464-466 (same)

DF's copy (header: `$FreeBSD: src/sys/dev/agp/agp_amd64.c,v 1.17 2009/01/12`)
inherited the bug verbatim; upstream carried it until the file's removal.
Log as divergence-with-upstream-ownership per AGENT.md contrib rules — but
this is base sys/dev/agp code in DF's tree, so DF should fix it locally.

## Why not_reproduced at runtime

Requires a VIA K8T800-class host bridge (ids 0x02041106/0x02381106/
0x02821106/0x31881106, agp_amd64.c:104-111) *plus* the 0:1:0 secondary AGP
bridge with AGPSEL bit clear. The QEMU audit guest presents a single i440FX
host bridge (0x12378086); agp_amd64 cannot probe, so the register write never
executes. There is no userspace-observable trigger for a config-space
programming defect even on real hardware short of AGP not working — hence
Info/likely (source-certain, impact reasoned not measured).

## Fix

`fix.diff` (validated `git apply --check`): read GARTCTRL back from GARTCTRL:

```diff
 	pci_cfgregwrite(0, 1, 0, AGP3_VIA_GARTCTRL,
-	    pci_cfgregread(0, 1, 0, AGP3_VIA_ATTBASE, 4) | 0x180, 4);
+	    pci_cfgregread(0, 1, 0, AGP3_VIA_GARTCTRL, 4) | 0x180, 4);
```

## Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest `make -j6 nativekernel KERNCONF=X86_64_GENERIC` completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
