veridian_kernel/drivers/gpu_nouveau.rs
1//! NVIDIA Nouveau GPU Driver Framework
2//!
3//! Provides PCI device detection and structured types for NVIDIA GPUs using
4//! the open-source Nouveau driver model. Actual register programming requires
5//! hardware access not available in QEMU's virtio-gpu environment.
6
7#![allow(dead_code)]
8
9#[cfg(target_arch = "x86_64")]
10use alloc::format;
11use alloc::{string::String, vec::Vec};
12
13use crate::error::KernelError;
14
15// ---------------------------------------------------------------------------
16// PCI Device IDs
17// ---------------------------------------------------------------------------
18
19/// NVIDIA GPU PCI device IDs (subset of common devices)
20pub mod device_ids {
21 // Pascal (GP10x)
22 /// GeForce GTX 1080 (GP104)
23 pub const GTX_1080: u16 = 0x1B80;
24 /// GeForce GTX 1070 (GP104)
25 pub const GTX_1070: u16 = 0x1B81;
26 /// GeForce GTX 1060 (GP106)
27 pub const GTX_1060: u16 = 0x1C03;
28
29 // Turing (TU10x)
30 /// GeForce RTX 2080 Ti (TU102)
31 pub const RTX_2080TI: u16 = 0x1E04;
32 /// GeForce RTX 2070 (TU106)
33 pub const RTX_2070: u16 = 0x1F02;
34
35 // Ampere (GA10x)
36 /// GeForce RTX 3090 (GA102)
37 pub const RTX_3090: u16 = 0x2204;
38 /// GeForce RTX 3080 (GA102)
39 pub const RTX_3080: u16 = 0x2206;
40 /// GeForce RTX 3070 (GA104)
41 pub const RTX_3070: u16 = 0x2484;
42
43 // Ada Lovelace (AD10x)
44 /// GeForce RTX 4090 (AD102)
45 pub const RTX_4090: u16 = 0x2684;
46 /// GeForce RTX 4080 (AD103)
47 pub const RTX_4080: u16 = 0x2704;
48}
49
50// ---------------------------------------------------------------------------
51// GPU Architecture Classification
52// ---------------------------------------------------------------------------
53
54/// NVIDIA GPU architecture
55#[derive(Debug, Clone, Copy, PartialEq, Eq)]
56pub enum NvidiaArchitecture {
57 /// Pascal (GTX 10-series, GP10x)
58 Pascal,
59 /// Turing (RTX 20-series, TU10x)
60 Turing,
61 /// Ampere (RTX 30-series, GA10x)
62 Ampere,
63 /// Ada Lovelace (RTX 40-series, AD10x)
64 Ada,
65 /// Unrecognised device ID
66 Unknown,
67}
68
69impl core::fmt::Display for NvidiaArchitecture {
70 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
71 match self {
72 Self::Pascal => write!(f, "Pascal"),
73 Self::Turing => write!(f, "Turing"),
74 Self::Ampere => write!(f, "Ampere"),
75 Self::Ada => write!(f, "Ada"),
76 Self::Unknown => write!(f, "Unknown"),
77 }
78 }
79}
80
81// ---------------------------------------------------------------------------
82// MMIO Register Offsets
83// ---------------------------------------------------------------------------
84
85/// MMIO register block offsets (per Nouveau/envytools documentation)
86pub mod regs {
87 /// Master control registers (PMC)
88 pub const NV_PMC: u64 = 0x000000;
89 /// Bus interface control (PBUS)
90 pub const NV_PBUS: u64 = 0x001000;
91 /// Display engine (PDISP)
92 pub const NV_PDISP: u64 = 0x610000;
93 /// Graphics engine (PGRAPH)
94 pub const NV_PGRAPH: u64 = 0x400000;
95 /// FIFO engine (command submission)
96 pub const NV_PFIFO: u64 = 0x002000;
97 /// Frame buffer interface (PFB)
98 pub const NV_PFB: u64 = 0x100000;
99 /// Timer / clock control (PTIMER)
100 pub const NV_PTIMER: u64 = 0x009000;
101 /// GPIO / fan control (PGPIO)
102 pub const NV_PGPIO: u64 = 0x00D000;
103 /// Power management (PPWR / PMU Falcon)
104 pub const NV_PPWR: u64 = 0x10A000;
105 /// Boot / strap registers
106 pub const NV_PBOOT: u64 = 0x000000;
107}
108
109// ---------------------------------------------------------------------------
110// Falcon Microcontroller Types
111// ---------------------------------------------------------------------------
112
113/// NVIDIA Falcon security co-processor engine
114#[derive(Debug, Clone, Copy, PartialEq, Eq)]
115pub enum FalconEngine {
116 /// Power Management Unit
117 Pmu,
118 /// Display engine
119 Display,
120 /// Graphics context switch
121 GrCtxSw,
122 /// Video decode (NVDEC)
123 Nvdec,
124 /// Video encode (NVENC)
125 Nvenc,
126 /// Security (SEC2)
127 Sec2,
128 /// GSP (GPU System Processor, Turing+)
129 Gsp,
130}
131
132/// Falcon engine state
133#[derive(Debug, Clone, Copy, PartialEq, Eq)]
134pub enum FalconState {
135 /// Engine is not initialised
136 Reset,
137 /// Firmware is loaded
138 Loaded,
139 /// Engine is running
140 Running,
141 /// Engine encountered an error
142 Error,
143}
144
145// ---------------------------------------------------------------------------
146// Device Representation
147// ---------------------------------------------------------------------------
148
149/// NVIDIA GPU device instance
150pub struct NouveauDevice {
151 /// PCI vendor ID (always 0x10DE for NVIDIA)
152 pub vendor_id: u16,
153 /// PCI device ID
154 pub device_id: u16,
155 /// Classified GPU architecture
156 pub architecture: NvidiaArchitecture,
157 /// BAR0 MMIO base address (registers)
158 pub mmio_base: u64,
159 /// BAR0 MMIO region size
160 pub mmio_size: u64,
161 /// VRAM aperture base (BAR1)
162 pub vram_base: u64,
163 /// VRAM aperture size
164 pub vram_size: u64,
165 /// Human-readable device name
166 pub name: String,
167}
168
169impl NouveauDevice {
170 /// Classify GPU architecture from PCI device ID.
171 ///
172 /// Device ID ranges are derived from the upstream Nouveau driver
173 /// chipset identification and envytools database.
174 pub fn classify_architecture(device_id: u16) -> NvidiaArchitecture {
175 match device_id {
176 // Pascal (GP10x): GTX 10-series
177 0x1B00..=0x1D8F => NvidiaArchitecture::Pascal,
178 // Turing (TU10x): RTX 20-series, GTX 16-series
179 0x1E00..=0x1EFF | 0x1F00..=0x1FFF | 0x2180..=0x21FF => NvidiaArchitecture::Turing,
180 // Ampere (GA10x): RTX 30-series
181 0x2200..=0x22FF | 0x2480..=0x24FF | 0x2500..=0x257F => NvidiaArchitecture::Ampere,
182 // Ada Lovelace (AD10x): RTX 40-series
183 0x2680..=0x27FF => NvidiaArchitecture::Ada,
184 _ => NvidiaArchitecture::Unknown,
185 }
186 }
187
188 /// Return `true` if this GPU requires GSP firmware (Turing+).
189 pub fn requires_gsp(&self) -> bool {
190 matches!(
191 self.architecture,
192 NvidiaArchitecture::Turing | NvidiaArchitecture::Ampere | NvidiaArchitecture::Ada
193 )
194 }
195
196 /// Return `true` if this GPU supports hardware raytracing (Turing+).
197 pub fn has_raytracing(&self) -> bool {
198 matches!(
199 self.architecture,
200 NvidiaArchitecture::Turing | NvidiaArchitecture::Ampere | NvidiaArchitecture::Ada
201 )
202 }
203}
204
205// ---------------------------------------------------------------------------
206// PCI Probing
207// ---------------------------------------------------------------------------
208
209/// Probe the PCI bus for NVIDIA GPU devices (x86_64 only).
210///
211/// Returns a list of detected NVIDIA display-class devices with architecture
212/// classification and BAR information. No register programming is performed.
213#[cfg(target_arch = "x86_64")]
214pub fn probe() -> Vec<NouveauDevice> {
215 let mut devices = Vec::new();
216
217 if !crate::drivers::pci::is_pci_initialized() {
218 return devices;
219 }
220
221 let bus = crate::drivers::pci::get_pci_bus().lock();
222 let pci_devices = bus.find_devices_by_class(crate::drivers::pci::class_codes::DISPLAY);
223
224 for pci_dev in &pci_devices {
225 if pci_dev.vendor_id != 0x10DE {
226 continue;
227 }
228
229 let arch = NouveauDevice::classify_architecture(pci_dev.device_id);
230
231 // BAR0 = MMIO registers
232 let (mmio_base, mmio_size) = pci_dev
233 .bars
234 .first()
235 .map(|bar| match bar {
236 crate::drivers::pci::PciBar::Memory { address, size, .. } => (*address, *size),
237 _ => (0, 0),
238 })
239 .unwrap_or((0, 0));
240
241 // BAR1 = VRAM aperture
242 let (vram_base, vram_size) = pci_dev
243 .bars
244 .get(1)
245 .map(|bar| match bar {
246 crate::drivers::pci::PciBar::Memory { address, size, .. } => (*address, *size),
247 _ => (0, 0),
248 })
249 .unwrap_or((0, 0));
250
251 devices.push(NouveauDevice {
252 vendor_id: pci_dev.vendor_id,
253 device_id: pci_dev.device_id,
254 architecture: arch,
255 mmio_base,
256 mmio_size,
257 vram_base,
258 vram_size,
259 name: format!("NVIDIA GPU {:04x} ({})", pci_dev.device_id, arch),
260 });
261 }
262
263 devices
264}
265
266/// Stub probe for non-x86_64 architectures.
267#[cfg(not(target_arch = "x86_64"))]
268pub fn probe() -> Vec<NouveauDevice> {
269 Vec::new()
270}
271
272// ---------------------------------------------------------------------------
273// Initialization
274// ---------------------------------------------------------------------------
275
276/// Initialize the Nouveau GPU driver (detection only).
277///
278/// Scans the PCI bus for NVIDIA display-class devices and logs any found.
279/// No register programming, firmware loading, or mode setting is performed.
280pub fn init() -> Result<(), KernelError> {
281 let devices = probe();
282
283 if devices.is_empty() {
284 crate::println!("[nouveau] No NVIDIA GPU devices found");
285 } else {
286 for dev in &devices {
287 crate::println!(
288 "[nouveau] Found: {} (BAR0: {:#x}, VRAM: {:#x}{})",
289 dev.name,
290 dev.mmio_base,
291 dev.vram_size,
292 if dev.requires_gsp() {
293 ", GSP required"
294 } else {
295 ""
296 }
297 );
298 }
299 }
300
301 Ok(())
302}