Patchwork [XEN,RFC,01/15] hvm: Modify interface to support multiple ioreq server

login
register
mail settings
Submitter Julien Grall
Date March 22, 2012, 3:59 p.m.
Message ID <2187e535bf91f5f650401a4e08e0e795003ad2aa.1332430810.git.julien.grall@citrix.com>
Download mbox | patch
Permalink /patch/148301/
State New
Headers show

Comments

Julien Grall - March 22, 2012, 3:59 p.m.
Add structure to handle ioreq server. It's server which can
handle a range of IO (MMIO and/or PIO) and emulate a PCI.
Each server as its own shared page to receive ioreq. So
we have introduced to HVM PARAM to set/get the first and
the last shared used for ioreq. With it's id, the server
knows which page it must use.

We introduce a new kind a ioreq type IOREQ_TYPE_PCICONFIG
which permit to forward easily PCI config space access.

Signed-off-by: Julien Grall <julien.grall@citrix.com>
---
 xen/include/asm-x86/hvm/domain.h |   24 +++++++++++++++++-
 xen/include/asm-x86/hvm/vcpu.h   |    4 ++-
 xen/include/public/hvm/hvm_op.h  |   49 ++++++++++++++++++++++++++++++++++++++
 xen/include/public/hvm/ioreq.h   |    1 +
 xen/include/public/hvm/params.h  |    6 ++++-
 xen/include/public/xen.h         |    1 +
 xen/include/xen/hvm/pci_emul.h   |   37 ++++++++++++++++++++++++++++
 7 files changed, 119 insertions(+), 3 deletions(-)
 create mode 100644 xen/include/xen/hvm/pci_emul.h
Jan Beulich - March 23, 2012, 8:18 a.m.
>>> On 22.03.12 at 16:59, Julien Grall <julien.grall@citrix.com> wrote:
> --- a/xen/include/public/hvm/hvm_op.h
> +++ b/xen/include/public/hvm/hvm_op.h
> @@ -24,6 +24,8 @@
>  #include "../xen.h"
>  #include "../trace.h"
>  
> +#include "hvm_info_table.h" /* HVM_MAX_VCPUS */
> +
>  /* Get/set subcommands: extra argument == pointer to xen_hvm_param struct. 
> */
>  #define HVMOP_set_param           0
>  #define HVMOP_get_param           1
> @@ -227,6 +229,53 @@ struct xen_hvm_inject_trap {
>  typedef struct xen_hvm_inject_trap xen_hvm_inject_trap_t;
>  DEFINE_XEN_GUEST_HANDLE(xen_hvm_inject_trap_t);
>  
> +#define HVMOP_register_ioreq_server 20
> +struct xen_hvm_register_ioreq_server {
> +    domid_t domid;          /* IN - domain to be serviced */
> +    unsigned int id;        /* OUT - handle for identifying this server */
> +};
> +typedef struct xen_hvm_register_ioreq_server 
> xen_hvm_register_ioreq_server_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_hvm_register_ioreq_server_t);
> +
> +#define HVMOP_get_ioreq_server_buf_channel 21
> +struct xen_hvm_get_ioreq_server_buf_channel {
> +    domid_t domid;	    /* IN - domain to be serviced */
> +    servid_t id;	    /* IN - handle from HVMOP_register_ioreq_server */
> +    unsigned int channel;   /* OUT - buf ioreq channel */
> +};
> +typedef struct xen_hvm_get_ioreq_server_buf_channel 
> xen_hvm_get_ioreq_server_buf_channel_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_hvm_get_ioreq_server_buf_channel_t);
> +
> +#define HVMOP_map_io_range_to_ioreq_server 22
> +struct xen_hvm_map_io_range_to_ioreq_server {
> +    domid_t domid;          /* IN - domain to be serviced */
> +    uint8_t is_mmio;        /* IN - MMIO or port IO? */
> +    servid_t id;            /* IN - handle from HVMOP_register_ioreq_server 
> */
> +    uint64_aligned_t s, e;  /* IN - inclusive start and end of range */
> +};
> +typedef struct xen_hvm_map_io_range_to_ioreq_server 
> xen_hvm_map_io_range_to_ioreq_server_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_hvm_map_io_range_to_ioreq_server_t);
> +
> +#define HVMOP_unmap_io_range_from_ioreq_server 23
> +struct xen_hvm_unmap_io_range_from_ioreq_server {
> +    domid_t domid;          /* IN - domain to be serviced */
> +    uint8_t is_mmio;        /* IN - MMIO or port IO? */
> +    servid_t id;            /* IN - handle from HVMOP_register_ioreq_server 
> */
> +    uint64_aligned_t addr;  /* IN - address inside the range to remove */
> +};
> +typedef struct xen_hvm_unmap_io_range_from_ioreq_server 
> xen_hvm_unmap_io_range_from_ioreq_server_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_hvm_unmap_io_range_from_ioreq_server_t);
> +
> +#define HVMOP_register_pcidev 24
> +struct xen_hvm_register_pcidev {
> +    domid_t domid;	   /* IN - domain to be serviced */
> +    servid_t id;	   /* IN - handle from HVMOP_register_ioreq_server */
> +    uint16_t bdf;	   /* IN - pci */

Can we please avoid the mistake of again not surfacing the PCI
segment in interface definitions, even if it may be required to be
zero for the immediate needs?

Jan

> +};
> +typedef struct xen_hvm_register_pcidev xen_hvm_register_pcidev_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_hvm_register_pcidev_t);
> +
> +
>  #endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
>  
>  #define HVMOP_get_mem_type    15
Ian Campbell - March 23, 2012, 11:33 a.m.
On Thu, 2012-03-22 at 15:59 +0000, Julien Grall wrote:
> Add structure to handle ioreq server. It's server which can
> handle a range of IO (MMIO and/or PIO) and emulate a PCI.
> Each server as its own shared page to receive ioreq. So
> we have introduced to HVM PARAM to set/get the first and
> the last shared used for ioreq.
> With it's id, the server knows which page it must use.

