diff mbox

[v2,19/30] xen/dcpi: add a dpci passthrough handler for hardware domain

Message ID 1474991845-27962-20-git-send-email-roger.pau@citrix.com (mailing list archive)
State New, archived
Headers show

Commit Message

Roger Pau Monné Sept. 27, 2016, 3:57 p.m. UTC
This is very similar to the PCI trap used for the traditional PV(H) Dom0.

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         | 72 ++++++++++++++++++++++++++++++++++++++++++-
 xen/arch/x86/traps.c          | 39 -----------------------
 xen/drivers/passthrough/pci.c | 39 +++++++++++++++++++++++
 xen/include/xen/pci.h         |  2 ++
 4 files changed, 112 insertions(+), 40 deletions(-)

Comments

Paul Durrant Oct. 3, 2016, 9:02 a.m. UTC | #1
> -----Original Message-----

> From: Roger Pau Monne [mailto:roger.pau@citrix.com]

> Sent: 27 September 2016 16:57

> To: xen-devel@lists.xenproject.org

> Cc: konrad.wilk@oracle.com; boris.ostrovsky@oracle.com; Roger Pau Monne

> <roger.pau@citrix.com>; Paul Durrant <Paul.Durrant@citrix.com>; Jan

> Beulich <jbeulich@suse.com>; Andrew Cooper

> <Andrew.Cooper3@citrix.com>

> Subject: [PATCH v2 19/30] xen/dcpi: add a dpci passthrough handler for

> hardware domain

> 

> This is very similar to the PCI trap used for the traditional PV(H) Dom0.

> 

> 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         | 72

> ++++++++++++++++++++++++++++++++++++++++++-

>  xen/arch/x86/traps.c          | 39 -----------------------

>  xen/drivers/passthrough/pci.c | 39 +++++++++++++++++++++++

>  xen/include/xen/pci.h         |  2 ++

>  4 files changed, 112 insertions(+), 40 deletions(-)

> 

> diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c index

> 1e7a5f9..31d54dc 100644

> --- a/xen/arch/x86/hvm/io.c

> +++ b/xen/arch/x86/hvm/io.c

> @@ -247,12 +247,79 @@ static int dpci_portio_write(const struct

> hvm_io_handler *handler,

>      return X86EMUL_OKAY;

>  }

> 

> +static bool_t hw_dpci_portio_accept(const struct hvm_io_handler

> *handler,

> +                                    const ioreq_t *p) {

> +    if ( (p->addr == 0xcf8 && p->size == 4) || (p->addr & 0xfffc) == 0xcfc)

> +    {

> +        return 1;

> +    }

> +

> +    return 0;


Why not just return the value of the boolean expression?

> +}

> +

> +static int hw_dpci_portio_read(const struct hvm_io_handler *handler,

> +                            uint64_t addr,

> +                            uint32_t size,

> +                            uint64_t *data) {

> +    struct domain *currd = current->domain;

> +

> +    if ( addr == 0xcf8 )

> +    {

> +        ASSERT(size == 4);

> +        *data = currd->arch.pci_cf8;

> +        return X86EMUL_OKAY;

> +    }

> +

> +    ASSERT((addr & 0xfffc) == 0xcfc);


You could do 'addr &= 3' and simplify the expressions below.

> +    size = min(size, 4 - ((uint32_t)addr & 3));

> +    if ( size == 3 )

> +        size = 2;

> +    if ( pci_cfg_ok(currd, addr & 3, size, NULL) )


Is this the right place to do the check. Can this not be done in the accept op?

> +        *data = pci_conf_read(currd->arch.pci_cf8, addr & 3, size);

> +

> +    return X86EMUL_OKAY;

> +}

> +

