danos/docs/device-driver-development/amd-gpus.md

345 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Native AMD GPU support — feasibility and roadmap
**Status: research snapshot, not implemented.** This records what a *minimal, display-only*
native driver for a real discrete AMD GPU — specifically an **RX 6600-class card (Navi 23,
RDNA2, DCN 3.0.2)**, the market analog of the RTX 3060 — would take, and how it slots into
danos's pluggable scanout architecture. It is a survey of primary sources (the Linux
[amdgpu Display Core](https://github.com/torvalds/linux/tree/master/drivers/gpu/drm/amd/display)
driver and its [kernel documentation](https://docs.kernel.org/gpu/amdgpu/display/index.html),
the AtomBIOS interpreter in
[drivers/gpu/drm/amd](https://github.com/torvalds/linux/tree/master/drivers/gpu/drm/amd),
linux-firmware's `LICENSE.amdgpu`, and Haiku's
[radeon_hd](https://github.com/haiku/haiku/tree/master/src/add-ons/kernel/drivers/graphics/radeon_hd)),
not an implementation. It completes the trilogy with [nvidia-gpus.md](nvidia-gpus.md) and
[intel-igpu.md](intel-igpu.md) and should be read against both — AMD lands *between* them:
NVIDIA-class discrete-card mechanics, but Intel-class (better, in one way) reference material.
Read [display.md](display.md) and [display-v2.md](display-v2.md) first — this doc assumes the
v2 model where scanout is a **pluggable backend** and a native driver is just another `.scanout`
service (like the virtio-gpu one), announcing to the compositor over `attach_scanout`.
## TL;DR
- **AMD's decisive advantage is that the vendor's own display driver is the register manual, and
it's MIT-licensed.** The entire Display Core (DC) — hardware sequencer, per-block code for
OTG/OPTC, HUBP, DPP, MPC, DIO/link encoders, plus the `asic_reg` register headers — ships in
the Linux tree under MIT/X11, deliberately written OS-agnostic because AMD shares it across
operating systems. You can study it, port it, even copy from it into a danos driver without
license contamination. NVIDIA has no analog (nouveau is GPL); Intel has PRM prose but you
still write the code yourself.
- **The firmware wall is one small blob, not a GSP.** The only display-side firmware the Linux
driver hard-requires is **DMCUB** (the display microcontroller), and only on **DCN 2.1
through 4.x** — which includes Navi 23. It is redistributable from linux-firmware, and it is
a display helper, not a full-card resource manager: on DCN 3.0.x, hardware init
(`dcn30_init_hw`) is **host-driven direct register programming** — the only DMUB call in it
is a capability query. All DCE generations, DCN 1.0 (Raven), and DCN 2.0 (Navi 10/12/14) run
display with **no display firmware at all**.
- **Whether the *silicon* (vs. the Linux driver) needs DMCUB for a bare GOP-inheriting modeset
is unproven** — Linux fails init with `-EINVAL` if the blob is missing on a DMUB ASIC, but
what it's *used for* at minimum scope (vs. PSR/ABM/offloaded DP link training) isn't
documented. The safe plan ships the blob; it's legally and practically cheap to do so.
- **Programming model is direct MMIO, not channel DMA.** DCN mode-set is ordered register-write
sequences (the DC "hardware sequencer") against named, header-documented registers — no
pushbuffers, no method streams, no RAMHT, no supervisor-interrupt handshake. This deletes the
hardest structural layer of the NVIDIA path.
- **Scanout is VRAM-only on discrete cards** — the claim that DCN can scan out of GTT/system
memory was checked and *refuted* for dGPUs (Linux allows GTT scanout only on select APUs). So
a small VRAM allocator + BAR CPU mapping is required, same as NVIDIA. Pitch-linear surfaces
are supported; no DCC/tiling needed.
- **danos's GOP boot helps here too, with a caveat.** DC explicitly models taking over a
VBIOS/GOP-lit pipe (`dc_validate_boot_timing` reads back live DIG/OTG/pixel-clock state), so
"repoint the surface on the running pipe" is demonstrably hardware-feasible — but Linux's
seamless-boot path is **eDP-only and default-off on discrete cards**, so plan on a full
self-owned modeset (including DP retrain) right after first light rather than living on the
inherited link.
- **AMD has real non-Linux prior art — but only for the old hardware.** Haiku's MIT `radeon_hd`
mode-sets by executing VBIOS **AtomBIOS command tables** through AMD's own MIT interpreter;
its compiled-in ceiling is **DCE 8.5 (Hawaii, ~2013)** — every Polaris/Vega/Navi entry sits
in a `#if 0` block. There is zero non-Linux DCN precedent; a danos DCN driver would be first.
- **Effort tier ≈ high-3 to 4** for a native DCN 3.0.x display-only driver on Navi 23 — the raw
register surface is GA106-class (tier 4), but the MIT vendor reference, the one-blob firmware
wall, and the absence of channel-DMA plumbing pull real risk out. The AtomBIOS-interpreter
route is tier ≈ 3 but dead-ends at pre-2016 silicon.
- **Recommendation:** the same sober conclusion as the other two docs — GOP already gives
native-res scanout for zero code — but if danos ever does drive real discrete silicon
natively, **an RDNA2 card is the best target of the three**: modern, mainstream, in-warranty
hardware with a legally clean, vendor-authored reference. That combination exists nowhere
else.
## The firmware wall (a fence, next to NVIDIA's wall)
AMD GPUs carry a zoo of firmware: PSP (security processor), SMU (power/clock management), CP/RLC
(graphics), SDMA, VCN (media) — and, on the display side, DMCU (legacy) then **DMCUB**
("Display Micro-Controller Unit, version B"), a per-generation blob in linux-firmware
(`navi23_dmcub.bin` etc.). The display-only question is: which of these does a scanout driver
actually need?
The Linux answer is precise and readable in
[`amdgpu_dm.c`](https://github.com/torvalds/linux/blob/master/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c):
`dm_init_microcode()` switches on the display IP version — **DCN 2.1 (Renoir) through DCN
3.0.x / 3.1.x / 3.2 / 3.5 / 4.x** request a DMCUB blob as `AMDGPU_UCODE_REQUIRED`, and
`dm_dmub_hw_init()` fails driver init with `-EINVAL` if it's absent. Everything earlier — **all
of DCE (Southern Islands through Vega), DCN 1.0 (Raven), and DCN 2.0 (Navi 10/12/14)** — hits
the `default:` case, `dmub_srv` stays NULL, and display runs with no display firmware at all
([kernel display-manager doc](https://docs.kernel.org/6.2/gpu/amdgpu/display/display-manager.html)).
Two nuances survive verification:
- **The requirement is Linux-driver enforcement backed by real functional need, and it's
version-sensitive.** AMD force-switched all Renoir ASICs to DMUB to fix a USB-C/resume bug
(kernel commit `652de07addd2`, "with new dmub f/w dmcu is superseded"), which regressed users
on old blobs and had to be patched with explicit `dmcub_fw_version` gating (`91adec9e0709`).
What DMUB is *used for* varies with blob version. Ship a current blob.
- **DMCUB is an architectural fixture, not a bolt-on** — the DCN hardware itself contains a DMU
block housing the microcontroller
([DCN overview](https://docs.kernel.org/gpu/amdgpu/display/dcn-overview.html)) — but it is
**not a mediator of the programming model** on DCN 3.0: `dcn30_init_hw()` initializes clocks,
disables power gating, and powers up link encoders via direct register writes; its sole DMUB
interaction is `dc_dmub_srv_query_caps_cmd`. Firmware-*assisted* PHY/link bring-up appears
from **DCN 3.1** onward — one more reason to target 3.0.x. Features like PSR and ABM are
DMUB-offloaded on all generations; a minimal driver simply doesn't enable them.
**Contrast with NVIDIA's GSP:** the GSP is a full resource manager with a signed multi-stage
boot chain and a firmware ABI that breaks every driver release. DMCUB is a display helper blob
you copy onto the boot image once, load into a reserved buffer, and mostly ignore. There is no
signature fuse-matching, no WPR carve-out, no RPC-only register access. The one genuinely open
question — whether a GOP-inheriting minimal modeset could skip DMCUB entirely on DCN 3.0.2 —
doesn't need answering, because shipping the blob costs nothing (see [Licensing](#licensing)).
**PSP/SMU remain the flagged risk.** Nothing display-only touches CP/RLC/SDMA (those gate the
graphics rings, exactly like NVIDIA's PGRAPH — irrelevant here). But `dcn30_init_hw` calls into
the clock manager, and on discrete cards the clock manager may message the SMU to change display
clocks (DISPCLK/DPPCLK). Whether inherited GOP boot clocks suffice for a same-or-lower mode —
avoiding SMU (and hence PSP firmware-load) entirely — is the largest unverified assumption in
the milestone list below. The survey produced no confirmed claim either way.
## The display engine landscape
Two eras, one boundary that matters:
| Generation | Display IP | Cards | Display firmware | Route |
|---|---|---|---|---|
| GCN 14 (SI→Polaris) | DCE 6/8/10/11 | HD 7000 → RX 580 | none | AtomBIOS tables or direct DCE registers |
| Vega / Raven | DCE 12 / DCN 1.0 | Vega 56/64, APUs | none | DC code (first DCN) |
| Navi 1x (RDNA1) | DCN 2.0 | RX 55005700 | none | DC code |
| Renoir APU | DCN 2.1 | 4000-series APUs | **DMCUB required** | DC code |
| **Navi 2x (RDNA2)** | **DCN 3.0.x** | **RX 66006900** | **DMCUB required** | **DC code, host-driven init** |
| RDNA3/RDNA4+ | DCN 3.1+/3.2/3.5/4.x | RX 7000/9000 | DMCUB required, fw-assisted PHY | DC code, more DMUB offload |
The best modern first-pixel target is **DCN 3.0.x**: it has the full MIT block stack from the
June 2020 Sienna Cichlid patch series (207 patches, Linux 5.9; Navi 23 reuses the dcn30
sequencer), host-driven hardware init, and sits *before* the DCN 3.1 shift toward
firmware-assisted link management. Older DCE cards are even simpler (no firmware at all, plus
the AtomBIOS escape hatch) but are 20132016 hardware; newer DCN 3.5/4.x pushes more into DMUB.
The DCN pipe, in one line each (the vocabulary the DC code speaks —
[programming model](https://docs.kernel.org/next/gpu/amdgpu/display/programming-model-dcn.html)):
**HUBP** fetches and unpacks the surface from memory (this is where the scanout address and
pitch live), **DPP** scales/converts colors, **MPC** blends planes (bypassable for one plane),
**OPP** packs output, **OTG/OPTC** generates raster timings (the CRTC), and the **DIO** block's
DIG encoders + PHY drive the connector. Mode-set is the DC *hardware sequencer* walking these
blocks with ordered register writes — plain MMIO with polling, no pushbuffer channels, no
supervisor interrupts. Structurally this is Intel-shaped, not NVIDIA-shaped.
## Two routes: AtomBIOS interpreter vs. native DC-derived registers
**AtomBIOS** is AMD's VBIOS bytecode: every card's ROM carries *data tables* (connector
topology, clock limits — the DCB equivalent) and *command tables* (`SetPixelClock`,
`SetCRTC_Timing`, `EnableCRTC`, DIG encoder/transmitter control), executed by a small
interpreter the driver embeds (`atom.c`, ~1.5k lines). The classic radeon driver and Haiku's
`radeon_hd` mode-set this way: parse the tables, execute them, and the VBIOS does the
register-level work for you — inherently per-board correct, since the tables come from the
card's own ROM.
- **Where it's proven:** through DCE 8.5 (Haiku's ceiling, below) and in Linux's pre-DC code
through Polaris (DCE 11.2). AMD's interpreter itself is MIT (Haiku ships AMD's own
`atom.cpp`, "Copyright 2008 Advanced Micro Devices").
- **Where it's unproven:** DCN. amdgpu's DC still *uses* AtomBIOS for init sub-steps
(`bios_golden_init` in `dcn30_init_hw` executes host-interpreted tables) and reads the data
tables for connector topology — but nobody drives a full DCN modeset from command tables, and
whether RDNA2 VBIOSes still carry a complete modeset path or vestigial init-only tables is an
open question no source answers. Do not bet on it.
**The native route** is: port the relevant slice of DC. Not wholesale — in-tree DC has
accumulated Linux-isms (kernel-FPU guards around DML, the bandwidth-calculation library, which a
single-plane fixed-mode driver can largely sidestep) — but the DC core is *designed* to be
retargeted: the kernel docs state outright that DC "is shared with other OSes" and holds the
OS-agnostic hardware programming behind a `dm_services` shim (register access, memory, delays,
firmware loading). Dave Airlie initially rejected the DAL/DC merge in 2016 *because* it was
AMD's cross-OS codebase — hostile-witness confirmation that this exact code runs outside Linux.
Reimplement the shim in Zig, and the dcn30 sequences sit on top.
## The memory floor
Same shape as NVIDIA's, and the survey *hardened* one assumption:
- **VRAM-only scanout on discrete cards.** The documented DCN fetch path is VRAM → Data Fabric
(SDP) → DCHUB → HUBP; the claim that display buffers can live in GTT/system memory was
refuted for dGPUs in verification — Linux permits GTT scanout only on select APUs. The NVIDIA
doc's "maybe sysmem ctxdma?" hope has a firm *no* here. Budget for a small VRAM allocator.
- **Pitch-linear is fine.** HUBP programs a surface address + pitch; linear (untiled, no DCC)
surfaces are first-class for scanout. No tiling math.
- **CPU access via the VRAM BAR.** Compositing writes go through the PCI VRAM aperture;
resizable BAR helps but isn't needed — one pitch-linear surface fits comfortably in a
fixed 256 MB small-BAR window.
- **No GPU VMM.** Display addresses are physical VRAM addresses programmed into HUBP; no page
tables, no GEM/TTM, no eviction.
**Net:** (1) a contiguous aligned VRAM allocator, (2) a BAR CPU mapping, (3) a small reserved
buffer for the DMCUB firmware regions. That's the whole memory story.
## Inheriting GOP state
danos's GOP boot pays off again, with sharper edges than on NVIDIA:
- **DC models pipe takeover explicitly.** `dc_validate_boot_timing()`
([dc.c](https://github.com/torvalds/linux/blob/master/drivers/gpu/drm/amd/display/dc/core/dc.c))
reads back *live* hardware — `is_dig_enabled` on the link encoder, OTG timing registers,
pixel clock within tolerance — and keeps the VBIOS/GOP-lit pipe running until first flip.
This is a vendor-blessed recipe for milestone 2 below: the exact register set that tells you
which pipe is alive and how it's configured.
- **But Linux's seamless path is eDP-only and APU-gated.** The code comment is blunt: "Support
seamless boot on EDP displays only", and the enabling check requires an APU with DCN ≥ 3.0
unless forced with `amdgpu.seamless=1`. On a discrete RX 6600 with DP/HDMI, Linux does a full
modeset at takeover. Read that as a warning, not a prohibition: repointing HUBP at your own
surface on the live pipe should still work (the readback code proves the state is
inspectable), but plan the full self-owned modeset — **including DP retraining** — as the
immediate next step, not a someday.
- **No supervisor handshake exists to re-learn.** The NVIDIA doc's SV1/SV2/SV3 open question has
no AMD counterpart; commit sequencing is ordered register writes + vblank/lock waits in the
hwseq, all visible in MIT source.
## Licensing
The inverse of the NVIDIA situation, and the single strongest argument for AMD:
- **The reference code is MIT.** `amdgpu_dm.c` carries `SPDX-License-Identifier: MIT`;
`dc/core/dc.c` and `dmub_srv.h` carry the full X11-style grant (use, copy, modify, merge,
publish, distribute, sell). The `asic_reg` register headers ship under the same terms. One
diligence note: SPDX tagging isn't uniform across the tree, so header-check each file before
copying from it — but no GPL files are known inside `dc/`. Where nouveau forces a
GPL-or-clean-room choice, here the *easy technical path and the permissive path are the same
path*.
- **Firmware redistribution is a solved problem.** linux-firmware's `LICENSE.amdgpu` grants
anyone a royalty-free right to reproduce and distribute the blobs, binary-only, with the
license text attached — no OSI-license gate like NVIDIA's, no AMD agreement needed. danos can
ship `navi23_dmcub.bin` (and PSP/SMU blobs if ever needed) on its boot image today. The same
license **prohibits reverse-engineering the blobs** — all programming knowledge must come
from the MIT source, never from blob disassembly. (VBIOS images aren't in linux-firmware;
they're read from the card's own ROM, as Haiku does.)
- **Prose register docs are a DCE-era artifact.** AMD's classic X.Org-hosted PDFs cover the old
families — and the famous `R6xx_3D_Registers.pdf` turns out to be 3D-only (verified: zero
display content; the display material lives in the separate per-ASIC Register Reference
Guides). For DCN there is **no prose display spec at all**: the MIT DC source plus the
`asic_reg` headers *are* the register manual. Plan accordingly.
## Prior art
AMD, unlike NVIDIA, has genuine working non-Linux precedent — with a hard generational ceiling:
- **Haiku `radeon_hd`** (MIT, still in the tree): a real, shipping, from-scratch display driver
that executes AtomBIOS command tables via AMD's own MIT interpreter. Verified ceiling:
the last *enabled* device entry is **Hawaii (DCE 8.5, 0x67be)**; everything newer —
Tonga/Fiji, Carrizo/Polaris, Vega/Raven, and every Navi/RDNA2 entry up to the RX 6900 XT —
sits inside one `#if 0 /* disabled for R1/beta5 */` block under the comment "WARN: DCE
versions below here get sketchy."
- **AmigaOS/MorphOS RadeonHD drivers** (hdrlab): commercial non-Linux Radeon display drivers,
again for the DCE era.
- **FreeBSD** `drm-kmod`: a port of Linux amdgpu (DC and all), not independent prior art — but
proof the DC codebase transplants.
**Nobody has driven DCN outside Linux-derived code.** A danos DCN 3.0.x driver would be a
first — but a first with the vendor's MIT code as its map, which is a different proposition
from nouveau-as-only-reference.
## Alternatives
| Option | What you get | The tradeoff |
|---|---|---|
| **Stay on GOP** (working today) | Native-res scanout, zero GPU code/firmware/maintenance | Resolution frozen at ExitBootServices; no runtime mode change, no hardware vsync, no multihead |
| **AtomBIOS interpreter on an old DCE card** | Proven end-to-end (Haiku); interpreter is small + MIT; board-correct by construction | 20132016 hardware ceiling; tier ≈ 3; teaches AtomBIOS, not modern DCN |
| **Native DCN 3.0.x on RX 6600** (this doc) | Runtime modeset, vsync, multihead on modern silicon; MIT vendor reference; one redistributable blob | Tier ≈ high-34; SMU/clock question open; no non-Linux precedent |
| **Port DC wholesale** (reimplement `dm_services`) | Vendor-maintained sequences verbatim; designed-for-porting seam | Big codebase to carry (DML, abstractions); Linux-isms to shear off; overkill for one plane |
| **RDNA3+/DCN 3.5+** | Newer cards | More DMUB offload (fw-assisted PHY from DCN 3.1); strictly harder than 3.0.x for no display-only gain |
## "First light" milestones (native DCN 3.0.x path)
Framed as a danos `.scanout` service, inheriting the GOP-initialized display:
1. **PCI/BAR bring-up** — enumerate Navi 23, map the register BAR and the VRAM BAR via danos
MMIO grants; prove the pipe is GOP-live by writing pixels into the *existing* GOP
framebuffer through the VRAM BAR.
2. **Read back the live pipe** — port the `dc_validate_boot_timing` register set: which OTG is
running, its timings, which DIG/link encoder is enabled, current HUBP surface address/pitch.
This is pure reads — zero risk, high information.
3. **Repoint the surface** — allocate a danos-owned pitch-linear VRAM surface, program the HUBP
surface address/pitch on the live pipe at vblank. First self-owned pixel with **no modeset,
no firmware, no clock changes**.
4. **DMCUB bring-up** — load `navi23_dmcub.bin` (redistributed per `LICENSE.amdgpu`) into its
reserved regions, minimal `dmub_srv` init, verify the caps query answers.
5. **Full owned modeset** — port the dcn30 hwseq slice: OTG timing programming, MPC bypass
(single plane), DIG/PHY enable, **DP link retrain** (or start on HDMI to defer it, exactly
as the NVIDIA doc advises). This is where the SMU/clock question lands — first attempt:
reuse inherited boot clocks for a same-or-lower mode.
6. **EDID** — AUX (DP) / DDC (HDMI) over the DCN AUX engine registers; parse and build the mode
list; connector topology from the VBIOS AtomBIOS data tables.
7. **Wire into the compositor**`attach_scanout`, vsync from the vblank/pageflip interrupt,
then multihead.
Keep the GOP backend as the fallback the whole way — a stall at any step still leaves danos with
a working display (the resilience v2 already provides via re-attach).
## Reading list
**The DC core (MIT — the register manual for DCN):**
- `drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c` — hardware init + the modeset
sequencer for the target generation (host-driven; one DMUB caps query).
- `dc/dcn30/` + `dc/dcn302/` blocks: `dcn30_hubp.c` (surface address/pitch — milestone 3),
`dcn30_optc.c` (OTG timings), `dcn30_dio_link_encoder.c` (DIG/PHY), `dcn30_mpc.c` (bypass),
`clk_mgr/dcn30/` (the SMU question, read before milestone 5).
- `dc/core/dc.c``dc_validate_boot_timing()`: the GOP-takeover readback recipe.
- `asic_reg/dcn/dcn_3_0_0_{offset,sh_mask}.h` — every register name and bitfield.
- `dmub/` (`dmub_srv.h`, `src/dmub_dcn30.c`) — firmware regions + bring-up for milestone 4.
**The Linux glue (for logic, not porting):**
[`amdgpu_dm.c`](https://github.com/torvalds/linux/blob/master/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c)
`dm_init_microcode` / `dm_dmub_hw_init` (the firmware-wall switch), seamless-boot gating.
**Kernel docs (read first):**
[DCN overview](https://docs.kernel.org/gpu/amdgpu/display/dcn-overview.html) (the block diagram
+ VRAM→DF→DCHUB fetch path) ·
[DC programming model](https://docs.kernel.org/next/gpu/amdgpu/display/programming-model-dcn.html)
(dc_plane/dc_stream/dc_link objects, hwseq, block APIs) ·
[display manager](https://docs.kernel.org/6.2/gpu/amdgpu/display/display-manager.html).
**AtomBIOS:** `drivers/gpu/drm/amd/amdgpu/atom.c` (the interpreter), `atombios.h` (table
formats), [osdev AMD AtomBIOS](https://wiki.osdev.org/AMD_Atombios) (hobby-OS orientation),
Haiku [`radeon_hd`](https://github.com/haiku/haiku/tree/master/src/add-ons/kernel/drivers/graphics/radeon_hd)
(a complete worked example, MIT, through DCE 8.5).
**Licensing:** linux-firmware
[`LICENSE.amdgpu`](https://github.com/endlessm/linux-firmware/blob/master/LICENSE.amdgpu);
DCE-era prose specs at [x.org/docs/AMD](https://www.x.org/docs/AMD/) (Register Reference
Guides — display; note `R6xx_3D_Registers.pdf` is 3D-only).
## Open questions (unresolved by the survey)
- **Does DCN 3.0.2 silicon need DMCUB for a bare inherit-and-modeset path**, or only for
PSR/ABM/offloaded features? (Moot if the blob is shipped regardless — but it decides whether
milestone 3 can precede milestone 4.)
- **Can a display-only driver avoid PSP and SMU entirely** by inheriting GOP boot clocks — what
does the dcn30 clock manager actually require from SMU messaging on Navi 23 for a
same-or-lower mode? *The largest open risk in the plan.*
- **Do RDNA2 VBIOS command tables still carry a complete modeset path**, or are they vestigial
init-only tables? (Would open a Haiku-style route on modern cards; no source answers it.)
- **Is the DCN 3.0 AUX/DDC engine and DP retrain fully host-drivable without DMUB**, as
`dcn30_hwseq` implies?
- Exact HUBP surface alignment/pitch constraints for linear scanout on Navi 23 (in the headers;
not captured verbatim in the survey).
---
*Research snapshot (2026-07); findings pinned to Linux master and Haiku master as of the survey
date. DMUB coverage only grows with new DCN generations — re-verify the firmware-wall switch in
`amdgpu_dm.c` against current source before building.*