blob: 20a100d337d5b6db276365aabefb0dc827b53493 [file] [log] [blame]
Arthur Heymans92a3b672023-06-22 21:30:58 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <acpi/acpi.h>
4#include <arch/ioapic.h>
5#include <cpu/cpu.h>
6#include <version.h>
7
8void acpi_create_dmar(acpi_dmar_t *dmar, enum dmar_flags flags,
9 unsigned long (*acpi_fill_dmar)(unsigned long))
10{
11 acpi_header_t *header = &(dmar->header);
12 unsigned long current = (unsigned long)dmar + sizeof(acpi_dmar_t);
13
14 memset((void *)dmar, 0, sizeof(acpi_dmar_t));
15
16 if (!header)
17 return;
18
19 /* Fill out header fields. */
20 memcpy(header->signature, "DMAR", 4);
21 memcpy(header->oem_id, OEM_ID, 6);
22 memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
23 memcpy(header->asl_compiler_id, ASLC, 4);
24
25 header->asl_compiler_revision = asl_revision;
26 header->length = sizeof(acpi_dmar_t);
27 header->revision = get_acpi_table_revision(DMAR);
28
Jeremy Compostellaba757a72023-12-20 09:07:04 -080029 dmar->host_address_width = soc_phys_address_size() - 1;
Arthur Heymans92a3b672023-06-22 21:30:58 +020030 dmar->flags = flags;
31
32 current = acpi_fill_dmar(current);
33
34 /* (Re)calculate length and checksum. */
35 header->length = current - (unsigned long)dmar;
36 header->checksum = acpi_checksum((void *)dmar, header->length);
37}
38
Shuo Liuf3aaa0e2024-06-25 18:50:06 +080039unsigned long acpi_create_dmar_drhd_4k(unsigned long current, u8 flags,
Arthur Heymans92a3b672023-06-22 21:30:58 +020040 u16 segment, u64 bar)
41{
42 dmar_entry_t *drhd = (dmar_entry_t *)current;
43 memset(drhd, 0, sizeof(*drhd));
44 drhd->type = DMAR_DRHD;
45 drhd->length = sizeof(*drhd); /* will be fixed up later */
46 drhd->flags = flags;
47 drhd->segment = segment;
48 drhd->bar = bar;
49
50 return drhd->length;
51}
52
53unsigned long acpi_create_dmar_rmrr(unsigned long current, u16 segment,
54 u64 bar, u64 limit)
55{
56 dmar_rmrr_entry_t *rmrr = (dmar_rmrr_entry_t *)current;
57 memset(rmrr, 0, sizeof(*rmrr));
58 rmrr->type = DMAR_RMRR;
59 rmrr->length = sizeof(*rmrr); /* will be fixed up later */
60 rmrr->segment = segment;
61 rmrr->bar = bar;
62 rmrr->limit = limit;
63
64 return rmrr->length;
65}
66
67unsigned long acpi_create_dmar_atsr(unsigned long current, u8 flags,
68 u16 segment)
69{
70 dmar_atsr_entry_t *atsr = (dmar_atsr_entry_t *)current;
71 memset(atsr, 0, sizeof(*atsr));
72 atsr->type = DMAR_ATSR;
73 atsr->length = sizeof(*atsr); /* will be fixed up later */
74 atsr->flags = flags;
75 atsr->segment = segment;
76
77 return atsr->length;
78}
79
80unsigned long acpi_create_dmar_rhsa(unsigned long current, u64 base_addr,
81 u32 proximity_domain)
82{
83 dmar_rhsa_entry_t *rhsa = (dmar_rhsa_entry_t *)current;
84 memset(rhsa, 0, sizeof(*rhsa));
85 rhsa->type = DMAR_RHSA;
86 rhsa->length = sizeof(*rhsa);
87 rhsa->base_address = base_addr;
88 rhsa->proximity_domain = proximity_domain;
89
90 return rhsa->length;
91}
92
93unsigned long acpi_create_dmar_andd(unsigned long current, u8 device_number,
94 const char *device_name)
95{
96 dmar_andd_entry_t *andd = (dmar_andd_entry_t *)current;
97 int andd_len = sizeof(dmar_andd_entry_t) + strlen(device_name) + 1;
98 memset(andd, 0, andd_len);
99 andd->type = DMAR_ANDD;
100 andd->length = andd_len;
101 andd->device_number = device_number;
102 memcpy(&andd->device_name, device_name, strlen(device_name));
103
104 return andd->length;
105}
106
107unsigned long acpi_create_dmar_satc(unsigned long current, u8 flags, u16 segment)
108{
109 dmar_satc_entry_t *satc = (dmar_satc_entry_t *)current;
110 int satc_len = sizeof(dmar_satc_entry_t);
111 memset(satc, 0, satc_len);
112 satc->type = DMAR_SATC;
113 satc->length = satc_len;
114 satc->flags = flags;
115 satc->segment_number = segment;
116
117 return satc->length;
118}
119
120void acpi_dmar_drhd_fixup(unsigned long base, unsigned long current)
121{
122 dmar_entry_t *drhd = (dmar_entry_t *)base;
123 drhd->length = current - base;
124}
125
126void acpi_dmar_rmrr_fixup(unsigned long base, unsigned long current)
127{
128 dmar_rmrr_entry_t *rmrr = (dmar_rmrr_entry_t *)base;
129 rmrr->length = current - base;
130}
131
132void acpi_dmar_atsr_fixup(unsigned long base, unsigned long current)
133{
134 dmar_atsr_entry_t *atsr = (dmar_atsr_entry_t *)base;
135 atsr->length = current - base;
136}
137
138void acpi_dmar_satc_fixup(unsigned long base, unsigned long current)
139{
140 dmar_satc_entry_t *satc = (dmar_satc_entry_t *)base;
141 satc->length = current - base;
142}
143
144static unsigned long acpi_create_dmar_ds(unsigned long current,
145 enum dev_scope_type type, u8 enumeration_id, u8 bus, u8 dev, u8 fn)
146{
147 /* we don't support longer paths yet */
148 const size_t dev_scope_length = sizeof(dev_scope_t) + 2;
149
150 dev_scope_t *ds = (dev_scope_t *)current;
151 memset(ds, 0, dev_scope_length);
152 ds->type = type;
153 ds->length = dev_scope_length;
154 ds->enumeration = enumeration_id;
155 ds->start_bus = bus;
156 ds->path[0].dev = dev;
157 ds->path[0].fn = fn;
158
159 return ds->length;
160}
161
162unsigned long acpi_create_dmar_ds_pci_br(unsigned long current, u8 bus,
163 u8 dev, u8 fn)
164{
165 return acpi_create_dmar_ds(current,
166 SCOPE_PCI_SUB, 0, bus, dev, fn);
167}
168
169unsigned long acpi_create_dmar_ds_pci(unsigned long current, u8 bus,
170 u8 dev, u8 fn)
171{
172 return acpi_create_dmar_ds(current,
173 SCOPE_PCI_ENDPOINT, 0, bus, dev, fn);
174}
175
176unsigned long acpi_create_dmar_ds_ioapic(unsigned long current,
177 u8 enumeration_id, u8 bus, u8 dev, u8 fn)
178{
179 return acpi_create_dmar_ds(current,
180 SCOPE_IOAPIC, enumeration_id, bus, dev, fn);
181}
182
183unsigned long acpi_create_dmar_ds_ioapic_from_hw(unsigned long current,
184 u32 addr, u8 bus, u8 dev, u8 fn)
185{
Felix Held0d192892024-02-06 16:55:29 +0100186 u8 enumeration_id = get_ioapic_id((uintptr_t)addr);
Arthur Heymans92a3b672023-06-22 21:30:58 +0200187 return acpi_create_dmar_ds(current,
188 SCOPE_IOAPIC, enumeration_id, bus, dev, fn);
189}
190
191unsigned long acpi_create_dmar_ds_msi_hpet(unsigned long current,
192 u8 enumeration_id, u8 bus, u8 dev, u8 fn)
193{
194 return acpi_create_dmar_ds(current,
195 SCOPE_MSI_HPET, enumeration_id, bus, dev, fn);
196}