> +static int hw_dpci_portio_write(const struct hvm_io_handler *handler,

> +                                uint64_t addr,

> +                                uint32_t size,

> +                                uint64_t data) {

> +    struct domain *currd = current->domain;

> +    uint32_t data32;

> +

> +    if ( addr == 0xcf8 )

> +    {

> +            ASSERT(size == 4);

> +            currd->arch.pci_cf8 = data;

> +            return X86EMUL_OKAY;

> +    }

> +

> +    ASSERT((addr & 0xfffc) == 0xcfc);


'addr &= 3' again here.

  Paul

> +    size = min(size, 4 - ((uint32_t)addr & 3));

> +    if ( size == 3 )

> +        size = 2;

> +    data32 = data;

> +    if ( pci_cfg_ok(currd, addr & 3, size, &data32) )

> +        pci_conf_write(currd->arch.pci_cf8, addr & 3, size, data);

> +

> +    return X86EMUL_OKAY;

> +}

> +

>  static const struct hvm_io_ops dpci_portio_ops = {

>      .accept = dpci_portio_accept,

>      .read = dpci_portio_read,

>      .write = dpci_portio_write

>  };

> 

> +static const struct hvm_io_ops hw_dpci_portio_ops = {

> +    .accept = hw_dpci_portio_accept,

> +    .read = hw_dpci_portio_read,

> +    .write = hw_dpci_portio_write

> +};

> +

>  void register_dpci_portio_handler(struct domain *d)  {

>      struct hvm_io_handler *handler = hvm_next_io_handler(d); @@ -261,7

> +328,10 @@ void register_dpci_portio_handler(struct domain *d)

>          return;

> 

>      handler->type = IOREQ_TYPE_PIO;

> -    handler->ops = &dpci_portio_ops;

> +    if ( is_hardware_domain(d) )

> +        handler->ops = &hw_dpci_portio_ops;

> +    else

> +        handler->ops = &dpci_portio_ops;

>  }

> 

>  /*

> diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index

> 24d173f..f3c5c9e 100644

> --- a/xen/arch/x86/traps.c

> +++ b/xen/arch/x86/traps.c

> @@ -2076,45 +2076,6 @@ static bool_t admin_io_okay(unsigned int port,

> unsigned int bytes,

>      return ioports_access_permitted(d, port, port + bytes - 1);  }

> 

> -static bool_t pci_cfg_ok(struct domain *currd, unsigned int start,

> -                         unsigned int size, uint32_t *write)

> -{

> -    uint32_t machine_bdf;

> -

> -    if ( !is_hardware_domain(currd) )

> -        return 0;

> -

> -    if ( !CF8_ENABLED(currd->arch.pci_cf8) )

> -        return 1;

> -

> -    machine_bdf = CF8_BDF(currd->arch.pci_cf8);

> -    if ( write )

> -    {

> -        const unsigned long *ro_map = pci_get_ro_map(0);

> -

> -        if ( ro_map && test_bit(machine_bdf, ro_map) )

> -            return 0;

> -    }

> -    start |= CF8_ADDR_LO(currd->arch.pci_cf8);

> -    /* AMD extended configuration space access? */

> -    if ( CF8_ADDR_HI(currd->arch.pci_cf8) &&

> -         boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&

> -         boot_cpu_data.x86 >= 0x10 && boot_cpu_data.x86 <= 0x17 )

> -    {

> -        uint64_t msr_val;

> -

> -        if ( rdmsr_safe(MSR_AMD64_NB_CFG, msr_val) )

> -            return 0;

> -        if ( msr_val & (1ULL << AMD64_NB_CFG_CF8_EXT_ENABLE_BIT) )

> -            start |= CF8_ADDR_HI(currd->arch.pci_cf8);

> -    }

> -

> -    return !write ?

> -           xsm_pci_config_permission(XSM_HOOK, currd, machine_bdf,

> -                                     start, start + size - 1, 0) == 0 :

> -           pci_conf_write_intercept(0, machine_bdf, start, size, write) >= 0;

> -}

> -

>  uint32_t guest_io_read(unsigned int port, unsigned int bytes,

>                         struct domain *currd)  { diff --git a/xen/drivers/passthrough/pci.c

> b/xen/drivers/passthrough/pci.c index dd291a2..a53b4c8 100644

> --- a/xen/drivers/passthrough/pci.c

> +++ b/xen/drivers/passthrough/pci.c

> @@ -966,6 +966,45 @@ void pci_check_disable_device(u16 seg, u8 bus, u8

> devfn)

>                       PCI_COMMAND, cword & ~PCI_COMMAND_MASTER);  }

