⚠️ VeridianOS Kernel Documentation - This is low-level kernel code. All functions are unsafe unless explicitly marked otherwise. no_std

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}