aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/acpi/pcihp.c18
-rw-r--r--hw/block/xen_blkif.h12
-rw-r--r--hw/block/xen_disk.c33
-rw-r--r--hw/i2c/pm_smbus.c63
-rw-r--r--hw/i2c/smbus.c68
-rw-r--r--hw/i386/Makefile.objs2
-rw-r--r--hw/i386/acpi-build.c13
-rw-r--r--hw/i386/pc_piix.c4
-rw-r--r--hw/i386/pc_q35.c4
-rw-r--r--hw/i386/xen/Makefile.objs1
-rw-r--r--hw/i386/xen/xen_apic.c (renamed from hw/xen/xen_apic.c)0
-rw-r--r--hw/i386/xen/xen_platform.c (renamed from hw/xen/xen_platform.c)0
-rw-r--r--hw/i386/xen/xen_pvdevice.c (renamed from hw/xen/xen_pvdevice.c)0
-rw-r--r--hw/intc/apic.c2
-rw-r--r--hw/intc/apic_common.c1
-rw-r--r--hw/intc/i8259.c3
-rw-r--r--hw/xen/Makefile.objs1
-rw-r--r--hw/xen/xen_pt_config_init.c6
-rw-r--r--hw/xen/xen_pt_msi.c6
-rw-r--r--hw/xenpv/Makefile.objs2
-rw-r--r--hw/xenpv/xen_domainbuild.c (renamed from hw/i386/xen_domainbuild.c)0
-rw-r--r--hw/xenpv/xen_domainbuild.h (renamed from hw/i386/xen_domainbuild.h)0
-rw-r--r--hw/xenpv/xen_machine_pv.c (renamed from hw/i386/xen_machine_pv.c)0
23 files changed, 177 insertions, 62 deletions
diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c
index f80c48008c..3b143b371b 100644
--- a/hw/acpi/pcihp.c
+++ b/hw/acpi/pcihp.c
@@ -63,16 +63,18 @@ typedef struct AcpiPciHpFind {
static int acpi_pcihp_get_bsel(PCIBus *bus)
{
- QObject *o = object_property_get_qobject(OBJECT(bus),
- ACPI_PCIHP_PROP_BSEL, NULL);
- int64_t bsel = -1;
- if (o) {
- bsel = qint_get_int(qobject_to_qint(o));
- }
- if (bsel < 0) {
+ Error *local_err = NULL;
+ int64_t bsel = object_property_get_int(OBJECT(bus), ACPI_PCIHP_PROP_BSEL,
+ &local_err);
+
+ if (local_err || bsel < 0 || bsel >= ACPI_PCIHP_MAX_HOTPLUG_BUS) {
+ if (local_err) {
+ error_free(local_err);
+ }
return -1;
+ } else {
+ return bsel;
}
- return bsel;
}
static void acpi_pcihp_test_hotplug_bus(PCIBus *bus, void *opaque)
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/i2c/pm_smbus.c b/hw/i2c/pm_smbus.c
index 9f50067735..fedb5fb4d4 100644
--- a/hw/i2c/pm_smbus.c
+++ b/hw/i2c/pm_smbus.c
@@ -60,59 +60,78 @@ static void smb_transaction(PMSMBus *s)
uint8_t cmd = s->smb_cmd;
uint8_t addr = s->smb_addr >> 1;
I2CBus *bus = s->smbus;
+ int ret;
SMBUS_DPRINTF("SMBus trans addr=0x%02x prot=0x%02x\n", addr, prot);
/* Transaction isn't exec if STS_DEV_ERR bit set */
if ((s->smb_stat & STS_DEV_ERR) != 0) {
- goto error;
- }
+ goto error;
+ }
switch(prot) {
case 0x0:
- smbus_quick_command(bus, addr, read);
- s->smb_stat |= STS_BYTE_DONE | STS_INTR;
- break;
+ ret = smbus_quick_command(bus, addr, read);
+ goto done;
case 0x1:
if (read) {
- s->smb_data0 = smbus_receive_byte(bus, addr);
+ ret = smbus_receive_byte(bus, addr);
+ goto data8;
} else {
- smbus_send_byte(bus, addr, cmd);
+ ret = smbus_send_byte(bus, addr, cmd);
+ goto done;
}
- s->smb_stat |= STS_BYTE_DONE | STS_INTR;
- break;
case 0x2:
if (read) {
- s->smb_data0 = smbus_read_byte(bus, addr, cmd);
+ ret = smbus_read_byte(bus, addr, cmd);
+ goto data8;
} else {
- smbus_write_byte(bus, addr, cmd, s->smb_data0);
+ ret = smbus_write_byte(bus, addr, cmd, s->smb_data0);
+ goto done;
}
- s->smb_stat |= STS_BYTE_DONE | STS_INTR;
break;
case 0x3:
if (read) {
- uint16_t val;
- val = smbus_read_word(bus, addr, cmd);
- s->smb_data0 = val;
- s->smb_data1 = val >> 8;
+ ret = smbus_read_word(bus, addr, cmd);
+ goto data16;
} else {
- smbus_write_word(bus, addr, cmd, (s->smb_data1 << 8) | s->smb_data0);
+ ret = smbus_write_word(bus, addr, cmd, (s->smb_data1 << 8) | s->smb_data0);
+ goto done;
}
- s->smb_stat |= STS_BYTE_DONE | STS_INTR;
break;
case 0x5:
if (read) {
- s->smb_data0 = smbus_read_block(bus, addr, cmd, s->smb_data);
+ ret = smbus_read_block(bus, addr, cmd, s->smb_data);
+ goto data8;
} else {
- smbus_write_block(bus, addr, cmd, s->smb_data, s->smb_data0);
+ ret = smbus_write_block(bus, addr, cmd, s->smb_data, s->smb_data0);
+ goto done;
}
- s->smb_stat |= STS_BYTE_DONE | STS_INTR;
break;
default:
goto error;
}
+ abort();
+
+data16:
+ if (ret < 0) {
+ goto error;
+ }
+ s->smb_data1 = ret >> 8;
+data8:
+ if (ret < 0) {
+ goto error;
+ }
+ s->smb_data0 = ret;
+done:
+ if (ret < 0) {
+ goto error;
+ }
+ s->smb_stat |= STS_BYTE_DONE | STS_INTR;
return;
- error:
+error:
s->smb_stat |= STS_DEV_ERR;
+ return;
+
}
static void smb_ioport_writeb(void *opaque, hwaddr addr, uint64_t val,
diff --git a/hw/i2c/smbus.c b/hw/i2c/smbus.c
index 3febf3c258..6e27ae8bd2 100644
--- a/hw/i2c/smbus.c
+++ b/hw/i2c/smbus.c
@@ -208,34 +208,44 @@ static int smbus_device_init(I2CSlave *i2c)
}
/* Master device commands. */
-void smbus_quick_command(I2CBus *bus, uint8_t addr, int read)
+int smbus_quick_command(I2CBus *bus, uint8_t addr, int read)
{
- i2c_start_transfer(bus, addr, read);
+ if (i2c_start_transfer(bus, addr, read)) {
+ return -1;
+ }
i2c_end_transfer(bus);
+ return 0;
}
-uint8_t smbus_receive_byte(I2CBus *bus, uint8_t addr)
+int smbus_receive_byte(I2CBus *bus, uint8_t addr)
{
uint8_t data;
- i2c_start_transfer(bus, addr, 1);
+ if (i2c_start_transfer(bus, addr, 1)) {
+ return -1;
+ }
data = i2c_recv(bus);
i2c_nack(bus);
i2c_end_transfer(bus);
return data;
}
-void smbus_send_byte(I2CBus *bus, uint8_t addr, uint8_t data)
+int smbus_send_byte(I2CBus *bus, uint8_t addr, uint8_t data)
{
- i2c_start_transfer(bus, addr, 0);
+ if (i2c_start_transfer(bus, addr, 0)) {
+ return -1;
+ }
i2c_send(bus, data);
i2c_end_transfer(bus);
+ return 0;
}
-uint8_t smbus_read_byte(I2CBus *bus, uint8_t addr, uint8_t command)
+int smbus_read_byte(I2CBus *bus, uint8_t addr, uint8_t command)
{
uint8_t data;
- i2c_start_transfer(bus, addr, 0);
+ if (i2c_start_transfer(bus, addr, 0)) {
+ return -1;
+ }
i2c_send(bus, command);
i2c_start_transfer(bus, addr, 1);
data = i2c_recv(bus);
@@ -244,18 +254,23 @@ uint8_t smbus_read_byte(I2CBus *bus, uint8_t addr, uint8_t command)
return data;
}
-void smbus_write_byte(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t data)
+int smbus_write_byte(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t data)
{
- i2c_start_transfer(bus, addr, 0);
+ if (i2c_start_transfer(bus, addr, 0)) {
+ return -1;
+ }
i2c_send(bus, command);
i2c_send(bus, data);
i2c_end_transfer(bus);
+ return 0;
}
-uint16_t smbus_read_word(I2CBus *bus, uint8_t addr, uint8_t command)
+int smbus_read_word(I2CBus *bus, uint8_t addr, uint8_t command)
{
uint16_t data;
- i2c_start_transfer(bus, addr, 0);
+ if (i2c_start_transfer(bus, addr, 0)) {
+ return -1;
+ }
i2c_send(bus, command);
i2c_start_transfer(bus, addr, 1);
data = i2c_recv(bus);
@@ -265,13 +280,16 @@ uint16_t smbus_read_word(I2CBus *bus, uint8_t addr, uint8_t command)
return data;
}
-void smbus_write_word(I2CBus *bus, uint8_t addr, uint8_t command, uint16_t data)
+int smbus_write_word(I2CBus *bus, uint8_t addr, uint8_t command, uint16_t data)
{
- i2c_start_transfer(bus, addr, 0);
+ if (i2c_start_transfer(bus, addr, 0)) {
+ return -1;
+ }
i2c_send(bus, command);
i2c_send(bus, data & 0xff);
i2c_send(bus, data >> 8);
i2c_end_transfer(bus);
+ return 0;
}
int smbus_read_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data)
@@ -279,33 +297,41 @@ int smbus_read_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data)
int len;
int i;
- i2c_start_transfer(bus, addr, 0);
+ if (i2c_start_transfer(bus, addr, 0)) {
+ return -1;
+ }
i2c_send(bus, command);
i2c_start_transfer(bus, addr, 1);
len = i2c_recv(bus);
- if (len > 32)
+ if (len > 32) {
len = 0;
- for (i = 0; i < len; i++)
+ }
+ for (i = 0; i < len; i++) {
data[i] = i2c_recv(bus);
+ }
i2c_nack(bus);
i2c_end_transfer(bus);
return len;
}
-void smbus_write_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data,
- int len)
+int smbus_write_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data,
+ int len)
{
int i;
if (len > 32)
len = 32;
- i2c_start_transfer(bus, addr, 0);
+ if (i2c_start_transfer(bus, addr, 0)) {
+ return -1;
+ }
i2c_send(bus, command);
i2c_send(bus, len);
- for (i = 0; i < len; i++)
+ for (i = 0; i < len; i++) {
i2c_send(bus, data[i]);
+ }
i2c_end_transfer(bus);
+ return 0;
}
static void smbus_device_class_init(ObjectClass *klass, void *data)
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/acpi-build.c b/hw/i386/acpi-build.c
index c98df88cd2..9fac589033 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -156,18 +156,21 @@ static void acpi_get_pm_info(AcpiPmInfo *pm)
} else {
pm->s3_disabled = false;
}
+ qobject_decref(o);
o = object_property_get_qobject(obj, ACPI_PM_PROP_S4_DISABLED, NULL);
if (o) {
pm->s4_disabled = qint_get_int(qobject_to_qint(o));
} else {
pm->s4_disabled = false;
}
+ qobject_decref(o);
o = object_property_get_qobject(obj, ACPI_PM_PROP_S4_VAL, NULL);
if (o) {
pm->s4_val = qint_get_int(qobject_to_qint(o));
} else {
pm->s4_val = false;
}
+ qobject_decref(o);
/* Fill in mandatory properties */
pm->sci_int = object_property_get_int(obj, ACPI_PM_PROP_SCI_INT, NULL);
@@ -973,6 +976,7 @@ static void build_pci_bus_end(PCIBus *bus, void *bus_state)
}
}
+ qobject_decref(bsel);
build_free_array(bus_table);
build_pci_bus_state_cleanup(child);
g_free(child);
@@ -1362,10 +1366,12 @@ static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
return false;
}
mcfg->mcfg_base = qint_get_int(qobject_to_qint(o));
+ qobject_decref(o);
o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_SIZE, NULL);
assert(o);
mcfg->mcfg_size = qint_get_int(qobject_to_qint(o));
+ qobject_decref(o);
return true;
}
@@ -1410,15 +1416,16 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
/* ACPI tables pointed to by RSDT */
acpi_add_table(table_offsets, tables->table_data);
build_fadt(tables->table_data, tables->linker, &pm, facs, dsdt);
- acpi_add_table(table_offsets, tables->table_data);
+ acpi_add_table(table_offsets, tables->table_data);
build_ssdt(tables->table_data, tables->linker, &cpu, &pm, &misc, &pci,
guest_info);
- acpi_add_table(table_offsets, tables->table_data);
- build_madt(tables->table_data, tables->linker, &cpu, guest_info);
acpi_add_table(table_offsets, tables->table_data);
+ build_madt(tables->table_data, tables->linker, &cpu, guest_info);
+
if (misc.has_hpet) {
+ acpi_add_table(table_offsets, tables->table_data);
build_hpet(tables->table_data, tables->linker);
}
if (guest_info->numa_nodes) {
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index ea72502420..eaf3e61994 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -414,6 +414,10 @@ static QEMUMachine pc_i440fx_machine_v2_0 = {
PC_I440FX_2_0_MACHINE_OPTIONS,
.name = "pc-i440fx-2.0",
.init = pc_init_pci_2_0,
+ .compat_props = (GlobalProperty[]) {
+ PC_COMPAT_2_0,
+ { /* end of list */ }
+ },
};
#define PC_I440FX_1_7_MACHINE_OPTIONS PC_I440FX_MACHINE_OPTIONS
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 3306f89b9e..9517ec653f 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -327,6 +327,10 @@ static QEMUMachine pc_q35_machine_v2_0 = {
PC_Q35_2_0_MACHINE_OPTIONS,
.name = "pc-q35-2.0",
.init = pc_q35_init_2_0,
+ .compat_props = (GlobalProperty[]) {
+ PC_Q35_COMPAT_2_0,
+ { /* end of list */ }
+ },
};
#define PC_Q35_1_7_MACHINE_OPTIONS PC_Q35_MACHINE_OPTIONS
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
index 63bb7f77c6..63bb7f77c6 100644
--- a/hw/xen/xen_apic.c
+++ b/hw/i386/xen/xen_apic.c
diff --git a/hw/xen/xen_platform.c b/hw/i386/xen/xen_platform.c
index 1d9d0e9f25..1d9d0e9f25 100644
--- a/hw/xen/xen_platform.c
+++ b/hw/i386/xen/xen_platform.c
diff --git a/hw/xen/xen_pvdevice.c b/hw/i386/xen/xen_pvdevice.c
index c2189473ba..c2189473ba 100644
--- a/hw/xen/xen_pvdevice.c
+++ b/hw/i386/xen/xen_pvdevice.c
diff --git a/hw/intc/apic.c b/hw/intc/apic.c
index 2f40cbad2d..ef19e5515c 100644
--- a/hw/intc/apic.c
+++ b/hw/intc/apic.c
@@ -675,7 +675,7 @@ static uint32_t apic_mem_readl(void *opaque, hwaddr addr)
val = s->id << 24;
break;
case 0x03: /* version */
- val = 0x11 | ((APIC_LVT_NB - 1) << 16); /* version 0x11 */
+ val = s->version | ((APIC_LVT_NB - 1) << 16);
break;
case 0x08:
apic_sync_vapic(s, SYNC_FROM_VAPIC);
diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c
index 7ecce2dcce..71376533ca 100644
--- a/hw/intc/apic_common.c
+++ b/hw/intc/apic_common.c
@@ -380,6 +380,7 @@ static const VMStateDescription vmstate_apic_common = {
static Property apic_properties_common[] = {
DEFINE_PROP_UINT8("id", APICCommonState, id, -1),
+ DEFINE_PROP_UINT8("version", APICCommonState, version, 0x14),
DEFINE_PROP_BIT("vapic", APICCommonState, vapic_control, VAPIC_ENABLE_BIT,
true),
DEFINE_PROP_END_OF_LIST(),
diff --git a/hw/intc/i8259.c b/hw/intc/i8259.c
index ec01393e4f..d0b0c52b97 100644
--- a/hw/intc/i8259.c
+++ b/hw/intc/i8259.c
@@ -265,7 +265,8 @@ static void pic_ioport_write(void *opaque, hwaddr addr64,
s->init4 = val & 1;
s->single_mode = val & 2;
if (val & 0x08) {
- hw_error("level sensitive irq not supported");
+ qemu_log_mask(LOG_UNIMP,
+ "i8259: level sensitive irq not supported\n");
}
} else if (val & 0x08) {
if (val & 0x04) {
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
index c0ab7537df..c0ab7537df 100644
--- a/hw/i386/xen_domainbuild.c
+++ b/hw/xenpv/xen_domainbuild.c
diff --git a/hw/i386/xen_domainbuild.h b/hw/xenpv/xen_domainbuild.h
index 29a91ea7b1..29a91ea7b1 100644
--- a/hw/i386/xen_domainbuild.h
+++ b/hw/xenpv/xen_domainbuild.h
diff --git a/hw/i386/xen_machine_pv.c b/hw/xenpv/xen_machine_pv.c
index 9adb57fc14..9adb57fc14 100644
--- a/hw/i386/xen_machine_pv.c
+++ b/hw/xenpv/xen_machine_pv.c