Skip to main content

gdma_defs/
lib.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Hardware definitions for the GDMA/MANA device, which is the NIC exposed by
5//! new Azure hardware SKUs.
6
7#![forbid(unsafe_code)]
8#![expect(missing_docs)]
9
10pub mod access;
11pub mod bnic;
12
13use bitfield_struct::bitfield;
14use inspect::Inspect;
15use open_enum::open_enum;
16use std::fmt::Debug;
17use zerocopy::FromBytes;
18use zerocopy::Immutable;
19use zerocopy::IntoBytes;
20use zerocopy::KnownLayout;
21
22pub const PAGE_SIZE32: u32 = 4096;
23pub const PAGE_SIZE64: u64 = 4096;
24
25#[repr(C)]
26#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes, Inspect)]
27pub struct RegMap {
28    #[inspect(hex)]
29    pub micro_version_number: u16,
30    #[inspect(hex)]
31    pub minor_version_number: u8,
32    #[inspect(hex)]
33    pub major_version_number: u8,
34    #[inspect(hex)]
35    pub reserved: u32,
36    #[inspect(hex)]
37    pub vf_db_pages_zone_offset: u64,
38    #[inspect(hex)]
39    pub vf_db_page_sz: u16,
40    #[inspect(hex)]
41    pub reserved2: u16,
42    #[inspect(hex)]
43    pub reserved3: u32,
44    #[inspect(hex)]
45    pub vf_gdma_sriov_shared_reg_start: u64,
46    #[inspect(hex)]
47    pub vf_gdma_sriov_shared_sz: u16,
48    #[inspect(hex)]
49    pub reserved4: u16,
50    #[inspect(hex)]
51    pub reserved5: u32,
52}
53
54pub const DB_SQ: u32 = 0;
55pub const DB_RQ: u32 = 0x400;
56pub const DB_RQ_CLIENT_DATA: u32 = 0x408;
57pub const DB_CQ: u32 = 0x800;
58pub const DB_EQ: u32 = 0xff8;
59
60#[bitfield(u64)]
61pub struct CqEqDoorbellValue {
62    #[bits(24)]
63    pub id: u32,
64    pub reserved: u8,
65    #[bits(31)]
66    pub tail: u32,
67    pub arm: bool,
68}
69
70#[bitfield(u64)]
71pub struct WqDoorbellValue {
72    #[bits(24)]
73    pub id: u32,
74    pub num_rwqe: u8,
75    pub tail: u32,
76}
77
78// Shmem
79#[bitfield(u32)]
80#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
81pub struct SmcProtoHdr {
82    #[bits(3)]
83    pub msg_type: u8,
84    #[bits(3)]
85    pub msg_version: u8,
86    pub reserved_1: bool,
87    pub is_response: bool,
88    pub status: u8,
89    pub reserved_2: u8,
90    pub reset_vf: bool,
91    #[bits(6)]
92    pub reserved_3: u8,
93    pub owner_is_pf: bool,
94}
95
96open_enum! {
97    pub enum SmcMessageType: u8 {
98        SMC_MSG_TYPE_ESTABLISH_HWC = 1,
99        SMC_MSG_TYPE_DESTROY_HWC = 2,
100        SMC_MSG_TYPE_REPORT_HWC_TIMEOUT = 4,
101    }
102}
103
104pub const SMC_MSG_TYPE_ESTABLISH_HWC_VERSION: u8 = 0;
105pub const SMC_MSG_TYPE_DESTROY_HWC_VERSION: u8 = 0;
106pub const SMC_MSG_TYPE_REPORT_HWC_TIMEOUT_VERSION: u8 = 1;
107
108#[repr(C)]
109#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
110pub struct EstablishHwc {
111    pub eq: [u8; 6],
112    pub cq: [u8; 6],
113    pub rq: [u8; 6],
114    pub sq: [u8; 6],
115    pub high: u16,
116    pub msix: u16,
117    pub hdr: SmcProtoHdr,
118}
119
120// Wq
121#[repr(C, align(8))]
122#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
123pub struct Wqe {
124    pub header: WqeHeader,
125    pub data: [u8; 512 - 8],
126}
127
128pub const WQE_ALIGNMENT: usize = 32;
129
130impl Wqe {
131    pub fn oob(&self) -> &[u8] {
132        &self.data[..self.header.oob_len()]
133    }
134
135    pub fn sgl(&self) -> &[Sge] {
136        <[Sge]>::ref_from_prefix_with_elems(
137            &self.data[self.header.sgl_offset()..],
138            self.header.params.num_sgl_entries() as usize,
139        )
140        .unwrap()
141        .0
142    }
143}
144
145#[repr(C)]
146#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
147pub struct WqeHeader {
148    pub reserved: [u8; 3],
149    pub last_vbytes: u8,
150    pub params: WqeParams,
151}
152
153impl WqeHeader {
154    pub fn total_len(&self) -> usize {
155        (self.data_len() + 8 + WQE_ALIGNMENT - 1) & !(WQE_ALIGNMENT - 1)
156    }
157
158    pub fn data_len(&self) -> usize {
159        self.oob_len() + self.sgl_len()
160    }
161
162    pub fn oob_len(&self) -> usize {
163        match self.params.inline_client_oob_size() {
164            CLIENT_OOB_8 => 8,
165            CLIENT_OOB_24 => 24,
166            CLIENT_OOB_32 => 32,
167            _ => 8,
168        }
169    }
170
171    pub fn sgl_offset(&self) -> usize {
172        ((8 + self.oob_len() + 15) & !15) - 8
173    }
174
175    pub fn sgl_len(&self) -> usize {
176        self.params.num_sgl_entries() as usize * 16
177    }
178
179    pub fn sgl_direct_len(&self) -> usize {
180        debug_assert!(self.params.sgl_direct());
181        let last = (self.last_vbytes.wrapping_sub(1) & 15) + 1;
182        self.sgl_len().wrapping_sub(16).wrapping_add(last as usize) & 31
183    }
184}
185
186#[bitfield(u32)]
187#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
188pub struct WqeParams {
189    pub num_sgl_entries: u8,
190    #[bits(3)]
191    pub inline_client_oob_size: u8,
192    pub client_oob_in_sgl: bool,
193    #[bits(4)]
194    pub reserved: u8,
195    #[bits(14)]
196    pub gd_client_unit_data: u16,
197    pub reserved2: bool,
198    pub sgl_direct: bool,
199}
200
201pub const CLIENT_OOB_8: u8 = 2;
202pub const CLIENT_OOB_24: u8 = 6;
203pub const CLIENT_OOB_32: u8 = 7;
204
205#[repr(C)]
206#[derive(Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
207pub struct Sge {
208    pub address: u64,
209    pub mem_key: u32,
210    pub size: u32,
211}
212
213#[repr(C)]
214#[derive(Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
215pub struct Cqe {
216    pub data: [u8; 60],
217    pub params: CqeParams,
218}
219
220#[bitfield(u32)]
221#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
222pub struct CqeParams {
223    #[bits(24)]
224    pub wq_number: u32,
225    pub is_send_wq: bool,
226    pub cmpln: bool,
227    #[bits(3)]
228    pub reserved: u8,
229    #[bits(3)]
230    pub owner_count: u8,
231}
232
233pub const OWNER_BITS: u32 = 3;
234pub const OWNER_MASK: u32 = (1 << OWNER_BITS) - 1;
235
236#[repr(C)]
237#[derive(Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
238pub struct Eqe {
239    pub data: [u8; 12],
240    pub params: EqeParams,
241}
242
243#[bitfield(u32)]
244#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
245pub struct EqeParams {
246    pub event_type: u8,
247    pub reserved: u8,
248    #[bits(13)]
249    pub reserved2: u16,
250    #[bits(3)]
251    pub owner_count: u8,
252}
253
254pub const GDMA_EQE_COMPLETION: u8 = 3;
255pub const GDMA_EQE_TEST_EVENT: u8 = 64;
256pub const GDMA_EQE_HWC_INIT_EQ_ID_DB: u8 = 129;
257pub const GDMA_EQE_HWC_INIT_DATA: u8 = 130;
258pub const GDMA_EQE_HWC_INIT_DONE: u8 = 131;
259pub const GDMA_EQE_HWC_RECONFIG_DATA: u8 = 133;
260pub const GDMA_EQE_HWC_RESET_REQUEST: u8 = 135;
261
262#[bitfield(u32)]
263#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
264pub struct HwcInitEqIdDb {
265    pub eq_id: u16,
266    pub doorbell: u16,
267}
268
269#[bitfield(u32)]
270#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
271pub struct HwcInitTypeData {
272    #[bits(24)]
273    pub value: u32,
274    pub ty: u8,
275}
276
277pub const HWC_DATA_CONFIG_HWC_TIMEOUT: u8 = 1;
278pub const HWC_DATA_TYPE_HW_VPORT_LINK_CONNECT: u8 = 2;
279pub const HWC_DATA_TYPE_HW_VPORT_LINK_DISCONNECT: u8 = 3;
280#[repr(C)]
281#[derive(Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
282pub struct EqeDataReconfig {
283    pub data: [u8; 3],
284    pub data_type: u8,
285    pub reserved1: [u8; 8],
286}
287
288#[bitfield(u32)]
289#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
290pub struct EqeVfReset {
291    #[bits(1)]
292    pub revoke_vtl0_vf: bool,
293    #[bits(7)]
294    pub reserved1: u8,
295    #[bits(24)]
296    pub reserved2: u32,
297}
298
299pub const HWC_INIT_DATA_CQID: u8 = 1;
300pub const HWC_INIT_DATA_RQID: u8 = 2;
301pub const HWC_INIT_DATA_SQID: u8 = 3;
302pub const HWC_INIT_DATA_QUEUE_DEPTH: u8 = 4;
303pub const HWC_INIT_DATA_MAX_REQUEST: u8 = 5;
304pub const HWC_INIT_DATA_MAX_RESPONSE: u8 = 6;
305pub const HWC_INIT_DATA_MAX_NUM_CQS: u8 = 7;
306pub const HWC_INIT_DATA_PDID: u8 = 8;
307pub const HWC_INIT_DATA_GPA_MKEY: u8 = 9;
308
309open_enum! {
310    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
311    pub enum GdmaRequestType : u32 {
312        GDMA_VERIFY_VF_DRIVER_VERSION = 1,
313        GDMA_QUERY_MAX_RESOURCES = 2,
314        GDMA_LIST_DEVICES = 3,
315        GDMA_REGISTER_DEVICE = 4,
316        GDMA_DEREGISTER_DEVICE = 5,
317        GDMA_GENERATE_TEST_EQE = 10,
318        GDMA_GENERATE_RESET_REQUEST_EQE = 11,
319        GDMA_CREATE_QUEUE = 12,
320        GDMA_DISABLE_QUEUE = 13,
321        GDMA_CREATE_DMA_REGION = 25,
322        GDMA_DMA_REGION_ADD_PAGES = 26,
323        GDMA_DESTROY_DMA_REGION = 27,
324        GDMA_CHANGE_MSIX_FOR_EQ = 81,
325    }
326}
327
328#[repr(C)]
329#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
330pub struct GdmaMsgHdr {
331    pub hdr_type: u32,
332    pub msg_type: u32,
333    pub msg_version: u16,
334    pub hwc_msg_id: u16,
335    pub msg_size: u32,
336}
337
338pub const GDMA_STANDARD_HEADER_TYPE: u32 = 0;
339
340pub const GDMA_MESSAGE_V1: u16 = 1;
341
342#[repr(C)]
343#[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq, Eq)]
344pub struct GdmaDevId {
345    pub ty: GdmaDevType,
346    pub instance: u16,
347}
348
349open_enum! {
350    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
351    pub enum GdmaDevType: u16 {
352        GDMA_DEVICE_NONE = 0,
353        GDMA_DEVICE_HWC = 1,
354        GDMA_DEVICE_MANA = 2,
355    }
356}
357
358pub const HWC_DEV_ID: GdmaDevId = GdmaDevId {
359    ty: GdmaDevType::GDMA_DEVICE_HWC,
360    instance: 0,
361};
362
363#[repr(C)]
364#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
365pub struct GdmaReqHdr {
366    pub req: GdmaMsgHdr,
367    pub resp: GdmaMsgHdr,
368    pub dev_id: GdmaDevId,
369    pub activity_id: u32,
370}
371
372#[repr(C)]
373#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
374pub struct GdmaRespHdr {
375    pub response: GdmaMsgHdr,
376    pub dev_id: GdmaDevId,
377    pub activity_id: u32,
378    pub status: u32,
379    pub reserved: u32,
380}
381
382#[repr(C)]
383#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
384pub struct GdmaGenerateTestEventReq {
385    pub queue_index: u32,
386}
387
388#[repr(C)]
389#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
390pub struct HwcTxOob {
391    pub reserved: u64,
392    pub flags1: HwcTxOobFlags1,
393    pub flags2: HwcTxOobFlags2,
394    pub flags3: HwcTxOobFlags3,
395    pub flags4: HwcTxOobFlags4,
396}
397
398#[bitfield(u32)]
399#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
400pub struct HwcTxOobFlags1 {
401    #[bits(24)]
402    pub vrq_id: u32,
403    pub dest_vfid: u8,
404}
405
406#[bitfield(u32)]
407#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
408pub struct HwcTxOobFlags2 {
409    #[bits(24)]
410    pub vrcq_id: u32,
411    pub reserved: u8,
412}
413
414#[bitfield(u32)]
415#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
416pub struct HwcTxOobFlags3 {
417    #[bits(24)]
418    pub vscq_id: u32,
419    pub loopback: bool,
420    pub lso_override: bool,
421    pub dest_pf: bool,
422    #[bits(5)]
423    pub reserved: u8,
424}
425
426#[bitfield(u32)]
427#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
428pub struct HwcTxOobFlags4 {
429    #[bits(24)]
430    pub vsq_id: u32,
431    pub reserved: u8,
432}
433
434#[repr(C)]
435#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
436pub struct HwcRxOob {
437    pub flags: HwcRxOobFlags,
438    pub reserved2: u32,
439    pub wqe_addr_low_or_offset: u32,
440    pub wqe_addr_high: u32,
441    pub client_data_unit: u32,
442    pub tx_oob_data_size: u32,
443    pub chunk_offset: u32,
444}
445
446#[bitfield(u64)]
447#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
448pub struct HwcRxOobFlags {
449    #[bits(6)]
450    pub ty: u8,
451    pub eom: bool,
452    pub som: bool,
453    pub vendor_err: u8,
454    pub reserved1: u16,
455
456    #[bits(24)]
457    pub src_virt_wq: u32,
458    pub src_vfid: u8,
459}
460
461pub const DRIVER_CAP_FLAG_1_HWC_TIMEOUT_RECONFIG: u64 = 0x08;
462pub const DRIVER_CAP_FLAG_1_VARIABLE_INDIRECTION_TABLE_SUPPORT: u64 = 0x20;
463pub const DRIVER_CAP_FLAG_1_HW_VPORT_LINK_AWARE: u64 = 0x40;
464pub const DRIVER_CAP_FLAG_1_SELF_RESET_ON_EQE_NOTIFICATION: u64 = 0x4000;
465pub const DRIVER_CAP_FLAG_1_VTL2_REVOKE_SUB_ON_RESET_EQE: u64 = 0x10000;
466pub const DRIVER_CAP_FLAG_1_VTL2_SELECTIVE_REVOKE_SUB_ON_RESET_EQE: u64 = 0x8000000;
467
468pub const OS_TYPE_OHCL: u32 = 0x60;
469
470#[repr(C)]
471#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
472pub struct GdmaVerifyVerReq {
473    pub protocol_ver_min: u64,
474    pub protocol_ver_max: u64,
475    pub gd_drv_cap_flags1: u64,
476    pub gd_drv_cap_flags2: u64,
477    pub gd_drv_cap_flags3: u64,
478    pub gd_drv_cap_flags4: u64,
479    pub drv_ver: u64,
480    pub os_type: u32,
481    pub reserved: u32,
482    pub os_ver_major: u32,
483    pub os_ver_minor: u32,
484    pub os_ver_build: u32,
485    pub os_ver_platform: u32,
486    pub reserved_2: u64,
487    pub os_ver_str1: [u8; 128],
488    pub os_ver_str2: [u8; 128],
489    pub os_ver_str3: [u8; 128],
490    pub os_ver_str4: [u8; 128],
491}
492
493pub const GDMA_PF_CAP_FLAG_1_QUERY_HWC_TIMEOUT: u64 = 0x08;
494pub const GDMA_PF_CAP_FLAG_1_EQE_REQUEST_VF_SELF_RESET: u64 = 0x80;
495
496#[repr(C)]
497#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
498pub struct GdmaVerifyVerResp {
499    pub gdma_protocol_ver: u64,
500    pub pf_cap_flags1: u64,
501    pub pf_cap_flags2: u64,
502    pub pf_cap_flags3: u64,
503    pub pf_cap_flags4: u64,
504}
505
506#[repr(C)]
507#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
508pub struct GdmaQueryMaxResourcesResp {
509    pub status: u32,
510    pub max_sq: u32,
511    pub max_rq: u32,
512    pub max_cq: u32,
513    pub max_eq: u32,
514    pub max_db: u32,
515    pub max_mst: u32,
516    pub max_cq_mod_ctx: u32,
517    pub max_mod_cq: u32,
518    pub max_msix: u32,
519}
520
521#[repr(C)]
522#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
523pub struct GdmaListDevicesResp {
524    pub num_of_devs: u32,
525    pub reserved: u32,
526    pub devs: [GdmaDevId; 64],
527}
528
529#[repr(C)]
530#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
531pub struct GdmaRegisterDeviceResp {
532    pub pdid: u32,
533    pub gpa_mkey: u32,
534    pub db_id: u32,
535}
536
537#[repr(C)]
538#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
539pub struct GdmaCreateDmaRegionReq {
540    pub length: u64,
541    pub offset_in_page: u32,
542    pub gdma_page_type: u32,
543    pub page_count: u32,
544    pub page_addr_list_len: u32,
545    // Followed by u64 page list.
546}
547
548pub const GDMA_PAGE_TYPE_4K: u32 = 0;
549
550#[repr(C)]
551#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
552pub struct GdmaCreateDmaRegionResp {
553    pub gdma_region: u64,
554}
555
556#[repr(C)]
557#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
558pub struct GdmaDestroyDmaRegionReq {
559    pub gdma_region: u64,
560}
561
562#[repr(C)]
563#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
564pub struct GdmaCreateQueueReq {
565    pub queue_type: GdmaQueueType,
566    pub reserved1: u32,
567    pub pdid: u32,
568    pub doorbell_id: u32,
569    pub gdma_region: u64,
570    pub reserved2: u32,
571    pub queue_size: u32,
572    pub log2_throttle_limit: u32,
573    pub eq_pci_msix_index: u32,
574    pub cq_mod_ctx_id: u32,
575    pub cq_parent_eq_id: u32,
576    pub rq_drop_on_overrun: u8,
577    pub rq_err_on_wqe_overflow: u8,
578    pub rq_chain_rec_wqes: u8,
579    pub sq_hw_db: u8,
580    pub reserved3: u32,
581}
582
583open_enum! {
584    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
585    pub enum GdmaQueueType: u32 {
586        GDMA_SQ = 1,
587        GDMA_RQ = 2,
588        GDMA_CQ = 3,
589        GDMA_EQ = 4,
590    }
591}
592
593#[repr(C)]
594#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
595pub struct GdmaCreateQueueResp {
596    pub queue_index: u32,
597}
598
599#[repr(C)]
600#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
601pub struct GdmaDisableQueueReq {
602    pub queue_type: GdmaQueueType,
603    pub queue_index: u32,
604    pub alloc_res_id_on_creation: u32,
605}
606
607#[repr(C)]
608#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
609pub struct GdmaChangeMsixVectorIndexForEq {
610    pub queue_index: u32,
611    pub msix: u32,
612    pub reserved1: u32,
613    pub reserved2: u32,
614}
615
616#[repr(C)]
617#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
618pub struct GdmaGenerateResetEventReq {
619    pub queue_index: u32,
620    pub data: EqeVfReset,
621}