1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include "qemu/osdep.h"
21#include "hw/sysbus.h"
22#include "hw/pci/pci_bridge.h"
23#include "hw/pci/pci_host.h"
24#include "hw/cxl/cxl.h"
25#include "hw/mem/memory-device.h"
26#include "hw/acpi/acpi.h"
27#include "hw/acpi/aml-build.h"
28#include "hw/acpi/bios-linker-loader.h"
29#include "hw/acpi/cxl.h"
30#include "qapi/error.h"
31#include "qemu/uuid.h"
32
33static void cedt_build_chbs(GArray *table_data, PXBDev *cxl)
34{
35 SysBusDevice *sbd = SYS_BUS_DEVICE(cxl->cxl.cxl_host_bridge);
36 struct MemoryRegion *mr = sbd->mmio[0].memory;
37
38
39 build_append_int_noprefix(table_data, 0, 1);
40
41
42 build_append_int_noprefix(table_data, 0, 1);
43
44
45 build_append_int_noprefix(table_data, 32, 2);
46
47
48 build_append_int_noprefix(table_data, cxl->bus_nr, 4);
49
50
51 build_append_int_noprefix(table_data, 1, 4);
52
53
54 build_append_int_noprefix(table_data, 0, 4);
55
56
57 build_append_int_noprefix(table_data, mr->container->addr + mr->addr, 8);
58
59
60 build_append_int_noprefix(table_data, memory_region_size(mr), 8);
61}
62
63
64
65
66
67
68static void cedt_build_cfmws(GArray *table_data, CXLState *cxls)
69{
70 GList *it;
71
72 for (it = cxls->fixed_windows; it; it = it->next) {
73 CXLFixedWindow *fw = it->data;
74 int i;
75
76
77 build_append_int_noprefix(table_data, 1, 1);
78
79
80 build_append_int_noprefix(table_data, 0, 1);
81
82
83 build_append_int_noprefix(table_data, 36 + 4 * fw->num_targets, 2);
84
85
86 build_append_int_noprefix(table_data, 0, 4);
87
88
89 build_append_int_noprefix(table_data, fw->mr.addr, 8);
90
91
92 build_append_int_noprefix(table_data, fw->size, 8);
93
94
95 build_append_int_noprefix(table_data, fw->enc_int_ways, 1);
96
97
98 build_append_int_noprefix(table_data, 0, 1);
99
100
101 build_append_int_noprefix(table_data, 0, 2);
102
103
104 build_append_int_noprefix(table_data, fw->enc_int_gran, 4);
105
106
107 build_append_int_noprefix(table_data, 0x0f, 2);
108
109
110 build_append_int_noprefix(table_data, 0, 2);
111
112
113 for (i = 0; i < fw->num_targets; i++) {
114 g_assert(fw->target_hbs[i]);
115 build_append_int_noprefix(table_data, fw->target_hbs[i]->bus_nr, 4);
116 }
117 }
118}
119
120static int cxl_foreach_pxb_hb(Object *obj, void *opaque)
121{
122 Aml *cedt = opaque;
123
124 if (object_dynamic_cast(obj, TYPE_PXB_CXL_DEVICE)) {
125 cedt_build_chbs(cedt->buf, PXB_CXL_DEV(obj));
126 }
127
128 return 0;
129}
130
131void cxl_build_cedt(GArray *table_offsets, GArray *table_data,
132 BIOSLinker *linker, const char *oem_id,
133 const char *oem_table_id, CXLState *cxl_state)
134{
135 Aml *cedt;
136 AcpiTable table = { .sig = "CEDT", .rev = 1, .oem_id = oem_id,
137 .oem_table_id = oem_table_id };
138
139 acpi_add_table(table_offsets, table_data);
140 acpi_table_begin(&table, table_data);
141 cedt = init_aml_allocator();
142
143
144
145 object_child_foreach_recursive(object_get_root(), cxl_foreach_pxb_hb, cedt);
146 cedt_build_cfmws(cedt->buf, cxl_state);
147
148
149 g_array_append_vals(table_data, cedt->buf->data, cedt->buf->len);
150 free_aml_allocator();
151
152 acpi_table_end(linker, &table);
153}
154
155static Aml *__build_cxl_osc_method(void)
156{
157 Aml *method, *if_uuid, *else_uuid, *if_arg1_not_1, *if_cxl, *if_caps_masked;
158 Aml *a_ctrl = aml_local(0);
159 Aml *a_cdw1 = aml_name("CDW1");
160
161 method = aml_method("_OSC", 4, AML_NOTSERIALIZED);
162
163 aml_append(method, aml_create_dword_field(aml_arg(3), aml_int(0), "CDW1"));
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178 if_uuid = aml_if(
179 aml_lor(aml_equal(aml_arg(0),
180 aml_touuid("33DB4D5B-1FF7-401C-9657-7441C03DD766")),
181 aml_equal(aml_arg(0),
182 aml_touuid("68F2D50B-C469-4D8A-BD3D-941A103FD3FC"))));
183 aml_append(if_uuid, aml_create_dword_field(aml_arg(3), aml_int(4), "CDW2"));
184 aml_append(if_uuid, aml_create_dword_field(aml_arg(3), aml_int(8), "CDW3"));
185
186 aml_append(if_uuid, aml_store(aml_name("CDW3"), a_ctrl));
187
188
189
190
191
192
193 aml_append(if_uuid, aml_and(a_ctrl, aml_int(0x1F), a_ctrl));
194
195
196
197
198
199
200 if_arg1_not_1 = aml_if(aml_lnot(aml_equal(aml_arg(1), aml_int(0x1))));
201 aml_append(if_arg1_not_1, aml_or(a_cdw1, aml_int(0x08), a_cdw1));
202 aml_append(if_uuid, if_arg1_not_1);
203
204 if_caps_masked = aml_if(aml_lnot(aml_equal(aml_name("CDW3"), a_ctrl)));
205
206
207 aml_append(if_caps_masked, aml_or(a_cdw1, aml_int(0x10), a_cdw1));
208 aml_append(if_uuid, if_caps_masked);
209
210 aml_append(if_uuid, aml_store(aml_name("CDW2"), aml_name("SUPP")));
211 aml_append(if_uuid, aml_store(aml_name("CDW3"), aml_name("CTRL")));
212
213
214 aml_append(if_uuid, aml_store(a_ctrl, aml_name("CDW3")));
215
216
217 if_cxl = aml_if(aml_equal(
218 aml_arg(0), aml_touuid("68F2D50B-C469-4D8A-BD3D-941A103FD3FC")));
219
220 aml_append(if_cxl, aml_create_dword_field(aml_arg(3), aml_int(12), "CDW4"));
221
222 aml_append(if_cxl, aml_create_dword_field(aml_arg(3), aml_int(16), "CDW5"));
223 aml_append(if_cxl, aml_store(aml_name("CDW4"), aml_name("SUPC")));
224 aml_append(if_cxl, aml_store(aml_name("CDW5"), aml_name("CTRC")));
225
226
227 aml_append(if_cxl,
228 aml_or(aml_name("CDW5"), aml_int(0x1), aml_name("CDW5")));
229 aml_append(if_uuid, if_cxl);
230
231 aml_append(if_uuid, aml_return(aml_arg(3)));
232 aml_append(method, if_uuid);
233
234
235
236
237
238
239 else_uuid = aml_else();
240
241 aml_append(else_uuid,
242 aml_or(aml_name("CDW1"), aml_int(0x4), aml_name("CDW1")));
243 aml_append(else_uuid, aml_return(aml_arg(3)));
244 aml_append(method, else_uuid);
245
246 return method;
247}
248
249void build_cxl_osc_method(Aml *dev)
250{
251 aml_append(dev, aml_name_decl("SUPP", aml_int(0)));
252 aml_append(dev, aml_name_decl("CTRL", aml_int(0)));
253 aml_append(dev, aml_name_decl("SUPC", aml_int(0)));
254 aml_append(dev, aml_name_decl("CTRC", aml_int(0)));
255 aml_append(dev, __build_cxl_osc_method());
256}
257