xref: /aosp_15_r20/external/coreboot/src/acpi/acpi_dmar.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <acpi/acpi.h>
4 #include <arch/ioapic.h>
5 #include <assert.h>
6 #include <cpu/cpu.h>
7 #include <lib.h>
8 #include <version.h>
9 
acpi_create_dmar(acpi_dmar_t * dmar,enum dmar_flags flags,unsigned long (* acpi_fill_dmar)(unsigned long))10 void acpi_create_dmar(acpi_dmar_t *dmar, enum dmar_flags flags,
11 		      unsigned long (*acpi_fill_dmar)(unsigned long))
12 {
13 	acpi_header_t *header = &(dmar->header);
14 	unsigned long current = (unsigned long)dmar + sizeof(acpi_dmar_t);
15 
16 	memset((void *)dmar, 0, sizeof(acpi_dmar_t));
17 
18 	if (!header)
19 		return;
20 
21 	/* Fill out header fields. */
22 	memcpy(header->signature, "DMAR", 4);
23 	memcpy(header->oem_id, OEM_ID, 6);
24 	memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
25 	memcpy(header->asl_compiler_id, ASLC, 4);
26 
27 	header->asl_compiler_revision = asl_revision;
28 	header->length = sizeof(acpi_dmar_t);
29 	header->revision = get_acpi_table_revision(DMAR);
30 
31 	dmar->host_address_width = soc_phys_address_size() - 1;
32 	dmar->flags = flags;
33 
34 	current = acpi_fill_dmar(current);
35 
36 	/* (Re)calculate length and checksum. */
37 	header->length = current - (unsigned long)dmar;
38 	header->checksum = acpi_checksum((void *)dmar, header->length);
39 }
40 
acpi_create_dmar_drhd_4k(unsigned long current,u8 flags,u16 segment,u64 bar)41 unsigned long acpi_create_dmar_drhd_4k(unsigned long current, u8 flags,
42 				       u16 segment, u64 bar)
43 {
44 	return acpi_create_dmar_drhd(current, flags, segment, bar, 4 * KiB);
45 }
46 
acpi_create_dmar_drhd(unsigned long current,u8 flags,u16 segment,u64 bar,size_t size)47 unsigned long acpi_create_dmar_drhd(unsigned long current, u8 flags,
48 	u16 segment, u64 bar, size_t size)
49 {
50 	/*
51 	 * Refer to Intel® Virtualization Technology for Directed I/O
52 	 * Architecture Specification Revision 4.1,
53 	 * size is at least 1 page and max 2^15 pages, 4 KiB each, and the bar
54 	 * should be aligned with size.
55 	 */
56 	assert(4 * KiB <= size && size <= (1 << 15) * 4 * KiB && IS_POWER_OF_2(size));
57 	assert(IS_ALIGNED(bar, size));
58 
59 	dmar_entry_t *drhd = (dmar_entry_t *)current;
60 	memset(drhd, 0, sizeof(*drhd));
61 	drhd->type = DMAR_DRHD;
62 	drhd->length = sizeof(*drhd); /* will be fixed up later */
63 	drhd->flags = flags;
64 	drhd->segment = segment;
65 	drhd->bar = bar;
66 	drhd->size = log2_64(size) - 12;
67 
68 	return drhd->length;
69 }
70 
acpi_create_dmar_rmrr(unsigned long current,u16 segment,u64 bar,u64 limit)71 unsigned long acpi_create_dmar_rmrr(unsigned long current, u16 segment,
72 				    u64 bar, u64 limit)
73 {
74 	dmar_rmrr_entry_t *rmrr = (dmar_rmrr_entry_t *)current;
75 	memset(rmrr, 0, sizeof(*rmrr));
76 	rmrr->type = DMAR_RMRR;
77 	rmrr->length = sizeof(*rmrr); /* will be fixed up later */
78 	rmrr->segment = segment;
79 	rmrr->bar = bar;
80 	rmrr->limit = limit;
81 
82 	return rmrr->length;
83 }
84 
acpi_create_dmar_atsr(unsigned long current,u8 flags,u16 segment)85 unsigned long acpi_create_dmar_atsr(unsigned long current, u8 flags,
86 	u16 segment)
87 {
88 	dmar_atsr_entry_t *atsr = (dmar_atsr_entry_t *)current;
89 	memset(atsr, 0, sizeof(*atsr));
90 	atsr->type = DMAR_ATSR;
91 	atsr->length = sizeof(*atsr); /* will be fixed up later */
92 	atsr->flags = flags;
93 	atsr->segment = segment;
94 
95 	return atsr->length;
96 }
97 
acpi_create_dmar_rhsa(unsigned long current,u64 base_addr,u32 proximity_domain)98 unsigned long acpi_create_dmar_rhsa(unsigned long current, u64 base_addr,
99 	u32 proximity_domain)
100 {
101 	dmar_rhsa_entry_t *rhsa = (dmar_rhsa_entry_t *)current;
102 	memset(rhsa, 0, sizeof(*rhsa));
103 	rhsa->type = DMAR_RHSA;
104 	rhsa->length = sizeof(*rhsa);
105 	rhsa->base_address = base_addr;
106 	rhsa->proximity_domain = proximity_domain;
107 
108 	return rhsa->length;
109 }
110 
acpi_create_dmar_andd(unsigned long current,u8 device_number,const char * device_name)111 unsigned long acpi_create_dmar_andd(unsigned long current, u8 device_number,
112 	const char *device_name)
113 {
114 	dmar_andd_entry_t *andd = (dmar_andd_entry_t *)current;
115 	int andd_len = sizeof(dmar_andd_entry_t) + strlen(device_name) + 1;
116 	memset(andd, 0, andd_len);
117 	andd->type = DMAR_ANDD;
118 	andd->length = andd_len;
119 	andd->device_number = device_number;
120 	memcpy(&andd->device_name, device_name, strlen(device_name));
121 
122 	return andd->length;
123 }
124 
acpi_create_dmar_satc(unsigned long current,u8 flags,u16 segment)125 unsigned long acpi_create_dmar_satc(unsigned long current, u8 flags, u16 segment)
126 {
127 	dmar_satc_entry_t *satc = (dmar_satc_entry_t *)current;
128 	int satc_len = sizeof(dmar_satc_entry_t);
129 	memset(satc, 0, satc_len);
130 	satc->type = DMAR_SATC;
131 	satc->length = satc_len;
132 	satc->flags = flags;
133 	satc->segment_number = segment;
134 
135 	return satc->length;
136 }
137 
acpi_dmar_drhd_fixup(unsigned long base,unsigned long current)138 void acpi_dmar_drhd_fixup(unsigned long base, unsigned long current)
139 {
140 	dmar_entry_t *drhd = (dmar_entry_t *)base;
141 	drhd->length = current - base;
142 }
143 
acpi_dmar_rmrr_fixup(unsigned long base,unsigned long current)144 void acpi_dmar_rmrr_fixup(unsigned long base, unsigned long current)
145 {
146 	dmar_rmrr_entry_t *rmrr = (dmar_rmrr_entry_t *)base;
147 	rmrr->length = current - base;
148 }
149 
acpi_dmar_atsr_fixup(unsigned long base,unsigned long current)150 void acpi_dmar_atsr_fixup(unsigned long base, unsigned long current)
151 {
152 	dmar_atsr_entry_t *atsr = (dmar_atsr_entry_t *)base;
153 	atsr->length = current - base;
154 }
155 
acpi_dmar_satc_fixup(unsigned long base,unsigned long current)156 void acpi_dmar_satc_fixup(unsigned long base, unsigned long current)
157 {
158 	dmar_satc_entry_t *satc = (dmar_satc_entry_t *)base;
159 	satc->length = current - base;
160 }
161 
acpi_create_dmar_ds(unsigned long current,enum dev_scope_type type,u8 enumeration_id,u8 bus,u8 dev,u8 fn)162 static unsigned long acpi_create_dmar_ds(unsigned long current,
163 	enum dev_scope_type type, u8 enumeration_id, u8 bus, u8 dev, u8 fn)
164 {
165 	/* we don't support longer paths yet */
166 	const size_t dev_scope_length = sizeof(dev_scope_t) + 2;
167 
168 	dev_scope_t *ds = (dev_scope_t *)current;
169 	memset(ds, 0, dev_scope_length);
170 	ds->type	= type;
171 	ds->length	= dev_scope_length;
172 	ds->enumeration	= enumeration_id;
173 	ds->start_bus	= bus;
174 	ds->path[0].dev	= dev;
175 	ds->path[0].fn	= fn;
176 
177 	return ds->length;
178 }
179 
acpi_create_dmar_ds_pci_br(unsigned long current,u8 bus,u8 dev,u8 fn)180 unsigned long acpi_create_dmar_ds_pci_br(unsigned long current, u8 bus,
181 	u8 dev, u8 fn)
182 {
183 	return acpi_create_dmar_ds(current,
184 			SCOPE_PCI_SUB, 0, bus, dev, fn);
185 }
186 
acpi_create_dmar_ds_pci(unsigned long current,u8 bus,u8 dev,u8 fn)187 unsigned long acpi_create_dmar_ds_pci(unsigned long current, u8 bus,
188 	u8 dev, u8 fn)
189 {
190 	return acpi_create_dmar_ds(current,
191 			SCOPE_PCI_ENDPOINT, 0, bus, dev, fn);
192 }
193 
acpi_create_dmar_ds_ioapic(unsigned long current,u8 enumeration_id,u8 bus,u8 dev,u8 fn)194 unsigned long acpi_create_dmar_ds_ioapic(unsigned long current,
195 	u8 enumeration_id, u8 bus, u8 dev, u8 fn)
196 {
197 	return acpi_create_dmar_ds(current,
198 			SCOPE_IOAPIC, enumeration_id, bus, dev, fn);
199 }
200 
acpi_create_dmar_ds_ioapic_from_hw(unsigned long current,u32 addr,u8 bus,u8 dev,u8 fn)201 unsigned long acpi_create_dmar_ds_ioapic_from_hw(unsigned long current,
202 						 u32 addr, u8 bus, u8 dev, u8 fn)
203 {
204 	u8 enumeration_id = get_ioapic_id((uintptr_t)addr);
205 	return acpi_create_dmar_ds(current,
206 			SCOPE_IOAPIC, enumeration_id, bus, dev, fn);
207 }
208 
acpi_create_dmar_ds_msi_hpet(unsigned long current,u8 enumeration_id,u8 bus,u8 dev,u8 fn)209 unsigned long acpi_create_dmar_ds_msi_hpet(unsigned long current,
210 	u8 enumeration_id, u8 bus, u8 dev, u8 fn)
211 {
212 	return acpi_create_dmar_ds(current,
213 			SCOPE_MSI_HPET, enumeration_id, bus, dev, fn);
214 }
215