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>staging
commit
8b84620715
|
@ -67,11 +67,15 @@ MemoryRegion):
|
|||
|
||||
You initialize a pure container with memory_region_init().
|
||||
|
||||
- alias: a subsection of another region. Aliases allow a region to be
|
||||
split apart into discontiguous regions. Examples of uses are memory banks
|
||||
used when the guest address space is smaller than the amount of RAM
|
||||
addressed, or a memory controller that splits main memory to expose a "PCI
|
||||
hole". Aliases may point to any type of region, including other aliases,
|
||||
- alias: a subsection of another region. Aliases allow a region to be
|
||||
split apart into discontiguous regions. Examples of uses are memory
|
||||
banks used when the guest address space is smaller than the amount
|
||||
of RAM addressed, or a memory controller that splits main memory to
|
||||
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.
|
||||
You initialize these with memory_region_init_alias().
|
||||
|
||||
|
|
|
@ -1091,7 +1091,7 @@ MemoryRegion *machine_consume_memdev(MachineState *machine,
|
|||
{
|
||||
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.",
|
||||
object_get_canonical_path_component(OBJECT(backend)));
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
|
@ -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);
|
||||
|
||||
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)",
|
||||
ncq_tfs->sglist.size, size);
|
||||
ncq_err(ncq_tfs);
|
||||
|
@ -1384,9 +1384,9 @@ static void ahci_pio_transfer(const IDEDMA *dma)
|
|||
const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
|
||||
|
||||
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 {
|
||||
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) {
|
||||
dma_buf_read(p, l, &s->sg, MEMTXATTRS_UNSPECIFIED);
|
||||
dma_buf_read(p, l, NULL, &s->sg, MEMTXATTRS_UNSPECIFIED);
|
||||
} 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 */
|
||||
|
|
|
@ -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) {
|
||||
const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
|
||||
uint64_t residual;
|
||||
dma_addr_t residual;
|
||||
|
||||
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 {
|
||||
residual = dma_buf_read(ptr, len, &sg->qsg, attrs);
|
||||
dma_buf_read(ptr, len, &residual, &sg->qsg, attrs);
|
||||
}
|
||||
|
||||
if (unlikely(residual)) {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# QOM interfaces must be available anytime QOM is used.
|
||||
qom_ss.add(files('fw_cfg-interface.c'))
|
||||
if have_system or have_tools
|
||||
# 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(when: 'CONFIG_CHRP_NVRAM', if_true: files('chrp_nvram.c'))
|
||||
|
|
|
@ -17,29 +17,29 @@
|
|||
#include "trace.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;
|
||||
hwaddr len = plen;
|
||||
dma_addr_t pci_len = len;
|
||||
|
||||
if (!addr) {
|
||||
rdma_error_report("addr is 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) {
|
||||
rdma_error_report("pci_dma_map fail, addr=0x%"PRIx64", len=%"PRId64,
|
||||
addr, len);
|
||||
addr, pci_len);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (len != plen) {
|
||||
rdma_pci_dma_unmap(dev, p, len);
|
||||
if (pci_len != len) {
|
||||
rdma_pci_dma_unmap(dev, p, pci_len);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
trace_rdma_pci_dma_map(addr, p, len);
|
||||
trace_rdma_pci_dma_map(addr, p, pci_len);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ typedef struct RdmaProtectedGSList {
|
|||
GSList *list;
|
||||
} 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_protected_gqueue_init(RdmaProtectedGQueue *list);
|
||||
void rdma_protected_gqueue_destroy(RdmaProtectedGQueue *list);
|
||||
|
|
|
@ -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_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"
|
||||
|
|
|
@ -750,6 +750,7 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd)
|
|||
size_t dcmd_size = sizeof(info);
|
||||
BusChild *kid;
|
||||
int num_pd_disks = 0;
|
||||
dma_addr_t residual;
|
||||
|
||||
memset(&info, 0x0, 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_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;
|
||||
}
|
||||
|
||||
|
@ -868,6 +871,7 @@ static int megasas_mfc_get_defaults(MegasasState *s, MegasasCmd *cmd)
|
|||
{
|
||||
struct mfi_defaults info;
|
||||
size_t dcmd_size = sizeof(struct mfi_defaults);
|
||||
dma_addr_t residual;
|
||||
|
||||
memset(&info, 0x0, 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.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;
|
||||
}
|
||||
|
||||
|
@ -898,6 +904,7 @@ static int megasas_dcmd_get_bios_info(MegasasState *s, MegasasCmd *cmd)
|
|||
{
|
||||
struct mfi_bios_data info;
|
||||
size_t dcmd_size = sizeof(info);
|
||||
dma_addr_t residual;
|
||||
|
||||
memset(&info, 0x0, 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -919,10 +928,13 @@ static int megasas_dcmd_get_fw_time(MegasasState *s, MegasasCmd *cmd)
|
|||
{
|
||||
uint64_t fw_time;
|
||||
size_t dcmd_size = sizeof(fw_time);
|
||||
dma_addr_t residual;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -942,6 +954,7 @@ static int megasas_event_info(MegasasState *s, MegasasCmd *cmd)
|
|||
{
|
||||
struct mfi_evt_log_state info;
|
||||
size_t dcmd_size = sizeof(info);
|
||||
dma_addr_t residual;
|
||||
|
||||
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.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;
|
||||
}
|
||||
|
||||
|
@ -979,6 +994,7 @@ static int megasas_dcmd_pd_get_list(MegasasState *s, MegasasCmd *cmd)
|
|||
size_t dcmd_size = sizeof(info);
|
||||
BusChild *kid;
|
||||
uint32_t offset, dcmd_limit, num_pd_disks = 0, max_pd_disks;
|
||||
dma_addr_t residual;
|
||||
|
||||
memset(&info, 0, dcmd_size);
|
||||
offset = 8;
|
||||
|
@ -1018,7 +1034,9 @@ static int megasas_dcmd_pd_get_list(MegasasState *s, MegasasCmd *cmd)
|
|||
info.size = cpu_to_le32(offset);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1045,7 +1063,8 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun,
|
|||
uint64_t pd_size;
|
||||
uint16_t pd_id = ((sdev->id & 0xFF) << 8) | (lun & 0xFF);
|
||||
uint8_t cmdbuf[6];
|
||||
size_t len, resid;
|
||||
size_t len;
|
||||
dma_addr_t residual;
|
||||
|
||||
if (!cmd->iov_buf) {
|
||||
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->device_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);
|
||||
cmd->iov_size = dcmd_size - resid;
|
||||
cmd->iov_size = dcmd_size - residual;
|
||||
cmd->iov_buf = NULL;
|
||||
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)
|
||||
{
|
||||
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;
|
||||
uint64_t ld_size;
|
||||
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);
|
||||
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);
|
||||
cmd->iov_size = dcmd_size - resid;
|
||||
dma_buf_read(&info, dcmd_size, &residual, &cmd->qsg,
|
||||
MEMTXATTRS_UNSPECIFIED);
|
||||
cmd->iov_size = dcmd_size - residual;
|
||||
return MFI_STAT_OK;
|
||||
}
|
||||
|
||||
|
@ -1193,7 +1216,8 @@ static int megasas_dcmd_ld_list_query(MegasasState *s, MegasasCmd *cmd)
|
|||
{
|
||||
uint16_t flags;
|
||||
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;
|
||||
BusChild *kid;
|
||||
|
||||
|
@ -1233,8 +1257,9 @@ static int megasas_dcmd_ld_list_query(MegasasState *s, MegasasCmd *cmd)
|
|||
info.size = dcmd_size;
|
||||
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);
|
||||
cmd->iov_size = dcmd_size - resid;
|
||||
dma_buf_read(&info, dcmd_size, &residual, &cmd->qsg,
|
||||
MEMTXATTRS_UNSPECIFIED);
|
||||
cmd->iov_size = dcmd_size - residual;
|
||||
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;
|
||||
size_t dcmd_size = sizeof(struct mfi_ld_info);
|
||||
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);
|
||||
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].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);
|
||||
cmd->iov_size = dcmd_size - resid;
|
||||
cmd->iov_size = dcmd_size - residual;
|
||||
cmd->iov_buf = NULL;
|
||||
return MFI_STAT_OK;
|
||||
}
|
||||
|
@ -1328,6 +1355,7 @@ static int megasas_dcmd_cfg_read(MegasasState *s, MegasasCmd *cmd)
|
|||
struct mfi_config_data *info;
|
||||
int num_pd_disks = 0, array_offset, ld_offset;
|
||||
BusChild *kid;
|
||||
dma_addr_t residual;
|
||||
|
||||
if (cmd->iov_size > 4096) {
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1410,6 +1440,7 @@ static int megasas_dcmd_get_properties(MegasasState *s, MegasasCmd *cmd)
|
|||
{
|
||||
struct mfi_ctrl_props info;
|
||||
size_t dcmd_size = sizeof(info);
|
||||
dma_addr_t residual;
|
||||
|
||||
memset(&info, 0x0, 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.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;
|
||||
}
|
||||
|
||||
|
@ -1477,7 +1510,7 @@ static int megasas_dcmd_set_properties(MegasasState *s, MegasasCmd *cmd)
|
|||
dcmd_size);
|
||||
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);
|
||||
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,
|
||||
SCSIRequest *req, size_t resid)
|
||||
SCSIRequest *req, dma_addr_t residual)
|
||||
{
|
||||
int retval = MFI_STAT_OK;
|
||||
int lun = req->lun;
|
||||
|
||||
trace_megasas_dcmd_internal_finish(cmd->index, cmd->dcmd_opcode, lun);
|
||||
cmd->iov_size -= resid;
|
||||
cmd->iov_size -= residual;
|
||||
switch (cmd->dcmd_opcode) {
|
||||
case MFI_DCMD_PD_GET_INFO:
|
||||
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;
|
||||
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) {
|
||||
return;
|
||||
|
@ -1880,7 +1913,7 @@ static void megasas_command_complete(SCSIRequest *req, size_t resid)
|
|||
/*
|
||||
* 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) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -760,7 +760,7 @@ SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
|
|||
}
|
||||
|
||||
req->cmd = cmd;
|
||||
req->resid = req->cmd.xfer;
|
||||
req->residual = req->cmd.xfer;
|
||||
|
||||
switch (buf[0]) {
|
||||
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);
|
||||
assert(req->cmd.mode != SCSI_XFER_NONE);
|
||||
if (!req->sg) {
|
||||
req->resid -= len;
|
||||
req->residual -= len;
|
||||
req->bus->info->transfer_data(req, len);
|
||||
return;
|
||||
}
|
||||
|
@ -1421,9 +1421,11 @@ void scsi_req_data(SCSIRequest *req, int len)
|
|||
|
||||
buf = scsi_req_get_buf(req);
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
|
@ -1512,7 +1514,7 @@ void scsi_req_complete(SCSIRequest *req, int status)
|
|||
|
||||
scsi_req_ref(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 */
|
||||
notifier_list_notify(&req->cancel_notifiers, req);
|
||||
|
|
|
@ -420,7 +420,7 @@ static void scsi_do_read(SCSIDiskReq *r, int ret)
|
|||
|
||||
if (r->req.sg) {
|
||||
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.sg, r->sector << BDRV_SECTOR_BITS,
|
||||
BDRV_SECTOR_SIZE,
|
||||
|
@ -580,7 +580,7 @@ static void scsi_write_data(SCSIRequest *req)
|
|||
|
||||
if (r->req.sg) {
|
||||
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.sg, r->sector << BDRV_SECTOR_BITS,
|
||||
BDRV_SECTOR_SIZE,
|
||||
|
|
|
@ -738,6 +738,7 @@ struct MemoryRegion {
|
|||
const MemoryRegionOps *ops;
|
||||
void *opaque;
|
||||
MemoryRegion *container;
|
||||
int mapped_via_alias; /* Mapped via an alias, container might be NULL */
|
||||
Int128 size;
|
||||
hwaddr addr;
|
||||
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
|
||||
* 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
|
||||
*/
|
||||
|
|
|
@ -881,6 +881,18 @@ PCI_DMA_DEFINE_LDST(q_be, q_be, 64);
|
|||
|
||||
#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,
|
||||
dma_addr_t *plen, DMADirection dir)
|
||||
{
|
||||
|
|
|
@ -30,7 +30,7 @@ struct SCSIRequest {
|
|||
int16_t status;
|
||||
int16_t host_status;
|
||||
void *hba_private;
|
||||
size_t resid;
|
||||
uint64_t residual;
|
||||
SCSICommand cmd;
|
||||
NotifierList cancel_notifiers;
|
||||
|
||||
|
@ -125,7 +125,7 @@ struct SCSIBusInfo {
|
|||
void *hba_private);
|
||||
void (*transfer_data)(SCSIRequest *req, uint32_t arg);
|
||||
void (*fail)(SCSIRequest *req);
|
||||
void (*complete)(SCSIRequest *req, size_t resid);
|
||||
void (*complete)(SCSIRequest *req, size_t residual);
|
||||
void (*cancel)(SCSIRequest *req);
|
||||
void (*change)(SCSIBus *bus, SCSIDevice *dev, SCSISense sense);
|
||||
QEMUSGList *(*get_sg_list)(SCSIRequest *req);
|
||||
|
|
|
@ -15,24 +15,11 @@
|
|||
#include "block/block.h"
|
||||
#include "block/accounting.h"
|
||||
|
||||
typedef struct ScatterGatherEntry ScatterGatherEntry;
|
||||
|
||||
typedef enum {
|
||||
DMA_DIRECTION_TO_DEVICE = 0,
|
||||
DMA_DIRECTION_FROM_DEVICE = 1,
|
||||
} 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
|
||||
* 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_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)
|
||||
{
|
||||
/*
|
||||
|
@ -288,7 +286,6 @@ void qemu_sglist_init(QEMUSGList *qsg, DeviceState *dev, int alloc_hint,
|
|||
AddressSpace *as);
|
||||
void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len);
|
||||
void qemu_sglist_destroy(QEMUSGList *qsg);
|
||||
#endif
|
||||
|
||||
typedef BlockAIOCB *DMAIOFunc(int64_t offset, QEMUIOVector *iov,
|
||||
BlockCompletionFunc *cb, void *cb_opaque,
|
||||
|
@ -304,8 +301,10 @@ BlockAIOCB *dma_blk_read(BlockBackend *blk,
|
|||
BlockAIOCB *dma_blk_write(BlockBackend *blk,
|
||||
QEMUSGList *sg, uint64_t offset, uint32_t align,
|
||||
BlockCompletionFunc *cb, void *opaque);
|
||||
uint64_t dma_buf_read(void *ptr, int32_t len, QEMUSGList *sg, MemTxAttrs attrs);
|
||||
uint64_t dma_buf_write(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);
|
||||
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,
|
||||
QEMUSGList *sg, enum BlockAcctType type);
|
||||
|
|
|
@ -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,
|
||||
MemTxAttrs attrs)
|
||||
{
|
||||
uint8_t *ptr = buf;
|
||||
uint64_t resid;
|
||||
dma_addr_t xresidual;
|
||||
int sg_cur_index;
|
||||
MemTxResult res = MEMTX_OK;
|
||||
|
||||
resid = sg->size;
|
||||
xresidual = sg->size;
|
||||
sg_cur_index = 0;
|
||||
len = MIN(len, resid);
|
||||
len = MIN(len, xresidual);
|
||||
while (len > 0) {
|
||||
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);
|
||||
ptr += xfer;
|
||||
len -= xfer;
|
||||
resid -= xfer;
|
||||
xresidual -= xfer;
|
||||
}
|
||||
|
||||
if (residp) {
|
||||
*residp = resid;
|
||||
if (residual) {
|
||||
*residual = xresidual;
|
||||
}
|
||||
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;
|
||||
|
||||
dma_buf_rw(ptr, len, &resid, sg, DMA_DIRECTION_FROM_DEVICE, attrs);
|
||||
|
||||
return resid;
|
||||
return dma_buf_rw(ptr, len, residual, sg, DMA_DIRECTION_FROM_DEVICE, attrs);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
dma_buf_rw(ptr, len, &resid, sg, DMA_DIRECTION_TO_DEVICE, attrs);
|
||||
|
||||
return resid;
|
||||
return dma_buf_rw(ptr, len, residual, sg, DMA_DIRECTION_TO_DEVICE, attrs);
|
||||
}
|
||||
|
||||
void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie,
|
||||
|
|
200
softmmu/memory.c
200
softmmu/memory.c
|
@ -1444,6 +1444,11 @@ MemTxResult memory_region_dispatch_read(MemoryRegion *mr,
|
|||
unsigned size = memop_size(op);
|
||||
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)) {
|
||||
*pval = unassigned_mem_read(mr, addr, size);
|
||||
return MEMTX_DECODE_ERROR;
|
||||
|
@ -1488,6 +1493,11 @@ MemTxResult memory_region_dispatch_write(MemoryRegion *mr,
|
|||
{
|
||||
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)) {
|
||||
unassigned_mem_write(mr, addr, data, size);
|
||||
return MEMTX_DECODE_ERROR;
|
||||
|
@ -2535,8 +2545,13 @@ static void memory_region_add_subregion_common(MemoryRegion *mr,
|
|||
hwaddr offset,
|
||||
MemoryRegion *subregion)
|
||||
{
|
||||
MemoryRegion *alias;
|
||||
|
||||
assert(!subregion->container);
|
||||
subregion->container = mr;
|
||||
for (alias = subregion->alias; alias; alias = alias->alias) {
|
||||
alias->mapped_via_alias++;
|
||||
}
|
||||
subregion->addr = offset;
|
||||
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,
|
||||
MemoryRegion *subregion)
|
||||
{
|
||||
MemoryRegion *alias;
|
||||
|
||||
memory_region_transaction_begin();
|
||||
assert(subregion->container == mr);
|
||||
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);
|
||||
memory_region_unref(subregion);
|
||||
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)
|
||||
{
|
||||
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
|
||||
|
@ -2773,6 +2794,8 @@ static VMChangeStateEntry *vmstate_change;
|
|||
|
||||
void memory_global_dirty_log_start(unsigned int flags)
|
||||
{
|
||||
unsigned int old_flags = global_dirty_tracking;
|
||||
|
||||
if (vmstate_change) {
|
||||
qemu_del_vm_change_state_handler(vmstate_change);
|
||||
vmstate_change = NULL;
|
||||
|
@ -2781,15 +2804,14 @@ void memory_global_dirty_log_start(unsigned int flags)
|
|||
assert(flags && !(flags & (~GLOBAL_DIRTY_MASK)));
|
||||
assert(!(global_dirty_tracking & flags));
|
||||
global_dirty_tracking |= flags;
|
||||
|
||||
trace_global_dirty_changed(global_dirty_tracking);
|
||||
|
||||
MEMORY_LISTENER_CALL_GLOBAL(log_global_start, Forward);
|
||||
|
||||
/* Refresh DIRTY_MEMORY_MIGRATION bit. */
|
||||
memory_region_transaction_begin();
|
||||
memory_region_update_pending = true;
|
||||
memory_region_transaction_commit();
|
||||
if (!old_flags) {
|
||||
MEMORY_LISTENER_CALL_GLOBAL(log_global_start, Forward);
|
||||
memory_region_transaction_begin();
|
||||
memory_region_update_pending = true;
|
||||
memory_region_transaction_commit();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/* Refresh DIRTY_MEMORY_MIGRATION bit. */
|
||||
memory_region_transaction_begin();
|
||||
memory_region_update_pending = true;
|
||||
memory_region_transaction_commit();
|
||||
|
||||
MEMORY_LISTENER_CALL_GLOBAL(log_global_stop, Reverse);
|
||||
if (!global_dirty_tracking) {
|
||||
memory_region_transaction_begin();
|
||||
memory_region_update_pending = true;
|
||||
memory_region_transaction_commit();
|
||||
MEMORY_LISTENER_CALL_GLOBAL(log_global_stop, Reverse);
|
||||
}
|
||||
}
|
||||
|
||||
static void memory_vm_change_state_handler(void *opaque, bool running,
|
||||
|
@ -3274,58 +3296,115 @@ static gboolean mtree_info_flatview_free(gpointer key, gpointer value,
|
|||
return true;
|
||||
}
|
||||
|
||||
void mtree_info(bool flatview, bool dispatch_tree, bool owner, bool disabled)
|
||||
static void mtree_info_flatview(bool dispatch_tree, bool owner)
|
||||
{
|
||||
struct FlatViewInfo fvi = {
|
||||
.counter = 0,
|
||||
.dispatch_tree = dispatch_tree,
|
||||
.owner = owner,
|
||||
};
|
||||
AddressSpace *as;
|
||||
FlatView *view;
|
||||
GArray *fv_address_spaces;
|
||||
GHashTable *views = g_hash_table_new(g_direct_hash, g_direct_equal);
|
||||
AccelClass *ac = ACCEL_GET_CLASS(current_accel());
|
||||
|
||||
if (ac->has_memory) {
|
||||
fvi.ac = ac;
|
||||
}
|
||||
|
||||
/* Gather all FVs in one table */
|
||||
QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
|
||||
view = address_space_get_flatview(as);
|
||||
|
||||
fv_address_spaces = g_hash_table_lookup(views, view);
|
||||
if (!fv_address_spaces) {
|
||||
fv_address_spaces = g_array_new(false, false, sizeof(as));
|
||||
g_hash_table_insert(views, view, fv_address_spaces);
|
||||
}
|
||||
|
||||
g_array_append_val(fv_address_spaces, as);
|
||||
}
|
||||
|
||||
/* Print */
|
||||
g_hash_table_foreach(views, mtree_print_flatview, &fvi);
|
||||
|
||||
/* Free */
|
||||
g_hash_table_foreach_remove(views, mtree_info_flatview_free, 0);
|
||||
g_hash_table_unref(views);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (flatview) {
|
||||
FlatView *view;
|
||||
struct FlatViewInfo fvi = {
|
||||
.counter = 0,
|
||||
.dispatch_tree = dispatch_tree,
|
||||
.owner = owner,
|
||||
};
|
||||
GArray *fv_address_spaces;
|
||||
GHashTable *views = g_hash_table_new(g_direct_hash, g_direct_equal);
|
||||
AccelClass *ac = ACCEL_GET_CLASS(current_accel());
|
||||
|
||||
if (ac->has_memory) {
|
||||
fvi.ac = ac;
|
||||
}
|
||||
|
||||
/* Gather all FVs in one table */
|
||||
QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
|
||||
view = address_space_get_flatview(as);
|
||||
|
||||
fv_address_spaces = g_hash_table_lookup(views, view);
|
||||
if (!fv_address_spaces) {
|
||||
fv_address_spaces = g_array_new(false, false, sizeof(as));
|
||||
g_hash_table_insert(views, view, fv_address_spaces);
|
||||
}
|
||||
|
||||
g_array_append_val(fv_address_spaces, as);
|
||||
}
|
||||
|
||||
/* Print */
|
||||
g_hash_table_foreach(views, mtree_print_flatview, &fvi);
|
||||
|
||||
/* Free */
|
||||
g_hash_table_foreach_remove(views, mtree_info_flatview_free, 0);
|
||||
g_hash_table_unref(views);
|
||||
|
||||
return;
|
||||
}
|
||||
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_FOREACH(as, &address_spaces, address_spaces_link) {
|
||||
qemu_printf("address-space: %s\n", as->name);
|
||||
mtree_print_mr(as->root, 1, 0, &ml_head, owner, disabled);
|
||||
qemu_printf("\n");
|
||||
/* Create hashtable, key=AS root MR, value = list of AS */
|
||||
as_same_root_mr_list = g_hash_table_lookup(views, as->root);
|
||||
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 */
|
||||
QTAILQ_FOREACH(ml, &ml_head, mrqueue) {
|
||||
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,
|
||||
Object *owner,
|
||||
const char *name,
|
||||
|
|
|
@ -11,7 +11,6 @@ stub_ss.add(files('icount.c'))
|
|||
stub_ss.add(files('dump.c'))
|
||||
stub_ss.add(files('error-printf.c'))
|
||||
stub_ss.add(files('fdset.c'))
|
||||
stub_ss.add(files('fw_cfg.c'))
|
||||
stub_ss.add(files('gdbstub.c'))
|
||||
stub_ss.add(files('get-vm-name.c'))
|
||||
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('monitor.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('qmp_memory_device.c'))
|
||||
stub_ss.add(files('qmp-command-available.c'))
|
||||
|
@ -51,6 +49,8 @@ if have_block
|
|||
stub_ss.add(files('replay-tools.c'))
|
||||
endif
|
||||
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('usb-dev-stub.c'))
|
||||
stub_ss.add(files('xen-hw-stub.c'))
|
||||
|
|
Loading…
Reference in New Issue