So id is always the page offset with the range? Why not just call it
iobuf_offset then? Is the additional layer of abstraction from calling
it "id" useful if we are just going to peek around it?

> We introduce a new kind a ioreq type IOREQ_TYPE_PCICONFIG
> which permit to forward easily PCI config space access.
> 
> Signed-off-by: Julien Grall <julien.grall@citrix.com>
> ---
> [...]
>  xen/include/public/hvm/hvm_op.h  |   49 ++++++++++++++++++++++++++++++++++++++
>  xen/include/public/hvm/ioreq.h   |    1 +
>  xen/include/public/hvm/params.h  |    6 ++++-
>  xen/include/public/xen.h         |    1 +

I only looked at the public interface changes so far.

> diff --git a/xen/include/public/hvm/hvm_op.h b/xen/include/public/hvm/hvm_op.h
> index 6a78f75..1e0e27b 100644
> --- a/xen/include/public/hvm/hvm_op.h
> +++ b/xen/include/public/hvm/hvm_op.h
> @@ -24,6 +24,8 @@
>  #include "../xen.h"
>  #include "../trace.h"
>  
> +#include "hvm_info_table.h" /* HVM_MAX_VCPUS */

You don't appear to use HVM_MAX_VCPUS anywhere in your additions?

>  /* Get/set subcommands: extra argument == pointer to xen_hvm_param struct. */
>  #define HVMOP_set_param           0
>  #define HVMOP_get_param           1
> @@ -227,6 +229,53 @@ struct xen_hvm_inject_trap {
>  typedef struct xen_hvm_inject_trap xen_hvm_inject_trap_t;
>  DEFINE_XEN_GUEST_HANDLE(xen_hvm_inject_trap_t);
>  
> +#define HVMOP_register_ioreq_server 20
> +struct xen_hvm_register_ioreq_server {
> +    domid_t domid;          /* IN - domain to be serviced */
> +    unsigned int id;        /* OUT - handle for identifying this server */

elsewhere this is called servid_t?

> +};
> +typedef struct xen_hvm_register_ioreq_server xen_hvm_register_ioreq_server_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_hvm_register_ioreq_server_t);
> +
> +#define HVMOP_get_ioreq_server_buf_channel 21
> +struct xen_hvm_get_ioreq_server_buf_channel {
> +    domid_t domid;	    /* IN - domain to be serviced */
> +    servid_t id;	    /* IN - handle from HVMOP_register_ioreq_server */
> +    unsigned int channel;   /* OUT - buf ioreq channel */

evtchn_port_t?

> +};
> +typedef struct xen_hvm_get_ioreq_server_buf_channel xen_hvm_get_ioreq_server_buf_channel_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_hvm_get_ioreq_server_buf_channel_t);
> +
> +#define HVMOP_map_io_range_to_ioreq_server 22
> +struct xen_hvm_map_io_range_to_ioreq_server {
> +    domid_t domid;          /* IN - domain to be serviced */
> +    uint8_t is_mmio;        /* IN - MMIO or port IO? */
> +    servid_t id;            /* IN - handle from HVMOP_register_ioreq_server */
> +    uint64_aligned_t s, e;  /* IN - inclusive start and end of range */
> +};
> +typedef struct xen_hvm_map_io_range_to_ioreq_server xen_hvm_map_io_range_to_ioreq_server_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_hvm_map_io_range_to_ioreq_server_t);
> +
> +#define HVMOP_unmap_io_range_from_ioreq_server 23
> +struct xen_hvm_unmap_io_range_from_ioreq_server {
> +    domid_t domid;          /* IN - domain to be serviced */
> +    uint8_t is_mmio;        /* IN - MMIO or port IO? */
> +    servid_t id;            /* IN - handle from HVMOP_register_ioreq_server */
> +    uint64_aligned_t addr;  /* IN - address inside the range to remove */
> +};
> +typedef struct xen_hvm_unmap_io_range_from_ioreq_server xen_hvm_unmap_io_range_from_ioreq_server_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_hvm_unmap_io_range_from_ioreq_server_t);
> +
> +#define HVMOP_register_pcidev 24
> +struct xen_hvm_register_pcidev {
> +    domid_t domid;	   /* IN - domain to be serviced */
> +    servid_t id;	   /* IN - handle from HVMOP_register_ioreq_server */
> +    uint16_t bdf;	   /* IN - pci */
> +};
> +typedef struct xen_hvm_register_pcidev xen_hvm_register_pcidev_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_hvm_register_pcidev_t);
> +
> +
>  #endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
>  
>  #define HVMOP_get_mem_type    15
> diff --git a/xen/include/public/hvm/ioreq.h b/xen/include/public/hvm/ioreq.h
> index 4022a1d..87aacd3 100644
> --- a/xen/include/public/hvm/ioreq.h
> +++ b/xen/include/public/hvm/ioreq.h
> @@ -34,6 +34,7 @@
>  
>  #define IOREQ_TYPE_PIO          0 /* pio */
>  #define IOREQ_TYPE_COPY         1 /* mmio ops */
> +#define IOREQ_TYPE_PCI_CONFIG   2 /* pci config space ops */
>  #define IOREQ_TYPE_TIMEOFFSET   7
>  #define IOREQ_TYPE_INVALIDATE   8 /* mapcache */
>  
> diff --git a/xen/include/public/hvm/params.h b/xen/include/public/hvm/params.h
> index 55c1b57..309ac1b 100644
> --- a/xen/include/public/hvm/params.h
> +++ b/xen/include/public/hvm/params.h
> @@ -147,6 +147,10 @@
>  #define HVM_PARAM_ACCESS_RING_PFN   28
>  #define HVM_PARAM_SHARING_RING_PFN  29
>  
> -#define HVM_NR_PARAMS          30
> +/* Param for ioreq servers */
> +#define HVM_PARAM_IO_PFN_FIRST	30
> +#define HVM_PARAM_IO_PFN_LAST	31
> +
> +#define HVM_NR_PARAMS          32
>  
>  #endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
> diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h
> index b2f6c50..26d0e9d 100644
> --- a/xen/include/public/xen.h
> +++ b/xen/include/public/xen.h
> @@ -466,6 +466,7 @@ DEFINE_XEN_GUEST_HANDLE(mmuext_op_t);
>  #ifndef __ASSEMBLY__
>  
>  typedef uint16_t domid_t;
> +typedef uint32_t servid_t;

