xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Roger Pau Monne <roger.pau@citrix.com>
To: xen-devel@lists.xenproject.org
Cc: Andrew Cooper <andrew.cooper3@citrix.com>,
	Paul Durrant <paul.durrant@citrix.com>,
	Jan Beulich <jbeulich@suse.com>,
	boris.ostrovsky@oracle.com,
	Roger Pau Monne <roger.pau@citrix.com>
Subject: [PATCH v2 26/30] xen/x86: add PCIe emulation
Date: Tue, 27 Sep 2016 17:57:21 +0200	[thread overview]
Message-ID: <1474991845-27962-27-git-send-email-roger.pau@citrix.com> (raw)
In-Reply-To: <1474991845-27962-1-git-send-email-roger.pau@citrix.com>

Add a new MMIO handler that traps accesses to PCIe regions, as discovered by
Xen from the MCFG ACPI table. The handler used is the same as the one used
for accesses to the IO PCI configuration space.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
---
Cc: Paul Durrant <paul.durrant@citrix.com>
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
---
 xen/arch/x86/hvm/io.c | 177 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 171 insertions(+), 6 deletions(-)

diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c
index 779babb..088e3ec 100644
--- a/xen/arch/x86/hvm/io.c
+++ b/xen/arch/x86/hvm/io.c
@@ -46,6 +46,8 @@
 #include <xen/iocap.h>
 #include <public/hvm/ioreq.h>
 
+#include "../x86_64/mmconfig.h"
+
 /* Set permissive mode for HVM Dom0 PCI pass-through by default */
 static bool_t opt_dom0permissive = 1;
 boolean_param("dom0permissive", opt_dom0permissive);
