Re: [Qemu-devel] [PATCH 1/5] spapr: Introduce DRC subclasses
On Sat, Jun 03, 2017 at 05:05:26PM -0500, Michael Roth wrote: > Quoting David Gibson (2017-06-02 02:29:48) > > Currently we only have a single QOM type for all DRCs, but lots of > > places where we switch behaviour based on the DRC's PAPR defined type. > > This is a poor use of our existing type system. > > > > So, instead create QOM subclasses for each PAPR defined DRC type. We > > also introduce intermediate subclasses for physical and logical DRCs, > > a division which will be useful later on. > > > > Instead of being stored in the DRC object itself, the PAPR type is now > > stored in the class structure. There are still many places where we > > switch directly on the PAPR type value, but this at least provides the > > basis to start to remove those. > > > > Signed-off-by: David Gibson > > --- > > hw/ppc/spapr.c | 5 +- > > hw/ppc/spapr_drc.c | 120 > > + > > hw/ppc/spapr_pci.c | 3 +- > > include/hw/ppc/spapr_drc.h | 47 -- > > 4 files changed, 136 insertions(+), 39 deletions(-) > > > > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c > > index 5d10366..456f9e7 100644 > > --- a/hw/ppc/spapr.c > > +++ b/hw/ppc/spapr.c > > @@ -1911,7 +1911,7 @@ static void > > spapr_create_lmb_dr_connectors(sPAPRMachineState *spapr) > > uint64_t addr; > > > > addr = i * lmb_size + spapr->hotplug_memory.base; > > -drc = spapr_dr_connector_new(OBJECT(spapr), > > SPAPR_DR_CONNECTOR_TYPE_LMB, > > +drc = spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_LMB, > > addr/lmb_size); > > qemu_register_reset(spapr_drc_reset, drc); > > } > > @@ -2008,8 +2008,7 @@ static void spapr_init_cpus(sPAPRMachineState *spapr) > > > > if (mc->has_hotpluggable_cpus) { > > sPAPRDRConnector *drc = > > -spapr_dr_connector_new(OBJECT(spapr), > > - SPAPR_DR_CONNECTOR_TYPE_CPU, > > +spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_CPU, > > (core_id / smp_threads) * smt); > > > > qemu_register_reset(spapr_drc_reset, drc); > > diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c > > index a35314e..690b41f 100644 > > --- a/hw/ppc/spapr_drc.c > > +++ b/hw/ppc/spapr_drc.c > > @@ -70,14 +70,23 @@ static sPAPRDRConnectorTypeShift > > get_type_shift(sPAPRDRConnectorType type) > > return shift; > > } > > > > +sPAPRDRConnectorType spapr_drc_type(sPAPRDRConnector *drc) > > +{ > > +sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); > > + > > +return 1 << drck->typeshift; > > +} > > + > > uint32_t spapr_drc_index(sPAPRDRConnector *drc) > > { > > +sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); > > + > > /* no set format for a drc index: it only needs to be globally > > * unique. this is how we encode the DRC type on bare-metal > > * however, so might as well do that here > > */ > > -return (get_type_shift(drc->type) << DRC_INDEX_TYPE_SHIFT) | > > -(drc->id & DRC_INDEX_ID_MASK); > > +return (drck->typeshift << DRC_INDEX_TYPE_SHIFT) > > +| (drc->id & DRC_INDEX_ID_MASK); > > } > > > > static uint32_t set_isolation_state(sPAPRDRConnector *drc, > > @@ -107,7 +116,7 @@ static uint32_t set_isolation_state(sPAPRDRConnector > > *drc, > > * If the LMB being removed doesn't belong to a DIMM device that is > > * actually being unplugged, fail the isolation request here. > > */ > > -if (drc->type == SPAPR_DR_CONNECTOR_TYPE_LMB) { > > +if (spapr_drc_type(drc) == SPAPR_DR_CONNECTOR_TYPE_LMB) { > > if ((state == SPAPR_DR_ISOLATION_STATE_ISOLATED) && > > !drc->awaiting_release) { > > return RTAS_OUT_HW_ERROR; > > @@ -177,7 +186,7 @@ static uint32_t set_allocation_state(sPAPRDRConnector > > *drc, > > } > > } > > > > -if (drc->type != SPAPR_DR_CONNECTOR_TYPE_PCI) { > > +if (spapr_drc_type(drc) != SPAPR_DR_CONNECTOR_TYPE_PCI) { > > drc->allocation_state = state; > > if (drc->awaiting_release && > > drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_UNUSABLE) { > > @@ -191,11 +200,6 @@ static uint32_t set_allocation_state(sPAPRDRConnector > > *drc, > > return RTAS_OUT_SUCCESS; > > } > > > > -sPAPRDRConnectorType spapr_drc_type(sPAPRDRConnector *drc) > > -{ > > -return drc->type; > > -} > > - > > static const char *get_name(sPAPRDRConnector *drc) > > { > > return drc->name; > > @@ -217,7 +221,7 @@ static void set_signalled(sPAPRDRConnector *drc) > > static uint32_t entity_sense(sPAPRDRConnector *drc, sPAPRDREntitySense > > *state) > > { > > if (drc->dev) { > > -if (drc->type != SPAPR_DR_CONNECTOR_TYPE_PCI && > > +if (spapr_drc_type(drc) != SPAPR_DR_CONNECTOR_TYPE_PCI && > > d
Re: [Qemu-devel] [PATCH 3/5] spapr: Move configure-connector state into DRC
On Sat, Jun 03, 2017 at 05:24:23PM -0500, Michael Roth wrote: > Quoting David Gibson (2017-06-02 02:29:50) > > Currently the sPAPRMachineState contains a of sPAPRConfigureConnector > > "contains a list"? Ta, corrected. > > structures which store intermediate state for the ibm,configure-connector > > RTAS call. > > > > This was an attempt to separate this state from the core of the DRC state. > > However the configure connector process is intimately tied to the DRC > > model, so there's really no point trying to have two levels of interface > > here. > > > > Moving the configure-connector state into its corresponding DRC allows > > removal of a number of helpers for maintaining the anciliary list. > > > > Signed-off-by: David Gibson > > Reviewed-by: Michael Roth > > > --- > > hw/ppc/spapr.c | 4 --- > > hw/ppc/spapr_drc.c | 73 > > -- > > include/hw/ppc/spapr.h | 14 - > > include/hw/ppc/spapr_drc.h | 7 + > > 4 files changed, 25 insertions(+), 73 deletions(-) > > > > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c > > index 7aac3b9..6234dbd 100644 > > --- a/hw/ppc/spapr.c > > +++ b/hw/ppc/spapr.c > > @@ -2339,10 +2339,6 @@ static void ppc_spapr_init(MachineState *machine) > > register_savevm_live(NULL, "spapr/htab", -1, 1, > > &savevm_htab_handlers, spapr); > > > > -/* used by RTAS */ > > -QTAILQ_INIT(&spapr->ccs_list); > > -qemu_register_reset(spapr_ccs_reset_hook, spapr); > > - > > qemu_register_boot_set(spapr_boot_set, spapr); > > > > if (kvm_enabled()) { > > diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c > > index 2514f87..27d4bd3 100644 > > --- a/hw/ppc/spapr_drc.c > > +++ b/hw/ppc/spapr_drc.c > > @@ -27,34 +27,6 @@ > > #define DRC_INDEX_TYPE_SHIFT 28 > > #define DRC_INDEX_ID_MASK ((1ULL << DRC_INDEX_TYPE_SHIFT) - 1) > > > > -static sPAPRConfigureConnectorState *spapr_ccs_find(sPAPRMachineState > > *spapr, > > -uint32_t drc_index) > > -{ > > -sPAPRConfigureConnectorState *ccs = NULL; > > - > > -QTAILQ_FOREACH(ccs, &spapr->ccs_list, next) { > > -if (ccs->drc_index == drc_index) { > > -break; > > -} > > -} > > - > > -return ccs; > > -} > > - > > -static void spapr_ccs_add(sPAPRMachineState *spapr, > > - sPAPRConfigureConnectorState *ccs) > > -{ > > -g_assert(!spapr_ccs_find(spapr, ccs->drc_index)); > > -QTAILQ_INSERT_HEAD(&spapr->ccs_list, ccs, next); > > -} > > - > > -static void spapr_ccs_remove(sPAPRMachineState *spapr, > > - sPAPRConfigureConnectorState *ccs) > > -{ > > -QTAILQ_REMOVE(&spapr->ccs_list, ccs, next); > > -g_free(ccs); > > -} > > - > > sPAPRDRConnectorType spapr_drc_type(sPAPRDRConnector *drc) > > { > > sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); > > @@ -81,6 +53,16 @@ static uint32_t set_isolation_state(sPAPRDRConnector > > *drc, > > > > trace_spapr_drc_set_isolation_state(spapr_drc_index(drc), state); > > > > +/* if the guest is configuring a device attached to this DRC, we > > + * should reset the configuration state at this point since it may > > + * no longer be reliable (guest released device and needs to start > > + * over, or unplug occurred so the FDT is no longer valid) > > + */ > > +if (state == SPAPR_DR_ISOLATION_STATE_ISOLATED) { > > +g_free(drc->ccs); > > +drc->ccs = NULL; > > +} > > + > > if (state == SPAPR_DR_ISOLATION_STATE_UNISOLATED) { > > /* cannot unisolate a non-existent resource, and, or resources > > * which are in an 'UNUSABLE' allocation state. (PAPR 2.7, > > 13.5.3.5) > > @@ -485,6 +467,10 @@ static void reset(DeviceState *d) > > sPAPRDREntitySense state; > > > > trace_spapr_drc_reset(spapr_drc_index(drc)); > > + > > +g_free(drc->ccs); > > +drc->ccs = NULL; > > + > > /* immediately upon reset we can safely assume DRCs whose devices > > * are pending removal can be safely removed, and that they will > > * subsequently be left in an ISOLATED state. move the DRC to this > > @@ -1020,19 +1006,6 @@ static void rtas_set_indicator(PowerPCCPU *cpu, > > sPAPRMachineState *spapr, > > > > switch (sensor_type) { > > case RTAS_SENSOR_TYPE_ISOLATION_STATE: > > -/* if the guest is configuring a device attached to this > > - * DRC, we should reset the configuration state at this > > - * point since it may no longer be reliable (guest released > > - * device and needs to start over, or unplug occurred so > > - * the FDT is no longer valid) > > - */ > > -if (sensor_state == SPAPR_DR_ISOLATION_STATE_ISOLATED) { > > -sPAPRConfigureConnectorState *ccs = spapr_ccs_find(spapr, > > - > > s
Re: [Qemu-devel] [virtio-dev] Re: [virtio-dev] Re: [virtio-dev] Re: [PATCH v2 00/16] Vhost-pci for inter-VM communication
On 05/26/2017 01:57 AM, Michael S. Tsirkin wrote: I think that's a very valid point. Linux isn't currently optimized to handle packets in device BAR. There are several issues here and you do need to address them in the kernel, no way around that: 1. lots of drivers set protection to vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); Sorry for my late reply. In the implementation tests, I didn't find an issue when letting the guest directly access the bar MMIO returned by ioremap_cache(). If that's conventionally improper, we can probably make a new function similar to ioremap_cache, as the 2nd comment suggests below. So, in any case, the vhost-pci driver uses ioremap_cache() or a similar function, which sets the memory type to WB. vfio certainly does, and so I think does pci sysfs. You won't get good performance with this, you want to use a cacheable mapping. This needs to be addressed for pmd to work well. In case it's useful for the discussion here, introduce a little background about how the bar MMIO is used in vhost-pci: The device in QEMU sets up the MemoryRegion of the bar as "ram" type, which will finally have translation mappings created in EPT. So, the memory setup of the bar is the same as adding a regular RAM. It's like we are passing through a bar memory to the guest which allows the guest to directly access to the bar memory. Back to the comments, why it is not cacheable memory when the vhost-pci driver explicitly uses ioremap_cache()? 2. linux mostly assumes PCI BAR isn't memory, ioremap_cache returns __iomem pointers which aren't supposed to be dereferenced directly. You want a new API that does direct remap or copy if not possible. Alternatively remap or fail, kind of like pci_remap_iospace. Maybe there's already something like that - I'm not sure. For the vhost-pci case, the bar is known to be a portion physical memory. So, in this case, would it be an issue if the driver directly accesses to it? (as mentioned above, the implementation functions correctly) Best, Wei
Re: [Qemu-devel] [PATCHv4 0/5] Clean up compatibility mode handling
On Fri, Jun 02, 2017 at 10:15:25AM +0200, Greg Kurz wrote: > On Fri, 2 Jun 2017 12:00:07 +1000 > David Gibson wrote: > > > On Thu, Jun 01, 2017 at 03:09:15PM +0200, Greg Kurz wrote: > > > On Thu, 1 Jun 2017 13:59:14 +0200 > > > Cédric Le Goater wrote: > > > > > > > On 06/01/2017 08:52 AM, David Gibson wrote: > > > > > On Wed, May 31, 2017 at 10:58:57AM +0200, Greg Kurz wrote: > > > > >> On Wed, 31 May 2017 12:57:48 +1000 > > > > >> David Gibson wrote: > > > > >>> [...] > > > > All old non-pseries machine types already complain when started > > > > with > > > > a POWER7 or newer CPU. Providing the extra error message looks > > > > weird: > > > > > > > > qemu-system-ppc64 -machine ppce500 \ > > > > -cpu POWER7,compat=power6 > > > > qemu-system-ppc64: CPU 'compat' property is deprecated and has no > > > > effect; > > > > use max-cpu-compat machine property instead > > > > MMU model 983043 not supported by this machine. > > > > > > > > but I guess it's better than crashing. :) > > > > >>> > > > > >>> Well, sure POWER7 doesn't make sense for an e500 machine for other > > > > >>> reasons. But POWER7 or POWER8 _would_ make sense for powernv, where > > > > >>> compat= doesn't. > > > > >>> > > > > >> > > > > >> The powernv machine type doesn't even support CPU features at all: > > > > >> > > > > >> chip_typename = g_strdup_printf(TYPE_PNV_CHIP "-%s", > > > > >> machine->cpu_model); > > > > >> if (!object_class_by_name(chip_typename)) { > > > > >> error_report("invalid CPU model '%s' for %s machine", > > > > >> machine->cpu_model, > > > > >> MACHINE_GET_CLASS(machine)->name); > > > > >> exit(1); > > > > >> } > > > > > > > > > > Ah, well, that's another bug, but not one that's in scope for this > > > > > series. > > > > > > > > PowerNV is still work in progress. I would not worry about it too much. > > > > > > > > > > Of course and this isn't the purpose of the discussion actually. We were > > > talking about CPU features being relevant or not depending on the machine > > > type. > > > > > > But I'm not even sure that CPU features are useful at all for ppc, not to > > > say very confusing (otherwise this series wouldn't be needed for example). > > > > > > Speaking of PowerNV, just as an example, I guess the fix would be to > > > forbid machine->cpu_model if it contains features. And probably the same > > > for all other machine types, except pseries for backward compatibility > > > reasons. > > > > I don't think that's correct in principle. I can imagine CPU > > properties it might make sense to really set on the cpu, regardless of > > machine type. A quick look says we don't have any such at the moment, > > but I don't think it's something we should prevent as a matter of policy. > > Fair enough. Then maybe all machine should parse CPU features and check which > one are valid before instantiating the CPUs ? Well, CPu properties *should* be valid for all machine types. The fact that compat= wasn't was a mistake. -- David Gibson| I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson signature.asc Description: PGP signature
[Qemu-devel] [PULL 02/22] qemu-doc: Add hyperlinks to further license information
From: Thomas Huth Add a link to the GPLv2 and a link to the LICENSE file in the QEMU repository to fix the two TODO items in this appendix. Signed-off-by: Thomas Huth Reviewed-by: Stefan Hajnoczi Signed-off-by: Michael Tokarev --- qemu-doc.texi | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/qemu-doc.texi b/qemu-doc.texi index 3f4ed0aa9a..965ba5929e 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -3021,10 +3021,10 @@ Run the emulation in single step mode. QEMU is a trademark of Fabrice Bellard. -QEMU is released under the GNU General Public License (TODO: add link). -Parts of QEMU have specific licenses, see file LICENSE. - -TODO (refer to file LICENSE, include it, include the GPL?) +QEMU is released under the +@url{https://www.gnu.org/licenses/gpl-2.0.txt,GNU General Public License}, +version 2. Parts of QEMU have specific licenses, see file +@url{http://git.qemu.org/?p=qemu.git;a=blob_plain;f=LICENSE,LICENSE}. @node Index @appendix Index -- 2.11.0
[Qemu-devel] [PULL 08/22] trivial: Remove unneeded ifndef in memory.h
From: Juan Quintela All the file is surounded already by #ifndef CONFIG_USER_ONLY. Signed-off-by: Juan Quintela Reviewed-by: Dr. David Alan Gilbert Reviewed-by: Laurent Vivier Signed-off-by: Michael Tokarev --- include/exec/memory.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/exec/memory.h b/include/exec/memory.h index bfdc685f24..80e605a96a 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -17,9 +17,7 @@ #ifndef CONFIG_USER_ONLY #include "exec/cpu-common.h" -#ifndef CONFIG_USER_ONLY #include "exec/hwaddr.h" -#endif #include "exec/memattrs.h" #include "exec/ramlist.h" #include "qemu/queue.h" -- 2.11.0
[Qemu-devel] [PULL 10/22] target/arm: add data cache invalidation cp15 instruction to cortex-r5
From: Luc MICHEL The cp15, CRn=15, opc1=0, CRm=5, opc2=0 instruction invalidates all the data cache on the cortex-r5. Implementing it as a NOP. Signed-off-by: Luc MICHEL Signed-off-by: Michael Tokarev --- target/arm/cpu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/arm/cpu.c b/target/arm/cpu.c index e748097860..04a3fea03f 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -1082,6 +1082,8 @@ static const ARMCPRegInfo cortexr5_cp_reginfo[] = { .access = PL1_RW, .type = ARM_CP_CONST }, { .name = "BTCM", .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 1, .access = PL1_RW, .type = ARM_CP_CONST }, +{ .name = "DCACHE_INVAL", .cp = 15, .opc1 = 0, .crn = 15, .crm = 5, + .opc2 = 0, .access = PL1_W, .type = ARM_CP_NOP }, REGINFO_SENTINEL }; -- 2.11.0
[Qemu-devel] [PULL 07/22] altera_timer: fix incorrect memset
From: Paolo Bonzini Use sizeof instead of ARRAY_SIZE, fixing -Wmemset-elt-size with recent GCC versions. Signed-off-by: Paolo Bonzini Reviewed-by: Laurent Vivier Signed-off-by: Michael Tokarev --- hw/timer/altera_timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/timer/altera_timer.c b/hw/timer/altera_timer.c index 6d4862661d..c9a0fc5dca 100644 --- a/hw/timer/altera_timer.c +++ b/hw/timer/altera_timer.c @@ -204,7 +204,7 @@ static void altera_timer_reset(DeviceState *dev) ptimer_stop(t->ptimer); ptimer_set_limit(t->ptimer, 0x, 1); -memset(t->regs, 0, ARRAY_SIZE(t->regs)); +memset(t->regs, 0, sizeof(t->regs)); } static Property altera_timer_properties[] = { -- 2.11.0
[Qemu-devel] [PULL 05/22] tests/libqtest: Print error instead of aborting when env variable is missing
From: Thomas Huth When you currently try to run a test directly from the command line without setting the QTEST_QEMU_BINARY environment variable first, you are presented with an unhelpful assertion message like this: ERROR:tests/libqtest.c:163:qtest_init_without_qmp_handshake: assertion failed: (qemu_binary != NULL) Aborted (core dumped) Let's replace the assert() with a more user friendly error message instead. Reviewed-by: Markus Armbruster Signed-off-by: Thomas Huth Signed-off-by: Michael Tokarev --- tests/libqtest.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/libqtest.c b/tests/libqtest.c index 84ecbd2bd8..4a5492a603 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -160,7 +160,10 @@ QTestState *qtest_init_without_qmp_handshake(const char *extra_args) const char *qemu_binary; qemu_binary = getenv("QTEST_QEMU_BINARY"); -g_assert(qemu_binary != NULL); +if (!qemu_binary) { +fprintf(stderr, "Environment variable QTEST_QEMU_BINARY required\n"); +exit(1); +} s = g_malloc(sizeof(*s)); -- 2.11.0
[Qemu-devel] [PULL 22/22] hw/core: nmi.c can be compiled as common-obj nowadays
From: Thomas Huth The target-specific code in nmi.c has been removed with this commit: commit f7e981f29548fe4af7812f5920304fe607e5bf0d nmi: remove x86 specific nmi handling Signed-off-by: Thomas Huth Reviewed-by: Juan Quintela Signed-off-by: Michael Tokarev --- hw/core/Makefile.objs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs index 91450b2eab..f8d7a4aaed 100644 --- a/hw/core/Makefile.objs +++ b/hw/core/Makefile.objs @@ -5,7 +5,7 @@ common-obj-y += fw-path-provider.o # irq.o needed for qdev GPIO handling: common-obj-y += irq.o common-obj-y += hotplug.o -obj-y += nmi.o +common-obj-y += nmi.o common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o common-obj-$(CONFIG_XILINX_AXI) += stream.o -- 2.11.0
[Qemu-devel] [PULL 00/22] Trivial patches for 2017-06-04
Trivial patches for 04 Jun 2017. Please consider applying. /mjt The following changes since commit c6e84fbd447a51e1161d74d71566a5f67b47eac5: Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging (2017-06-02 17:46:22 +0100) are available in the git repository at: git://git.corpit.ru/qemu.git tags/trivial-patches-fetch for you to fetch changes up to 070ccceda3b23f85d048bbcf3c0040252a9a793a: hw/core: nmi.c can be compiled as common-obj nowadays (2017-06-04 18:43:09 +0300) trivial patches for 2017-06-04 Eric Blake (2): block: Correct documentation for BLOCK_WRITE_THRESHOLD qapi: Fix some QMP documentation regressions John Snow (1): ide-test: check return of fwrite Juan Quintela (1): trivial: Remove unneeded ifndef in memory.h Kamil Rytarowski (2): configure: Detect native NetBSD curses(3) ivshmem-server: ivshmem-client: Build when eventfd() is available Luc MICHEL (1): target/arm: add data cache invalidation cp15 instruction to cortex-r5 Mao Zhongyi (1): scsi/lsi53c895a: Remove unused lsi_mem_*() return value Marc-André Lureau (2): qemu-ga: remove useless allocation dump: fix memory_mapping_filter leak Markus Armbruster (2): docs qemu-doc: Avoid ide-drive, it's deprecated docs/qdev-device-use.txt: update section Default Devices Max Filippov (1): hw/xtensa: sim: use g_string/g_new Paolo Bonzini (1): altera_timer: fix incorrect memset Philippe Mathieu-Daudé (3): hw/sparc: use ARRAY_SIZE() macro register: display register prefix (name) since it is available hw/mips: add missing include Suraj Jitindar Singh (1): help: Add newline to end of thread option help text Thomas Huth (4): qemu-doc: Move the qemu-ga description into a separate chapter qemu-doc: Add hyperlinks to further license information tests/libqtest: Print error instead of aborting when env variable is missing hw/core: nmi.c can be compiled as common-obj nowadays configure| 5 +++-- contrib/ivshmem-client/Makefile.objs | 2 +- contrib/ivshmem-server/Makefile.objs | 2 +- docs/bootindex.txt | 2 +- docs/qdev-device-use.txt | 13 +++-- hw/core/Makefile.objs| 2 +- hw/core/register.c | 8 hw/scsi/lsi53c895a.c | 10 -- hw/sparc64/sun4u.c | 2 +- hw/timer/altera_timer.c | 2 +- hw/xtensa/sim.c | 10 +- include/exec/memory.h| 2 -- include/hw/mips/mips.h | 1 + memory_mapping.c | 1 + qapi/block-core.json | 30 +++--- qapi/block.json | 2 +- qemu-doc.texi| 21 +++-- qemu-options.hx | 4 ++-- qga/commands-posix.c | 4 +--- target/arm/cpu.c | 2 ++ tests/ide-test.c | 8 ++-- tests/libqtest.c | 5 - 22 files changed, 73 insertions(+), 65 deletions(-)
[Qemu-devel] [PULL 11/22] hw/xtensa: sim: use g_string/g_new
From: Max Filippov Replace malloc/free/sprintf with g_string/g_string_printf/g_string_free. Replace g_malloc with g_new when allocating the MemoryRegion to get more type safety. Suggested-by: Alex Bennée Signed-off-by: Max Filippov Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Michael Tokarev --- hw/xtensa/sim.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/hw/xtensa/sim.c b/hw/xtensa/sim.c index d2d1d3a6fd..b27e28d802 100644 --- a/hw/xtensa/sim.c +++ b/hw/xtensa/sim.c @@ -41,21 +41,21 @@ static void xtensa_create_memory_regions(const XtensaMemory *memory, const char *name) { unsigned i; -char *num_name = malloc(strlen(name) + sizeof(i) * 3 + 1); +GString *num_name = g_string_new(NULL); for (i = 0; i < memory->num; ++i) { MemoryRegion *m; -sprintf(num_name, "%s%u", name, i); -m = g_malloc(sizeof(*m)); -memory_region_init_ram(m, NULL, num_name, +g_string_printf(num_name, "%s%u", name, i); +m = g_new(MemoryRegion, 1); +memory_region_init_ram(m, NULL, num_name->str, memory->location[i].size, &error_fatal); vmstate_register_ram_global(m); memory_region_add_subregion(get_system_memory(), memory->location[i].addr, m); } -free(num_name); +g_string_free(num_name, true); } static uint64_t translate_phys_addr(void *opaque, uint64_t addr) -- 2.11.0
Re: [Qemu-devel] [PATCH v2 1/4] dump: add DumpInfo structure
On 06/03/2017 06:49 AM, Laszlo Ersek wrote: On 06/02/17 11:55, Marc-André Lureau wrote: Hi On Fri, Jun 2, 2017 at 1:46 PM Marc-André Lureau wrote: Hi On Thu, Jun 1, 2017 at 10:19 PM Eric Blake wrote: On 06/01/2017 01:06 PM, Laszlo Ersek wrote: On 06/01/17 15:03, Marc-André Lureau wrote: One way or another, the guest could communicate various dump info (via guest agent or vmcoreinfo device) and populate that structure. It can then be used to augment the dump with various details, as done in the following patch. Signed-off-by: Marc-André Lureau --- include/sysemu/dump-info.h | 18 ++ dump.c | 3 +++ 2 files changed, 21 insertions(+) create mode 100644 include/sysemu/dump-info.h diff --git a/include/sysemu/dump-info.h b/include/sysemu/dump-info.h new file mode 100644 index 00..d2378e15e2 --- /dev/null +++ b/include/sysemu/dump-info.h @@ -0,0 +1,18 @@ +#ifndef DUMP_INFO_H +#define DUMP_INFO_H Can you please spell out, in the commit message, the reason for introducing a new header file? (I suspect your reason, but it should be documented explicitly.) Also, should you have a copyright header in the new file? And does MAINTAINERS cover it? None of the dump support is covered. Based on commit history, I can suggest Wen Congyang, as original author. Sadly, Qiao Nuohan cannot be reached with his mail today (anyone knows if he is still contributing?). Laszlo has done significant changes and reviews too. I can also propose myself to help with reviews. Wen or Laszla, do you want to be the main maintainer? I can cc Qiao Nuohan... Thanks Zhang Chen (sorry for the typo) or rather "Supported" ("Someone is actually paid to look after this" according to MAINTAINERS) Thanks, but I don't wish to have an official responsibility for this feature. My current responsibilities are more than enough to keep me busy. If you'd like to volunteer for maintaining the dump stuff, you have my blessing of course (whatever weight that might carry). Thanks Laszlo -- Thanks Zhang Chen
[Qemu-devel] [PULL 14/22] hw/mips: add missing include
From: Philippe Mathieu-Daudé Signed-off-by: Philippe Mathieu-Daudé Acked-by: Aurelien Jarno Signed-off-by: Michael Tokarev --- include/hw/mips/mips.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/hw/mips/mips.h b/include/hw/mips/mips.h index e0065ce808..16412dc150 100644 --- a/include/hw/mips/mips.h +++ b/include/hw/mips/mips.h @@ -6,6 +6,7 @@ #define INITRD_PAGE_MASK (~((1 << 16) - 1)) #include "exec/memory.h" +#include "hw/irq.h" /* gt64xxx.c */ PCIBus *gt64120_register(qemu_irq *pic); -- 2.11.0
[Qemu-devel] [PULL 19/22] ide-test: check return of fwrite
From: John Snow To quiet patchew, add an assert for fwrite's return value. Signed-off-by: John Snow Reviewed-by: Jeff Cody Reviewed-by: Laurent Vivier Signed-off-by: Michael Tokarev --- tests/ide-test.c | 8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/ide-test.c b/tests/ide-test.c index 139ebc0ec6..bfd79ddbdc 100644 --- a/tests/ide-test.c +++ b/tests/ide-test.c @@ -796,11 +796,13 @@ static void cdrom_pio_impl(int nblocks) int i, j; uint8_t data; uint16_t limit; +size_t ret; /* Prepopulate the CDROM with an interesting pattern */ generate_pattern(pattern, patt_len, ATAPI_BLOCK_SIZE); fh = fopen(tmp_path, "w+"); -fwrite(pattern, ATAPI_BLOCK_SIZE, patt_blocks, fh); +ret = fwrite(pattern, ATAPI_BLOCK_SIZE, patt_blocks, fh); +g_assert_cmpint(ret, ==, patt_blocks); fclose(fh); ide_test_start("-drive if=none,file=%s,media=cdrom,format=raw,id=sr0,index=0 " @@ -880,6 +882,7 @@ static void test_cdrom_pio_large(void) static void test_cdrom_dma(void) { static const size_t len = ATAPI_BLOCK_SIZE; +size_t ret; char *pattern = g_malloc(ATAPI_BLOCK_SIZE * 16); char *rx = g_malloc0(len); uintptr_t guest_buf; @@ -896,7 +899,8 @@ static void test_cdrom_dma(void) generate_pattern(pattern, ATAPI_BLOCK_SIZE * 16, ATAPI_BLOCK_SIZE); fh = fopen(tmp_path, "w+"); -fwrite(pattern, ATAPI_BLOCK_SIZE, 16, fh); +ret = fwrite(pattern, ATAPI_BLOCK_SIZE, 16, fh); +g_assert_cmpint(ret, ==, 16); fclose(fh); send_dma_request(CMD_PACKET, 0, 1, prdt, 1, send_scsi_cdb_read10); -- 2.11.0
[Qemu-devel] [PULL 01/22] qemu-doc: Move the qemu-ga description into a separate chapter
From: Thomas Huth The qemu-ga description is currently a subsection of the Disk Images chapter - which does not make much sense since the qemu-ga is not directly related to disk images. So let's move this information into a separate chapter instead. Signed-off-by: Thomas Huth Reviewed-by: Stefan Hajnoczi Signed-off-by: Michael Tokarev --- qemu-doc.texi | 13 +++-- 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/qemu-doc.texi b/qemu-doc.texi index de0cc30790..3f4ed0aa9a 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -34,6 +34,7 @@ * Introduction:: * QEMU PC System emulator:: * QEMU System emulator for non PC targets:: +* QEMU Guest Agent:: * QEMU User space emulator:: * Implementation notes:: * License:: @@ -396,7 +397,6 @@ snapshots. * vm_snapshots:: VM snapshots * qemu_img_invocation:: qemu-img Invocation * qemu_nbd_invocation:: qemu-nbd Invocation -* qemu_ga_invocation::qemu-ga Invocation * disk_images_formats:: Disk image file formats * host_drives:: Using host drives * disk_images_fat_images::Virtual FAT disk images @@ -490,11 +490,6 @@ state is not saved or restored properly (in particular USB). @include qemu-nbd.texi -@node qemu_ga_invocation -@subsection @code{qemu-ga} Invocation - -@include qemu-ga.texi - @node disk_images_formats @subsection Disk image file formats @@ -2685,6 +2680,12 @@ Note that this allows guest direct access to the host filesystem, so should only be used with trusted guest OS. @end table + +@node QEMU Guest Agent +@chapter QEMU Guest Agent invocation + +@include qemu-ga.texi + @node QEMU User space emulator @chapter QEMU User space emulator -- 2.11.0
[Qemu-devel] [PULL 17/22] qemu-ga: remove useless allocation
From: Marc-André Lureau There is no need to duplicate a fixed string. Signed-off-by: Marc-André Lureau Reviewed-by: Eric Blake Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Michael Tokarev --- qga/commands-posix.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 284ecc6d7e..d8e412275e 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -2197,12 +2197,10 @@ static void transfer_memory_block(GuestMemoryBlock *mem_blk, bool sys2memblk, } } else { if (mem_blk->online != (strncmp(status, "online", 6) == 0)) { -char *new_state = mem_blk->online ? g_strdup("online") : -g_strdup("offline"); +const char *new_state = mem_blk->online ? "online" : "offline"; ga_write_sysfs_file(dirfd, "state", new_state, strlen(new_state), &local_err); -g_free(new_state); if (local_err) { error_free(local_err); result->response = -- 2.11.0
[Qemu-devel] [PULL 18/22] help: Add newline to end of thread option help text
From: Suraj Jitindar Singh The help text for the thread sub option of the accel option is missing a newline at the end. This is annoying as it makes it hard to see the help text for the next option. Add the new line so that the following option help text (-smp) is displayed on a new line rather on the same line and directly after the thread help. Before patch: -accel [accel=]accelerator[,thread=single|multi] select accelerator (kvm, xen, hax or tcg; use 'help' for a list) thread=single|multi (enable multi-threaded TCG)-smp [cpus=]n[,maxcpus=cpus][,cores=cores][,threads=threads][,sockets=sockets] set the number of CPUs to 'n' [default=1] maxcpus= maximum number of total cpus, including offline CPUs for hotplug, etc cores= number of CPU cores on one socket threads= number of threads on one CPU core sockets= number of discrete sockets in the system After patch: -accel [accel=]accelerator[,thread=single|multi] select accelerator (kvm, xen, hax or tcg; use 'help' for a list) thread=single|multi (enable multi-threaded TCG) -smp [cpus=]n[,maxcpus=cpus][,cores=cores][,threads=threads][,sockets=sockets] set the number of CPUs to 'n' [default=1] maxcpus= maximum number of total cpus, including offline CPUs for hotplug, etc cores= number of CPU cores on one socket threads= number of threads on one CPU core sockets= number of discrete sockets in the system Signed-off-by: Suraj Jitindar Singh Signed-off-by: Michael Tokarev --- qemu-options.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qemu-options.hx b/qemu-options.hx index 10995dc932..30c4f9850f 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -102,7 +102,7 @@ ETEXI DEF("accel", HAS_ARG, QEMU_OPTION_accel, "-accel [accel=]accelerator[,thread=single|multi]\n" "select accelerator (kvm, xen, hax or tcg; use 'help' for a list)\n" -"thread=single|multi (enable multi-threaded TCG)", QEMU_ARCH_ALL) +"thread=single|multi (enable multi-threaded TCG)\n", QEMU_ARCH_ALL) STEXI @item -accel @var{name}[,prop=@var{value}[,...]] @findex -accel -- 2.11.0
[Qemu-devel] [PULL 20/22] dump: fix memory_mapping_filter leak
From: Marc-André Lureau Spotted by ASAN. Signed-off-by: Marc-André Lureau Signed-off-by: Michael Tokarev --- memory_mapping.c | 1 + 1 file changed, 1 insertion(+) diff --git a/memory_mapping.c b/memory_mapping.c index 6a39d71da2..a5d38552a6 100644 --- a/memory_mapping.c +++ b/memory_mapping.c @@ -337,6 +337,7 @@ void memory_mapping_filter(MemoryMappingList *list, int64_t begin, if (cur->phys_addr >= begin + length || cur->phys_addr + cur->length <= begin) { QTAILQ_REMOVE(&list->head, cur, next); +g_free(cur); list->num--; continue; } -- 2.11.0
[Qemu-devel] [PULL 15/22] qapi: Fix some QMP documentation regressions
From: Eric Blake In the process of getting rid of docs/qmp-commands.txt, we managed to regress on some of the text that changed after the point where the move was first branched and when the move actually occurred. For example, commit 3282eca for blockdev-snapshot re-added the extra "options" layer which had been cleaned up in commit 0153d2f. This clears up all regressions identified over the range 02b351d..bd6092e: https://lists.gnu.org/archive/html/qemu-devel/2017-05/msg05127.html as well as a cleanup to x-blockdev-remove-medium to prefer 'id' over 'device' (matching the cleanup for 'eject'). Signed-off-by: Eric Blake Reviewed-by: Markus Armbruster Signed-off-by: Michael Tokarev --- qapi/block-core.json | 28 ++-- qapi/block.json | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/qapi/block-core.json b/qapi/block-core.json index 309b1df214..88a7471a23 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -1206,11 +1206,11 @@ # Example: # # -> { "execute": "blockdev-add", -# "arguments": { "options": { "driver": "qcow2", -# "node-name": "node1534", -# "file": { "driver": "file", -#"filename": "hd1.qcow2" }, -# "backing": "" } } } +# "arguments": { "driver": "qcow2", +# "node-name": "node1534", +# "file": { "driver": "file", +# "filename": "hd1.qcow2" }, +# "backing": "" } } # # <- { "return": {} } # @@ -3214,7 +3214,7 @@ # <- { "return": {} } # # -> { "execute": "x-blockdev-remove-medium", -# "arguments": { "device": "ide0-1-0" } } +# "arguments": { "id": "ide0-1-0" } } # # <- { "return": {} } # @@ -3245,10 +3245,10 @@ # # -> { "execute": "blockdev-add", # "arguments": { -# "options": { "node-name": "node0", -# "driver": "raw", -# "file": { "driver": "file", -# "filename": "fedora.iso" } } } } +# "node-name": "node0", +# "driver": "raw", +# "file": { "driver": "file", +#"filename": "fedora.iso" } } } # <- { "return": {} } # # -> { "execute": "x-blockdev-insert-medium", @@ -3701,10 +3701,10 @@ # 1. Add a new node to a quorum # -> { "execute": "blockdev-add", # "arguments": { -# "options": { "driver": "raw", -# "node-name": "new_node", -#"file": { "driver": "file", -# "filename": "test.raw" } } } } +# "driver": "raw", +# "node-name": "new_node", +# "file": { "driver": "file", +#"filename": "test.raw" } } } # <- { "return": {} } # -> { "execute": "x-blockdev-change", # "arguments": { "parent": "disk1", diff --git a/qapi/block.json b/qapi/block.json index 6a2fdc73f7..414b61bde7 100644 --- a/qapi/block.json +++ b/qapi/block.json @@ -180,7 +180,7 @@ # # Example: # -# -> { "execute": "eject", "arguments": { "device": "ide1-0-1" } } +# -> { "execute": "eject", "arguments": { "id": "ide1-0-1" } } # <- { "return": {} } ## { 'command': 'eject', -- 2.11.0
[Qemu-devel] [PULL 04/22] docs/qdev-device-use.txt: update section Default Devices
From: Markus Armbruster Resynchronize the table of default device suppressions with vl.c's default_list[]. Signed-off-by: Markus Armbruster Reviewed-by: Thomas Huth Signed-off-by: Michael Tokarev --- docs/qdev-device-use.txt | 9 + 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/qdev-device-use.txt b/docs/qdev-device-use.txt index 95a0c3ae55..1f297b5e9c 100644 --- a/docs/qdev-device-use.txt +++ b/docs/qdev-device-use.txt @@ -399,12 +399,13 @@ type. some DEVNAMEs: default device suppressing DEVNAMEs -CD-ROM ide-cd, ide-drive, scsi-cd -isa-fdc's driveAisa-fdc +CD-ROM ide-cd, ide-drive, ide-hd, scsi-cd, scsi-hd +isa-fdc's driveAfloppy, isa-fdc parallelisa-parallel serial isa-serial -VGA VGA, cirrus-vga, vmware-svga -virtioconsole virtio-serial-pci, virtio-serial-s390, virtio-serial +VGA VGA, cirrus-vga, isa-vga, isa-cirrus-vga, +vmware-svga, qxl-vga, virtio-vga +virtioconsole virtio-serial-pci, virtio-serial The default NIC is connected to a default part created along with it. It is *not* suppressed by configuring a NIC with -device (you may call -- 2.11.0
[Qemu-devel] [PULL 03/22] docs qemu-doc: Avoid ide-drive, it's deprecated
From: Markus Armbruster Suggested-by: Thomas Huth Signed-off-by: Markus Armbruster Reviewed-by: Thomas Huth Signed-off-by: Michael Tokarev --- docs/bootindex.txt | 2 +- docs/qdev-device-use.txt | 4 ++-- qemu-options.hx | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/bootindex.txt b/docs/bootindex.txt index b9a8ba122f..6937862ba0 100644 --- a/docs/bootindex.txt +++ b/docs/bootindex.txt @@ -13,7 +13,7 @@ Let's assume we have a QEMU machine with two NICs (virtio, e1000) and two disks (IDE, virtio): qemu -drive file=disk1.img,if=none,id=disk1 - -device ide-drive,drive=disk1,bootindex=4 + -device ide-hd,drive=disk1,bootindex=4 -drive file=disk2.img,if=none,id=disk2 -device virtio-blk-pci,drive=disk2,bootindex=3 -netdev type=user,id=net0 -device virtio-net-pci,netdev=net0,bootindex=2 diff --git a/docs/qdev-device-use.txt b/docs/qdev-device-use.txt index 4274fe9f25..95a0c3ae55 100644 --- a/docs/qdev-device-use.txt +++ b/docs/qdev-device-use.txt @@ -31,8 +31,8 @@ A QEMU block device (drive) has a host and a guest part. In the general case, the guest device is connected to a controller device. For instance, the IDE controller provides two IDE buses, each -of which can have up to two ide-drive devices, and each ide-drive -device is a guest part, and is connected to a host part. +of which can have up to two devices, and each device is a guest part, +and is connected to a host part. Except we sometimes lump controller, bus(es) and drive device(s) all together into a single device. For instance, the ISA floppy diff --git a/qemu-options.hx b/qemu-options.hx index a6c9b9e763..10995dc932 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -262,7 +262,7 @@ STEXI Set default value of @var{driver}'s property @var{prop} to @var{value}, e.g.: @example -qemu-system-i386 -global ide-drive.physical_block_size=4096 -drive file=file,if=ide,index=0,media=disk +qemu-system-i386 -global ide-hd.physical_block_size=4096 disk-image.img @end example In particular, you can use this to set driver properties for devices which are -- 2.11.0
[Qemu-devel] [PULL 13/22] register: display register prefix (name) since it is available
From: Philippe Mathieu-Daudé Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Signed-off-by: Michael Tokarev --- hw/core/register.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/core/register.c b/hw/core/register.c index da38ef3a54..900294b9c4 100644 --- a/hw/core/register.c +++ b/hw/core/register.c @@ -195,8 +195,8 @@ void register_write_memory(void *opaque, hwaddr addr, } if (!reg) { -qemu_log_mask(LOG_GUEST_ERROR, "Write to unimplemented register at " \ - "address: %#" PRIx64 "\n", addr); +qemu_log_mask(LOG_GUEST_ERROR, "%s: write to unimplemented register " \ + "at address: %#" PRIx64 "\n", reg_array->prefix, addr); return; } @@ -224,8 +224,8 @@ uint64_t register_read_memory(void *opaque, hwaddr addr, } if (!reg) { -qemu_log_mask(LOG_GUEST_ERROR, "Read to unimplemented register at " \ - "address: %#" PRIx64 "\n", addr); +qemu_log_mask(LOG_GUEST_ERROR, "%s: read to unimplemented register " \ + "at address: %#" PRIx64 "\n", reg_array->prefix, addr); return 0; } -- 2.11.0
[Qemu-devel] [PULL 06/22] configure: Detect native NetBSD curses(3)
From: Kamil Rytarowski NetBSD ships with traditional BSD curses with compatibility with ncurses. qemu works nicely with the basesystem version of curses(3) from NetBSD. The only mismatch between curses(3) and ncurses is the lack of curses_version() in the NetBSD version. This function is used solely in the configure script, therefore eliminate it from the curses(3) detection. With this change applied, configure detects correctly curses frontend. Signed-off-by: Kamil Rytarowski Reviewed-by: Alex Bennée Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Michael Tokarev --- configure | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/configure b/configure index 21944eaa05..fbb6a93c99 100755 --- a/configure +++ b/configure @@ -3042,14 +3042,13 @@ if test "$curses" != "no" ; then #include #include int main(void) { - const char *s = curses_version(); wchar_t wch = L'w'; setlocale(LC_ALL, ""); resize_term(0, 0); addwstr(L"wide chars\n"); addnwstr(&wch, 1); add_wch(WACS_DEGREE); - return s != 0; + return 0; } EOF IFS=: -- 2.11.0
[Qemu-devel] [PULL 21/22] ivshmem-server: ivshmem-client: Build when eventfd() is available
From: Kamil Rytarowski Currently ivshmem requires eventfd() which is Linux specific. Do not and build it unconditionally on every Linux/BSD/Solaris. This patch indirectly fixes build failure on NetBSD, where these tools additionally require -lrt for shm_open(3). In future there should be added support for NetBSD and the linking addressed appropriately. Signed-off-by: Kamil Rytarowski Reviewed-by: Markus Armbruster Signed-off-by: Michael Tokarev --- configure| 2 ++ contrib/ivshmem-client/Makefile.objs | 2 +- contrib/ivshmem-server/Makefile.objs | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/configure b/configure index fbb6a93c99..965727bca8 100755 --- a/configure +++ b/configure @@ -4910,6 +4910,8 @@ if test "$want_tools" = "yes" ; then tools="qemu-img\$(EXESUF) qemu-io\$(EXESUF) $tools" if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then tools="qemu-nbd\$(EXESUF) $tools" + fi + if [ "$eventfd" = "yes" ]; then tools="ivshmem-client\$(EXESUF) ivshmem-server\$(EXESUF) $tools" fi fi diff --git a/contrib/ivshmem-client/Makefile.objs b/contrib/ivshmem-client/Makefile.objs index bfab2d20dd..13d864082d 100644 --- a/contrib/ivshmem-client/Makefile.objs +++ b/contrib/ivshmem-client/Makefile.objs @@ -1 +1 @@ -ivshmem-client-obj-y = ivshmem-client.o main.o +ivshmem-client-obj-$(CONFIG_IVSHMEM) = ivshmem-client.o main.o diff --git a/contrib/ivshmem-server/Makefile.objs b/contrib/ivshmem-server/Makefile.objs index c060dd3698..d9469fd777 100644 --- a/contrib/ivshmem-server/Makefile.objs +++ b/contrib/ivshmem-server/Makefile.objs @@ -1 +1 @@ -ivshmem-server-obj-y = ivshmem-server.o main.o +ivshmem-server-obj-$(CONFIG_IVSHMEM) = ivshmem-server.o main.o -- 2.11.0
[Qemu-devel] [PULL 16/22] scsi/lsi53c895a: Remove unused lsi_mem_*() return value
From: Mao Zhongyi lsi_mem_read/write() always return 0 about which their callers actually don't care. Change the function type to void. Signed-off-by: Mao Zhongyi Signed-off-by: Michael Tokarev --- hw/scsi/lsi53c895a.c | 10 -- 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c index 595c26017a..3e56ab267c 100644 --- a/hw/scsi/lsi53c895a.c +++ b/hw/scsi/lsi53c895a.c @@ -408,27 +408,25 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val); static void lsi_execute_script(LSIState *s); static void lsi_reselect(LSIState *s, lsi_request *p); -static inline int lsi_mem_read(LSIState *s, dma_addr_t addr, +static inline void lsi_mem_read(LSIState *s, dma_addr_t addr, void *buf, dma_addr_t len) { if (s->dmode & LSI_DMODE_SIOM) { address_space_read(&s->pci_io_as, addr, MEMTXATTRS_UNSPECIFIED, buf, len); -return 0; } else { -return pci_dma_read(PCI_DEVICE(s), addr, buf, len); +pci_dma_read(PCI_DEVICE(s), addr, buf, len); } } -static inline int lsi_mem_write(LSIState *s, dma_addr_t addr, +static inline void lsi_mem_write(LSIState *s, dma_addr_t addr, const void *buf, dma_addr_t len) { if (s->dmode & LSI_DMODE_DIOM) { address_space_write(&s->pci_io_as, addr, MEMTXATTRS_UNSPECIFIED, buf, len); -return 0; } else { -return pci_dma_write(PCI_DEVICE(s), addr, buf, len); +pci_dma_write(PCI_DEVICE(s), addr, buf, len); } } -- 2.11.0
[Qemu-devel] [PULL 09/22] block: Correct documentation for BLOCK_WRITE_THRESHOLD
From: Eric Blake Use the correct command name. Signed-off-by: Eric Blake Signed-off-by: Michael Tokarev --- qapi/block-core.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qapi/block-core.json b/qapi/block-core.json index ea0b3e8b13..309b1df214 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -3624,7 +3624,7 @@ # means the device should be extended to avoid pausing for # disk exhaustion. # The event is one shot. Once triggered, it needs to be -# re-registered with another block-set-threshold command. +# re-registered with another block-set-write-threshold command. # # @node-name: graph node name on which the threshold was exceeded. # -- 2.11.0
[Qemu-devel] [PULL 12/22] hw/sparc: use ARRAY_SIZE() macro
From: Philippe Mathieu-Daudé Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alex Bennée Signed-off-by: Michael Tokarev --- hw/sparc64/sun4u.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index 18b8f8bcba..69f565db25 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -214,7 +214,7 @@ static void isa_irq_handler(void *opaque, int n, int level) qemu_irq *irqs = opaque; int ivec; -assert(n < 16); +assert(n < ARRAY_SIZE(isa_irq_to_ivec)); ivec = isa_irq_to_ivec[n]; EBUS_DPRINTF("Set ISA IRQ %d level %d -> ivec 0x%x\n", n, level, ivec); if (ivec) { -- 2.11.0
Re: [Qemu-devel] [PATCH v1] target/s390x: addressing exceptions are suppressing
On 05/29/2017 05:12 AM, David Hildenbrand wrote: We have to make the address in the old PSW point at the next instruction, as addressing exceptions are suppressing and not nullifying. I assume that there are a lot of other broken cases (as most instructions we care about are suppressing) - all trigger_pgm_exception() specifying and explicit number or ILEN_LATER look suspicious, however this is another story that might require bigger changes (and I have to understand when the address might already have been incremented first). This is needed to make an upcoming kvm-unit-test work. Signed-off-by: David Hildenbrand --- target/s390x/helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) Applied, thanks. r~
[Qemu-devel] [PULL 00/69] target/s390x tcg patches
The queue has gotten overlong. This includes my unwinding patches, the execute rewrite, and Aurelien's flushing out of missing Z insns. It does *not* include Aurelian's final patch to bump the base tcg cpu to z800. David Hildenbrand had objections to that; I expect that we can address that in the next patch set. r~ The following changes since commit c6e84fbd447a51e1161d74d71566a5f67b47eac5: Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging (2017-06-02 17:46:22 +0100) are available in the git repository at: git://github.com/rth7680/qemu.git tags/pull-s390-20170604 for you to fetch changes up to 2be5fdbe14165d47a88054c9d117801e09239098: target/s390x: addressing exceptions are suppressing (2017-06-04 10:23:15 -0700) Queued s390x tcg patches Aurelien Jarno (29): target/s390x: remove dead code in translate.c target/s390x: remove some Linux assumptions from IPTE target/s390x: implement local-TLB-clearing in IPTE target/s390x: implement TEST AND SET target/s390x: implement TEST ADDRESSING MODE target/s390x: implement PACK target/s390x: implement LOAD PAIR FROM QUADWORD target/s390x: implement STORE PAIR TO QUADWORD target/s390x: implement COMPARE AND SIGNAL target/s390x: implement MOVE INVERSE target/s390x: implement MOVE NUMERICS target/s390x: implement MOVE WITH OFFSET target/s390x: implement MOVE ZONES target/s390x: improve 24-bit and 31-bit addresses read target/s390x: improve 24-bit and 31-bit addresses write target/s390x: improve 24-bit and 31-bit lengths read/write target/s390x: fix COMPARE LOGICAL LONG EXTENDED target/s390x: implement COMPARE LOGICAL LONG target/s390x: fix adj_len_to_page target/s390x: improve MOVE LONG and MOVE LONG EXTENDED target/s390x: implement COMPARE LOGICAL LONG UNICODE target/s390x: implement MOVE LONG UNICODE target/s390x: implement PACK ASCII target/s390x: implement PACK UNICODE target/s390x: implement UNPACK ASCII target/s390x: implement UNPACK UNICODE target/s390x: implement TEST DECIMAL target/s390x: implement TRANSLATE ONE/TWO TO ONE/TWO target/s390x: mark ETF2 and ETF2-ENH facilities as available David Hildenbrand (1): target/s390x: addressing exceptions are suppressing Richard Henderson (37): target/s390x: Use cpu_loop_exit_restore for tlb_fill target/s390x: Move helper_ex to end of file target/s390x: Use unwind data for helper_nc target/s390x: Use unwind data for helper_oc target/s390x: Use unwind data for helper_xc target/s390x: Use unwind data for helper_mvc target/s390x: Use unwind data for helper_clc target/s390x: Use unwind data for helper_clm target/s390x: Use unwind data for helper_srst target/s390x: Use unwind data for helper_clst target/s390x: Use unwind data for helper_mvpg target/s390x: Use unwind data for helper_mvst target/s390x: Use unwind data for helper_lam target/s390x: Use unwind data for helper_stam target/s390x: Use unwind data for helper_mvcl target/s390x: Use unwind data for helper_mvcle target/s390x: Use unwind data for helper_clcle target/s390x: Use unwind data for helper_cksm target/s390x: Use unwind data for helper_unpk target/s390x: Use unwind data for helper_tr target/s390x: Use unwind data for helper_tre target/s390x: Use unwind data for helper_trt target/s390x: Use unwind data for helper_lctlg target/s390x: Use unwind data for helper_lctl target/s390x: Use unwind data for helper_stctl target/s390x: Use unwind data for helper_testblock target/s390x: Use unwind data for helper_tprot target/s390x: Use unwind data for helper_lra target/s390x: Use unwind data for helper_mvcs/mvcp target/s390x: Fix some helper_ex problems target/s390x: Fix EXECUTE with R1==0 target/s390x: Use atomic operations for COMPARE SWAP PURGE target/s390x: Implement CSPG target/s390x: Save current ilen during translation target/s390x: End the TB after EXECUTE target/s390x: Implement EXECUTE via new TranslationBlock target/s390x: Re-implement a few EXECUTE target insns directly Thomas Huth (2): target/s390x: Add support for the TEST BLOCK instruction target/s390x/cpu_models: Allow some additional feature bits for the "qemu" CPU target/s390x/cpu.h |7 +- target/s390x/cpu_models.c | 36 +- target/s390x/fpu_helper.c | 27 + target/s390x/helper.c |7 +- target/s390x/helper.h | 28 +- target/s390x/insn-data.def | 66 ++- target/s390x/machine.c | 19 + target/s390x/mem_helper.c | 1297
[Qemu-devel] [PULL 01/69] target/s390x: Add support for the TEST BLOCK instruction
From: Thomas Huth TEST BLOCK was likely once used to execute basic memory tests, but nowadays it's just a (slow) way to clear a page. Reviewed-by: Aurelien Jarno Reviewed-by: David Hildenbrand Reviewed-by: Richard Henderson Signed-off-by: Thomas Huth Message-Id: <1495128400-23759-1-git-send-email-th...@redhat.com> Signed-off-by: Richard Henderson --- target/s390x/cpu.h | 1 + target/s390x/helper.h | 1 + target/s390x/insn-data.def | 2 ++ target/s390x/mem_helper.c | 28 target/s390x/mmu_helper.c | 2 +- target/s390x/translate.c | 11 +++ 6 files changed, 44 insertions(+), 1 deletion(-) diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h index c74b419..f463113 100644 --- a/target/s390x/cpu.h +++ b/target/s390x/cpu.h @@ -1084,6 +1084,7 @@ struct sysib_322 { #define SIGP_ORDER_MASK 0x00ff void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr); +target_ulong mmu_real2abs(CPUS390XState *env, target_ulong raddr); int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc, target_ulong *raddr, int *flags, bool exc); int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code); diff --git a/target/s390x/helper.h b/target/s390x/helper.h index 0b70770..1fae191 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -102,6 +102,7 @@ DEF_HELPER_FLAGS_4(lctl, TCG_CALL_NO_WG, void, env, i32, i64, i32) DEF_HELPER_FLAGS_4(lctlg, TCG_CALL_NO_WG, void, env, i32, i64, i32) DEF_HELPER_FLAGS_4(stctl, TCG_CALL_NO_WG, void, env, i32, i64, i32) DEF_HELPER_FLAGS_4(stctg, TCG_CALL_NO_WG, void, env, i32, i64, i32) +DEF_HELPER_FLAGS_2(testblock, TCG_CALL_NO_WG, i32, env, i64) DEF_HELPER_FLAGS_2(tprot, TCG_CALL_NO_RWG, i32, i64, i64) DEF_HELPER_FLAGS_2(iske, TCG_CALL_NO_RWG_SE, i64, env, i64) DEF_HELPER_FLAGS_3(sske, TCG_CALL_NO_RWG, void, env, i64, i64) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 55a7c52..cac0f51 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -918,6 +918,8 @@ /* STORE USING REAL ADDRESS */ C(0xb246, STURA, RRE, Z, r1_o, r2_o, 0, 0, stura, 0) C(0xb925, STURG, RRE, Z, r1_o, r2_o, 0, 0, sturg, 0) +/* TEST BLOCK */ +C(0xb22c, TB, RRE, Z, 0, r2_o, 0, 0, testblock, 0) /* TEST PROTECTION */ C(0xe501, TPROT, SSE, Z, la1, a2, 0, 0, tprot, 0) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index f6e5bce..0c6a0d9 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -20,6 +20,7 @@ #include "qemu/osdep.h" #include "cpu.h" +#include "exec/address-spaces.h" #include "exec/helper-proto.h" #include "exec/exec-all.h" #include "exec/cpu_ldst.h" @@ -973,6 +974,33 @@ void HELPER(stctl)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) } } +uint32_t HELPER(testblock)(CPUS390XState *env, uint64_t real_addr) +{ +CPUState *cs = CPU(s390_env_get_cpu(env)); +uint64_t abs_addr; +int i; + +real_addr = fix_address(env, real_addr); +abs_addr = mmu_real2abs(env, real_addr) & TARGET_PAGE_MASK; +if (!address_space_access_valid(&address_space_memory, abs_addr, +TARGET_PAGE_SIZE, true)) { +program_interrupt(env, PGM_ADDRESSING, 4); +return 1; +} + +/* Check low-address protection */ +if ((env->cregs[0] & CR0_LOWPROT) && real_addr < 0x2000) { +program_interrupt(env, PGM_PROTECTION, 4); +return 1; +} + +for (i = 0; i < TARGET_PAGE_SIZE; i += 8) { +stq_phys(cs->as, abs_addr + i, 0); +} + +return 0; +} + uint32_t HELPER(tprot)(uint64_t a1, uint64_t a2) { /* XXX implement */ diff --git a/target/s390x/mmu_helper.c b/target/s390x/mmu_helper.c index b11a027..31eb9ef 100644 --- a/target/s390x/mmu_helper.c +++ b/target/s390x/mmu_helper.c @@ -108,7 +108,7 @@ static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr, * Translate real address to absolute (= physical) * address by taking care of the prefix mapping. */ -static target_ulong mmu_real2abs(CPUS390XState *env, target_ulong raddr) +target_ulong mmu_real2abs(CPUS390XState *env, target_ulong raddr) { if (raddr < 0x2000) { return raddr + env->psa;/* Map the lowcore. */ diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 4c48c59..d6736e4 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -4057,6 +4057,16 @@ static ExitStatus op_tcxb(DisasContext *s, DisasOps *o) } #ifndef CONFIG_USER_ONLY + +static ExitStatus op_testblock(DisasContext *s, DisasOps *o) +{ +check_privileged(s); +potential_page_fault(s); +gen_helper_testblock(cc_op, cpu_env, o->in2); +set_cc_static(s); +return NO_EXIT; +} + static ExitStatus op_tprot(DisasContext *s, DisasOps *o) { potential_page_fault(s); @@ -4064,6 +4074,7 @@ static ExitStatus op_tprot(DisasContext *s, DisasOps *o)
[Qemu-devel] [PULL 02/69] target/s390x: Use cpu_loop_exit_restore for tlb_fill
Reviewed-by: Thomas Huth Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 10 ++ 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 0c6a0d9..e3325a4 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -41,15 +41,9 @@ void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) { -int ret; - -ret = s390_cpu_handle_mmu_fault(cs, addr, access_type, mmu_idx); +int ret = s390_cpu_handle_mmu_fault(cs, addr, access_type, mmu_idx); if (unlikely(ret != 0)) { -if (likely(retaddr)) { -/* now we have a real cpu fault */ -cpu_restore_state(cs, retaddr); -} -cpu_loop_exit(cs); +cpu_loop_exit_restore(cs, retaddr); } } -- 2.9.4
[Qemu-devel] [PULL 08/69] target/s390x: Use unwind data for helper_clc
Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 29 + target/s390x/translate.c | 1 - 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 78a9ac1..50689bb 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -233,32 +233,37 @@ void HELPER(mvc)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) } /* compare unsigned byte arrays */ -uint32_t HELPER(clc)(CPUS390XState *env, uint32_t l, uint64_t s1, uint64_t s2) +static uint32_t do_helper_clc(CPUS390XState *env, uint32_t l, uint64_t s1, + uint64_t s2, uintptr_t ra) { -int i; -unsigned char x, y; -uint32_t cc; +uint32_t i; +uint32_t cc = 0; HELPER_LOG("%s l %d s1 %" PRIx64 " s2 %" PRIx64 "\n", __func__, l, s1, s2); + for (i = 0; i <= l; i++) { -x = cpu_ldub_data(env, s1 + i); -y = cpu_ldub_data(env, s2 + i); +uint8_t x = cpu_ldub_data_ra(env, s1 + i, ra); +uint8_t y = cpu_ldub_data_ra(env, s2 + i, ra); HELPER_LOG("%02x (%c)/%02x (%c) ", x, x, y, y); if (x < y) { cc = 1; -goto done; +break; } else if (x > y) { cc = 2; -goto done; +break; } } -cc = 0; - done: + HELPER_LOG("\n"); return cc; } +uint32_t HELPER(clc)(CPUS390XState *env, uint32_t l, uint64_t s1, uint64_t s2) +{ +return do_helper_clc(env, l, s1, s2, GETPC()); +} + /* compare logical under mask */ uint32_t HELPER(clm)(CPUS390XState *env, uint32_t r1, uint32_t mask, uint64_t addr) @@ -1237,8 +1242,8 @@ uint32_t HELPER(ex)(CPUS390XState *env, uint32_t cc, uint64_t v1, get_address(env, 0, b2, d2), 0); break; case 0x500: -cc = helper_clc(env, l, get_address(env, 0, b1, d1), -get_address(env, 0, b2, d2)); +cc = do_helper_clc(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2), 0); break; case 0x600: cc = do_helper_oc(env, l, get_address(env, 0, b1, d1), diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 729924a..0f9148a 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -1901,7 +1901,6 @@ static ExitStatus op_clc(DisasContext *s, DisasOps *o) tcg_gen_qemu_ld64(cc_dst, o->in2, get_mem_index(s)); break; default: -potential_page_fault(s); vl = tcg_const_i32(l); gen_helper_clc(cc_op, cpu_env, vl, o->addr1, o->in2); tcg_temp_free_i32(vl); -- 2.9.4
[Qemu-devel] [PULL 03/69] target/s390x: Move helper_ex to end of file
This will avoid needing forward declarations in following patches. Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 161 +++--- 1 file changed, 81 insertions(+), 80 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index e3325a4..90b62fa 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -436,86 +436,6 @@ static uint32_t helper_icm(CPUS390XState *env, uint32_t r1, uint64_t address, return cc; } -/* execute instruction - this instruction executes an insn modified with the contents of r1 - it does not change the executed instruction in memory - it does not change the program counter - in other words: tricky... - currently implemented by interpreting the cases it is most commonly used in -*/ -uint32_t HELPER(ex)(CPUS390XState *env, uint32_t cc, uint64_t v1, -uint64_t addr, uint64_t ret) -{ -S390CPU *cpu = s390_env_get_cpu(env); -uint16_t insn = cpu_lduw_code(env, addr); - -HELPER_LOG("%s: v1 0x%lx addr 0x%lx insn 0x%x\n", __func__, v1, addr, - insn); -if ((insn & 0xf0ff) == 0xd000) { -uint32_t l, insn2, b1, b2, d1, d2; - -l = v1 & 0xff; -insn2 = cpu_ldl_code(env, addr + 2); -b1 = (insn2 >> 28) & 0xf; -b2 = (insn2 >> 12) & 0xf; -d1 = (insn2 >> 16) & 0xfff; -d2 = insn2 & 0xfff; -switch (insn & 0xf00) { -case 0x200: -helper_mvc(env, l, get_address(env, 0, b1, d1), - get_address(env, 0, b2, d2)); -break; -case 0x400: -cc = helper_nc(env, l, get_address(env, 0, b1, d1), -get_address(env, 0, b2, d2)); -break; -case 0x500: -cc = helper_clc(env, l, get_address(env, 0, b1, d1), -get_address(env, 0, b2, d2)); -break; -case 0x600: -cc = helper_oc(env, l, get_address(env, 0, b1, d1), -get_address(env, 0, b2, d2)); -break; -case 0x700: -cc = helper_xc(env, l, get_address(env, 0, b1, d1), - get_address(env, 0, b2, d2)); -break; -case 0xc00: -helper_tr(env, l, get_address(env, 0, b1, d1), - get_address(env, 0, b2, d2)); -break; -case 0xd00: -cc = helper_trt(env, l, get_address(env, 0, b1, d1), -get_address(env, 0, b2, d2)); -break; -default: -goto abort; -} -} else if ((insn & 0xff00) == 0x0a00) { -/* supervisor call */ -HELPER_LOG("%s: svc %ld via execute\n", __func__, (insn | v1) & 0xff); -env->psw.addr = ret - 4; -env->int_svc_code = (insn | v1) & 0xff; -env->int_svc_ilen = 4; -helper_exception(env, EXCP_SVC); -} else if ((insn & 0xff00) == 0xbf00) { -uint32_t insn2, r1, r3, b2, d2; - -insn2 = cpu_ldl_code(env, addr + 2); -r1 = (insn2 >> 20) & 0xf; -r3 = (insn2 >> 16) & 0xf; -b2 = (insn2 >> 12) & 0xf; -d2 = insn2 & 0xfff; -cc = helper_icm(env, r1, get_address(env, 0, b2, d2), r3); -} else { -abort: -cpu_abort(CPU(cpu), "EXECUTE on instruction prefix 0x%x not implemented\n", - insn); -} -return cc; -} - /* load access registers r1 to r3 from memory at a2 */ void HELPER(lam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { @@ -1262,3 +1182,84 @@ uint64_t HELPER(lra)(CPUS390XState *env, uint64_t addr) return ret; } #endif + +/* execute instruction + this instruction executes an insn modified with the contents of r1 + it does not change the executed instruction in memory + it does not change the program counter + in other words: tricky... + currently implemented by interpreting the cases it is most commonly used. +*/ +uint32_t HELPER(ex)(CPUS390XState *env, uint32_t cc, uint64_t v1, +uint64_t addr, uint64_t ret) +{ +S390CPU *cpu = s390_env_get_cpu(env); +uint16_t insn = cpu_lduw_code(env, addr); + +HELPER_LOG("%s: v1 0x%lx addr 0x%lx insn 0x%x\n", __func__, v1, addr, + insn); +if ((insn & 0xf0ff) == 0xd000) { +uint32_t l, insn2, b1, b2, d1, d2; + +l = v1 & 0xff; +insn2 = cpu_ldl_code(env, addr + 2); +b1 = (insn2 >> 28) & 0xf; +b2 = (insn2 >> 12) & 0xf; +d1 = (insn2 >> 16) & 0xfff; +d2 = insn2 & 0xfff; +switch (insn & 0xf00) { +case 0x200: +helper_mvc(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2)); +break; +case 0x400: +cc = helper_nc(env, l, get_address(env, 0, b1, d1), +get_address(env, 0, b2, d2)); +br
[Qemu-devel] [PULL 11/69] target/s390x: Use unwind data for helper_clst
Reviewed-by: Thomas Huth Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 5 +++-- target/s390x/translate.c | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 33d83e5..af2801e 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -362,6 +362,7 @@ uint64_t HELPER(srst)(CPUS390XState *env, uint64_t r0, uint64_t end, /* unsigned string compare (c is string terminator) */ uint64_t HELPER(clst)(CPUS390XState *env, uint64_t c, uint64_t s1, uint64_t s2) { +uintptr_t ra = GETPC(); uint32_t len; c = c & 0xff; @@ -371,8 +372,8 @@ uint64_t HELPER(clst)(CPUS390XState *env, uint64_t c, uint64_t s1, uint64_t s2) /* Lest we fail to service interrupts in a timely manner, limit the amount of work we're willing to do. For now, let's cap at 8k. */ for (len = 0; len < 0x2000; ++len) { -uint8_t v1 = cpu_ldub_data(env, s1 + len); -uint8_t v2 = cpu_ldub_data(env, s2 + len); +uint8_t v1 = cpu_ldub_data_ra(env, s1 + len, ra); +uint8_t v2 = cpu_ldub_data_ra(env, s2 + len, ra); if (v1 == v2) { if (v1 == c) { /* Equal. CC=0, and don't advance the registers. */ diff --git a/target/s390x/translate.c b/target/s390x/translate.c index cd33c51..a24e288 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -1937,7 +1937,6 @@ static ExitStatus op_clm(DisasContext *s, DisasOps *o) static ExitStatus op_clst(DisasContext *s, DisasOps *o) { -potential_page_fault(s); gen_helper_clst(o->in1, cpu_env, regs[0], o->in1, o->in2); set_cc_static(s); return_low128(o->in2); -- 2.9.4
[Qemu-devel] [PULL 16/69] target/s390x: Use unwind data for helper_mvcl
Reviewed-by: Thomas Huth Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 7 --- target/s390x/translate.c | 1 - 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 2acc984..49cfc9b 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -501,6 +501,7 @@ void HELPER(stam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) /* move long */ uint32_t HELPER(mvcl)(CPUS390XState *env, uint32_t r1, uint32_t r2) { +uintptr_t ra = GETPC(); uint64_t destlen = env->regs[r1 + 1] & 0xff; uint64_t dest = get_address_31fix(env, r1); uint64_t srclen = env->regs[r2 + 1] & 0xff; @@ -522,12 +523,12 @@ uint32_t HELPER(mvcl)(CPUS390XState *env, uint32_t r1, uint32_t r2) } for (; destlen && srclen; src++, dest++, destlen--, srclen--) { -v = cpu_ldub_data(env, src); -cpu_stb_data(env, dest, v); +v = cpu_ldub_data_ra(env, src, ra); +cpu_stb_data_ra(env, dest, v, ra); } for (; destlen; dest++, destlen--) { -cpu_stb_data(env, dest, pad); +cpu_stb_data_ra(env, dest, pad, ra); } env->regs[r1 + 1] = destlen; diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 7af2a0b..fb2d6ff 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2871,7 +2871,6 @@ static ExitStatus op_mvcl(DisasContext *s, DisasOps *o) { TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2)); -potential_page_fault(s); gen_helper_mvcl(cc_op, cpu_env, r1, r2); tcg_temp_free_i32(r1); tcg_temp_free_i32(r2); -- 2.9.4
[Qemu-devel] [PULL 04/69] target/s390x: Use unwind data for helper_nc
Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 31 ++- target/s390x/translate.c | 1 - 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 90b62fa..7d6133b 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -119,23 +119,28 @@ static void fast_memmove(CPUS390XState *env, uint64_t dest, uint64_t src, } /* and on array */ -uint32_t HELPER(nc)(CPUS390XState *env, uint32_t l, uint64_t dest, -uint64_t src) +static uint32_t do_helper_nc(CPUS390XState *env, uint32_t l, uint64_t dest, + uint64_t src, uintptr_t ra) { -int i; -unsigned char x; -uint32_t cc = 0; +uint32_t i; +uint8_t c = 0; HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n", __func__, l, dest, src); + for (i = 0; i <= l; i++) { -x = cpu_ldub_data(env, dest + i) & cpu_ldub_data(env, src + i); -if (x) { -cc = 1; -} -cpu_stb_data(env, dest + i, x); +uint8_t x = cpu_ldub_data_ra(env, src + i, ra); +x &= cpu_ldub_data_ra(env, dest + i, ra); +c |= x; +cpu_stb_data_ra(env, dest + i, x, ra); } -return cc; +return c != 0; +} + +uint32_t HELPER(nc)(CPUS390XState *env, uint32_t l, uint64_t dest, +uint64_t src) +{ +return do_helper_nc(env, l, dest, src, GETPC()); } /* xor on array */ @@ -1213,8 +1218,8 @@ uint32_t HELPER(ex)(CPUS390XState *env, uint32_t cc, uint64_t v1, get_address(env, 0, b2, d2)); break; case 0x400: -cc = helper_nc(env, l, get_address(env, 0, b1, d1), -get_address(env, 0, b2, d2)); +cc = do_helper_nc(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2), 0); break; case 0x500: cc = helper_clc(env, l, get_address(env, 0, b1, d1), diff --git a/target/s390x/translate.c b/target/s390x/translate.c index d6736e4..7e4cc6c 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -3043,7 +3043,6 @@ static ExitStatus op_nabsf128(DisasContext *s, DisasOps *o) static ExitStatus op_nc(DisasContext *s, DisasOps *o) { TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); -potential_page_fault(s); gen_helper_nc(cc_op, cpu_env, l, o->addr1, o->in2); tcg_temp_free_i32(l); set_cc_static(s); -- 2.9.4
[Qemu-devel] [PULL 07/69] target/s390x: Use unwind data for helper_mvc
Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 30 ++ target/s390x/translate.c | 1 - 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index b71437a..78a9ac1 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -91,7 +91,7 @@ static void fast_memset(CPUS390XState *env, uint64_t dest, uint8_t byte, } static void fast_memmove(CPUS390XState *env, uint64_t dest, uint64_t src, - uint32_t l) + uint32_t l, uintptr_t ra) { int mmu_idx = cpu_mmu_index(env, false); @@ -110,7 +110,7 @@ static void fast_memmove(CPUS390XState *env, uint64_t dest, uint64_t src, /* We failed to get access to one or both whole pages. The next read or write access will likely fill the QEMU TLB for the next iteration. */ -cpu_stb_data(env, dest, cpu_ldub_data(env, src)); +cpu_stb_data_ra(env, dest, cpu_ldub_data_ra(env, src, ra), ra); src++; dest++; l--; @@ -200,32 +200,38 @@ uint32_t HELPER(oc)(CPUS390XState *env, uint32_t l, uint64_t dest, } /* memmove */ -void HELPER(mvc)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) +static void do_helper_mvc(CPUS390XState *env, uint32_t l, uint64_t dest, + uint64_t src, uintptr_t ra) { -int i = 0; +uint32_t i; HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n", __func__, l, dest, src); /* mvc with source pointing to the byte after the destination is the same as memset with the first source byte */ -if (dest == (src + 1)) { -fast_memset(env, dest, cpu_ldub_data(env, src), l + 1, 0); +if (dest == src + 1) { +fast_memset(env, dest, cpu_ldub_data_ra(env, src, ra), l + 1, ra); return; } /* mvc and memmove do not behave the same when areas overlap! */ -if ((dest < src) || (src + l < dest)) { -fast_memmove(env, dest, src, l + 1); +if (dest < src || src + l < dest) { +fast_memmove(env, dest, src, l + 1, ra); return; } /* slow version with byte accesses which always work */ for (i = 0; i <= l; i++) { -cpu_stb_data(env, dest + i, cpu_ldub_data(env, src + i)); +cpu_stb_data_ra(env, dest + i, cpu_ldub_data_ra(env, src + i, ra), ra); } } +void HELPER(mvc)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) +{ +do_helper_mvc(env, l, dest, src, GETPC()); +} + /* compare unsigned byte arrays */ uint32_t HELPER(clc)(CPUS390XState *env, uint32_t l, uint64_t s1, uint64_t s2) { @@ -388,7 +394,7 @@ void HELPER(mvpg)(CPUS390XState *env, uint64_t r0, uint64_t r1, uint64_t r2) { /* XXX missing r0 handling */ env->cc_op = 0; -fast_memmove(env, r1, r2, TARGET_PAGE_SIZE); +fast_memmove(env, r1, r2, TARGET_PAGE_SIZE, 0); } /* string copy (c is string terminator) */ @@ -1223,8 +1229,8 @@ uint32_t HELPER(ex)(CPUS390XState *env, uint32_t cc, uint64_t v1, d2 = insn2 & 0xfff; switch (insn & 0xf00) { case 0x200: -helper_mvc(env, l, get_address(env, 0, b1, d1), - get_address(env, 0, b2, d2)); +do_helper_mvc(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2), 0); break; case 0x400: cc = do_helper_nc(env, l, get_address(env, 0, b1, d1), diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 40a4099..729924a 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2866,7 +2866,6 @@ static ExitStatus op_movx(DisasContext *s, DisasOps *o) static ExitStatus op_mvc(DisasContext *s, DisasOps *o) { TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); -potential_page_fault(s); gen_helper_mvc(cpu_env, l, o->addr1, o->in2); tcg_temp_free_i32(l); return NO_EXIT; -- 2.9.4
[Qemu-devel] [PULL 05/69] target/s390x: Use unwind data for helper_oc
Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 31 ++- target/s390x/translate.c | 1 - 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 7d6133b..b4b50d1 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -171,23 +171,28 @@ uint32_t HELPER(xc)(CPUS390XState *env, uint32_t l, uint64_t dest, } /* or on array */ -uint32_t HELPER(oc)(CPUS390XState *env, uint32_t l, uint64_t dest, -uint64_t src) +static uint32_t do_helper_oc(CPUS390XState *env, uint32_t l, uint64_t dest, + uint64_t src, uintptr_t ra) { -int i; -unsigned char x; -uint32_t cc = 0; +uint32_t i; +uint8_t c = 0; HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n", __func__, l, dest, src); + for (i = 0; i <= l; i++) { -x = cpu_ldub_data(env, dest + i) | cpu_ldub_data(env, src + i); -if (x) { -cc = 1; -} -cpu_stb_data(env, dest + i, x); +uint8_t x = cpu_ldub_data_ra(env, src + i, ra); +x |= cpu_ldub_data_ra(env, dest + i, ra); +c |= x; +cpu_stb_data_ra(env, dest + i, x, ra); } -return cc; +return c != 0; +} + +uint32_t HELPER(oc)(CPUS390XState *env, uint32_t l, uint64_t dest, +uint64_t src) +{ +return do_helper_oc(env, l, dest, src, GETPC()); } /* memmove */ @@ -1226,8 +1231,8 @@ uint32_t HELPER(ex)(CPUS390XState *env, uint32_t cc, uint64_t v1, get_address(env, 0, b2, d2)); break; case 0x600: -cc = helper_oc(env, l, get_address(env, 0, b1, d1), -get_address(env, 0, b2, d2)); +cc = do_helper_oc(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2), 0); break; case 0x700: cc = helper_xc(env, l, get_address(env, 0, b1, d1), diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 7e4cc6c..db86b70 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -3077,7 +3077,6 @@ static ExitStatus op_negf128(DisasContext *s, DisasOps *o) static ExitStatus op_oc(DisasContext *s, DisasOps *o) { TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); -potential_page_fault(s); gen_helper_oc(cc_op, cpu_env, l, o->addr1, o->in2); tcg_temp_free_i32(l); set_cc_static(s); -- 2.9.4
[Qemu-devel] [PULL 17/69] target/s390x: Use unwind data for helper_mvcle
Reviewed-by: Thomas Huth Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 7 --- target/s390x/translate.c | 1 - 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 49cfc9b..8a095ad 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -544,6 +544,7 @@ uint32_t HELPER(mvcl)(CPUS390XState *env, uint32_t r1, uint32_t r2) uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { +uintptr_t ra = GETPC(); uint64_t destlen = env->regs[r1 + 1]; uint64_t dest = env->regs[r1]; uint64_t srclen = env->regs[r3 + 1]; @@ -572,12 +573,12 @@ uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, } for (; destlen && srclen; src++, dest++, destlen--, srclen--) { -v = cpu_ldub_data(env, src); -cpu_stb_data(env, dest, v); +v = cpu_ldub_data_ra(env, src, ra); +cpu_stb_data_ra(env, dest, v, ra); } for (; destlen; dest++, destlen--) { -cpu_stb_data(env, dest, pad); +cpu_stb_data_ra(env, dest, pad, ra); } env->regs[r1 + 1] = destlen; diff --git a/target/s390x/translate.c b/target/s390x/translate.c index fb2d6ff..b42acae 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2882,7 +2882,6 @@ static ExitStatus op_mvcle(DisasContext *s, DisasOps *o) { TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); -potential_page_fault(s); gen_helper_mvcle(cc_op, cpu_env, r1, o->in2, r3); tcg_temp_free_i32(r1); tcg_temp_free_i32(r3); -- 2.9.4
[Qemu-devel] [PULL 19/69] target/s390x: Use unwind data for helper_cksm
Reviewed-by: Thomas Huth Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 11 ++- target/s390x/translate.c | 1 - 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index f5a3044..d4ee364 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -633,6 +633,7 @@ uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint64_t HELPER(cksm)(CPUS390XState *env, uint64_t r1, uint64_t src, uint64_t src_len) { +uintptr_t ra = GETPC(); uint64_t max_len, len; uint64_t cksm = (uint32_t)r1; @@ -642,21 +643,21 @@ uint64_t HELPER(cksm)(CPUS390XState *env, uint64_t r1, /* Process full words as available. */ for (len = 0; len + 4 <= max_len; len += 4, src += 4) { -cksm += (uint32_t)cpu_ldl_data(env, src); +cksm += (uint32_t)cpu_ldl_data_ra(env, src, ra); } switch (max_len - len) { case 1: -cksm += cpu_ldub_data(env, src) << 24; +cksm += cpu_ldub_data_ra(env, src, ra) << 24; len += 1; break; case 2: -cksm += cpu_lduw_data(env, src) << 16; +cksm += cpu_lduw_data_ra(env, src, ra) << 16; len += 2; break; case 3: -cksm += cpu_lduw_data(env, src) << 16; -cksm += cpu_ldub_data(env, src + 2) << 8; +cksm += cpu_lduw_data_ra(env, src, ra) << 16; +cksm += cpu_ldub_data_ra(env, src + 2, ra) << 8; len += 3; break; } diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 9270067..76910bc 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -1866,7 +1866,6 @@ static ExitStatus op_cksm(DisasContext *s, DisasOps *o) int r2 = get_field(s->fields, r2); TCGv_i64 len = tcg_temp_new_i64(); -potential_page_fault(s); gen_helper_cksm(len, cpu_env, o->in1, o->in2, regs[r2 + 1]); set_cc_static(s); return_low128(o->out); -- 2.9.4
[Qemu-devel] [PULL 21/69] target/s390x: Use unwind data for helper_tr
Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 25 +++-- target/s390x/translate.c | 1 - 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 0701e10..b37a963 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -723,19 +723,24 @@ void HELPER(unpk)(CPUS390XState *env, uint32_t len, uint64_t dest, } } -void HELPER(tr)(CPUS390XState *env, uint32_t len, uint64_t array, -uint64_t trans) +static void do_helper_tr(CPUS390XState *env, uint32_t len, uint64_t array, + uint64_t trans, uintptr_t ra) { -int i; +uint32_t i; for (i = 0; i <= len; i++) { -uint8_t byte = cpu_ldub_data(env, array + i); -uint8_t new_byte = cpu_ldub_data(env, trans + byte); - -cpu_stb_data(env, array + i, new_byte); +uint8_t byte = cpu_ldub_data_ra(env, array + i, ra); +uint8_t new_byte = cpu_ldub_data_ra(env, trans + byte, ra); +cpu_stb_data_ra(env, array + i, new_byte, ra); } } +void HELPER(tr)(CPUS390XState *env, uint32_t len, uint64_t array, +uint64_t trans) +{ +return do_helper_tr(env, len, array, trans, GETPC()); +} + uint64_t HELPER(tre)(CPUS390XState *env, uint64_t array, uint64_t len, uint64_t trans) { @@ -1265,9 +1270,9 @@ uint32_t HELPER(ex)(CPUS390XState *env, uint32_t cc, uint64_t v1, get_address(env, 0, b2, d2), 0); break; case 0xc00: -helper_tr(env, l, get_address(env, 0, b1, d1), - get_address(env, 0, b2, d2)); -break; +do_helper_tr(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2), 0); +return cc; case 0xd00: cc = helper_trt(env, l, get_address(env, 0, b1, d1), get_address(env, 0, b2, d2)); diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 4978f19..1842cc3 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -4065,7 +4065,6 @@ static ExitStatus op_tprot(DisasContext *s, DisasOps *o) static ExitStatus op_tr(DisasContext *s, DisasOps *o) { TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); -potential_page_fault(s); gen_helper_tr(cpu_env, l, o->addr1, o->in2); tcg_temp_free_i32(l); set_cc_static(s); -- 2.9.4
[Qemu-devel] [PULL 06/69] target/s390x: Use unwind data for helper_xc
Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 44 target/s390x/translate.c | 1 - 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index b4b50d1..b71437a 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -57,7 +57,7 @@ void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType access_type, #endif /* Reduce the length so that addr + len doesn't cross a page boundary. */ -static inline uint64_t adj_len_to_page(uint64_t len, uint64_t addr) +static inline uint32_t adj_len_to_page(uint32_t len, uint64_t addr) { #ifndef CONFIG_USER_ONLY if ((addr & ~TARGET_PAGE_MASK) + len - 1 >= TARGET_PAGE_SIZE) { @@ -68,7 +68,7 @@ static inline uint64_t adj_len_to_page(uint64_t len, uint64_t addr) } static void fast_memset(CPUS390XState *env, uint64_t dest, uint8_t byte, -uint32_t l) +uint32_t l, uintptr_t ra) { int mmu_idx = cpu_mmu_index(env, false); @@ -76,14 +76,14 @@ static void fast_memset(CPUS390XState *env, uint64_t dest, uint8_t byte, void *p = tlb_vaddr_to_host(env, dest, MMU_DATA_STORE, mmu_idx); if (p) { /* Access to the whole page in write mode granted. */ -int l_adj = adj_len_to_page(l, dest); +uint32_t l_adj = adj_len_to_page(l, dest); memset(p, byte, l_adj); dest += l_adj; l -= l_adj; } else { /* We failed to get access to the whole page. The next write access will likely fill the QEMU TLB for the next iteration. */ -cpu_stb_data(env, dest, byte); +cpu_stb_data_ra(env, dest, byte, ra); dest++; l--; } @@ -100,7 +100,7 @@ static void fast_memmove(CPUS390XState *env, uint64_t dest, uint64_t src, void *dest_p = tlb_vaddr_to_host(env, dest, MMU_DATA_STORE, mmu_idx); if (src_p && dest_p) { /* Access to both whole pages granted. */ -int l_adj = adj_len_to_page(l, src); +uint32_t l_adj = adj_len_to_page(l, src); l_adj = adj_len_to_page(l_adj, dest); memmove(dest_p, src_p, l_adj); src += l_adj; @@ -144,30 +144,34 @@ uint32_t HELPER(nc)(CPUS390XState *env, uint32_t l, uint64_t dest, } /* xor on array */ -uint32_t HELPER(xc)(CPUS390XState *env, uint32_t l, uint64_t dest, -uint64_t src) +static uint32_t do_helper_xc(CPUS390XState *env, uint32_t l, uint64_t dest, + uint64_t src, uintptr_t ra) { -int i; -unsigned char x; -uint32_t cc = 0; +uint32_t i; +uint8_t c = 0; HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n", __func__, l, dest, src); /* xor with itself is the same as memset(0) */ if (src == dest) { -fast_memset(env, dest, 0, l + 1); +fast_memset(env, dest, 0, l + 1, ra); return 0; } for (i = 0; i <= l; i++) { -x = cpu_ldub_data(env, dest + i) ^ cpu_ldub_data(env, src + i); -if (x) { -cc = 1; -} -cpu_stb_data(env, dest + i, x); +uint8_t x = cpu_ldub_data_ra(env, src + i, ra); +x ^= cpu_ldub_data_ra(env, dest + i, ra); +c |= x; +cpu_stb_data_ra(env, dest + i, x, ra); } -return cc; +return c != 0; +} + +uint32_t HELPER(xc)(CPUS390XState *env, uint32_t l, uint64_t dest, +uint64_t src) +{ +return do_helper_xc(env, l, dest, src, GETPC()); } /* or on array */ @@ -206,7 +210,7 @@ void HELPER(mvc)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) /* mvc with source pointing to the byte after the destination is the same as memset with the first source byte */ if (dest == (src + 1)) { -fast_memset(env, dest, cpu_ldub_data(env, src), l + 1); +fast_memset(env, dest, cpu_ldub_data(env, src), l + 1, 0); return; } @@ -1235,8 +1239,8 @@ uint32_t HELPER(ex)(CPUS390XState *env, uint32_t cc, uint64_t v1, get_address(env, 0, b2, d2), 0); break; case 0x700: -cc = helper_xc(env, l, get_address(env, 0, b1, d1), - get_address(env, 0, b2, d2)); +cc = do_helper_xc(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2), 0); break; case 0xc00: helper_tr(env, l, get_address(env, 0, b1, d1), diff --git a/target/s390x/translate.c b/target/s390x/translate.c index db86b70..40a4099 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -4160,7 +4160,6 @@ static ExitStatus op_xc(DisasContext *s, DisasOps *o) /* But in general we'll defer to a helper. */ o->in2 = get_address(s,
[Qemu-devel] [PULL 20/69] target/s390x: Use unwind data for helper_unpk
Reviewed-by: Thomas Huth Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 9 + target/s390x/translate.c | 1 - 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index d4ee364..0701e10 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -679,6 +679,7 @@ uint64_t HELPER(cksm)(CPUS390XState *env, uint64_t r1, void HELPER(unpk)(CPUS390XState *env, uint32_t len, uint64_t dest, uint64_t src) { +uintptr_t ra = GETPC(); int len_dest = len >> 4; int len_src = len & 0xf; uint8_t b; @@ -688,8 +689,8 @@ void HELPER(unpk)(CPUS390XState *env, uint32_t len, uint64_t dest, src += len_src; /* last byte is special, it only flips the nibbles */ -b = cpu_ldub_data(env, src); -cpu_stb_data(env, dest, (b << 4) | (b >> 4)); +b = cpu_ldub_data_ra(env, src, ra); +cpu_stb_data_ra(env, dest, (b << 4) | (b >> 4), ra); src--; len_src--; @@ -699,7 +700,7 @@ void HELPER(unpk)(CPUS390XState *env, uint32_t len, uint64_t dest, uint8_t cur_byte = 0; if (len_src > 0) { -cur_byte = cpu_ldub_data(env, src); +cur_byte = cpu_ldub_data_ra(env, src, ra); } len_dest--; @@ -718,7 +719,7 @@ void HELPER(unpk)(CPUS390XState *env, uint32_t len, uint64_t dest, /* zone bits */ cur_byte |= 0xf0; -cpu_stb_data(env, dest, cur_byte); +cpu_stb_data_ra(env, dest, cur_byte, ra); } } diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 76910bc..4978f19 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -4094,7 +4094,6 @@ static ExitStatus op_trt(DisasContext *s, DisasOps *o) static ExitStatus op_unpk(DisasContext *s, DisasOps *o) { TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); -potential_page_fault(s); gen_helper_unpk(cpu_env, l, o->addr1, o->in2); tcg_temp_free_i32(l); return NO_EXIT; -- 2.9.4
[Qemu-devel] [PULL 15/69] target/s390x: Use unwind data for helper_stam
Reviewed-by: Thomas Huth Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 3 ++- target/s390x/translate.c | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 88e817a..2acc984 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -485,10 +485,11 @@ void HELPER(lam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) /* store access registers r1 to r3 in memory at a2 */ void HELPER(stam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { +uintptr_t ra = GETPC(); int i; for (i = r1;; i = (i + 1) % 16) { -cpu_stl_data(env, a2, env->aregs[i]); +cpu_stl_data_ra(env, a2, env->aregs[i], ra); a2 += 4; if (i == r3) { diff --git a/target/s390x/translate.c b/target/s390x/translate.c index dca2096..7af2a0b 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -3862,7 +3862,6 @@ static ExitStatus op_stam(DisasContext *s, DisasOps *o) { TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); -potential_page_fault(s); gen_helper_stam(cpu_env, r1, o->in2, r3); tcg_temp_free_i32(r1); tcg_temp_free_i32(r3); -- 2.9.4
[Qemu-devel] [PULL 23/69] target/s390x: Use unwind data for helper_trt
Reviewed-by: Thomas Huth Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 28 target/s390x/translate.c | 1 - 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index fd6dbf7..ff12777 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -781,25 +781,29 @@ uint64_t HELPER(tre)(CPUS390XState *env, uint64_t array, return array + i; } -uint32_t HELPER(trt)(CPUS390XState *env, uint32_t len, uint64_t array, - uint64_t trans) +static uint32_t do_helper_trt(CPUS390XState *env, uint32_t len, uint64_t array, + uint64_t trans, uintptr_t ra) { -uint32_t cc = 0; -int i; +uint32_t i; for (i = 0; i <= len; i++) { -uint8_t byte = cpu_ldub_data(env, array + i); -uint8_t sbyte = cpu_ldub_data(env, trans + byte); +uint8_t byte = cpu_ldub_data_ra(env, array + i, ra); +uint8_t sbyte = cpu_ldub_data_ra(env, trans + byte, ra); if (sbyte != 0) { env->regs[1] = array + i; -env->regs[2] = (env->regs[2] & ~0xff) | sbyte; -cc = (i == len) ? 2 : 1; -break; +env->regs[2] = deposit64(env->regs[2], 0, 8, sbyte); +return (i == len) ? 2 : 1; } } -return cc; +return 0; +} + +uint32_t HELPER(trt)(CPUS390XState *env, uint32_t len, uint64_t array, + uint64_t trans) +{ +return do_helper_trt(env, len, array, trans, GETPC()); } void HELPER(cdsg)(CPUS390XState *env, uint64_t addr, @@ -1275,8 +1279,8 @@ uint32_t HELPER(ex)(CPUS390XState *env, uint32_t cc, uint64_t v1, get_address(env, 0, b2, d2), 0); return cc; case 0xd00: -cc = helper_trt(env, l, get_address(env, 0, b1, d1), -get_address(env, 0, b2, d2)); +cc = do_helper_trt(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2), 0); break; default: goto abort; diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 447ba07..fed9f17 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -4082,7 +4082,6 @@ static ExitStatus op_tre(DisasContext *s, DisasOps *o) static ExitStatus op_trt(DisasContext *s, DisasOps *o) { TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); -potential_page_fault(s); gen_helper_trt(cc_op, cpu_env, l, o->addr1, o->in2); tcg_temp_free_i32(l); set_cc_static(s); -- 2.9.4
[Qemu-devel] [PULL 09/69] target/s390x: Use unwind data for helper_clm
Reviewed-by: Thomas Huth Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 11 ++- target/s390x/translate.c | 1 - 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 50689bb..3e75cae 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -268,16 +268,16 @@ uint32_t HELPER(clc)(CPUS390XState *env, uint32_t l, uint64_t s1, uint64_t s2) uint32_t HELPER(clm)(CPUS390XState *env, uint32_t r1, uint32_t mask, uint64_t addr) { -uint8_t r, d; -uint32_t cc; +uintptr_t ra = GETPC(); +uint32_t cc = 0; HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%" PRIx64 "\n", __func__, r1, mask, addr); -cc = 0; + while (mask) { if (mask & 8) { -d = cpu_ldub_data(env, addr); -r = (r1 & 0xff00UL) >> 24; +uint8_t d = cpu_ldub_data_ra(env, addr, ra); +uint8_t r = extract32(r1, 24, 8); HELPER_LOG("mask 0x%x %02x/%02x (0x%" PRIx64 ") ", mask, r, d, addr); if (r < d) { @@ -292,6 +292,7 @@ uint32_t HELPER(clm)(CPUS390XState *env, uint32_t r1, uint32_t mask, mask = (mask << 1) & 0xf; r1 <<= 8; } + HELPER_LOG("\n"); return cc; } diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 0f9148a..34ccc22 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -1928,7 +1928,6 @@ static ExitStatus op_clm(DisasContext *s, DisasOps *o) TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3)); TCGv_i32 t1 = tcg_temp_new_i32(); tcg_gen_extrl_i64_i32(t1, o->in1); -potential_page_fault(s); gen_helper_clm(cc_op, cpu_env, t1, m3, o->in2); set_cc_static(s); tcg_temp_free_i32(t1); -- 2.9.4
[Qemu-devel] [PULL 25/69] target/s390x: Use unwind data for helper_lctl
Reviewed-by: Thomas Huth Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 9 + target/s390x/translate.c | 1 - 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 68e3817..614cdb2 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -878,18 +878,19 @@ void HELPER(lctlg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) void HELPER(lctl)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { +uintptr_t ra = GETPC(); S390CPU *cpu = s390_env_get_cpu(env); bool PERchanged = false; -int i; uint64_t src = a2; -uint32_t val; +uint32_t i; for (i = r1;; i = (i + 1) % 16) { -val = cpu_ldl_data(env, src); +uint32_t val = cpu_ldl_data_ra(env, src, ra); if ((uint32_t)env->cregs[i] != val && i >= 9 && i <= 11) { PERchanged = true; } -env->cregs[i] = (env->cregs[i] & 0xULL) | val; +env->cregs[i] = deposit64(env->cregs[i], 0, 32, val); +HELPER_LOG("load ctl %d from 0x%" PRIx64 " == 0x%x\n", i, src, val); src += sizeof(uint32_t); if (i == r3) { diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 65ae573..26f6b37 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2540,7 +2540,6 @@ static ExitStatus op_lctl(DisasContext *s, DisasOps *o) TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); check_privileged(s); -potential_page_fault(s); gen_helper_lctl(cpu_env, r1, o->in2, r3); tcg_temp_free_i32(r1); tcg_temp_free_i32(r3); -- 2.9.4
[Qemu-devel] [PULL 18/69] target/s390x: Use unwind data for helper_clcle
Reviewed-by: Thomas Huth Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 6 +++--- target/s390x/translate.c | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 8a095ad..f5a3044 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -595,12 +595,12 @@ uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { +uintptr_t ra = GETPC(); uint64_t destlen = env->regs[r1 + 1]; uint64_t dest = get_address_31fix(env, r1); uint64_t srclen = env->regs[r3 + 1]; uint64_t src = get_address_31fix(env, r3); uint8_t pad = a2 & 0xff; -uint8_t v1 = 0, v2 = 0; uint32_t cc = 0; if (!(destlen || srclen)) { @@ -612,8 +612,8 @@ uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, } for (; destlen || srclen; src++, dest++, destlen--, srclen--) { -v1 = srclen ? cpu_ldub_data(env, src) : pad; -v2 = destlen ? cpu_ldub_data(env, dest) : pad; +uint8_t v1 = srclen ? cpu_ldub_data_ra(env, src, ra) : pad; +uint8_t v2 = destlen ? cpu_ldub_data_ra(env, dest, ra) : pad; if (v1 != v2) { cc = (v1 < v2) ? 1 : 2; break; diff --git a/target/s390x/translate.c b/target/s390x/translate.c index b42acae..9270067 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -1915,7 +1915,6 @@ static ExitStatus op_clcle(DisasContext *s, DisasOps *o) { TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); -potential_page_fault(s); gen_helper_clcle(cc_op, cpu_env, r1, o->in2, r3); tcg_temp_free_i32(r1); tcg_temp_free_i32(r3); -- 2.9.4
[Qemu-devel] [PULL 27/69] target/s390x: Use unwind data for helper_testblock
Reviewed-by: Thomas Huth Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 3 +++ target/s390x/translate.c | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index b64c04e..7df2e53 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -939,6 +939,7 @@ void HELPER(stctl)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) uint32_t HELPER(testblock)(CPUS390XState *env, uint64_t real_addr) { +uintptr_t ra = GETPC(); CPUState *cs = CPU(s390_env_get_cpu(env)); uint64_t abs_addr; int i; @@ -947,12 +948,14 @@ uint32_t HELPER(testblock)(CPUS390XState *env, uint64_t real_addr) abs_addr = mmu_real2abs(env, real_addr) & TARGET_PAGE_MASK; if (!address_space_access_valid(&address_space_memory, abs_addr, TARGET_PAGE_SIZE, true)) { +cpu_restore_state(cs, ra); program_interrupt(env, PGM_ADDRESSING, 4); return 1; } /* Check low-address protection */ if ((env->cregs[0] & CR0_LOWPROT) && real_addr < 0x2000) { +cpu_restore_state(cs, ra); program_interrupt(env, PGM_PROTECTION, 4); return 1; } diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 669da89..cd017ce 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -4042,7 +4042,6 @@ static ExitStatus op_tcxb(DisasContext *s, DisasOps *o) static ExitStatus op_testblock(DisasContext *s, DisasOps *o) { check_privileged(s); -potential_page_fault(s); gen_helper_testblock(cc_op, cpu_env, o->in2); set_cc_static(s); return NO_EXIT; -- 2.9.4
[Qemu-devel] [PULL 10/69] target/s390x: Use unwind data for helper_srst
Reviewed-by: Thomas Huth Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 3 ++- target/s390x/translate.c | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 3e75cae..33d83e5 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -327,6 +327,7 @@ static inline uint64_t get_address_31fix(CPUS390XState *env, int reg) uint64_t HELPER(srst)(CPUS390XState *env, uint64_t r0, uint64_t end, uint64_t str) { +uintptr_t ra = GETPC(); uint32_t len; uint8_t v, c = r0; @@ -344,7 +345,7 @@ uint64_t HELPER(srst)(CPUS390XState *env, uint64_t r0, uint64_t end, env->cc_op = 2; return end; } -v = cpu_ldub_data(env, str + len); +v = cpu_ldub_data_ra(env, str + len, ra); if (v == c) { /* Character found. Set R1 to the location; R2 is unmodified. */ env->cc_op = 1; diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 34ccc22..cd33c51 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -3972,7 +3972,6 @@ static ExitStatus op_stmh(DisasContext *s, DisasOps *o) static ExitStatus op_srst(DisasContext *s, DisasOps *o) { -potential_page_fault(s); gen_helper_srst(o->in1, cpu_env, regs[0], o->in1, o->in2); set_cc_static(s); return_low128(o->in2); -- 2.9.4
[Qemu-devel] [PULL 26/69] target/s390x: Use unwind data for helper_stctl
Reviewed-by: Thomas Huth Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 10 ++ target/s390x/translate.c | 2 -- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 614cdb2..b64c04e 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -907,11 +907,12 @@ void HELPER(lctl)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) void HELPER(stctg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { -int i; +uintptr_t ra = GETPC(); uint64_t dest = a2; +uint32_t i; for (i = r1;; i = (i + 1) % 16) { -cpu_stq_data(env, dest, env->cregs[i]); +cpu_stq_data_ra(env, dest, env->cregs[i], ra); dest += sizeof(uint64_t); if (i == r3) { @@ -922,11 +923,12 @@ void HELPER(stctg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) void HELPER(stctl)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { -int i; +uintptr_t ra = GETPC(); uint64_t dest = a2; +uint32_t i; for (i = r1;; i = (i + 1) % 16) { -cpu_stl_data(env, dest, env->cregs[i]); +cpu_stl_data_ra(env, dest, env->cregs[i], ra); dest += sizeof(uint32_t); if (i == r3) { diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 26f6b37..669da89 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -3612,7 +3612,6 @@ static ExitStatus op_stctg(DisasContext *s, DisasOps *o) TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); check_privileged(s); -potential_page_fault(s); gen_helper_stctg(cpu_env, r1, o->in2, r3); tcg_temp_free_i32(r1); tcg_temp_free_i32(r3); @@ -3624,7 +3623,6 @@ static ExitStatus op_stctl(DisasContext *s, DisasOps *o) TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); check_privileged(s); -potential_page_fault(s); gen_helper_stctl(cpu_env, r1, o->in2, r3); tcg_temp_free_i32(r1); tcg_temp_free_i32(r3); -- 2.9.4
[Qemu-devel] [PULL 22/69] target/s390x: Use unwind data for helper_tre
Reviewed-by: Thomas Huth Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 15 --- target/s390x/translate.c | 1 - 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index b37a963..fd6dbf7 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -744,9 +744,11 @@ void HELPER(tr)(CPUS390XState *env, uint32_t len, uint64_t array, uint64_t HELPER(tre)(CPUS390XState *env, uint64_t array, uint64_t len, uint64_t trans) { +uintptr_t ra = GETPC(); uint8_t end = env->regs[0] & 0xff; uint64_t l = len; uint64_t i; +uint32_t cc = 0; if (!(env->psw.mask & PSW_MASK_64)) { array &= 0x7fff; @@ -757,25 +759,24 @@ uint64_t HELPER(tre)(CPUS390XState *env, uint64_t array, amount of work we're willing to do. For now, let's cap at 8k. */ if (l > 0x2000) { l = 0x2000; -env->cc_op = 3; -} else { -env->cc_op = 0; +cc = 3; } for (i = 0; i < l; i++) { uint8_t byte, new_byte; -byte = cpu_ldub_data(env, array + i); +byte = cpu_ldub_data_ra(env, array + i, ra); if (byte == end) { -env->cc_op = 1; +cc = 1; break; } -new_byte = cpu_ldub_data(env, trans + byte); -cpu_stb_data(env, array + i, new_byte); +new_byte = cpu_ldub_data_ra(env, trans + byte, ra); +cpu_stb_data_ra(env, array + i, new_byte, ra); } +env->cc_op = cc; env->retxl = len - i; return array + i; } diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 1842cc3..447ba07 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -4073,7 +4073,6 @@ static ExitStatus op_tr(DisasContext *s, DisasOps *o) static ExitStatus op_tre(DisasContext *s, DisasOps *o) { -potential_page_fault(s); gen_helper_tre(o->out, cpu_env, o->out, o->out2, o->in2); return_low128(o->out2); set_cc_static(s); -- 2.9.4
[Qemu-devel] [PULL 12/69] target/s390x: Use unwind data for helper_mvpg
Reviewed-by: Thomas Huth Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/helper.h | 2 +- target/s390x/mem_helper.c | 9 + target/s390x/translate.c | 3 +-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index 1fae191..ea35834 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -12,7 +12,7 @@ DEF_HELPER_FLAGS_3(divs64, TCG_CALL_NO_WG, s64, env, s64, s64) DEF_HELPER_FLAGS_4(divu64, TCG_CALL_NO_WG, i64, env, i64, i64, i64) DEF_HELPER_4(srst, i64, env, i64, i64, i64) DEF_HELPER_4(clst, i64, env, i64, i64, i64) -DEF_HELPER_4(mvpg, void, env, i64, i64, i64) +DEF_HELPER_FLAGS_4(mvpg, TCG_CALL_NO_WG, i32, env, i64, i64, i64) DEF_HELPER_4(mvst, i64, env, i64, i64, i64) DEF_HELPER_5(ex, i32, env, i32, i64, i64, i64) DEF_HELPER_FLAGS_4(stam, TCG_CALL_NO_WG, void, env, i32, i64, i32) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index af2801e..1c36a47 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -398,11 +398,12 @@ uint64_t HELPER(clst)(CPUS390XState *env, uint64_t c, uint64_t s1, uint64_t s2) } /* move page */ -void HELPER(mvpg)(CPUS390XState *env, uint64_t r0, uint64_t r1, uint64_t r2) +uint32_t HELPER(mvpg)(CPUS390XState *env, uint64_t r0, uint64_t r1, uint64_t r2) { -/* XXX missing r0 handling */ -env->cc_op = 0; -fast_memmove(env, r1, r2, TARGET_PAGE_SIZE, 0); +/* ??? missing r0 handling, which includes access keys, but more + importantly optional suppression of the exception! */ +fast_memmove(env, r1, r2, TARGET_PAGE_SIZE, GETPC()); +return 0; /* data moved */ } /* string copy (c is string terminator) */ diff --git a/target/s390x/translate.c b/target/s390x/translate.c index a24e288..f55f10a 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2916,8 +2916,7 @@ static ExitStatus op_mvcs(DisasContext *s, DisasOps *o) static ExitStatus op_mvpg(DisasContext *s, DisasOps *o) { -potential_page_fault(s); -gen_helper_mvpg(cpu_env, regs[0], o->in1, o->in2); +gen_helper_mvpg(cc_op, cpu_env, regs[0], o->in1, o->in2); set_cc_static(s); return NO_EXIT; } -- 2.9.4
[Qemu-devel] [PULL 40/69] target/s390x: remove dead code in translate.c
From: Aurelien Jarno Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-2-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/translate.c | 5 + 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 97ca639..f759818 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -5467,10 +5467,7 @@ void gen_intermediate_code(CPUS390XState *env, struct TranslationBlock *tb) gen_io_start(); } -status = NO_EXIT; -if (status == NO_EXIT) { -status = translate_one(env, &dc); -} +status = translate_one(env, &dc); /* If we reach a page boundary, are single stepping, or exhaust instruction count, stop generation. */ -- 2.9.4
[Qemu-devel] [PULL 29/69] target/s390x: Use unwind data for helper_lra
Fix saving exception_index around mmu_translate; eliminate a dead store. Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 6 +++--- target/s390x/translate.c | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index a8c85c9..17d8257 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -1208,17 +1208,17 @@ uint64_t HELPER(lra)(CPUS390XState *env, uint64_t addr) { CPUState *cs = CPU(s390_env_get_cpu(env)); uint32_t cc = 0; -int old_exc = cs->exception_index; uint64_t asc = env->psw.mask & PSW_MASK_ASC; uint64_t ret; -int flags; +int old_exc, flags; /* XXX incomplete - has more corner cases */ if (!(env->psw.mask & PSW_MASK_64) && (addr >> 32)) { +cpu_restore_state(cs, GETPC()); program_interrupt(env, PGM_SPECIAL_OP, 2); } -cs->exception_index = old_exc; +old_exc = cs->exception_index; if (mmu_translate(env, addr, 0, asc, &ret, &flags, true)) { cc = 3; } diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 7b9c111..141be22 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2560,7 +2560,6 @@ static ExitStatus op_lctlg(DisasContext *s, DisasOps *o) static ExitStatus op_lra(DisasContext *s, DisasOps *o) { check_privileged(s); -potential_page_fault(s); gen_helper_lra(o->out, cpu_env, o->in2); set_cc_static(s); return NO_EXIT; -- 2.9.4
[Qemu-devel] [PULL 30/69] target/s390x: Use unwind data for helper_mvcs/mvcp
Reviewed-by: Thomas Huth Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 8 ++-- target/s390x/translate.c | 2 -- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 17d8257..a73d486 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -1082,6 +1082,7 @@ uint32_t HELPER(csp)(CPUS390XState *env, uint32_t r1, uint64_t r2) uint32_t HELPER(mvcs)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2) { +uintptr_t ra = GETPC(); int cc = 0, i; HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n", @@ -1095,7 +1096,8 @@ uint32_t HELPER(mvcs)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2) /* XXX replace w/ memcpy */ for (i = 0; i < l; i++) { -cpu_stb_secondary(env, a1 + i, cpu_ldub_primary(env, a2 + i)); +uint8_t x = cpu_ldub_primary_ra(env, a2 + i, ra); +cpu_stb_secondary_ra(env, a1 + i, x, ra); } return cc; @@ -1103,6 +1105,7 @@ uint32_t HELPER(mvcs)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2) uint32_t HELPER(mvcp)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2) { +uintptr_t ra = GETPC(); int cc = 0, i; HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n", @@ -1116,7 +1119,8 @@ uint32_t HELPER(mvcp)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2) /* XXX replace w/ memcpy */ for (i = 0; i < l; i++) { -cpu_stb_primary(env, a1 + i, cpu_ldub_secondary(env, a2 + i)); +uint8_t x = cpu_ldub_secondary_ra(env, a2 + i, ra); +cpu_stb_primary_ra(env, a1 + i, x, ra); } return cc; diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 141be22..422bbf1 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2889,7 +2889,6 @@ static ExitStatus op_mvcp(DisasContext *s, DisasOps *o) { int r1 = get_field(s->fields, l1); check_privileged(s); -potential_page_fault(s); gen_helper_mvcp(cc_op, cpu_env, regs[r1], o->addr1, o->in2); set_cc_static(s); return NO_EXIT; @@ -2899,7 +2898,6 @@ static ExitStatus op_mvcs(DisasContext *s, DisasOps *o) { int r1 = get_field(s->fields, l1); check_privileged(s); -potential_page_fault(s); gen_helper_mvcs(cc_op, cpu_env, regs[r1], o->addr1, o->in2); set_cc_static(s); return NO_EXIT; -- 2.9.4
[Qemu-devel] [PULL 35/69] target/s390x: Save current ilen during translation
Use this saved value instead of recomputing from next_pc difference. Reviewed-by: David Hildenbrand Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/translate.c | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 4bd16d9..5b8333f 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -58,6 +58,7 @@ struct DisasContext { const DisasInsn *insn; DisasFields *fields; uint64_t pc, next_pc; +uint32_t ilen; enum cc_op cc_op; bool singlestep_enabled; }; @@ -349,7 +350,7 @@ static void gen_program_exception(DisasContext *s, int code) tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_code)); tcg_temp_free_i32(tmp); -tmp = tcg_const_i32(s->next_pc - s->pc); +tmp = tcg_const_i32(s->ilen); tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_ilen)); tcg_temp_free_i32(tmp); @@ -2207,7 +2208,7 @@ static ExitStatus op_ex(DisasContext *s, DisasOps *o) v1 = regs[r1]; } -ilen = tcg_const_i32(s->next_pc - s->pc); +ilen = tcg_const_i32(s->ilen); gen_helper_ex(cpu_env, ilen, v1, o->in2); tcg_temp_free_i32(ilen); @@ -4052,7 +4053,7 @@ static ExitStatus op_svc(DisasContext *s, DisasOps *o) tcg_gen_st_i32(t, cpu_env, offsetof(CPUS390XState, int_svc_code)); tcg_temp_free_i32(t); -t = tcg_const_i32(s->next_pc - s->pc); +t = tcg_const_i32(s->ilen); tcg_gen_st_i32(t, cpu_env, offsetof(CPUS390XState, int_svc_ilen)); tcg_temp_free_i32(t); @@ -5191,6 +5192,7 @@ static const DisasInsn *extract_insn(CPUS390XState *env, DisasContext *s, op = (insn >> 8) & 0xff; ilen = get_ilen(op); s->next_pc = s->pc + ilen; +s->ilen = ilen; switch (ilen) { case 2: -- 2.9.4
[Qemu-devel] [PULL 13/69] target/s390x: Use unwind data for helper_mvst
Reviewed-by: Thomas Huth Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 5 +++-- target/s390x/translate.c | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 1c36a47..e4bfc6e 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -409,6 +409,7 @@ uint32_t HELPER(mvpg)(CPUS390XState *env, uint64_t r0, uint64_t r1, uint64_t r2) /* string copy (c is string terminator) */ uint64_t HELPER(mvst)(CPUS390XState *env, uint64_t c, uint64_t d, uint64_t s) { +uintptr_t ra = GETPC(); uint32_t len; c = c & 0xff; @@ -418,8 +419,8 @@ uint64_t HELPER(mvst)(CPUS390XState *env, uint64_t c, uint64_t d, uint64_t s) /* Lest we fail to service interrupts in a timely manner, limit the amount of work we're willing to do. For now, let's cap at 8k. */ for (len = 0; len < 0x2000; ++len) { -uint8_t v = cpu_ldub_data(env, s + len); -cpu_stb_data(env, d + len, v); +uint8_t v = cpu_ldub_data_ra(env, s + len, ra); +cpu_stb_data_ra(env, d + len, v, ra); if (v == c) { /* Complete. Set CC=1 and advance R1. */ env->cc_op = 1; diff --git a/target/s390x/translate.c b/target/s390x/translate.c index f55f10a..86e5567 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2923,7 +2923,6 @@ static ExitStatus op_mvpg(DisasContext *s, DisasOps *o) static ExitStatus op_mvst(DisasContext *s, DisasOps *o) { -potential_page_fault(s); gen_helper_mvst(o->in1, cpu_env, regs[0], o->in1, o->in2); set_cc_static(s); return_low128(o->in2); -- 2.9.4
[Qemu-devel] [PULL 44/69] target/s390x: implement TEST ADDRESSING MODE
From: Aurelien Jarno Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-6-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/insn-data.def | 3 +++ target/s390x/translate.c | 10 ++ 2 files changed, 13 insertions(+) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 0f70ace..170b50e 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -810,6 +810,9 @@ /* SUPERVISOR CALL */ C(0x0a00, SVC, I, Z, 0, 0, 0, 0, svc, 0) +/* TEST ADDRESSING MODE */ +C(0x010b, TAM, E, Z, 0, 0, 0, 0, tam, 0) + /* TEST AND SET */ C(0x9300, TS, S, Z, 0, a2, 0, 0, ts, 0) diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 0cfa8cc..7f265ae 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -4063,6 +4063,16 @@ static ExitStatus op_svc(DisasContext *s, DisasOps *o) return EXIT_NORETURN; } +static ExitStatus op_tam(DisasContext *s, DisasOps *o) +{ +int cc = 0; + +cc |= (s->tb->flags & FLAG_MASK_64) ? 2 : 0; +cc |= (s->tb->flags & FLAG_MASK_32) ? 1 : 0; +gen_op_movi_cc(s, cc); +return NO_EXIT; +} + static ExitStatus op_tceb(DisasContext *s, DisasOps *o) { gen_helper_tceb(cc_op, cpu_env, o->in1, o->in2); -- 2.9.4
[Qemu-devel] [PULL 33/69] target/s390x: Use atomic operations for COMPARE SWAP PURGE
Also provide the cross-cpu tlb flushing required by the PoO. Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/helper.h | 2 +- target/s390x/insn-data.def | 2 +- target/s390x/mem_helper.c | 32 target/s390x/translate.c | 42 ++ 4 files changed, 48 insertions(+), 30 deletions(-) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index 3819409..cc451c7 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -107,13 +107,13 @@ DEF_HELPER_FLAGS_2(tprot, TCG_CALL_NO_RWG, i32, i64, i64) DEF_HELPER_FLAGS_2(iske, TCG_CALL_NO_RWG_SE, i64, env, i64) DEF_HELPER_FLAGS_3(sske, TCG_CALL_NO_RWG, void, env, i64, i64) DEF_HELPER_FLAGS_2(rrbe, TCG_CALL_NO_RWG, i32, env, i64) -DEF_HELPER_3(csp, i32, env, i32, i64) DEF_HELPER_4(mvcs, i32, env, i64, i64, i64) DEF_HELPER_4(mvcp, i32, env, i64, i64, i64) DEF_HELPER_4(sigp, i32, env, i64, i32, i64) DEF_HELPER_FLAGS_2(sacf, TCG_CALL_NO_WG, void, env, i64) DEF_HELPER_FLAGS_3(ipte, TCG_CALL_NO_RWG, void, env, i64, i64) DEF_HELPER_FLAGS_1(ptlb, TCG_CALL_NO_RWG, void, env) +DEF_HELPER_FLAGS_1(purge, TCG_CALL_NO_RWG, void, env) DEF_HELPER_2(lra, i64, env, i64) DEF_HELPER_FLAGS_2(lura, TCG_CALL_NO_WG, i64, env, i64) DEF_HELPER_FLAGS_2(lurag, TCG_CALL_NO_WG, i64, env, i64) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 3c3541c..4c91f30 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -837,7 +837,7 @@ #ifndef CONFIG_USER_ONLY /* COMPARE AND SWAP AND PURGE */ -C(0xb250, CSP, RRE, Z, 0, ra2, 0, 0, csp, 0) +D(0xb250, CSP, RRE, Z, r1_32u, ra2, r1_P, 0, csp, 0, MO_TEUL) /* DIAGNOSE (KVM hypercall) */ C(0x8300, DIAG,RSI, Z, 0, 0, 0, 0, diag, 0) /* INSERT STORAGE KEY EXTENDED */ diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index fa03129..4b96c27 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -1056,30 +1056,6 @@ uint32_t HELPER(rrbe)(CPUS390XState *env, uint64_t r2) return re >> 1; } -/* compare and swap and purge */ -uint32_t HELPER(csp)(CPUS390XState *env, uint32_t r1, uint64_t r2) -{ -S390CPU *cpu = s390_env_get_cpu(env); -uint32_t cc; -uint32_t o1 = env->regs[r1]; -uint64_t a2 = r2 & ~3ULL; -uint32_t o2 = cpu_ldl_data(env, a2); - -if (o1 == o2) { -cpu_stl_data(env, a2, env->regs[(r1 + 1) & 15]); -if (r2 & 0x3) { -/* flush TLB / ALB */ -tlb_flush(CPU(cpu)); -} -cc = 0; -} else { -env->regs[r1] = (env->regs[r1] & 0xULL) | o2; -cc = 1; -} - -return cc; -} - uint32_t HELPER(mvcs)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2) { uintptr_t ra = GETPC(); @@ -1161,6 +1137,14 @@ void HELPER(ptlb)(CPUS390XState *env) tlb_flush(CPU(cpu)); } +/* flush global tlb */ +void HELPER(purge)(CPUS390XState *env) +{ +S390CPU *cpu = s390_env_get_cpu(env); + +tlb_flush_all_cpus_synced(CPU(cpu)); +} + /* load using real address */ uint64_t HELPER(lura)(CPUS390XState *env, uint64_t addr) { diff --git a/target/s390x/translate.c b/target/s390x/translate.c index b7b4843..a3fb324 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2001,11 +2001,45 @@ static ExitStatus op_cdsg(DisasContext *s, DisasOps *o) #ifndef CONFIG_USER_ONLY static ExitStatus op_csp(DisasContext *s, DisasOps *o) { -TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); +TCGMemOp mop = s->insn->data; +TCGv_i64 addr, old, cc; +TCGLabel *lab = gen_new_label(); + +/* Note that in1 = R1 (zero-extended expected value), + out = R1 (original reg), out2 = R1+1 (new value). */ + check_privileged(s); -gen_helper_csp(cc_op, cpu_env, r1, o->in2); -tcg_temp_free_i32(r1); -set_cc_static(s); +addr = tcg_temp_new_i64(); +old = tcg_temp_new_i64(); +tcg_gen_andi_i64(addr, o->in2, -1ULL << (mop & MO_SIZE)); +tcg_gen_atomic_cmpxchg_i64(old, addr, o->in1, o->out2, + get_mem_index(s), mop | MO_ALIGN); +tcg_temp_free_i64(addr); + +/* Are the memory and expected values (un)equal? */ +cc = tcg_temp_new_i64(); +tcg_gen_setcond_i64(TCG_COND_NE, cc, o->in1, old); +tcg_gen_extrl_i64_i32(cc_op, cc); + +/* Write back the output now, so that it happens before the + following branch, so that we don't need local temps. */ +if ((mop & MO_SIZE) == MO_32) { +tcg_gen_deposit_i64(o->out, o->out, old, 0, 32); +} else { +tcg_gen_mov_i64(o->out, old); +} +tcg_temp_free_i64(old); + +/* If the comparison was equal, and the LSB of R2 was set, + then we need to flush the TLB (for all cpus). */ +tcg_gen_xori_i64(cc, cc, 1); +tcg_gen_and_i64(cc, cc, o->in2); +tcg_gen_brcondi_i64(TCG_COND_EQ, cc, 0, lab); +tcg_temp_free_i64(cc); + +gen_hel
[Qemu-devel] [PULL 14/69] target/s390x: Use unwind data for helper_lam
Reviewed-by: Thomas Huth Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 3 ++- target/s390x/translate.c | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index e4bfc6e..88e817a 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -469,10 +469,11 @@ static uint32_t helper_icm(CPUS390XState *env, uint32_t r1, uint64_t address, /* load access registers r1 to r3 from memory at a2 */ void HELPER(lam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { +uintptr_t ra = GETPC(); int i; for (i = r1;; i = (i + 1) % 16) { -env->aregs[i] = cpu_ldl_data(env, a2); +env->aregs[i] = cpu_ldl_data_ra(env, a2, ra); a2 += 4; if (i == r3) { diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 86e5567..dca2096 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2621,7 +2621,6 @@ static ExitStatus op_lam(DisasContext *s, DisasOps *o) { TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); -potential_page_fault(s); gen_helper_lam(cpu_env, r1, o->in2, r3); tcg_temp_free_i32(r1); tcg_temp_free_i32(r3); -- 2.9.4
[Qemu-devel] [PULL 37/69] target/s390x: Implement EXECUTE via new TranslationBlock
Previously, helper_ex would construct the insn and then implement the insn via direct calls other helpers. This was sufficient to boot Linux but that is all. It is easy enough to go the whole nine yards by stashing state for EXECUTE within the cpu, and then rely on a new TB to be created that properly and completely interprets the insn. Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/cpu.h| 4 +- target/s390x/helper.c | 5 ++ target/s390x/machine.c| 19 target/s390x/mem_helper.c | 118 +- target/s390x/translate.c | 80 ++- 5 files changed, 85 insertions(+), 141 deletions(-) diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h index f463113..fdb2f50 100644 --- a/target/s390x/cpu.h +++ b/target/s390x/cpu.h @@ -107,6 +107,8 @@ typedef struct CPUS390XState { uint64_t cc_dst; uint64_t cc_vr; +uint64_t ex_value; + uint64_t __excp_addr; uint64_t psa; @@ -393,7 +395,7 @@ static inline void cpu_get_tb_cpu_state(CPUS390XState* env, target_ulong *pc, target_ulong *cs_base, uint32_t *flags) { *pc = env->psw.addr; -*cs_base = 0; +*cs_base = env->ex_value; *flags = ((env->psw.mask >> 32) & ~FLAG_MASK_CC) | ((env->psw.mask & PSW_MASK_32) ? FLAG_MASK_32 : 0); } diff --git a/target/s390x/helper.c b/target/s390x/helper.c index 4f8aadf..291db72 100644 --- a/target/s390x/helper.c +++ b/target/s390x/helper.c @@ -642,6 +642,11 @@ bool s390_cpu_exec_interrupt(CPUState *cs, int interrupt_request) S390CPU *cpu = S390_CPU(cs); CPUS390XState *env = &cpu->env; +if (env->ex_value) { +/* Execution of the target insn is indivisible from + the parent EXECUTE insn. */ +return false; +} if (env->psw.mask & PSW_MASK_EXT) { s390_cpu_do_interrupt(cs); return true; diff --git a/target/s390x/machine.c b/target/s390x/machine.c index 8503fa1..8f908bb 100644 --- a/target/s390x/machine.c +++ b/target/s390x/machine.c @@ -34,6 +34,7 @@ static int cpu_post_load(void *opaque, int version_id) return 0; } + static void cpu_pre_save(void *opaque) { S390CPU *cpu = opaque; @@ -156,6 +157,23 @@ const VMStateDescription vmstate_riccb = { } }; +static bool exval_needed(void *opaque) +{ +S390CPU *cpu = opaque; +return cpu->env.ex_value != 0; +} + +const VMStateDescription vmstate_exval = { +.name = "cpu/exval", +.version_id = 1, +.minimum_version_id = 1, +.needed = exval_needed, +.fields = (VMStateField[]) { +VMSTATE_UINT64(env.ex_value, S390CPU), +VMSTATE_END_OF_LIST() +} +}; + const VMStateDescription vmstate_s390_cpu = { .name = "cpu", .post_load = cpu_post_load, @@ -188,6 +206,7 @@ const VMStateDescription vmstate_s390_cpu = { &vmstate_fpu, &vmstate_vregs, &vmstate_riccb, +&vmstate_exval, NULL }, }; diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index d57d5b1..3a77edc 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -435,37 +435,6 @@ uint64_t HELPER(mvst)(CPUS390XState *env, uint64_t c, uint64_t d, uint64_t s) return d + len; } -static uint32_t helper_icm(CPUS390XState *env, uint32_t r1, uint64_t address, - uint32_t mask) -{ -int pos = 24; /* top of the lower half of r1 */ -uint64_t rmask = 0xff00ULL; -uint8_t val = 0; -int ccd = 0; -uint32_t cc = 0; - -while (mask) { -if (mask & 8) { -env->regs[r1] &= ~rmask; -val = cpu_ldub_data(env, address); -if ((val & 0x80) && !ccd) { -cc = 1; -} -ccd = 1; -if (val && cc == 0) { -cc = 2; -} -env->regs[r1] |= (uint64_t)val << pos; -address++; -} -mask = (mask << 1) & 0xf; -pos -= 8; -rmask >>= 8; -} - -return cc; -} - /* load access registers r1 to r3 from memory at a2 */ void HELPER(lam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { @@ -1222,19 +1191,17 @@ uint64_t HELPER(lra)(CPUS390XState *env, uint64_t addr) } #endif -/* execute instruction - this instruction executes an insn modified with the contents of r1 - it does not change the executed instruction in memory - it does not change the program counter - in other words: tricky... - currently implemented by interpreting the cases it is most commonly used. +/* Execute instruction. This instruction executes an insn modified with + the contents of r1. It does not change the executed instruction in memory; + it does not change the program counter. + + Perform this by recording the modified instruction in env->ex_value. + This will be noticed by cpu_get_tb_cpu
[Qemu-devel] [PULL 45/69] target/s390x: implement PACK
From: Aurelien Jarno Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-7-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 5 + target/s390x/mem_helper.c | 37 + target/s390x/translate.c | 8 4 files changed, 51 insertions(+) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index 3f5a05d..c6fbc3b 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -75,6 +75,7 @@ DEF_HELPER_FLAGS_2(sqeb, TCG_CALL_NO_WG, i64, env, i64) DEF_HELPER_FLAGS_2(sqdb, TCG_CALL_NO_WG, i64, env, i64) DEF_HELPER_FLAGS_3(sqxb, TCG_CALL_NO_WG, i64, env, i64, i64) DEF_HELPER_FLAGS_1(cvd, TCG_CALL_NO_RWG_SE, i64, s32) +DEF_HELPER_FLAGS_4(pack, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(unpk, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(tr, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_4(tre, i64, env, i64, i64, i64) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 170b50e..f92bfde 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -639,6 +639,11 @@ C(0x9600, OI, SI,Z, m1_8u, i2_8u, new, m1_8, or, nz64) C(0xeb56, OIY, SIY, LD, m1_8u, i2_8u, new, m1_8, or, nz64) +/* PACK */ +/* Really format SS_b, but we pack both lengths into one argument + for the helper call, so we might as well leave one 8-bit field. */ +C(0xf200, PACK,SS_a, Z, la1, a2, 0, 0, pack, 0) + /* PREFETCH */ /* Implemented as nops of course. */ C(0xe336, PFD, RXY_b, GIE, 0, 0, 0, 0, 0, 0) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index ddbebcd..850472e 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -644,6 +644,43 @@ uint64_t HELPER(cksm)(CPUS390XState *env, uint64_t r1, return len; } +void HELPER(pack)(CPUS390XState *env, uint32_t len, uint64_t dest, uint64_t src) +{ +uintptr_t ra = GETPC(); +int len_dest = len >> 4; +int len_src = len & 0xf; +uint8_t b; + +dest += len_dest; +src += len_src; + +/* last byte is special, it only flips the nibbles */ +b = cpu_ldub_data_ra(env, src, ra); +cpu_stb_data_ra(env, dest, (b << 4) | (b >> 4), ra); +src--; +len_src--; + +/* now pack every value */ +while (len_dest >= 0) { +b = 0; + +if (len_src > 0) { +b = cpu_ldub_data_ra(env, src, ra) & 0x0f; +src--; +len_src--; +} +if (len_src > 0) { +b |= cpu_ldub_data_ra(env, src, ra) << 4; +src--; +len_src--; +} + +len_dest--; +dest--; +cpu_stb_data_ra(env, dest, b, ra); +} +} + void HELPER(unpk)(CPUS390XState *env, uint32_t len, uint64_t dest, uint64_t src) { diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 7f265ae..00b91c4 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -3139,6 +3139,14 @@ static ExitStatus op_ori(DisasContext *s, DisasOps *o) return NO_EXIT; } +static ExitStatus op_pack(DisasContext *s, DisasOps *o) +{ +TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); +gen_helper_pack(cpu_env, l, o->addr1, o->in2); +tcg_temp_free_i32(l); +return NO_EXIT; +} + static ExitStatus op_popcnt(DisasContext *s, DisasOps *o) { gen_helper_popcnt(o->out, o->in2); -- 2.9.4
[Qemu-devel] [PULL 34/69] target/s390x: Implement CSPG
Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/insn-data.def | 1 + target/s390x/translate.c | 1 + 2 files changed, 2 insertions(+) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 4c91f30..f818437 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -838,6 +838,7 @@ #ifndef CONFIG_USER_ONLY /* COMPARE AND SWAP AND PURGE */ D(0xb250, CSP, RRE, Z, r1_32u, ra2, r1_P, 0, csp, 0, MO_TEUL) +D(0xb98a, CSPG,RRE, DAT_ENH, r1_o, ra2, r1_P, 0, csp, 0, MO_TEQ) /* DIAGNOSE (KVM hypercall) */ C(0x8300, DIAG,RSI, Z, 0, 0, 0, 0, diag, 0) /* INSERT STORAGE KEY EXTENDED */ diff --git a/target/s390x/translate.c b/target/s390x/translate.c index a3fb324..4bd16d9 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -1195,6 +1195,7 @@ typedef enum DisasFacility { FAC_SFLE, /* store facility list extended */ FAC_ILA,/* interlocked access facility 1 */ FAC_LPP,/* load-program-parameter */ +FAC_DAT_ENH,/* DAT-enhancement */ } DisasFacility; struct DisasInsn { -- 2.9.4
[Qemu-devel] [PULL 41/69] target/s390x: remove some Linux assumptions from IPTE
From: Aurelien Jarno Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-3-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/cpu.h| 2 ++ target/s390x/mem_helper.c | 17 ++--- target/s390x/mmu_helper.c | 2 -- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h index fdb2f50..a4d31df 100644 --- a/target/s390x/cpu.h +++ b/target/s390x/cpu.h @@ -1035,6 +1035,8 @@ struct sysib_322 { #define _SEGMENT_ENTRY_RO 0x200 /* page protection bit */ #define _SEGMENT_ENTRY_INV 0x20 /* invalid segment table entry */ +#define VADDR_PX0xff000 /* page index bits */ + #define _PAGE_RO0x200/* HW read-only bit */ #define _PAGE_INVALID 0x400/* HW invalid bit*/ #define _PAGE_RES0 0x800/* bit must be zero */ diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index e35571e..0ebd65d 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -1073,19 +1073,22 @@ uint32_t HELPER(mvcp)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2) } /* invalidate pte */ -void HELPER(ipte)(CPUS390XState *env, uint64_t pte_addr, uint64_t vaddr) +void HELPER(ipte)(CPUS390XState *env, uint64_t pto, uint64_t vaddr) { CPUState *cs = CPU(s390_env_get_cpu(env)); uint64_t page = vaddr & TARGET_PAGE_MASK; -uint64_t pte = 0; +uint64_t pte_addr, pte; /* XXX broadcast to other CPUs */ -/* XXX Linux is nice enough to give us the exact pte address. - According to spec we'd have to find it out ourselves */ -/* XXX Linux is fine with overwriting the pte, the spec requires - us to only set the invalid bit */ -stq_phys(cs->as, pte_addr, pte | _PAGE_INVALID); +/* Compute the page table entry address */ +pte_addr = (pto & _SEGMENT_ENTRY_ORIGIN); +pte_addr += (vaddr & _VADDR_PX) >> 9; + +/* Mark the page table entry as invalid */ +pte = ldq_phys(cs->as, pte_addr); +pte |= _PAGE_INVALID; +stq_phys(cs->as, pte_addr, pte); /* XXX we exploit the fact that Linux passes the exact virtual address here - it's not obliged to! */ diff --git a/target/s390x/mmu_helper.c b/target/s390x/mmu_helper.c index 31eb9ef..501e390 100644 --- a/target/s390x/mmu_helper.c +++ b/target/s390x/mmu_helper.c @@ -143,8 +143,6 @@ static int mmu_translate_pte(CPUS390XState *env, target_ulong vaddr, return 0; } -#define VADDR_PX0xff000 /* Page index bits */ - /* Decode segment table entry */ static int mmu_translate_segment(CPUS390XState *env, target_ulong vaddr, uint64_t asc, uint64_t st_entry, -- 2.9.4
[Qemu-devel] [PULL 46/69] target/s390x: implement LOAD PAIR FROM QUADWORD
From: Aurelien Jarno Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-8-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 2 ++ target/s390x/mem_helper.c | 13 + target/s390x/translate.c | 7 +++ 4 files changed, 23 insertions(+) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index c6fbc3b..ca78d1b 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -87,6 +87,7 @@ DEF_HELPER_FLAGS_2(sfas, TCG_CALL_NO_WG, void, env, i64) DEF_HELPER_FLAGS_1(popcnt, TCG_CALL_NO_RWG_SE, i64, i64) DEF_HELPER_FLAGS_1(stfl, TCG_CALL_NO_RWG, void, env) DEF_HELPER_2(stfle, i32, env, i64) +DEF_HELPER_FLAGS_2(lpq, TCG_CALL_NO_WG, i64, env, i64) #ifndef CONFIG_USER_ONLY DEF_HELPER_3(servc, i32, env, i64, i64) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index f92bfde..53c86d5 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -507,6 +507,8 @@ /* LOAD PAIR DISJOINT */ D(0xc804, LPD, SSF, ILA, 0, 0, new_P, r3_P32, lpd, 0, MO_TEUL) D(0xc805, LPDG,SSF, ILA, 0, 0, new_P, r3_P64, lpd, 0, MO_TEQ) +/* LOAD PAIR FROM QUADWORD */ +C(0xe38f, LPQ, RXY_a, Z, 0, a2, r1_P, 0, lpq, 0) /* LOAD POSITIVE */ C(0x1000, LPR, RR_a, Z, 0, r2_32s, new, r1_32, abs, abs32) C(0xb900, LPGR,RRE, Z, 0, r2, r1, 0, abs, abs64) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 850472e..4f34f87 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -1237,6 +1237,19 @@ uint64_t HELPER(lra)(CPUS390XState *env, uint64_t addr) } #endif +/* load pair from quadword */ +uint64_t HELPER(lpq)(CPUS390XState *env, uint64_t addr) +{ +uintptr_t ra = GETPC(); +int mem_idx = cpu_mmu_index(env, false); +TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx); + +Int128 v = helper_atomic_ldo_be_mmu(env, addr, oi, ra); + +env->retxl = int128_getlo(v); +return int128_gethi(v); +} + /* Execute instruction. This instruction executes an insn modified with the contents of r1. It does not change the executed instruction in memory; it does not change the program counter. diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 00b91c4..ec61590 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2830,6 +2830,13 @@ static ExitStatus op_lpd(DisasContext *s, DisasOps *o) return NO_EXIT; } +static ExitStatus op_lpq(DisasContext *s, DisasOps *o) +{ +gen_helper_lpq(o->out, cpu_env, o->in2); +return_low128(o->out2); +return NO_EXIT; +} + #ifndef CONFIG_USER_ONLY static ExitStatus op_lura(DisasContext *s, DisasOps *o) { -- 2.9.4
[Qemu-devel] [PULL 24/69] target/s390x: Use unwind data for helper_lctlg
Reviewed-by: Thomas Huth Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 8 target/s390x/translate.c | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index ff12777..68e3817 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -848,20 +848,20 @@ void HELPER(cdsg)(CPUS390XState *env, uint64_t addr, #if !defined(CONFIG_USER_ONLY) void HELPER(lctlg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { +uintptr_t ra = GETPC(); S390CPU *cpu = s390_env_get_cpu(env); bool PERchanged = false; -int i; uint64_t src = a2; -uint64_t val; +uint32_t i; for (i = r1;; i = (i + 1) % 16) { -val = cpu_ldq_data(env, src); +uint64_t val = cpu_ldq_data_ra(env, src, ra); if (env->cregs[i] != val && i >= 9 && i <= 11) { PERchanged = true; } env->cregs[i] = val; HELPER_LOG("load ctl %d from 0x%" PRIx64 " == 0x%" PRIx64 "\n", - i, src, env->cregs[i]); + i, src, val); src += sizeof(uint64_t); if (i == r3) { diff --git a/target/s390x/translate.c b/target/s390x/translate.c index fed9f17..65ae573 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2552,7 +2552,6 @@ static ExitStatus op_lctlg(DisasContext *s, DisasOps *o) TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); check_privileged(s); -potential_page_fault(s); gen_helper_lctlg(cpu_env, r1, o->in2, r3); tcg_temp_free_i32(r1); tcg_temp_free_i32(r3); -- 2.9.4
[Qemu-devel] [PULL 36/69] target/s390x: End the TB after EXECUTE
This split will be required for implementing EXECUTE properly. Do this now as a separate step to aid comparison of before and after TB listings. Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 54 --- target/s390x/translate.c | 6 +- 2 files changed, 37 insertions(+), 23 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 4b96c27..d57d5b1 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -1234,6 +1234,7 @@ void HELPER(ex)(CPUS390XState *env, uint32_t ilen, uint64_t r1, uint64_t addr) S390CPU *cpu = s390_env_get_cpu(env); uint64_t insn = cpu_lduw_code(env, addr); uint8_t opc = insn >> 8; +uint32_t cc; /* Or in the contents of R1[56:63]. */ insn |= r1 & 0xff; @@ -1263,42 +1264,46 @@ void HELPER(ex)(CPUS390XState *env, uint32_t ilen, uint64_t r1, uint64_t addr) b2 = extract64(insn, 28, 4); d1 = extract64(insn, 32, 12); d2 = extract64(insn, 16, 12); + +cc = env->cc_op; switch (opc & 0xf) { case 0x2: do_helper_mvc(env, l, get_address(env, 0, b1, d1), get_address(env, 0, b2, d2), 0); -return; +break; case 0x4: -env->cc_op = do_helper_nc(env, l, get_address(env, 0, b1, d1), - get_address(env, 0, b2, d2), 0); -return; +cc = do_helper_nc(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2), 0); +break; case 0x5: -env->cc_op = do_helper_clc(env, l, get_address(env, 0, b1, d1), - get_address(env, 0, b2, d2), 0); -return; +cc = do_helper_clc(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2), 0); +break; case 0x6: -env->cc_op = do_helper_oc(env, l, get_address(env, 0, b1, d1), - get_address(env, 0, b2, d2), 0); -return; +cc = do_helper_oc(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2), 0); +break; case 0x7: -env->cc_op = do_helper_xc(env, l, get_address(env, 0, b1, d1), - get_address(env, 0, b2, d2), 0); -return; +cc = do_helper_xc(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2), 0); +break; case 0xc: do_helper_tr(env, l, get_address(env, 0, b1, d1), get_address(env, 0, b2, d2), 0); -return; +break; case 0xd: -env->cc_op = do_helper_trt(env, l, get_address(env, 0, b1, d1), - get_address(env, 0, b2, d2), 0); -return; +cc = do_helper_trt(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2), 0); +break; +default: +goto abort; } } else if (opc == 0x0a) { /* supervisor call */ env->int_svc_code = extract64(insn, 48, 8); env->int_svc_ilen = ilen; helper_exception(env, EXCP_SVC); -return; +g_assert_not_reached(); } else if (opc == 0xbf) { uint32_t r1, r3, b2, d2; @@ -1306,10 +1311,15 @@ void HELPER(ex)(CPUS390XState *env, uint32_t ilen, uint64_t r1, uint64_t addr) r3 = extract64(insn, 48, 4); b2 = extract64(insn, 44, 4); d2 = extract64(insn, 32, 12); -env->cc_op = helper_icm(env, r1, get_address(env, 0, b2, d2), r3); -return; +cc = helper_icm(env, r1, get_address(env, 0, b2, d2), r3); +} else { + abort: +cpu_abort(CPU(cpu), + "EXECUTE on instruction prefix 0x%x not implemented\n", + opc); +g_assert_not_reached(); } -cpu_abort(CPU(cpu), "EXECUTE on instruction prefix 0x%x not implemented\n", - opc); +env->cc_op = cc; +env->psw.addr += ilen; } diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 5b8333f..70212c8 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -1163,6 +1163,8 @@ typedef enum { the PC (for whatever reason), so there's no need to do it again on exiting the TB. */ EXIT_PC_UPDATED, +/* We have updated the PC and CC values. */ +EXIT_PC_CC_UPDATED, /* We are exiting the TB, but have neither emitted a goto_tb, nor updated the PC for the next instruction to be executed. */ EXIT_PC_STALE, @@ -2216,7 +2218,7 @@ static ExitStatus op_ex(DisasContext *s, DisasOps *o) tcg_temp_free_i64(v1); } -return NO_EXIT; +re
[Qemu-devel] [PULL 28/69] target/s390x: Use unwind data for helper_tprot
Reviewed-by: Thomas Huth Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 1 - target/s390x/translate.c | 1 - 2 files changed, 2 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 7df2e53..a8c85c9 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -970,7 +970,6 @@ uint32_t HELPER(testblock)(CPUS390XState *env, uint64_t real_addr) uint32_t HELPER(tprot)(uint64_t a1, uint64_t a2) { /* XXX implement */ - return 0; } diff --git a/target/s390x/translate.c b/target/s390x/translate.c index cd017ce..7b9c111 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -4049,7 +4049,6 @@ static ExitStatus op_testblock(DisasContext *s, DisasOps *o) static ExitStatus op_tprot(DisasContext *s, DisasOps *o) { -potential_page_fault(s); gen_helper_tprot(cc_op, o->addr1, o->in2); set_cc_static(s); return NO_EXIT; -- 2.9.4
[Qemu-devel] [PULL 53/69] target/s390x: improve 24-bit and 31-bit addresses read
From: Aurelien Jarno Improve fix_address to also handle the 24-bit mode. Rename fix_address to wrap_address to better explain what is changed. Replace the calls to get_address with x2 = 0 and b2 = 0 by call to wrap_address, leading to the removal of this function. Rename get_address_31fix into get_address. Reviewed-by: Thomas Huth Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-15-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 71 +-- 1 file changed, 31 insertions(+), 40 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 95f701d..2425bfc 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -365,30 +365,23 @@ uint32_t HELPER(clm)(CPUS390XState *env, uint32_t r1, uint32_t mask, return cc; } -static inline uint64_t fix_address(CPUS390XState *env, uint64_t a) +static inline uint64_t wrap_address(CPUS390XState *env, uint64_t a) { -/* 31-Bit mode */ if (!(env->psw.mask & PSW_MASK_64)) { -a &= 0x7fff; +if (!(env->psw.mask & PSW_MASK_32)) { +/* 24-Bit mode */ +a &= 0x00ff; +} else { +/* 31-Bit mode */ +a &= 0x7fff; +} } return a; } -static inline uint64_t get_address(CPUS390XState *env, int x2, int b2, int d2) -{ -uint64_t r = d2; -if (x2) { -r += env->regs[x2]; -} -if (b2) { -r += env->regs[b2]; -} -return fix_address(env, r); -} - -static inline uint64_t get_address_31fix(CPUS390XState *env, int reg) +static inline uint64_t get_address(CPUS390XState *env, int reg) { -return fix_address(env, env->regs[reg]); +return wrap_address(env, env->regs[reg]); } /* search string (c is byte to search, r2 is string, r1 end of string) */ @@ -399,8 +392,8 @@ uint64_t HELPER(srst)(CPUS390XState *env, uint64_t r0, uint64_t end, uint32_t len; uint8_t v, c = r0; -str = fix_address(env, str); -end = fix_address(env, end); +str = wrap_address(env, str); +end = wrap_address(env, end); /* Assume for now that R2 is unmodified. */ env->retxl = str; @@ -434,8 +427,8 @@ uint64_t HELPER(clst)(CPUS390XState *env, uint64_t c, uint64_t s1, uint64_t s2) uint32_t len; c = c & 0xff; -s1 = fix_address(env, s1); -s2 = fix_address(env, s2); +s1 = wrap_address(env, s1); +s2 = wrap_address(env, s2); /* Lest we fail to service interrupts in a timely manner, limit the amount of work we're willing to do. For now, let's cap at 8k. */ @@ -481,8 +474,8 @@ uint64_t HELPER(mvst)(CPUS390XState *env, uint64_t c, uint64_t d, uint64_t s) uint32_t len; c = c & 0xff; -d = fix_address(env, d); -s = fix_address(env, s); +d = wrap_address(env, d); +s = wrap_address(env, s); /* Lest we fail to service interrupts in a timely manner, limit the amount of work we're willing to do. For now, let's cap at 8k. */ @@ -540,9 +533,9 @@ uint32_t HELPER(mvcl)(CPUS390XState *env, uint32_t r1, uint32_t r2) { uintptr_t ra = GETPC(); uint64_t destlen = env->regs[r1 + 1] & 0xff; -uint64_t dest = get_address_31fix(env, r1); +uint64_t dest = get_address(env, r1); uint64_t srclen = env->regs[r2 + 1] & 0xff; -uint64_t src = get_address_31fix(env, r2); +uint64_t src = get_address(env, r2); uint8_t pad = env->regs[r2 + 1] >> 24; uint8_t v; uint32_t cc; @@ -583,9 +576,9 @@ uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, { uintptr_t ra = GETPC(); uint64_t destlen = env->regs[r1 + 1]; -uint64_t dest = env->regs[r1]; +uint64_t dest = get_address(env, r1); uint64_t srclen = env->regs[r3 + 1]; -uint64_t src = env->regs[r3]; +uint64_t src = get_address(env, r3); uint8_t pad = a2 & 0xff; uint8_t v; uint32_t cc; @@ -593,8 +586,6 @@ uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, if (!(env->psw.mask & PSW_MASK_64)) { destlen = (uint32_t)destlen; srclen = (uint32_t)srclen; -dest &= 0x7fff; -src &= 0x7fff; } if (destlen == srclen) { @@ -634,9 +625,9 @@ uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, { uintptr_t ra = GETPC(); uint64_t destlen = env->regs[r1 + 1]; -uint64_t dest = get_address_31fix(env, r1); +uint64_t dest = get_address(env, r1); uint64_t srclen = env->regs[r3 + 1]; -uint64_t src = get_address_31fix(env, r3); +uint64_t src = get_address(env, r3); uint8_t pad = a2 & 0xff; uint32_t cc = 0; @@ -1020,7 +1011,7 @@ uint32_t HELPER(testblock)(CPUS390XState *env, uint64_t real_addr) uint64_t abs_addr; int i; -real_addr = fix_address(env, real_addr); +real_addr = wrap_address(env, real_addr); abs_addr = mmu
[Qemu-devel] [PULL 47/69] target/s390x: implement STORE PAIR TO QUADWORD
From: Aurelien Jarno Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-9-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 2 ++ target/s390x/mem_helper.c | 12 target/s390x/translate.c | 6 ++ 4 files changed, 21 insertions(+) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index ca78d1b..596fec2 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -88,6 +88,7 @@ DEF_HELPER_FLAGS_1(popcnt, TCG_CALL_NO_RWG_SE, i64, i64) DEF_HELPER_FLAGS_1(stfl, TCG_CALL_NO_RWG, void, env) DEF_HELPER_2(stfle, i32, env, i64) DEF_HELPER_FLAGS_2(lpq, TCG_CALL_NO_WG, i64, env, i64) +DEF_HELPER_FLAGS_4(stpq, TCG_CALL_NO_WG, void, env, i64, i64, i64) #ifndef CONFIG_USER_ONLY DEF_HELPER_3(servc, i32, env, i64, i64) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 53c86d5..5314162 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -770,6 +770,8 @@ /* STORE ACCESS MULTIPLE */ C(0x9b00, STAM,RS_a, Z, 0, a2, 0, 0, stam, 0) C(0xeb9b, STAMY, RSY_a, LD, 0, a2, 0, 0, stam, 0) +/* STORE PAIR TO QUADWORD */ +C(0xe38e, STPQ,RXY_a, Z, 0, a2, r1_P, 0, stpq, 0) /* SUBTRACT */ C(0x1b00, SR, RR_a, Z, r1, r2, new, r1_32, sub, subs32) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 4f34f87..15b5f45 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -1250,6 +1250,18 @@ uint64_t HELPER(lpq)(CPUS390XState *env, uint64_t addr) return int128_gethi(v); } +/* store pair to quadword */ +void HELPER(stpq)(CPUS390XState *env, uint64_t addr, + uint64_t low, uint64_t high) +{ +uintptr_t ra = GETPC(); +int mem_idx = cpu_mmu_index(env, false); +TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx); + +Int128 v = int128_make128(low, high); +helper_atomic_sto_be_mmu(env, addr, v, oi, ra); +} + /* Execute instruction. This instruction executes an insn modified with the contents of r1. It does not change the executed instruction in memory; it does not change the program counter. diff --git a/target/s390x/translate.c b/target/s390x/translate.c index ec61590..6635877 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -4019,6 +4019,12 @@ static ExitStatus op_stmh(DisasContext *s, DisasOps *o) return NO_EXIT; } +static ExitStatus op_stpq(DisasContext *s, DisasOps *o) +{ +gen_helper_stpq(cpu_env, o->in2, o->out2, o->out); +return NO_EXIT; +} + static ExitStatus op_srst(DisasContext *s, DisasOps *o) { gen_helper_srst(o->in1, cpu_env, regs[0], o->in1, o->in2); -- 2.9.4
[Qemu-devel] [PULL 38/69] target/s390x: Re-implement a few EXECUTE target insns directly
While the previous patch is required for proper conformance, the vast majority of target insns are MVC and XC for implementing memmove and memset respectively. The next most common are CLC, TR, and SVC. Implementing these (and a few others for which we already have an implementation) directly is faster than going through full translation to a TB. Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 66 --- 1 file changed, 51 insertions(+), 15 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 3a77edc..e35571e 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -200,31 +200,30 @@ uint32_t HELPER(oc)(CPUS390XState *env, uint32_t l, uint64_t dest, } /* memmove */ -static void do_helper_mvc(CPUS390XState *env, uint32_t l, uint64_t dest, - uint64_t src, uintptr_t ra) +static uint32_t do_helper_mvc(CPUS390XState *env, uint32_t l, uint64_t dest, + uint64_t src, uintptr_t ra) { uint32_t i; HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n", __func__, l, dest, src); +/* mvc and memmove do not behave the same when areas overlap! */ /* mvc with source pointing to the byte after the destination is the same as memset with the first source byte */ if (dest == src + 1) { fast_memset(env, dest, cpu_ldub_data_ra(env, src, ra), l + 1, ra); -return; -} - -/* mvc and memmove do not behave the same when areas overlap! */ -if (dest < src || src + l < dest) { +} else if (dest < src || src + l < dest) { fast_memmove(env, dest, src, l + 1, ra); -return; +} else { +/* slow version with byte accesses which always work */ +for (i = 0; i <= l; i++) { +uint8_t x = cpu_ldub_data_ra(env, src + i, ra); +cpu_stb_data_ra(env, dest + i, x, ra); +} } -/* slow version with byte accesses which always work */ -for (i = 0; i <= l; i++) { -cpu_stb_data_ra(env, dest + i, cpu_ldub_data_ra(env, src + i, ra), ra); -} +return env->cc_op; } void HELPER(mvc)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) @@ -692,8 +691,8 @@ void HELPER(unpk)(CPUS390XState *env, uint32_t len, uint64_t dest, } } -static void do_helper_tr(CPUS390XState *env, uint32_t len, uint64_t array, - uint64_t trans, uintptr_t ra) +static uint32_t do_helper_tr(CPUS390XState *env, uint32_t len, uint64_t array, + uint64_t trans, uintptr_t ra) { uint32_t i; @@ -702,12 +701,14 @@ static void do_helper_tr(CPUS390XState *env, uint32_t len, uint64_t array, uint8_t new_byte = cpu_ldub_data_ra(env, trans + byte, ra); cpu_stb_data_ra(env, array + i, new_byte, ra); } + +return env->cc_op; } void HELPER(tr)(CPUS390XState *env, uint32_t len, uint64_t array, uint64_t trans) { -return do_helper_tr(env, len, array, trans, GETPC()); +do_helper_tr(env, len, array, trans, GETPC()); } uint64_t HELPER(tre)(CPUS390XState *env, uint64_t array, @@ -1221,6 +1222,41 @@ void HELPER(ex)(CPUS390XState *env, uint32_t ilen, uint64_t r1, uint64_t addr) g_assert_not_reached(); } +/* The very most common cases can be sped up by avoiding a new TB. */ +if ((opc & 0xf0) == 0xd0) { +typedef uint32_t (*dx_helper)(CPUS390XState *, uint32_t, uint64_t, + uint64_t, uintptr_t); +static const dx_helper dx[16] = { +[0x2] = do_helper_mvc, +[0x4] = do_helper_nc, +[0x5] = do_helper_clc, +[0x6] = do_helper_oc, +[0x7] = do_helper_xc, +[0xc] = do_helper_tr, +[0xd] = do_helper_trt, +}; +dx_helper helper = dx[opc & 0xf]; + +if (helper) { +uint32_t l = extract64(insn, 48, 8); +uint32_t b1 = extract64(insn, 44, 4); +uint32_t d1 = extract64(insn, 32, 12); +uint32_t b2 = extract64(insn, 28, 4); +uint32_t d2 = extract64(insn, 16, 12); +uint64_t a1 = get_address(env, 0, b1, d1); +uint64_t a2 = get_address(env, 0, b2, d2); + +env->cc_op = helper(env, l, a1, a2, 0); +env->psw.addr += ilen; +return; +} +} else if (opc == 0x0a) { +env->int_svc_code = extract64(insn, 48, 8); +env->int_svc_ilen = ilen; +helper_exception(env, EXCP_SVC); +g_assert_not_reached(); +} + /* Record the insn we want to execute as well as the ilen to use during the execution of the target insn. This will also ensure that ex_value is non-zero, which flags that we are in a state -- 2.9.4
[Qemu-devel] [PULL 31/69] target/s390x: Fix some helper_ex problems
(1) The OR of the low bits or R1 into INSN were not being done consistently; it was forgotten along all but the SVC path. (2) The setting of ILEN was wrong on SVC path for EXRL. (3) The data load for ICM read too much. Fix these by consolidating data load at the beginning, using get_ilen to control the number of bytes loaded, and ORing in the byte from R1. Use extract64 from the full aligned insn to extract arguments. Pass in ILEN rather than RET as the more natural way to give the required data along the SVC path. Modify ENV->CC_OP directly rather than include it in the functional interface. Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/helper.h | 2 +- target/s390x/mem_helper.c | 135 +- target/s390x/translate.c | 8 +-- 3 files changed, 78 insertions(+), 67 deletions(-) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index ea35834..3819409 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -14,7 +14,7 @@ DEF_HELPER_4(srst, i64, env, i64, i64, i64) DEF_HELPER_4(clst, i64, env, i64, i64, i64) DEF_HELPER_FLAGS_4(mvpg, TCG_CALL_NO_WG, i32, env, i64, i64, i64) DEF_HELPER_4(mvst, i64, env, i64, i64, i64) -DEF_HELPER_5(ex, i32, env, i32, i64, i64, i64) +DEF_HELPER_4(ex, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(stam, TCG_CALL_NO_WG, void, env, i32, i64, i32) DEF_HELPER_FLAGS_4(lam, TCG_CALL_NO_WG, void, env, i32, i64, i32) DEF_HELPER_4(mvcle, i32, env, i32, i64, i32) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index a73d486..fa03129 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -1245,76 +1245,87 @@ uint64_t HELPER(lra)(CPUS390XState *env, uint64_t addr) in other words: tricky... currently implemented by interpreting the cases it is most commonly used. */ -uint32_t HELPER(ex)(CPUS390XState *env, uint32_t cc, uint64_t v1, -uint64_t addr, uint64_t ret) +void HELPER(ex)(CPUS390XState *env, uint32_t ilen, uint64_t r1, uint64_t addr) { S390CPU *cpu = s390_env_get_cpu(env); -uint16_t insn = cpu_lduw_code(env, addr); - -HELPER_LOG("%s: v1 0x%lx addr 0x%lx insn 0x%x\n", __func__, v1, addr, - insn); -if ((insn & 0xf0ff) == 0xd000) { -uint32_t l, insn2, b1, b2, d1, d2; - -l = v1 & 0xff; -insn2 = cpu_ldl_code(env, addr + 2); -b1 = (insn2 >> 28) & 0xf; -b2 = (insn2 >> 12) & 0xf; -d1 = (insn2 >> 16) & 0xfff; -d2 = insn2 & 0xfff; -switch (insn & 0xf00) { -case 0x200: +uint64_t insn = cpu_lduw_code(env, addr); +uint8_t opc = insn >> 8; + +/* Or in the contents of R1[56:63]. */ +insn |= r1 & 0xff; + +/* Load the rest of the instruction. */ +insn <<= 48; +switch (get_ilen(opc)) { +case 2: +break; +case 4: +insn |= (uint64_t)cpu_lduw_code(env, addr + 2) << 32; +break; +case 6: +insn |= (uint64_t)(uint32_t)cpu_ldl_code(env, addr + 2) << 16; +break; +default: +g_assert_not_reached(); +} + +HELPER_LOG("%s: addr 0x%lx insn 0x%" PRIx64 "\n", __func__, addr, insn); + +if ((opc & 0xf0) == 0xd0) { +uint32_t l, b1, b2, d1, d2; + +l = extract64(insn, 48, 8); +b1 = extract64(insn, 44, 4); +b2 = extract64(insn, 28, 4); +d1 = extract64(insn, 32, 12); +d2 = extract64(insn, 16, 12); +switch (opc & 0xf) { +case 0x2: do_helper_mvc(env, l, get_address(env, 0, b1, d1), get_address(env, 0, b2, d2), 0); -break; -case 0x400: -cc = do_helper_nc(env, l, get_address(env, 0, b1, d1), - get_address(env, 0, b2, d2), 0); -break; -case 0x500: -cc = do_helper_clc(env, l, get_address(env, 0, b1, d1), - get_address(env, 0, b2, d2), 0); -break; -case 0x600: -cc = do_helper_oc(env, l, get_address(env, 0, b1, d1), - get_address(env, 0, b2, d2), 0); -break; -case 0x700: -cc = do_helper_xc(env, l, get_address(env, 0, b1, d1), - get_address(env, 0, b2, d2), 0); -break; -case 0xc00: +return; +case 0x4: +env->cc_op = do_helper_nc(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2), 0); +return; +case 0x5: +env->cc_op = do_helper_clc(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2), 0); +return; +case 0x6: +env->cc_op = do_helper_oc(env, l, get_address(env, 0, b1, d1), + get_address(env, 0, b2, d2), 0); +return; +case 0x7: +env->
[Qemu-devel] [PULL 54/69] target/s390x: improve 24-bit and 31-bit addresses write
From: Aurelien Jarno Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-16-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 37 ++--- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 2425bfc..2113494 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -384,6 +384,29 @@ static inline uint64_t get_address(CPUS390XState *env, int reg) return wrap_address(env, env->regs[reg]); } +static inline void set_address(CPUS390XState *env, int reg, uint64_t address) +{ +if (env->psw.mask & PSW_MASK_64) { +/* 64-Bit mode */ +env->regs[reg] = address; +} else { +if (!(env->psw.mask & PSW_MASK_32)) { +/* 24-Bit mode. According to the PoO it is implementation +dependent if bits 32-39 remain unchanged or are set to +zeros. Choose the former so that the function can also be +used for TRT. */ +env->regs[reg] = deposit64(env->regs[reg], 0, 24, address); +} else { +/* 31-Bit mode. According to the PoO it is implementation +dependent if bit 32 remains unchanged or is set to zero. +Choose the latter so that the function can also be used for +TRT. */ +address &= 0x7fff; +env->regs[reg] = deposit64(env->regs[reg], 0, 32, address); +} +} +} + /* search string (c is byte to search, r2 is string, r1 end of string) */ uint64_t HELPER(srst)(CPUS390XState *env, uint64_t r0, uint64_t end, uint64_t str) @@ -564,8 +587,8 @@ uint32_t HELPER(mvcl)(CPUS390XState *env, uint32_t r1, uint32_t r2) env->regs[r1 + 1] = destlen; /* can't use srclen here, we trunc'ed it */ env->regs[r2 + 1] -= src - env->regs[r2]; -env->regs[r1] = dest; -env->regs[r2] = src; +set_address(env, r1, dest); +set_address(env, r2, src); return cc; } @@ -613,8 +636,8 @@ uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, /* can't use srclen here, we trunc'ed it */ /* FIXME: 31-bit mode! */ env->regs[r3 + 1] -= src - env->regs[r3]; -env->regs[r1] = dest; -env->regs[r3] = src; +set_address(env, r1, dest); +set_address(env, r3, src); return cc; } @@ -651,8 +674,8 @@ uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, env->regs[r1 + 1] = destlen; /* can't use srclen here, we trunc'ed it */ env->regs[r3 + 1] -= src - env->regs[r3]; -env->regs[r1] = dest; -env->regs[r3] = src; +set_address(env, r1, dest); +set_address(env, r3, src); return cc; } @@ -858,7 +881,7 @@ static uint32_t do_helper_trt(CPUS390XState *env, uint32_t len, uint64_t array, uint8_t sbyte = cpu_ldub_data_ra(env, trans + byte, ra); if (sbyte != 0) { -env->regs[1] = array + i; +set_address(env, 1, array + i); env->regs[2] = deposit64(env->regs[2], 0, 8, sbyte); return (i == len) ? 2 : 1; } -- 2.9.4
[Qemu-devel] [PULL 42/69] target/s390x: implement local-TLB-clearing in IPTE
From: Aurelien Jarno And at the same time make IPTE SMP aware. Reviewed-by: Thomas Huth Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-4-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 2 +- target/s390x/mem_helper.c | 21 + target/s390x/translate.c | 6 +- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index cc451c7..3f5a05d 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -111,7 +111,7 @@ DEF_HELPER_4(mvcs, i32, env, i64, i64, i64) DEF_HELPER_4(mvcp, i32, env, i64, i64, i64) DEF_HELPER_4(sigp, i32, env, i64, i32, i64) DEF_HELPER_FLAGS_2(sacf, TCG_CALL_NO_WG, void, env, i64) -DEF_HELPER_FLAGS_3(ipte, TCG_CALL_NO_RWG, void, env, i64, i64) +DEF_HELPER_FLAGS_4(ipte, TCG_CALL_NO_RWG, void, env, i64, i64, i32) DEF_HELPER_FLAGS_1(ptlb, TCG_CALL_NO_RWG, void, env) DEF_HELPER_FLAGS_1(purge, TCG_CALL_NO_RWG, void, env) DEF_HELPER_2(lra, i64, env, i64) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 0ebd65d..ddbebcd 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -1073,17 +1073,16 @@ uint32_t HELPER(mvcp)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2) } /* invalidate pte */ -void HELPER(ipte)(CPUS390XState *env, uint64_t pto, uint64_t vaddr) +void HELPER(ipte)(CPUS390XState *env, uint64_t pto, uint64_t vaddr, + uint32_t m4) { CPUState *cs = CPU(s390_env_get_cpu(env)); uint64_t page = vaddr & TARGET_PAGE_MASK; uint64_t pte_addr, pte; -/* XXX broadcast to other CPUs */ - /* Compute the page table entry address */ pte_addr = (pto & _SEGMENT_ENTRY_ORIGIN); -pte_addr += (vaddr & _VADDR_PX) >> 9; +pte_addr += (vaddr & VADDR_PX) >> 9; /* Mark the page table entry as invalid */ pte = ldq_phys(cs->as, pte_addr); @@ -1092,13 +1091,19 @@ void HELPER(ipte)(CPUS390XState *env, uint64_t pto, uint64_t vaddr) /* XXX we exploit the fact that Linux passes the exact virtual address here - it's not obliged to! */ -tlb_flush_page(cs, page); +/* XXX: the LC bit should be considered as 0 if the local-TLB-clearing + facility is not installed. */ +if (m4 & 1) { +tlb_flush_page(cs, page); +} else { +tlb_flush_page_all_cpus_synced(cs, page); +} /* XXX 31-bit hack */ -if (page & 0x8000) { -tlb_flush_page(cs, page & ~0x8000); +if (m4 & 1) { +tlb_flush_page(cs, page ^ 0x8000); } else { -tlb_flush_page(cs, page | 0x8000); +tlb_flush_page_all_cpus_synced(cs, page ^ 0x8000); } } diff --git a/target/s390x/translate.c b/target/s390x/translate.c index f759818..f160b62 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2352,8 +2352,12 @@ static ExitStatus op_ipm(DisasContext *s, DisasOps *o) #ifndef CONFIG_USER_ONLY static ExitStatus op_ipte(DisasContext *s, DisasOps *o) { +TCGv_i32 m4; + check_privileged(s); -gen_helper_ipte(cpu_env, o->in1, o->in2); +m4 = tcg_const_i32(get_field(s->fields, m4)); +gen_helper_ipte(cpu_env, o->in1, o->in2, m4); +tcg_temp_free_i32(m4); return NO_EXIT; } -- 2.9.4
[Qemu-devel] [PULL 48/69] target/s390x: implement COMPARE AND SIGNAL
From: Aurelien Jarno These functions differ from COMPARE by generating an exception for a QNaN input. Use the non quiet version of floatXX_compare. Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-10-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/fpu_helper.c | 27 +++ target/s390x/helper.h | 3 +++ target/s390x/insn-data.def | 6 ++ target/s390x/translate.c | 21 + 4 files changed, 57 insertions(+) diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c index e604e9f..26f124f 100644 --- a/target/s390x/fpu_helper.c +++ b/target/s390x/fpu_helper.c @@ -585,6 +585,33 @@ uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint32_t m3) return RET128(ret); } +/* 32-bit FP compare and signal */ +uint32_t HELPER(keb)(CPUS390XState *env, uint64_t f1, uint64_t f2) +{ +int cmp = float32_compare(f1, f2, &env->fpu_status); +handle_exceptions(env, GETPC()); +return float_comp_to_cc(env, cmp); +} + +/* 64-bit FP compare and signal */ +uint32_t HELPER(kdb)(CPUS390XState *env, uint64_t f1, uint64_t f2) +{ +int cmp = float64_compare(f1, f2, &env->fpu_status); +handle_exceptions(env, GETPC()); +return float_comp_to_cc(env, cmp); +} + +/* 128-bit FP compare and signal */ +uint32_t HELPER(kxb)(CPUS390XState *env, uint64_t ah, uint64_t al, + uint64_t bh, uint64_t bl) +{ +int cmp = float128_compare(make_float128(ah, al), + make_float128(bh, bl), + &env->fpu_status); +handle_exceptions(env, GETPC()); +return float_comp_to_cc(env, cmp); +} + /* 32-bit FP multiply and add */ uint64_t HELPER(maeb)(CPUS390XState *env, uint64_t f1, uint64_t f2, uint64_t f3) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index 596fec2..4ada894 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -89,6 +89,9 @@ DEF_HELPER_FLAGS_1(stfl, TCG_CALL_NO_RWG, void, env) DEF_HELPER_2(stfle, i32, env, i64) DEF_HELPER_FLAGS_2(lpq, TCG_CALL_NO_WG, i64, env, i64) DEF_HELPER_FLAGS_4(stpq, TCG_CALL_NO_WG, void, env, i64, i64, i64) +DEF_HELPER_FLAGS_3(keb, TCG_CALL_NO_WG, i32, env, i64, i64) +DEF_HELPER_FLAGS_3(kdb, TCG_CALL_NO_WG, i32, env, i64, i64) +DEF_HELPER_FLAGS_5(kxb, TCG_CALL_NO_WG, i32, env, i64, i64, i64, i64) #ifndef CONFIG_USER_ONLY DEF_HELPER_3(servc, i32, env, i64, i64) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 5314162..0127894 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -154,6 +154,12 @@ C(0xb349, CXBR,RRE, Z, x1_o, x2_o, 0, 0, cxb, 0) C(0xed09, CEB, RXE, Z, e1, m2_32u, 0, 0, ceb, 0) C(0xed19, CDB, RXE, Z, f1_o, m2_64, 0, 0, cdb, 0) +/* COMPARE AND SIGNAL */ +C(0xb308, KEBR,RRE, Z, e1, e2, 0, 0, keb, 0) +C(0xb318, KDBR,RRE, Z, f1_o, f2_o, 0, 0, kdb, 0) +C(0xb348, KXBR,RRE, Z, x1_o, x2_o, 0, 0, kxb, 0) +C(0xed08, KEB, RXE, Z, e1, m2_32u, 0, 0, keb, 0) +C(0xed18, KDB, RXE, Z, f1_o, m2_64, 0, 0, kdb, 0) /* COMPARE IMMEDIATE */ C(0xc20d, CFI, RIL_a, EI, r1, i2, 0, 0, 0, cmps32) C(0xc20c, CGFI,RIL_a, EI, r1, i2, 0, 0, 0, cmps64) diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 6635877..30d0575 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2369,6 +2369,27 @@ static ExitStatus op_iske(DisasContext *s, DisasOps *o) } #endif +static ExitStatus op_keb(DisasContext *s, DisasOps *o) +{ +gen_helper_keb(cc_op, cpu_env, o->in1, o->in2); +set_cc_static(s); +return NO_EXIT; +} + +static ExitStatus op_kdb(DisasContext *s, DisasOps *o) +{ +gen_helper_kdb(cc_op, cpu_env, o->in1, o->in2); +set_cc_static(s); +return NO_EXIT; +} + +static ExitStatus op_kxb(DisasContext *s, DisasOps *o) +{ +gen_helper_kxb(cc_op, cpu_env, o->out, o->out2, o->in1, o->in2); +set_cc_static(s); +return NO_EXIT; +} + static ExitStatus op_laa(DisasContext *s, DisasOps *o) { /* The real output is indeed the original value in memory; -- 2.9.4
[Qemu-devel] [PULL 32/69] target/s390x: Fix EXECUTE with R1==0
The PoO specifies that when R1==0, no ORing into the insn loaded from storage takes place. Load a zero for this case. Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- target/s390x/insn-data.def | 4 ++-- target/s390x/translate.c | 14 +- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index cac0f51..3c3541c 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -327,9 +327,9 @@ C(0xeb57, XIY, SIY, LD, m1_8u, i2_8u, new, m1_8, xor, nz64) /* EXECUTE */ -C(0x4400, EX, RX_a, Z, r1_o, a2, 0, 0, ex, 0) +C(0x4400, EX, RX_a, Z, 0, a2, 0, 0, ex, 0) /* EXECUTE RELATIVE LONG */ -C(0xc600, EXRL,RIL_b, EE, r1_o, ri2, 0, 0, ex, 0) +C(0xc600, EXRL,RIL_b, EE, 0, ri2, 0, 0, ex, 0) /* EXTRACT ACCESS */ C(0xb24f, EAR, RRE, Z, 0, 0, new, r1_32, ear, 0) diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 921a842..b7b4843 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2159,15 +2159,27 @@ static ExitStatus op_ex(DisasContext *s, DisasOps *o) MVC inside of memcpy, which needs a helper call anyway. So perhaps this doesn't bear thinking about any further. */ +int r1 = get_field(s->fields, r1); TCGv_i32 ilen; +TCGv_i64 v1; update_psw_addr(s); gen_op_calc_cc(s); +if (r1 == 0) { +v1 = tcg_const_i64(0); +} else { +v1 = regs[r1]; +} + ilen = tcg_const_i32(s->next_pc - s->pc); -gen_helper_ex(cpu_env, ilen, o->in1, o->in2); +gen_helper_ex(cpu_env, ilen, v1, o->in2); tcg_temp_free_i32(ilen); +if (r1 == 0) { +tcg_temp_free_i64(v1); +} + return NO_EXIT; } -- 2.9.4
[Qemu-devel] [PULL 58/69] target/s390x: fix adj_len_to_page
From: Aurelien Jarno adj_len_to_page doesn't return the correct result when the address is already page aligned and the length is bigger than a page. Fix that. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-20-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index aaa347c..6dfa087 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -61,7 +61,7 @@ static inline uint32_t adj_len_to_page(uint32_t len, uint64_t addr) { #ifndef CONFIG_USER_ONLY if ((addr & ~TARGET_PAGE_MASK) + len - 1 >= TARGET_PAGE_SIZE) { -return -addr & ~TARGET_PAGE_MASK; +return -(addr | TARGET_PAGE_MASK); } #endif return len; -- 2.9.4
[Qemu-devel] [PULL 49/69] target/s390x: implement MOVE INVERSE
From: Aurelien Jarno Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-11-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 2 ++ target/s390x/mem_helper.c | 12 target/s390x/translate.c | 8 4 files changed, 23 insertions(+) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index 4ada894..a618fe5 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -3,6 +3,7 @@ DEF_HELPER_FLAGS_4(nc, TCG_CALL_NO_WG, i32, env, i32, i64, i64) DEF_HELPER_FLAGS_4(oc, TCG_CALL_NO_WG, i32, env, i32, i64, i64) DEF_HELPER_FLAGS_4(xc, TCG_CALL_NO_WG, i32, env, i32, i64, i64) DEF_HELPER_FLAGS_4(mvc, TCG_CALL_NO_WG, void, env, i32, i64, i64) +DEF_HELPER_FLAGS_4(mvcin, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(clc, TCG_CALL_NO_WG, i32, env, i32, i64, i64) DEF_HELPER_3(mvcl, i32, env, i32, i32) DEF_HELPER_FLAGS_4(clm, TCG_CALL_NO_WG, i32, env, i32, i32, i64) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 0127894..c8f7761 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -572,6 +572,8 @@ C(0xe548, MVGHI, SIL, GIE, la1, i2, 0, m1_64, mov2, 0) C(0x9200, MVI, SI,Z, la1, i2, 0, m1_8, mov2, 0) C(0xeb52, MVIY,SIY, LD, la1, i2, 0, m1_8, mov2, 0) +/* MOVE INVERSE */ +C(0xe800, MVCIN, SS_a, Z, la1, a2, 0, 0, mvcin, 0) /* MOVE LONG */ C(0x0e00, MVCL,RR_a, Z, 0, 0, 0, 0, mvcl, 0) /* MOVE LONG EXTENDED */ diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 15b5f45..eef7547 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -231,6 +231,18 @@ void HELPER(mvc)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) do_helper_mvc(env, l, dest, src, GETPC()); } +/* move inverse */ +void HELPER(mvcin)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) +{ +uintptr_t ra = GETPC(); +int i; + +for (i = 0; i <= l; i++) { +uint8_t v = cpu_ldub_data_ra(env, src - i, ra); +cpu_stb_data_ra(env, dest + i, v, ra); +} +} + /* compare unsigned byte arrays */ static uint32_t do_helper_clc(CPUS390XState *env, uint32_t l, uint64_t s1, uint64_t s2, uintptr_t ra) diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 30d0575..61373df 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2940,6 +2940,14 @@ static ExitStatus op_mvc(DisasContext *s, DisasOps *o) return NO_EXIT; } +static ExitStatus op_mvcin(DisasContext *s, DisasOps *o) +{ +TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); +gen_helper_mvcin(cpu_env, l, o->addr1, o->in2); +tcg_temp_free_i32(l); +return NO_EXIT; +} + static ExitStatus op_mvcl(DisasContext *s, DisasOps *o) { TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); -- 2.9.4
[Qemu-devel] [PULL 57/69] target/s390x: implement COMPARE LOGICAL LONG
From: Aurelien Jarno As CLCL and CLCLE mostly differ by their operands, use a common do_clcl helper. Another difference is that CLCL is not interruptible. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-19-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 2 ++ target/s390x/mem_helper.c | 84 +- target/s390x/translate.c | 21 4 files changed, 84 insertions(+), 24 deletions(-) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index ba21e4d..546beec 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -6,6 +6,7 @@ DEF_HELPER_FLAGS_4(mvc, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(mvcin, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(clc, TCG_CALL_NO_WG, i32, env, i32, i64, i64) DEF_HELPER_3(mvcl, i32, env, i32, i32) +DEF_HELPER_3(clcl, i32, env, i32, i32) DEF_HELPER_FLAGS_4(clm, TCG_CALL_NO_WG, i32, env, i32, i32, i64) DEF_HELPER_FLAGS_3(divs32, TCG_CALL_NO_WG, s64, env, s64, s64) DEF_HELPER_FLAGS_3(divu32, TCG_CALL_NO_WG, i64, env, i64, i64) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index b40611b..1aa2b8b 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -216,6 +216,8 @@ C(0xc60e, CLGFRL, RIL_b, GIE, r1_o, mri2_32u, 0, 0, 0, cmpu64) C(0xc607, CLHRL, RIL_b, GIE, r1_o, mri2_16u, 0, 0, 0, cmpu32) C(0xc606, CLGHRL, RIL_b, GIE, r1_o, mri2_16u, 0, 0, 0, cmpu64) +/* COMPARE LOGICAL LONG */ +C(0x0f00, CLCL,RR_a, Z, 0, 0, 0, 0, clcl, 0) /* COMPARE LOGICAL LONG EXTENDED */ C(0xa900, CLCLE, RS_a, Z, 0, a2, 0, 0, clcle, 0) /* COMPARE LOGICAL CHARACTERS UNDER MASK */ diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index e992fd9..aaa347c 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -661,17 +661,14 @@ uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, return cc; } -/* compare logical long extended memcompare insn with padding */ -uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, - uint32_t r3) -{ -uintptr_t ra = GETPC(); -uint64_t src1len = get_length(env, r1 + 1); -uint64_t src1 = get_address(env, r1); -uint64_t src3len = get_length(env, r3 + 1); -uint64_t src3 = get_address(env, r3); -uint8_t pad = a2 & 0xff; -uint64_t len = MAX(src1len, src3len); +/* compare logical long helper */ +static inline uint32_t do_clcl(CPUS390XState *env, + uint64_t *src1, uint64_t *src1len, + uint64_t *src3, uint64_t *src3len, + uint8_t pad, uint64_t limit, + uintptr_t ra) +{ +uint64_t len = MAX(*src1len, *src3len); uint32_t cc = 0; if (!len) { @@ -679,9 +676,9 @@ uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, } /* Lest we fail to service interrupts in a timely manner, limit the - amount of work we're willing to do. For now, let's cap at 8k. */ -if (len > 0x2000) { -len = 0x2000; + amount of work we're willing to do. */ +if (len > limit) { +len = limit; cc = 3; } @@ -689,11 +686,11 @@ uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint8_t v1 = pad; uint8_t v3 = pad; -if (src1len) { -v1 = cpu_ldub_data_ra(env, src1, ra); +if (*src1len) { +v1 = cpu_ldub_data_ra(env, *src1, ra); } -if (src3len) { -v3 = cpu_ldub_data_ra(env, src3, ra); +if (*src3len) { +v3 = cpu_ldub_data_ra(env, *src3, ra); } if (v1 != v3) { @@ -701,16 +698,55 @@ uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, break; } -if (src1len) { -src1++; -src1len--; +if (*src1len) { +*src1 += 1; +*src1len -= 1; } -if (src3len) { -src3++; -src3len--; +if (*src3len) { +*src3 += 1; +*src3len -= 1; } } +return cc; +} + + +/* compare logical long */ +uint32_t HELPER(clcl)(CPUS390XState *env, uint32_t r1, uint32_t r2) +{ +uintptr_t ra = GETPC(); +uint64_t src1len = extract64(env->regs[r1 + 1], 0, 24); +uint64_t src1 = get_address(env, r1); +uint64_t src3len = extract64(env->regs[r2 + 1], 0, 24); +uint64_t src3 = get_address(env, r2); +uint8_t pad = env->regs[r2 + 1] >> 24; +uint32_t cc; + +cc = do_clcl(env, &src1, &src1len, &src3, &src3len, pad, -1, ra); + +env->regs[r1 + 1] = deposit64(env->regs[r1 + 1], 0, 24, src1len); +env->regs[r2 + 1] = deposit64(env->regs[r2 + 1], 0, 24, src3len); +set_address(e
[Qemu-devel] [PULL 59/69] target/s390x: improve MOVE LONG and MOVE LONG EXTENDED
From: Aurelien Jarno As MVCL and MVCLE only differ by their operands, use a common do_mvcl helper. Optimize it calling fast_memmove and fast_memset. Correctly write back addresses. Check that r1 and r2/r3 registers are even. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-21-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 90 +-- target/s390x/translate.c | 40 +++-- 2 files changed, 70 insertions(+), 60 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 6dfa087..cb0ec3e 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -576,49 +576,60 @@ void HELPER(stam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) } } -/* move long */ -uint32_t HELPER(mvcl)(CPUS390XState *env, uint32_t r1, uint32_t r2) +/* move long helper */ +static inline uint32_t do_mvcl(CPUS390XState *env, + uint64_t *dest, uint64_t *destlen, + uint64_t *src, uint64_t *srclen, + uint8_t pad, uintptr_t ra) { -uintptr_t ra = GETPC(); -uint64_t destlen = env->regs[r1 + 1] & 0xff; -uint64_t dest = get_address(env, r1); -uint64_t srclen = env->regs[r2 + 1] & 0xff; -uint64_t src = get_address(env, r2); -uint8_t pad = env->regs[r2 + 1] >> 24; -uint8_t v; +uint64_t len = MIN(*srclen, *destlen); uint32_t cc; -if (destlen == srclen) { +if (*destlen == *srclen) { cc = 0; -} else if (destlen < srclen) { +} else if (*destlen < *srclen) { cc = 1; } else { cc = 2; } -if (srclen > destlen) { -srclen = destlen; -} +/* Copy the src array */ +fast_memmove(env, *dest, *src, len, ra); +*src += len; +*srclen -= len; +*dest += len; +*destlen -= len; -for (; destlen && srclen; src++, dest++, destlen--, srclen--) { -v = cpu_ldub_data_ra(env, src, ra); -cpu_stb_data_ra(env, dest, v, ra); -} +/* Pad the remaining area */ +fast_memset(env, *dest, pad, *destlen, ra); +*dest += *destlen; +*destlen = 0; -for (; destlen; dest++, destlen--) { -cpu_stb_data_ra(env, dest, pad, ra); -} +return cc; +} -env->regs[r1 + 1] = destlen; -/* can't use srclen here, we trunc'ed it */ -env->regs[r2 + 1] -= src - env->regs[r2]; +/* move long */ +uint32_t HELPER(mvcl)(CPUS390XState *env, uint32_t r1, uint32_t r2) +{ +uintptr_t ra = GETPC(); +uint64_t destlen = env->regs[r1 + 1] & 0xff; +uint64_t dest = get_address(env, r1); +uint64_t srclen = env->regs[r2 + 1] & 0xff; +uint64_t src = get_address(env, r2); +uint8_t pad = env->regs[r2 + 1] >> 24; +uint32_t cc; + +cc = do_mvcl(env, &dest, &destlen, &src, &srclen, pad, ra); + +env->regs[r1 + 1] = deposit64(env->regs[r1 + 1], 0, 24, destlen); +env->regs[r2 + 1] = deposit64(env->regs[r2 + 1], 0, 24, srclen); set_address(env, r1, dest); set_address(env, r2, src); return cc; } -/* move long extended another memcopy insn with more bells and whistles */ +/* move long extended */ uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { @@ -627,34 +638,13 @@ uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint64_t dest = get_address(env, r1); uint64_t srclen = get_length(env, r3 + 1); uint64_t src = get_address(env, r3); -uint8_t pad = a2 & 0xff; -uint8_t v; +uint8_t pad = a2; uint32_t cc; -if (destlen == srclen) { -cc = 0; -} else if (destlen < srclen) { -cc = 1; -} else { -cc = 2; -} - -if (srclen > destlen) { -srclen = destlen; -} - -for (; destlen && srclen; src++, dest++, destlen--, srclen--) { -v = cpu_ldub_data_ra(env, src, ra); -cpu_stb_data_ra(env, dest, v, ra); -} - -for (; destlen; dest++, destlen--) { -cpu_stb_data_ra(env, dest, pad, ra); -} +cc = do_mvcl(env, &dest, &destlen, &src, &srclen, pad, ra); -set_length(env, r1 + 1 , destlen); -/* can't use srclen here, we trunc'ed it */ -set_length(env, r3 + 1, env->regs[r3 + 1] - src - env->regs[r3]); +set_length(env, r1 + 1, destlen); +set_length(env, r3 + 1, srclen); set_address(env, r1, dest); set_address(env, r3, src); diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 999d716..729d25d 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2981,22 +2981,42 @@ static ExitStatus op_mvcin(DisasContext *s, DisasOps *o) static ExitStatus op_mvcl(DisasContext *s, DisasOps *o) { -TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); -TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2)); -gen_helper_mvcl(cc_op
[Qemu-devel] [PULL 39/69] target/s390x/cpu_models: Allow some additional feature bits for the "qemu" CPU
From: Thomas Huth Currently we only present the plain z900 feature bits to the guest, but QEMU already emulates some additional features (but not all of the next CPU generation, so we can not use the next CPU level as default yet). Since newer Linux kernels are checking the feature bits and refuse to work if a required feature is missing, it would be nice to have a way to present more of the supported features when we are running with the "qemu" CPU. This patch now adds the supported features to the "full_feat" bitmap, so that additional features can be enabled on the command line now, for example with: qemu-system-s390x -cpu qemu,stfle=true,ldisp=true,eimm=true,stckf=true Acked-by: David Hildenbrand Reviewed-by: Aurelien Jarno Signed-off-by: Thomas Huth Message-Id: <1495704132-5675-1-git-send-email-th...@redhat.com> Signed-off-by: Richard Henderson --- target/s390x/cpu_models.c | 34 +++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c index 8d27363..e5e005a 100644 --- a/target/s390x/cpu_models.c +++ b/target/s390x/cpu_models.c @@ -658,6 +658,30 @@ static void check_compatibility(const S390CPUModel *max_model, "available in the configuration: "); } +/** + * The base TCG CPU model "qemu" is based on the z900. However, we already + * can also emulate some additional features of later CPU generations, so + * we add these additional feature bits here. + */ +static void add_qemu_cpu_model_features(S390FeatBitmap fbm) +{ +static const int feats[] = { +S390_FEAT_STFLE, +S390_FEAT_EXTENDED_IMMEDIATE, +S390_FEAT_LONG_DISPLACEMENT, +S390_FEAT_LONG_DISPLACEMENT_FAST, +S390_FEAT_STORE_CLOCK_FAST, +S390_FEAT_GENERAL_INSTRUCTIONS_EXT, +S390_FEAT_EXECUTE_EXT, +S390_FEAT_STFLE_45, +}; +int i; + +for (i = 0; i < ARRAY_SIZE(feats); i++) { +set_bit(feats[i], fbm); +} +} + static S390CPUModel *get_max_cpu_model(Error **errp) { static S390CPUModel max_model; @@ -670,10 +694,11 @@ static S390CPUModel *get_max_cpu_model(Error **errp) if (kvm_enabled()) { kvm_s390_get_host_cpu_model(&max_model, errp); } else { -/* TCG emulates a z900 */ +/* TCG emulates a z900 (with some optional additional features) */ max_model.def = &s390_cpu_defs[0]; bitmap_copy(max_model.features, max_model.def->default_feat, S390_FEAT_MAX); +add_qemu_cpu_model_features(max_model.features); } if (!*errp) { cached = true; @@ -925,11 +950,14 @@ static void s390_host_cpu_model_initfn(Object *obj) static void s390_qemu_cpu_model_initfn(Object *obj) { +static S390CPUDef s390_qemu_cpu_defs; S390CPU *cpu = S390_CPU(obj); cpu->model = g_malloc0(sizeof(*cpu->model)); -/* TCG emulates a z900 */ -cpu->model->def = &s390_cpu_defs[0]; +/* TCG emulates a z900 (with some optional additional features) */ +memcpy(&s390_qemu_cpu_defs, &s390_cpu_defs[0], sizeof(s390_qemu_cpu_defs)); +add_qemu_cpu_model_features(s390_qemu_cpu_defs.full_feat); +cpu->model->def = &s390_qemu_cpu_defs; bitmap_copy(cpu->model->features, cpu->model->def->default_feat, S390_FEAT_MAX); } -- 2.9.4
[Qemu-devel] [PULL 50/69] target/s390x: implement MOVE NUMERICS
From: Aurelien Jarno Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-12-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 2 ++ target/s390x/mem_helper.c | 13 + target/s390x/translate.c | 8 4 files changed, 24 insertions(+) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index a618fe5..e62e455 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -13,6 +13,7 @@ DEF_HELPER_FLAGS_3(divs64, TCG_CALL_NO_WG, s64, env, s64, s64) DEF_HELPER_FLAGS_4(divu64, TCG_CALL_NO_WG, i64, env, i64, i64, i64) DEF_HELPER_4(srst, i64, env, i64, i64, i64) DEF_HELPER_4(clst, i64, env, i64, i64, i64) +DEF_HELPER_FLAGS_4(mvn, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(mvpg, TCG_CALL_NO_WG, i32, env, i64, i64, i64) DEF_HELPER_4(mvst, i64, env, i64, i64, i64) DEF_HELPER_4(ex, void, env, i32, i64, i64) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index c8f7761..6af7176 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -578,6 +578,8 @@ C(0x0e00, MVCL,RR_a, Z, 0, 0, 0, 0, mvcl, 0) /* MOVE LONG EXTENDED */ C(0xa800, MVCLE, RS_a, Z, 0, a2, 0, 0, mvcle, 0) +/* MOVE NUMERICS */ +C(0xd100, MVN, SS_a, Z, la1, a2, 0, 0, mvn, 0) /* MOVE PAGE */ C(0xb254, MVPG,RRE, Z, r1_o, r2_o, 0, 0, mvpg, 0) /* MOVE STRING */ diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index eef7547..5385278 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -243,6 +243,19 @@ void HELPER(mvcin)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) } } +/* move numerics */ +void HELPER(mvn)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) +{ +uintptr_t ra = GETPC(); +int i; + +for (i = 0; i <= l; i++) { +uint8_t v = cpu_ldub_data_ra(env, dest + i, ra) & 0xf0; +v |= cpu_ldub_data_ra(env, src + i, ra) & 0x0f; +cpu_stb_data_ra(env, dest + i, v, ra); +} +} + /* compare unsigned byte arrays */ static uint32_t do_helper_clc(CPUS390XState *env, uint32_t l, uint64_t s1, uint64_t s2, uintptr_t ra) diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 61373df..4e72112 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2990,6 +2990,14 @@ static ExitStatus op_mvcs(DisasContext *s, DisasOps *o) } #endif +static ExitStatus op_mvn(DisasContext *s, DisasOps *o) +{ +TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); +gen_helper_mvn(cpu_env, l, o->addr1, o->in2); +tcg_temp_free_i32(l); +return NO_EXIT; +} + static ExitStatus op_mvpg(DisasContext *s, DisasOps *o) { gen_helper_mvpg(cc_op, cpu_env, regs[0], o->in1, o->in2); -- 2.9.4
[Qemu-devel] [PULL 43/69] target/s390x: implement TEST AND SET
From: Aurelien Jarno Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-5-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/insn-data.def | 3 +++ target/s390x/translate.c | 10 ++ 2 files changed, 13 insertions(+) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index f818437..0f70ace 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -810,6 +810,9 @@ /* SUPERVISOR CALL */ C(0x0a00, SVC, I, Z, 0, 0, 0, 0, svc, 0) +/* TEST AND SET */ +C(0x9300, TS, S, Z, 0, a2, 0, 0, ts, 0) + /* TEST DATA CLASS */ C(0xed10, TCEB,RXE, Z, e1, a2, 0, 0, tceb, 0) C(0xed11, TCDB,RXE, Z, f1_o, a2, 0, 0, tcdb, 0) diff --git a/target/s390x/translate.c b/target/s390x/translate.c index f160b62..0cfa8cc 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -4129,6 +4129,16 @@ static ExitStatus op_trt(DisasContext *s, DisasOps *o) return NO_EXIT; } +static ExitStatus op_ts(DisasContext *s, DisasOps *o) +{ +TCGv_i32 t1 = tcg_const_i32(0xff); +tcg_gen_atomic_xchg_i32(t1, o->in2, t1, get_mem_index(s), MO_UB); +tcg_gen_extract_i32(cc_op, t1, 7, 1); +tcg_temp_free_i32(t1); +set_cc_static(s); +return NO_EXIT; +} + static ExitStatus op_unpk(DisasContext *s, DisasOps *o) { TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); -- 2.9.4
[Qemu-devel] [PULL 66/69] target/s390x: implement TEST DECIMAL
From: Aurelien Jarno Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-28-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 3 +++ target/s390x/mem_helper.c | 23 +++ target/s390x/translate.c | 9 + 4 files changed, 36 insertions(+) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index dc85a14..c043be6 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -88,6 +88,7 @@ DEF_HELPER_FLAGS_4(pku, TCG_CALL_NO_WG, void, env, i64, i64, i32) DEF_HELPER_FLAGS_4(unpk, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(unpka, TCG_CALL_NO_WG, i32, env, i64, i32, i64) DEF_HELPER_FLAGS_4(unpku, TCG_CALL_NO_WG, i32, env, i64, i32, i64) +DEF_HELPER_FLAGS_3(tp, TCG_CALL_NO_WG, i32, env, i64, i32) DEF_HELPER_FLAGS_4(tr, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_4(tre, i64, env, i64, i64, i64) DEF_HELPER_4(trt, i32, env, i32, i64, i64) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 683f91b..7f554ab 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -856,6 +856,9 @@ C(0xed11, TCDB,RXE, Z, f1_o, a2, 0, 0, tcdb, 0) C(0xed12, TCXB,RXE, Z, x1_o, a2, 0, 0, tcxb, 0) +/* TEST DECIMAL */ +C(0xebc0, TP, RSL, E2, la1, 0, 0, 0, tp, 0) + /* TEST UNDER MASK */ C(0x9100, TM, SI,Z, m1_8u, i2_8u, 0, 0, 0, tm32) C(0xeb51, TMY, SIY, LD, m1_8u, i2_8u, 0, 0, 0, tm32) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 5cb1a8a..a9297c1 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -1088,6 +1088,29 @@ uint32_t HELPER(unpku)(CPUS390XState *env, uint64_t dest, uint32_t destlen, return do_unpkau(env, dest, destlen, 2, src, GETPC()); } +uint32_t HELPER(tp)(CPUS390XState *env, uint64_t dest, uint32_t destlen) +{ +uintptr_t ra = GETPC(); +uint32_t cc = 0; +int i; + +for (i = 0; i < destlen; i++) { +uint8_t b = cpu_ldub_data_ra(env, dest + i, ra); +/* digit */ +cc |= (b & 0xf0) > 0x90 ? 2 : 0; + +if (i == (destlen - 1)) { +/* sign */ +cc |= (b & 0xf) < 0xa ? 1 : 0; +} else { +/* digit */ +cc |= (b & 0xf) > 0x9 ? 2 : 0; +} +} + +return cc; +} + static uint32_t do_helper_tr(CPUS390XState *env, uint32_t len, uint64_t array, uint64_t trans, uintptr_t ra) { diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 747d4eb..a7c564f 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -4313,6 +4313,15 @@ static ExitStatus op_tprot(DisasContext *s, DisasOps *o) #endif +static ExitStatus op_tp(DisasContext *s, DisasOps *o) +{ +TCGv_i32 l1 = tcg_const_i32(get_field(s->fields, l1) + 1); +gen_helper_tp(cc_op, cpu_env, o->addr1, l1); +tcg_temp_free_i32(l1); +set_cc_static(s); +return NO_EXIT; +} + static ExitStatus op_tr(DisasContext *s, DisasOps *o) { TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); -- 2.9.4
[Qemu-devel] [PULL 63/69] target/s390x: implement PACK UNICODE
From: Aurelien Jarno Use a common helper with PACK ASCII as the differences are limited to the stride of the source operand. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-25-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 2 ++ target/s390x/mem_helper.c | 30 +- target/s390x/translate.c | 16 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index 7898064..5b61a0d 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -84,6 +84,7 @@ DEF_HELPER_FLAGS_3(sqxb, TCG_CALL_NO_WG, i64, env, i64, i64) DEF_HELPER_FLAGS_1(cvd, TCG_CALL_NO_RWG_SE, i64, s32) DEF_HELPER_FLAGS_4(pack, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(pka, TCG_CALL_NO_WG, void, env, i64, i64, i32) +DEF_HELPER_FLAGS_4(pku, TCG_CALL_NO_WG, void, env, i64, i64, i32) DEF_HELPER_FLAGS_4(unpk, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(tr, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_4(tre, i64, env, i64, i64, i64) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 41431af..16f788c 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -669,6 +669,8 @@ C(0xf200, PACK,SS_a, Z, la1, a2, 0, 0, pack, 0) /* PACK ASCII */ C(0xe900, PKA, SS_f, E2, la1, a2, 0, 0, pka, 0) +/* PACK UNICODE */ +C(0xe100, PKU, SS_f, E2, la1, a2, 0, 0, pku, 0) /* PREFETCH */ /* Implemented as nops of course. */ diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 425d4b6..d827a12 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -914,10 +914,9 @@ void HELPER(pack)(CPUS390XState *env, uint32_t len, uint64_t dest, uint64_t src) } } -void HELPER(pka)(CPUS390XState *env, uint64_t dest, uint64_t src, - uint32_t srclen) +static inline void do_pkau(CPUS390XState *env, uint64_t dest, uint64_t src, + uint32_t srclen, int ssize, uintptr_t ra) { -uintptr_t ra = GETPC(); int i; /* The destination operand is always 16 bytes long. */ const int destlen = 16; @@ -932,16 +931,16 @@ void HELPER(pka)(CPUS390XState *env, uint64_t dest, uint64_t src, /* Start with a positive sign */ if (i == 0) { b = 0xc; -} else if (srclen > 1) { +} else if (srclen > ssize) { b = cpu_ldub_data_ra(env, src, ra) & 0x0f; -src--; -srclen--; +src -= ssize; +srclen -= ssize; } -if (srclen > 1) { +if (srclen > ssize) { b |= cpu_ldub_data_ra(env, src, ra) << 4; -src--; -srclen--; +src -= ssize; +srclen -= ssize; } cpu_stb_data_ra(env, dest, b, ra); @@ -949,6 +948,19 @@ void HELPER(pka)(CPUS390XState *env, uint64_t dest, uint64_t src, } } + +void HELPER(pka)(CPUS390XState *env, uint64_t dest, uint64_t src, + uint32_t srclen) +{ +do_pkau(env, dest, src, srclen, 1, GETPC()); +} + +void HELPER(pku)(CPUS390XState *env, uint64_t dest, uint64_t src, + uint32_t srclen) +{ +do_pkau(env, dest, src, srclen, 2, GETPC()); +} + void HELPER(unpk)(CPUS390XState *env, uint32_t len, uint64_t dest, uint64_t src) { diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 5093995..d8b0515 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -3317,6 +3317,22 @@ static ExitStatus op_pka(DisasContext *s, DisasOps *o) return NO_EXIT; } +static ExitStatus op_pku(DisasContext *s, DisasOps *o) +{ +int l2 = get_field(s->fields, l2) + 1; +TCGv_i32 l; + +/* The length must be even and should not exceed 64 bytes. */ +if ((l2 & 1) || (l2 > 64)) { +gen_program_exception(s, PGM_SPECIFICATION); +return EXIT_NORETURN; +} +l = tcg_const_i32(l2); +gen_helper_pku(cpu_env, o->addr1, o->in2, l); +tcg_temp_free_i32(l); +return NO_EXIT; +} + static ExitStatus op_popcnt(DisasContext *s, DisasOps *o) { gen_helper_popcnt(o->out, o->in2); -- 2.9.4
[Qemu-devel] [PULL 51/69] target/s390x: implement MOVE WITH OFFSET
From: Aurelien Jarno Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-13-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 4 target/s390x/mem_helper.c | 31 +++ target/s390x/translate.c | 8 4 files changed, 44 insertions(+) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index e62e455..a197b8b 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -14,6 +14,7 @@ DEF_HELPER_FLAGS_4(divu64, TCG_CALL_NO_WG, i64, env, i64, i64, i64) DEF_HELPER_4(srst, i64, env, i64, i64, i64) DEF_HELPER_4(clst, i64, env, i64, i64, i64) DEF_HELPER_FLAGS_4(mvn, TCG_CALL_NO_WG, void, env, i32, i64, i64) +DEF_HELPER_FLAGS_4(mvo, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(mvpg, TCG_CALL_NO_WG, i32, env, i64, i64, i64) DEF_HELPER_4(mvst, i64, env, i64, i64, i64) DEF_HELPER_4(ex, void, env, i32, i64, i64) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 6af7176..47542ee 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -584,6 +584,10 @@ C(0xb254, MVPG,RRE, Z, r1_o, r2_o, 0, 0, mvpg, 0) /* MOVE STRING */ C(0xb255, MVST,RRE, Z, r1_o, r2_o, 0, 0, mvst, 0) +/* MOVE WITH OFFSET */ +/* Really format SS_b, but we pack both lengths into one argument + for the helper call, so we might as well leave one 8-bit field. */ +C(0xf100, MVO, SS_a, Z, la1, a2, 0, 0, mvo, 0) /* MULTIPLY */ C(0x1c00, MR, RR_a, Z, r1p1_32s, r2_32s, new, r1_D32, mul, 0) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 5385278..3601bb9 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -256,6 +256,37 @@ void HELPER(mvn)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) } } +/* move with offset */ +void HELPER(mvo)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) +{ +uintptr_t ra = GETPC(); +int len_dest = l >> 4; +int len_src = l & 0xf; +uint8_t byte_dest, byte_src; +int i; + +src += len_src; +dest += len_dest; + +/* Handle rightmost byte */ +byte_src = cpu_ldub_data_ra(env, src, ra); +byte_dest = cpu_ldub_data_ra(env, dest, ra); +byte_dest = (byte_dest & 0x0f) | (byte_src << 4); +cpu_stb_data_ra(env, dest, byte_dest, ra); + +/* Process remaining bytes from right to left */ +for (i = 1; i <= len_dest; i++) { +byte_dest = byte_src >> 4; +if (len_src - i >= 0) { +byte_src = cpu_ldub_data_ra(env, src - i, ra); +} else { +byte_src = 0; +} +byte_dest |= byte_src << 4; +cpu_stb_data_ra(env, dest - i, byte_dest, ra); +} +} + /* compare unsigned byte arrays */ static uint32_t do_helper_clc(CPUS390XState *env, uint32_t l, uint64_t s1, uint64_t s2, uintptr_t ra) diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 4e72112..b1877cf 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -2998,6 +2998,14 @@ static ExitStatus op_mvn(DisasContext *s, DisasOps *o) return NO_EXIT; } +static ExitStatus op_mvo(DisasContext *s, DisasOps *o) +{ +TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); +gen_helper_mvo(cpu_env, l, o->addr1, o->in2); +tcg_temp_free_i32(l); +return NO_EXIT; +} + static ExitStatus op_mvpg(DisasContext *s, DisasOps *o) { gen_helper_mvpg(cc_op, cpu_env, regs[0], o->in1, o->in2); -- 2.9.4
[Qemu-devel] [PULL 52/69] target/s390x: implement MOVE ZONES
From: Aurelien Jarno Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-14-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 2 ++ target/s390x/mem_helper.c | 13 + target/s390x/translate.c | 8 4 files changed, 24 insertions(+) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index a197b8b..ba21e4d 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -16,6 +16,7 @@ DEF_HELPER_4(clst, i64, env, i64, i64, i64) DEF_HELPER_FLAGS_4(mvn, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(mvo, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(mvpg, TCG_CALL_NO_WG, i32, env, i64, i64, i64) +DEF_HELPER_FLAGS_4(mvz, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_4(mvst, i64, env, i64, i64, i64) DEF_HELPER_4(ex, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(stam, TCG_CALL_NO_WG, void, env, i32, i64, i32) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 47542ee..b40611b 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -588,6 +588,8 @@ /* Really format SS_b, but we pack both lengths into one argument for the helper call, so we might as well leave one 8-bit field. */ C(0xf100, MVO, SS_a, Z, la1, a2, 0, 0, mvo, 0) +/* MOVE ZONES */ +C(0xd300, MVZ, SS_a, Z, la1, a2, 0, 0, mvz, 0) /* MULTIPLY */ C(0x1c00, MR, RR_a, Z, r1p1_32s, r2_32s, new, r1_D32, mul, 0) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 3601bb9..95f701d 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -287,6 +287,19 @@ void HELPER(mvo)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) } } +/* move zones */ +void HELPER(mvz)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) +{ +uintptr_t ra = GETPC(); +int i; + +for (i = 0; i <= l; i++) { +uint8_t b = cpu_ldub_data_ra(env, dest + i, ra) & 0x0f; +b |= cpu_ldub_data_ra(env, src + i, ra) & 0xf0; +cpu_stb_data_ra(env, dest + i, b, ra); +} +} + /* compare unsigned byte arrays */ static uint32_t do_helper_clc(CPUS390XState *env, uint32_t l, uint64_t s1, uint64_t s2, uintptr_t ra) diff --git a/target/s390x/translate.c b/target/s390x/translate.c index b1877cf..95ca53c 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -3021,6 +3021,14 @@ static ExitStatus op_mvst(DisasContext *s, DisasOps *o) return NO_EXIT; } +static ExitStatus op_mvz(DisasContext *s, DisasOps *o) +{ +TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); +gen_helper_mvz(cpu_env, l, o->addr1, o->in2); +tcg_temp_free_i32(l); +return NO_EXIT; +} + static ExitStatus op_mul(DisasContext *s, DisasOps *o) { tcg_gen_mul_i64(o->out, o->in1, o->in2); -- 2.9.4
[Qemu-devel] [PULL 67/69] target/s390x: implement TRANSLATE ONE/TWO TO ONE/TWO
From: Aurelien Jarno Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-29-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 9 + target/s390x/mem_helper.c | 45 + target/s390x/translate.c | 30 ++ 4 files changed, 85 insertions(+) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index c043be6..e139611 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -92,6 +92,7 @@ DEF_HELPER_FLAGS_3(tp, TCG_CALL_NO_WG, i32, env, i64, i32) DEF_HELPER_FLAGS_4(tr, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_4(tre, i64, env, i64, i64, i64) DEF_HELPER_4(trt, i32, env, i32, i64, i64) +DEF_HELPER_5(trXX, i32, env, i32, i32, i32, i32) DEF_HELPER_4(cksm, i64, env, i64, i64, i64) DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_NO_RWG_SE, i32, env, i32, i64, i64, i64) DEF_HELPER_FLAGS_2(sfpc, TCG_CALL_NO_RWG, void, env, i64) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 7f554ab..73dd05d 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -874,6 +874,15 @@ /* TRANSLATE EXTENDED */ C(0xb2a5, TRE, RRE, Z, 0, r2, r1_P, 0, tre, 0) +/* TRANSLATE ONE TO ONE */ +C(0xb993, TROO,RRF_c, E2, 0, 0, 0, 0, trXX, 0) +/* TRANSLATE ONE TO TWO */ +C(0xb992, TROT,RRF_c, E2, 0, 0, 0, 0, trXX, 0) +/* TRANSLATE TWO TO ONE */ +C(0xb991, TRTO,RRF_c, E2, 0, 0, 0, 0, trXX, 0) +/* TRANSLATE TWO TO TWO */ +C(0xb990, TRTT,RRF_c, E2, 0, 0, 0, 0, trXX, 0) + /* UNPACK */ /* Really format SS_b, but we pack both lengths into one argument for the helper call, so we might as well leave one 8-bit field. */ diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index a9297c1..6fb97fa 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -1196,6 +1196,51 @@ uint32_t HELPER(trt)(CPUS390XState *env, uint32_t len, uint64_t array, return do_helper_trt(env, len, array, trans, GETPC()); } +/* Translate one/two to one/two */ +uint32_t HELPER(trXX)(CPUS390XState *env, uint32_t r1, uint32_t r2, + uint32_t tst, uint32_t sizes) +{ +uintptr_t ra = GETPC(); +int dsize = (sizes & 1) ? 1 : 2; +int ssize = (sizes & 2) ? 1 : 2; +uint64_t tbl = get_address(env, 1) & ~7; +uint64_t dst = get_address(env, r1); +uint64_t len = get_length(env, r1 + 1); +uint64_t src = get_address(env, r2); +uint32_t cc = 3; +int i; + +check_alignment(env, len, ssize, ra); + +/* Lest we fail to service interrupts in a timely manner, */ +/* limit the amount of work we're willing to do. */ +for (i = 0; i < 0x2000; i++) { +uint16_t sval = cpu_ldusize_data_ra(env, src, ssize, ra); +uint64_t tble = tbl + (sval * dsize); +uint16_t dval = cpu_ldusize_data_ra(env, tble, dsize, ra); +if (dval == tst) { +cc = 1; +break; +} +cpu_stsize_data_ra(env, dst, dval, dsize, ra); + +len -= ssize; +src += ssize; +dst += dsize; + +if (len == 0) { +cc = 0; +break; +} +} + +set_address(env, r1, dst); +set_length(env, r1 + 1, len); +set_address(env, r2, src); + +return cc; +} + void HELPER(cdsg)(CPUS390XState *env, uint64_t addr, uint32_t r1, uint32_t r3) { diff --git a/target/s390x/translate.c b/target/s390x/translate.c index a7c564f..8702cc8 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -4348,6 +4348,36 @@ static ExitStatus op_trt(DisasContext *s, DisasOps *o) return NO_EXIT; } +static ExitStatus op_trXX(DisasContext *s, DisasOps *o) +{ +TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); +TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2)); +TCGv_i32 sizes = tcg_const_i32(s->insn->opc & 3); +TCGv_i32 tst = tcg_temp_new_i32(); +int m3 = get_field(s->fields, m3); + +/* XXX: the C bit in M3 should be considered as 0 when the + ETF2-enhancement facility is not installed. */ +if (m3 & 1) { +tcg_gen_movi_i32(tst, -1); +} else { +tcg_gen_extrl_i64_i32(tst, regs[0]); +if (s->insn->opc & 3) { +tcg_gen_ext8u_i32(tst, tst); +} else { +tcg_gen_ext16u_i32(tst, tst); +} +} +gen_helper_trXX(cc_op, cpu_env, r1, r2, tst, sizes); + +tcg_temp_free_i32(r1); +tcg_temp_free_i32(r2); +tcg_temp_free_i32(sizes); +tcg_temp_free_i32(tst); +set_cc_static(s); +return NO_EXIT; +} + static ExitStatus op_ts(DisasContext *s, DisasOps *o) { TCGv_i32 t1 = tcg_const_i32(0xff); -- 2.9.4
[Qemu-devel] [PULL 60/69] target/s390x: implement COMPARE LOGICAL LONG UNICODE
From: Aurelien Jarno For that we need to make program_interrupt available to qemu-user. Fortunately there is almost nothing to change as both kvm_enabled and CONFIG_KVM evaluate to false in that case. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-22-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 2 ++ target/s390x/mem_helper.c | 76 ++ target/s390x/misc_helper.c | 4 +-- target/s390x/translate.c | 22 ++ 5 files changed, 90 insertions(+), 15 deletions(-) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index 546beec..509e3f3 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -24,6 +24,7 @@ DEF_HELPER_FLAGS_4(stam, TCG_CALL_NO_WG, void, env, i32, i64, i32) DEF_HELPER_FLAGS_4(lam, TCG_CALL_NO_WG, void, env, i32, i64, i32) DEF_HELPER_4(mvcle, i32, env, i32, i64, i32) DEF_HELPER_4(clcle, i32, env, i32, i64, i32) +DEF_HELPER_4(clclu, i32, env, i32, i64, i32) DEF_HELPER_3(cegb, i64, env, s64, i32) DEF_HELPER_3(cdgb, i64, env, s64, i32) DEF_HELPER_3(cxgb, i64, env, s64, i32) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 1aa2b8b..c781a97 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -220,6 +220,8 @@ C(0x0f00, CLCL,RR_a, Z, 0, 0, 0, 0, clcl, 0) /* COMPARE LOGICAL LONG EXTENDED */ C(0xa900, CLCLE, RS_a, Z, 0, a2, 0, 0, clcle, 0) +/* COMPARE LOGICAL LONG UNICODE */ +C(0xeb8f, CLCLU, RSY_a, E2, 0, a2, 0, 0, clclu, 0) /* COMPARE LOGICAL CHARACTERS UNDER MASK */ C(0xbd00, CLM, RS_b, Z, r1_o, a2, 0, 0, clm, 0) C(0xeb21, CLMY,RSY_b, LD, r1_o, a2, 0, 0, clm, 0) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index cb0ec3e..59992fa 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -67,6 +67,32 @@ static inline uint32_t adj_len_to_page(uint32_t len, uint64_t addr) return len; } +/* Trigger a SPECIFICATION exception if an address or a length is not + naturally aligned. */ +static inline void check_alignment(CPUS390XState *env, uint64_t v, + int wordsize, uintptr_t ra) +{ +if (v % wordsize) { +CPUState *cs = CPU(s390_env_get_cpu(env)); +cpu_restore_state(cs, ra); +program_interrupt(env, PGM_SPECIFICATION, 6); +} +} + +/* Load a value from memory according to its size. */ +static inline uint64_t cpu_ldusize_data_ra(CPUS390XState *env, uint64_t addr, + int wordsize, uintptr_t ra) +{ +switch (wordsize) { +case 1: +return cpu_ldub_data_ra(env, addr, ra); +case 2: +return cpu_lduw_data_ra(env, addr, ra); +default: +abort(); +} +} + static void fast_memset(CPUS390XState *env, uint64_t dest, uint8_t byte, uint32_t l, uintptr_t ra) { @@ -655,12 +681,14 @@ uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, static inline uint32_t do_clcl(CPUS390XState *env, uint64_t *src1, uint64_t *src1len, uint64_t *src3, uint64_t *src3len, - uint8_t pad, uint64_t limit, - uintptr_t ra) + uint16_t pad, uint64_t limit, + int wordsize, uintptr_t ra) { uint64_t len = MAX(*src1len, *src3len); uint32_t cc = 0; +check_alignment(env, *src1len | *src3len, wordsize, ra); + if (!len) { return cc; } @@ -672,15 +700,15 @@ static inline uint32_t do_clcl(CPUS390XState *env, cc = 3; } -for (; len; len--) { -uint8_t v1 = pad; -uint8_t v3 = pad; +for (; len; len -= wordsize) { +uint16_t v1 = pad; +uint16_t v3 = pad; if (*src1len) { -v1 = cpu_ldub_data_ra(env, *src1, ra); +v1 = cpu_ldusize_data_ra(env, *src1, wordsize, ra); } if (*src3len) { -v3 = cpu_ldub_data_ra(env, *src3, ra); +v3 = cpu_ldusize_data_ra(env, *src3, wordsize, ra); } if (v1 != v3) { @@ -689,12 +717,12 @@ static inline uint32_t do_clcl(CPUS390XState *env, } if (*src1len) { -*src1 += 1; -*src1len -= 1; +*src1 += wordsize; +*src1len -= wordsize; } if (*src3len) { -*src3 += 1; -*src3len -= 1; +*src3 += wordsize; +*src3len -= wordsize; } } @@ -713,7 +741,7 @@ uint32_t HELPER(clcl)(CPUS390XState *env, uint32_t r1, uint32_t r2) uint8_t pad = env->regs[r2 + 1] >> 24; uint32_t cc; -cc = do_clcl(env, &src1, &src1len, &src3, &src3len, pad, -1, ra); +cc = do_clcl(env, &src1, &src1len, &src3, &src3l
[Qemu-devel] [PULL 55/69] target/s390x: improve 24-bit and 31-bit lengths read/write
From: Aurelien Jarno Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-17-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 47 +-- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 2113494..98a7aa2 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -407,6 +407,31 @@ static inline void set_address(CPUS390XState *env, int reg, uint64_t address) } } +static inline uint64_t wrap_length(CPUS390XState *env, uint64_t length) +{ +if (!(env->psw.mask & PSW_MASK_64)) { +/* 24-Bit and 31-Bit mode */ +length &= 0x7fff; +} +return length; +} + +static inline uint64_t get_length(CPUS390XState *env, int reg) +{ +return wrap_length(env, env->regs[reg]); +} + +static inline void set_length(CPUS390XState *env, int reg, uint64_t length) +{ +if (env->psw.mask & PSW_MASK_64) { +/* 64-Bit mode */ +env->regs[reg] = length; +} else { +/* 24-Bit and 31-Bit mode */ +env->regs[reg] = deposit64(env->regs[reg], 0, 32, length); +} +} + /* search string (c is byte to search, r2 is string, r1 end of string) */ uint64_t HELPER(srst)(CPUS390XState *env, uint64_t r0, uint64_t end, uint64_t str) @@ -598,19 +623,14 @@ uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { uintptr_t ra = GETPC(); -uint64_t destlen = env->regs[r1 + 1]; +uint64_t destlen = get_length(env, r1 + 1); uint64_t dest = get_address(env, r1); -uint64_t srclen = env->regs[r3 + 1]; +uint64_t srclen = get_length(env, r3 + 1); uint64_t src = get_address(env, r3); uint8_t pad = a2 & 0xff; uint8_t v; uint32_t cc; -if (!(env->psw.mask & PSW_MASK_64)) { -destlen = (uint32_t)destlen; -srclen = (uint32_t)srclen; -} - if (destlen == srclen) { cc = 0; } else if (destlen < srclen) { @@ -632,10 +652,9 @@ uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, cpu_stb_data_ra(env, dest, pad, ra); } -env->regs[r1 + 1] = destlen; +set_length(env, r1 + 1 , destlen); /* can't use srclen here, we trunc'ed it */ -/* FIXME: 31-bit mode! */ -env->regs[r3 + 1] -= src - env->regs[r3]; +set_length(env, r3 + 1, env->regs[r3 + 1] - src - env->regs[r3]); set_address(env, r1, dest); set_address(env, r3, src); @@ -647,9 +666,9 @@ uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { uintptr_t ra = GETPC(); -uint64_t destlen = env->regs[r1 + 1]; +uint64_t destlen = get_length(env, r1 + 1); uint64_t dest = get_address(env, r1); -uint64_t srclen = env->regs[r3 + 1]; +uint64_t srclen = get_length(env, r3 + 1); uint64_t src = get_address(env, r3); uint8_t pad = a2 & 0xff; uint32_t cc = 0; @@ -671,9 +690,9 @@ uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, } } -env->regs[r1 + 1] = destlen; +set_length(env, r1 + 1, destlen); /* can't use srclen here, we trunc'ed it */ -env->regs[r3 + 1] -= src - env->regs[r3]; +set_length(env, r3 + 1, env->regs[r3 + 1] - src - env->regs[r3]); set_address(env, r1, dest); set_address(env, r3, src); -- 2.9.4
[Qemu-devel] [PULL 61/69] target/s390x: implement MOVE LONG UNICODE
From: Aurelien Jarno Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-23-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 2 ++ target/s390x/mem_helper.c | 47 -- target/s390x/translate.c | 21 + 4 files changed, 65 insertions(+), 6 deletions(-) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index 509e3f3..5811911 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -23,6 +23,7 @@ DEF_HELPER_4(ex, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(stam, TCG_CALL_NO_WG, void, env, i32, i64, i32) DEF_HELPER_FLAGS_4(lam, TCG_CALL_NO_WG, void, env, i32, i64, i32) DEF_HELPER_4(mvcle, i32, env, i32, i64, i32) +DEF_HELPER_4(mvclu, i32, env, i32, i64, i32) DEF_HELPER_4(clcle, i32, env, i32, i64, i32) DEF_HELPER_4(clclu, i32, env, i32, i64, i32) DEF_HELPER_3(cegb, i64, env, s64, i32) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index c781a97..e3b7b78 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -582,6 +582,8 @@ C(0x0e00, MVCL,RR_a, Z, 0, 0, 0, 0, mvcl, 0) /* MOVE LONG EXTENDED */ C(0xa800, MVCLE, RS_a, Z, 0, a2, 0, 0, mvcle, 0) +/* MOVE LONG UNICODE */ +C(0xeb8e, MVCLU, RSY_a, E2, 0, a2, 0, 0, mvclu, 0) /* MOVE NUMERICS */ C(0xd100, MVN, SS_a, Z, la1, a2, 0, 0, mvn, 0) /* MOVE PAGE */ diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 59992fa..a2d65cf 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -606,7 +606,7 @@ void HELPER(stam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) static inline uint32_t do_mvcl(CPUS390XState *env, uint64_t *dest, uint64_t *destlen, uint64_t *src, uint64_t *srclen, - uint8_t pad, uintptr_t ra) + uint16_t pad, int wordsize, uintptr_t ra) { uint64_t len = MIN(*srclen, *destlen); uint32_t cc; @@ -627,9 +627,22 @@ static inline uint32_t do_mvcl(CPUS390XState *env, *destlen -= len; /* Pad the remaining area */ -fast_memset(env, *dest, pad, *destlen, ra); -*dest += *destlen; -*destlen = 0; +if (wordsize == 1) { +fast_memset(env, *dest, pad, *destlen, ra); +*dest += *destlen; +*destlen = 0; +} else { +/* If remaining length is odd, pad with odd byte first. */ +if (*destlen & 1) { +cpu_stb_data_ra(env, *dest, pad & 0xff, ra); +*dest += 1; +*destlen -= 1; +} +/* The remaining length is even, pad using words. */ +for (; *destlen; *dest += 2, *destlen -= 2) { +cpu_stw_data_ra(env, *dest, pad, ra); +} +} return cc; } @@ -645,7 +658,7 @@ uint32_t HELPER(mvcl)(CPUS390XState *env, uint32_t r1, uint32_t r2) uint8_t pad = env->regs[r2 + 1] >> 24; uint32_t cc; -cc = do_mvcl(env, &dest, &destlen, &src, &srclen, pad, ra); +cc = do_mvcl(env, &dest, &destlen, &src, &srclen, pad, 1, ra); env->regs[r1 + 1] = deposit64(env->regs[r1 + 1], 0, 24, destlen); env->regs[r2 + 1] = deposit64(env->regs[r2 + 1], 0, 24, srclen); @@ -667,7 +680,29 @@ uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint8_t pad = a2; uint32_t cc; -cc = do_mvcl(env, &dest, &destlen, &src, &srclen, pad, ra); +cc = do_mvcl(env, &dest, &destlen, &src, &srclen, pad, 1, ra); + +set_length(env, r1 + 1, destlen); +set_length(env, r3 + 1, srclen); +set_address(env, r1, dest); +set_address(env, r3, src); + +return cc; +} + +/* move long unicode */ +uint32_t HELPER(mvclu)(CPUS390XState *env, uint32_t r1, uint64_t a2, + uint32_t r3) +{ +uintptr_t ra = GETPC(); +uint64_t destlen = get_length(env, r1 + 1); +uint64_t dest = get_address(env, r1); +uint64_t srclen = get_length(env, r3 + 1); +uint64_t src = get_address(env, r3); +uint16_t pad = a2; +uint32_t cc; + +cc = do_mvcl(env, &dest, &destlen, &src, &srclen, pad, 2, ra); set_length(env, r1 + 1, destlen); set_length(env, r3 + 1, srclen); diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 892949a..b160a0c 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -3043,6 +3043,27 @@ static ExitStatus op_mvcle(DisasContext *s, DisasOps *o) return NO_EXIT; } +static ExitStatus op_mvclu(DisasContext *s, DisasOps *o) +{ +int r1 = get_field(s->fields, r1); +int r3 = get_field(s->fields, r3); +TCGv_i32 t1, t3; + +/* r1 and r3 must be even. */ +if (r1 & 1 || r3 & 1) { +gen_program_exception(s, PGM_SPECIFICATION); +return EXIT_NORETURN; +} + +t1 = tcg_const_i32(r1); +t3 = tcg_const_i32(r3); +
[Qemu-devel] [PULL 69/69] target/s390x: addressing exceptions are suppressing
From: David Hildenbrand We have to make the address in the old PSW point at the next instruction, as addressing exceptions are suppressing and not nullifying. I assume that there are a lot of other broken cases (as most instructions we care about are suppressing) - all trigger_pgm_exception() specifying and explicit number or ILEN_LATER look suspicious, however this is another story that might require bigger changes (and I have to understand when the address might already have been incremented first). This is needed to make an upcoming kvm-unit-test work. Reviewed-by: Thomas Huth Signed-off-by: David Hildenbrand Message-Id: <20170529121228.2789-1-da...@redhat.com> Signed-off-by: Richard Henderson --- target/s390x/helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/s390x/helper.c b/target/s390x/helper.c index 291db72..a8d20c5 100644 --- a/target/s390x/helper.c +++ b/target/s390x/helper.c @@ -204,7 +204,7 @@ int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr orig_vaddr, if (raddr > ram_size) { DPRINTF("%s: raddr %" PRIx64 " > ram_size %" PRIx64 "\n", __func__, (uint64_t)raddr, (uint64_t)ram_size); -trigger_pgm_exception(env, PGM_ADDRESSING, ILEN_LATER); +trigger_pgm_exception(env, PGM_ADDRESSING, ILEN_LATER_INC); return 1; } -- 2.9.4
[Qemu-devel] [PULL 56/69] target/s390x: fix COMPARE LOGICAL LONG EXTENDED
From: Aurelien Jarno There are multiple issues with the COMPARE LOGICAL LONG EXTENDED instruction: - The test between the two operands is inverted, leading to an inversion of the cc values 1 and 2. - The address and length of an operand continue to be decreased after reaching the end of this operand. These values are then wrong write back to the registers. - We should limit the amount of bytes to process, so that interrupts can be served correctly. At the same time rename dest into src1 and src into src3 to match the operand names and make the code less confusing. Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-18-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/mem_helper.c | 54 --- target/s390x/translate.c | 20 +- 2 files changed, 52 insertions(+), 22 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 98a7aa2..e992fd9 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -666,35 +666,55 @@ uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { uintptr_t ra = GETPC(); -uint64_t destlen = get_length(env, r1 + 1); -uint64_t dest = get_address(env, r1); -uint64_t srclen = get_length(env, r3 + 1); -uint64_t src = get_address(env, r3); +uint64_t src1len = get_length(env, r1 + 1); +uint64_t src1 = get_address(env, r1); +uint64_t src3len = get_length(env, r3 + 1); +uint64_t src3 = get_address(env, r3); uint8_t pad = a2 & 0xff; +uint64_t len = MAX(src1len, src3len); uint32_t cc = 0; -if (!(destlen || srclen)) { +if (!len) { return cc; } -if (srclen > destlen) { -srclen = destlen; +/* Lest we fail to service interrupts in a timely manner, limit the + amount of work we're willing to do. For now, let's cap at 8k. */ +if (len > 0x2000) { +len = 0x2000; +cc = 3; } -for (; destlen || srclen; src++, dest++, destlen--, srclen--) { -uint8_t v1 = srclen ? cpu_ldub_data_ra(env, src, ra) : pad; -uint8_t v2 = destlen ? cpu_ldub_data_ra(env, dest, ra) : pad; -if (v1 != v2) { -cc = (v1 < v2) ? 1 : 2; +for (; len; len--) { +uint8_t v1 = pad; +uint8_t v3 = pad; + +if (src1len) { +v1 = cpu_ldub_data_ra(env, src1, ra); +} +if (src3len) { +v3 = cpu_ldub_data_ra(env, src3, ra); +} + +if (v1 != v3) { +cc = (v1 < v3) ? 1 : 2; break; } + +if (src1len) { +src1++; +src1len--; +} +if (src3len) { +src3++; +src3len--; +} } -set_length(env, r1 + 1, destlen); -/* can't use srclen here, we trunc'ed it */ -set_length(env, r3 + 1, env->regs[r3 + 1] - src - env->regs[r3]); -set_address(env, r1, dest); -set_address(env, r3, src); +set_length(env, r1 + 1, src1len); +set_length(env, r3 + 1, src3len); +set_address(env, r1, src1); +set_address(env, r3, src3); return cc; } diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 95ca53c..9309e58 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -1917,11 +1917,21 @@ static ExitStatus op_clc(DisasContext *s, DisasOps *o) static ExitStatus op_clcle(DisasContext *s, DisasOps *o) { -TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); -TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); -gen_helper_clcle(cc_op, cpu_env, r1, o->in2, r3); -tcg_temp_free_i32(r1); -tcg_temp_free_i32(r3); +int r1 = get_field(s->fields, r1); +int r3 = get_field(s->fields, r3); +TCGv_i32 t1, t3; + +/* r1 and r3 must be even. */ +if (r1 & 1 || r3 & 1) { +gen_program_exception(s, PGM_SPECIFICATION); +return EXIT_NORETURN; +} + +t1 = tcg_const_i32(r1); +t3 = tcg_const_i32(r3); +gen_helper_clcle(cc_op, cpu_env, t1, o->in2, t3); +tcg_temp_free_i32(t1); +tcg_temp_free_i32(t3); set_cc_static(s); return NO_EXIT; } -- 2.9.4
[Qemu-devel] [PULL 64/69] target/s390x: implement UNPACK ASCII
From: Aurelien Jarno Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-26-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 2 ++ target/s390x/mem_helper.c | 51 ++ target/s390x/translate.c | 17 4 files changed, 71 insertions(+) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index 5b61a0d..42c3de6 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -86,6 +86,7 @@ DEF_HELPER_FLAGS_4(pack, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(pka, TCG_CALL_NO_WG, void, env, i64, i64, i32) DEF_HELPER_FLAGS_4(pku, TCG_CALL_NO_WG, void, env, i64, i64, i32) DEF_HELPER_FLAGS_4(unpk, TCG_CALL_NO_WG, void, env, i32, i64, i64) +DEF_HELPER_FLAGS_4(unpka, TCG_CALL_NO_WG, i32, env, i64, i32, i64) DEF_HELPER_FLAGS_4(tr, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_4(tre, i64, env, i64, i64, i64) DEF_HELPER_4(trt, i32, env, i32, i64, i64) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 16f788c..33434a3 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -875,6 +875,8 @@ /* Really format SS_b, but we pack both lengths into one argument for the helper call, so we might as well leave one 8-bit field. */ C(0xf300, UNPK,SS_a, Z, la1, a2, 0, 0, unpk, 0) +/* UNPACK ASCII */ +C(0xea00, UNPKA, SS_a, E2, la1, a2, 0, 0, unpka, 0) #ifndef CONFIG_USER_ONLY /* COMPARE AND SWAP AND PURGE */ diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index d827a12..1c5f29c 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -1008,6 +1008,57 @@ void HELPER(unpk)(CPUS390XState *env, uint32_t len, uint64_t dest, } } +uint32_t HELPER(unpka)(CPUS390XState *env, uint64_t dest, uint32_t destlen, + uint64_t src) +{ +uintptr_t ra = GETPC(); +int i; +uint32_t cc; +uint8_t b; +/* The source operand is always 16 bytes long. */ +const int srclen = 16; + +/* The operands are processed from right to left. */ +src += srclen - 1; +dest += destlen - 1; + +/* Check for the sign. */ +b = cpu_ldub_data_ra(env, src, ra); +src--; +switch (b & 0xf) { +case 0xa: +case 0xc: +case 0xe ... 0xf: +cc = 0; /* plus */ +break; +case 0xb: +case 0xd: +cc = 1; /* minus */ +break; +default: +case 0x0 ... 0x9: +cc = 3; /* invalid */ +break; +} + +/* Now pad every nibble with 0x30, advancing one nibble at a time. */ +for (i = 0; i < destlen; i++) { +if (i == 31) { +/* If length is 32 bytes, the leftmost byte is 0. */ +b = 0; +} else if (i % 2) { +b = cpu_ldub_data_ra(env, src, ra); +src--; +} else { +b >>= 4; +} +cpu_stb_data_ra(env, dest, 0x30 + (b & 0xf), ra); +dest--; +} + +return cc; +} + static uint32_t do_helper_tr(CPUS390XState *env, uint32_t len, uint64_t array, uint64_t trans, uintptr_t ra) { diff --git a/target/s390x/translate.c b/target/s390x/translate.c index d8b0515..2ff6665 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -4357,6 +4357,23 @@ static ExitStatus op_unpk(DisasContext *s, DisasOps *o) return NO_EXIT; } +static ExitStatus op_unpka(DisasContext *s, DisasOps *o) +{ +int l1 = get_field(s->fields, l1) + 1; +TCGv_i32 l; + +/* The length must not exceed 32 bytes. */ +if (l1 > 32) { +gen_program_exception(s, PGM_SPECIFICATION); +return EXIT_NORETURN; +} +l = tcg_const_i32(l1); +gen_helper_unpka(cc_op, cpu_env, o->addr1, l, o->in2); +tcg_temp_free_i32(l); +set_cc_static(s); +return NO_EXIT; +} + static ExitStatus op_xc(DisasContext *s, DisasOps *o) { int d1 = get_field(s->fields, d1); -- 2.9.4
[Qemu-devel] [PULL 62/69] target/s390x: implement PACK ASCII
From: Aurelien Jarno Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-24-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 2 ++ target/s390x/mem_helper.c | 35 +++ target/s390x/translate.c | 16 4 files changed, 54 insertions(+) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index 5811911..7898064 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -83,6 +83,7 @@ DEF_HELPER_FLAGS_2(sqdb, TCG_CALL_NO_WG, i64, env, i64) DEF_HELPER_FLAGS_3(sqxb, TCG_CALL_NO_WG, i64, env, i64, i64) DEF_HELPER_FLAGS_1(cvd, TCG_CALL_NO_RWG_SE, i64, s32) DEF_HELPER_FLAGS_4(pack, TCG_CALL_NO_WG, void, env, i32, i64, i64) +DEF_HELPER_FLAGS_4(pka, TCG_CALL_NO_WG, void, env, i64, i64, i32) DEF_HELPER_FLAGS_4(unpk, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(tr, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_4(tre, i64, env, i64, i64, i64) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index e3b7b78..41431af 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -667,6 +667,8 @@ /* Really format SS_b, but we pack both lengths into one argument for the helper call, so we might as well leave one 8-bit field. */ C(0xf200, PACK,SS_a, Z, la1, a2, 0, 0, pack, 0) +/* PACK ASCII */ +C(0xe900, PKA, SS_f, E2, la1, a2, 0, 0, pka, 0) /* PREFETCH */ /* Implemented as nops of course. */ diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index a2d65cf..425d4b6 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -914,6 +914,41 @@ void HELPER(pack)(CPUS390XState *env, uint32_t len, uint64_t dest, uint64_t src) } } +void HELPER(pka)(CPUS390XState *env, uint64_t dest, uint64_t src, + uint32_t srclen) +{ +uintptr_t ra = GETPC(); +int i; +/* The destination operand is always 16 bytes long. */ +const int destlen = 16; + +/* The operands are processed from right to left. */ +src += srclen - 1; +dest += destlen - 1; + +for (i = 0; i < destlen; i++) { +uint8_t b = 0; + +/* Start with a positive sign */ +if (i == 0) { +b = 0xc; +} else if (srclen > 1) { +b = cpu_ldub_data_ra(env, src, ra) & 0x0f; +src--; +srclen--; +} + +if (srclen > 1) { +b |= cpu_ldub_data_ra(env, src, ra) << 4; +src--; +srclen--; +} + +cpu_stb_data_ra(env, dest, b, ra); +dest--; +} +} + void HELPER(unpk)(CPUS390XState *env, uint32_t len, uint64_t dest, uint64_t src) { diff --git a/target/s390x/translate.c b/target/s390x/translate.c index b160a0c..5093995 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -3301,6 +3301,22 @@ static ExitStatus op_pack(DisasContext *s, DisasOps *o) return NO_EXIT; } +static ExitStatus op_pka(DisasContext *s, DisasOps *o) +{ +int l2 = get_field(s->fields, l2) + 1; +TCGv_i32 l; + +/* The length must not exceed 32 bytes. */ +if (l2 > 32) { +gen_program_exception(s, PGM_SPECIFICATION); +return EXIT_NORETURN; +} +l = tcg_const_i32(l2); +gen_helper_pka(cpu_env, o->addr1, o->in2, l); +tcg_temp_free_i32(l); +return NO_EXIT; +} + static ExitStatus op_popcnt(DisasContext *s, DisasOps *o) { gen_helper_popcnt(o->out, o->in2); -- 2.9.4
[Qemu-devel] [PULL 65/69] target/s390x: implement UNPACK UNICODE
From: Aurelien Jarno Reviewed-by: Richard Henderson Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-27-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/helper.h | 1 + target/s390x/insn-data.def | 2 ++ target/s390x/mem_helper.c | 49 -- target/s390x/translate.c | 18 + 4 files changed, 60 insertions(+), 10 deletions(-) diff --git a/target/s390x/helper.h b/target/s390x/helper.h index 42c3de6..dc85a14 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -87,6 +87,7 @@ DEF_HELPER_FLAGS_4(pka, TCG_CALL_NO_WG, void, env, i64, i64, i32) DEF_HELPER_FLAGS_4(pku, TCG_CALL_NO_WG, void, env, i64, i64, i32) DEF_HELPER_FLAGS_4(unpk, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(unpka, TCG_CALL_NO_WG, i32, env, i64, i32, i64) +DEF_HELPER_FLAGS_4(unpku, TCG_CALL_NO_WG, i32, env, i64, i32, i64) DEF_HELPER_FLAGS_4(tr, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_4(tre, i64, env, i64, i64, i64) DEF_HELPER_4(trt, i32, env, i32, i64, i64) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 33434a3..683f91b 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -877,6 +877,8 @@ C(0xf300, UNPK,SS_a, Z, la1, a2, 0, 0, unpk, 0) /* UNPACK ASCII */ C(0xea00, UNPKA, SS_a, E2, la1, a2, 0, 0, unpka, 0) +/* UNPACK UNICODE */ +C(0xe200, UNPKU, SS_a, E2, la1, a2, 0, 0, unpku, 0) #ifndef CONFIG_USER_ONLY /* COMPARE AND SWAP AND PURGE */ diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 1c5f29c..5cb1a8a 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -93,6 +93,23 @@ static inline uint64_t cpu_ldusize_data_ra(CPUS390XState *env, uint64_t addr, } } +/* Store a to memory according to its size. */ +static inline void cpu_stsize_data_ra(CPUS390XState *env, uint64_t addr, + uint64_t value, int wordsize, + uintptr_t ra) +{ +switch (wordsize) { +case 1: +cpu_stb_data_ra(env, addr, value, ra); +break; +case 2: +cpu_stw_data_ra(env, addr, value, ra); +break; +default: +abort(); +} +} + static void fast_memset(CPUS390XState *env, uint64_t dest, uint8_t byte, uint32_t l, uintptr_t ra) { @@ -1008,10 +1025,10 @@ void HELPER(unpk)(CPUS390XState *env, uint32_t len, uint64_t dest, } } -uint32_t HELPER(unpka)(CPUS390XState *env, uint64_t dest, uint32_t destlen, - uint64_t src) +static inline uint32_t do_unpkau(CPUS390XState *env, uint64_t dest, + uint32_t destlen, int dsize, uint64_t src, + uintptr_t ra) { -uintptr_t ra = GETPC(); int i; uint32_t cc; uint8_t b; @@ -1020,7 +1037,7 @@ uint32_t HELPER(unpka)(CPUS390XState *env, uint64_t dest, uint32_t destlen, /* The operands are processed from right to left. */ src += srclen - 1; -dest += destlen - 1; +dest += destlen - dsize; /* Check for the sign. */ b = cpu_ldub_data_ra(env, src, ra); @@ -1042,23 +1059,35 @@ uint32_t HELPER(unpka)(CPUS390XState *env, uint64_t dest, uint32_t destlen, } /* Now pad every nibble with 0x30, advancing one nibble at a time. */ -for (i = 0; i < destlen; i++) { -if (i == 31) { -/* If length is 32 bytes, the leftmost byte is 0. */ +for (i = 0; i < destlen; i += dsize) { +if (i == (31 * dsize)) { +/* If length is 32/64 bytes, the leftmost byte is 0. */ b = 0; -} else if (i % 2) { +} else if (i % (2 * dsize)) { b = cpu_ldub_data_ra(env, src, ra); src--; } else { b >>= 4; } -cpu_stb_data_ra(env, dest, 0x30 + (b & 0xf), ra); -dest--; +cpu_stsize_data_ra(env, dest, 0x30 + (b & 0xf), dsize, ra); +dest -= dsize; } return cc; } +uint32_t HELPER(unpka)(CPUS390XState *env, uint64_t dest, uint32_t destlen, + uint64_t src) +{ +return do_unpkau(env, dest, destlen, 1, src, GETPC()); +} + +uint32_t HELPER(unpku)(CPUS390XState *env, uint64_t dest, uint32_t destlen, + uint64_t src) +{ +return do_unpkau(env, dest, destlen, 2, src, GETPC()); +} + static uint32_t do_helper_tr(CPUS390XState *env, uint32_t len, uint64_t array, uint64_t trans, uintptr_t ra) { diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 2ff6665..747d4eb 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -4374,6 +4374,24 @@ static ExitStatus op_unpka(DisasContext *s, DisasOps *o) return NO_EXIT; } +static ExitStatus op_unpku(DisasContext *s, DisasOps *o) +{ +int l1 = get_field(s->fields, l1) + 1; +TCGv_i32 l;
[Qemu-devel] [PULL 68/69] target/s390x: mark ETF2 and ETF2-ENH facilities as available
From: Aurelien Jarno Signed-off-by: Aurelien Jarno Message-Id: <20170531220129.27724-30-aurel...@aurel32.net> Signed-off-by: Richard Henderson --- target/s390x/cpu_models.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c index e5e005a..fc3cb25 100644 --- a/target/s390x/cpu_models.c +++ b/target/s390x/cpu_models.c @@ -668,8 +668,10 @@ static void add_qemu_cpu_model_features(S390FeatBitmap fbm) static const int feats[] = { S390_FEAT_STFLE, S390_FEAT_EXTENDED_IMMEDIATE, +S390_FEAT_EXTENDED_TRANSLATION_2, S390_FEAT_LONG_DISPLACEMENT, S390_FEAT_LONG_DISPLACEMENT_FAST, +S390_FEAT_ETF2_ENH, S390_FEAT_STORE_CLOCK_FAST, S390_FEAT_GENERAL_INSTRUCTIONS_EXT, S390_FEAT_EXECUTE_EXT, -- 2.9.4
Re: [Qemu-devel] [PATCH] tcg: allocate TB structs before the corresponding translated code
On 06/02/2017 04:39 PM, Emilio G. Cota wrote: +aligned = (void *)ROUND_UP((uintptr_t)s->code_gen_ptr, 64); I would prefer that this and +} QEMU_ALIGNED(64); this both use a define. We may well have to adjust this for different hosts. In particular I'm thinking of PPC64 which would prefer 128. +if (unlikely(!tcg_ctx.tb_ctx.tbs_size)) { +tcg_ctx.tb_ctx.tbs_size = 1024; +} And I know that you resize this on demand, but surely we can avoid some startup slowdown by picking a more reasonable initial estimate here. Like 32k or 64k. Otherwise this looks good. I'll have to have a more detailed look at the differences in the generated code later. r~