[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v2] qemu-trad: stop using the default IOREQ server


  • To: Andrew Cooper <Andrew.Cooper3@xxxxxxxxxx>, Xen-devel <xen-devel@xxxxxxxxxxxxx>
  • From: Paul Durrant <Paul.Durrant@xxxxxxxxxx>
  • Date: Thu, 23 Aug 2018 08:53:12 +0000
  • Accept-language: en-GB, en-US
  • Cc: Ian Jackson <Ian.Jackson@xxxxxxxxxx>
  • Delivery-date: Thu, 23 Aug 2018 08:53:25 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>
  • Thread-index: AQHUNLZhsFf2V8KrpUSo1NI0KmwXiKTNE95Q
  • Thread-topic: [PATCH v2] qemu-trad: stop using the default IOREQ server

> -----Original Message-----
> From: Andrew Cooper [mailto:andrew.cooper3@xxxxxxxxxx]
> Sent: 15 August 2018 17:38
> To: Xen-devel <xen-devel@xxxxxxxxxxxxx>
> Cc: Ian Jackson <Ian.Jackson@xxxxxxxxxx>; Paul Durrant
> <Paul.Durrant@xxxxxxxxxx>
> Subject: [PATCH v2] qemu-trad: stop using the default IOREQ server
> 
> From: Paul Durrant <paul.durrant@xxxxxxxxxx>
> 
> Because qemu-trad is using the legacy HVM param mechanism of hooking
> into
> Xen, it means that Xen has to maintain the notion of a 'default' IOREQ
> server which is where all I/O goes if no other device model claims it.
> Maintaining this code in Xen has a cost and it would be good if the project
> no longer had to pay it.
> 
> This patch makes the necessary minimal changes to the qemu-trad to use the
> IOREQ server API to hook into Xen. This means the default IOREQ server
> will no longer be in use and thus it no longer needs to be maintained.
> 
> Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
> Acked-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
> ---
> v2: Leave comment about MMCFG/legacy compatibility
> ---
>  hw/pci.c            |  3 +++
>  hw/xen_machine_fv.c | 75
> +++++++++++++++++++++++++++++++++++++++++++++++------
>  i386-dm/exec-dm.c   | 10 ++++---
>  i386-dm/helper2.c   | 35 +++++++++++++++++++------
>  qemu-xen.h          |  8 ++++++
>  5 files changed, 112 insertions(+), 19 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index c423285..68e5805 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -263,6 +263,8 @@ PCIDevice *pci_register_device(PCIBus *bus, const
> char *name,
>      pci_dev->config_write = config_write;
>      bus->devices[devfn] = pci_dev;
>      pci_dev->irq = qemu_allocate_irqs(pci_set_irq, pci_dev, 4);
> +
> +    map_pci_dev(pci_dev->devfn);
>      return pci_dev;
>  }
> 
> @@ -305,6 +307,7 @@ int pci_unregister_device(PCIDevice *pci_dev)
>  {
>      int ret = 0;
> 
> +    unmap_pci_dev(pci_dev->devfn);
>      if (pci_dev->unregister)
>          ret = pci_dev->unregister(pci_dev);
>      if (ret)
> diff --git a/hw/xen_machine_fv.c b/hw/xen_machine_fv.c
> index b385d6a..f0989fa 100644
> --- a/hw/xen_machine_fv.c
> +++ b/hw/xen_machine_fv.c
> @@ -30,6 +30,7 @@
>  #include "qemu-xen.h"
>  #include "qemu-aio.h"
>  #include "xen_backend.h"
> +#include "pci.h"
> 
>  #include <xen/hvm/params.h>
>  #include <sys/mman.h>
> @@ -270,6 +271,17 @@ void qemu_invalidate_entry(uint8_t *buffer) {};
> 
>  #endif /* defined(MAPCACHE) */
> 
> +static ioservid_t ioservid;
> +
> +void xen_enable_io(void)
> +{
> +    xc_hvm_set_ioreq_server_state(xc_handle, domid, ioservid, 1);
> +}
> +
> +void xen_disable_io(void)
> +{
> +    xc_hvm_set_ioreq_server_state(xc_handle, domid, ioservid, 0);
> +}
> 
>  static void xen_init_fv(ram_addr_t ram_size, int vga_ram_size,
>                       const char *boot_device,
> @@ -277,7 +289,9 @@ 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;
> +    extern xen_pfn_t ioreq_pfn;
> +    extern xen_pfn_t bufioreq_pfn;
> +    extern evtchn_port_t bufioreq_evtchn;
>      extern void *shared_page;
>      extern void *buffered_io_page;
>  #ifdef __ia64__
> @@ -295,10 +309,22 @@ static void xen_init_fv(ram_addr_t ram_size, int
> vga_ram_size,
>      }
>  #endif
> 
> -#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);
> +    if (xc_hvm_create_ioreq_server(xc_handle, domid,
> +                                   HVM_IOREQSRV_BUFIOREQ_ATOMIC,
> +                                   &ioservid)) {
> +        fprintf(logfile, "failed to create ioreq server: error %d\n",
> +                errno);
> +        exit(-1);
> +    }
> +
> +    if (xc_hvm_get_ioreq_server_info(xc_handle, domid, ioservid,
> +                                     &ioreq_pfn, &bufioreq_pfn,
> +                                     &bufioreq_evtchn)) {
> +        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 +333,17 @@ 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);
>      }
> 
> +    xen_enable_io();
> +
>  #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);
> @@ -377,6 +405,37 @@ static void xen_init_fv(ram_addr_t ram_size, int
> vga_ram_size,
>      pc_machine.init(ram_size, vga_ram_size, boot_device,
>                   kernel_filename, kernel_cmdline, initrd_filename,
>                   cpu_model, direct_pci);
> +
> +    xc_hvm_map_io_range_to_ioreq_server(xc_handle, domid, ioservid,
> +                                        0, 0, 65536);
> +}
> +
> +void map_mmio_range(target_phys_addr_t start_addr, ram_addr_t size)
> +{
> +    ram_addr_t end_addr = start_addr + size - 1;
> +
> +    xc_hvm_map_io_range_to_ioreq_server(xc_handle, domid, ioservid,
> +                                        1, start_addr, end_addr);
> +}
> +
> +void unmap_mmio_range(target_phys_addr_t start_addr, ram_addr_t
> size)
> +{
> +    ram_addr_t end_addr = start_addr + size - 1;
> +
> +    xc_hvm_unmap_io_range_from_ioreq_server(xc_handle, domid,
> ioservid,
> +                                            1, start_addr, end_addr);
> +}
> +
> +void map_pci_dev(int devfn)
> +{
> +    xc_hvm_map_pcidev_to_ioreq_server(xc_handle, domid, ioservid, 0, 0,
> +                                      PCI_SLOT(devfn), PCI_FUNC(devfn));
> +}
> +
> +void unmap_pci_dev(int devfn)
> +{
> +    xc_hvm_unmap_pcidev_from_ioreq_server(xc_handle, domid, ioservid,
> 0, 0,
> +                                          PCI_SLOT(devfn), PCI_FUNC(devfn));
>  }
> 
>  QEMUMachine xenfv_machine = {
> diff --git a/i386-dm/exec-dm.c b/i386-dm/exec-dm.c
> index 96274d9..efdd77e 100644
> --- a/i386-dm/exec-dm.c
> +++ b/i386-dm/exec-dm.c
> @@ -294,8 +294,10 @@ void
> cpu_register_physical_memory(target_phys_addr_t start_addr,
> 
>      for (i = 0; i < mmio_cnt; i++) {
>          if(mmio[i].start == start_addr) {
> +            unmap_mmio_range(start_addr, mmio[i].size);
>              mmio[i].io_index = phys_offset;
>              mmio[i].size = size;
> +            map_mmio_range(start_addr, size);
>              return;
>          }
>      }
> @@ -308,6 +310,7 @@ 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;
> +    map_mmio_range(start_addr, size);
>  }
> 
>  static int get_free_io_mem_idx(void)
> @@ -360,9 +363,10 @@ void cpu_unregister_io_memory(int
> io_table_address)
>      int io_index = io_table_address >> IO_MEM_SHIFT;
> 
>      for (i = 0; i < mmio_cnt; i++) {
> -     if (mmio[i].io_index == io_index) {
> -        mmio[i].start = mmio[i].size = 0;
> -        break;
> +        if (mmio[i].io_index == io_index) {
> +            unmap_mmio_range(mmio[i].start, mmio[i].size);
> +            mmio[i].start = mmio[i].size = 0;
> +            break;
>       }
>      }
> 
> diff --git a/i386-dm/helper2.c b/i386-dm/helper2.c
> index 78093fe..995d63f 100644
> --- a/i386-dm/helper2.c
> +++ b/i386-dm/helper2.c
> @@ -98,6 +98,10 @@ int domid_backend = 0;
> 
>  long time_offset = 0;
> 
> +xen_pfn_t ioreq_pfn;
> +xen_pfn_t bufioreq_pfn;
> +evtchn_port_t bufioreq_evtchn;
> +
>  shared_iopage_t *shared_page = NULL;
> 
>  #define BUFFER_IO_MAX_DELAY  100
> @@ -120,7 +124,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 +161,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);
> @@ -489,6 +485,27 @@ static void __handle_ioreq(CPUState *env, ioreq_t
> *req)
>      case IOREQ_TYPE_INVALIDATE:
>          qemu_invalidate_map_cache();
>          break;
> +    case IOREQ_TYPE_PCI_CONFIG: {
> +        uint32_t sbdf = req->addr >> 32;
> +        uint32_t val;
> +
> +        /*
> +         * QEMU doesn't support MMCFG, so replay the Config cycle as if it 
> has
> +         * been issued via the legacy cf8/cfc mechanism.
> +         */

FAOD this wording looks fine to me.

  Paul

> +
> +        /* Fake out to 0xcf8 */
> +        val = (1u << 31) |
> +            ((req->addr & 0x0f00) << 16) |
> +            ((sbdf & 0xffff) << 8) |
> +            (req->addr & 0xfc);
> +        do_outp(env, 0xcf8, 4, val);
> +
> +        /* Now fake I/O to 0xcfc */
> +        req->addr = 0xcfc | (req->addr & 0x03);
> +        cpu_ioreq_pio(env, req);
> +        break;
> +    }
>      default:
>          hw_error("Invalid ioreq type 0x%x\n", req->type);
>      }
> @@ -645,6 +662,7 @@ int main_loop(void)
> 
>          /* Save the device state */
>          asprintf(&qemu_file, "/var/lib/xen/qemu-save.%d", domid);
> +        xen_disable_io();
>          do_savevm(qemu_file);
>          free(qemu_file);
> 
> @@ -658,6 +676,7 @@ int main_loop(void)
>                  xenstore_process_event(NULL);
>          }
> 
> +        xen_enable_io();
>          xenstore_record_dm_state("running");
>      }
> 
> diff --git a/qemu-xen.h b/qemu-xen.h
> index 0598668..862d399 100644
> --- a/qemu-xen.h
> +++ b/qemu-xen.h
> @@ -138,4 +138,12 @@ int has_tpm_device_danger(void);
>  static void vga_dirty_log_start(void *s) { }
>  static void vga_dirty_log_stop(void *s) { }
> 
> +void xen_enable_io(void);
> +void xen_disable_io(void);
> +
> +void map_mmio_range(target_phys_addr_t start_addr, ram_addr_t size);
> +void unmap_mmio_range(target_phys_addr_t start_addr, ram_addr_t
> size);
> +void map_pci_dev(int devfn);
> +void unmap_pci_dev(int devfn);
> +
>  #endif /*QEMU_XEN_H*/
> --
> 2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.