* [PATCH] qemu-trad: stop using the default IOREQ server
@ 2018-08-03 13:20 Paul Durrant
2018-08-03 13:23 ` Andrew Cooper
2018-08-15 11:00 ` Ian Jackson
0 siblings, 2 replies; 5+ messages in thread
From: Paul Durrant @ 2018-08-03 13:20 UTC (permalink / raw)
To: xen-devel
Cc: Stefano Stabellini, Wei Liu, George Dunlap, Andrew Cooper,
Ian Jackson, Tim Deegan, Julien Grall, Paul Durrant, Jan Beulich
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@citrix.com>
---
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: George Dunlap <George.Dunlap@eu.citrix.com>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Julien Grall <julien.grall@arm.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Tim Deegan <tim@xen.org>
Cc: Wei Liu <wei.liu2@citrix.com>
---
hw/pci.c | 3 +++
hw/xen_machine_fv.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++------
i386-dm/exec-dm.c | 10 ++++---
i386-dm/helper2.c | 30 +++++++++++++++------
qemu-xen.h | 8 ++++++
5 files changed, 107 insertions(+), 19 deletions(-)
diff --git a/hw/pci.c b/hw/pci.c
index c4232856..68e5805f 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 b385d6a5..f0989fad 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 96274d9d..efdd77eb 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 78093fef..f2f82e1c 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,22 @@ 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;
+
+ /* 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 +657,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 +671,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 05986687..862d3998 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.11.0
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH] qemu-trad: stop using the default IOREQ server
2018-08-03 13:20 [PATCH] qemu-trad: stop using the default IOREQ server Paul Durrant
@ 2018-08-03 13:23 ` Andrew Cooper
2018-08-15 11:00 ` Ian Jackson
1 sibling, 0 replies; 5+ messages in thread
From: Andrew Cooper @ 2018-08-03 13:23 UTC (permalink / raw)
To: Paul Durrant, xen-devel
Cc: Stefano Stabellini, Wei Liu, George Dunlap, Tim Deegan,
Ian Jackson, Julien Grall, Jan Beulich
On 03/08/18 14:20, Paul Durrant wrote:
> 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@citrix.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
While qemu-trad is supposed to be in deep-freeze, this small change will
allow for substantial cleanup and simplification in the hypervisor.
~Andrew
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] qemu-trad: stop using the default IOREQ server
2018-08-03 13:20 [PATCH] qemu-trad: stop using the default IOREQ server Paul Durrant
2018-08-03 13:23 ` Andrew Cooper
@ 2018-08-15 11:00 ` Ian Jackson
2018-08-15 13:26 ` Andrew Cooper
1 sibling, 1 reply; 5+ messages in thread
From: Ian Jackson @ 2018-08-15 11:00 UTC (permalink / raw)
To: Paul Durrant
Cc: Stefano Stabellini, Wei Liu, George Dunlap, Andrew Cooper,
Tim Deegan, Julien Grall, Jan Beulich, xen-devel
Paul Durrant writes ("[PATCH] qemu-trad: stop using the default IOREQ server"):
> 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.
That is a good thing.
I looked overr the patch. Most of it is about what I would have
expected.
But I did want to query this:
> + case IOREQ_TYPE_PCI_CONFIG: {
> + uint32_t sbdf = req->addr >> 32;
> + uint32_t val;
> +
> + /* 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;
> + }
This looks messy. Can someone please explain why this is needed and
why it is best to do it this way ?
(I'm don't know much about PCI, which is probably a contributory
factor in my querying this. Sorry about that.)
Regards,
Ian.
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH] qemu-trad: stop using the default IOREQ server
2018-08-15 11:00 ` Ian Jackson
@ 2018-08-15 13:26 ` Andrew Cooper
2018-08-15 15:55 ` Ian Jackson
0 siblings, 1 reply; 5+ messages in thread
From: Andrew Cooper @ 2018-08-15 13:26 UTC (permalink / raw)
To: Ian Jackson, Paul Durrant
Cc: Stefano Stabellini, Wei Liu, George Dunlap, Tim Deegan,
Julien Grall, Jan Beulich, xen-devel
On 15/08/18 12:00, Ian Jackson wrote:
> Paul Durrant writes ("[PATCH] qemu-trad: stop using the default IOREQ server"):
>> 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.
> That is a good thing.
>
> I looked overr the patch. Most of it is about what I would have
> expected.
>
> But I did want to query this:
>
>> + case IOREQ_TYPE_PCI_CONFIG: {
>> + uint32_t sbdf = req->addr >> 32;
>> + uint32_t val;
>> +
>> + /* 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;
>> + }
> This looks messy. Can someone please explain why this is needed and
> why it is best to do it this way ?
>
> (I'm don't know much about PCI, which is probably a contributory
> factor in my querying this. Sorry about that.)
Paul is OoO for a while, so replying on his behalf.
Qemu-trad has no support for MMCFG, which is the memory mapped interface
which supersedes the more legacy cfc/cf8 handling for PCI config space
accesses.
Xen's interface passes the requisite information in MMCFG format, which
is the most efficient way to do it. This piece of (admittedly messy)
code converts the information to the legacy interface which is the one
which Qemu understands.
tl;dr, It's messy, but it is correct, and is the best (/only, short of
implementing MMCFG support in qemu-trad) way of doing it.
~Andrew
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH] qemu-trad: stop using the default IOREQ server
2018-08-15 13:26 ` Andrew Cooper
@ 2018-08-15 15:55 ` Ian Jackson
0 siblings, 0 replies; 5+ messages in thread
From: Ian Jackson @ 2018-08-15 15:55 UTC (permalink / raw)
To: Andrew Cooper
Cc: Stefano Stabellini, Wei Liu, George Dunlap, Tim Deegan,
Julien Grall, Paul Durrant, Jan Beulich, xen-devel
Andrew Cooper writes ("[PATCH] qemu-trad: stop using the default IOREQ server"):
> Paul is OoO for a while, so replying on his behalf.
Thank you.
> Qemu-trad has no support for MMCFG, which is the memory mapped interface
> which supersedes the more legacy cfc/cf8 handling for PCI config space
> accesses.
>
> Xen's interface passes the requisite information in MMCFG format, which
> is the most efficient way to do it. This piece of (admittedly messy)
> code converts the information to the legacy interface which is the one
> which Qemu understands.
>
> tl;dr, It's messy, but it is correct, and is the best (/only, short of
> implementing MMCFG support in qemu-trad) way of doing it.
Thanks for this excelent explanation. Can you please add it to the
commit message and/or to a comment in the code ? You may then add my
ack. I will then commit the patch :-).
Ian.
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2018-08-15 15:55 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-08-03 13:20 [PATCH] qemu-trad: stop using the default IOREQ server Paul Durrant
2018-08-03 13:23 ` Andrew Cooper
2018-08-15 11:00 ` Ian Jackson
2018-08-15 13:26 ` Andrew Cooper
2018-08-15 15:55 ` Ian Jackson
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).