1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
|
/**
* @file
*
* Routines for IOMMU.
*
* Implement the IOMMU init and ACPI feature.
*
* @xrefitem bom "File Content Label" "Release Content"
* @e project: CIMx-NB
* @e sub-project:
* @e \$Revision:$ @e \$Date:$
*
*/
/*****************************************************************************
*
* Copyright (C) 2012 Advanced Micro Devices, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Advanced Micro Devices, Inc. nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
***************************************************************************/
// Identifying an IOMMU:
// RD890S - IOMMU present
// all other (including RD890) - IOMMU not present
// Class = System Base Peripheral (08h)
// Subclass = IOMMU (06h)
// Programming Interface Code = 0h
// Must reside on top/root complex PCI hierarchy
// There is always a NB device at bus 0 device 0 function 0 (fcn 2 for IOMMU) - device ID 0x5A23
// Inputs:
// From OEM: Get exclusion table
// From OEM: Get text buffer
// Outputs:
// To OEM: Complete IVRS table for linking
#ifndef _NBIOMMU_H_
#define _NBIOMMU_H_
/*----------------------------------------------------------------------------------------
* E X P O R T E D F U N C T I O N S
*----------------------------------------------------------------------------------------
*/
AGESA_STATUS
NbIommuInit (
IN OUT AMD_NB_CONFIG_BLOCK *ConfigPtr
);
AGESA_STATUS
NbIommuInitS3 (
IN OUT AMD_NB_CONFIG_BLOCK *ConfigPtr
);
AGESA_STATUS
NbIommuAcpiInit (
IN OUT AMD_NB_CONFIG_BLOCK *ConfigPtr
);
AGESA_STATUS
NbIommuAcpiFixup (
IN OUT AMD_NB_CONFIG_BLOCK *ConfigPtr
);
VOID
NbIommuDisconnectPcieCore (
IN CORE CoreId,
IN AMD_NB_CONFIG *pConfig
);
/*----------------------------------------------------------------------------------------
* D E F I N I T I O N S A N D M A C R O S
*----------------------------------------------------------------------------------------
*/
// IOMMU Architectural
#define IVRS_BUFFER_SIZE 0x2000 // Default 8KB allocated to table
//#define IVHD_MIN_8BYTE_ALIGNMENT // Align IVHD entries on 8 byte boundary
#define IVHD_SIZE_ALIGNMENT // Align IVHD entries on MOD entry-size boundary
#define IVHD_HPET_SUPPORT // Create HPET entries
#define IVHD_APIC_SUPPORT // Create IOAPIC entries
// IOMMU Northbridge
#define RD890S_CAP_MISC 0x50 // RD890/S Capabilities Misc Info
#define NB_PCI_DEV 0 // PCI NB device number
#define NB_HOST 0 // Function 0 = NB HOST
#define NB_IOMMU 2 // Function 2 = IOMMU
#define SB_DEV 0x14 // PCI SB device number
#define SB_SMBUS 3 // Function 3 = SMBUS
#define SB_SATA 0x11 // SB SATA
#define SATA_ENABLE_REG 0xAD // Dev. 0x14, Func 0, Reg 0xAD for SATA combined mode
#define SATA_COMBINED_MODE BIT3 // Bit 3 of SB_ENABLE_REG., 1 = Combined mode
#define IOMMU_CAP_HEADER_OFFSET 0x00
#define IOMMU_BASE_LOW_OFFSET 0x04
#define IOMMU_BASE_HIGH_OFFSET 0x08
#define IOMMU_RANGE_OFFSET 0x0C
#define IOMMU_MISC_OFFSET 0x10
#define DEVICEID_NB ((0 << 8) + (NB_PCI_DEV << 3) + NB_HOST)
#define DEVICEID_IOMMU ((0 << 8) + (NB_PCI_DEV << 3) + NB_IOMMU)
#define DEVICEID_GPP1_0 ((0 << 8) + (0x2 << 3) + 0)
#define DEVICEID_GPP1_1 ((0 << 8) + (0x3 << 3) + 0)
#define DEVICEID_GPP2_0 ((0 << 8) + (0xB << 3) + 0)
#define DEVICEID_GPP2_1 ((0 << 8) + (0xC << 3) + 0)
#define DEVICEID_GPP3A_0 ((0 << 8) + (0x4 << 3) + 0)
#define DEVICEID_GPP3A_1 ((0 << 8) + (0x5 << 3) + 0)
#define DEVICEID_GPP3A_2 ((0 << 8) + (0x6 << 3) + 0)
#define DEVICEID_GPP3A_3 ((0 << 8) + (0x7 << 3) + 0)
#define DEVICEID_GPP3A_4 ((0 << 8) + (0x9 << 3) + 0)
#define DEVICEID_GPP3A_5 ((0 << 8) + (0xA << 3) + 0)
#define DEVICEID_GPP3B_0 ((0 << 8) + (0xD << 3) + 0)
#define DEVICEID_SATA ((0 << 8) + (0x11 << 3) + 0)
#define DEVICEID_IDE ((0 << 8) + (0x14 << 3) + 1)
#define L1CFG_INDEX 0xF8
// There is an L1 for each device (6), which is selected by [19:16] of L1CFG_INDEX
// e.g. (LibNbPciIndexRead (Address | L1CFGIND, L1_REG_0C | L1_CFG_SEL, AccessWidth32, &Value, pConfig)
#define L1CFG_SEL_WR_EN 0x80000000
#define L1CFG_SEL_GPP1 0x00000000
#define L1CFG_SEL_GPP2 0x00010000
#define L1CFG_SEL_SB 0x00020000
#define L1CFG_SEL_GPP3A 0x00030000
#define L1CFG_SEL_GPP3B 0x00040000
#define L1CFG_SEL_VC1 0x00050000
#define L1REG_06 0x6
#define L1REG_0C 0xC
#define L1REG_0D 0xD
#define L1REG_07 0x7
#define L1CFG_DATA 0xFC
#define L2CFG_INDEX 0xF0
// e.g. (LibNbPciIndexRead (Address | L2CFGIND, L2_REG_0C, AccessWidth16, &Value, pConfig)
#define L2CFG_SEL_WR_EN 0x100
#define L2REG_06 0x6
#define L2REG_07 0x7
#define L2REG_0C 0xC
#define L2REG_10 0x10
#define L2REG_11 0x11
#define L2REG_14 0x14
#define L2REG_15 0x15
#define L2REG_18 0x18
#define L2REG_19 0x19
#define L2REG_1C 0x1C
#define L2REG_1D 0x1D
#define L2REG_46 0x46
#define L2REG_47 0x47
#define L2REG_50 0x50
#define L2REG_51 0x51
#define L2REG_52 0x52
#define L2REG_56 0x56
#define L2REG_30 0x30
#define L2REG_80 0x80
#define L2CFG_DATA 0xF4
// PCI/PCIe Architectural
#define PCIE_CAPID 0x10
#define PCIE_PORTMASK 0xF0 // Device cap reg 2
#define PCIE_PCIE2PCIX 0x70 // Device cap reg 2
#define PCIE_PHANTOMMASK 0x18 // Device cap reg 4
#define PCIX_CAPID 0x07
#define IOMMU_CAPID 0x0F
#define PCI_DVID 0x00
#define PCI_INVALID 0xFFFFFFFF
#define PCI_CLASS 0x08
#define PCI_HEADER 0x0C
#define PCI_MULTIFUNCTION 0x00800000
#define PCI_BUS 0x18
#define PCI_SUBMASK 0xFF0000
#define PCI_SECMASK 0xFF00
#define PCI_PRIMASK 0xFF
#define PCI_BRIDGE_CLASS 0x0604
// IVRS Table Access
#define TYPE_IVHD 0x10
#define IVINFO_ATSMASK 0x00400000 // [22] = ATS
#define IVINFO_VAMASK 0x003F8000 // [21:15] = Virtual Address Size
#define IVINFO_PAMASK 0x00007F00 // [14:8] = Physical Address Size
#define FLAGS_COHERENT BIT5
#define FLAGS_IOTLBSUP BIT4
#define FLAGS_ISOC BIT3
#define FLAGS_RESPASSPW BIT2
#define FLAGS_PASSPW BIT1
#define TYPE_IVMD_ALL 0x20
#define TYPE_IVMD_SELECT 0x21
#define TYPE_IVMD_RANGE 0x22
#define DE_PAD4 1
#define DE_BYTE0 0
#define DE_BYTE1 1
#define DE_BYTE2 2
#define DE_BYTE3 3
#define DE_SELECT 2
#define DATA_NOINTS 0
#define DATA_LINT_EINT_INIT BIT7 + BIT6 + BIT1 + BIT0
#define DATA_ALLINTS 0xD7
#define DE_START 3
#define DE_END 4
#define DE_PAD8 64
#define DE_BYTE4 4
#define DE_BYTE5 5
#define DE_BYTE6 6
#define DE_BYTE7 7
#define DE_ALIASSELECT 66
#define DE_ALIASSTART 67
#define DE_SPECIAL 72
#define VARIETY_IOAPIC 0x1
#define VARIETY_HPET 0x2
#define DE_SPECIAL_VARIETY 7
#define DE_DEVICEID 5
#define DE_SPECIAL_ID 4
// MADT Table Access
#define MADT_APIC_TYPE 0x1
#define MADT_APIC_ID 0x2
#define MADT_APIC_BASE 0x4
/*----------------------------------------------------------------------------------------
* T Y P E D E F S A N D S T R U C T U R E S
*----------------------------------------------------------------------------------------
*/
#pragma pack (push, 1)
/// IVRS header
typedef struct {
UINT32 Signature; ///< see IOMMU specification for details
UINT32 Length; ///< see IOMMU specification for details
UINT8 Revision; ///< see IOMMU specification for details
UINT8 Checksum; ///< see IOMMU specification for details
CHAR8 OemId[6]; ///< see IOMMU specification for details
CHAR8 OemTableId[8]; ///< see IOMMU specification for details
CHAR8 OemRevision[4]; ///< see IOMMU specification for details
CHAR8 CreatorId[4]; ///< see IOMMU specification for details
CHAR8 CreatorRevision[4]; ///< see IOMMU specification for details
UINT32 IvInfo; ///< see IOMMU specification for details
UINT64 Reserved; ///< see IOMMU specification for details
} IOMMU_IVRS_HEADER;
/// DeviceID
typedef struct {
UINT16 TableLength; ///< length of table
UINT16 Device[]; ///< DeviceID
} IOMMU_DEVICELIST;
/// PCI Topology Based Settings
typedef struct {
// BOOLEAN PhantomFunction; ///< phantom functions present
UINT8 MaxBus; ///< max bus accumulator
UINT8 MaxDevice; ///< max device accumulator
UINT16 MaxFunction; ///< max function accumulator
} IOMMU_PCI_TOPOLOGY;
/// IVHD for each hardware definition (i.e. # of northbridges)
typedef struct {
UINT8 Type; ///< see IOMMU specification for details
UINT8 Flags; ///< see IOMMU specification for details
UINT16 Length; ///< see IOMMU specification for details
UINT16 DeviceId; ///< see IOMMU specification for details
UINT16 CapabilityOffset; ///< see IOMMU specification for details
UINT64 BaseAddress; ///< see IOMMU specification for details
UINT16 PciSegment; ///< see IOMMU specification for details
UINT16 IommuInfo; ///< see IOMMU specification for details
UINT32 Reserved; ///< see IOMMU specification for details
UINT32 DeviceEntry[]; ///< see IOMMU specification for details
} IOMMU_IVHD_ENTRY;
/// IVMD for each memory range
typedef struct {
UINT8 Type; ///< see IOMMU specification for details
UINT8 Flags; ///< see IOMMU specification for details
UINT16 Length; ///< see IOMMU specification for details
UINT16 DeviceId; ///< see IOMMU specification for details
UINT16 AuxData; ///< see IOMMU specification for details
UINT64 Reserved; ///< see IOMMU specification for details
UINT64 BlockStartAddress; ///< see IOMMU specification for details
UINT64 BlockLength; ///< see IOMMU specification for details
} IOMMU_IVMD_ENTRY;
//#define IVRS_HANDLE 'SRVI'
#define IVRS_HANDLE Int32FromChar ('S', 'R', 'V', 'I')
#define L2_DTC_CONTROL 0x10
#define L2_ITC_CONTROL 0x14
#define L2_PTC_A_CONTROL 0x18
#define L2_PTC_B_CONTROL 0x1C
#define L2_PDC_CONTROL 0x50
#define EXCLUDE_SB_DEVICE_FROM_L2_HASH
/// L2 cache init
typedef struct {
UINT8 HashControl; ///<Control regsiter block address
} L2_HASH_CONTROL;
#pragma pack (pop)
#endif
|