Memory API patches

- Directly dispatch MemoryRegion alias accesses
 - Remove duplicated Address Space information in 'info mtree'
 - Cleanups around memory_region_is_mapped()
 - Fix incorrect calls of log_global_start/stop()
 - Use dma_addr_t type definition when relevant
 - Let dma_buf_read() / dma_buf_write() propagate MemTxResult
 - Clarify MemoryRegion aliases documentation
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmHmrAYACgkQ4+MsLN6t
 wN5HQQ//VAnHE3/IDJ1c3pKcpVUn14tOY45vdnlDTxLceZCmkw74dy+ua7nfjnzV
 ooazcL2/k5MqcWhf86f9PQad1cGO3hl47xvUa6WTfhWkl8MfLgNXMFsLOmYVLMl8
 /Wl7Rc9wmv4LAM+UeL7kOXIdoTyvkhoKQc1esRcXQ70SEfYQdbSNjPi4RgggmSSk
 EgN0D6U2OugpTmG87XdIRdarJSyXqq5c0NqKIa2kDsizYs3lsQlGElIYpgDX0HZP
 jb/dG1KBW2/KIbPOHENNWfMLJsHSf/aEhALJqQEzJiEsg0xCRK3E8zIUshVYbffS
 n+NezT5PPoElsLt6/LTSY5F5tGi/HSL4JE/TaviaI8c2NNyI6qrpHmD/m3RVBAId
 Ngw7bDlnIvOwwwrYOCxCxJuk/TJbXsU1CYSTrhEJ0xpzQmey97Xuxli8B+TzDQg+
 fN+uVts+8XhMLyFhSiQis7ehLLcMzgeDwkt1NDNrTQRFK/w986S0tRRKkctLYUff
 4rldjo5lPF9T8uecpY247exvqG+UnvHbehO+f/kEXoTBfJeSAl1NbmLPEKihXbKY
 O/ur4GMZ0F1FsGdZ1JHx6/xawY9TL4/0Rm2bT3NWwzTkijo+qBYWpO6FeNPHhbkr
 tWv/6aqBKclr+0QRm5plybTSF6CG5afIodsrj83hFhb2nsRK4b0=
 =hVZR
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/philmd/tags/memory-api-20220118' into staging

Memory API patches

- Directly dispatch MemoryRegion alias accesses
- Remove duplicated Address Space information in 'info mtree'
- Cleanups around memory_region_is_mapped()
- Fix incorrect calls of log_global_start/stop()
- Use dma_addr_t type definition when relevant
- Let dma_buf_read() / dma_buf_write() propagate MemTxResult
- Clarify MemoryRegion aliases documentation

# gpg: Signature made Tue 18 Jan 2022 12:01:10 GMT
# gpg:                using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE
# gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <f4bug@amsat.org>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: FAAB E75E 1291 7221 DCFD  6BB2 E3E3 2C2C DEAD C0DE

* remotes/philmd/tags/memory-api-20220118:
  docs/devel: add some clarifying text for aliases
  hw/dma: Let dma_buf_read() / dma_buf_write() propagate MemTxResult
  hw/dma: Use dma_addr_t type definition when relevant
  hw/dma: Move ScatterGatherEntry / QEMUSGList declarations around
  hw/dma: Fix format string issues using dma_addr_t
  hw/scsi: Rename SCSIRequest::resid as 'residual'
  hw/rdma/rdma_utils: Rename rdma_pci_dma_map 'len' argument
  hw/dma: Remove CONFIG_USER_ONLY check
  hw/pci: Document pci_dma_map()
  hw/pci: Restrict pci-bus stub to sysemu
  hw/nvram: Restrict fw_cfg QOM interface to sysemu and tools
  stubs: Restrict fw_cfg to system emulation
  memory: Fix incorrect calls of log_global_start/stop
  memory: Update description of memory_region_is_mapped()
  memory: Make memory_region_is_mapped() succeed when mapped via an alias
  machine: Use host_memory_backend_is_mapped() in machine_consume_memdev()
  memory: Have 'info mtree' remove duplicated Address Space information
  memory: Split mtree_info() as mtree_info_flatview() + mtree_info_as()
  memory: Directly dispatch alias accesses on origin memory region

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2022-01-18 15:06:08 +00:00
commit 8b84620715
18 changed files with 291 additions and 155 deletions

View File

@ -68,10 +68,14 @@ MemoryRegion):
You initialize a pure container with memory_region_init(). You initialize a pure container with memory_region_init().
- alias: a subsection of another region. Aliases allow a region to be - alias: a subsection of another region. Aliases allow a region to be
split apart into discontiguous regions. Examples of uses are memory banks split apart into discontiguous regions. Examples of uses are memory
used when the guest address space is smaller than the amount of RAM banks used when the guest address space is smaller than the amount
addressed, or a memory controller that splits main memory to expose a "PCI of RAM addressed, or a memory controller that splits main memory to
hole". Aliases may point to any type of region, including other aliases, expose a "PCI hole". You can also create aliases to avoid trying to
add the original region to multiple parents via
`memory_region_add_subregion`.
Aliases may point to any type of region, including other aliases,
but an alias may not point back to itself, directly or indirectly. but an alias may not point back to itself, directly or indirectly.
You initialize these with memory_region_init_alias(). You initialize these with memory_region_init_alias().

View File

