View | Details | Raw Unified | Return to bug 229852
Collapse All | Expand All

(-)./vtd-fix.c (-18 / +104 lines)
Lines 49-54 Link Here
49
 * Architecture Spec, September 2008.
49
 * Architecture Spec, September 2008.
50
 */
50
 */
51
51
52
#define VTD_DRHD_INCLUDE_PCI_ALL(Flags)  (((Flags) >> 0) & 0x1)
53
52
/* Section 10.4 "Register Descriptions" */
54
/* Section 10.4 "Register Descriptions" */
53
struct vtdmap {
55
struct vtdmap {
54
	volatile uint32_t	version;
56
	volatile uint32_t	version;
Lines 114-123 Link Here
114
static SLIST_HEAD(, domain) domhead;
116
static SLIST_HEAD(, domain) domhead;
115
117
116
#define	DRHD_MAX_UNITS	8
118
#define	DRHD_MAX_UNITS	8
117
static int		drhd_num;
119
static ACPI_DMAR_HARDWARE_UNIT	*drhds[DRHD_MAX_UNITS];
118
static struct vtdmap	*vtdmaps[DRHD_MAX_UNITS];
120
static int			drhd_num;
119
static int		max_domains;
121
static struct vtdmap		*vtdmaps[DRHD_MAX_UNITS];
120
typedef int		(*drhd_ident_func_t)(void);
122
static int			max_domains;
123
typedef int			(*drhd_ident_func_t)(void);
121
124
122
static uint64_t root_table[PAGE_SIZE / sizeof(uint64_t)] __aligned(4096);
125
static uint64_t root_table[PAGE_SIZE / sizeof(uint64_t)] __aligned(4096);
123
static uint64_t ctx_tables[256][PAGE_SIZE / sizeof(uint64_t)] __aligned(4096);
126
static uint64_t ctx_tables[256][PAGE_SIZE / sizeof(uint64_t)] __aligned(4096);
Lines 173-178 Link Here
173
	return (id);
176
	return (id);
174
}
177
}
175
178
179
static struct vtdmap *
180
vtd_device_scope(uint16_t rid)
181
{
182
	int i, remaining, pathremaining;
183
	char *end, *pathend;
184
	struct vtdmap *vtdmap;
185
	ACPI_DMAR_HARDWARE_UNIT *drhd;
186
	ACPI_DMAR_DEVICE_SCOPE *device_scope;
187
	ACPI_DMAR_PCI_PATH *path;
188
189
	for (i = 0; i < drhd_num; i++) {
190
		drhd = drhds[i];
191
192
		if (VTD_DRHD_INCLUDE_PCI_ALL(drhd->Flags)) {
193
			/*
194
			 * From Intel VT-d arch spec, version 3.0:
195
			 * If a DRHD structure with INCLUDE_PCI_ALL flag Set is reported
196
			 * for a Segment, it must be enumerated by BIOS after all other
197
			 * DRHD structures for the same Segment.
198
			 */
199
			vtdmap = vtdmaps[i];
200
			return(vtdmap);
201
		}
202
203
		end = (char *)drhd + drhd->Header.Length;
204
		remaining = drhd->Header.Length - sizeof(ACPI_DMAR_HARDWARE_UNIT);
205
		while (remaining > sizeof(ACPI_DMAR_DEVICE_SCOPE)) {
206
			device_scope = (ACPI_DMAR_DEVICE_SCOPE *)(end - remaining);
207
			remaining -= device_scope->Length;
208
209
			switch (device_scope->EntryType){
210
				/* 0x01 and 0x02 are PCI device entries */
211
				case 0x01:
212
				case 0x02:
213
					break;
214
				default:
215
					continue;
216
			}
217
218
			if (PCI_RID2BUS(rid) != device_scope->Bus)
219
				continue;
220
221
			pathend = (char *)device_scope + device_scope->Length;
222
			pathremaining = device_scope->Length - sizeof(ACPI_DMAR_DEVICE_SCOPE);
223
			while (pathremaining >= sizeof(ACPI_DMAR_PCI_PATH)) {
224
				path = (ACPI_DMAR_PCI_PATH *)(pathend - pathremaining);
225
				pathremaining -= sizeof(ACPI_DMAR_PCI_PATH);
226
227
				if (PCI_RID2SLOT(rid) != path->Device)
228
					continue;
229
				if (PCI_RID2FUNC(rid) != path->Function)
230
					continue;
231
232
				vtdmap = vtdmaps[i];
233
				return (vtdmap);
234
			}
235
		}
236
	}
237
238
	/* No matching scope */
239
	return (NULL);
240
}
241
176
static void
242
static void
177
vtd_wbflush(struct vtdmap *vtdmap)
243
vtd_wbflush(struct vtdmap *vtdmap)
178
{
244
{
Lines 238-244 Link Here
238
static int
304
static int
239
vtd_init(void)
305
vtd_init(void)
240
{
306
{
241
	int i, units, remaining;
307
	int i, units, remaining, tmp;
242
	struct vtdmap *vtdmap;
308
	struct vtdmap *vtdmap;
243
	vm_paddr_t ctx_paddr;
309
	vm_paddr_t ctx_paddr;
244
	char *end, envname[32];
310
	char *end, envname[32];
Lines 289-296 Link Here
289
			break;
355
			break;
290
356
291
		drhd = (ACPI_DMAR_HARDWARE_UNIT *)hdr;
357
		drhd = (ACPI_DMAR_HARDWARE_UNIT *)hdr;
292
		vtdmaps[units++] = (struct vtdmap *)PHYS_TO_DMAP(drhd->Address);
358
		drhds[units] = drhd;
293
		if (units >= DRHD_MAX_UNITS)
359
		vtdmaps[units] = (struct vtdmap *)PHYS_TO_DMAP(drhd->Address);
360
		if (++units >= DRHD_MAX_UNITS)
294
			break;
361
			break;
295
		remaining -= hdr->Length;
362
		remaining -= hdr->Length;
296
	}
363
	}
Lines 300-311 Link Here
300
367
301
skip_dmar:
368
skip_dmar:
302
	drhd_num = units;
369
	drhd_num = units;
303
	vtdmap = vtdmaps[0];
304
370
305
	if (VTD_CAP_CM(vtdmap->cap) != 0)
371
	max_domains = 64 * 1024; /* maximum valid value */
306
		panic("vtd_init: invalid caching mode");
372
	for (i = 0; i < drhd_num; i++){
373
		vtdmap = vtdmaps[i];
374
375
		if (VTD_CAP_CM(vtdmap->cap) != 0)
376
			panic("vtd_init: invalid caching mode");
307
377
308
	max_domains = vtd_max_domains(vtdmap);
378
		/* take most compatible (minimum) value */
379
		if ((tmp = vtd_max_domains(vtdmap)) < max_domains)
380
			max_domains = tmp;
381
	}
309
382
310
	/*
383
	/*
311
	 * Set up the root-table to point to the context-entry tables
384
	 * Set up the root-table to point to the context-entry tables
Lines 371-377 Link Here
371
	struct vtdmap *vtdmap;
444
	struct vtdmap *vtdmap;
372
	uint8_t bus;
445
	uint8_t bus;
373
446
374
	vtdmap = vtdmaps[0];
375
	bus = PCI_RID2BUS(rid);
447
	bus = PCI_RID2BUS(rid);
376
	ctxp = ctx_tables[bus];
448
	ctxp = ctx_tables[bus];
377
	pt_paddr = vtophys(dom->ptp);
449
	pt_paddr = vtophys(dom->ptp);
Lines 383-388 Link Here
383
		      (uint16_t)(ctxp[idx + 1] >> 8));
455
		      (uint16_t)(ctxp[idx + 1] >> 8));
384
	}
456
	}
385
457
458
	if ((vtdmap = vtd_device_scope(rid)) == NULL)
459
		panic("vtd_add_device: device %x is not in scope for "
460
		      "any DMA remapping unit", rid);
461
386
	/*
462
	/*
387
	 * Order is important. The 'present' bit is set only after all fields
463
	 * Order is important. The 'present' bit is set only after all fields
388
	 * of the context pointer are initialized.
464
	 * of the context pointer are initialized.
Lines 566-573 Link Here
566
	if (drhd_num <= 0)
642
	if (drhd_num <= 0)
567
		panic("vtd_create_domain: no dma remapping hardware available");
643
		panic("vtd_create_domain: no dma remapping hardware available");
568
644
569
	vtdmap = vtdmaps[0];
570
571
	/*
645
	/*
572
	 * Calculate AGAW.
646
	 * Calculate AGAW.
573
	 * Section 3.4.2 "Adjusted Guest Address Width", Architecture Spec.
647
	 * Section 3.4.2 "Adjusted Guest Address Width", Architecture Spec.
Lines 592-598 Link Here
592
	pt_levels = 2;
666
	pt_levels = 2;
593
	sagaw = 30;
667
	sagaw = 30;
594
	addrwidth = 0;
668
	addrwidth = 0;
595
	tmp = VTD_CAP_SAGAW(vtdmap->cap);
669
670
	tmp = ~0;
671
	for (i = 0; i < drhd_num; i++) {
672
		vtdmap = vtdmaps[i];
673
		/* take most compatible value */
674
		tmp &= VTD_CAP_SAGAW(vtdmap->cap);
675
	}
676
596
	for (i = 0; i < 5; i++) {
677
	for (i = 0; i < 5; i++) {
597
		if ((tmp & (1 << i)) != 0 && sagaw >= agaw)
678
		if ((tmp & (1 << i)) != 0 && sagaw >= agaw)
598
			break;
679
			break;
Lines 604-611 Link Here
604
	}
685
	}
605
686
606
	if (i >= 5) {
687
	if (i >= 5) {
607
		panic("vtd_create_domain: SAGAW 0x%lx does not support AGAW %d",
688
		panic("vtd_create_domain: SAGAW 0x%x does not support AGAW %d",
608
		      VTD_CAP_SAGAW(vtdmap->cap), agaw);
689
		      tmp, agaw);
609
	}
690
	}
610
691
611
	dom = malloc(sizeof(struct domain), M_VTD, M_ZERO | M_WAITOK);
692
	dom = malloc(sizeof(struct domain), M_VTD, M_ZERO | M_WAITOK);
Lines 632-638 Link Here
632
	 * There is not any code to deal with the demotion at the moment
713
	 * There is not any code to deal with the demotion at the moment
633
	 * so we disable superpage mappings altogether.
714
	 * so we disable superpage mappings altogether.
634
	 */
715
	 */
635
	dom->spsmask = VTD_CAP_SPS(vtdmap->cap);
716
	dom->spsmask = ~0;
717
	for (i = 0; i < drhd_num; i++) {
718
		vtdmap = vtdmaps[i];
719
		/* take most compatible value */
720
		dom->spsmask &= VTD_CAP_SPS(vtdmap->cap);
721
	}
636
#endif
722
#endif
637
723
638
	SLIST_INSERT_HEAD(&domhead, dom, next);
724
	SLIST_INSERT_HEAD(&domhead, dom, next);

Return to bug 229852