> 

> +bool_t pci_cfg_ok(struct domain *currd, unsigned int start,

> +                         unsigned int size, uint32_t *write) {

> +    uint32_t machine_bdf;

> +

> +    if ( !is_hardware_domain(currd) )

> +        return 0;

> +

> +    if ( !CF8_ENABLED(currd->arch.pci_cf8) )

> +        return 1;

> +

> +    machine_bdf = CF8_BDF(currd->arch.pci_cf8);

> +    if ( write )

> +    {

> +        const unsigned long *ro_map = pci_get_ro_map(0);

> +

> +        if ( ro_map && test_bit(machine_bdf, ro_map) )

> +            return 0;

> +    }

> +    start |= CF8_ADDR_LO(currd->arch.pci_cf8);

> +    /* AMD extended configuration space access? */

> +    if ( CF8_ADDR_HI(currd->arch.pci_cf8) &&

> +         boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&

> +         boot_cpu_data.x86 >= 0x10 && boot_cpu_data.x86 <= 0x17 )

> +    {

> +        uint64_t msr_val;

> +

> +        if ( rdmsr_safe(MSR_AMD64_NB_CFG, msr_val) )

> +            return 0;

> +        if ( msr_val & (1ULL << AMD64_NB_CFG_CF8_EXT_ENABLE_BIT) )

> +            start |= CF8_ADDR_HI(currd->arch.pci_cf8);

> +    }

> +

> +    return !write ?

> +           xsm_pci_config_permission(XSM_HOOK, currd, machine_bdf,

> +                                     start, start + size - 1, 0) == 0 :

> +           pci_conf_write_intercept(0, machine_bdf, start, size, write)

> +>= 0; }

> +

