xref: /openbmc/qemu/hw/cxl/cxl-host.c (revision 5885bcef3d760e84d17eb4113e85f2aea0bd0582)
1aadfe320SJonathan Cameron /*
2aadfe320SJonathan Cameron  * CXL host parameter parsing routines
3aadfe320SJonathan Cameron  *
4aadfe320SJonathan Cameron  * Copyright (c) 2022 Huawei
5aadfe320SJonathan Cameron  * Modeled loosely on the NUMA options handling in hw/core/numa.c
6aadfe320SJonathan Cameron  */
7aadfe320SJonathan Cameron 
8aadfe320SJonathan Cameron #include "qemu/osdep.h"
9aadfe320SJonathan Cameron #include "qemu/units.h"
10aadfe320SJonathan Cameron #include "qemu/bitmap.h"
11aadfe320SJonathan Cameron #include "qemu/error-report.h"
12aadfe320SJonathan Cameron #include "qapi/error.h"
13aadfe320SJonathan Cameron #include "sysemu/qtest.h"
14aadfe320SJonathan Cameron #include "hw/boards.h"
15aadfe320SJonathan Cameron 
16aadfe320SJonathan Cameron #include "qapi/qapi-visit-machine.h"
17aadfe320SJonathan Cameron #include "hw/cxl/cxl.h"
1803b39fcfSJonathan Cameron #include "hw/cxl/cxl_host.h"
19eb19d907SJonathan Cameron #include "hw/pci/pci_bus.h"
20eb19d907SJonathan Cameron #include "hw/pci/pci_bridge.h"
21eb19d907SJonathan Cameron #include "hw/pci/pci_host.h"
22eb19d907SJonathan Cameron #include "hw/pci/pcie_port.h"
237bd1900bSJonathan Cameron #include "hw/pci-bridge/pci_expander_bridge.h"
24aadfe320SJonathan Cameron 
cxl_fixed_memory_window_config(CXLState * cxl_state,CXLFixedMemoryWindowOptions * object,Error ** errp)2503b39fcfSJonathan Cameron static void cxl_fixed_memory_window_config(CXLState *cxl_state,
26aadfe320SJonathan Cameron                                            CXLFixedMemoryWindowOptions *object,
27aadfe320SJonathan Cameron                                            Error **errp)
28aadfe320SJonathan Cameron {
295c7eedf5SZhao Liu     ERRP_GUARD();
30a99fbb00SJonathan Cameron     g_autofree CXLFixedWindow *fw = g_malloc0(sizeof(*fw));
31aadfe320SJonathan Cameron     strList *target;
32aadfe320SJonathan Cameron     int i;
33aadfe320SJonathan Cameron 
34aadfe320SJonathan Cameron     for (target = object->targets; target; target = target->next) {
35aadfe320SJonathan Cameron         fw->num_targets++;
36aadfe320SJonathan Cameron     }
37aadfe320SJonathan Cameron 
38aadfe320SJonathan Cameron     fw->enc_int_ways = cxl_interleave_ways_enc(fw->num_targets, errp);
39aadfe320SJonathan Cameron     if (*errp) {
40aadfe320SJonathan Cameron         return;
41aadfe320SJonathan Cameron     }
42aadfe320SJonathan Cameron 
43aadfe320SJonathan Cameron     if (object->size % (256 * MiB)) {
44aadfe320SJonathan Cameron         error_setg(errp,
45f99ad11cSHoa Nguyen                    "Size of a CXL fixed memory window must be a multiple of 256MiB");
46aadfe320SJonathan Cameron         return;
47aadfe320SJonathan Cameron     }
48aadfe320SJonathan Cameron     fw->size = object->size;
49aadfe320SJonathan Cameron 
50aadfe320SJonathan Cameron     if (object->has_interleave_granularity) {
51aadfe320SJonathan Cameron         fw->enc_int_gran =
52aadfe320SJonathan Cameron             cxl_interleave_granularity_enc(object->interleave_granularity,
53aadfe320SJonathan Cameron                                            errp);
54aadfe320SJonathan Cameron         if (*errp) {
55aadfe320SJonathan Cameron             return;
56aadfe320SJonathan Cameron         }
57aadfe320SJonathan Cameron     } else {
58aadfe320SJonathan Cameron         /* Default to 256 byte interleave */
59aadfe320SJonathan Cameron         fw->enc_int_gran = 0;
60aadfe320SJonathan Cameron     }
61aadfe320SJonathan Cameron 
627b165fa1SLi Zhijian     fw->targets = g_malloc0_n(fw->num_targets, sizeof(*fw->targets));
637b165fa1SLi Zhijian     for (i = 0, target = object->targets; target; i++, target = target->next) {
647b165fa1SLi Zhijian         /* This link cannot be resolved yet, so stash the name for now */
657b165fa1SLi Zhijian         fw->targets[i] = g_strdup(target->value);
667b165fa1SLi Zhijian     }
677b165fa1SLi Zhijian 
68a99fbb00SJonathan Cameron     cxl_state->fixed_windows = g_list_append(cxl_state->fixed_windows,
69a99fbb00SJonathan Cameron                                              g_steal_pointer(&fw));
70aadfe320SJonathan Cameron 
71aadfe320SJonathan Cameron     return;
72aadfe320SJonathan Cameron }
73aadfe320SJonathan Cameron 
cxl_fmws_link_targets(CXLState * cxl_state,Error ** errp)74dab390ffSJonathan Cameron void cxl_fmws_link_targets(CXLState *cxl_state, Error **errp)
75aadfe320SJonathan Cameron {
76dab390ffSJonathan Cameron     if (cxl_state && cxl_state->fixed_windows) {
77aadfe320SJonathan Cameron         GList *it;
78aadfe320SJonathan Cameron 
79dab390ffSJonathan Cameron         for (it = cxl_state->fixed_windows; it; it = it->next) {
80aadfe320SJonathan Cameron             CXLFixedWindow *fw = it->data;
81aadfe320SJonathan Cameron             int i;
82aadfe320SJonathan Cameron 
83aadfe320SJonathan Cameron             for (i = 0; i < fw->num_targets; i++) {
84aadfe320SJonathan Cameron                 Object *o;
85aadfe320SJonathan Cameron                 bool ambig;
86aadfe320SJonathan Cameron 
87aadfe320SJonathan Cameron                 o = object_resolve_path_type(fw->targets[i],
88c28db9e0SJonathan Cameron                                              TYPE_PXB_CXL_DEV,
89aadfe320SJonathan Cameron                                              &ambig);
90aadfe320SJonathan Cameron                 if (!o) {
91aadfe320SJonathan Cameron                     error_setg(errp, "Could not resolve CXLFM target %s",
92aadfe320SJonathan Cameron                                fw->targets[i]);
93aadfe320SJonathan Cameron                     return;
94aadfe320SJonathan Cameron                 }
95aadfe320SJonathan Cameron                 fw->target_hbs[i] = PXB_CXL_DEV(o);
96aadfe320SJonathan Cameron             }
97aadfe320SJonathan Cameron         }
98aadfe320SJonathan Cameron     }
99aadfe320SJonathan Cameron }
100eb19d907SJonathan Cameron 
cxl_hdm_find_target(uint32_t * cache_mem,hwaddr addr,uint8_t * target)101eb19d907SJonathan Cameron static bool cxl_hdm_find_target(uint32_t *cache_mem, hwaddr addr,
102eb19d907SJonathan Cameron                                 uint8_t *target)
103eb19d907SJonathan Cameron {
10461c44bcfSJonathan Cameron     int hdm_inc = R_CXL_HDM_DECODER1_BASE_LO - R_CXL_HDM_DECODER0_BASE_LO;
105e967413fSJonathan Cameron     unsigned int hdm_count;
106e967413fSJonathan Cameron     bool found = false;
107e967413fSJonathan Cameron     int i;
108e967413fSJonathan Cameron     uint32_t cap;
109eb19d907SJonathan Cameron 
110e967413fSJonathan Cameron     cap = ldl_le_p(cache_mem + R_CXL_HDM_DECODER_CAPABILITY);
111e967413fSJonathan Cameron     hdm_count = cxl_decoder_count_dec(FIELD_EX32(cap,
112e967413fSJonathan Cameron                                                  CXL_HDM_DECODER_CAPABILITY,
113e967413fSJonathan Cameron                                                  DECODER_COUNT));
114e967413fSJonathan Cameron     for (i = 0; i < hdm_count; i++) {
115e967413fSJonathan Cameron         uint32_t ctrl, ig_enc, iw_enc, target_idx;
116e967413fSJonathan Cameron         uint32_t low, high;
117e967413fSJonathan Cameron         uint64_t base, size;
118e967413fSJonathan Cameron 
119e967413fSJonathan Cameron         low = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_BASE_LO + i * hdm_inc);
120e967413fSJonathan Cameron         high = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_BASE_HI + i * hdm_inc);
121e967413fSJonathan Cameron         base = (low & 0xf0000000) | ((uint64_t)high << 32);
122e967413fSJonathan Cameron         low = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_SIZE_LO + i * hdm_inc);
123e967413fSJonathan Cameron         high = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_SIZE_HI + i * hdm_inc);
124e967413fSJonathan Cameron         size = (low & 0xf0000000) | ((uint64_t)high << 32);
125e967413fSJonathan Cameron         if (addr < base || addr >= base + size) {
126e967413fSJonathan Cameron             continue;
127e967413fSJonathan Cameron         }
128e967413fSJonathan Cameron 
129e967413fSJonathan Cameron         ctrl = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL + i * hdm_inc);
130eb19d907SJonathan Cameron         if (!FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, COMMITTED)) {
131eb19d907SJonathan Cameron             return false;
132eb19d907SJonathan Cameron         }
133e967413fSJonathan Cameron         found = true;
134eb19d907SJonathan Cameron         ig_enc = FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, IG);
135eb19d907SJonathan Cameron         iw_enc = FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, IW);
136eb19d907SJonathan Cameron         target_idx = (addr / cxl_decode_ig(ig_enc)) % (1 << iw_enc);
137eb19d907SJonathan Cameron 
138d2289b52SJonathan Cameron         if (target_idx < 4) {
139e967413fSJonathan Cameron             uint32_t val = ldl_le_p(cache_mem +
140e967413fSJonathan Cameron                                     R_CXL_HDM_DECODER0_TARGET_LIST_LO +
141e967413fSJonathan Cameron                                     i * hdm_inc);
142e967413fSJonathan Cameron             *target = extract32(val, target_idx * 8, 8);
143eb19d907SJonathan Cameron         } else {
144e967413fSJonathan Cameron             uint32_t val = ldl_le_p(cache_mem +
145e967413fSJonathan Cameron                                     R_CXL_HDM_DECODER0_TARGET_LIST_HI +
146e967413fSJonathan Cameron                                     i * hdm_inc);
147e967413fSJonathan Cameron             *target = extract32(val, (target_idx - 4) * 8, 8);
148e967413fSJonathan Cameron         }
149e967413fSJonathan Cameron         break;
150eb19d907SJonathan Cameron     }
151eb19d907SJonathan Cameron 
152e967413fSJonathan Cameron     return found;
153eb19d907SJonathan Cameron }
154eb19d907SJonathan Cameron 
cxl_cfmws_find_device(CXLFixedWindow * fw,hwaddr addr)155eb19d907SJonathan Cameron static PCIDevice *cxl_cfmws_find_device(CXLFixedWindow *fw, hwaddr addr)
156eb19d907SJonathan Cameron {
15718cef1c6SJonathan Cameron     CXLComponentState *hb_cstate, *usp_cstate;
158eb19d907SJonathan Cameron     PCIHostState *hb;
15918cef1c6SJonathan Cameron     CXLUpstreamPort *usp;
160eb19d907SJonathan Cameron     int rb_index;
161eb19d907SJonathan Cameron     uint32_t *cache_mem;
162eb19d907SJonathan Cameron     uint8_t target;
163eb19d907SJonathan Cameron     bool target_found;
164eb19d907SJonathan Cameron     PCIDevice *rp, *d;
165eb19d907SJonathan Cameron 
166eb19d907SJonathan Cameron     /* Address is relative to memory region. Convert to HPA */
167eb19d907SJonathan Cameron     addr += fw->base;
168eb19d907SJonathan Cameron 
169eb19d907SJonathan Cameron     rb_index = (addr / cxl_decode_ig(fw->enc_int_gran)) % fw->num_targets;
170c28db9e0SJonathan Cameron     hb = PCI_HOST_BRIDGE(fw->target_hbs[rb_index]->cxl_host_bridge);
171eb19d907SJonathan Cameron     if (!hb || !hb->bus || !pci_bus_is_cxl(hb->bus)) {
172eb19d907SJonathan Cameron         return NULL;
173eb19d907SJonathan Cameron     }
174eb19d907SJonathan Cameron 
175154070eaSJonathan Cameron     if (cxl_get_hb_passthrough(hb)) {
176154070eaSJonathan Cameron         rp = pcie_find_port_first(hb->bus);
177154070eaSJonathan Cameron         if (!rp) {
178154070eaSJonathan Cameron             return NULL;
179154070eaSJonathan Cameron         }
180154070eaSJonathan Cameron     } else {
181eb19d907SJonathan Cameron         hb_cstate = cxl_get_hb_cstate(hb);
182eb19d907SJonathan Cameron         if (!hb_cstate) {
183eb19d907SJonathan Cameron             return NULL;
184eb19d907SJonathan Cameron         }
185eb19d907SJonathan Cameron 
186eb19d907SJonathan Cameron         cache_mem = hb_cstate->crb.cache_mem_registers;
187eb19d907SJonathan Cameron 
188eb19d907SJonathan Cameron         target_found = cxl_hdm_find_target(cache_mem, addr, &target);
189eb19d907SJonathan Cameron         if (!target_found) {
190eb19d907SJonathan Cameron             return NULL;
191eb19d907SJonathan Cameron         }
192eb19d907SJonathan Cameron 
193eb19d907SJonathan Cameron         rp = pcie_find_port_by_pn(hb->bus, target);
194eb19d907SJonathan Cameron         if (!rp) {
195eb19d907SJonathan Cameron             return NULL;
196eb19d907SJonathan Cameron         }
197154070eaSJonathan Cameron     }
198eb19d907SJonathan Cameron 
199eb19d907SJonathan Cameron     d = pci_bridge_get_sec_bus(PCI_BRIDGE(rp))->devices[0];
20018cef1c6SJonathan Cameron     if (!d) {
20118cef1c6SJonathan Cameron         return NULL;
20218cef1c6SJonathan Cameron     }
203eb19d907SJonathan Cameron 
20418cef1c6SJonathan Cameron     if (object_dynamic_cast(OBJECT(d), TYPE_CXL_TYPE3)) {
20518cef1c6SJonathan Cameron         return d;
20618cef1c6SJonathan Cameron     }
20718cef1c6SJonathan Cameron 
20818cef1c6SJonathan Cameron     /*
20918cef1c6SJonathan Cameron      * Could also be a switch.  Note only one level of switching currently
21018cef1c6SJonathan Cameron      * supported.
21118cef1c6SJonathan Cameron      */
21218cef1c6SJonathan Cameron     if (!object_dynamic_cast(OBJECT(d), TYPE_CXL_USP)) {
21318cef1c6SJonathan Cameron         return NULL;
21418cef1c6SJonathan Cameron     }
21518cef1c6SJonathan Cameron     usp = CXL_USP(d);
21618cef1c6SJonathan Cameron 
21718cef1c6SJonathan Cameron     usp_cstate = cxl_usp_to_cstate(usp);
21818cef1c6SJonathan Cameron     if (!usp_cstate) {
21918cef1c6SJonathan Cameron         return NULL;
22018cef1c6SJonathan Cameron     }
22118cef1c6SJonathan Cameron 
22218cef1c6SJonathan Cameron     cache_mem = usp_cstate->crb.cache_mem_registers;
22318cef1c6SJonathan Cameron 
22418cef1c6SJonathan Cameron     target_found = cxl_hdm_find_target(cache_mem, addr, &target);
22518cef1c6SJonathan Cameron     if (!target_found) {
22618cef1c6SJonathan Cameron         return NULL;
22718cef1c6SJonathan Cameron     }
22818cef1c6SJonathan Cameron 
22918cef1c6SJonathan Cameron     d = pcie_find_port_by_pn(&PCI_BRIDGE(d)->sec_bus, target);
23018cef1c6SJonathan Cameron     if (!d) {
23118cef1c6SJonathan Cameron         return NULL;
23218cef1c6SJonathan Cameron     }
23318cef1c6SJonathan Cameron 
23418cef1c6SJonathan Cameron     d = pci_bridge_get_sec_bus(PCI_BRIDGE(d))->devices[0];
23518cef1c6SJonathan Cameron     if (!d) {
23618cef1c6SJonathan Cameron         return NULL;
23718cef1c6SJonathan Cameron     }
23818cef1c6SJonathan Cameron 
23918cef1c6SJonathan Cameron     if (!object_dynamic_cast(OBJECT(d), TYPE_CXL_TYPE3)) {
240eb19d907SJonathan Cameron         return NULL;
241eb19d907SJonathan Cameron     }
242eb19d907SJonathan Cameron 
243eb19d907SJonathan Cameron     return d;
244eb19d907SJonathan Cameron }
245eb19d907SJonathan Cameron 
cxl_read_cfmws(void * opaque,hwaddr addr,uint64_t * data,unsigned size,MemTxAttrs attrs)246eb19d907SJonathan Cameron static MemTxResult cxl_read_cfmws(void *opaque, hwaddr addr, uint64_t *data,
247eb19d907SJonathan Cameron                                   unsigned size, MemTxAttrs attrs)
248eb19d907SJonathan Cameron {
249eb19d907SJonathan Cameron     CXLFixedWindow *fw = opaque;
250eb19d907SJonathan Cameron     PCIDevice *d;
251eb19d907SJonathan Cameron 
252eb19d907SJonathan Cameron     d = cxl_cfmws_find_device(fw, addr);
253eb19d907SJonathan Cameron     if (d == NULL) {
254eb19d907SJonathan Cameron         *data = 0;
255eb19d907SJonathan Cameron         /* Reads to invalid address return poison */
256eb19d907SJonathan Cameron         return MEMTX_ERROR;
257eb19d907SJonathan Cameron     }
258eb19d907SJonathan Cameron 
259eb19d907SJonathan Cameron     return cxl_type3_read(d, addr + fw->base, data, size, attrs);
260eb19d907SJonathan Cameron }
261eb19d907SJonathan Cameron 
cxl_write_cfmws(void * opaque,hwaddr addr,uint64_t data,unsigned size,MemTxAttrs attrs)262eb19d907SJonathan Cameron static MemTxResult cxl_write_cfmws(void *opaque, hwaddr addr,
263eb19d907SJonathan Cameron                                    uint64_t data, unsigned size,
264eb19d907SJonathan Cameron                                    MemTxAttrs attrs)
265eb19d907SJonathan Cameron {
266eb19d907SJonathan Cameron     CXLFixedWindow *fw = opaque;
267eb19d907SJonathan Cameron     PCIDevice *d;
268eb19d907SJonathan Cameron 
269eb19d907SJonathan Cameron     d = cxl_cfmws_find_device(fw, addr);
270eb19d907SJonathan Cameron     if (d == NULL) {
271eb19d907SJonathan Cameron         /* Writes to invalid address are silent */
272eb19d907SJonathan Cameron         return MEMTX_OK;
273eb19d907SJonathan Cameron     }
274eb19d907SJonathan Cameron 
275eb19d907SJonathan Cameron     return cxl_type3_write(d, addr + fw->base, data, size, attrs);
276eb19d907SJonathan Cameron }
277eb19d907SJonathan Cameron 
278eb19d907SJonathan Cameron const MemoryRegionOps cfmws_ops = {
279eb19d907SJonathan Cameron     .read_with_attrs = cxl_read_cfmws,
280eb19d907SJonathan Cameron     .write_with_attrs = cxl_write_cfmws,
281eb19d907SJonathan Cameron     .endianness = DEVICE_LITTLE_ENDIAN,
282eb19d907SJonathan Cameron     .valid = {
283eb19d907SJonathan Cameron         .min_access_size = 1,
284eb19d907SJonathan Cameron         .max_access_size = 8,
285eb19d907SJonathan Cameron         .unaligned = true,
286eb19d907SJonathan Cameron     },
287eb19d907SJonathan Cameron     .impl = {
288eb19d907SJonathan Cameron         .min_access_size = 1,
289eb19d907SJonathan Cameron         .max_access_size = 8,
290eb19d907SJonathan Cameron         .unaligned = true,
291eb19d907SJonathan Cameron     },
292eb19d907SJonathan Cameron };
29303b39fcfSJonathan Cameron 
machine_get_cxl(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)29403b39fcfSJonathan Cameron static void machine_get_cxl(Object *obj, Visitor *v, const char *name,
29503b39fcfSJonathan Cameron                             void *opaque, Error **errp)
29603b39fcfSJonathan Cameron {
29703b39fcfSJonathan Cameron     CXLState *cxl_state = opaque;
29803b39fcfSJonathan Cameron     bool value = cxl_state->is_enabled;
29903b39fcfSJonathan Cameron 
30003b39fcfSJonathan Cameron     visit_type_bool(v, name, &value, errp);
30103b39fcfSJonathan Cameron }
30203b39fcfSJonathan Cameron 
machine_set_cxl(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)30303b39fcfSJonathan Cameron static void machine_set_cxl(Object *obj, Visitor *v, const char *name,
30403b39fcfSJonathan Cameron                             void *opaque, Error **errp)
30503b39fcfSJonathan Cameron {
30603b39fcfSJonathan Cameron     CXLState *cxl_state = opaque;
30703b39fcfSJonathan Cameron     bool value;
30803b39fcfSJonathan Cameron 
30903b39fcfSJonathan Cameron     if (!visit_type_bool(v, name, &value, errp)) {
31003b39fcfSJonathan Cameron         return;
31103b39fcfSJonathan Cameron     }
31203b39fcfSJonathan Cameron     cxl_state->is_enabled = value;
31303b39fcfSJonathan Cameron }
31403b39fcfSJonathan Cameron 
machine_get_cfmw(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)31503b39fcfSJonathan Cameron static void machine_get_cfmw(Object *obj, Visitor *v, const char *name,
31603b39fcfSJonathan Cameron                              void *opaque, Error **errp)
31703b39fcfSJonathan Cameron {
318*a207d5f8SZhao Liu     CXLState *state = opaque;
319*a207d5f8SZhao Liu     CXLFixedMemoryWindowOptionsList **list = &state->cfmw_list;
32003b39fcfSJonathan Cameron 
32103b39fcfSJonathan Cameron     visit_type_CXLFixedMemoryWindowOptionsList(v, name, list, errp);
32203b39fcfSJonathan Cameron }
32303b39fcfSJonathan Cameron 
machine_set_cfmw(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)32403b39fcfSJonathan Cameron static void machine_set_cfmw(Object *obj, Visitor *v, const char *name,
32503b39fcfSJonathan Cameron                              void *opaque, Error **errp)
32603b39fcfSJonathan Cameron {
32703b39fcfSJonathan Cameron     CXLState *state = opaque;
32803b39fcfSJonathan Cameron     CXLFixedMemoryWindowOptionsList *cfmw_list = NULL;
32903b39fcfSJonathan Cameron     CXLFixedMemoryWindowOptionsList *it;
33003b39fcfSJonathan Cameron 
33103b39fcfSJonathan Cameron     visit_type_CXLFixedMemoryWindowOptionsList(v, name, &cfmw_list, errp);
33203b39fcfSJonathan Cameron     if (!cfmw_list) {
33303b39fcfSJonathan Cameron         return;
33403b39fcfSJonathan Cameron     }
33503b39fcfSJonathan Cameron 
33603b39fcfSJonathan Cameron     for (it = cfmw_list; it; it = it->next) {
33703b39fcfSJonathan Cameron         cxl_fixed_memory_window_config(state, it->value, errp);
33803b39fcfSJonathan Cameron     }
33903b39fcfSJonathan Cameron     state->cfmw_list = cfmw_list;
34003b39fcfSJonathan Cameron }
34103b39fcfSJonathan Cameron 
cxl_machine_init(Object * obj,CXLState * state)34203b39fcfSJonathan Cameron void cxl_machine_init(Object *obj, CXLState *state)
34303b39fcfSJonathan Cameron {
34403b39fcfSJonathan Cameron     object_property_add(obj, "cxl", "bool", machine_get_cxl,
34503b39fcfSJonathan Cameron                         machine_set_cxl, NULL, state);
34603b39fcfSJonathan Cameron     object_property_set_description(obj, "cxl",
34703b39fcfSJonathan Cameron                                     "Set on/off to enable/disable "
34803b39fcfSJonathan Cameron                                     "CXL instantiation");
34903b39fcfSJonathan Cameron 
35003b39fcfSJonathan Cameron     object_property_add(obj, "cxl-fmw", "CXLFixedMemoryWindow",
35103b39fcfSJonathan Cameron                         machine_get_cfmw, machine_set_cfmw,
35203b39fcfSJonathan Cameron                         NULL, state);
35303b39fcfSJonathan Cameron     object_property_set_description(obj, "cxl-fmw",
35403b39fcfSJonathan Cameron                                     "CXL Fixed Memory Windows (array)");
35503b39fcfSJonathan Cameron }
3567bd1900bSJonathan Cameron 
cxl_hook_up_pxb_registers(PCIBus * bus,CXLState * state,Error ** errp)3577bd1900bSJonathan Cameron void cxl_hook_up_pxb_registers(PCIBus *bus, CXLState *state, Error **errp)
3587bd1900bSJonathan Cameron {
3597bd1900bSJonathan Cameron     /* Walk the pci busses looking for pxb busses to hook up */
3607bd1900bSJonathan Cameron     if (bus) {
3617bd1900bSJonathan Cameron         QLIST_FOREACH(bus, &bus->child, sibling) {
3627bd1900bSJonathan Cameron             if (!pci_bus_is_root(bus)) {
3637bd1900bSJonathan Cameron                 continue;
3647bd1900bSJonathan Cameron             }
3657bd1900bSJonathan Cameron             if (pci_bus_is_cxl(bus)) {
3667bd1900bSJonathan Cameron                 if (!state->is_enabled) {
3677bd1900bSJonathan Cameron                     error_setg(errp, "CXL host bridges present, but cxl=off");
3687bd1900bSJonathan Cameron                     return;
3697bd1900bSJonathan Cameron                 }
3707bd1900bSJonathan Cameron                 pxb_cxl_hook_up_registers(state, bus, errp);
3717bd1900bSJonathan Cameron             }
3727bd1900bSJonathan Cameron         }
3737bd1900bSJonathan Cameron     }
3747bd1900bSJonathan Cameron }
375