On Mon, Oct 26, 2026 at 07:03:24PM +0900, Yukiya Takaki wrote:
> The previously added `hpa_offset` on CXLType3Dev records the offset of a
> device within its CFMW window, but there is no simple helper to obtain the
> full host physical address (HPA) range for a given Type 3 device.
>
> This patch adds `ct3_type3_get_hpm_range()`, which returns the HPA base and
> size for a CXLType3Dev by combining the CFMW base, the per‑device offset
> and the device size. The helper is declared in the header so that other
> code can use it when building tables and regions.
>
> Co-developed-by: Li Zhijian <[email protected]>
> Signed-off-by: Yukiya Takaki <[email protected]>
> ---
> hw/mem/cxl_type3.c | 40 +++++++++++++++++++++++++++++++++++++
> include/hw/cxl/cxl_device.h | 1 +
> 2 files changed, 41 insertions(+)
>
> diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
> index d08a4255c9..811f8e247d 100644
> --- a/hw/mem/cxl_type3.c
> +++ b/hw/mem/cxl_type3.c
> @@ -1358,6 +1358,46 @@ MemTxResult cxl_type3_write(PCIDevice *d, hwaddr
> host_addr, uint64_t data,
> return address_space_write(as, dpa_offset, attrs, &data, size);
> }
>
> +static uint64_t c3t_addr_size(DeviceState *dev)
> +{
> + CXLType3Dev *ct3d = CXL_TYPE3(dev);
> + MemoryRegion *vmr = host_memory_backend_get_memory(ct3d->hostvmem);
> +
I think the reason program-hdm-decoder=true fails on CXL PMEM
topologies as you mentioned in the cover letter is because this function only
calculates size from ct3d->hostvmem, which will pass NULL to
memory_region_size() here.
RAM and PMEM size is already calculated in cxl_setup_memory() in
ct3d->cxl_dstate.static_mem_size
I think this helper can be deleted by directly using static_mem_size in
ct3_type3_get_hpm_range().
Or if you prefer not to support PMEM for this feature at all, you can
reject it in patch 2:
static bool cxl_setup_memory(CXLType3Dev *ct3d, Error **errp) {
...
if (ct3d->program_hdm_decoder &&
(!ct3d->hostvmem || ct3d->hostpmem || ct3d->dc.num_regions)) {
error_setg(errp, "program-hdm-decoder requires volatile-memdev "
"and no persistent or dynamic capacity");
return false;
}
}
> + return memory_region_size(vmr);
> +}
> +
> +static uint64_t c3t_hpa_base(DeviceState *dev)
> +{
> + GSList *cfmws_list, *iter;
> +
> + cfmws_list = cxl_fmws_get_all_sorted();
> + for (iter = cfmws_list; iter; iter = iter->next) {
> + struct CXLFixedWindow *fw;
> +
> + if (!object_dynamic_cast(iter->data, TYPE_CXL_FMW)) {
> + continue;
> + }
> + fw = CXL_FMW(iter->data);
> +
> + PXBCXLDev *pxb = fw->target_hbs[0];
> + if (ct3d_to_cxl_pxb(dev) != pxb->cxl_host_bridge) {
> + continue;
> + }
> +
> + g_slist_free(cfmws_list);
> + return fw->base;
> + }
> + g_slist_free(cfmws_list);
> +
> + return 0;
> +}
> +
> +void ct3_type3_get_hpm_range(CXLType3Dev *dev, uint64_t *base, uint64_t
> *size)
> +{
> + *base = c3t_hpa_base(DEVICE(dev)) + dev->hpa_offset;
> + *size = c3t_addr_size(DEVICE(dev));
*size = dev->cxl_dstate.static_mem_size;
Thanks,
Anisa
> +}
> +
> static void ct3d_reset(DeviceState *dev)
> {
> CXLType3Dev *ct3d = CXL_TYPE3(dev);
> diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h
> index c3a729f8c5..07654f4b62 100644
> --- a/include/hw/cxl/cxl_device.h
> +++ b/include/hw/cxl/cxl_device.h
> @@ -878,6 +878,7 @@ void ct3_clear_region_block_backed(CXLType3Dev *ct3d,
> uint64_t dpa,
> uint64_t len);
> bool ct3_test_region_block_backed(CXLType3Dev *ct3d, uint64_t dpa,
> uint64_t len);
> +void ct3_type3_get_hpm_range(CXLType3Dev *dev, uint64_t *base, uint64_t
> *size);
> void cxl_assign_event_header(CXLEventRecordHdr *hdr,
> const QemuUUID *uuid, uint32_t flags,
> uint8_t length, uint64_t timestamp,
> --
> 2.52.0
>