diff options
author | Peter Maydell | 2016-06-14 10:30:05 +0200 |
---|---|---|
committer | Peter Maydell | 2016-06-14 10:30:05 +0200 |
commit | a28aae041aa76a779df6467a7fe68b9e8a8b2c0a (patch) | |
tree | 4b5ff0e7a997bae3b58ef16f52c57faf49bdf50c /hw | |
parent | Merge remote-tracking branch 'remotes/kraxel/tags/pull-usb-20160613-1' into s... (diff) | |
parent | spapr: Ensure all LMBs are represented in ibm,dynamic-memory (diff) | |
download | qemu-a28aae041aa76a779df6467a7fe68b9e8a8b2c0a.tar.gz qemu-a28aae041aa76a779df6467a7fe68b9e8a8b2c0a.tar.xz qemu-a28aae041aa76a779df6467a7fe68b9e8a8b2c0a.zip |
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.7-20160614' into staging
ppc patch queue for 2016-06-14
Latest patch queue for ppc.
* Allow qemu to support a generic architecture 2.07 (POWER8-era)
compatibility mode. This is useful for guests which are POWER8
aware, but don't know about the specific POWER8 variant that
qemu (and/or KVM) is emulating. (Thomas Huth)
* Fix a bug where macio wasn't removing DMA mappings (Mark Cave-Ayland)
* Add a workaround for Linux guest's miscalculation of maximum
memory address (including hotplugged memory), which could break
when hotplug memory was combined with VFIO. The previous
approach was technically correct by spec, but differed from
PowerVM's behaviour enough to trip a guest kernel bug. This
works around the bug, while remaining correct-to-spec. (Bharata Rao)
# gpg: Signature made Tue 14 Jun 2016 06:53:58 BST
# gpg: using RSA key 0x6C38CACA20D9B392
# gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>"
# gpg: aka "David Gibson (Red Hat) <dgibson@redhat.com>"
# gpg: aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>"
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg: It is not certain that the signature belongs to the owner.
# Primary key fingerprint: 75F4 6586 AE61 A66C C44E 87DC 6C38 CACA 20D9 B392
* remotes/dgibson/tags/ppc-for-2.7-20160614:
spapr: Ensure all LMBs are represented in ibm,dynamic-memory
macio: call dma_memory_unmap() at the end of each DMA transfer
Add PowerPC AT_HWCAP2 definitions
ppc: Add PowerISA 2.07 compatibility mode
ppc: Improve PCR bit selection in ppc_set_compat()
ppc: Provide function to get CPU class of the host CPU
ppc: Split pcr_mask settings into supported bits and the register mask
ppc/spapr: Refactor h_client_architecture_support() CPU parsing code
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/ide/macio.c | 46 | ||||
-rw-r--r-- | hw/ppc/spapr.c | 57 | ||||
-rw-r--r-- | hw/ppc/spapr_hcall.c | 63 |
3 files changed, 101 insertions, 65 deletions
diff --git a/hw/ide/macio.c b/hw/ide/macio.c index 78c10a0406..fa57352fc8 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -66,8 +66,7 @@ static void pmac_dma_read(BlockBackend *blk, DBDMA_io *io = opaque; MACIOIDEState *m = io->opaque; IDEState *s = idebus_active_if(&m->bus); - dma_addr_t dma_addr, dma_len; - void *mem; + dma_addr_t dma_addr; int64_t sector_num; int nsector; uint64_t align = BDRV_SECTOR_SIZE; @@ -84,9 +83,10 @@ static void pmac_dma_read(BlockBackend *blk, sector_num, nsector); dma_addr = io->addr; - dma_len = io->len; - mem = dma_memory_map(&address_space_memory, dma_addr, &dma_len, - DMA_DIRECTION_FROM_DEVICE); + io->dir = DMA_DIRECTION_FROM_DEVICE; + io->dma_len = io->len; + io->dma_mem = dma_memory_map(&address_space_memory, dma_addr, &io->dma_len, + io->dir); if (offset & (align - 1)) { head_bytes = offset & (align - 1); @@ -100,7 +100,7 @@ static void pmac_dma_read(BlockBackend *blk, offset = offset & ~(align - 1); } - qemu_iovec_add(&io->iov, mem, io->len); + qemu_iovec_add(&io->iov, io->dma_mem, io->len); if ((offset + bytes) & (align - 1)) { tail_bytes = (offset + bytes) & (align - 1); @@ -130,8 +130,7 @@ static void pmac_dma_write(BlockBackend *blk, DBDMA_io *io = opaque; MACIOIDEState *m = io->opaque; IDEState *s = idebus_active_if(&m->bus); - dma_addr_t dma_addr, dma_len; - void *mem; + dma_addr_t dma_addr; int64_t sector_num; int nsector; uint64_t align = BDRV_SECTOR_SIZE; @@ -149,9 +148,10 @@ static void pmac_dma_write(BlockBackend *blk, sector_num, nsector); dma_addr = io->addr; - dma_len = io->len; - mem = dma_memory_map(&address_space_memory, dma_addr, &dma_len, - DMA_DIRECTION_TO_DEVICE); + io->dir = DMA_DIRECTION_TO_DEVICE; + io->dma_len = io->len; + io->dma_mem = dma_memory_map(&address_space_memory, dma_addr, &io->dma_len, + io->dir); if (offset & (align - 1)) { head_bytes = offset & (align - 1); @@ -163,7 +163,7 @@ static void pmac_dma_write(BlockBackend *blk, blk_pread(s->blk, (sector_num << 9), &io->head_remainder, align); qemu_iovec_add(&io->iov, &io->head_remainder, head_bytes); - qemu_iovec_add(&io->iov, mem, io->len); + qemu_iovec_add(&io->iov, io->dma_mem, io->len); bytes += offset & (align - 1); offset = offset & ~(align - 1); @@ -181,7 +181,7 @@ static void pmac_dma_write(BlockBackend *blk, blk_pread(s->blk, (sector_num << 9), &io->tail_remainder, align); if (!unaligned_head) { - qemu_iovec_add(&io->iov, mem, io->len); + qemu_iovec_add(&io->iov, io->dma_mem, io->len); } qemu_iovec_add(&io->iov, &io->tail_remainder + tail_bytes, @@ -193,7 +193,7 @@ static void pmac_dma_write(BlockBackend *blk, } if (!unaligned_head && !unaligned_tail) { - qemu_iovec_add(&io->iov, mem, io->len); + qemu_iovec_add(&io->iov, io->dma_mem, io->len); } s->io_buffer_size -= io->len; @@ -214,18 +214,18 @@ static void pmac_dma_trim(BlockBackend *blk, DBDMA_io *io = opaque; MACIOIDEState *m = io->opaque; IDEState *s = idebus_active_if(&m->bus); - dma_addr_t dma_addr, dma_len; - void *mem; + dma_addr_t dma_addr; qemu_iovec_destroy(&io->iov); qemu_iovec_init(&io->iov, io->len / MACIO_PAGE_SIZE + 1); dma_addr = io->addr; - dma_len = io->len; - mem = dma_memory_map(&address_space_memory, dma_addr, &dma_len, - DMA_DIRECTION_TO_DEVICE); + io->dir = DMA_DIRECTION_TO_DEVICE; + io->dma_len = io->len; + io->dma_mem = dma_memory_map(&address_space_memory, dma_addr, &io->dma_len, + io->dir); - qemu_iovec_add(&io->iov, mem, io->len); + qemu_iovec_add(&io->iov, io->dma_mem, io->len); s->io_buffer_size -= io->len; s->io_buffer_index += io->len; io->len = 0; @@ -285,6 +285,9 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret) return; done: + dma_memory_unmap(&address_space_memory, io->dma_mem, io->dma_len, + io->dir, io->dma_len); + if (ret < 0) { block_acct_failed(blk_get_stats(s->blk), &s->acct); } else { @@ -351,6 +354,9 @@ static void pmac_ide_transfer_cb(void *opaque, int ret) return; done: + dma_memory_unmap(&address_space_memory, io->dma_mem, io->dma_len, + io->dir, io->dma_len); + if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) { if (ret < 0) { block_acct_failed(blk_get_stats(s->blk), &s->acct); diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 0636642341..9a4a803b17 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -762,14 +762,17 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt) int ret, i, offset; uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; uint32_t prop_lmb_size[] = {0, cpu_to_be32(lmb_size)}; - uint32_t nr_lmbs = (machine->maxram_size - machine->ram_size)/lmb_size; + uint32_t hotplug_lmb_start = spapr->hotplug_memory.base / lmb_size; + uint32_t nr_lmbs = (spapr->hotplug_memory.base + + memory_region_size(&spapr->hotplug_memory.mr)) / + lmb_size; uint32_t *int_buf, *cur_index, buf_len; int nr_nodes = nb_numa_nodes ? nb_numa_nodes : 1; /* - * Don't create the node if there are no DR LMBs. + * Don't create the node if there is no hotpluggable memory */ - if (!nr_lmbs) { + if (machine->ram_size == machine->maxram_size) { return 0; } @@ -803,26 +806,40 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt) int_buf[0] = cpu_to_be32(nr_lmbs); cur_index++; for (i = 0; i < nr_lmbs; i++) { - sPAPRDRConnector *drc; - sPAPRDRConnectorClass *drck; - uint64_t addr = i * lmb_size + spapr->hotplug_memory.base;; + uint64_t addr = i * lmb_size; uint32_t *dynamic_memory = cur_index; - drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, - addr/lmb_size); - g_assert(drc); - drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - - dynamic_memory[0] = cpu_to_be32(addr >> 32); - dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); - dynamic_memory[2] = cpu_to_be32(drck->get_index(drc)); - dynamic_memory[3] = cpu_to_be32(0); /* reserved */ - dynamic_memory[4] = cpu_to_be32(numa_get_node(addr, NULL)); - if (addr < machine->ram_size || - memory_region_present(get_system_memory(), addr)) { - dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_ASSIGNED); + if (i >= hotplug_lmb_start) { + sPAPRDRConnector *drc; + sPAPRDRConnectorClass *drck; + + drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, i); + g_assert(drc); + drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); + + dynamic_memory[0] = cpu_to_be32(addr >> 32); + dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); + dynamic_memory[2] = cpu_to_be32(drck->get_index(drc)); + dynamic_memory[3] = cpu_to_be32(0); /* reserved */ + dynamic_memory[4] = cpu_to_be32(numa_get_node(addr, NULL)); + if (memory_region_present(get_system_memory(), addr)) { + dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_ASSIGNED); + } else { + dynamic_memory[5] = cpu_to_be32(0); + } } else { - dynamic_memory[5] = cpu_to_be32(0); + /* + * LMB information for RMA, boot time RAM and gap b/n RAM and + * hotplug memory region -- all these are marked as reserved + * and as having no valid DRC. + */ + dynamic_memory[0] = cpu_to_be32(addr >> 32); + dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); + dynamic_memory[2] = cpu_to_be32(0); + dynamic_memory[3] = cpu_to_be32(0); /* reserved */ + dynamic_memory[4] = cpu_to_be32(-1); + dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_RESERVED | + SPAPR_LMB_FLAGS_DRC_INVALID); } cur_index += SPAPR_DR_LMB_LIST_ENTRY_SIZE; diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 9a3f4ecc1e..2ba5cbdb19 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -922,6 +922,41 @@ static void do_set_compat(void *arg) ((cpuver) == CPU_POWERPC_LOGICAL_2_06_PLUS) ? 2061 : \ ((cpuver) == CPU_POWERPC_LOGICAL_2_07) ? 2070 : 0) +static void cas_handle_compat_cpu(PowerPCCPUClass *pcc, uint32_t pvr, + unsigned max_lvl, unsigned *compat_lvl, + unsigned *cpu_version) +{ + unsigned lvl = get_compat_level(pvr); + bool is205, is206, is207; + + if (!lvl) { + return; + } + + /* If it is a logical PVR, try to determine the highest level */ + is205 = (pcc->pcr_supported & PCR_COMPAT_2_05) && + (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_05)); + is206 = (pcc->pcr_supported & PCR_COMPAT_2_06) && + ((lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_06)) || + (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_06_PLUS))); + is207 = (pcc->pcr_supported & PCR_COMPAT_2_07) && + (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_07)); + + if (is205 || is206 || is207) { + if (!max_lvl) { + /* User did not set the level, choose the highest */ + if (*compat_lvl <= lvl) { + *compat_lvl = lvl; + *cpu_version = pvr; + } + } else if (max_lvl >= lvl) { + /* User chose the level, don't set higher than this */ + *compat_lvl = lvl; + *cpu_version = pvr; + } + } +} + #define OV5_DRCONF_MEMORY 0x20 static target_ulong h_client_architecture_support(PowerPCCPU *cpu_, @@ -931,7 +966,7 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu_, { target_ulong list = ppc64_phys_to_real(args[0]); target_ulong ov_table, ov5; - PowerPCCPUClass *pcc_ = POWERPC_CPU_GET_CLASS(cpu_); + PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu_); CPUState *cs; bool cpu_match = false, cpu_update = true, memory_update = false; unsigned old_cpu_version = cpu_->cpu_version; @@ -958,29 +993,7 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu_, cpu_match = true; cpu_version = cpu_->cpu_version; } else if (!cpu_match) { - /* If it is a logical PVR, try to determine the highest level */ - unsigned lvl = get_compat_level(pvr); - if (lvl) { - bool is205 = (pcc_->pcr_mask & PCR_COMPAT_2_05) && - (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_05)); - bool is206 = (pcc_->pcr_mask & PCR_COMPAT_2_06) && - ((lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_06)) || - (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_06_PLUS))); - - if (is205 || is206) { - if (!max_lvl) { - /* User did not set the level, choose the highest */ - if (compat_lvl <= lvl) { - compat_lvl = lvl; - cpu_version = pvr; - } - } else if (max_lvl >= lvl) { - /* User chose the level, don't set higher than this */ - compat_lvl = lvl; - cpu_version = pvr; - } - } - } + cas_handle_compat_cpu(pcc, pvr, max_lvl, &compat_lvl, &cpu_version); } /* Terminator record */ if (~pvr_mask & pvr) { @@ -990,7 +1003,7 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu_, /* Parsing finished */ trace_spapr_cas_pvr(cpu_->cpu_version, cpu_match, - cpu_version, pcc_->pcr_mask); + cpu_version, pcc->pcr_mask); /* Update CPUs */ if (old_cpu_version != cpu_version) { |