VirtualBox

source: vbox/trunk/src/VBox/Devices/Bus/DevIommuIntel.cpp@ 88164

Last change on this file since 88164 was 88153, checked in by vboxsync, 4 years ago

Intel IOMMU: bugref:9967 Skeleton bits.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.7 KB
Line 
1/* $Id: DevIommuIntel.cpp 88153 2021-03-17 12:56:48Z vboxsync $ */
2/** @file
3 * IOMMU - Input/Output Memory Management Unit - Intel implementation.
4 */
5
6/*
7 * Copyright (C) 2021 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_DEV_IOMMU
23#include <VBox/vmm/pdmdev.h>
24#include <VBox/iommu-intel.h>
25
26#include <iprt/string.h>
27
28#include "VBoxDD.h"
29
30
31/*********************************************************************************************************************************
32* Defined Constants And Macros *
33*********************************************************************************************************************************/
34/** Release log prefix string. */
35#define IOMMU_LOG_PFX "Intel-IOMMU"
36/** The current saved state version. */
37#define IOMMU_SAVED_STATE_VERSION 1
38/** The IOMMU device instance magic. */
39#define IOMMU_MAGIC 0x10acce55
40
41
42/**
43 * The shared IOMMU device state.
44 */
45typedef struct IOMMU
46{
47 /** IOMMU device index (0 is at the top of the PCI tree hierarchy). */
48 uint32_t idxIommu;
49 /** IOMMU magic. */
50 uint32_t u32Magic;
51
52 /** The MMIO handle. */
53 IOMMMIOHANDLE hMmio;
54} IOMMU;
55/** Pointer to the IOMMU device state. */
56typedef IOMMU *PIOMMU;
57/** Pointer to the const IOMMU device state. */
58typedef const IOMMU *PCIOMMU;
59
60/**
61 * The ring-3 IOMMU device state.
62 */
63typedef struct IOMMUR3
64{
65 /** Device instance. */
66 PPDMDEVINSR3 pDevInsR3;
67 /** The IOMMU helper. */
68 R3PTRTYPE(PCPDMIOMMUHLPR3) pIommuHlpR3;
69} IOMMUR3;
70/** Pointer to the ring-3 IOMMU device state. */
71typedef IOMMUR3 *PIOMMUR3;
72/** Pointer to the const ring-3 IOMMU device state. */
73typedef const IOMMUR3 *PCIOMMUR3;
74
75/**
76 * The ring-0 IOMMU device state.
77 */
78typedef struct IOMMUR0
79{
80 /** Device instance. */
81 PPDMDEVINSR0 pDevInsR0;
82 /** The IOMMU helper. */
83 R0PTRTYPE(PCPDMIOMMUHLPR0) pIommuHlpR0;
84} IOMMUR0;
85/** Pointer to the ring-0 IOMMU device state. */
86typedef IOMMUR0 *PIOMMUR0;
87/** Pointer to the const ring-0 IOMMU device state. */
88typedef const IOMMUR0 *PCIOMMUR0;
89
90/**
91 * The raw-mode IOMMU device state.
92 */
93typedef struct IOMMURC
94{
95 /** Device instance. */
96 PPDMDEVINSRC pDevInsRC;
97 /** The IOMMU helper. */
98 RCPTRTYPE(PCPDMIOMMUHLPRC) pIommuHlpRC;
99} IOMMURC;
100/** Pointer to the raw-mode IOMMU device state. */
101typedef IOMMURC *PIOMMURC;
102/** Pointer to the const raw-mode IOMMU device state. */
103typedef const IOMMURC *CPIOMMURC;
104
105/** The IOMMU device state for the current context. */
106typedef CTX_SUFF(IOMMU) IOMMUCC;
107/** Pointer to the IOMMU device state for the current context. */
108typedef CTX_SUFF(PIOMMU) PIOMMUCC;
109
110
111#ifndef VBOX_DEVICE_STRUCT_TESTCASE
112
113/**
114 * Memory access bulk (one or more 4K pages) request from a device.
115 *
116 * @returns VBox status code.
117 * @param pDevIns The IOMMU device instance.
118 * @param idDevice The device ID (bus, device, function).
119 * @param cIovas The number of addresses being accessed.
120 * @param pauIovas The I/O virtual addresses for each page being accessed.
121 * @param fFlags The access flags, see PDMIOMMU_MEM_F_XXX.
122 * @param paGCPhysSpa Where to store the translated physical addresses.
123 *
124 * @thread Any.
125 */
126static DECLCALLBACK(int) iommuIntelMemBulkAccess(PPDMDEVINS pDevIns, uint16_t idDevice, size_t cIovas, uint64_t const *pauIovas,
127 uint32_t fFlags, PRTGCPHYS paGCPhysSpa)
128{
129 RT_NOREF6(pDevIns, idDevice, cIovas, pauIovas, fFlags, paGCPhysSpa);
130 return VERR_NOT_IMPLEMENTED;
131}
132
133
134/**
135 * Memory access transaction from a device.
136 *
137 * @returns VBox status code.
138 * @param pDevIns The IOMMU device instance.
139 * @param idDevice The device ID (bus, device, function).
140 * @param uIova The I/O virtual address being accessed.
141 * @param cbIova The size of the access.
142 * @param fFlags The access flags, see PDMIOMMU_MEM_F_XXX.
143 * @param pGCPhysSpa Where to store the translated system physical address.
144 * @param pcbContiguous Where to store the number of contiguous bytes translated
145 * and permission-checked.
146 *
147 * @thread Any.
148 */
149static DECLCALLBACK(int) iommuIntelMemAccess(PPDMDEVINS pDevIns, uint16_t idDevice, uint64_t uIova, size_t cbIova,
150 uint32_t fFlags, PRTGCPHYS pGCPhysSpa, size_t *pcbContiguous)
151{
152 RT_NOREF7(pDevIns, idDevice, uIova, cbIova, fFlags, pGCPhysSpa, pcbContiguous);
153 return VERR_NOT_IMPLEMENTED;
154}
155
156
157/**
158 * Interrupt remap request from a device.
159 *
160 * @returns VBox status code.
161 * @param pDevIns The IOMMU device instance.
162 * @param idDevice The device ID (bus, device, function).
163 * @param pMsiIn The source MSI.
164 * @param pMsiOut Where to store the remapped MSI.
165 */
166static DECLCALLBACK(int) iommuIntelMsiRemap(PPDMDEVINS pDevIns, uint16_t idDevice, PCMSIMSG pMsiIn, PMSIMSG pMsiOut)
167{
168 RT_NOREF4(pDevIns, idDevice, pMsiIn, pMsiOut);
169 return VERR_NOT_IMPLEMENTED;
170}
171
172
173/**
174 * @callback_method_impl{FNIOMMMIONEWWRITE}
175 */
176static DECLCALLBACK(VBOXSTRICTRC) iommuIntelMmioWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void const *pv, unsigned cb)
177{
178 RT_NOREF5(pDevIns, pvUser, off, pv, cb);
179 return VERR_NOT_IMPLEMENTED;
180}
181
182
183/**
184 * @callback_method_impl{FNIOMMMIONEWREAD}
185 */
186static DECLCALLBACK(VBOXSTRICTRC) iommuIntelMmioRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void *pv, unsigned cb)
187{
188 RT_NOREF5(pDevIns, pvUser, off, pv, cb);
189 return VERR_NOT_IMPLEMENTED;
190}
191
192
193#ifdef IN_RING3
194/**
195 * @interface_method_impl{PDMDEVREG,pfnReset}
196 */
197static DECLCALLBACK(void) iommuIntelR3Reset(PPDMDEVINS pDevIns)
198{
199 RT_NOREF1(pDevIns);
200}
201
202
203/**
204 * @interface_method_impl{PDMDEVREG,pfnDestruct}
205 */
206static DECLCALLBACK(int) iommuIntelR3Destruct(PPDMDEVINS pDevIns)
207{
208 RT_NOREF(pDevIns);
209 return VERR_NOT_IMPLEMENTED;
210}
211
212
213/**
214 * @interface_method_impl{PDMDEVREG,pfnConstruct}
215 */
216static DECLCALLBACK(int) iommuIntelR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
217{
218 RT_NOREF3(pDevIns, iInstance, pCfg);
219 return VERR_NOT_IMPLEMENTED;
220}
221
222#else
223
224/**
225 * @callback_method_impl{PDMDEVREGR0,pfnConstruct}
226 */
227static DECLCALLBACK(int) iommuIntelRZConstruct(PPDMDEVINS pDevIns)
228{
229 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
230 PIOMMU pThis = PDMDEVINS_2_DATA(pDevIns, PIOMMU);
231 PIOMMUCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PIOMMUCC);
232 pThisCC->CTX_SUFF(pDevIns) = pDevIns;
233
234 /* We will use PDM's critical section (via helpers) for the IOMMU device. */
235 int rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
236 AssertRCReturn(rc, rc);
237
238 /* Set up the MMIO RZ handlers. */
239 rc = PDMDevHlpMmioSetUpContext(pDevIns, pThis->hMmio, iommuIntelMmioWrite, iommuIntelMmioRead, NULL /* pvUser */);
240 AssertRCReturn(rc, rc);
241
242 /* Set up the IOMMU RZ callbacks. */
243 PDMIOMMUREGCC IommuReg;
244 RT_ZERO(IommuReg);
245 IommuReg.u32Version = PDM_IOMMUREGCC_VERSION;
246 IommuReg.idxIommu = pThis->idxIommu;
247 IommuReg.pfnMemAccess = iommuIntelMemAccess;
248 IommuReg.pfnMemBulkAccess = iommuIntelMemBulkAccess;
249 IommuReg.pfnMsiRemap = iommuIntelMsiRemap;
250 IommuReg.u32TheEnd = PDM_IOMMUREGCC_VERSION;
251 rc = PDMDevHlpIommuSetUpContext(pDevIns, &IommuReg, &pThisCC->CTX_SUFF(pIommuHlp));
252 AssertRCReturn(rc, rc);
253 AssertPtrReturn(pThisCC->CTX_SUFF(pIommuHlp), VERR_IOMMU_IPE_1);
254 AssertReturn(pThisCC->CTX_SUFF(pIommuHlp)->u32Version == CTX_SUFF(PDM_IOMMUHLP)_VERSION, VERR_VERSION_MISMATCH);
255 AssertReturn(pThisCC->CTX_SUFF(pIommuHlp)->u32TheEnd == CTX_SUFF(PDM_IOMMUHLP)_VERSION, VERR_VERSION_MISMATCH);
256 AssertPtrReturn(pThisCC->CTX_SUFF(pIommuHlp)->pfnLock, VERR_INVALID_POINTER);
257 AssertPtrReturn(pThisCC->CTX_SUFF(pIommuHlp)->pfnUnlock, VERR_INVALID_POINTER);
258 return VINF_SUCCESS;
259}
260
261#endif
262
263
264/**
265 * The device registration structure.
266 */
267const PDMDEVREG g_DeviceIommuIntel =
268{
269 /* .u32Version = */ PDM_DEVREG_VERSION,
270 /* .uReserved0 = */ 0,
271 /* .szName = */ "iommu-intel",
272 /* .fFlags = */ PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RZ | PDM_DEVREG_FLAGS_NEW_STYLE,
273 /* .fClass = */ PDM_DEVREG_CLASS_PCI_BUILTIN,
274 /* .cMaxInstances = */ ~0U,
275 /* .uSharedVersion = */ 42,
276 /* .cbInstanceShared = */ sizeof(IOMMU),
277 /* .cbInstanceCC = */ sizeof(IOMMUCC),
278 /* .cbInstanceRC = */ sizeof(IOMMURC),
279 /* .cMaxPciDevices = */ 1,
280 /* .cMaxMsixVectors = */ 0,
281 /* .pszDescription = */ "IOMMU (Intel)",
282#if defined(IN_RING3)
283 /* .pszRCMod = */ "VBoxDDRC.rc",
284 /* .pszR0Mod = */ "VBoxDDR0.r0",
285 /* .pfnConstruct = */ iommuIntelR3Construct,
286 /* .pfnDestruct = */ iommuIntelR3Destruct,
287 /* .pfnRelocate = */ NULL,
288 /* .pfnMemSetup = */ NULL,
289 /* .pfnPowerOn = */ NULL,
290 /* .pfnReset = */ iommuIntelR3Reset,
291 /* .pfnSuspend = */ NULL,
292 /* .pfnResume = */ NULL,
293 /* .pfnAttach = */ NULL,
294 /* .pfnDetach = */ NULL,
295 /* .pfnQueryInterface = */ NULL,
296 /* .pfnInitComplete = */ NULL,
297 /* .pfnPowerOff = */ NULL,
298 /* .pfnSoftReset = */ NULL,
299 /* .pfnReserved0 = */ NULL,
300 /* .pfnReserved1 = */ NULL,
301 /* .pfnReserved2 = */ NULL,
302 /* .pfnReserved3 = */ NULL,
303 /* .pfnReserved4 = */ NULL,
304 /* .pfnReserved5 = */ NULL,
305 /* .pfnReserved6 = */ NULL,
306 /* .pfnReserved7 = */ NULL,
307#elif defined(IN_RING0)
308 /* .pfnEarlyConstruct = */ NULL,
309 /* .pfnConstruct = */ iommuIntelRZConstruct,
310 /* .pfnDestruct = */ NULL,
311 /* .pfnFinalDestruct = */ NULL,
312 /* .pfnRequest = */ NULL,
313 /* .pfnReserved0 = */ NULL,
314 /* .pfnReserved1 = */ NULL,
315 /* .pfnReserved2 = */ NULL,
316 /* .pfnReserved3 = */ NULL,
317 /* .pfnReserved4 = */ NULL,
318 /* .pfnReserved5 = */ NULL,
319 /* .pfnReserved6 = */ NULL,
320 /* .pfnReserved7 = */ NULL,
321#elif defined(IN_RC)
322 /* .pfnConstruct = */ iommuIntelRZConstruct,
323 /* .pfnReserved0 = */ NULL,
324 /* .pfnReserved1 = */ NULL,
325 /* .pfnReserved2 = */ NULL,
326 /* .pfnReserved3 = */ NULL,
327 /* .pfnReserved4 = */ NULL,
328 /* .pfnReserved5 = */ NULL,
329 /* .pfnReserved6 = */ NULL,
330 /* .pfnReserved7 = */ NULL,
331#else
332# error "Not in IN_RING3, IN_RING0 or IN_RC!"
333#endif
334 /* .u32VersionEnd = */ PDM_DEVREG_VERSION
335};
336
337#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
338
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette