xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Oleksandr Tyshchenko <olekstysh@gmail.com>
To: xen-devel@lists.xenproject.org
Cc: "Oleksandr Andrushchenko" <oleksandr_andrushchenko@epam.com>,
	"Roger Pau Monné" <roger.pau@citrix.com>
Subject: [PATCH V7 07/11] vpci/header: emulate PCI_COMMAND register for guests
Date: Tue, 19 Jul 2022 20:42:49 +0300	[thread overview]
Message-ID: <20220719174253.541965-8-olekstysh@gmail.com> (raw)
In-Reply-To: <20220719174253.541965-1-olekstysh@gmail.com>

From: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>

Xen and/or Dom0 may have put values in PCI_COMMAND which they expect
to remain unaltered. PCI_COMMAND_SERR bit is a good example: while the
guest's view of this will want to be zero initially, the host having set
it to 1 may not easily be overwritten with 0, or else we'd effectively
imply giving the guest control of the bit. Thus, PCI_COMMAND register needs
proper emulation in order to honor host's settings.

There are examples of emulators [1], [2] which already deal with PCI_COMMAND
register emulation and it seems that at most they care about is the only INTx
bit (besides IO/memory enable and bus master which are write through).
It could be because in order to properly emulate the PCI_COMMAND register
we need to know about the whole PCI topology, e.g. if any setting in device's
command register is aligned with the upstream port etc.
This makes me think that because of this complexity others just ignore that.
Neither I think this can easily be done in Xen case.

According to "PCI LOCAL BUS SPECIFICATION, REV. 3.0", section "6.2.2
Device Control" the reset state of the command register is typically 0,
so when assigning a PCI device use 0 as the initial state for the guest's view
of the command register.

For now our emulation only makes sure INTx is set according to the host
requirements, i.e. depending on MSI/MSI-X enabled state.

This implementation and the decision to only emulate INTx bit for now
is based on the previous discussion at [3].

[1] https://github.com/qemu/qemu/blob/master/hw/xen/xen_pt_config_init.c#L310
[2] https://github.com/projectacrn/acrn-hypervisor/blob/master/hypervisor/hw/pci.c#L336
[3] https://patchwork.kernel.org/project/xen-devel/patch/20210903100831.177748-9-andr2000@gmail.com/

Signed-off-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
---
Since v6:
- fold guest's logic into cmd_write
- implement cmd_read, so we can report emulated INTx state to guests
- introduce header->guest_cmd to hold the emulated state of the
  PCI_COMMAND register for guests
- OT: rebased
- OT: add cf_check specifier to cmd_read()
Since v5:
- add additional check for MSI-X enabled while altering INTX bit
- make sure INTx disabled while guests enable MSI/MSI-X
Since v3:
- gate more code on CONFIG_HAS_MSI
- removed logic for the case when MSI/MSI-X not enabled
---
 xen/drivers/vpci/header.c | 38 +++++++++++++++++++++++++++++++++++++-
 xen/drivers/vpci/msi.c    |  4 ++++
 xen/drivers/vpci/msix.c   |  4 ++++
 xen/include/xen/vpci.h    |  3 +++
 4 files changed, 48 insertions(+), 1 deletion(-)

diff --git a/xen/drivers/vpci/header.c b/xen/drivers/vpci/header.c
index 4e6547a54d..2ce69a63a2 100644
--- a/xen/drivers/vpci/header.c
+++ b/xen/drivers/vpci/header.c
@@ -443,11 +443,27 @@ static int modify_bars(const struct pci_dev *pdev, uint16_t cmd, bool rom_only)
     return 0;
 }
 
