Merge remote-tracking branch 'remotes/sstabellini/xen-140507-2' into staging

* remotes/sstabellini/xen-140507-2:
  xen_disk: add discard support
  pass an inclusive address range to xc_domain_pin_memory_cacheattr
  xen: factor out common functions
  xen: move Xen HVM files under hw/i386/xen
  xen: move Xen PV machine files to hw/xenpv
  qemu-xen: free all the pirqs for msi/msix when driver unload
  exec: Limit translation limiting in address_space_translate to xen

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
master
Peter Maydell 2014-05-07 18:12:14 +01:00
commit 5894145a26
21 changed files with 227 additions and 133 deletions

View File

@ -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)

2
exec.c
View File

@ -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);
}

View File

@ -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++)

View File

@ -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;

View File

@ -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

View File

@ -0,0 +1 @@
obj-y += xen_platform.o xen_apic.o xen_pvdevice.o

View File

@ -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

View File

@ -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;

View File

@ -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;
}

2
hw/xenpv/Makefile.objs Normal file
View File

@ -0,0 +1,2 @@
# Xen PV machine support
obj-$(CONFIG_XEN) += xen_domainbuild.o xen_machine_pv.o

View File

@ -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)

19
xen-common-stub.c Normal file
View File

@ -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;
}

123
xen-common.c Normal file
View File

@ -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;
}

View File

@ -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)
{
}

View File

@ -26,9 +26,9 @@
#include <xen/hvm/params.h>
#include <xen/hvm/e820.h>
//#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();
}
}