@@ -363,7 +365,7 @@ static int hvm_pt_pci_config_access_check(struct hvm_pt_device *d,
 }
 
 static int hvm_pt_pci_read_config(struct hvm_pt_device *d, uint32_t addr,
-                                  uint32_t *data, int len)
+                                  uint32_t *data, int len, bool pcie)
 {
     uint32_t val = 0;
     struct hvm_pt_reg_group *reg_grp_entry = NULL;
@@ -377,7 +379,7 @@ static int hvm_pt_pci_read_config(struct hvm_pt_device *d, uint32_t addr,
     unsigned int func = PCI_FUNC(d->pdev->devfn);
 
     /* Sanity checks. */
-    if ( hvm_pt_pci_config_access_check(d, addr, len) )
+    if ( !pcie && hvm_pt_pci_config_access_check(d, addr, len) )
         return X86EMUL_UNHANDLEABLE;
 
     /* Find register group entry. */
@@ -468,7 +470,7 @@ static int hvm_pt_pci_read_config(struct hvm_pt_device *d, uint32_t addr,
 }
 
 static int hvm_pt_pci_write_config(struct hvm_pt_device *d, uint32_t addr,
-                                    uint32_t val, int len)
+                                    uint32_t val, int len, bool pcie)
 {
     int index = 0;
     struct hvm_pt_reg_group *reg_grp_entry = NULL;
@@ -485,7 +487,7 @@ static int hvm_pt_pci_write_config(struct hvm_pt_device *d, uint32_t addr,
     unsigned int func = PCI_FUNC(d->pdev->devfn);
 
     /* Sanity checks. */
-    if ( hvm_pt_pci_config_access_check(d, addr, len) )
+    if ( !pcie && hvm_pt_pci_config_access_check(d, addr, len) )
         return X86EMUL_UNHANDLEABLE;
 
     /* Find register group entry. */
@@ -677,7 +679,7 @@ static int hw_dpci_portio_read(const struct hvm_io_handler *handler,
     if ( dev != NULL )
     {
         reg = (currd->arch.pci_cf8 & 0xfc) | (addr & 0x3);
-        rc = hvm_pt_pci_read_config(dev, reg, &data32, size);
+        rc = hvm_pt_pci_read_config(dev, reg, &data32, size, false);
         if ( rc == X86EMUL_OKAY )
         {
             read_unlock(&currd->arch.hvm_domain.pt_lock);
@@ -722,7 +724,7 @@ static int hw_dpci_portio_write(const struct hvm_io_handler *handler,
     if ( dev != NULL )
     {
         reg = (currd->arch.pci_cf8 & 0xfc) | (addr & 0x3);
-        rc = hvm_pt_pci_write_config(dev, reg, data32, size);
+        rc = hvm_pt_pci_write_config(dev, reg, data32, size, false);
         if ( rc == X86EMUL_OKAY )
         {
             read_unlock(&currd->arch.hvm_domain.pt_lock);
@@ -1002,6 +1004,166 @@ static const struct hvm_io_ops hw_dpci_portio_ops = {
     .write = hw_dpci_portio_write
 };
 
+static struct acpi_mcfg_allocation *pcie_find_mmcfg(unsigned long addr)
+{
+    int i;
+
+    for ( i = 0; i < pci_mmcfg_config_num; i++ )
+    {
+        unsigned long start, end;
+
+        start = pci_mmcfg_config[i].address;
+        end = pci_mmcfg_config[i].address +
+              ((pci_mmcfg_config[i].end_bus_number + 1) << 20);
+        if ( addr >= start && addr < end )
+            return &pci_mmcfg_config[i];
+    }
+
+    return NULL;
+}
+
+static struct hvm_pt_device *hw_pcie_get_device(unsigned int seg,
+                                                unsigned int bus,
+                                                unsigned int slot,
+                                                unsigned int func)
+{
+    struct hvm_pt_device *dev;
+    struct domain *d = current->domain;
+
+    list_for_each_entry( dev, &d->arch.hvm_domain.pt_devices, entries )
+    {
+        if ( dev->pdev->seg != seg || dev->pdev->bus != bus ||
+             dev->pdev->devfn != PCI_DEVFN(slot, func) )
+            continue;
+
+        return dev;
+    }
+
+    return NULL;
+}
+
+static void pcie_decode_addr(unsigned long addr, unsigned int *bus,
+                             unsigned int *slot, unsigned int *func,
+                             unsigned int *reg)
+{
+
+    *bus = (addr >> 20) & 0xff;
+    *slot = (addr >> 15) & 0x1f;
+    *func = (addr >> 12) & 0x7;
+    *reg = addr & 0xfff;
+}
+
+static int pcie_range(struct vcpu *v, unsigned long addr)
+{
+
+    return pcie_find_mmcfg(addr) != NULL ? 1 : 0;
+}
+
+static int pcie_read(struct vcpu *v, unsigned long addr,
+                     unsigned int len, unsigned long *pval)
+{
+    struct acpi_mcfg_allocation *mmcfg = pcie_find_mmcfg(addr);
+    struct domain *d = v->domain;
+    unsigned int seg, bus, slot, func, reg;
+    struct hvm_pt_device *dev;
+    uint32_t val;
+    int rc;
+
+    ASSERT(mmcfg != NULL);
+
+    if ( len > 4 || len == 3 )
+        return X86EMUL_UNHANDLEABLE;
+
+    addr -= mmcfg->address;
+    seg = mmcfg->pci_segment;
+    pcie_decode_addr(addr, &bus, &slot, &func, &reg);
+
+    read_lock(&d->arch.hvm_domain.pt_lock);
+    dev = hw_pcie_get_device(seg, bus, slot, func);
+    if ( dev != NULL )
+    {
+        rc = hvm_pt_pci_read_config(dev, reg, &val, len, true);
+        if ( rc == X86EMUL_OKAY )
+        {
+            read_unlock(&d->arch.hvm_domain.pt_lock);
+            goto out;
+        }
+    }
+    read_unlock(&d->arch.hvm_domain.pt_lock);
+
+    /* Pass-through */
+    switch ( len )
+    {
+    case 1:
+        val = pci_conf_read8(seg, bus, slot, func, reg);
+        break;
+    case 2:
+        val = pci_conf_read16(seg, bus, slot, func, reg);
+        break;
+    case 4:
+        val = pci_conf_read32(seg, bus, slot, func, reg);
+        break;
+    }
+
+ out:
+    *pval = val;
+    return X86EMUL_OKAY;
+}
+
+static int pcie_write(struct vcpu *v, unsigned long addr,
+                      unsigned int len, unsigned long val)
+{
+    struct acpi_mcfg_allocation *mmcfg = pcie_find_mmcfg(addr);
+    struct domain *d = v->domain;
+    unsigned int seg, bus, slot, func, reg;
+    struct hvm_pt_device *dev;
+    int rc;
+
+    ASSERT(mmcfg != NULL);
+
+    if ( len > 4 || len == 3 )
+        return X86EMUL_UNHANDLEABLE;
+
+    addr -= mmcfg->address;
+    seg = mmcfg->pci_segment;
+    pcie_decode_addr(addr, &bus, &slot, &func, &reg);
+
+    read_lock(&d->arch.hvm_domain.pt_lock);
+    dev = hw_pcie_get_device(seg, bus, slot, func);
+    if ( dev != NULL )
+    {
+        rc = hvm_pt_pci_write_config(dev, reg, val, len, true);
+        if ( rc == X86EMUL_OKAY )
+        {
+            read_unlock(&d->arch.hvm_domain.pt_lock);
+            return rc;
+        }
+    }
+    read_unlock(&d->arch.hvm_domain.pt_lock);
+
+    /* Pass-through */
+    switch ( len )
+    {
+    case 1:
+        pci_conf_write8(seg, bus, slot, func, reg, val);
+        break;
+    case 2:
+        pci_conf_write16(seg, bus, slot, func, reg, val);
+        break;
+    case 4:
+        pci_conf_write32(seg, bus, slot, func, reg, val);
+        break;
+    }
+
+    return X86EMUL_OKAY;
+}
+
+static const struct hvm_mmio_ops pcie_mmio_ops = {
+    .check = pcie_range,
+    .read = pcie_read,
+    .write = pcie_write
+};
+
 void register_dpci_portio_handler(struct domain *d)
 {
     struct hvm_io_handler *handler = hvm_next_io_handler(d);
@@ -1011,7 +1173,10 @@ void register_dpci_portio_handler(struct domain *d)
 
     handler->type = IOREQ_TYPE_PIO;
     if ( is_hardware_domain(d) )
+    {
         handler->ops = &hw_dpci_portio_ops;
+        register_mmio_handler(d, &pcie_mmio_ops);
+    }
     else
         handler->ops = &dpci_portio_ops;
 }
-- 
2.7.4 (Apple Git-66)


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

  parent reply	other threads:[~2016-09-27 15:58 UTC|newest]

Thread overview: 146+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-09-27 15:56 [PATCH v2 00/30] PVHv2 Dom0 Roger Pau Monne
2016-09-27 15:56 ` [PATCH v2 01/30] xen/x86: move setup of the VM86 TSS to the domain builder Roger Pau Monne
2016-09-28 15:35   ` Jan Beulich
2016-09-29 12:57     ` Roger Pau Monne
2016-09-27 15:56 ` [PATCH v2 02/30] xen/x86: remove XENFEAT_hvm_pirqs for PVHv2 guests Roger Pau Monne
2016-09-28 16:03   ` Jan Beulich
2016-09-29 14:17     ` Roger Pau Monne
2016-09-29 16:07       ` Jan Beulich
2016-09-27 15:56 ` [PATCH v2 03/30] xen/x86: fix parameters and return value of *_set_allocation functions Roger Pau Monne
2016-09-28  9:34   ` Tim Deegan
2016-09-29 10:39   ` Jan Beulich
2016-09-29 14:33     ` Roger Pau Monne
2016-09-29 16:09       ` Jan Beulich
2016-09-30 16:48   ` George Dunlap
2016-10-03  8:05   ` Paul Durrant
2016-10-06 11:33     ` Roger Pau Monne
2016-09-27 15:56 ` [PATCH v2 04/30] xen/x86: allow calling {sh/hap}_set_allocation with the idle domain Roger Pau Monne
2016-09-29 10:43   ` Jan Beulich
2016-09-29 14:37     ` Roger Pau Monne
2016-09-29 16:10       ` Jan Beulich
2016-09-30 16:56   ` George Dunlap
2016-09-30 16:56     ` George Dunlap
2016-09-27 15:57 ` [PATCH v2 05/30] xen/x86: assert that local_events_need_delivery is not called by " Roger Pau Monne
2016-09-29 10:45   ` Jan Beulich
2016-09-30  8:32     ` Roger Pau Monne
2016-09-30  8:59       ` Jan Beulich
2016-09-27 15:57 ` [PATCH v2 06/30] x86/paging: introduce paging_set_allocation Roger Pau Monne
2016-09-29 10:51   ` Jan Beulich
2016-09-29 14:51     ` Roger Pau Monne
2016-09-29 16:12       ` Jan Beulich
2016-09-29 16:57         ` Roger Pau Monne
2016-09-30 17:00   ` George Dunlap
2016-09-27 15:57 ` [PATCH v2 07/30] xen/x86: split the setup of Dom0 permissions to a function Roger Pau Monne
2016-09-29 13:47   ` Jan Beulich
2016-09-29 15:53     ` Roger Pau Monne
2016-09-27 15:57 ` [PATCH v2 08/30] xen/x86: do the PCI scan unconditionally Roger Pau Monne
2016-09-29 13:55   ` Jan Beulich
2016-09-29 15:11     ` Roger Pau Monne
2016-09-29 16:14       ` Jan Beulich
2016-09-27 15:57 ` [PATCH v2 09/30] x86/vtd: fix and simplify mapping RMRR regions Roger Pau Monne
2016-09-29 14:18   ` Jan Beulich
2016-09-30 11:27     ` Roger Pau Monne
2016-09-30 13:21       ` Jan Beulich
2016-09-30 15:02         ` Roger Pau Monne
2016-09-30 15:09           ` Jan Beulich
2016-09-27 15:57 ` [PATCH v2 10/30] xen/x86: allow the emulated APICs to be enbled for the hardware domain Roger Pau Monne
2016-09-29 14:26   ` Jan Beulich
2016-09-30 15:44     ` Roger Pau Monne
2016-09-27 15:57 ` [PATCH v2 11/30] xen/x86: split Dom0 build into PV and PVHv2 Roger Pau Monne
2016-09-30 15:03   ` Jan Beulich
2016-10-03 10:09     ` Roger Pau Monne
2016-10-04  6:54       ` Jan Beulich
2016-10-04  7:09         ` Andrew Cooper
2016-09-27 15:57 ` [PATCH v2 12/30] xen/x86: make print_e820_memory_map global Roger Pau Monne
2016-09-30 15:04   ` Jan Beulich
2016-10-03 16:23     ` Roger Pau Monne
2016-10-04  6:47       ` Jan Beulich
2016-09-27 15:57 ` [PATCH v2 13/30] xen: introduce a new format specifier to print sizes in human-readable form Roger Pau Monne
2016-09-28  8:24   ` Juergen Gross
2016-09-28 11:56     ` Roger Pau Monne
2016-09-28 12:01       ` Andrew Cooper
2016-10-03  8:36   ` Paul Durrant
2016-10-11 10:27   ` Roger Pau Monne
2016-09-27 15:57 ` [PATCH v2 14/30] xen/mm: add a ceil sufix to current page calculation routine Roger Pau Monne
2016-09-30 15:20   ` Jan Beulich
2016-09-27 15:57 ` [PATCH v2 15/30] xen/x86: populate PVHv2 Dom0 physical memory map Roger Pau Monne
2016-09-30 15:52   ` Jan Beulich
2016-10-04  9:12     ` Roger Pau Monne
2016-10-04 11:16       ` Jan Beulich
2016-10-11 14:01         ` Roger Pau Monne
2016-10-12 11:51           ` Jan Beulich
2016-10-11 14:06     ` Roger Pau Monne
2016-10-12 11:58       ` Jan Beulich
2016-09-27 15:57 ` [PATCH v2 16/30] xen/x86: parse Dom0 kernel for PVHv2 Roger Pau Monne
2016-10-06 15:14   ` Jan Beulich
2016-10-11 15:02     ` Roger Pau Monne
2016-09-27 15:57 ` [PATCH v2 17/30] xen/x86: setup PVHv2 Dom0 CPUs Roger Pau Monne
2016-10-06 15:20   ` Jan Beulich
2016-10-12 11:06     ` Roger Pau Monne
2016-10-12 11:32       ` Andrew Cooper
2016-10-12 12:02       ` Jan Beulich
2016-09-27 15:57 ` [PATCH v2 18/30] xen/x86: setup PVHv2 Dom0 ACPI tables Roger Pau Monne
2016-10-06 15:40   ` Jan Beulich
2016-10-06 15:48     ` Andrew Cooper
2016-10-12 15:35     ` Roger Pau Monne
2016-10-12 15:55       ` Jan Beulich
2016-10-26 11:35         ` Roger Pau Monne
2016-10-26 14:10           ` Jan Beulich
2016-10-26 15:08             ` Roger Pau Monne
2016-10-26 15:16               ` Jan Beulich
2016-10-26 16:03                 ` Roger Pau Monne
2016-10-27  7:25                   ` Jan Beulich
2016-10-27 11:08                     ` Roger Pau Monne
2016-10-26 17:14                 ` Boris Ostrovsky
2016-10-27  7:27                   ` Jan Beulich
2016-10-27 11:13                   ` Roger Pau Monne
2016-10-27 11:25                     ` Jan Beulich
2016-10-27 13:51                     ` Boris Ostrovsky
2016-10-27 14:02                       ` Jan Beulich
2016-10-27 14:15                         ` Boris Ostrovsky
2016-10-27 14:30                           ` Jan Beulich
2016-10-27 14:40                             ` Boris Ostrovsky
2016-10-27 15:04                               ` Roger Pau Monne
2016-10-27 15:20                                 ` Jan Beulich
2016-10-27 15:37                                   ` Roger Pau Monne
2016-10-28 13:51                                 ` Boris Ostrovsky
2016-09-27 15:57 ` [PATCH v2 19/30] xen/dcpi: add a dpci passthrough handler for hardware domain Roger Pau Monne
2016-10-03  9:02   ` Paul Durrant
2016-10-06 14:31     ` Roger Pau Monne
2016-10-06 15:44   ` Jan Beulich
2016-09-27 15:57 ` [PATCH v2 20/30] xen/x86: add the basic infrastructure to import QEMU passthrough code Roger Pau Monne
2016-10-03  9:54   ` Paul Durrant
2016-10-06 15:08     ` Roger Pau Monne
2016-10-06 15:52       ` Lars Kurth
2016-10-07  9:13       ` Jan Beulich
2016-10-06 15:47   ` Jan Beulich
2016-10-10 12:41   ` Jan Beulich
2016-09-27 15:57 ` [PATCH v2 21/30] xen/pci: split code to size BARs from pci_add_device Roger Pau Monne
2016-10-06 16:00   ` Jan Beulich
2016-09-27 15:57 ` [PATCH v2 22/30] xen/x86: support PVHv2 Dom0 BAR remapping Roger Pau Monne
2016-10-03 10:10   ` Paul Durrant
2016-10-06 15:25     ` Roger Pau Monne
2016-09-27 15:57 ` [PATCH v2 23/30] xen/x86: route legacy PCI interrupts to Dom0 Roger Pau Monne
2016-10-10 13:37   ` Jan Beulich
2016-09-27 15:57 ` [PATCH v2 24/30] x86/vmsi: add MSI emulation for hardware domain Roger Pau Monne
2016-09-27 15:57 ` [PATCH v2 25/30] xen/x86: add all PCI devices to PVHv2 Dom0 Roger Pau Monne
2016-10-10 13:44   ` Jan Beulich
2016-09-27 15:57 ` Roger Pau Monne [this message]
2016-10-03 10:46   ` [PATCH v2 26/30] xen/x86: add PCIe emulation Paul Durrant
2016-10-06 15:53     ` Roger Pau Monne
2016-10-10 13:57   ` Jan Beulich
2016-09-27 15:57 ` [PATCH v2 27/30] x86/msixtbl: disable MSI-X intercepts for domains without an ioreq server Roger Pau Monne
2016-10-10 14:18   ` Jan Beulich
2016-09-27 15:57 ` [PATCH v2 28/30] xen/x86: add MSI-X emulation to PVHv2 Dom0 Roger Pau Monne
2016-10-03 10:57   ` Paul Durrant
2016-10-06 15:58     ` Roger Pau Monne
2016-10-10 16:15   ` Jan Beulich
2016-09-27 15:57 ` [PATCH v2 29/30] xen/x86: allow PVHv2 to perform foreign memory mappings Roger Pau Monne
2016-09-30 17:36   ` George Dunlap
2016-10-10 14:21   ` Jan Beulich
2016-10-10 14:27     ` George Dunlap
2016-10-10 14:50       ` Jan Beulich
2016-10-10 14:58         ` George Dunlap
2016-09-27 15:57 ` [PATCH v2 30/30] xen: allow setting the store pfn HVM parameter Roger Pau Monne
2016-10-03 11:01   ` Paul Durrant
2016-09-28 12:22 ` [PATCH v2 00/30] PVHv2 Dom0 Roger Pau Monne

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=1474991845-27962-27-git-send-email-roger.pau@citrix.com \
    --to=roger.pau@citrix.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=boris.ostrovsky@oracle.com \
    --cc=jbeulich@suse.com \
    --cc=paul.durrant@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).