On Fri, May 16, 2025 at 05:44:34AM +0000, Zhijian Li (Fujitsu) wrote: > > > On 13/05/2025 19:14, Jonathan Cameron via wrote: > > Previously these somewhat device like structures were tracked using a list > > in the CXLState in each machine. This is proving restrictive in a few > > cases where we need to iterate through these without being aware of the > > machine type. Just make them sysbus devices. > Make sense. > > Minor comments inline > > > > > Restrict them to not user created as they need to be visible to early > > stages of machine init given effects on the memory map. > > > > This change both simplifies state tracking and enables features needed > > for performance optimization and hotness tracking by making it possible > > to retrieve the fixed memory window on actions elsewhere in the topology. > > > > In some cases the ordering of the Fixed Memory Windows matters. > > For those utility functions provide a GSList sorted by the window index. > > This ensures that we get consistency across: > > - ordering in the command line > > - ordering of the host PA ranges > > - ordering of ACPI CEDT structures describing the CFMWS. > > > > Other aspects don't have this constraint. For those direct iteration > > of the underlying hash structures is fine. > > > > Signed-off-by: Jonathan Cameron <jonathan.came...@huawei.com> > > --- > > I think Peter Maydell suggested this a long time back when > > the original CXL support series was under review but not 100% sure. > > --- > > include/hw/cxl/cxl.h | 3 + > > include/hw/cxl/cxl_host.h | 4 +- > > hw/acpi/cxl.c | 83 +++++++++++-------- > > hw/cxl/cxl-host-stubs.c | 6 +- > > hw/cxl/cxl-host.c | 169 +++++++++++++++++++++++++++++++------- > > hw/i386/pc.c | 51 ++++++------ > > 6 files changed, 223 insertions(+), 93 deletions(-) > > > > diff --git a/include/hw/cxl/cxl.h b/include/hw/cxl/cxl.h > > index b2bcce7ed6..a610795c87 100644 > > --- a/include/hw/cxl/cxl.h > > +++ b/include/hw/cxl/cxl.h > > @@ -27,6 +27,7 @@ > > typedef struct PXBCXLDev PXBCXLDev; > > > > typedef struct CXLFixedWindow { > > + SysBusDevice parent_obj; > > int index; > > uint64_t size; > > char **targets; > > @@ -38,6 +39,8 @@ typedef struct CXLFixedWindow { > > MemoryRegion mr; > > hwaddr base; > > } CXLFixedWindow; > > +#define TYPE_CXL_FMW "cxl-fmw" > > +OBJECT_DECLARE_SIMPLE_TYPE(CXLFixedWindow, CXL_FMW) > > > > typedef struct CXLState { > > bool is_enabled; > > diff --git a/include/hw/cxl/cxl_host.h b/include/hw/cxl/cxl_host.h > > index c9bc9c7c50..6dce2cde07 100644 > > --- a/include/hw/cxl/cxl_host.h > > +++ b/include/hw/cxl/cxl_host.h > > @@ -14,8 +14,10 @@ > > #define CXL_HOST_H > > > > void cxl_machine_init(Object *obj, CXLState *state); > > -void cxl_fmws_link_targets(CXLState *stat, Error **errp); > > +void cxl_fmws_link_targets(Error **errp); > > void cxl_hook_up_pxb_registers(PCIBus *bus, CXLState *state, Error > > **errp); > > +hwaddr cxl_fmws_set_memmap_and_update_mmio(hwaddr base, hwaddr max_addr); > > +GSList *cxl_fmws_get_all_sorted(void); > > > > extern const MemoryRegionOps cfmws_ops; > > > > diff --git a/hw/acpi/cxl.c b/hw/acpi/cxl.c > > index 9cd7905ea2..20806e5dd4 100644 > > --- a/hw/acpi/cxl.c > > +++ b/hw/acpi/cxl.c > > @@ -22,6 +22,7 @@ > > #include "hw/pci/pci_bridge.h" > > #include "hw/pci/pci_host.h" > > #include "hw/cxl/cxl.h" > > +#include "hw/cxl/cxl_host.h" > > #include "hw/mem/memory-device.h" > > #include "hw/acpi/acpi.h" > > #include "hw/acpi/aml-build.h" > > @@ -135,56 +136,62 @@ static void cedt_build_chbs(GArray *table_data, > > PXBCXLDev *cxl) > > * Interleave ways encoding in CXL 2.0 ECN: 3, 6, 12 and 16-way memory > > * interleaving. > > */ > > -static void cedt_build_cfmws(GArray *table_data, CXLState *cxls) > > +static int cedt_build_cfmws(Object *obj, void *opaque) > > Too much unrelated indent updates in this function I think that is because now the function only process one cfw, while it used to process all. So the loop is no longer needed within this function.
fan > > > > { > > - GList *it; > > + struct CXLFixedWindow *fw; > > + Aml *cedt = opaque; > > + GArray *table_data = cedt->buf; > > + int i; > > > > - for (it = cxls->fixed_windows; it; it = it->next) { > > - CXLFixedWindow *fw = it->data; > > - int i; > > + if (!object_dynamic_cast(obj, TYPE_CXL_FMW)) { > > + return 0; > > Never reach here? It seems the caller has ensured passing TYPE_CXL_FMW obj. > > > > > > + } > > + fw = CXL_FMW(obj); > > > > - /* Type */ > > - build_append_int_noprefix(table_data, 1, 1); > > + /* Type */ > > + build_append_int_noprefix(table_data, 1, 1); > > > > - /* Reserved */ > > - build_append_int_noprefix(table_data, 0, 1); > > + /* Reserved */ > > + build_append_int_noprefix(table_data, 0, 1); > > > > - /* Record Length */ > > - build_append_int_noprefix(table_data, 36 + 4 * fw->num_targets, 2); > > + /* Record Length */ > > + build_append_int_noprefix(table_data, 36 + 4 * fw->num_targets, 2); > > > > - /* Reserved */ > > - build_append_int_noprefix(table_data, 0, 4); > > + /* Reserved */ > > + build_append_int_noprefix(table_data, 0, 4); > > > > - /* Base HPA */ > > - build_append_int_noprefix(table_data, fw->mr.addr, 8); > > + /* Base HPA */ > > + build_append_int_noprefix(table_data, fw->mr.addr, 8); > > > > - /* Window Size */ > > - build_append_int_noprefix(table_data, fw->size, 8); > > + /* Window Size */ > > + build_append_int_noprefix(table_data, fw->size, 8); > > > > - /* Host Bridge Interleave Ways */ > > - build_append_int_noprefix(table_data, fw->enc_int_ways, 1); > > + /* Host Bridge Interleave Ways */ > > + build_append_int_noprefix(table_data, fw->enc_int_ways, 1); > > > > - /* Host Bridge Interleave Arithmetic */ > > - build_append_int_noprefix(table_data, 0, 1); > > + /* Host Bridge Interleave Arithmetic */ > > + build_append_int_noprefix(table_data, 0, 1); > > > > - /* Reserved */ > > - build_append_int_noprefix(table_data, 0, 2); > > + /* Reserved */ > > + build_append_int_noprefix(table_data, 0, 2); > > > > - /* Host Bridge Interleave Granularity */ > > - build_append_int_noprefix(table_data, fw->enc_int_gran, 4); > > + /* Host Bridge Interleave Granularity */ > > + build_append_int_noprefix(table_data, fw->enc_int_gran, 4); > > > > - /* Window Restrictions */ > > - build_append_int_noprefix(table_data, 0x0f, 2); /* No restrictions > > */ > > + /* Window Restrictions */ > > + build_append_int_noprefix(table_data, 0x0f, 2); > > > > - /* QTG ID */ > > - build_append_int_noprefix(table_data, 0, 2); > > + /* QTG ID */ > > + build_append_int_noprefix(table_data, 0, 2); > > > > - /* Host Bridge List (list of UIDs - currently bus_nr) */ > > - for (i = 0; i < fw->num_targets; i++) { > > - g_assert(fw->target_hbs[i]); > > - build_append_int_noprefix(table_data, > > PXB_DEV(fw->target_hbs[i])->bus_nr, 4); > > - } > > + /* Host Bridge List (list of UIDs - currently bus_nr) */ > > + for (i = 0; i < fw->num_targets; i++) { > > + g_assert(fw->target_hbs[i]); > > + build_append_int_noprefix(table_data, > > + PXB_DEV(fw->target_hbs[i])->bus_nr, 4); > > } > > + > > + return 0; > > } > > > > static int cxl_foreach_pxb_hb(Object *obj, void *opaque) > > @@ -202,6 +209,7 @@ void cxl_build_cedt(GArray *table_offsets, GArray > > *table_data, > > BIOSLinker *linker, const char *oem_id, > > const char *oem_table_id, CXLState *cxl_state) > > { > > + GSList *cfmws_list, *iter; > > Aml *cedt; > > AcpiTable table = { .sig = "CEDT", .rev = 1, .oem_id = oem_id, > > .oem_table_id = oem_table_id }; > > @@ -213,7 +221,12 @@ void cxl_build_cedt(GArray *table_offsets, GArray > > *table_data, > > /* reserve space for CEDT header */ > > > > object_child_foreach_recursive(object_get_root(), cxl_foreach_pxb_hb, > > cedt); > > - cedt_build_cfmws(cedt->buf, cxl_state); > > + > > + cfmws_list = cxl_fmws_get_all_sorted(); > > + for (iter = cfmws_list; iter; iter = iter->next) { > > + cedt_build_cfmws(iter->data, cedt); > > + } > > + g_slist_free(cfmws_list); > > > > /* copy AML table into ACPI tables blob and patch header there */ > > g_array_append_vals(table_data, cedt->buf->data, cedt->buf->len); > > diff --git a/hw/cxl/cxl-host-stubs.c b/hw/cxl/cxl-host-stubs.c > > index cae4afcdde..13eb6bf6a4 100644 > > --- a/hw/cxl/cxl-host-stubs.c > > +++ b/hw/cxl/cxl-host-stubs.c > > @@ -8,8 +8,12 @@ > > #include "hw/cxl/cxl.h" > > #include "hw/cxl/cxl_host.h" > > > > -void cxl_fmws_link_targets(CXLState *stat, Error **errp) {}; > > +void cxl_fmws_link_targets(Error **errp) {}; > > void cxl_machine_init(Object *obj, CXLState *state) {}; > > void cxl_hook_up_pxb_registers(PCIBus *bus, CXLState *state, Error > > **errp) {}; > > +hwaddr cxl_fmws_set_memmap_and_update_mmio(hwaddr base, hwaddr max_addr) > > +{ > > + return base; > > +}; > > > > const MemoryRegionOps cfmws_ops; > > diff --git a/hw/cxl/cxl-host.c b/hw/cxl/cxl-host.c > > index b7aa429ddf..438f2920e1 100644 > > --- a/hw/cxl/cxl-host.c > > +++ b/hw/cxl/cxl-host.c > > @@ -22,12 +22,12 @@ > > #include "hw/pci/pcie_port.h" > > #include "hw/pci-bridge/pci_expander_bridge.h" > > > > -static void cxl_fixed_memory_window_config(CXLState *cxl_state, > > - CXLFixedMemoryWindowOptions > > *object, > > +static void cxl_fixed_memory_window_config(CXLFixedMemoryWindowOptions > > *object, > > int index, Error **errp) > > { > > ERRP_GUARD(); > > - g_autofree CXLFixedWindow *fw = g_malloc0(sizeof(*fw)); > > + DeviceState *dev = qdev_new(TYPE_CXL_FMW); > > + CXLFixedWindow *fw = CXL_FMW(dev); > > strList *target; > > int i; > > > > @@ -67,35 +67,41 @@ static void cxl_fixed_memory_window_config(CXLState > > *cxl_state, > > fw->targets[i] = g_strdup(target->value); > > } > > > > - cxl_state->fixed_windows = g_list_append(cxl_state->fixed_windows, > > - g_steal_pointer(&fw)); > > + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), errp); > > + > > + return; > > } > > > > -void cxl_fmws_link_targets(CXLState *cxl_state, Error **errp) > > +static int cxl_fmws_link(Object *obj, void *opaque) > > { > > - if (cxl_state && cxl_state->fixed_windows) { > > - GList *it; > > - > > - for (it = cxl_state->fixed_windows; it; it = it->next) { > > - CXLFixedWindow *fw = it->data; > > - int i; > > - > > - for (i = 0; i < fw->num_targets; i++) { > > - Object *o; > > - bool ambig; > > - > > - o = object_resolve_path_type(fw->targets[i], > > - TYPE_PXB_CXL_DEV, > > - &ambig); > > - if (!o) { > > - error_setg(errp, "Could not resolve CXLFM target %s", > > - fw->targets[i]); > > - return; > > - } > > - fw->target_hbs[i] = PXB_CXL_DEV(o); > > - } > > + struct CXLFixedWindow *fw; > > + int i; > > + > > + if (!object_dynamic_cast(obj, TYPE_CXL_FMW)) { > > + return 0; > > + } > > + fw = CXL_FMW(obj); > > + > > + for (i = 0; i < fw->num_targets; i++) { > > + Object *o; > > + bool ambig; > > + > > + o = object_resolve_path_type(fw->targets[i], TYPE_PXB_CXL_DEV, > > + &ambig); > > + if (!o) { > > + error_setg(&error_fatal, "Could not resolve CXLFM target %s", > > + fw->targets[i]); > > + return 1; > > } > > + fw->target_hbs[i] = PXB_CXL_DEV(o); > > } > > + return 0; > > +} > > + > > +void cxl_fmws_link_targets(Error **errp) > > +{ > > + /* Order doesn't matter for this, so no need to build list */ > > + object_child_foreach_recursive(object_get_root(), cxl_fmws_link, NULL); > > } > > > > static bool cxl_hdm_find_target(uint32_t *cache_mem, hwaddr addr, > > @@ -335,7 +341,7 @@ static void machine_set_cfmw(Object *obj, Visitor *v, > > const char *name, > > } > > > > for (it = cfmw_list, index = 0; it; it = it->next, index++) { > > - cxl_fixed_memory_window_config(state, it->value, index, errp); > > + cxl_fixed_memory_window_config(it->value, index, errp); > > } > > state->cfmw_list = cfmw_list; > > } > > @@ -373,3 +379,110 @@ void cxl_hook_up_pxb_registers(PCIBus *bus, CXLState > > *state, Error **errp) > > } > > } > > } > > + > > +struct cfmw_update_state { > > + hwaddr base; > > + hwaddr maxaddr; > > +}; > > + > > +static void cxl_fmws_update(Object *obj, void *opaque) > > +{ > > + struct CXLFixedWindow *fw; > > + struct cfmw_update_state *s = opaque; > > + > > + if (!object_dynamic_cast(obj, TYPE_CXL_FMW)) { > > > Never reach here? It seems the caller has ensured passing TYPE_CXL_FMW obj. > > > Thanks > Zhijian > > > + return; > > + } > > + > > + fw = CXL_FMW(obj); > > + if (s->base + fw->size <= s->maxaddr) { > > + fw->base = s->base; > > + sysbus_mmio_map(SYS_BUS_DEVICE(fw), 0, fw->base); > > + s->base += fw->size; > > + } > > + > > + return; > > +} > > + > > +static int cxl_fmws_find(Object *obj, void *opaque) > > +{ > > + GSList **list = opaque; > > + > > + if (!object_dynamic_cast(obj, TYPE_CXL_FMW)) { > > + return 0; > > + } > > + *list = g_slist_prepend(*list, obj); > > + > > + return 0; > > +} > > + > > +static GSList *cxl_fmws_get_all(void) > > +{ > > + GSList *list = NULL; > > + > > + object_child_foreach_recursive(object_get_root(), cxl_fmws_find, > > &list); > > + > > + return list; > > +} > > + > > +static gint cfmws_cmp(gconstpointer a, gconstpointer b, gpointer d) > > +{ > > + const struct CXLFixedWindow *ap = a; > > + const struct CXLFixedWindow *bp = b; > > + > > + return ap->index > bp->index; > > +} > > + > > +GSList *cxl_fmws_get_all_sorted(void) > > +{ > > + return g_slist_sort_with_data(cxl_fmws_get_all(), cfmws_cmp, NULL); > > +} > > + > > +hwaddr cxl_fmws_set_memmap_and_update_mmio(hwaddr base, hwaddr max_addr) > > +{ > > + GSList *cfmws_list, *iter; > > + > > + struct cfmw_update_state cfmwss = { > > + .base = base, > > + .maxaddr = max_addr, > > + }; > > + cfmws_list = cxl_fmws_get_all_sorted(); > > + for (iter = cfmws_list; iter; iter = iter->next) { > > + cxl_fmws_update(iter->data, &cfmwss); > > + } > > + g_slist_free(cfmws_list); > > + > > + return cfmwss.base; > > +} > > + > > +static void cxl_fmw_realize(DeviceState *dev, Error **errp) > > +{ > > + CXLFixedWindow *fw = CXL_FMW(dev); > > + > > + memory_region_init_io(&fw->mr, OBJECT(dev), &cfmws_ops, fw, > > + "cxl-fixed-memory-region", fw->size); > > + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &fw->mr); > > +} > > + > > +static void cxl_fmw_class_init(ObjectClass *klass, const void *data) > > +{ > > + DeviceClass *dc = DEVICE_CLASS(klass); > > + > > + dc->desc = "CXL Fixed Memory Window"; > > + dc->realize = cxl_fmw_realize; > > + /* Reason - created by machines as tightly coupled to machine memory > > map */ > > + dc->user_creatable = false; > > +} > > + > > +static const TypeInfo cxl_fmw_info = { > > + .name = TYPE_CXL_FMW, > > + .parent = TYPE_SYS_BUS_DEVICE, > > + .instance_size = sizeof(CXLFixedWindow), > > + .class_init = cxl_fmw_class_init, > > +}; > > + > > +static void cxl_host_register_types(void) > > +{ > > + type_register_static(&cxl_fmw_info); > > +} > > +type_init(cxl_host_register_types) > > diff --git a/hw/i386/pc.c b/hw/i386/pc.c > > index 70656157ca..9978398876 100644 > > --- a/hw/i386/pc.c > > +++ b/hw/i386/pc.c > > @@ -630,7 +630,7 @@ void pc_machine_done(Notifier *notifier, void *data) > > &error_fatal); > > > > if (pcms->cxl_devices_state.is_enabled) { > > - cxl_fmws_link_targets(&pcms->cxl_devices_state, &error_fatal); > > + cxl_fmws_link_targets(&error_fatal); > > } > > > > /* set the number of CPUs */ > > @@ -739,20 +739,28 @@ static uint64_t pc_get_cxl_range_start(PCMachineState > > *pcms) > > return cxl_base; > > } > > > > -static uint64_t pc_get_cxl_range_end(PCMachineState *pcms) > > +static int cxl_get_fmw_end(Object *obj, void *opaque) > > { > > - uint64_t start = pc_get_cxl_range_start(pcms) + MiB; > > + struct CXLFixedWindow *fw; > > + uint64_t *start = opaque; > > > > - if (pcms->cxl_devices_state.fixed_windows) { > > - GList *it; > > - > > - start = ROUND_UP(start, 256 * MiB); > > - for (it = pcms->cxl_devices_state.fixed_windows; it; it = > > it->next) { > > - CXLFixedWindow *fw = it->data; > > - start += fw->size; > > - } > > + if (!object_dynamic_cast(obj, TYPE_CXL_FMW)) { > > + return 0; > > } > > + fw = CXL_FMW(obj); > > + > > + *start += fw->size; > > > > + return 0; > > +} > > + > > +static uint64_t pc_get_cxl_range_end(PCMachineState *pcms) > > +{ > > + uint64_t start = pc_get_cxl_range_start(pcms) + MiB; > > + > > + /* Ordering doesn't matter so no need to build a sorted list */ > > + object_child_foreach_recursive(object_get_root(), cxl_get_fmw_end, > > + &start); > > return start; > > } > > > > @@ -954,23 +962,10 @@ void pc_memory_init(PCMachineState *pcms, > > cxl_base = pc_get_cxl_range_start(pcms); > > memory_region_init(mr, OBJECT(machine), "cxl_host_reg", cxl_size); > > memory_region_add_subregion(system_memory, cxl_base, mr); > > - cxl_resv_end = cxl_base + cxl_size; > > - if (pcms->cxl_devices_state.fixed_windows) { > > - hwaddr cxl_fmw_base; > > - GList *it; > > - > > - cxl_fmw_base = ROUND_UP(cxl_base + cxl_size, 256 * MiB); > > - for (it = pcms->cxl_devices_state.fixed_windows; it; it = > > it->next) { > > - CXLFixedWindow *fw = it->data; > > - > > - fw->base = cxl_fmw_base; > > - memory_region_init_io(&fw->mr, OBJECT(machine), > > &cfmws_ops, fw, > > - "cxl-fixed-memory-region", fw->size); > > - memory_region_add_subregion(system_memory, fw->base, > > &fw->mr); > > - cxl_fmw_base += fw->size; > > - cxl_resv_end = cxl_fmw_base; > > - } > > - } > > + cxl_base = ROUND_UP(cxl_base + cxl_size, 256 * MiB); > > + > > + cxl_resv_end = cxl_fmws_set_memmap_and_update_mmio(cxl_base, > > + maxphysaddr); > > } > > > > /* Initialize PC system firmware */ -- Fan Ni (From gmail)