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
Peter Maydell 2022-01-18 15:06:08 +00:00
commit 8b84620715
18 changed files with 291 additions and 155 deletions

View File

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

View File

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

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);
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 */

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

View File

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

View File

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

View File

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

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_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"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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