ioservid_t?
 
>  /* Domain ids >= DOMID_FIRST_RESERVED cannot be used for ordinary domains. */
>  #define DOMID_FIRST_RESERVED (0x7FF0U)
Julien Grall - March 26, 2012, 12:32 p.m.
On 03/23/2012 08:18 AM, Jan Beulich wrote:
>> +#define HVMOP_register_pcidev 24
>> +struct xen_hvm_register_pcidev {
>> +    domid_t domid;	   /* IN - domain to be serviced */
>> +    servid_t id;	   /* IN - handle from HVMOP_register_ioreq_server */
>> +    uint16_t bdf;	   /* IN - pci */
>>      
> Can we please avoid the mistake of again not surfacing the PCI
> segment in interface definitions, even if it may be required to be
> zero for the immediate needs?
>    

What do you hear by surfacing the PCI segment ?
Do I need to add the PCI domain ?
Jan Beulich - March 26, 2012, 12:53 p.m.
>>> On 26.03.12 at 14:32, Julien Grall <julien.grall@citrix.com> wrote:
> On 03/23/2012 08:18 AM, Jan Beulich wrote:
>>> +#define HVMOP_register_pcidev 24
>>> +struct xen_hvm_register_pcidev {
>>> +    domid_t domid;	   /* IN - domain to be serviced */
>>> +    servid_t id;	   /* IN - handle from HVMOP_register_ioreq_server */
>>> +    uint16_t bdf;	   /* IN - pci */
>>>      
>> Can we please avoid the mistake of again not surfacing the PCI
>> segment in interface definitions, even if it may be required to be
>> zero for the immediate needs?
>>    
> 
> What do you hear by surfacing the PCI segment ?
> Do I need to add the PCI domain ?

"domain" and "segment" appear to be used interchangeably.

Jan
Ian Jackson - April 2, 2012, 5:12 p.m.
Julien Grall writes ("[Xen-devel] [XEN][RFC PATCH 01/15] hvm: Modify interface to support multiple ioreq server"):
> Add structure to handle ioreq server. It's server which can
> handle a range of IO (MMIO and/or PIO) and emulate a PCI.
> Each server as its own shared page to receive ioreq. So
> we have introduced to HVM PARAM to set/get the first and
> the last shared used for ioreq. With it's id, the server
> knows which page it must use.

This explanation, and full documentation of the new HVMOPs, should be
included in the hvm_op.h header.

Ian.
Julien Grall - April 12, 2012, 7:33 p.m.
On 03/23/2012 11:33 AM, Ian Campbell wrote:
> On Thu, 2012-03-22 at 15:59 +0000, Julien Grall wrote:
>    
>> Add structure to handle ioreq server. It's server which can
>> handle a range of IO (MMIO and/or PIO) and emulate a PCI.
>> Each server as its own shared page to receive ioreq. So
>> we have introduced to HVM PARAM to set/get the first and
>> the last shared used for ioreq.
>> With it's id, the server knows which page it must use.
>>      
> So id is always the page offset with the range? Why not just call it
> iobuf_offset then? Is the additional layer of abstraction from calling
> it "id" useful if we are just going to peek around it?
>    
Indeed, but this parameter is also used to register bdf/io range.
So can we call it server_id or server_offset ?

>> diff --git a/xen/include/public/hvm/hvm_op.h b/xen/include/public/hvm/hvm_op.h
>> index 6a78f75..1e0e27b 100644
>> --- a/xen/include/public/hvm/hvm_op.h
>> +++ b/xen/include/public/hvm/hvm_op.h
>> @@ -24,6 +24,8 @@
>>   #include "../xen.h"
>>   #include "../trace.h"
>>
>> +#include "hvm_info_table.h" /* HVM_MAX_VCPUS */
>>      
> You don't appear to use HVM_MAX_VCPUS anywhere in your additions?
>
>    
I use it in xen-all.c in QEMU. It permits to check that smp_cpus is lower
that the maximum of vpcus. It avoids page overflow.

Patch

diff --git a/xen/include/asm-x86/hvm/domain.h b/xen/include/asm-x86/hvm/domain.h
index 27b3de5..0cfdc69 100644
--- a/xen/include/asm-x86/hvm/domain.h
+++ b/xen/include/asm-x86/hvm/domain.h
@@ -28,6 +28,7 @@ 
 #include <asm/hvm/vioapic.h>
 #include <asm/hvm/io.h>
 #include <xen/hvm/iommu.h>
+#include <xen/hvm/pci_emul.h>
 #include <asm/hvm/viridian.h>
 #include <asm/hvm/vmx/vmcs.h>
 #include <asm/hvm/svm/vmcb.h>
@@ -41,14 +42,35 @@  struct hvm_ioreq_page {
     void *va;
 };
 
+struct hvm_io_range {
+    uint64_t s, e;
+    struct hvm_io_range *next;
+};
+
+struct hvm_ioreq_server {
+    unsigned int id;
+    struct hvm_io_range *mmio_range_list;
+    struct hvm_io_range *portio_range_list;
+    struct hvm_ioreq_server *next;
+    struct hvm_ioreq_page ioreq;
+    struct hvm_ioreq_page buf_ioreq;
+    unsigned int buf_ioreq_evtchn;
+};
+
 struct hvm_domain {
+    /* Use for the IO handles by Xen */
     struct hvm_ioreq_page  ioreq;
-    struct hvm_ioreq_page  buf_ioreq;
+    struct hvm_ioreq_server *ioreq_server_list;
+    uint32_t		     nr_ioreq_server;
+    spinlock_t               ioreq_server_lock;
 
     struct pl_time         pl_time;
 
     struct hvm_io_handler *io_handler;
 
+    /* PCI Information */
+    struct pci_root_emul pci_root;
+
     /* Lock protects access to irq, vpic and vioapic. */
     spinlock_t             irq_lock;
     struct hvm_irq         irq;
diff --git a/xen/include/asm-x86/hvm/vcpu.h b/xen/include/asm-x86/hvm/vcpu.h
index 537da96..2774ced 100644
--- a/xen/include/asm-x86/hvm/vcpu.h
+++ b/xen/include/asm-x86/hvm/vcpu.h
@@ -125,7 +125,9 @@  struct hvm_vcpu {
     spinlock_t          tm_lock;
     struct list_head    tm_list;
 
-    int                 xen_port;
+    struct hvm_ioreq_page	*ioreq;
+    /* PCI Information */
+    uint32_t		pci_cf8;
 
     bool_t              flag_dr_dirty;
     bool_t              debug_state_latch;
diff --git a/xen/include/public/hvm/hvm_op.h b/xen/include/public/hvm/hvm_op.h
index 6a78f75..1e0e27b 100644
--- a/xen/include/public/hvm/hvm_op.h
+++ b/xen/include/public/hvm/hvm_op.h
@@ -24,6 +24,8 @@ 
 #include "../xen.h"
 #include "../trace.h"
 
+#include "hvm_info_table.h" /* HVM_MAX_VCPUS */
+
 /* Get/set subcommands: extra argument == pointer to xen_hvm_param struct. */
 #define HVMOP_set_param           0
 #define HVMOP_get_param           1
@@ -227,6 +229,53 @@  struct xen_hvm_inject_trap {
 typedef struct xen_hvm_inject_trap xen_hvm_inject_trap_t;
 DEFINE_XEN_GUEST_HANDLE(xen_hvm_inject_trap_t);
 
+#define HVMOP_register_ioreq_server 20
+struct xen_hvm_register_ioreq_server {
+    domid_t domid;          /* IN - domain to be serviced */
+    unsigned int id;        /* OUT - handle for identifying this server */
+};
+typedef struct xen_hvm_register_ioreq_server xen_hvm_register_ioreq_server_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_register_ioreq_server_t);
+
+#define HVMOP_get_ioreq_server_buf_channel 21
+struct xen_hvm_get_ioreq_server_buf_channel {
+    domid_t domid;	    /* IN - domain to be serviced */
+    servid_t id;	    /* IN - handle from HVMOP_register_ioreq_server */
+    unsigned int channel;   /* OUT - buf ioreq channel */
+};
+typedef struct xen_hvm_get_ioreq_server_buf_channel xen_hvm_get_ioreq_server_buf_channel_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_get_ioreq_server_buf_channel_t);
+
+#define HVMOP_map_io_range_to_ioreq_server 22
+struct xen_hvm_map_io_range_to_ioreq_server {
+    domid_t domid;          /* IN - domain to be serviced */
+    uint8_t is_mmio;        /* IN - MMIO or port IO? */
+    servid_t id;            /* IN - handle from HVMOP_register_ioreq_server */
+    uint64_aligned_t s, e;  /* IN - inclusive start and end of range */
+};
+typedef struct xen_hvm_map_io_range_to_ioreq_server xen_hvm_map_io_range_to_ioreq_server_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_map_io_range_to_ioreq_server_t);
+
+#define HVMOP_unmap_io_range_from_ioreq_server 23
+struct xen_hvm_unmap_io_range_from_ioreq_server {
+    domid_t domid;          /* IN - domain to be serviced */
+    uint8_t is_mmio;        /* IN - MMIO or port IO? */
+    servid_t id;            /* IN - handle from HVMOP_register_ioreq_server */
+    uint64_aligned_t addr;  /* IN - address inside the range to remove */
+};
+typedef struct xen_hvm_unmap_io_range_from_ioreq_server xen_hvm_unmap_io_range_from_ioreq_server_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_unmap_io_range_from_ioreq_server_t);
+
+#define HVMOP_register_pcidev 24
+struct xen_hvm_register_pcidev {
+    domid_t domid;	   /* IN - domain to be serviced */
+    servid_t id;	   /* IN - handle from HVMOP_register_ioreq_server */
+    uint16_t bdf;	   /* IN - pci */
+};
+typedef struct xen_hvm_register_pcidev xen_hvm_register_pcidev_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_register_pcidev_t);
+
+
 #endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
 
 #define HVMOP_get_mem_type    15