>  /*

>   * scan pci devices to add all existed PCI devices to alldevs_list,

>   * and setup pci hierarchy in array bus2bridge.

> diff --git a/xen/include/xen/pci.h b/xen/include/xen/pci.h index

> 0872401..f191773 100644

> --- a/xen/include/xen/pci.h

> +++ b/xen/include/xen/pci.h

> @@ -162,6 +162,8 @@ const char *parse_pci(const char *, unsigned int *seg,

> unsigned int *bus,

> 

>  bool_t pcie_aer_get_firmware_first(const struct pci_dev *);

> 

> +bool_t pci_cfg_ok(struct domain *, unsigned int, unsigned int, uint32_t

> +*);

> +

>  struct pirq;

>  int msixtbl_pt_register(struct domain *, struct pirq *, uint64_t gtable);  void

> msixtbl_pt_unregister(struct domain *, struct pirq *);

> --

> 2.7.4 (Apple Git-66)
Roger Pau Monné Oct. 6, 2016, 2:31 p.m. UTC | #2
On Mon, Oct 03, 2016 at 10:02:27AM +0100, Paul Durrant wrote:
> > -----Original Message-----
> > From: Roger Pau Monne [mailto:roger.pau@citrix.com]
> > Sent: 27 September 2016 16:57
> > To: xen-devel@lists.xenproject.org
> > Cc: konrad.wilk@oracle.com; boris.ostrovsky@oracle.com; Roger Pau Monne
> > <roger.pau@citrix.com>; Paul Durrant <Paul.Durrant@citrix.com>; Jan
> > Beulich <jbeulich@suse.com>; Andrew Cooper
> > <Andrew.Cooper3@citrix.com>
> > Subject: [PATCH v2 19/30] xen/dcpi: add a dpci passthrough handler for
> > hardware domain
> > 
> > This is very similar to the PCI trap used for the traditional PV(H) Dom0.
> > 
> > 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         | 72
> > ++++++++++++++++++++++++++++++++++++++++++-
> >  xen/arch/x86/traps.c          | 39 -----------------------
> >  xen/drivers/passthrough/pci.c | 39 +++++++++++++++++++++++
> >  xen/include/xen/pci.h         |  2 ++
> >  4 files changed, 112 insertions(+), 40 deletions(-)
> > 
> > diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c index
> > 1e7a5f9..31d54dc 100644
> > --- a/xen/arch/x86/hvm/io.c
> > +++ b/xen/arch/x86/hvm/io.c
> > @@ -247,12 +247,79 @@ static int dpci_portio_write(const struct
> > hvm_io_handler *handler,
> >      return X86EMUL_OKAY;
> >  }
> > 
> > +static bool_t hw_dpci_portio_accept(const struct hvm_io_handler
> > *handler,
> > +                                    const ioreq_t *p) {
> > +    if ( (p->addr == 0xcf8 && p->size == 4) || (p->addr & 0xfffc) == 0xcfc)
> > +    {
> > +        return 1;
> > +    }
> > +
> > +    return 0;
> 
> Why not just return the value of the boolean expression?

Thanks, fixed.
 
> > +}
> > +
> > +static int hw_dpci_portio_read(const struct hvm_io_handler *handler,
> > +                            uint64_t addr,
> > +                            uint32_t size,
> > +                            uint64_t *data) {
> > +    struct domain *currd = current->domain;
> > +
> > +    if ( addr == 0xcf8 )
> > +    {
> > +        ASSERT(size == 4);
> > +        *data = currd->arch.pci_cf8;
> > +        return X86EMUL_OKAY;
> > +    }
> > +
> > +    ASSERT((addr & 0xfffc) == 0xcfc);
> 
> You could do 'addr &= 3' and simplify the expressions below.

Fixed.
 
> > +    size = min(size, 4 - ((uint32_t)addr & 3));
> > +    if ( size == 3 )
> > +        size = 2;
> > +    if ( pci_cfg_ok(currd, addr & 3, size, NULL) )
> 
> Is this the right place to do the check. Can this not be done in the accept op?

In the intercept op we don't know if the operation is a read or a write, and 
pci_cfg_ok seems to do more than a check, it calls pci_conf_write_intercept. 

> > +        *data = pci_conf_read(currd->arch.pci_cf8, addr & 3, size);
> > +
> > +    return X86EMUL_OKAY;
> > +}
> > +
> > +static int hw_dpci_portio_write(const struct hvm_io_handler *handler,
> > +                                uint64_t addr,
> > +                                uint32_t size,
> > +                                uint64_t data) {
> > +    struct domain *currd = current->domain;
> > +    uint32_t data32;
> > +
> > +    if ( addr == 0xcf8 )
> > +    {
> > +            ASSERT(size == 4);
> > +            currd->arch.pci_cf8 = data;
> > +            return X86EMUL_OKAY;
> > +    }
> > +
> > +    ASSERT((addr & 0xfffc) == 0xcfc);
> 
> 'addr &= 3' again here.

Thanks.

Roger.
Jan Beulich Oct. 6, 2016, 3:44 p.m. UTC | #3
>>> On 27.09.16 at 17:57, <roger.pau@citrix.com> wrote:
> --- a/xen/arch/x86/traps.c
> +++ b/xen/arch/x86/traps.c
> @@ -2076,45 +2076,6 @@ static bool_t admin_io_okay(unsigned int port, unsigned int bytes,
>      return ioports_access_permitted(d, port, port + bytes - 1);
>  }
>  
> -static bool_t pci_cfg_ok(struct domain *currd, unsigned int start,
> -                         unsigned int size, uint32_t *write)

I don't follow why you move this ...

> --- a/xen/drivers/passthrough/pci.c
> +++ b/xen/drivers/passthrough/pci.c
> @@ -966,6 +966,45 @@ void pci_check_disable_device(u16 seg, u8 bus, u8 devfn)
>                       PCI_COMMAND, cword & ~PCI_COMMAND_MASTER);
>  }
>  
> +bool_t pci_cfg_ok(struct domain *currd, unsigned int start,
> +                         unsigned int size, uint32_t *write)

here. After all ...

> +{
> +    uint32_t machine_bdf;
> +
> +    if ( !is_hardware_domain(currd) )
> +        return 0;
> +
> +    if ( !CF8_ENABLED(currd->arch.pci_cf8) )
> +        return 1;
> +
> +    machine_bdf = CF8_BDF(currd->arch.pci_cf8);

... concepts like I/O ports in general and ports CF8 / CFC in particular
are x86-specific. If this really needs moving at all, it should stay in an
x86-specific file.

Jan
diff mbox

Patch

diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c
index 1e7a5f9..31d54dc 100644
--- a/xen/arch/x86/hvm/io.c
+++ b/xen/arch/x86/hvm/io.c
@@ -247,12 +247,79 @@  static int dpci_portio_write(const struct hvm_io_handler *handler,
     return X86EMUL_OKAY;
 }
 
+static bool_t hw_dpci_portio_accept(const struct hvm_io_handler *handler,
+                                    const ioreq_t *p)
+{
+    if ( (p->addr == 0xcf8 && p->size == 4) || (p->addr & 0xfffc) == 0xcfc)
+    {
+        return 1;
+    }
+
+    return 0;
+}
+
+static int hw_dpci_portio_read(const struct hvm_io_handler *handler,
+                            uint64_t addr,
+                            uint32_t size,
+                            uint64_t *data)
+{
+    struct domain *currd = current->domain;
+
+    if ( addr == 0xcf8 )
+    {
+        ASSERT(size == 4);
+        *data = currd->arch.pci_cf8;
+        return X86EMUL_OKAY;
+    }
+
+    ASSERT((addr & 0xfffc) == 0xcfc);
+    size = min(size, 4 - ((uint32_t)addr & 3));
+    if ( size == 3 )
+        size = 2;
+    if ( pci_cfg_ok(currd, addr & 3, size, NULL) )
+        *data = pci_conf_read(currd->arch.pci_cf8, addr & 3, size);
+
+    return X86EMUL_OKAY;
+}
+
+static int hw_dpci_portio_write(const struct hvm_io_handler *handler,
+                                uint64_t addr,
+                                uint32_t size,
+                                uint64_t data)
+{
+    struct domain *currd = current->domain;
+    uint32_t data32;
+
+    if ( addr == 0xcf8 )
+    {
+            ASSERT(size == 4);
+            currd->arch.pci_cf8 = data;
+            return X86EMUL_OKAY;
+    }
+
+    ASSERT((addr & 0xfffc) == 0xcfc);
+    size = min(size, 4 - ((uint32_t)addr & 3));
+    if ( size == 3 )
+        size = 2;
+    data32 = data;
+    if ( pci_cfg_ok(currd, addr & 3, size, &data32) )
+        pci_conf_write(currd->arch.pci_cf8, addr & 3, size, data);
+
+    return X86EMUL_OKAY;
+}
+
 static const struct hvm_io_ops dpci_portio_ops = {
     .accept = dpci_portio_accept,
     .read = dpci_portio_read,
     .write = dpci_portio_write
 };
 
+static const struct hvm_io_ops hw_dpci_portio_ops = {
+    .accept = hw_dpci_portio_accept,
+    .read = hw_dpci_portio_read,
+    .write = hw_dpci_portio_write
+};
+
 void register_dpci_portio_handler(struct domain *d)
 {
     struct hvm_io_handler *handler = hvm_next_io_handler(d);
@@ -261,7 +328,10 @@  void register_dpci_portio_handler(struct domain *d)
         return;
 
     handler->type = IOREQ_TYPE_PIO;
-    handler->ops = &dpci_portio_ops;
+    if ( is_hardware_domain(d) )
+        handler->ops = &hw_dpci_portio_ops;
+    else
+        handler->ops = &dpci_portio_ops;
 }
 
 /*
diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
index 24d173f..f3c5c9e 100644
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -2076,45 +2076,6 @@  static bool_t admin_io_okay(unsigned int port, unsigned int bytes,
     return ioports_access_permitted(d, port, port + bytes - 1);
 }
 
-static bool_t pci_cfg_ok(struct domain *currd, unsigned int start,
-                         unsigned int size, uint32_t *write)
-{
-    uint32_t machine_bdf;
-
-    if ( !is_hardware_domain(currd) )
-        return 0;
-
-    if ( !CF8_ENABLED(currd->arch.pci_cf8) )
-        return 1;
-
-    machine_bdf = CF8_BDF(currd->arch.pci_cf8);
-    if ( write )
-    {
-        const unsigned long *ro_map = pci_get_ro_map(0);
-
-        if ( ro_map && test_bit(machine_bdf, ro_map) )
-            return 0;
-    }
-    start |= CF8_ADDR_LO(currd->arch.pci_cf8);
-    /* AMD extended configuration space access? */
-    if ( CF8_ADDR_HI(currd->arch.pci_cf8) &&
-         boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
-         boot_cpu_data.x86 >= 0x10 && boot_cpu_data.x86 <= 0x17 )
-    {
-        uint64_t msr_val;
-
-        if ( rdmsr_safe(MSR_AMD64_NB_CFG, msr_val) )
-            return 0;
-        if ( msr_val & (1ULL << AMD64_NB_CFG_CF8_EXT_ENABLE_BIT) )
-            start |= CF8_ADDR_HI(currd->arch.pci_cf8);
-    }
-
-    return !write ?
-           xsm_pci_config_permission(XSM_HOOK, currd, machine_bdf,
-                                     start, start + size - 1, 0) == 0 :
-           pci_conf_write_intercept(0, machine_bdf, start, size, write) >= 0;
-}
-
 uint32_t guest_io_read(unsigned int port, unsigned int bytes,
                        struct domain *currd)
 {
diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c
index dd291a2..a53b4c8 100644
--- a/xen/drivers/passthrough/pci.c
+++ b/xen/drivers/passthrough/pci.c
@@ -966,6 +966,45 @@  void pci_check_disable_device(u16 seg, u8 bus, u8 devfn)
                      PCI_COMMAND, cword & ~PCI_COMMAND_MASTER);
 }
 
