diff --git a/Makefile.target b/Makefile.target index ba1234063e..6d8fde8b9e 100644 --- a/Makefile.target +++ b/Makefile.target @@ -120,8 +120,10 @@ obj-y += dump.o LIBS+=$(libs_softmmu) # xen support -obj-$(CONFIG_XEN) += xen-all.o xen-mapcache.o -obj-$(call lnot,$(CONFIG_XEN)) += xen-stub.o +obj-$(CONFIG_XEN) += xen-common.o +obj-$(CONFIG_XEN_I386) += xen-hvm.o xen-mapcache.o +obj-$(call lnot,$(CONFIG_XEN)) += xen-common-stub.o +obj-$(call lnot,$(CONFIG_XEN_I386)) += xen-hvm-stub.o # Hardware support ifeq ($(TARGET_NAME), sparc64) diff --git a/exec.c b/exec.c index 91513c6c43..cf120496f7 100644 --- a/exec.c +++ b/exec.c @@ -380,7 +380,7 @@ MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr, as = iotlb.target_as; } - if (memory_access_is_direct(mr, is_write)) { + if (xen_enabled() && memory_access_is_direct(mr, is_write)) { hwaddr page = ((addr & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE) - addr; len = MIN(page, len); } diff --git a/hw/block/xen_blkif.h b/hw/block/xen_blkif.h index c0f4136228..711b692742 100644 --- a/hw/block/xen_blkif.h +++ b/hw/block/xen_blkif.h @@ -79,6 +79,12 @@ static inline void blkif_get_x86_32_req(blkif_request_t *dst, blkif_x86_32_reque dst->handle = src->handle; dst->id = src->id; dst->sector_number = src->sector_number; + if (src->operation == BLKIF_OP_DISCARD) { + struct blkif_request_discard *s = (void *)src; + struct blkif_request_discard *d = (void *)dst; + d->nr_sectors = s->nr_sectors; + return; + } if (n > src->nr_segments) n = src->nr_segments; for (i = 0; i < n; i++) @@ -94,6 +100,12 @@ static inline void blkif_get_x86_64_req(blkif_request_t *dst, blkif_x86_64_reque dst->handle = src->handle; dst->id = src->id; dst->sector_number = src->sector_number; + if (src->operation == BLKIF_OP_DISCARD) { + struct blkif_request_discard *s = (void *)src; + struct blkif_request_discard *d = (void *)dst; + d->nr_sectors = s->nr_sectors; + return; + } if (n > src->nr_segments) n = src->nr_segments; for (i = 0; i < n; i++) diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c index a8fea72edf..aed5b5b3e9 100644 --- a/hw/block/xen_disk.c +++ b/hw/block/xen_disk.c @@ -114,6 +114,7 @@ struct XenBlkDev { int requests_finished; /* Persistent grants extension */ + gboolean feature_discard; gboolean feature_persistent; GTree *persistent_gnts; unsigned int persistent_gnt_count; @@ -253,6 +254,8 @@ static int ioreq_parse(struct ioreq *ioreq) case BLKIF_OP_WRITE: ioreq->prot = PROT_READ; /* from memory */ break; + case BLKIF_OP_DISCARD: + return 0; default: xen_be_printf(&blkdev->xendev, 0, "error: unknown operation (%d)\n", ioreq->req.operation); @@ -492,6 +495,7 @@ static void qemu_aio_complete(void *opaque, int ret) case BLKIF_OP_READ: bdrv_acct_done(ioreq->blkdev->bs, &ioreq->acct); break; + case BLKIF_OP_DISCARD: default: break; } @@ -532,6 +536,15 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq) &ioreq->v, ioreq->v.size / BLOCK_SIZE, qemu_aio_complete, ioreq); break; + case BLKIF_OP_DISCARD: + { + struct blkif_request_discard *discard_req = (void *)&ioreq->req; + ioreq->aio_inflight++; + bdrv_aio_discard(blkdev->bs, + discard_req->sector_number, discard_req->nr_sectors, + qemu_aio_complete, ioreq); + break; + } default: /* unknown operation (shouldn't happen -- parse catches this) */ goto err; @@ -710,6 +723,21 @@ static void blk_alloc(struct XenDevice *xendev) } } +static void blk_parse_discard(struct XenBlkDev *blkdev) +{ + int enable; + + blkdev->feature_discard = true; + + if (xenstore_read_be_int(&blkdev->xendev, "discard-enable", &enable) == 0) { + blkdev->feature_discard = !!enable; + } + + if (blkdev->feature_discard) { + xenstore_write_be_int(&blkdev->xendev, "feature-discard", 1); + } +} + static int blk_init(struct XenDevice *xendev) { struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); @@ -777,6 +805,8 @@ static int blk_init(struct XenDevice *xendev) xenstore_write_be_int(&blkdev->xendev, "feature-persistent", 1); xenstore_write_be_int(&blkdev->xendev, "info", info); + blk_parse_discard(blkdev); + g_free(directiosafe); return 0; @@ -812,6 +842,9 @@ static int blk_connect(struct XenDevice *xendev) qflags |= BDRV_O_RDWR; readonly = false; } + if (blkdev->feature_discard) { + qflags |= BDRV_O_UNMAP; + } /* init qemu block driver */ index = (blkdev->xendev.dev - 202 * 256) / 16; diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs index 3df1612651..f66c349508 100644 --- a/hw/i386/Makefile.objs +++ b/hw/i386/Makefile.objs @@ -2,7 +2,7 @@ obj-$(CONFIG_KVM) += kvm/ obj-y += multiboot.o smbios.o obj-y += pc.o pc_piix.o pc_q35.o obj-y += pc_sysfw.o -obj-$(CONFIG_XEN) += xen_domainbuild.o xen_machine_pv.o +obj-$(CONFIG_XEN) += ../xenpv/ xen/ obj-y += kvmvapic.o obj-y += acpi-build.o diff --git a/hw/i386/xen/Makefile.objs b/hw/i386/xen/Makefile.objs new file mode 100644 index 0000000000..801a68d326 --- /dev/null +++ b/hw/i386/xen/Makefile.objs @@ -0,0 +1 @@ +obj-y += xen_platform.o xen_apic.o xen_pvdevice.o diff --git a/hw/xen/xen_apic.c b/hw/i386/xen/xen_apic.c similarity index 100% rename from hw/xen/xen_apic.c rename to hw/i386/xen/xen_apic.c diff --git a/hw/xen/xen_platform.c b/hw/i386/xen/xen_platform.c similarity index 100% rename from hw/xen/xen_platform.c rename to hw/i386/xen/xen_platform.c diff --git a/hw/xen/xen_pvdevice.c b/hw/i386/xen/xen_pvdevice.c similarity index 100% rename from hw/xen/xen_pvdevice.c rename to hw/i386/xen/xen_pvdevice.c diff --git a/hw/xen/Makefile.objs b/hw/xen/Makefile.objs index ce640c61a5..a0ca0aa3df 100644 --- a/hw/xen/Makefile.objs +++ b/hw/xen/Makefile.objs @@ -1,6 +1,5 @@ # xen backend driver support common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o xen_devconfig.o -obj-$(CONFIG_XEN_I386) += xen_platform.o xen_apic.o xen_pvdevice.o obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen-host-pci-device.o obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_msi.o diff --git a/hw/xen/xen_pt_config_init.c b/hw/xen/xen_pt_config_init.c index 8ccc2e4b9c..de9a20f437 100644 --- a/hw/xen/xen_pt_config_init.c +++ b/hw/xen/xen_pt_config_init.c @@ -1123,8 +1123,8 @@ static int xen_pt_msgctrl_reg_write(XenPCIPassthroughState *s, msi->mapped = true; } msi->flags |= PCI_MSI_FLAGS_ENABLE; - } else { - msi->flags &= ~PCI_MSI_FLAGS_ENABLE; + } else if (msi->mapped) { + xen_pt_msi_disable(s); } /* pass through MSI_ENABLE bit */ @@ -1397,6 +1397,8 @@ static int xen_pt_msixctrl_reg_write(XenPCIPassthroughState *s, if ((*val & PCI_MSIX_FLAGS_ENABLE) && !(*val & PCI_MSIX_FLAGS_MASKALL)) { xen_pt_msix_update(s); + } else if (!(*val & PCI_MSIX_FLAGS_ENABLE) && s->msix->enabled) { + xen_pt_msix_disable(s); } debug_msix_enabled_old = s->msix->enabled; diff --git a/hw/xen/xen_pt_msi.c b/hw/xen/xen_pt_msi.c index 6fbe0cc86b..12b4c4560c 100644 --- a/hw/xen/xen_pt_msi.c +++ b/hw/xen/xen_pt_msi.c @@ -282,7 +282,8 @@ void xen_pt_msi_disable(XenPCIPassthroughState *s) msi->initialized); /* clear msi info */ - msi->flags = 0; + msi->flags &= ~PCI_MSI_FLAGS_ENABLE; + msi->initialized = false; msi->mapped = false; msi->pirq = XEN_PT_UNASSIGNED_PIRQ; } @@ -446,7 +447,8 @@ static void pci_msix_write(void *opaque, hwaddr addr, if (offset != PCI_MSIX_ENTRY_VECTOR_CTRL) { const volatile uint32_t *vec_ctrl; - if (get_entry_value(entry, offset) == val) { + if (get_entry_value(entry, offset) == val + && entry->pirq != XEN_PT_UNASSIGNED_PIRQ) { return; } diff --git a/hw/xenpv/Makefile.objs b/hw/xenpv/Makefile.objs new file mode 100644 index 0000000000..49f6e9e3c5 --- /dev/null +++ b/hw/xenpv/Makefile.objs @@ -0,0 +1,2 @@ +# Xen PV machine support +obj-$(CONFIG_XEN) += xen_domainbuild.o xen_machine_pv.o diff --git a/hw/i386/xen_domainbuild.c b/hw/xenpv/xen_domainbuild.c similarity index 100% rename from hw/i386/xen_domainbuild.c rename to hw/xenpv/xen_domainbuild.c diff --git a/hw/i386/xen_domainbuild.h b/hw/xenpv/xen_domainbuild.h similarity index 100% rename from hw/i386/xen_domainbuild.h rename to hw/xenpv/xen_domainbuild.h diff --git a/hw/i386/xen_machine_pv.c b/hw/xenpv/xen_machine_pv.c similarity index 100% rename from hw/i386/xen_machine_pv.c rename to hw/xenpv/xen_machine_pv.c diff --git a/include/hw/xen/xen_common.h b/include/hw/xen/xen_common.h index 2d5a25bf40..07731b9289 100644 --- a/include/hw/xen/xen_common.h +++ b/include/hw/xen/xen_common.h @@ -144,6 +144,13 @@ static inline int xen_xc_hvm_inject_msi(XenXC xen_xc, domid_t dom, { return -ENOSYS; } +/* The followings are only to compile op_discard related code on older + * Xen releases. */ +#define BLKIF_OP_DISCARD 5 +struct blkif_request_discard { + uint64_t nr_sectors; + uint64_t sector_number; +}; #else static inline int xen_xc_hvm_inject_msi(XenXC xen_xc, domid_t dom, uint64_t addr, uint32_t data) diff --git a/xen-common-stub.c b/xen-common-stub.c new file mode 100644 index 0000000000..bd56ca2ce5 --- /dev/null +++ b/xen-common-stub.c @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2014 Citrix Systems UK Ltd. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu-common.h" +#include "hw/xen/xen.h" + +void xenstore_store_pv_console_info(int i, CharDriverState *chr) +{ +} + +int xen_init(MachineClass *mc) +{ + return -ENOSYS; +} + diff --git a/xen-common.c b/xen-common.c new file mode 100644 index 0000000000..f07b35e471 --- /dev/null +++ b/xen-common.c @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2014 Citrix Systems UK Ltd. + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + * Contributions after 2012-01-13 are licensed under the terms of the + * GNU GPL, version 2 or (at your option) any later version. + */ + +#include "hw/xen/xen_backend.h" +#include "qmp-commands.h" +#include "sysemu/char.h" + +//#define DEBUG_XEN + +#ifdef DEBUG_XEN +#define DPRINTF(fmt, ...) \ + do { fprintf(stderr, "xen: " fmt, ## __VA_ARGS__); } while (0) +#else +#define DPRINTF(fmt, ...) \ + do { } while (0) +#endif + +static int store_dev_info(int domid, CharDriverState *cs, const char *string) +{ + struct xs_handle *xs = NULL; + char *path = NULL; + char *newpath = NULL; + char *pts = NULL; + int ret = -1; + + /* Only continue if we're talking to a pty. */ + if (strncmp(cs->filename, "pty:", 4)) { + return 0; + } + pts = cs->filename + 4; + + /* We now have everything we need to set the xenstore entry. */ + xs = xs_open(0); + if (xs == NULL) { + fprintf(stderr, "Could not contact XenStore\n"); + goto out; + } + + path = xs_get_domain_path(xs, domid); + if (path == NULL) { + fprintf(stderr, "xs_get_domain_path() error\n"); + goto out; + } + newpath = realloc(path, (strlen(path) + strlen(string) + + strlen("/tty") + 1)); + if (newpath == NULL) { + fprintf(stderr, "realloc error\n"); + goto out; + } + path = newpath; + + strcat(path, string); + strcat(path, "/tty"); + if (!xs_write(xs, XBT_NULL, path, pts, strlen(pts))) { + fprintf(stderr, "xs_write for '%s' fail", string); + goto out; + } + ret = 0; + +out: + free(path); + xs_close(xs); + + return ret; +} + +void xenstore_store_pv_console_info(int i, CharDriverState *chr) +{ + if (i == 0) { + store_dev_info(xen_domid, chr, "/console"); + } else { + char buf[32]; + snprintf(buf, sizeof(buf), "/device/console/%d", i); + store_dev_info(xen_domid, chr, buf); + } +} + + +static void xenstore_record_dm_state(struct xs_handle *xs, const char *state) +{ + char path[50]; + + if (xs == NULL) { + fprintf(stderr, "xenstore connection not initialized\n"); + exit(1); + } + + snprintf(path, sizeof (path), "device-model/%u/state", xen_domid); + if (!xs_write(xs, XBT_NULL, path, state, strlen(state))) { + fprintf(stderr, "error recording dm state\n"); + exit(1); + } +} + + +static void xen_change_state_handler(void *opaque, int running, + RunState state) +{ + if (running) { + /* record state running */ + xenstore_record_dm_state(xenstore, "running"); + } +} + +int xen_init(MachineClass *mc) +{ + xen_xc = xen_xc_interface_open(0, 0, 0); + if (xen_xc == XC_HANDLER_INITIAL_VALUE) { + xen_be_printf(NULL, 0, "can't open xen interface\n"); + return -1; + } + qemu_add_vm_change_state_handler(xen_change_state_handler, NULL); + + return 0; +} + diff --git a/xen-stub.c b/xen-hvm-stub.c similarity index 90% rename from xen-stub.c rename to xen-hvm-stub.c index de26583a23..4eb27b5f2b 100644 --- a/xen-stub.c +++ b/xen-hvm-stub.c @@ -13,10 +13,6 @@ #include "exec/memory.h" #include "qmp-commands.h" -void xenstore_store_pv_console_info(int i, CharDriverState *chr) -{ -} - int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num) { return -1; @@ -47,19 +43,10 @@ qemu_irq *xen_interrupt_controller_init(void) return NULL; } -int xen_init(MachineClass *mc) -{ - return -ENOSYS; -} - void xen_register_framebuffer(MemoryRegion *mr) { } -void qmp_xen_set_global_dirty_log(bool enable, Error **errp) -{ -} - void xen_modified_memory(ram_addr_t start, ram_addr_t length) { } @@ -68,3 +55,7 @@ int xen_hvm_init(MemoryRegion **ram_memory) { return 0; } + +void qmp_xen_set_global_dirty_log(bool enable, Error **errp) +{ +} diff --git a/xen-all.c b/xen-hvm.c similarity index 93% rename from xen-all.c rename to xen-hvm.c index a63b53152a..a64486cd35 100644 --- a/xen-all.c +++ b/xen-hvm.c @@ -26,9 +26,9 @@ #include #include -//#define DEBUG_XEN +//#define DEBUG_XEN_HVM -#ifdef DEBUG_XEN +#ifdef DEBUG_XEN_HVM #define DPRINTF(fmt, ...) \ do { fprintf(stderr, "xen: " fmt, ## __VA_ARGS__); } while (0) #else @@ -323,7 +323,7 @@ go_physmap: xc_domain_pin_memory_cacheattr(xen_xc, xen_domid, start_addr >> TARGET_PAGE_BITS, - (start_addr + size) >> TARGET_PAGE_BITS, + (start_addr + size - 1) >> TARGET_PAGE_BITS, XEN_DOMCTL_MEM_CACHEATTR_WB); snprintf(path, sizeof(path), @@ -569,15 +569,6 @@ static MemoryListener xen_memory_listener = { .priority = 10, }; -void qmp_xen_set_global_dirty_log(bool enable, Error **errp) -{ - if (enable) { - memory_global_dirty_log_start(); - } else { - memory_global_dirty_log_stop(); - } -} - /* get the ioreq packets from share mem */ static ioreq_t *cpu_get_ioreq_from_shared_memory(XenIOState *state, int vcpu) { @@ -880,82 +871,6 @@ static void cpu_handle_ioreq(void *opaque) } } -static int store_dev_info(int domid, CharDriverState *cs, const char *string) -{ - struct xs_handle *xs = NULL; - char *path = NULL; - char *newpath = NULL; - char *pts = NULL; - int ret = -1; - - /* Only continue if we're talking to a pty. */ - if (strncmp(cs->filename, "pty:", 4)) { - return 0; - } - pts = cs->filename + 4; - - /* We now have everything we need to set the xenstore entry. */ - xs = xs_open(0); - if (xs == NULL) { - fprintf(stderr, "Could not contact XenStore\n"); - goto out; - } - - path = xs_get_domain_path(xs, domid); - if (path == NULL) { - fprintf(stderr, "xs_get_domain_path() error\n"); - goto out; - } - newpath = realloc(path, (strlen(path) + strlen(string) + - strlen("/tty") + 1)); - if (newpath == NULL) { - fprintf(stderr, "realloc error\n"); - goto out; - } - path = newpath; - - strcat(path, string); - strcat(path, "/tty"); - if (!xs_write(xs, XBT_NULL, path, pts, strlen(pts))) { - fprintf(stderr, "xs_write for '%s' fail", string); - goto out; - } - ret = 0; - -out: - free(path); - xs_close(xs); - - return ret; -} - -void xenstore_store_pv_console_info(int i, CharDriverState *chr) -{ - if (i == 0) { - store_dev_info(xen_domid, chr, "/console"); - } else { - char buf[32]; - snprintf(buf, sizeof(buf), "/device/console/%d", i); - store_dev_info(xen_domid, chr, buf); - } -} - -static void xenstore_record_dm_state(struct xs_handle *xs, const char *state) -{ - char path[50]; - - if (xs == NULL) { - fprintf(stderr, "xenstore connection not initialized\n"); - exit(1); - } - - snprintf(path, sizeof (path), "device-model/%u/state", xen_domid); - if (!xs_write(xs, XBT_NULL, path, state, strlen(state))) { - fprintf(stderr, "error recording dm state\n"); - exit(1); - } -} - static void xen_main_loop_prepare(XenIOState *state) { int evtchn_fd = -1; @@ -973,17 +888,6 @@ static void xen_main_loop_prepare(XenIOState *state) } -/* Initialise Xen */ - -static void xen_change_state_handler(void *opaque, int running, - RunState state) -{ - if (running) { - /* record state running */ - xenstore_record_dm_state(xenstore, "running"); - } -} - static void xen_hvm_change_state_handler(void *opaque, int running, RunState rstate) { @@ -1001,18 +905,6 @@ static void xen_exit_notifier(Notifier *n, void *data) xs_daemon_close(state->xenstore); } -int xen_init(MachineClass *mc) -{ - xen_xc = xen_xc_interface_open(0, 0, 0); - if (xen_xc == XC_HANDLER_INITIAL_VALUE) { - xen_be_printf(NULL, 0, "can't open xen interface\n"); - return -1; - } - qemu_add_vm_change_state_handler(xen_change_state_handler, NULL); - - return 0; -} - static void xen_read_physmap(XenIOState *state) { XenPhysmap *physmap = NULL; @@ -1226,3 +1118,12 @@ void xen_modified_memory(ram_addr_t start, ram_addr_t length) } } } + +void qmp_xen_set_global_dirty_log(bool enable, Error **errp) +{ + if (enable) { + memory_global_dirty_log_start(); + } else { + memory_global_dirty_log_stop(); + } +}