diff --git a/xen/include/public/hvm/ioreq.h b/xen/include/public/hvm/ioreq.h
index 4022a1d..87aacd3 100644
--- a/xen/include/public/hvm/ioreq.h
+++ b/xen/include/public/hvm/ioreq.h
@@ -34,6 +34,7 @@ 
 
 #define IOREQ_TYPE_PIO          0 /* pio */
 #define IOREQ_TYPE_COPY         1 /* mmio ops */
+#define IOREQ_TYPE_PCI_CONFIG   2 /* pci config space ops */
 #define IOREQ_TYPE_TIMEOFFSET   7
 #define IOREQ_TYPE_INVALIDATE   8 /* mapcache */
 
diff --git a/xen/include/public/hvm/params.h b/xen/include/public/hvm/params.h
index 55c1b57..309ac1b 100644
--- a/xen/include/public/hvm/params.h
+++ b/xen/include/public/hvm/params.h
@@ -147,6 +147,10 @@ 
 #define HVM_PARAM_ACCESS_RING_PFN   28
 #define HVM_PARAM_SHARING_RING_PFN  29
 
-#define HVM_NR_PARAMS          30
+/* Param for ioreq servers */
+#define HVM_PARAM_IO_PFN_FIRST	30
+#define HVM_PARAM_IO_PFN_LAST	31
+
+#define HVM_NR_PARAMS          32
 
 #endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h