+/* TODO: Add proper emulation for all bits of the command register. */
 static void cf_check cmd_write(
     const struct pci_dev *pdev, unsigned int reg, uint32_t cmd, void *data)
 {
     uint16_t current_cmd = pci_conf_read16(pdev->sbdf, reg);
 
+    if ( !is_hardware_domain(pdev->domain) )
+    {
+        struct vpci_header *header = data;
+
+        header->guest_cmd = cmd;
+#ifdef CONFIG_HAS_PCI_MSI
+        if ( pdev->vpci->msi->enabled || pdev->vpci->msix->enabled )
+            /*
+             * Guest wants to enable INTx, but it can't be enabled
+             * if MSI/MSI-X enabled.
+             */
+            cmd |= PCI_COMMAND_INTX_DISABLE;
+#endif
+    }
+
     /*
      * Let Dom0 play with all the bits directly except for the memory
      * decoding one.
@@ -464,6 +480,19 @@ static void cf_check cmd_write(
         pci_conf_write16(pdev->sbdf, reg, cmd);
 }
 
+static uint32_t cf_check cmd_read(
+    const struct pci_dev *pdev, unsigned int reg, void *data)
+{
+    if ( !is_hardware_domain(pdev->domain) )
+    {
+        struct vpci_header *header = data;
+
+        return header->guest_cmd;
+    }
+
+    return pci_conf_read16(pdev->sbdf, reg);
+}
+
 static void cf_check bar_write(
     const struct pci_dev *pdev, unsigned int reg, uint32_t val, void *data)
 {
@@ -665,8 +694,15 @@ static int cf_check init_bars(struct pci_dev *pdev)
         return -EOPNOTSUPP;
     }
 
+    /*
+     * According to "PCI LOCAL BUS SPECIFICATION, REV. 3.0", section "6.2.2
+     * Device Control" the reset state of the command register is
+     * typically all 0's, so this is used as initial value for the guests.
+     */
+    ASSERT(header->guest_cmd == 0);
+
     /* Setup a handler for the command register. */
-    rc = vpci_add_register(pdev->vpci, vpci_hw_read16, cmd_write, PCI_COMMAND,
+    rc = vpci_add_register(pdev->vpci, cmd_read, cmd_write, PCI_COMMAND,
                            2, header);
     if ( rc )
         return rc;
diff --git a/xen/drivers/vpci/msi.c b/xen/drivers/vpci/msi.c
index d864f740cf..c8c495e2d7 100644
--- a/xen/drivers/vpci/msi.c
+++ b/xen/drivers/vpci/msi.c
@@ -70,6 +70,10 @@ static void cf_check control_write(
 
         if ( vpci_msi_arch_enable(msi, pdev, vectors) )
             return;
+
+        /* Make sure guest doesn't enable INTx while enabling MSI. */
+        if ( !is_hardware_domain(pdev->domain) )
+            pci_intx(pdev, false);
     }
     else
         vpci_msi_arch_disable(msi, pdev);
diff --git a/xen/drivers/vpci/msix.c b/xen/drivers/vpci/msix.c
index 35cc9280f4..06f84b8b02 100644
--- a/xen/drivers/vpci/msix.c
+++ b/xen/drivers/vpci/msix.c
@@ -92,6 +92,10 @@ static void cf_check control_write(
         for ( i = 0; i < msix->max_entries; i++ )
             if ( !msix->entries[i].masked && msix->entries[i].updated )
                 update_entry(&msix->entries[i], pdev, i);
+
+        /* Make sure guest doesn't enable INTx while enabling MSI-X. */
+        if ( !is_hardware_domain(pdev->domain) )
+            pci_intx(pdev, false);
     }
     else if ( !new_enabled && msix->enabled )
     {
diff --git a/xen/include/xen/vpci.h b/xen/include/xen/vpci.h
index 6332659c4a..1010f68c28 100644
--- a/xen/include/xen/vpci.h
+++ b/xen/include/xen/vpci.h
@@ -87,6 +87,9 @@ struct vpci {
         } bars[PCI_HEADER_NORMAL_NR_BARS + 1];
         /* At most 6 BARS + 1 expansion ROM BAR. */
 
+        /* Guest view of the PCI_COMMAND register. */
+        uint16_t guest_cmd;
+
         /*
          * Store whether the ROM enable bit is set (doesn't imply ROM BAR
          * is mapped into guest p2m) if there's a ROM BAR on the device.
-- 
2.25.1



  parent reply	other threads:[~2022-07-19 17:43 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-07-19 17:42 [PATCH V7 00/11] PCI devices passthrough on Arm, part 3 Oleksandr Tyshchenko
2022-07-19 17:42 ` [PATCH V7 01/11] xen/pci: arm: add stub for is_memory_hole Oleksandr Tyshchenko
2022-07-29 16:28   ` Oleksandr
2022-08-03  9:29     ` Rahul Singh
2022-08-03 14:18       ` Oleksandr
2022-07-19 17:42 ` [PATCH V7 02/11] vpci: add hooks for PCI device assign/de-assign Oleksandr Tyshchenko
2022-07-27 10:03   ` Jan Beulich
2022-07-27 14:01     ` Oleksandr
2022-07-27 14:35       ` Jan Beulich
2022-07-27 16:49         ` Oleksandr
2022-07-19 17:42 ` [PATCH V7 03/11] vpci/header: implement guest BAR register handlers Oleksandr Tyshchenko
2022-07-27 10:15   ` Jan Beulich
2022-07-27 16:17     ` Oleksandr
2022-07-28  7:01       ` Jan Beulich
2022-07-28 14:56         ` Oleksandr
2022-07-19 17:42 ` [PATCH V7 04/11] rangeset: add RANGESETF_no_print flag Oleksandr Tyshchenko
2022-07-26 14:48   ` Rahul Singh
2022-07-19 17:42 ` [PATCH V7 05/11] vpci/header: handle p2m range sets per BAR Oleksandr Tyshchenko
2022-07-19 17:42 ` [PATCH V7 06/11] vpci/header: program p2m with guest BAR view Oleksandr Tyshchenko
2022-07-27 10:19   ` Jan Beulich
2022-07-27 17:06     ` Oleksandr
2022-07-28  7:04       ` Jan Beulich
2022-07-19 17:42 ` Oleksandr Tyshchenko [this message]
2022-07-26 15:30   ` [PATCH V7 07/11] vpci/header: emulate PCI_COMMAND register for guests Jan Beulich
2022-07-27 17:30     ` Oleksandr
2022-07-19 17:42 ` [PATCH V7 08/11] vpci/header: reset the command register when adding devices Oleksandr Tyshchenko
2022-07-26 15:09   ` Rahul Singh
2022-07-26 15:23   ` Jan Beulich
2022-07-27  8:58     ` Oleksandr
2022-07-27  9:46       ` Jan Beulich
2022-07-27 16:53         ` Oleksandr
2022-07-19 17:42 ` [PATCH V7 09/11] vpci: add initial support for virtual PCI bus topology Oleksandr Tyshchenko
2022-07-27 10:32   ` Jan Beulich
2022-07-28 14:16     ` Oleksandr
2022-07-28 14:26       ` Jan Beulich
2022-07-28 14:41         ` Oleksandr
2022-07-19 17:42 ` [PATCH V7 10/11] xen/arm: translate virtual PCI bus topology for guests Oleksandr Tyshchenko
2022-07-26 15:16   ` Jan Beulich
2022-07-27 17:54     ` Oleksandr
2022-07-27 19:39       ` Oleksandr
2022-07-28  7:15         ` Jan Beulich
2022-07-28 16:35           ` Oleksandr
2022-07-29  6:06             ` Jan Beulich
2022-07-29 16:26               ` Oleksandr
2022-07-19 17:42 ` [PATCH V7 11/11] xen/arm: account IO handlers for emulated PCI MSI-X Oleksandr Tyshchenko
2022-07-26 14:50   ` Rahul Singh
2022-07-26 13:47 ` [PATCH V7 00/11] PCI devices passthrough on Arm, part 3 Rahul Singh
2022-07-26 15:18   ` Oleksandr Tyshchenko

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=20220719174253.541965-8-olekstysh@gmail.com \
    --to=olekstysh@gmail.com \
    --cc=oleksandr_andrushchenko@epam.com \
    --cc=roger.pau@citrix.com \
    --cc=xen-devel@lists.xenproject.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).