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)

Reply via email to