index b2f6c50..26d0e9d 100644
--- a/xen/include/public/xen.h
+++ b/xen/include/public/xen.h
@@ -466,6 +466,7 @@  DEFINE_XEN_GUEST_HANDLE(mmuext_op_t);
 #ifndef __ASSEMBLY__
 
 typedef uint16_t domid_t;
+typedef uint32_t servid_t;
 
 /* Domain ids >= DOMID_FIRST_RESERVED cannot be used for ordinary domains. */
 #define DOMID_FIRST_RESERVED (0x7FF0U)
diff --git a/xen/include/xen/hvm/pci_emul.h b/xen/include/xen/hvm/pci_emul.h
new file mode 100644
index 0000000..4e4a2fd
--- /dev/null
+++ b/xen/include/xen/hvm/pci_emul.h
@@ -0,0 +1,37 @@ 
+#ifndef PCI_EMUL_H_
+# define PCI_EMUL_H_
+
+# include <xen/spinlock.h>
+# include <xen/types.h>
+
+int hvm_init_pci_emul(struct domain *d);
+void hvm_destroy_pci_emul(struct domain *d);
+int hvm_register_pcidev(domid_t domid, servid_t id, u16 bdf);
+
+/* Size of the standard PCI config space */
+#define PCI_CONFIG_SPACE_SIZE 0x100
+#define PCI_CMP_BDF(Pci, Bdf) ((Pci)->bdf == PCI_MASK_BDF(Bdf))
+#define PCI_MASK_BDF(bdf) (((bdf) & 0x00ffff00) >> 8)
+
+struct pci_device_emul {
+    u16 bdf;
+    struct hvm_ioreq_server *server;
+    struct pci_device_emul *next;
+};
+
+struct pci_root_emul {
+    spinlock_t pci_lock;
+    struct pci_device_emul *pci;
+};
+
+#endif /* !PCI_EMUL_H_ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */