From: Fan Ni <fan.ni@samsung.com>
To: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Cc: "qemu-devel@nongnu.org" <qemu-devel@nongnu.org>,
Michael Tsirkin <mst@redhat.com>,
Ben Widawsky <bwidawsk@kernel.org>,
"linux-cxl@vger.kernel.org" <linux-cxl@vger.kernel.org>,
"linuxarm@huawei.com" <linuxarm@huawei.com>,
Ira Weiny <ira.weiny@intel.com>,
Dave Jiang <dave.jiang@intel.com>,
"alison.schofield@intel.com" <alison.schofield@intel.com>
Subject: Re: [PATCH 2/2] hw/pxb-cxl: Support passthrough HDM Decoders unless overridden
Date: Thu, 26 Jan 2023 21:57:35 +0000 [thread overview]
Message-ID: <20230126215727.GA203951@bgt-140510-bm03> (raw)
In-Reply-To: <20230125152703.9928-3-Jonathan.Cameron@huawei.com>
On Wed, Jan 25, 2023 at 03:27:03PM +0000, Jonathan Cameron wrote:
> The CXL r3.0 specification allows for there to be no HDM decoders on CXL
> Host Bridges if they have only a single root port. Instead, all accesses
> directed to the host bridge (as specified in CXL Fixed Memory Windows)
> are assumed to be routed to the single root port.
>
> Linux currently assumes this implementation choice. So to simplify testing,
> make QEMU emulation also default to no HDM decoders under these particular
> circumstances, but provide a hdm_for_passthrough boolean option to have
> HDM decoders as previously.
>
> Technically this is breaking backwards compatibility, but given the only
> known software stack used with the QEMU emulation is the Linux kernel
> and this configuration did not work before this change, there are
> unlikely to be any complaints that it now works. The option is retained
> to allow testing of software that does allow for these HDM decoders to exist,
> once someone writes it.
>
> Reported-by: Fan Ni <fan.ni@samsung.com>
> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> ---
> hw/cxl/cxl-host.c | 31 ++++++++++++--------
> hw/pci-bridge/pci_expander_bridge.c | 44 +++++++++++++++++++++++++----
> include/hw/cxl/cxl.h | 1 +
> include/hw/cxl/cxl_component.h | 1 +
> include/hw/pci/pci_bridge.h | 1 +
> 5 files changed, 61 insertions(+), 17 deletions(-)
>
> diff --git a/hw/cxl/cxl-host.c b/hw/cxl/cxl-host.c
> index 3c1ec8732a..6e923ceeaf 100644
> --- a/hw/cxl/cxl-host.c
> +++ b/hw/cxl/cxl-host.c
> @@ -146,21 +146,28 @@ static PCIDevice *cxl_cfmws_find_device(CXLFixedWindow *fw, hwaddr addr)
> return NULL;
> }
>
> - hb_cstate = cxl_get_hb_cstate(hb);
> - if (!hb_cstate) {
> - return NULL;
> - }
> + if (cxl_get_hb_passthrough(hb)) {
> + rp = pcie_find_port_first(hb->bus);
> + if (!rp) {
> + return NULL;
> + }
> + } else {
> + hb_cstate = cxl_get_hb_cstate(hb);
> + if (!hb_cstate) {
> + return NULL;
> + }
>
> - cache_mem = hb_cstate->crb.cache_mem_registers;
> + cache_mem = hb_cstate->crb.cache_mem_registers;
>
> - target_found = cxl_hdm_find_target(cache_mem, addr, &target);
> - if (!target_found) {
> - return NULL;
> - }
> + target_found = cxl_hdm_find_target(cache_mem, addr, &target);
> + if (!target_found) {
> + return NULL;
> + }
>
> - rp = pcie_find_port_by_pn(hb->bus, target);
> - if (!rp) {
> - return NULL;
> + rp = pcie_find_port_by_pn(hb->bus, target);
> + if (!rp) {
> + return NULL;
> + }
> }
>
> d = pci_bridge_get_sec_bus(PCI_BRIDGE(rp))->devices[0];
> diff --git a/hw/pci-bridge/pci_expander_bridge.c b/hw/pci-bridge/pci_expander_bridge.c
> index e752a21292..ead33f0c05 100644
> --- a/hw/pci-bridge/pci_expander_bridge.c
> +++ b/hw/pci-bridge/pci_expander_bridge.c
> @@ -15,6 +15,7 @@
> #include "hw/pci/pci.h"
> #include "hw/pci/pci_bus.h"
> #include "hw/pci/pci_host.h"
> +#include "hw/pci/pcie_port.h"
> #include "hw/qdev-properties.h"
> #include "hw/pci/pci_bridge.h"
> #include "hw/pci-bridge/pci_expander_bridge.h"
> @@ -79,6 +80,13 @@ CXLComponentState *cxl_get_hb_cstate(PCIHostState *hb)
> return &host->cxl_cstate;
> }
>
> +bool cxl_get_hb_passthrough(PCIHostState *hb)
> +{
> + CXLHost *host = PXB_CXL_HOST(hb);
> +
> + return host->passthrough;
> +}
> +
> static int pxb_bus_num(PCIBus *bus)
> {
> PXBDev *pxb = convert_to_pxb(bus->parent_dev);
> @@ -289,15 +297,32 @@ static int pxb_map_irq_fn(PCIDevice *pci_dev, int pin)
> return pin - PCI_SLOT(pxb->devfn);
> }
>
> -static void pxb_dev_reset(DeviceState *dev)
> +static void pxb_cxl_dev_reset(DeviceState *dev)
> {
> CXLHost *cxl = PXB_CXL_DEV(dev)->cxl.cxl_host_bridge;
> CXLComponentState *cxl_cstate = &cxl->cxl_cstate;
> + PCIHostState *hb = PCI_HOST_BRIDGE(cxl);
> uint32_t *reg_state = cxl_cstate->crb.cache_mem_registers;
> uint32_t *write_msk = cxl_cstate->crb.cache_mem_regs_write_mask;
> + int dsp_count = 0;
>
> cxl_component_register_init_common(reg_state, write_msk, CXL2_ROOT_PORT);
> - ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, TARGET_COUNT, 8);
> + /*
> + * The CXL specification allows for host bridges with no HDM decoders
> + * if they only have a single root port.
> + */
> + if (!PXB_DEV(dev)->hdm_for_passthrough) {
> + dsp_count = pcie_count_ds_ports(hb->bus);
> + }
> + /* Initial reset will have 0 dsp so wait until > 0 */
> + if (dsp_count == 1) {
> + cxl->passthrough = true;
> + /* Set Capability ID in header to NONE */
> + ARRAY_FIELD_DP32(reg_state, CXL_HDM_CAPABILITY_HEADER, ID, 0);
> + } else {
> + ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, TARGET_COUNT,
> + 8);
> + }
> }
>
> static gint pxb_compare(gconstpointer a, gconstpointer b)
> @@ -481,9 +506,18 @@ static void pxb_cxl_dev_realize(PCIDevice *dev, Error **errp)
> }
>
> pxb_dev_realize_common(dev, CXL, errp);
> - pxb_dev_reset(DEVICE(dev));
> + pxb_cxl_dev_reset(DEVICE(dev));
> }
>
> +static Property pxb_cxl_dev_properties[] = {
> + /* Note: 0 is not a legal PXB bus number. */
> + DEFINE_PROP_UINT8("bus_nr", PXBDev, bus_nr, 0),
> + DEFINE_PROP_UINT16("numa_node", PXBDev, numa_node, NUMA_NODE_UNASSIGNED),
> + DEFINE_PROP_BOOL("bypass_iommu", PXBDev, bypass_iommu, false),
> + DEFINE_PROP_BOOL("hdm_for_passthrough", PXBDev, hdm_for_passthrough, false),
when setting hdm_for_passthrough to true at the qemu command line, we
will see the segfault issue as before. I think this is expected as it
is the logic in cxl_cfmws_find_device. Wondering if there will be
following fixes to handle the case when hdm_for_passthrough is true.
> + DEFINE_PROP_END_OF_LIST(),
> +};
> +
> static void pxb_cxl_dev_class_init(ObjectClass *klass, void *data)
> {
> DeviceClass *dc = DEVICE_CLASS(klass);
> @@ -497,12 +531,12 @@ static void pxb_cxl_dev_class_init(ObjectClass *klass, void *data)
> */
>
> dc->desc = "CXL Host Bridge";
> - device_class_set_props(dc, pxb_dev_properties);
> + device_class_set_props(dc, pxb_cxl_dev_properties);
> set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
>
> /* Host bridges aren't hotpluggable. FIXME: spec reference */
> dc->hotpluggable = false;
> - dc->reset = pxb_dev_reset;
> + dc->reset = pxb_cxl_dev_reset;
> }
>
> static const TypeInfo pxb_cxl_dev_info = {
> diff --git a/include/hw/cxl/cxl.h b/include/hw/cxl/cxl.h
> index b161be59b7..b2cffbb364 100644
> --- a/include/hw/cxl/cxl.h
> +++ b/include/hw/cxl/cxl.h
> @@ -49,6 +49,7 @@ struct CXLHost {
> PCIHostState parent_obj;
>
> CXLComponentState cxl_cstate;
> + bool passthrough;
> };
>
> #define TYPE_PXB_CXL_HOST "pxb-cxl-host"
> diff --git a/include/hw/cxl/cxl_component.h b/include/hw/cxl/cxl_component.h
> index 8752171f70..b4104b78b5 100644
> --- a/include/hw/cxl/cxl_component.h
> +++ b/include/hw/cxl/cxl_component.h
> @@ -249,6 +249,7 @@ static inline hwaddr cxl_decode_ig(int ig)
> }
>
> CXLComponentState *cxl_get_hb_cstate(PCIHostState *hb);
> +bool cxl_get_hb_passthrough(PCIHostState *hb);
>
> void cxl_doe_cdat_init(CXLComponentState *cxl_cstate, Error **errp);
> void cxl_doe_cdat_release(CXLComponentState *cxl_cstate);
> diff --git a/include/hw/pci/pci_bridge.h b/include/hw/pci/pci_bridge.h
> index 63a7521567..81a058bb2c 100644
> --- a/include/hw/pci/pci_bridge.h
> +++ b/include/hw/pci/pci_bridge.h
> @@ -92,6 +92,7 @@ struct PXBDev {
> uint8_t bus_nr;
> uint16_t numa_node;
> bool bypass_iommu;
> + bool hdm_for_passthrough;
> struct cxl_dev {
> CXLHost *cxl_host_bridge; /* Pointer to a CXLHost */
> } cxl;
> --
> 2.37.2
>
>
next prev parent reply other threads:[~2023-01-26 21:58 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-01-25 15:27 [PATCH 0/2] hw/cxl: Passthrough HDM decoder emulation Jonathan Cameron via
2023-01-25 15:27 ` [PATCH 1/2] hw/pci: Add pcie_count_ds_port() and pcie_find_port_first() helpers Jonathan Cameron via
2023-01-25 15:27 ` [PATCH 2/2] hw/pxb-cxl: Support passthrough HDM Decoders unless overridden Jonathan Cameron via
[not found] ` <CGME20230126215736uscas1p2166334bf8185239cf6ac70053dc386c5@uscas1p2.samsung.com>
2023-01-26 21:57 ` Fan Ni [this message]
2023-01-27 10:01 ` Jonathan Cameron via
2023-01-27 17:02 ` Fan Ni
2023-01-27 17:15 ` Jonathan Cameron via
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230126215727.GA203951@bgt-140510-bm03 \
--to=fan.ni@samsung.com \
--cc=Jonathan.Cameron@huawei.com \
--cc=alison.schofield@intel.com \
--cc=bwidawsk@kernel.org \
--cc=dave.jiang@intel.com \
--cc=ira.weiny@intel.com \
--cc=linux-cxl@vger.kernel.org \
--cc=linuxarm@huawei.com \
--cc=mst@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).