diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c index d095c081ccd151a4f1101889f55d2ec8d955ef31..892358214708a108b5dcb3bac2cda38b9a52dad7 100644 --- a/hw/xen/xen_pt.c +++ b/hw/xen/xen_pt.c @@ -234,7 +234,7 @@ static void xen_pt_pci_write_config(PCIDevice *d, uint32_t addr, int index = 0; XenPTRegGroup *reg_grp_entry = NULL; int rc = 0; - uint32_t read_val = 0; + uint32_t read_val = 0, wb_mask; int emul_len = 0; XenPTReg *reg_entry = NULL; uint32_t find_addr = addr; @@ -271,6 +271,9 @@ static void xen_pt_pci_write_config(PCIDevice *d, uint32_t addr, if (rc < 0) { XEN_PT_ERR(d, "pci_read_block failed. return value: %d.\n", rc); memset(&read_val, 0xff, len); + wb_mask = 0; + } else { + wb_mask = 0xFFFFFFFF >> ((4 - len) << 3); } /* pass directly to the real device for passthrough type register group */ @@ -298,6 +301,11 @@ static void xen_pt_pci_write_config(PCIDevice *d, uint32_t addr, valid_mask <<= (find_addr - real_offset) << 3; ptr_val = (uint8_t *)&val + (real_offset & 3); + if (reg->emu_mask == (0xFFFFFFFF >> ((4 - reg->size) << 3))) { + wb_mask &= ~((reg->emu_mask + >> ((find_addr - real_offset) << 3)) + << ((len - emul_len) << 3)); + } /* do emulation based on register size */ switch (reg->size) { @@ -350,10 +358,19 @@ static void xen_pt_pci_write_config(PCIDevice *d, uint32_t addr, memory_region_transaction_commit(); out: - if (!(reg && reg->no_wb)) { + for (index = 0; wb_mask; index += len) { /* unknown regs are passed through */ - rc = xen_host_pci_set_block(&s->real_device, addr, - (uint8_t *)&val, len); + while (!(wb_mask & 0xff)) { + index++; + wb_mask >>= 8; + } + len = 0; + do { + len++; + wb_mask >>= 8; + } while (wb_mask & 0xff); + rc = xen_host_pci_set_block(&s->real_device, addr + index, + (uint8_t *)&val + index, len); if (rc < 0) { XEN_PT_ERR(d, "pci_write_block failed. return value: %d.\n", rc); diff --git a/hw/xen/xen_pt.h b/hw/xen/xen_pt.h index 942dc60cc72f82e37eea03b46f50e6f15c08318a..52ceb856f9794b2471321ce544aa5dc72a721141 100644 --- a/hw/xen/xen_pt.h +++ b/hw/xen/xen_pt.h @@ -105,8 +105,6 @@ struct XenPTRegInfo { uint32_t ro_mask; /* reg emulate field mask (ON:emu, OFF:passthrough) */ uint32_t emu_mask; - /* no write back allowed */ - uint32_t no_wb; xen_pt_conf_reg_init init; /* read/write function pointer * for double_word/word/byte size */ diff --git a/hw/xen/xen_pt_config_init.c b/hw/xen/xen_pt_config_init.c index 95a51dbbb113b27f9d60d2cf3247c3acb088b511..dae05192d80b5a489f5ca820930bc23ec17162ad 100644 --- a/hw/xen/xen_pt_config_init.c +++ b/hw/xen/xen_pt_config_init.c @@ -1279,7 +1279,6 @@ static XenPTRegInfo xen_pt_emu_reg_msi[] = { .init_val = 0x00000000, .ro_mask = 0x00000003, .emu_mask = 0xFFFFFFFF, - .no_wb = 1, .init = xen_pt_common_reg_init, .u.dw.read = xen_pt_long_reg_read, .u.dw.write = xen_pt_msgaddr32_reg_write, @@ -1291,7 +1290,6 @@ static XenPTRegInfo xen_pt_emu_reg_msi[] = { .init_val = 0x00000000, .ro_mask = 0x00000000, .emu_mask = 0xFFFFFFFF, - .no_wb = 1, .init = xen_pt_msgaddr64_reg_init, .u.dw.read = xen_pt_long_reg_read, .u.dw.write = xen_pt_msgaddr64_reg_write, @@ -1303,7 +1301,6 @@ static XenPTRegInfo xen_pt_emu_reg_msi[] = { .init_val = 0x0000, .ro_mask = 0x0000, .emu_mask = 0xFFFF, - .no_wb = 1, .init = xen_pt_msgdata_reg_init, .u.w.read = xen_pt_word_reg_read, .u.w.write = xen_pt_msgdata_reg_write, @@ -1315,7 +1312,6 @@ static XenPTRegInfo xen_pt_emu_reg_msi[] = { .init_val = 0x0000, .ro_mask = 0x0000, .emu_mask = 0xFFFF, - .no_wb = 1, .init = xen_pt_msgdata_reg_init, .u.w.read = xen_pt_word_reg_read, .u.w.write = xen_pt_msgdata_reg_write,