@ -1091,7 +1091,7 @@ MemoryRegion *machine_consume_memdev(MachineState *machine,
{ {
MemoryRegion *ret = host_memory_backend_get_memory(backend); MemoryRegion *ret = host_memory_backend_get_memory(backend);
if (memory_region_is_mapped(ret)) { if (host_memory_backend_is_mapped(backend)) {
error_report("memory backend %s can't be used multiple times.", error_report("memory backend %s can't be used multiple times.",
object_get_canonical_path_component(OBJECT(backend))); object_get_canonical_path_component(OBJECT(backend)));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);

View File

@ -1159,7 +1159,7 @@ static void process_ncq_command(AHCIState *s, int port, const uint8_t *cmd_fis,
ahci_populate_sglist(ad, &ncq_tfs->sglist, ncq_tfs->cmdh, size, 0); ahci_populate_sglist(ad, &ncq_tfs->sglist, ncq_tfs->cmdh, size, 0);
if (ncq_tfs->sglist.size < size) { if (ncq_tfs->sglist.size < size) {
error_report("ahci: PRDT length for NCQ command (0x%zx) " error_report("ahci: PRDT length for NCQ command (0x" DMA_ADDR_FMT ") "
"is smaller than the requested size (0x%zx)", "is smaller than the requested size (0x%zx)",
ncq_tfs->sglist.size, size); ncq_tfs->sglist.size, size);
ncq_err(ncq_tfs); ncq_err(ncq_tfs);
@ -1384,9 +1384,9 @@ static void ahci_pio_transfer(const IDEDMA *dma)
const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
if (is_write) { if (is_write) {
dma_buf_write(s->data_ptr, size, &s->sg, attrs); dma_buf_write(s->data_ptr, size, NULL, &s->sg, attrs);
} else { } else {
dma_buf_read(s->data_ptr, size, &s->sg, attrs); dma_buf_read(s->data_ptr, size, NULL, &s->sg, attrs);
} }
} }
@ -1479,9 +1479,9 @@ static int ahci_dma_rw_buf(const IDEDMA *dma, bool is_write)
} }
if (is_write) { if (is_write) {
dma_buf_read(p, l, &s->sg, MEMTXATTRS_UNSPECIFIED); dma_buf_read(p, l, NULL, &s->sg, MEMTXATTRS_UNSPECIFIED);
} else { } else {
dma_buf_write(p, l, &s->sg, MEMTXATTRS_UNSPECIFIED); dma_buf_write(p, l, NULL, &s->sg, MEMTXATTRS_UNSPECIFIED);
} }
/* free sglist, update byte count */ /* free sglist, update byte count */

View File

@ -1147,12 +1147,12 @@ static uint16_t nvme_tx(NvmeCtrl *n, NvmeSg *sg, uint8_t *ptr, uint32_t len,
if (sg->flags & NVME_SG_DMA) { if (sg->flags & NVME_SG_DMA) {
const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
uint64_t residual; dma_addr_t residual;
if (dir == NVME_TX_DIRECTION_TO_DEVICE) { if (dir == NVME_TX_DIRECTION_TO_DEVICE) {
residual = dma_buf_write(ptr, len, &sg->qsg, attrs); dma_buf_write(ptr, len, &residual, &sg->qsg, attrs);
} else { } else {
residual = dma_buf_read(ptr, len, &sg->qsg, attrs); dma_buf_read(ptr, len, &residual, &sg->qsg, attrs);
} }
if (unlikely(residual)) { if (unlikely(residual)) {

View File

@ -1,5 +1,7 @@
# QOM interfaces must be available anytime QOM is used. if have_system or have_tools
qom_ss.add(files('fw_cfg-interface.c')) # QOM interfaces must be available anytime QOM is used.
qom_ss.add(files('fw_cfg-interface.c'))
endif
softmmu_ss.add(files('fw_cfg.c')) softmmu_ss.add(files('fw_cfg.c'))
softmmu_ss.add(when: 'CONFIG_CHRP_NVRAM', if_true: files('chrp_nvram.c')) softmmu_ss.add(when: 'CONFIG_CHRP_NVRAM', if_true: files('chrp_nvram.c'))

View File

@ -17,29 +17,29 @@
#include "trace.h" #include "trace.h"
#include "rdma_utils.h" #include "rdma_utils.h"
void *rdma_pci_dma_map(PCIDevice *dev, dma_addr_t addr, dma_addr_t plen) void *rdma_pci_dma_map(PCIDevice *dev, dma_addr_t addr, dma_addr_t len)
{ {
void *p; void *p;
hwaddr len = plen; dma_addr_t pci_len = len;
if (!addr) { if (!addr) {
rdma_error_report("addr is NULL"); rdma_error_report("addr is NULL");
return NULL; return NULL;
} }
p = pci_dma_map(dev, addr, &len, DMA_DIRECTION_TO_DEVICE); p = pci_dma_map(dev, addr, &pci_len, DMA_DIRECTION_TO_DEVICE);
if (!p) { if (!p) {
rdma_error_report("pci_dma_map fail, addr=0x%"PRIx64", len=%"PRId64, rdma_error_report("pci_dma_map fail, addr=0x%"PRIx64", len=%"PRId64,
addr, len); addr, pci_len);
return NULL; return NULL;
} }
if (len != plen) { if (pci_len != len) {
rdma_pci_dma_unmap(dev, p, len); rdma_pci_dma_unmap(dev, p, pci_len);
return NULL; return NULL;
} }
trace_rdma_pci_dma_map(addr, p, len); trace_rdma_pci_dma_map(addr, p, pci_len);
return p; return p;
} }

View File

@ -38,7 +38,7 @@ typedef struct RdmaProtectedGSList {
GSList *list; GSList *list;
} RdmaProtectedGSList; } RdmaProtectedGSList;
void *rdma_pci_dma_map(PCIDevice *dev, dma_addr_t addr, dma_addr_t plen); void *rdma_pci_dma_map(PCIDevice *dev, dma_addr_t addr, dma_addr_t len);
void rdma_pci_dma_unmap(PCIDevice *dev, void *buffer, dma_addr_t len); void rdma_pci_dma_unmap(PCIDevice *dev, void *buffer, dma_addr_t len);
void rdma_protected_gqueue_init(RdmaProtectedGQueue *list); void rdma_protected_gqueue_init(RdmaProtectedGQueue *list);
void rdma_protected_gqueue_destroy(RdmaProtectedGQueue *list); void rdma_protected_gqueue_destroy(RdmaProtectedGQueue *list);

View File

@ -27,5 +27,5 @@ rdma_rm_alloc_qp(uint32_t rm_qpn, uint32_t backend_qpn, uint8_t qp_type) "rm_qpn
rdma_rm_modify_qp(uint32_t qpn, uint32_t attr_mask, int qp_state, uint8_t sgid_idx) "qpn=0x%x, attr_mask=0x%x, qp_state=%d, sgid_idx=%d" rdma_rm_modify_qp(uint32_t qpn, uint32_t attr_mask, int qp_state, uint8_t sgid_idx) "qpn=0x%x, attr_mask=0x%x, qp_state=%d, sgid_idx=%d"
# rdma_utils.c # rdma_utils.c
rdma_pci_dma_map(uint64_t addr, void *vaddr, uint64_t len) "0x%"PRIx64" -> %p (len=%" PRId64")" rdma_pci_dma_map(uint64_t addr, void *vaddr, uint64_t len) "0x%"PRIx64" -> %p (len=%" PRIu64")"
rdma_pci_dma_unmap(void *vaddr) "%p" rdma_pci_dma_unmap(void *vaddr) "%p"

View File

@ -750,6 +750,7 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd)
size_t dcmd_size = sizeof(info); size_t dcmd_size = sizeof(info);
BusChild *kid; BusChild *kid;
int num_pd_disks = 0; int num_pd_disks = 0;
dma_addr_t residual;
memset(&info, 0x0, dcmd_size); memset(&info, 0x0, dcmd_size);
if (cmd->iov_size < dcmd_size) { if (cmd->iov_size < dcmd_size) {
@ -860,7 +861,9 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd)
MFI_INFO_PDMIX_SATA | MFI_INFO_PDMIX_SATA |
MFI_INFO_PDMIX_LD); MFI_INFO_PDMIX_LD);
cmd->iov_size -= dma_buf_read(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); dma_buf_read(&info, dcmd_size, &residual, &cmd->qsg,
MEMTXATTRS_UNSPECIFIED);
cmd->iov_size -= residual;
return MFI_STAT_OK; return MFI_STAT_OK;
} }
@ -868,6 +871,7 @@ static int megasas_mfc_get_defaults(MegasasState *s, MegasasCmd *cmd)
{ {
struct mfi_defaults info; struct mfi_defaults info;
size_t dcmd_size = sizeof(struct mfi_defaults); size_t dcmd_size = sizeof(struct mfi_defaults);
dma_addr_t residual;
memset(&info, 0x0, dcmd_size); memset(&info, 0x0, dcmd_size);
if (cmd->iov_size < dcmd_size) { if (cmd->iov_size < dcmd_size) {
@ -890,7 +894,9 @@ static int megasas_mfc_get_defaults(MegasasState *s, MegasasCmd *cmd)
info.disable_preboot_cli = 1; info.disable_preboot_cli = 1;
info.cluster_disable = 1; info.cluster_disable = 1;
cmd->iov_size -= dma_buf_read(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); dma_buf_read(&info, dcmd_size, &residual, &cmd->qsg,
MEMTXATTRS_UNSPECIFIED);
cmd->iov_size -= residual;
return MFI_STAT_OK; return MFI_STAT_OK;
} }
@ -898,6 +904,7 @@ static int megasas_dcmd_get_bios_info(MegasasState *s, MegasasCmd *cmd)
{ {
struct mfi_bios_data info; struct mfi_bios_data info;
size_t dcmd_size = sizeof(info); size_t dcmd_size = sizeof(info);
dma_addr_t residual;
memset(&info, 0x0, dcmd_size); memset(&info, 0x0, dcmd_size);
if (cmd->iov_size < dcmd_size) { if (cmd->iov_size < dcmd_size) {
@ -911,7 +918,9 @@ static int megasas_dcmd_get_bios_info(MegasasState *s, MegasasCmd *cmd)
info.expose_all_drives = 1; info.expose_all_drives = 1;
} }
cmd->iov_size -= dma_buf_read(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); dma_buf_read(&info, dcmd_size, &residual, &cmd->qsg,
MEMTXATTRS_UNSPECIFIED);
cmd->iov_size -= residual;
return MFI_STAT_OK; return MFI_STAT_OK;
} }
@ -919,10 +928,13 @@ static int megasas_dcmd_get_fw_time(MegasasState *s, MegasasCmd *cmd)
{ {
uint64_t fw_time; uint64_t fw_time;
size_t dcmd_size = sizeof(fw_time); size_t dcmd_size = sizeof(fw_time);
dma_addr_t residual;
fw_time = cpu_to_le64(megasas_fw_time()); fw_time = cpu_to_le64(megasas_fw_time());
cmd->iov_size -= dma_buf_read(&fw_time, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); dma_buf_read(&fw_time, dcmd_size, &residual, &cmd->qsg,
MEMTXATTRS_UNSPECIFIED);
cmd->iov_size -= residual;
return MFI_STAT_OK; return MFI_STAT_OK;
} }
@ -942,6 +954,7 @@ static int megasas_event_info(MegasasState *s, MegasasCmd *cmd)
{ {
struct mfi_evt_log_state info; struct mfi_evt_log_state info;
size_t dcmd_size = sizeof(info); size_t dcmd_size = sizeof(info);
dma_addr_t residual;
memset(&info, 0, dcmd_size); memset(&info, 0, dcmd_size);
@ -949,7 +962,9 @@ static int megasas_event_info(MegasasState *s, MegasasCmd *cmd)
info.shutdown_seq_num = cpu_to_le32(s->shutdown_event); info.shutdown_seq_num = cpu_to_le32(s->shutdown_event);
info.boot_seq_num = cpu_to_le32(s->boot_event); info.boot_seq_num = cpu_to_le32(s->boot_event);
cmd->iov_size -= dma_buf_read(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); dma_buf_read(&info, dcmd_size, &residual, &cmd->qsg,
MEMTXATTRS_UNSPECIFIED);
cmd->iov_size -= residual;
return MFI_STAT_OK; return MFI_STAT_OK;
} }
@ -979,6 +994,7 @@ static int megasas_dcmd_pd_get_list(MegasasState *s, MegasasCmd *cmd)
size_t dcmd_size = sizeof(info); size_t dcmd_size = sizeof(info);
BusChild *kid; BusChild *kid;
uint32_t offset, dcmd_limit, num_pd_disks = 0, max_pd_disks; uint32_t offset, dcmd_limit, num_pd_disks = 0, max_pd_disks;
dma_addr_t residual;
memset(&info, 0, dcmd_size); memset(&info, 0, dcmd_size);
offset = 8; offset = 8;
@ -1018,7 +1034,9 @@ static int megasas_dcmd_pd_get_list(MegasasState *s, MegasasCmd *cmd)
info.size = cpu_to_le32(offset); info.size = cpu_to_le32(offset);
info.count = cpu_to_le32(num_pd_disks); info.count = cpu_to_le32(num_pd_disks);
cmd->iov_size -= dma_buf_read(&info, offset, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); dma_buf_read(&info, offset, &residual, &cmd->qsg,
MEMTXATTRS_UNSPECIFIED);
cmd->iov_size -= residual;
return MFI_STAT_OK; return MFI_STAT_OK;
} }
@ -1045,7 +1063,8 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun,
uint64_t pd_size; uint64_t pd_size;
uint16_t pd_id = ((sdev->id & 0xFF) << 8) | (lun & 0xFF); uint16_t pd_id = ((sdev->id & 0xFF) << 8) | (lun & 0xFF);
uint8_t cmdbuf[6]; uint8_t cmdbuf[6];
size_t len, resid; size_t len;
dma_addr_t residual;
if (!cmd->iov_buf) { if (!cmd->iov_buf) {
cmd->iov_buf = g_malloc0(dcmd_size); cmd->iov_buf = g_malloc0(dcmd_size);
@ -1112,9 +1131,11 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun,
info->connected_port_bitmap = 0x1; info->connected_port_bitmap = 0x1;
info->device_speed = 1; info->device_speed = 1;
info->link_speed = 1; info->link_speed = 1;
resid = dma_buf_read(cmd->iov_buf, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); dma_buf_read(cmd->iov_buf, dcmd_size, &residual, &cmd->qsg,
MEMTXATTRS_UNSPECIFIED);
cmd->iov_size -= residual;
g_free(cmd->iov_buf); g_free(cmd->iov_buf);
cmd->iov_size = dcmd_size - resid; cmd->iov_size = dcmd_size - residual;
cmd->iov_buf = NULL; cmd->iov_buf = NULL;
return MFI_STAT_OK; return MFI_STAT_OK;
} }
@ -1149,7 +1170,8 @@ static int megasas_dcmd_pd_get_info(MegasasState *s, MegasasCmd *cmd)
static int megasas_dcmd_ld_get_list(MegasasState *s, MegasasCmd *cmd) static int megasas_dcmd_ld_get_list(MegasasState *s, MegasasCmd *cmd)
{ {
struct mfi_ld_list info; struct mfi_ld_list info;
size_t dcmd_size = sizeof(info), resid; size_t dcmd_size = sizeof(info);
dma_addr_t residual;
uint32_t num_ld_disks = 0, max_ld_disks; uint32_t num_ld_disks = 0, max_ld_disks;
uint64_t ld_size; uint64_t ld_size;
BusChild *kid; BusChild *kid;
@ -1184,8 +1206,9 @@ static int megasas_dcmd_ld_get_list(MegasasState *s, MegasasCmd *cmd)
info.ld_count = cpu_to_le32(num_ld_disks); info.ld_count = cpu_to_le32(num_ld_disks);
trace_megasas_dcmd_ld_get_list(cmd->index, num_ld_disks, max_ld_disks); trace_megasas_dcmd_ld_get_list(cmd->index, num_ld_disks, max_ld_disks);
resid = dma_buf_read(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); dma_buf_read(&info, dcmd_size, &residual, &cmd->qsg,
cmd->iov_size = dcmd_size - resid; MEMTXATTRS_UNSPECIFIED);
cmd->iov_size = dcmd_size - residual;
return MFI_STAT_OK; return MFI_STAT_OK;
} }
@ -1193,7 +1216,8 @@ static int megasas_dcmd_ld_list_query(MegasasState *s, MegasasCmd *cmd)
{ {
uint16_t flags; uint16_t flags;
struct mfi_ld_targetid_list info; struct mfi_ld_targetid_list info;
size_t dcmd_size = sizeof(info), resid; size_t dcmd_size = sizeof(info);
dma_addr_t residual;
uint32_t num_ld_disks = 0, max_ld_disks = s->fw_luns; uint32_t num_ld_disks = 0, max_ld_disks = s->fw_luns;
BusChild *kid; BusChild *kid;
@ -1233,8 +1257,9 @@ static int megasas_dcmd_ld_list_query(MegasasState *s, MegasasCmd *cmd)
info.size = dcmd_size; info.size = dcmd_size;
trace_megasas_dcmd_ld_get_list(cmd->index, num_ld_disks, max_ld_disks); trace_megasas_dcmd_ld_get_list(cmd->index, num_ld_disks, max_ld_disks);
resid = dma_buf_read(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); dma_buf_read(&info, dcmd_size, &residual, &cmd->qsg,
cmd->iov_size = dcmd_size - resid; MEMTXATTRS_UNSPECIFIED);
cmd->iov_size = dcmd_size - residual;
return MFI_STAT_OK; return MFI_STAT_OK;
} }
@ -1244,7 +1269,8 @@ static int megasas_ld_get_info_submit(SCSIDevice *sdev, int lun,
struct mfi_ld_info *info = cmd->iov_buf; struct mfi_ld_info *info = cmd->iov_buf;
size_t dcmd_size = sizeof(struct mfi_ld_info); size_t dcmd_size = sizeof(struct mfi_ld_info);
uint8_t cdb[6]; uint8_t cdb[6];
ssize_t len, resid; ssize_t len;
dma_addr_t residual;
uint16_t sdev_id = ((sdev->id & 0xFF) << 8) | (lun & 0xFF); uint16_t sdev_id = ((sdev->id & 0xFF) << 8) | (lun & 0xFF);
uint64_t ld_size; uint64_t ld_size;
@ -1283,9 +1309,10 @@ static int megasas_ld_get_info_submit(SCSIDevice *sdev, int lun,
info->ld_config.span[0].num_blocks = info->size; info->ld_config.span[0].num_blocks = info->size;
info->ld_config.span[0].array_ref = cpu_to_le16(sdev_id); info->ld_config.span[0].array_ref = cpu_to_le16(sdev_id);
resid = dma_buf_read(cmd->iov_buf, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); dma_buf_read(cmd->iov_buf, dcmd_size, &residual, &cmd->qsg,
MEMTXATTRS_UNSPECIFIED);
g_free(cmd->iov_buf); g_free(cmd->iov_buf);
cmd->iov_size = dcmd_size - resid; cmd->iov_size = dcmd_size - residual;
cmd->iov_buf = NULL; cmd->iov_buf = NULL;
return MFI_STAT_OK; return MFI_STAT_OK;
} }
@ -1328,6 +1355,7 @@ static int megasas_dcmd_cfg_read(MegasasState *s, MegasasCmd *cmd)
struct mfi_config_data *info; struct mfi_config_data *info;
int num_pd_disks = 0, array_offset, ld_offset; int num_pd_disks = 0, array_offset, ld_offset;
BusChild *kid; BusChild *kid;
dma_addr_t residual;
if (cmd->iov_size > 4096) { if (cmd->iov_size > 4096) {
return MFI_STAT_INVALID_PARAMETER; return MFI_STAT_INVALID_PARAMETER;
@ -1402,7 +1430,9 @@ static int megasas_dcmd_cfg_read(MegasasState *s, MegasasCmd *cmd)
ld_offset += sizeof(struct mfi_ld_config); ld_offset += sizeof(struct mfi_ld_config);
} }
cmd->iov_size -= dma_buf_read(data, info->size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); dma_buf_read(data, info->size, &residual, &cmd->qsg,
MEMTXATTRS_UNSPECIFIED);
cmd->iov_size -= residual;
return MFI_STAT_OK; return MFI_STAT_OK;
} }
@ -1410,6 +1440,7 @@ static int megasas_dcmd_get_properties(MegasasState *s, MegasasCmd *cmd)
{ {
struct mfi_ctrl_props info; struct mfi_ctrl_props info;
size_t dcmd_size = sizeof(info); size_t dcmd_size = sizeof(info);
dma_addr_t residual;
memset(&info, 0x0, dcmd_size); memset(&info, 0x0, dcmd_size);
if (cmd->iov_size < dcmd_size) { if (cmd->iov_size < dcmd_size) {
@ -1432,7 +1463,9 @@ static int megasas_dcmd_get_properties(MegasasState *s, MegasasCmd *cmd)
info.ecc_bucket_leak_rate = cpu_to_le16(1440); info.ecc_bucket_leak_rate = cpu_to_le16(1440);
info.expose_encl_devices = 1; info.expose_encl_devices = 1;
cmd->iov_size -= dma_buf_read(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); dma_buf_read(&info, dcmd_size, &residual, &cmd->qsg,
MEMTXATTRS_UNSPECIFIED);
cmd->iov_size -= residual;
return MFI_STAT_OK; return MFI_STAT_OK;
} }
@ -1477,7 +1510,7 @@ static int megasas_dcmd_set_properties(MegasasState *s, MegasasCmd *cmd)
dcmd_size); dcmd_size);
return MFI_STAT_INVALID_PARAMETER; return MFI_STAT_INVALID_PARAMETER;
} }
dma_buf_write(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); dma_buf_write(&info, dcmd_size, NULL, &cmd->qsg, MEMTXATTRS_UNSPECIFIED);
trace_megasas_dcmd_unsupported(cmd->index, cmd->iov_size); trace_megasas_dcmd_unsupported(cmd->index, cmd->iov_size);
return MFI_STAT_OK; return MFI_STAT_OK;
} }
@ -1617,13 +1650,13 @@ static int megasas_handle_dcmd(MegasasState *s, MegasasCmd *cmd)
} }
static int megasas_finish_internal_dcmd(MegasasCmd *cmd, static int megasas_finish_internal_dcmd(MegasasCmd *cmd,
SCSIRequest *req, size_t resid) SCSIRequest *req, dma_addr_t residual)
{ {
int retval = MFI_STAT_OK; int retval = MFI_STAT_OK;
int lun = req->lun; int lun = req->lun;
trace_megasas_dcmd_internal_finish(cmd->index, cmd->dcmd_opcode, lun); trace_megasas_dcmd_internal_finish(cmd->index, cmd->dcmd_opcode, lun);
cmd->iov_size -= resid; cmd->iov_size -= residual;
switch (cmd->dcmd_opcode) { switch (cmd->dcmd_opcode) {
case MFI_DCMD_PD_GET_INFO: case MFI_DCMD_PD_GET_INFO:
retval = megasas_pd_get_info_submit(req->dev, lun, cmd); retval = megasas_pd_get_info_submit(req->dev, lun, cmd);
@ -1865,12 +1898,12 @@ static void megasas_xfer_complete(SCSIRequest *req, uint32_t len)
} }
} }
static void megasas_command_complete(SCSIRequest *req, size_t resid) static void megasas_command_complete(SCSIRequest *req, size_t residual)
{ {
MegasasCmd *cmd = req->hba_private; MegasasCmd *cmd = req->hba_private;
uint8_t cmd_status = MFI_STAT_OK; uint8_t cmd_status = MFI_STAT_OK;
trace_megasas_command_complete(cmd->index, req->status, resid); trace_megasas_command_complete(cmd->index, req->status, residual);
if (req->io_canceled) { if (req->io_canceled) {
return; return;
@ -1880,7 +1913,7 @@ static void megasas_command_complete(SCSIRequest *req, size_t resid)
/* /*
* Internal command complete * Internal command complete
*/ */
cmd_status = megasas_finish_internal_dcmd(cmd, req, resid); cmd_status = megasas_finish_internal_dcmd(cmd, req, residual);
if (cmd_status == MFI_STAT_INVALID_STATUS) { if (cmd_status == MFI_STAT_INVALID_STATUS) {
return; return;
} }

View File

@ -760,7 +760,7 @@ SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
} }
req->cmd = cmd; req->cmd = cmd;
req->resid = req->cmd.xfer; req->residual = req->cmd.xfer;
switch (buf[0]) { switch (buf[0]) {
case INQUIRY: case INQUIRY:
@ -1408,7 +1408,7 @@ void scsi_req_data(SCSIRequest *req, int len)
trace_scsi_req_data(req->dev->id, req->lun, req->tag, len); trace_scsi_req_data(req->dev->id, req->lun, req->tag, len);
assert(req->cmd.mode != SCSI_XFER_NONE); assert(req->cmd.mode != SCSI_XFER_NONE);
if (!req->sg) { if (!req->sg) {
req->resid -= len; req->residual -= len;
req->bus->info->transfer_data(req, len); req->bus->info->transfer_data(req, len);
return; return;
} }
@ -1421,9 +1421,11 @@ void scsi_req_data(SCSIRequest *req, int len)
buf = scsi_req_get_buf(req); buf = scsi_req_get_buf(req);
if (req->cmd.mode == SCSI_XFER_FROM_DEV) { if (req->cmd.mode == SCSI_XFER_FROM_DEV) {
req->resid = dma_buf_read(buf, len, req->sg, MEMTXATTRS_UNSPECIFIED); dma_buf_read(buf, len, &req->residual, req->sg,
MEMTXATTRS_UNSPECIFIED);
} else { } else {
req->resid = dma_buf_write(buf, len, req->sg, MEMTXATTRS_UNSPECIFIED); dma_buf_write(buf, len, &req->residual, req->sg,
MEMTXATTRS_UNSPECIFIED);
} }
scsi_req_continue(req); scsi_req_continue(req);
} }
@ -1512,7 +1514,7 @@ void scsi_req_complete(SCSIRequest *req, int status)
scsi_req_ref(req); scsi_req_ref(req);
scsi_req_dequeue(req); scsi_req_dequeue(req);
req->bus->info->complete(req, req->resid); req->bus->info->complete(req, req->residual);
/* Cancelled requests might end up being completed instead of cancelled */ /* Cancelled requests might end up being completed instead of cancelled */
notifier_list_notify(&req->cancel_notifiers, req); notifier_list_notify(&req->cancel_notifiers, req);

View File

@ -420,7 +420,7 @@ static void scsi_do_read(SCSIDiskReq *r, int ret)
if (r->req.sg) { if (r->req.sg) {
dma_acct_start(s->qdev.conf.blk, &r->acct, r->req.sg, BLOCK_ACCT_READ); dma_acct_start(s->qdev.conf.blk, &r->acct, r->req.sg, BLOCK_ACCT_READ);
r->req.resid -= r->req.sg->size; r->req.residual -= r->req.sg->size;
r->req.aiocb = dma_blk_io(blk_get_aio_context(s->qdev.conf.blk), r->req.aiocb = dma_blk_io(blk_get_aio_context(s->qdev.conf.blk),
r->req.sg, r->sector << BDRV_SECTOR_BITS, r->req.sg, r->sector << BDRV_SECTOR_BITS,
BDRV_SECTOR_SIZE, BDRV_SECTOR_SIZE,
@ -580,7 +580,7 @@ static void scsi_write_data(SCSIRequest *req)
if (r->req.sg) { if (r->req.sg) {
dma_acct_start(s->qdev.conf.blk, &r->acct, r->req.sg, BLOCK_ACCT_WRITE); dma_acct_start(s->qdev.conf.blk, &r->acct, r->req.sg, BLOCK_ACCT_WRITE);
r->req.resid -= r->req.sg->size; r->req.residual -= r->req.sg->size;
r->req.aiocb = dma_blk_io(blk_get_aio_context(s->qdev.conf.blk), r->req.aiocb = dma_blk_io(blk_get_aio_context(s->qdev.conf.blk),
r->req.sg, r->sector << BDRV_SECTOR_BITS, r->req.sg, r->sector << BDRV_SECTOR_BITS,
BDRV_SECTOR_SIZE, BDRV_SECTOR_SIZE,

View File

@ -738,6 +738,7 @@ struct MemoryRegion {
const MemoryRegionOps *ops; const MemoryRegionOps *ops;
void *opaque; void *opaque;
MemoryRegion *container; MemoryRegion *container;
int mapped_via_alias; /* Mapped via an alias, container might be NULL */
Int128 size; Int128 size;
hwaddr addr; hwaddr addr;
void (*destructor)(MemoryRegion *mr); void (*destructor)(MemoryRegion *mr);
@ -2296,7 +2297,8 @@ bool memory_region_present(MemoryRegion *container, hwaddr addr);
/** /**
* memory_region_is_mapped: returns true if #MemoryRegion is mapped * memory_region_is_mapped: returns true if #MemoryRegion is mapped
* into any address space. * into another memory region, which does not necessarily imply that it is
* mapped into an address space.
* *
* @mr: a #MemoryRegion which should be checked if it's mapped * @mr: a #MemoryRegion which should be checked if it's mapped
*/ */

View File

@ -881,6 +881,18 @@ PCI_DMA_DEFINE_LDST(q_be, q_be, 64);
#undef PCI_DMA_DEFINE_LDST #undef PCI_DMA_DEFINE_LDST
/**
* pci_dma_map: Map device PCI address space range into host virtual address
* @dev: #PCIDevice to be accessed
* @addr: address within that device's address space
* @plen: pointer to length of buffer; updated on return to indicate
* if only a subset of the requested range has been mapped
* @dir: indicates the transfer direction
*
* Return: A host pointer, or %NULL if the resources needed to
* perform the mapping are exhausted (in that case *@plen
* is set to zero).
*/
static inline void *pci_dma_map(PCIDevice *dev, dma_addr_t addr, static inline void *pci_dma_map(PCIDevice *dev, dma_addr_t addr,
dma_addr_t *plen, DMADirection dir) dma_addr_t *plen, DMADirection dir)
{ {

View File

@ -30,7 +30,7 @@ struct SCSIRequest {
int16_t status; int16_t status;
int16_t host_status; int16_t host_status;
void *hba_private; void *hba_private;
size_t resid; uint64_t residual;
SCSICommand cmd; SCSICommand cmd;
NotifierList cancel_notifiers; NotifierList cancel_notifiers;
@ -125,7 +125,7 @@ struct SCSIBusInfo {
void *hba_private); void *hba_private);
void (*transfer_data)(SCSIRequest *req, uint32_t arg); void (*transfer_data)(SCSIRequest *req, uint32_t arg);
void (*fail)(SCSIRequest *req); void (*fail)(SCSIRequest *req);
void (*complete)(SCSIRequest *req, size_t resid); void (*complete)(SCSIRequest *req, size_t residual);
void (*cancel)(SCSIRequest *req); void (*cancel)(SCSIRequest *req);
void (*change)(SCSIBus *bus, SCSIDevice *dev, SCSISense sense); void (*change)(SCSIBus *bus, SCSIDevice *dev, SCSISense sense);
QEMUSGList *(*get_sg_list)(SCSIRequest *req); QEMUSGList *(*get_sg_list)(SCSIRequest *req);

View File

@ -15,24 +15,11 @@
#include "block/block.h" #include "block/block.h"
#include "block/accounting.h" #include "block/accounting.h"
typedef struct ScatterGatherEntry ScatterGatherEntry;
typedef enum { typedef enum {
DMA_DIRECTION_TO_DEVICE = 0, DMA_DIRECTION_TO_DEVICE = 0,
DMA_DIRECTION_FROM_DEVICE = 1, DMA_DIRECTION_FROM_DEVICE = 1,
} DMADirection; } DMADirection;
struct QEMUSGList {
ScatterGatherEntry *sg;
int nsg;
int nalloc;
size_t size;
DeviceState *dev;
AddressSpace *as;
};
#ifndef CONFIG_USER_ONLY
/* /*
* When an IOMMU is present, bus addresses become distinct from * When an IOMMU is present, bus addresses become distinct from
* CPU/memory physical addresses and may be a different size. Because * CPU/memory physical addresses and may be a different size. Because
@ -45,6 +32,17 @@ typedef uint64_t dma_addr_t;
#define DMA_ADDR_BITS 64 #define DMA_ADDR_BITS 64
#define DMA_ADDR_FMT "%" PRIx64 #define DMA_ADDR_FMT "%" PRIx64
typedef struct ScatterGatherEntry ScatterGatherEntry;
struct QEMUSGList {
ScatterGatherEntry *sg;
int nsg;
int nalloc;
dma_addr_t size;
DeviceState *dev;
AddressSpace *as;
};
static inline void dma_barrier(AddressSpace *as, DMADirection dir) static inline void dma_barrier(AddressSpace *as, DMADirection dir)
{ {
/* /*
@ -288,7 +286,6 @@ void qemu_sglist_init(QEMUSGList *qsg, DeviceState *dev, int alloc_hint,
AddressSpace *as); AddressSpace *as);
void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len); void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len);
void qemu_sglist_destroy(QEMUSGList *qsg); void qemu_sglist_destroy(QEMUSGList *qsg);
#endif
typedef BlockAIOCB *DMAIOFunc(int64_t offset, QEMUIOVector *iov, typedef BlockAIOCB *DMAIOFunc(int64_t offset, QEMUIOVector *iov,
BlockCompletionFunc *cb, void *cb_opaque, BlockCompletionFunc *cb, void *cb_opaque,
@ -304,8 +301,10 @@ BlockAIOCB *dma_blk_read(BlockBackend *blk,
BlockAIOCB *dma_blk_write(BlockBackend *blk, BlockAIOCB *dma_blk_write(BlockBackend *blk,
QEMUSGList *sg, uint64_t offset, uint32_t align, QEMUSGList *sg, uint64_t offset, uint32_t align,
BlockCompletionFunc *cb, void *opaque); BlockCompletionFunc *cb, void *opaque);
uint64_t dma_buf_read(void *ptr, int32_t len, QEMUSGList *sg, MemTxAttrs attrs); MemTxResult dma_buf_read(void *ptr, dma_addr_t len, dma_addr_t *residual,
uint64_t dma_buf_write(void *ptr, int32_t len, QEMUSGList *sg, MemTxAttrs attrs); QEMUSGList *sg, MemTxAttrs attrs);
MemTxResult dma_buf_write(void *ptr, dma_addr_t len, dma_addr_t *residual,
QEMUSGList *sg, MemTxAttrs attrs);
void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie, void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie,
QEMUSGList *sg, enum BlockAcctType type); QEMUSGList *sg, enum BlockAcctType type);

View File

@ -294,49 +294,43 @@ BlockAIOCB *dma_blk_write(BlockBackend *blk,
} }
static MemTxResult dma_buf_rw(void *buf, int32_t len, uint64_t *residp, static MemTxResult dma_buf_rw(void *buf, dma_addr_t len, dma_addr_t *residual,
QEMUSGList *sg, DMADirection dir, QEMUSGList *sg, DMADirection dir,
MemTxAttrs attrs) MemTxAttrs attrs)
{ {
uint8_t *ptr = buf; uint8_t *ptr = buf;
uint64_t resid; dma_addr_t xresidual;
int sg_cur_index; int sg_cur_index;
MemTxResult res = MEMTX_OK; MemTxResult res = MEMTX_OK;
resid = sg->size; xresidual = sg->size;
sg_cur_index = 0; sg_cur_index = 0;
len = MIN(len, resid); len = MIN(len, xresidual);
while (len > 0) { while (len > 0) {
ScatterGatherEntry entry = sg->sg[sg_cur_index++]; ScatterGatherEntry entry = sg->sg[sg_cur_index++];
int32_t xfer = MIN(len, entry.len); dma_addr_t xfer = MIN(len, entry.len);
res |= dma_memory_rw(sg->as, entry.base, ptr, xfer, dir, attrs); res |= dma_memory_rw(sg->as, entry.base, ptr, xfer, dir, attrs);
ptr += xfer; ptr += xfer;
len -= xfer; len -= xfer;
resid -= xfer; xresidual -= xfer;
} }
if (residp) { if (residual) {
*residp = resid; *residual = xresidual;
} }
return res; return res;
} }
uint64_t dma_buf_read(void *ptr, int32_t len, QEMUSGList *sg, MemTxAttrs attrs) MemTxResult dma_buf_read(void *ptr, dma_addr_t len, dma_addr_t *residual,
QEMUSGList *sg, MemTxAttrs attrs)
{ {
uint64_t resid; return dma_buf_rw(ptr, len, residual, sg, DMA_DIRECTION_FROM_DEVICE, attrs);
dma_buf_rw(ptr, len, &resid, sg, DMA_DIRECTION_FROM_DEVICE, attrs);
return resid;
} }
uint64_t dma_buf_write(void *ptr, int32_t len, QEMUSGList *sg, MemTxAttrs attrs) MemTxResult dma_buf_write(void *ptr, dma_addr_t len, dma_addr_t *residual,
QEMUSGList *sg, MemTxAttrs attrs)
{ {
uint64_t resid; return dma_buf_rw(ptr, len, residual, sg, DMA_DIRECTION_TO_DEVICE, attrs);
dma_buf_rw(ptr, len, &resid, sg, DMA_DIRECTION_TO_DEVICE, attrs);
return resid;
} }
void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie, void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie,

View File

@ -1444,6 +1444,11 @@ MemTxResult memory_region_dispatch_read(MemoryRegion *mr,
unsigned size = memop_size(op); unsigned size = memop_size(op);
MemTxResult r; MemTxResult r;
if (mr->alias) {
return memory_region_dispatch_read(mr->alias,
mr->alias_offset + addr,
pval, op, attrs);
}
if (!memory_region_access_valid(mr, addr, size, false, attrs)) { if (!memory_region_access_valid(mr, addr, size, false, attrs)) {
*pval = unassigned_mem_read(mr, addr, size); *pval = unassigned_mem_read(mr, addr, size);
return MEMTX_DECODE_ERROR; return MEMTX_DECODE_ERROR;
@ -1488,6 +1493,11 @@ MemTxResult memory_region_dispatch_write(MemoryRegion *mr,
{ {
unsigned size = memop_size(op); unsigned size = memop_size(op);
if (mr->alias) {
return memory_region_dispatch_write(mr->alias,
mr->alias_offset + addr,
data, op, attrs);
}
if (!memory_region_access_valid(mr, addr, size, true, attrs)) { if (!memory_region_access_valid(mr, addr, size, true, attrs)) {
unassigned_mem_write(mr, addr, data, size); unassigned_mem_write(mr, addr, data, size);
return MEMTX_DECODE_ERROR; return MEMTX_DECODE_ERROR;
@ -2535,8 +2545,13 @@ static void memory_region_add_subregion_common(MemoryRegion *mr,
hwaddr offset, hwaddr offset,
MemoryRegion *subregion) MemoryRegion *subregion)
{ {
MemoryRegion *alias;
assert(!subregion->container); assert(!subregion->container);
subregion->container = mr; subregion->container = mr;
for (alias = subregion->alias; alias; alias = alias->alias) {
alias->mapped_via_alias++;
}
subregion->addr = offset; subregion->addr = offset;
memory_region_update_container_subregions(subregion); memory_region_update_container_subregions(subregion);
} }
@ -2561,9 +2576,15 @@ void memory_region_add_subregion_overlap(MemoryRegion *mr,
void memory_region_del_subregion(MemoryRegion *mr, void memory_region_del_subregion(MemoryRegion *mr,
MemoryRegion *subregion) MemoryRegion *subregion)
{ {
MemoryRegion *alias;
memory_region_transaction_begin(); memory_region_transaction_begin();
assert(subregion->container == mr); assert(subregion->container == mr);
subregion->container = NULL; subregion->container = NULL;
for (alias = subregion->alias; alias; alias = alias->alias) {
alias->mapped_via_alias--;
assert(alias->mapped_via_alias >= 0);
}
QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link); QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link);
memory_region_unref(subregion); memory_region_unref(subregion);
memory_region_update_pending |= mr->enabled && subregion->enabled; memory_region_update_pending |= mr->enabled && subregion->enabled;
@ -2660,7 +2681,7 @@ static FlatRange *flatview_lookup(FlatView *view, AddrRange addr)
bool memory_region_is_mapped(MemoryRegion *mr) bool memory_region_is_mapped(MemoryRegion *mr)
{ {
return mr->container ? true : false; return !!mr->container || mr->mapped_via_alias;
} }
/* Same as memory_region_find, but it does not add a reference to the /* Same as memory_region_find, but it does not add a reference to the
@ -2773,6 +2794,8 @@ static VMChangeStateEntry *vmstate_change;
void memory_global_dirty_log_start(unsigned int flags) void memory_global_dirty_log_start(unsigned int flags)
{ {
unsigned int old_flags = global_dirty_tracking;
if (vmstate_change) { if (vmstate_change) {
qemu_del_vm_change_state_handler(vmstate_change); qemu_del_vm_change_state_handler(vmstate_change);
vmstate_change = NULL; vmstate_change = NULL;
@ -2781,15 +2804,14 @@ void memory_global_dirty_log_start(unsigned int flags)
assert(flags && !(flags & (~GLOBAL_DIRTY_MASK))); assert(flags && !(flags & (~GLOBAL_DIRTY_MASK)));
assert(!(global_dirty_tracking & flags)); assert(!(global_dirty_tracking & flags));
global_dirty_tracking |= flags; global_dirty_tracking |= flags;
trace_global_dirty_changed(global_dirty_tracking); trace_global_dirty_changed(global_dirty_tracking);
if (!old_flags) {
MEMORY_LISTENER_CALL_GLOBAL(log_global_start, Forward); MEMORY_LISTENER_CALL_GLOBAL(log_global_start, Forward);
/* Refresh DIRTY_MEMORY_MIGRATION bit. */
memory_region_transaction_begin(); memory_region_transaction_begin();
memory_region_update_pending = true; memory_region_update_pending = true;
memory_region_transaction_commit(); memory_region_transaction_commit();
}
} }
static void memory_global_dirty_log_do_stop(unsigned int flags) static void memory_global_dirty_log_do_stop(unsigned int flags)
@ -2800,12 +2822,12 @@ static void memory_global_dirty_log_do_stop(unsigned int flags)
trace_global_dirty_changed(global_dirty_tracking); trace_global_dirty_changed(global_dirty_tracking);
/* Refresh DIRTY_MEMORY_MIGRATION bit. */ if (!global_dirty_tracking) {
memory_region_transaction_begin(); memory_region_transaction_begin();
memory_region_update_pending = true; memory_region_update_pending = true;
memory_region_transaction_commit(); memory_region_transaction_commit();
MEMORY_LISTENER_CALL_GLOBAL(log_global_stop, Reverse); MEMORY_LISTENER_CALL_GLOBAL(log_global_stop, Reverse);
}
} }
static void memory_vm_change_state_handler(void *opaque, bool running, static void memory_vm_change_state_handler(void *opaque, bool running,
@ -3274,19 +3296,15 @@ static gboolean mtree_info_flatview_free(gpointer key, gpointer value,
return true; return true;
} }
void mtree_info(bool flatview, bool dispatch_tree, bool owner, bool disabled) static void mtree_info_flatview(bool dispatch_tree, bool owner)
{ {
MemoryRegionListHead ml_head;
MemoryRegionList *ml, *ml2;
AddressSpace *as;
if (flatview) {
FlatView *view;
struct FlatViewInfo fvi = { struct FlatViewInfo fvi = {
.counter = 0, .counter = 0,
.dispatch_tree = dispatch_tree, .dispatch_tree = dispatch_tree,
.owner = owner, .owner = owner,
}; };
AddressSpace *as;
FlatView *view;
GArray *fv_address_spaces; GArray *fv_address_spaces;
GHashTable *views = g_hash_table_new(g_direct_hash, g_direct_equal); GHashTable *views = g_hash_table_new(g_direct_hash, g_direct_equal);
AccelClass *ac = ACCEL_GET_CLASS(current_accel()); AccelClass *ac = ACCEL_GET_CLASS(current_accel());
@ -3314,18 +3332,79 @@ void mtree_info(bool flatview, bool dispatch_tree, bool owner, bool disabled)
/* Free */ /* Free */
g_hash_table_foreach_remove(views, mtree_info_flatview_free, 0); g_hash_table_foreach_remove(views, mtree_info_flatview_free, 0);
g_hash_table_unref(views); g_hash_table_unref(views);
}
return; struct AddressSpaceInfo {
} MemoryRegionListHead *ml_head;
bool owner;
bool disabled;
};
/* Returns negative value if a < b; zero if a = b; positive value if a > b. */
static gint address_space_compare_name(gconstpointer a, gconstpointer b)
{
const AddressSpace *as_a = a;
const AddressSpace *as_b = b;
return g_strcmp0(as_a->name, as_b->name);
}
static void mtree_print_as_name(gpointer data, gpointer user_data)
{
AddressSpace *as = data;
qemu_printf("address-space: %s\n", as->name);
}
static void mtree_print_as(gpointer key, gpointer value, gpointer user_data)
{
MemoryRegion *mr = key;
GSList *as_same_root_mr_list = value;
struct AddressSpaceInfo *asi = user_data;
g_slist_foreach(as_same_root_mr_list, mtree_print_as_name, NULL);
mtree_print_mr(mr, 1, 0, asi->ml_head, asi->owner, asi->disabled);
qemu_printf("\n");
}
static gboolean mtree_info_as_free(gpointer key, gpointer value,
gpointer user_data)
{
GSList *as_same_root_mr_list = value;
g_slist_free(as_same_root_mr_list);
return true;
}
static void mtree_info_as(bool dispatch_tree, bool owner, bool disabled)
{
MemoryRegionListHead ml_head;
MemoryRegionList *ml, *ml2;
AddressSpace *as;
GHashTable *views = g_hash_table_new(g_direct_hash, g_direct_equal);
GSList *as_same_root_mr_list;
struct AddressSpaceInfo asi = {
.ml_head = &ml_head,
.owner = owner,
.disabled = disabled,
};
QTAILQ_INIT(&ml_head); QTAILQ_INIT(&ml_head);
QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
qemu_printf("address-space: %s\n", as->name); /* Create hashtable, key=AS root MR, value = list of AS */
mtree_print_mr(as->root, 1, 0, &ml_head, owner, disabled); as_same_root_mr_list = g_hash_table_lookup(views, as->root);
qemu_printf("\n"); as_same_root_mr_list = g_slist_insert_sorted(as_same_root_mr_list, as,
address_space_compare_name);
g_hash_table_insert(views, as->root, as_same_root_mr_list);
} }
/* print address spaces */
g_hash_table_foreach(views, mtree_print_as, &asi);
g_hash_table_foreach_remove(views, mtree_info_as_free, 0);
g_hash_table_unref(views);
/* print aliased regions */ /* print aliased regions */
QTAILQ_FOREACH(ml, &ml_head, mrqueue) { QTAILQ_FOREACH(ml, &ml_head, mrqueue) {
qemu_printf("memory-region: %s\n", memory_region_name(ml->mr)); qemu_printf("memory-region: %s\n", memory_region_name(ml->mr));
@ -3338,6 +3417,15 @@ void mtree_info(bool flatview, bool dispatch_tree, bool owner, bool disabled)
} }
} }
void mtree_info(bool flatview, bool dispatch_tree, bool owner, bool disabled)
{
if (flatview) {
mtree_info_flatview(dispatch_tree, owner);
} else {
mtree_info_as(dispatch_tree, owner, disabled);
}
}
void memory_region_init_ram(MemoryRegion *mr, void memory_region_init_ram(MemoryRegion *mr,
Object *owner, Object *owner,
const char *name, const char *name,

View File

@ -11,7 +11,6 @@ stub_ss.add(files('icount.c'))
stub_ss.add(files('dump.c')) stub_ss.add(files('dump.c'))
stub_ss.add(files('error-printf.c')) stub_ss.add(files('error-printf.c'))
stub_ss.add(files('fdset.c')) stub_ss.add(files('fdset.c'))
stub_ss.add(files('fw_cfg.c'))
stub_ss.add(files('gdbstub.c')) stub_ss.add(files('gdbstub.c'))
stub_ss.add(files('get-vm-name.c')) stub_ss.add(files('get-vm-name.c'))
if linux_io_uring.found() if linux_io_uring.found()
@ -27,7 +26,6 @@ stub_ss.add(files('migr-blocker.c'))
stub_ss.add(files('module-opts.c')) stub_ss.add(files('module-opts.c'))
stub_ss.add(files('monitor.c')) stub_ss.add(files('monitor.c'))
stub_ss.add(files('monitor-core.c')) stub_ss.add(files('monitor-core.c'))
stub_ss.add(files('pci-bus.c'))
stub_ss.add(files('qemu-timer-notify-cb.c')) stub_ss.add(files('qemu-timer-notify-cb.c'))
stub_ss.add(files('qmp_memory_device.c')) stub_ss.add(files('qmp_memory_device.c'))
stub_ss.add(files('qmp-command-available.c')) stub_ss.add(files('qmp-command-available.c'))
@ -51,6 +49,8 @@ if have_block
stub_ss.add(files('replay-tools.c')) stub_ss.add(files('replay-tools.c'))
endif endif
if have_system if have_system
stub_ss.add(files('fw_cfg.c'))
stub_ss.add(files('pci-bus.c'))
stub_ss.add(files('semihost.c')) stub_ss.add(files('semihost.c'))
stub_ss.add(files('usb-dev-stub.c')) stub_ss.add(files('usb-dev-stub.c'))
stub_ss.add(files('xen-hw-stub.c')) stub_ss.add(files('xen-hw-stub.c'))