Message ID | 20170906092830.3760-1-vkuznets@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
> -----Original Message----- > From: Vitaly Kuznetsov [mailto:vkuznets@redhat.com] > Sent: 06 September 2017 10:29 > To: xen-devel@lists.xen.org > Cc: Paul Durrant <Paul.Durrant@citrix.com>; Ian Jackson > <Ian.Jackson@citrix.com> > Subject: [PATCH qemu-traditional] switch to the new ioreq server API > > Instead of using implicit ioreq server creation side-effect upon reading > HVM params switch qemu-traditional to using explicit APIs. This opens a > possibility for removing the above mentioned side-effect and special > 'default_ioreq_server' code pathes in Xen hypervisor in the future. > > This also solves an issue with soft reset when qemu-traditional is being > used. Xen c/s e7dabe5 ("x86/hvm: don't unconditionally create a default > ioreq server") disabled ioreq server creation after domain was created > for the first time and this is needed for soft reset. > > IOREQ_TYPE_PCI_CONFIG handling code is stolen as-is from qemu- > upstream. > > Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> Reviewed-by: Paul Durrant <paul.durrant@citrix.com> > --- > hw/pci.c | 5 ++ > hw/xen_common.h | 163 > ++++++++++++++++++++++++++++++++++++++++++++++++++++ > hw/xen_machine_fv.c | 31 ++++++++-- > i386-dm/exec-dm.c | 7 +++ > i386-dm/helper2.c | 31 +++++++--- > vl.c | 9 +++ > xen-vl-extra.c | 3 + > 7 files changed, 236 insertions(+), 13 deletions(-) > > diff --git a/hw/pci.c b/hw/pci.c > index c4232856..d6cafb3e 100644 > --- a/hw/pci.c > +++ b/hw/pci.c > @@ -34,6 +34,7 @@ > #ifdef CONFIG_PASSTHROUGH > #include "hw/pass-through.h" > #endif > +#include "hw/xen_common.h" > > extern int igd_passthru; > > @@ -248,6 +249,10 @@ PCIDevice *pci_register_device(PCIBus *bus, const > char *name, > return NULL; > found: ; > } > + > + xen_map_pcidev(xc_handle, domid, ioservid, 0, > + PCI_SLOT(devfn), PCI_FUNC(devfn)); > + > pci_dev = qemu_mallocz(instance_size); > pci_dev->bus = bus; > pci_dev->devfn = devfn; > diff --git a/hw/xen_common.h b/hw/xen_common.h > index cc48892f..5e172bb2 100644 > --- a/hw/xen_common.h > +++ b/hw/xen_common.h > @@ -33,4 +33,167 @@ > # define xen_wmb() wmb() > #endif > > +extern uint16_t ioservid; > + > +#if __XEN_LATEST_INTERFACE_VERSION__ < 0x00040500 > +static inline int xen_create_ioreq_server(xc_interface *xc, domid_t dom, > + uint16_t *ioservid) > +{ > + return 0; > +} > + > +static inline int xen_get_ioreq_server_info(xc_interface *xc, domid_t dom, > + uint16_t ioservid, > + xen_pfn_t *ioreq_pfn, > + xen_pfn_t *bufioreq_pfn, > + uint32_t *bufioreq_evtchn) > +{ > + unsigned long param; > + int rc; > + > + rc = xc_get_hvm_param(xc, dom, HVM_PARAM_IOREQ_PFN, ¶m); > + if (rc < 0) { > + fprintf(stderr, "failed to get HVM_PARAM_IOREQ_PFN\n"); > + return -1; > + } > + > + *ioreq_pfn = param; > + > + rc = xc_get_hvm_param(xc, dom, HVM_PARAM_BUFIOREQ_PFN, > ¶m); > + if (rc < 0) { > + fprintf(stderr, "failed to get HVM_PARAM_BUFIOREQ_PFN\n"); > + return -1; > + } > + > + *bufioreq_pfn = param; > + > + rc = xc_get_hvm_param(xc, dom, HVM_PARAM_BUFIOREQ_EVTCHN, > ¶m); > + if (rc < 0) { > + fprintf(stderr, "failed to get HVM_PARAM_BUFIOREQ_EVTCHN\n"); > + return -1; > + } > + > + *bufioreq_evtchn = param; > + > + return 0; > +} > + > +static inline int xen_set_ioreq_server_state(xc_interface *xc, domid_t > dom, > + uint16_t ioservid, > + bool enable) > +{ > + return 0; > +} > + > +static inline void xen_map_memory_section(xc_interface *xc, domid_t > dom, > + uint16_t ioservid, > + uint64_t start, uint64_t end) > +{ > +} > + > +static inline void xen_unmap_memory_section(xc_interface *xc, domid_t > dom, > + uint16_t ioservid, > + uint64_t start, uint64_t end) > +{ > +} > + > +static inline void xen_map_io_section(xc_interface *xc, domid_t dom, > + uint16_t ioservid, > + uint64_t start, uint64_t end) > +{ > +} > + > +static inline void xen_unmap_io_section(xc_interface *xc, domid_t dom, > + uint16_t ioservid, > + uint64_t start, uint64_t end) > +{ > +} > + > +static inline void xen_map_pcidev(xc_interface *xc, domid_t dom, > + uint16_t ioservid, > + uint8_t bus, uint8_t device, > + uint8_t function) > +{ > +} > + > +static inline void xen_unmap_pcidev(xc_interface *xc, domid_t dom, > + uint16_t ioservid, > + uint8_t bus, uint8_t device, > + uint8_t function) > +{ > +} > +#else > +static inline int xen_create_ioreq_server(xc_interface *xc, domid_t dom, > + uint16_t *ioservid) > +{ > + int rc = xc_hvm_create_ioreq_server(xc, dom, 1, ioservid); > + > + return rc; > +} > + > +static inline int xen_get_ioreq_server_info(xc_interface *xc, domid_t dom, > + uint16_t ioservid, > + xen_pfn_t *ioreq_pfn, > + xen_pfn_t *bufioreq_pfn, > + uint32_t *bufioreq_evtchn) > +{ > + return xc_hvm_get_ioreq_server_info(xc, dom, ioservid, > + ioreq_pfn, bufioreq_pfn, > + bufioreq_evtchn); > +} > + > +static inline int xen_set_ioreq_server_state(xc_interface *xc, domid_t > dom, > + uint16_t ioservid, > + bool enable) > +{ > + return xc_hvm_set_ioreq_server_state(xc, dom, ioservid, enable); > +} > + > +static inline void xen_map_memory_section(xc_interface *xc, domid_t > dom, > + uint16_t ioservid, > + uint64_t start, uint64_t end) > +{ > + xc_hvm_map_io_range_to_ioreq_server(xc, dom, ioservid, 1, start, end); > +} > + > +static inline void xen_unmap_memory_section(xc_interface *xc, domid_t > dom, > + uint16_t ioservid, > + uint64_t start, uint64_t end) > +{ > + xc_hvm_unmap_io_range_from_ioreq_server(xc, dom, ioservid, 1, start, > end); > +} > + > +static inline void xen_map_io_section(xc_interface *xc, domid_t dom, > + uint16_t ioservid, > + uint64_t start, uint64_t end) > +{ > + xc_hvm_map_io_range_to_ioreq_server(xc, dom, ioservid, 0, start, end); > +} > + > +static inline void xen_unmap_io_section(xc_interface *xc, domid_t dom, > + uint16_t ioservid, > + uint64_t start, uint64_t end) > +{ > + xc_hvm_unmap_io_range_from_ioreq_server(xc, dom, ioservid, 0, start, > end); > +} > + > +static inline void xen_map_pcidev(xc_interface *xc, domid_t dom, > + uint16_t ioservid, > + uint8_t bus, uint8_t device, > + uint8_t function) > +{ > + xc_hvm_map_pcidev_to_ioreq_server(xc, dom, ioservid, 0, > + bus, device, function); > +} > + > +static inline void xen_unmap_pcidev(xc_interface *xc, domid_t dom, > + uint16_t ioservid, > + uint8_t bus, uint8_t device, > + uint8_t function) > +{ > + xc_hvm_unmap_pcidev_from_ioreq_server(xc, dom, ioservid, 0, > + bus, device, function); > +} > +#endif > + > #endif /* QEMU_HW_XEN_COMMON_H */ > diff --git a/hw/xen_machine_fv.c b/hw/xen_machine_fv.c > index b385d6a5..edb8167d 100644 > --- a/hw/xen_machine_fv.c > +++ b/hw/xen_machine_fv.c > @@ -277,7 +277,8 @@ static void xen_init_fv(ram_addr_t ram_size, int > vga_ram_size, > const char *initrd_filename, const char *cpu_model, > const char *direct_pci) > { > - unsigned long ioreq_pfn; > + unsigned long ioreq_pfn, bufioreq_pfn; > + extern uint32_t bufioreq_evtchn; > extern void *shared_page; > extern void *buffered_io_page; > #ifdef __ia64__ > @@ -286,6 +287,7 @@ static void xen_init_fv(ram_addr_t ram_size, int > vga_ram_size, > extern void *buffered_pio_page; > int i; > #endif > + int rc; > > #if defined(__i386__) || defined(__x86_64__) > > @@ -298,7 +300,21 @@ static void xen_init_fv(ram_addr_t ram_size, int > vga_ram_size, > #ifdef CONFIG_STUBDOM /* the hvmop is not supported on older > hypervisors */ > xc_set_hvm_param(xc_handle, domid, HVM_PARAM_DM_DOMAIN, > DOMID_SELF); > #endif > - xc_get_hvm_param(xc_handle, domid, HVM_PARAM_IOREQ_PFN, > &ioreq_pfn); > + rc = xen_create_ioreq_server(xc_handle, domid, &ioservid); > + if (rc < 0) { > + fprintf(logfile, "failed to create ioreq server: error %d\n", errno); > + exit(-1); > + } > + > + fprintf(logfile, "created ioreq server %d\n", ioservid); > + > + rc = xen_get_ioreq_server_info(xc_handle, domid, ioservid, &ioreq_pfn, > + &bufioreq_pfn, &bufioreq_evtchn); > + if (rc < 0) { > + fprintf(logfile, "failed to get ioreq server info: error %d\n", errno); > + exit(-1); > + } > + > fprintf(logfile, "shared page at pfn %lx\n", ioreq_pfn); > shared_page = xc_map_foreign_range(xc_handle, domid, XC_PAGE_SIZE, > PROT_READ|PROT_WRITE, ioreq_pfn); > @@ -307,15 +323,20 @@ static void xen_init_fv(ram_addr_t ram_size, int > vga_ram_size, > exit(-1); > } > > - xc_get_hvm_param(xc_handle, domid, HVM_PARAM_BUFIOREQ_PFN, > &ioreq_pfn); > - fprintf(logfile, "buffered io page at pfn %lx\n", ioreq_pfn); > + fprintf(logfile, "buffered io page at pfn %lx\n", bufioreq_pfn); > buffered_io_page = xc_map_foreign_range(xc_handle, domid, > XC_PAGE_SIZE, > - PROT_READ|PROT_WRITE, ioreq_pfn); > + PROT_READ|PROT_WRITE, bufioreq_pfn); > if (buffered_io_page == NULL) { > fprintf(logfile, "map buffered IO page returned error %d\n", errno); > exit(-1); > } > > + rc = xen_set_ioreq_server_state(xc_handle, domid, ioservid, true); > + if (rc < 0) { > + fprintf(logfile, "failed to enable ioreq server %d\n", errno); > + exit(-1); > + } > + > #if defined(__ia64__) > xc_get_hvm_param(xc_handle, domid, HVM_PARAM_BUFPIOREQ_PFN, > &ioreq_pfn); > fprintf(logfile, "buffered pio page at pfn %lx\n", ioreq_pfn); > diff --git a/i386-dm/exec-dm.c b/i386-dm/exec-dm.c > index 96274d9d..783685ce 100644 > --- a/i386-dm/exec-dm.c > +++ b/i386-dm/exec-dm.c > @@ -40,6 +40,7 @@ > #include "pc.h" > #include "disas.h" > #include "qemu-xen.h" > +#include "xen_common.h" > > //#define DEBUG_TB_INVALIDATE > //#define DEBUG_FLUSH > @@ -308,6 +309,9 @@ void > cpu_register_physical_memory(target_phys_addr_t start_addr, > mmio[mmio_cnt].io_index = phys_offset; > mmio[mmio_cnt].start = start_addr; > mmio[mmio_cnt++].size = size; > + > + xen_map_memory_section(xc_handle, domid, ioservid, start_addr, > + start_addr + size -1); > } > > static int get_free_io_mem_idx(void) > @@ -476,6 +480,9 @@ void unregister_iomem(target_phys_addr_t start) > (unsigned long)(mmio[index].start), > (unsigned long)(mmio[index].start + mmio[index].size)); > mmio[index].size = 0; > + xen_unmap_memory_section(xc_handle, domid, ioservid, > + mmio[index].start, > + mmio[index].start + mmio[index].size - 1); > } > } > > diff --git a/i386-dm/helper2.c b/i386-dm/helper2.c > index 78093fef..ba9d2cee 100644 > --- a/i386-dm/helper2.c > +++ b/i386-dm/helper2.c > @@ -100,6 +100,9 @@ long time_offset = 0; > > shared_iopage_t *shared_page = NULL; > > +uint16_t ioservid; > + > +uint32_t bufioreq_evtchn; > #define BUFFER_IO_MAX_DELAY 100 > buffered_iopage_t *buffered_io_page = NULL; > QEMUTimer *buffered_io_timer; > @@ -120,7 +123,6 @@ CPUX86State *cpu_x86_init(const char *cpu_model) > CPUX86State *env; > static int inited; > int i, rc; > - unsigned long bufioreq_evtchn; > > env = qemu_mallocz(sizeof(CPUX86State)); > if (!env) > @@ -158,13 +160,6 @@ CPUX86State *cpu_x86_init(const char *cpu_model) > } > ioreq_local_port[i] = rc; > } > - rc = xc_get_hvm_param(xc_handle, domid, > HVM_PARAM_BUFIOREQ_EVTCHN, > - &bufioreq_evtchn); > - if (rc < 0) { > - fprintf(logfile, "failed to get HVM_PARAM_BUFIOREQ_EVTCHN > error=%d\n", > - errno); > - return NULL; > - } > rc = xenevtchn_bind_interdomain(xce_handle, domid, > (uint32_t)bufioreq_evtchn); > if (rc == -1) { > fprintf(logfile, "bind interdomain ioctl error %d\n", errno); > @@ -472,11 +467,31 @@ static void cpu_ioreq_timeoffset(CPUState *env, > ioreq_t *req) > > static void __handle_ioreq(CPUState *env, ioreq_t *req) > { > + uint32_t sbdf, val; > + > if (!req->data_is_ptr && (req->dir == IOREQ_WRITE) && > (req->size < sizeof(target_ulong))) > req->data &= ((target_ulong)1 << (8 * req->size)) - 1; > > switch (req->type) { > + case IOREQ_TYPE_PCI_CONFIG: > + sbdf = req->addr >> 32; > + > + /* Fake a write to port 0xCF8 so that > + * the config space access will target the > + * correct device model. > + */ > + val = (1u << 31) | > + ((req->addr & 0x0f00) << 16) | > + ((sbdf & 0xffff) << 8) | > + (req->addr & 0xfc); > + do_outp(env, 0xcf8, 4, val); > + > + /* Now issue the config space access via > + * port 0xCFC > + */ > + req->addr = 0xcfc | (req->addr & 0x03); > + cpu_ioreq_pio(env, req); > case IOREQ_TYPE_PIO: > cpu_ioreq_pio(env, req); > break; > diff --git a/vl.c b/vl.c > index c3c5d630..c8d9896d 100644 > --- a/vl.c > +++ b/vl.c > @@ -46,6 +46,7 @@ > > #include "hw/pci.h" > #include "hw/xen.h" > +#include "hw/xen_common.h" > #include <stdlib.h> > > #include "qemu-xen.h" > @@ -390,6 +391,9 @@ int register_ioport_read(int start, int length, int size, > hw_error("register_ioport_read: invalid opaque"); > ioport_opaque[i] = opaque; > } > + > + xen_map_io_section(xc_handle, domid, ioservid, start, start + length - 1); > + > return 0; > } > > @@ -415,6 +419,9 @@ int register_ioport_write(int start, int length, int size, > hw_error("register_ioport_write: invalid opaque"); > ioport_opaque[i] = opaque; > } > + > + xen_map_io_section(xc_handle, domid, ioservid, start, start + length - 1); > + > return 0; > } > > @@ -433,6 +440,8 @@ void isa_unassign_ioport(int start, int length) > > ioport_opaque[i] = NULL; > } > + > + xen_unmap_io_section(xc_handle, domid, ioservid, start, start + length - > 1); > } > > > /********************************************************** > */ > diff --git a/xen-vl-extra.c b/xen-vl-extra.c > index 206ac658..c346e779 100644 > --- a/xen-vl-extra.c > +++ b/xen-vl-extra.c > @@ -117,6 +117,9 @@ void do_pci_del(char *devname) > else > acpi_php_del(devfn); > > + xen_unmap_pcidev(xc_handle, domid, ioservid, 0, > + PCI_SLOT(devfn), PCI_FUNC(devfn)); > + > free(devname_cpy); > } > > -- > 2.13.5
Paul Durrant <Paul.Durrant@citrix.com> writes: >> -----Original Message----- >> From: Vitaly Kuznetsov [mailto:vkuznets@redhat.com] >> Sent: 06 September 2017 10:29 >> To: xen-devel@lists.xen.org >> Cc: Paul Durrant <Paul.Durrant@citrix.com>; Ian Jackson >> <Ian.Jackson@citrix.com> >> Subject: [PATCH qemu-traditional] switch to the new ioreq server API >> >> Instead of using implicit ioreq server creation side-effect upon reading >> HVM params switch qemu-traditional to using explicit APIs. This opens a >> possibility for removing the above mentioned side-effect and special >> 'default_ioreq_server' code pathes in Xen hypervisor in the future. >> >> This also solves an issue with soft reset when qemu-traditional is being >> used. Xen c/s e7dabe5 ("x86/hvm: don't unconditionally create a default >> ioreq server") disabled ioreq server creation after domain was created >> for the first time and this is needed for soft reset. >> >> IOREQ_TYPE_PCI_CONFIG handling code is stolen as-is from qemu- >> upstream. >> >> Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> > > Reviewed-by: Paul Durrant <paul.durrant@citrix.com> > Ian, could you please have a look? Thanks!
diff --git a/hw/pci.c b/hw/pci.c index c4232856..d6cafb3e 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -34,6 +34,7 @@ #ifdef CONFIG_PASSTHROUGH #include "hw/pass-through.h" #endif +#include "hw/xen_common.h" extern int igd_passthru; @@ -248,6 +249,10 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name, return NULL; found: ; } + + xen_map_pcidev(xc_handle, domid, ioservid, 0, + PCI_SLOT(devfn), PCI_FUNC(devfn)); + pci_dev = qemu_mallocz(instance_size); pci_dev->bus = bus; pci_dev->devfn = devfn; diff --git a/hw/xen_common.h b/hw/xen_common.h index cc48892f..5e172bb2 100644 --- a/hw/xen_common.h +++ b/hw/xen_common.h @@ -33,4 +33,167 @@ # define xen_wmb() wmb() #endif +extern uint16_t ioservid; + +#if __XEN_LATEST_INTERFACE_VERSION__ < 0x00040500 +static inline int xen_create_ioreq_server(xc_interface *xc, domid_t dom, + uint16_t *ioservid) +{ + return 0; +} + +static inline int xen_get_ioreq_server_info(xc_interface *xc, domid_t dom, + uint16_t ioservid, + xen_pfn_t *ioreq_pfn, + xen_pfn_t *bufioreq_pfn, + uint32_t *bufioreq_evtchn) +{ + unsigned long param; + int rc; + + rc = xc_get_hvm_param(xc, dom, HVM_PARAM_IOREQ_PFN, ¶m); + if (rc < 0) { + fprintf(stderr, "failed to get HVM_PARAM_IOREQ_PFN\n"); + return -1; + } + + *ioreq_pfn = param; + + rc = xc_get_hvm_param(xc, dom, HVM_PARAM_BUFIOREQ_PFN, ¶m); + if (rc < 0) { + fprintf(stderr, "failed to get HVM_PARAM_BUFIOREQ_PFN\n"); + return -1; + } + + *bufioreq_pfn = param; + + rc = xc_get_hvm_param(xc, dom, HVM_PARAM_BUFIOREQ_EVTCHN, ¶m); + if (rc < 0) { + fprintf(stderr, "failed to get HVM_PARAM_BUFIOREQ_EVTCHN\n"); + return -1; + } + + *bufioreq_evtchn = param; + + return 0; +} + +static inline int xen_set_ioreq_server_state(xc_interface *xc, domid_t dom, + uint16_t ioservid, + bool enable) +{ + return 0; +} + +static inline void xen_map_memory_section(xc_interface *xc, domid_t dom, + uint16_t ioservid, + uint64_t start, uint64_t end) +{ +} + +static inline void xen_unmap_memory_section(xc_interface *xc, domid_t dom, + uint16_t ioservid, + uint64_t start, uint64_t end) +{ +} + +static inline void xen_map_io_section(xc_interface *xc, domid_t dom, + uint16_t ioservid, + uint64_t start, uint64_t end) +{ +} + +static inline void xen_unmap_io_section(xc_interface *xc, domid_t dom, + uint16_t ioservid, + uint64_t start, uint64_t end) +{ +} + +static inline void xen_map_pcidev(xc_interface *xc, domid_t dom, + uint16_t ioservid, + uint8_t bus, uint8_t device, + uint8_t function) +{ +} + +static inline void xen_unmap_pcidev(xc_interface *xc, domid_t dom, + uint16_t ioservid, + uint8_t bus, uint8_t device, + uint8_t function) +{ +} +#else +static inline int xen_create_ioreq_server(xc_interface *xc, domid_t dom, + uint16_t *ioservid) +{ + int rc = xc_hvm_create_ioreq_server(xc, dom, 1, ioservid); + + return rc; +} + +static inline int xen_get_ioreq_server_info(xc_interface *xc, domid_t dom, + uint16_t ioservid, + xen_pfn_t *ioreq_pfn, + xen_pfn_t *bufioreq_pfn, + uint32_t *bufioreq_evtchn) +{ + return xc_hvm_get_ioreq_server_info(xc, dom, ioservid, + ioreq_pfn, bufioreq_pfn, + bufioreq_evtchn); +} + +static inline int xen_set_ioreq_server_state(xc_interface *xc, domid_t dom, + uint16_t ioservid, + bool enable) +{ + return xc_hvm_set_ioreq_server_state(xc, dom, ioservid, enable); +} + +static inline void xen_map_memory_section(xc_interface *xc, domid_t dom, + uint16_t ioservid, + uint64_t start, uint64_t end) +{ + xc_hvm_map_io_range_to_ioreq_server(xc, dom, ioservid, 1, start, end); +} + +static inline void xen_unmap_memory_section(xc_interface *xc, domid_t dom, + uint16_t ioservid, + uint64_t start, uint64_t end) +{ + xc_hvm_unmap_io_range_from_ioreq_server(xc, dom, ioservid, 1, start, end); +} + +static inline void xen_map_io_section(xc_interface *xc, domid_t dom, + uint16_t ioservid, + uint64_t start, uint64_t end) +{ + xc_hvm_map_io_range_to_ioreq_server(xc, dom, ioservid, 0, start, end); +} + +static inline void xen_unmap_io_section(xc_interface *xc, domid_t dom, + uint16_t ioservid, + uint64_t start, uint64_t end) +{ + xc_hvm_unmap_io_range_from_ioreq_server(xc, dom, ioservid, 0, start, end); +} + +static inline void xen_map_pcidev(xc_interface *xc, domid_t dom, + uint16_t ioservid, + uint8_t bus, uint8_t device, + uint8_t function) +{ + xc_hvm_map_pcidev_to_ioreq_server(xc, dom, ioservid, 0, + bus, device, function); +} + +static inline void xen_unmap_pcidev(xc_interface *xc, domid_t dom, + uint16_t ioservid, + uint8_t bus, uint8_t device, + uint8_t function) +{ + xc_hvm_unmap_pcidev_from_ioreq_server(xc, dom, ioservid, 0, + bus, device, function); +} +#endif + #endif /* QEMU_HW_XEN_COMMON_H */ diff --git a/hw/xen_machine_fv.c b/hw/xen_machine_fv.c index b385d6a5..edb8167d 100644 --- a/hw/xen_machine_fv.c +++ b/hw/xen_machine_fv.c @@ -277,7 +277,8 @@ static void xen_init_fv(ram_addr_t ram_size, int vga_ram_size, const char *initrd_filename, const char *cpu_model, const char *direct_pci) { - unsigned long ioreq_pfn; + unsigned long ioreq_pfn, bufioreq_pfn; + extern uint32_t bufioreq_evtchn; extern void *shared_page; extern void *buffered_io_page; #ifdef __ia64__ @@ -286,6 +287,7 @@ static void xen_init_fv(ram_addr_t ram_size, int vga_ram_size, extern void *buffered_pio_page; int i; #endif + int rc; #if defined(__i386__) || defined(__x86_64__) @@ -298,7 +300,21 @@ static void xen_init_fv(ram_addr_t ram_size, int vga_ram_size, #ifdef CONFIG_STUBDOM /* the hvmop is not supported on older hypervisors */ xc_set_hvm_param(xc_handle, domid, HVM_PARAM_DM_DOMAIN, DOMID_SELF); #endif - xc_get_hvm_param(xc_handle, domid, HVM_PARAM_IOREQ_PFN, &ioreq_pfn); + rc = xen_create_ioreq_server(xc_handle, domid, &ioservid); + if (rc < 0) { + fprintf(logfile, "failed to create ioreq server: error %d\n", errno); + exit(-1); + } + + fprintf(logfile, "created ioreq server %d\n", ioservid); + + rc = xen_get_ioreq_server_info(xc_handle, domid, ioservid, &ioreq_pfn, + &bufioreq_pfn, &bufioreq_evtchn); + if (rc < 0) { + fprintf(logfile, "failed to get ioreq server info: error %d\n", errno); + exit(-1); + } + fprintf(logfile, "shared page at pfn %lx\n", ioreq_pfn); shared_page = xc_map_foreign_range(xc_handle, domid, XC_PAGE_SIZE, PROT_READ|PROT_WRITE, ioreq_pfn); @@ -307,15 +323,20 @@ static void xen_init_fv(ram_addr_t ram_size, int vga_ram_size, exit(-1); } - xc_get_hvm_param(xc_handle, domid, HVM_PARAM_BUFIOREQ_PFN, &ioreq_pfn); - fprintf(logfile, "buffered io page at pfn %lx\n", ioreq_pfn); + fprintf(logfile, "buffered io page at pfn %lx\n", bufioreq_pfn); buffered_io_page = xc_map_foreign_range(xc_handle, domid, XC_PAGE_SIZE, - PROT_READ|PROT_WRITE, ioreq_pfn); + PROT_READ|PROT_WRITE, bufioreq_pfn); if (buffered_io_page == NULL) { fprintf(logfile, "map buffered IO page returned error %d\n", errno); exit(-1); } + rc = xen_set_ioreq_server_state(xc_handle, domid, ioservid, true); + if (rc < 0) { + fprintf(logfile, "failed to enable ioreq server %d\n", errno); + exit(-1); + } + #if defined(__ia64__) xc_get_hvm_param(xc_handle, domid, HVM_PARAM_BUFPIOREQ_PFN, &ioreq_pfn); fprintf(logfile, "buffered pio page at pfn %lx\n", ioreq_pfn); diff --git a/i386-dm/exec-dm.c b/i386-dm/exec-dm.c index 96274d9d..783685ce 100644 --- a/i386-dm/exec-dm.c +++ b/i386-dm/exec-dm.c @@ -40,6 +40,7 @@ #include "pc.h" #include "disas.h" #include "qemu-xen.h" +#include "xen_common.h" //#define DEBUG_TB_INVALIDATE //#define DEBUG_FLUSH @@ -308,6 +309,9 @@ void cpu_register_physical_memory(target_phys_addr_t start_addr, mmio[mmio_cnt].io_index = phys_offset; mmio[mmio_cnt].start = start_addr; mmio[mmio_cnt++].size = size; + + xen_map_memory_section(xc_handle, domid, ioservid, start_addr, + start_addr + size -1); } static int get_free_io_mem_idx(void) @@ -476,6 +480,9 @@ void unregister_iomem(target_phys_addr_t start) (unsigned long)(mmio[index].start), (unsigned long)(mmio[index].start + mmio[index].size)); mmio[index].size = 0; + xen_unmap_memory_section(xc_handle, domid, ioservid, + mmio[index].start, + mmio[index].start + mmio[index].size - 1); } } diff --git a/i386-dm/helper2.c b/i386-dm/helper2.c index 78093fef..ba9d2cee 100644 --- a/i386-dm/helper2.c +++ b/i386-dm/helper2.c @@ -100,6 +100,9 @@ long time_offset = 0; shared_iopage_t *shared_page = NULL; +uint16_t ioservid; + +uint32_t bufioreq_evtchn; #define BUFFER_IO_MAX_DELAY 100 buffered_iopage_t *buffered_io_page = NULL; QEMUTimer *buffered_io_timer; @@ -120,7 +123,6 @@ CPUX86State *cpu_x86_init(const char *cpu_model) CPUX86State *env; static int inited; int i, rc; - unsigned long bufioreq_evtchn; env = qemu_mallocz(sizeof(CPUX86State)); if (!env) @@ -158,13 +160,6 @@ CPUX86State *cpu_x86_init(const char *cpu_model) } ioreq_local_port[i] = rc; } - rc = xc_get_hvm_param(xc_handle, domid, HVM_PARAM_BUFIOREQ_EVTCHN, - &bufioreq_evtchn); - if (rc < 0) { - fprintf(logfile, "failed to get HVM_PARAM_BUFIOREQ_EVTCHN error=%d\n", - errno); - return NULL; - } rc = xenevtchn_bind_interdomain(xce_handle, domid, (uint32_t)bufioreq_evtchn); if (rc == -1) { fprintf(logfile, "bind interdomain ioctl error %d\n", errno); @@ -472,11 +467,31 @@ static void cpu_ioreq_timeoffset(CPUState *env, ioreq_t *req) static void __handle_ioreq(CPUState *env, ioreq_t *req) { + uint32_t sbdf, val; + if (!req->data_is_ptr && (req->dir == IOREQ_WRITE) && (req->size < sizeof(target_ulong))) req->data &= ((target_ulong)1 << (8 * req->size)) - 1; switch (req->type) { + case IOREQ_TYPE_PCI_CONFIG: + sbdf = req->addr >> 32; + + /* Fake a write to port 0xCF8 so that + * the config space access will target the + * correct device model. + */ + val = (1u << 31) | + ((req->addr & 0x0f00) << 16) | + ((sbdf & 0xffff) << 8) | + (req->addr & 0xfc); + do_outp(env, 0xcf8, 4, val); + + /* Now issue the config space access via + * port 0xCFC + */ + req->addr = 0xcfc | (req->addr & 0x03); + cpu_ioreq_pio(env, req); case IOREQ_TYPE_PIO: cpu_ioreq_pio(env, req); break; diff --git a/vl.c b/vl.c index c3c5d630..c8d9896d 100644 --- a/vl.c +++ b/vl.c @@ -46,6 +46,7 @@ #include "hw/pci.h" #include "hw/xen.h" +#include "hw/xen_common.h" #include <stdlib.h> #include "qemu-xen.h" @@ -390,6 +391,9 @@ int register_ioport_read(int start, int length, int size, hw_error("register_ioport_read: invalid opaque"); ioport_opaque[i] = opaque; } + + xen_map_io_section(xc_handle, domid, ioservid, start, start + length - 1); + return 0; } @@ -415,6 +419,9 @@ int register_ioport_write(int start, int length, int size, hw_error("register_ioport_write: invalid opaque"); ioport_opaque[i] = opaque; } + + xen_map_io_section(xc_handle, domid, ioservid, start, start + length - 1); + return 0; } @@ -433,6 +440,8 @@ void isa_unassign_ioport(int start, int length) ioport_opaque[i] = NULL; } + + xen_unmap_io_section(xc_handle, domid, ioservid, start, start + length - 1); } /***********************************************************/ diff --git a/xen-vl-extra.c b/xen-vl-extra.c index 206ac658..c346e779 100644 --- a/xen-vl-extra.c +++ b/xen-vl-extra.c @@ -117,6 +117,9 @@ void do_pci_del(char *devname) else acpi_php_del(devfn); + xen_unmap_pcidev(xc_handle, domid, ioservid, 0, + PCI_SLOT(devfn), PCI_FUNC(devfn)); + free(devname_cpy); }
Instead of using implicit ioreq server creation side-effect upon reading HVM params switch qemu-traditional to using explicit APIs. This opens a possibility for removing the above mentioned side-effect and special 'default_ioreq_server' code pathes in Xen hypervisor in the future. This also solves an issue with soft reset when qemu-traditional is being used. Xen c/s e7dabe5 ("x86/hvm: don't unconditionally create a default ioreq server") disabled ioreq server creation after domain was created for the first time and this is needed for soft reset. IOREQ_TYPE_PCI_CONFIG handling code is stolen as-is from qemu-upstream. Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> --- hw/pci.c | 5 ++ hw/xen_common.h | 163 ++++++++++++++++++++++++++++++++++++++++++++++++++++ hw/xen_machine_fv.c | 31 ++++++++-- i386-dm/exec-dm.c | 7 +++ i386-dm/helper2.c | 31 +++++++--- vl.c | 9 +++ xen-vl-extra.c | 3 + 7 files changed, 236 insertions(+), 13 deletions(-)