+bool_t pci_cfg_ok(struct domain *currd, unsigned int start,
+                         unsigned int size, uint32_t *write)
+{
+    uint32_t machine_bdf;
+
+    if ( !is_hardware_domain(currd) )
+        return 0;
+
+    if ( !CF8_ENABLED(currd->arch.pci_cf8) )
+        return 1;
+
+    machine_bdf = CF8_BDF(currd->arch.pci_cf8);
+    if ( write )
+    {
+        const unsigned long *ro_map = pci_get_ro_map(0);
+
+        if ( ro_map && test_bit(machine_bdf, ro_map) )
+            return 0;
+    }
+    start |= CF8_ADDR_LO(currd->arch.pci_cf8);
+    /* AMD extended configuration space access? */
+    if ( CF8_ADDR_HI(currd->arch.pci_cf8) &&
+         boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
+         boot_cpu_data.x86 >= 0x10 && boot_cpu_data.x86 <= 0x17 )
+    {
+        uint64_t msr_val;
+
+        if ( rdmsr_safe(MSR_AMD64_NB_CFG, msr_val) )
+            return 0;
+        if ( msr_val & (1ULL << AMD64_NB_CFG_CF8_EXT_ENABLE_BIT) )
+            start |= CF8_ADDR_HI(currd->arch.pci_cf8);
+    }
+
+    return !write ?
+           xsm_pci_config_permission(XSM_HOOK, currd, machine_bdf,
+                                     start, start + size - 1, 0) == 0 :
+           pci_conf_write_intercept(0, machine_bdf, start, size, write) >= 0;
+}
+
 /*
  * scan pci devices to add all existed PCI devices to alldevs_list,
  * and setup pci hierarchy in array bus2bridge.
diff --git a/xen/include/xen/pci.h b/xen/include/xen/pci.h
index 0872401..f191773 100644
--- a/xen/include/xen/pci.h
+++ b/xen/include/xen/pci.h
@@ -162,6 +162,8 @@  const char *parse_pci(const char *, unsigned int *seg, unsigned int *bus,
 
 bool_t pcie_aer_get_firmware_first(const struct pci_dev *);
 
+bool_t pci_cfg_ok(struct domain *, unsigned int, unsigned int, uint32_t *);
+
 struct pirq;
 int msixtbl_pt_register(struct domain *, struct pirq *, uint64_t gtable);
 void msixtbl_pt_unregister(struct domain *, struct pirq *);