diff options
264 files changed, 13997 insertions, 7832 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 8206fc51db..2cce50287a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -383,6 +383,8 @@ F: target/s390x/kvm-stub.c F: target/s390x/ioinst.[ch] F: target/s390x/machine.c F: target/s390x/sigp.c +F: target/s390x/cpu_features*.[ch] +F: target/s390x/cpu_models.[ch] F: hw/intc/s390_flic.c F: hw/intc/s390_flic_kvm.c F: include/hw/s390x/s390_flic.h @@ -728,6 +730,14 @@ F: include/hw/arm/fsl-imx6.h F: include/hw/misc/imx6_*.h F: include/hw/ssi/imx_spi.h +SBSA-REF +M: Radoslaw Biernacki <radoslaw.biernacki@linaro.org> +M: Peter Maydell <peter.maydell@linaro.org> +R: Leif Lindholm <leif.lindholm@linaro.org> +L: qemu-arm@nongnu.org +S: Maintained +F: hw/arm/sbsa-ref.c + Sharp SL-5500 (Collie) PDA M: Peter Maydell <peter.maydell@linaro.org> L: qemu-arm@nongnu.org @@ -1264,11 +1274,18 @@ Machine core M: Eduardo Habkost <ehabkost@redhat.com> M: Marcel Apfelbaum <marcel.apfelbaum@gmail.com> S: Supported +F: hw/core/machine-qmp-cmds.c F: hw/core/machine.c F: hw/core/null-machine.c +F: hw/core/numa.c F: hw/cpu/cluster.c +F: qapi/machine.json +F: qapi/machine-target.json +F: qom/cpu.c F: include/hw/boards.h F: include/hw/cpu/cluster.h +F: include/qom/cpu.h +F: include/sysemu/numa.h T: git https://github.com/ehabkost/qemu.git machine-next Xtensa Machines @@ -1833,11 +1850,6 @@ M: Markus Armbruster <armbru@redhat.com> S: Supported F: scripts/coverity-model.c -CPU -S: Supported -F: qom/cpu.c -F: include/qom/cpu.h - Device Tree M: Alistair Francis <alistair.francis@wdc.com> R: David Gibson <david@gibson.dropbear.id.au> @@ -1848,11 +1860,13 @@ F: include/sysemu/device_tree.h Dump S: Supported M: Marc-André Lureau <marcandre.lureau@redhat.com> -F: dump.c +F: dump/ F: hw/misc/vmcoreinfo.c F: include/hw/misc/vmcoreinfo.h +F: include/qemu/win_dump_defs F: include/sysemu/dump-arch.h F: include/sysemu/dump.h +F: qapi/dump.json F: scripts/dump-guest-memory.py F: stubs/dump.c @@ -1934,6 +1948,7 @@ M: Jason Wang <jasowang@redhat.com> S: Maintained F: net/ F: include/net/ +F: qemu-bridge-helper.c T: git https://github.com/jasowang/qemu.git net F: qapi/net.json @@ -1945,13 +1960,6 @@ W: http://info.iet.unipi.it/~luigi/netmap/ S: Maintained F: net/netmap.c -NUMA -M: Eduardo Habkost <ehabkost@redhat.com> -S: Maintained -F: numa.c -F: include/sysemu/numa.h -T: git https://github.com/ehabkost/qemu.git machine-next - Host Memory Backends M: Eduardo Habkost <ehabkost@redhat.com> M: Igor Mammedov <imammedo@redhat.com> @@ -2029,15 +2037,24 @@ F: docs/interop/qemu-ga-ref.texi T: git https://github.com/mdroth/qemu.git qga QOM -M: Andreas Färber <afaerber@suse.de> +M: Paolo Bonzini <pbonzini@redhat.com> +R: Daniel P. Berrange <berrange@redhat.com> +R: Eduardo Habkost <ehabkost@redhat.com> S: Supported -T: git https://github.com/afaerber/qemu-cpu.git qom-next +F: docs/qdev-device-use.txt +F: hw/core/qdev* +F: include/hw/qdev* +F: include/monitor/qdev.h F: include/qom/ X: include/qom/cpu.h +F: qapi/qom.json +F: qapi/qdev.json +F: qdev-monitor.c F: qom/ X: qom/cpu.c F: tests/check-qom-interface.c F: tests/check-qom-proplist.c +F: tests/test-qdev-global-props.c QMP M: Markus Armbruster <armbru@redhat.com> @@ -753,7 +753,7 @@ bepo cz ifdef INSTALL_BLOBS BLOBS=bios.bin bios-256k.bin sgabios.bin vgabios.bin vgabios-cirrus.bin \ vgabios-stdvga.bin vgabios-vmware.bin vgabios-qxl.bin vgabios-virtio.bin \ -vgabios-ramfb.bin vgabios-bochs-display.bin \ +vgabios-ramfb.bin vgabios-bochs-display.bin vgabios-ati.bin \ ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc QEMU,tcx.bin QEMU,cgthree.bin \ pxe-e1000.rom pxe-eepro100.rom pxe-ne2k_pci.rom \ pxe-pcnet.rom pxe-rtl8139.rom pxe-virtio.rom \ diff --git a/Makefile.objs b/Makefile.objs index 3b83621f32..6a143dcd57 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -45,6 +45,7 @@ io-obj-y = io/ ifeq ($(CONFIG_SOFTMMU),y) common-obj-y = blockdev.o blockdev-nbd.o block/ common-obj-y += bootdevice.o iothread.o +common-obj-y += dump/ common-obj-y += job-qmp.o common-obj-y += monitor/ common-obj-y += net/ @@ -85,7 +86,6 @@ common-obj-$(CONFIG_FDT) += device_tree.o # qapi common-obj-y += qapi/ -common-obj-y += monitor/ endif ####################################################################### diff --git a/Makefile.target b/Makefile.target index 72c267f7dc..a6919e0caf 100644 --- a/Makefile.target +++ b/Makefile.target @@ -148,15 +148,14 @@ endif #CONFIG_BSD_USER ######################################################### # System emulator target ifdef CONFIG_SOFTMMU -obj-y += arch_init.o cpus.o gdbstub.o balloon.o ioport.o numa.o +obj-y += arch_init.o cpus.o gdbstub.o balloon.o ioport.o obj-y += qtest.o +obj-y += dump/ obj-y += hw/ obj-y += monitor/ obj-y += qapi/ obj-y += memory.o obj-y += memory_mapping.o -obj-y += dump.o -obj-$(TARGET_X86_64) += win_dump.o obj-y += migration/ram.o LIBS := $(libs_softmmu) $(LIBS) diff --git a/audio/paaudio.c b/audio/paaudio.c index fa9dd9efd4..5fc886bb33 100644 --- a/audio/paaudio.c +++ b/audio/paaudio.c @@ -618,7 +618,7 @@ static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) ss.rate = as->freq; ba.fragsize = pa_usec_to_bytes(ppdo->latency, &ss); - ba.maxlength = -1; + ba.maxlength = pa_usec_to_bytes(ppdo->latency * 2, &ss); ba.minreq = -1; ba.prebuf = -1; diff --git a/block/commit.c b/block/commit.c index 212c6f639e..ca7e408b26 100644 --- a/block/commit.c +++ b/block/commit.c @@ -174,7 +174,7 @@ static int coroutine_fn commit_run(Job *job, Error **errp) break; } /* Copy if allocated above the base */ - ret = bdrv_is_allocated_above(blk_bs(s->top), blk_bs(s->base), + ret = bdrv_is_allocated_above(blk_bs(s->top), blk_bs(s->base), false, offset, COMMIT_BUFFER_SIZE, &n); copy = (ret == 1); trace_commit_one_iteration(s, offset, n, ret); diff --git a/block/io.c b/block/io.c index 9ba1bada36..24a18759fd 100644 --- a/block/io.c +++ b/block/io.c @@ -2295,10 +2295,11 @@ int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t offset, /* * Given an image chain: ... -> [BASE] -> [INTER1] -> [INTER2] -> [TOP] * - * Return true if (a prefix of) the given range is allocated in any image - * between BASE and TOP (inclusive). BASE can be NULL to check if the given - * offset is allocated in any image of the chain. Return false otherwise, - * or negative errno on failure. + * Return 1 if (a prefix of) the given range is allocated in any image + * between BASE and TOP (BASE is only included if include_base is set). + * BASE can be NULL to check if the given offset is allocated in any + * image of the chain. Return 0 otherwise, or negative errno on + * failure. * * 'pnum' is set to the number of bytes (including and immediately * following the specified offset) that are known to be in the same @@ -2310,17 +2311,21 @@ int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t offset, */ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base, - int64_t offset, int64_t bytes, int64_t *pnum) + bool include_base, int64_t offset, + int64_t bytes, int64_t *pnum) { BlockDriverState *intermediate; int ret; int64_t n = bytes; + assert(base || !include_base); + intermediate = top; - while (intermediate && intermediate != base) { + while (include_base || intermediate != base) { int64_t pnum_inter; int64_t size_inter; + assert(intermediate); ret = bdrv_is_allocated(intermediate, offset, bytes, &pnum_inter); if (ret < 0) { return ret; @@ -2339,6 +2344,10 @@ int bdrv_is_allocated_above(BlockDriverState *top, n = pnum_inter; } + if (intermediate == base) { + break; + } + intermediate = backing_bs(intermediate); } diff --git a/block/mirror.c b/block/mirror.c index d17be4cdbc..2fcec70e35 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -808,7 +808,7 @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s) return 0; } - ret = bdrv_is_allocated_above(bs, base, offset, bytes, &count); + ret = bdrv_is_allocated_above(bs, base, false, offset, bytes, &count); if (ret < 0) { return ret; } diff --git a/block/qcow2.c b/block/qcow2.c index 9396d490d5..2a59eb27fe 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -2148,7 +2148,8 @@ static bool is_unallocated(BlockDriverState *bs, int64_t offset, int64_t bytes) { int64_t nr; return !bytes || - (!bdrv_is_allocated_above(bs, NULL, offset, bytes, &nr) && nr == bytes); + (!bdrv_is_allocated_above(bs, NULL, false, offset, bytes, &nr) && + nr == bytes); } static bool is_zero_cow(BlockDriverState *bs, QCowL2Meta *m) diff --git a/block/rbd.c b/block/rbd.c index f2ac2c06f4..59757b3120 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -103,6 +103,7 @@ typedef struct BDRVRBDState { rbd_image_t image; char *image_name; char *snap; + uint64_t image_size; } BDRVRBDState; static int qemu_rbd_connect(rados_t *cluster, rados_ioctx_t *io_ctx, @@ -778,6 +779,14 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags, goto failed_open; } + r = rbd_get_size(s->image, &s->image_size); + if (r < 0) { + error_setg_errno(errp, -r, "error getting image size from %s", + s->image_name); + rbd_close(s->image); + goto failed_open; + } + /* If we are using an rbd snapshot, we must be r/o, otherwise * leave as-is */ if (s->snap != NULL) { @@ -834,6 +843,22 @@ static void qemu_rbd_close(BlockDriverState *bs) rados_shutdown(s->cluster); } +/* Resize the RBD image and update the 'image_size' with the current size */ +static int qemu_rbd_resize(BlockDriverState *bs, uint64_t size) +{ + BDRVRBDState *s = bs->opaque; + int r; + + r = rbd_resize(s->image, size); + if (r < 0) { + return r; + } + + s->image_size = size; + + return 0; +} + static const AIOCBInfo rbd_aiocb_info = { .aiocb_size = sizeof(RBDAIOCB), }; @@ -935,13 +960,25 @@ static BlockAIOCB *rbd_start_aio(BlockDriverState *bs, } switch (cmd) { - case RBD_AIO_WRITE: + case RBD_AIO_WRITE: { + /* + * RBD APIs don't allow us to write more than actual size, so in order + * to support growing images, we resize the image before write + * operations that exceed the current size. + */ + if (off + size > s->image_size) { + r = qemu_rbd_resize(bs, off + size); + if (r < 0) { + goto failed_completion; + } + } #ifdef LIBRBD_SUPPORTS_IOVEC r = rbd_aio_writev(s->image, qiov->iov, qiov->niov, off, c); #else r = rbd_aio_write(s->image, off, size, rcb->buf, c); #endif break; + } case RBD_AIO_READ: #ifdef LIBRBD_SUPPORTS_IOVEC r = rbd_aio_readv(s->image, qiov->iov, qiov->niov, off, c); @@ -1052,7 +1089,6 @@ static int coroutine_fn qemu_rbd_co_truncate(BlockDriverState *bs, PreallocMode prealloc, Error **errp) { - BDRVRBDState *s = bs->opaque; int r; if (prealloc != PREALLOC_MODE_OFF) { @@ -1061,7 +1097,7 @@ static int coroutine_fn qemu_rbd_co_truncate(BlockDriverState *bs, return -ENOTSUP; } - r = rbd_resize(s->image, offset); + r = qemu_rbd_resize(bs, offset); if (r < 0) { error_setg_errno(errp, -r, "Failed to resize file"); return r; diff --git a/block/replication.c b/block/replication.c index b41bc507c0..23b2993d74 100644 --- a/block/replication.c +++ b/block/replication.c @@ -275,7 +275,7 @@ static coroutine_fn int replication_co_writev(BlockDriverState *bs, while (remaining_sectors > 0) { int64_t count; - ret = bdrv_is_allocated_above(top->bs, base->bs, + ret = bdrv_is_allocated_above(top->bs, base->bs, false, sector_num * BDRV_SECTOR_SIZE, remaining_sectors * BDRV_SECTOR_SIZE, &count); diff --git a/block/stream.c b/block/stream.c index 1a906fd860..cd5e2ba9b0 100644 --- a/block/stream.c +++ b/block/stream.c @@ -31,7 +31,7 @@ enum { typedef struct StreamBlockJob { BlockJob common; - BlockDriverState *base; + BlockDriverState *bottom; BlockdevOnError on_error; char *backing_file_str; bool bs_read_only; @@ -54,7 +54,7 @@ static void stream_abort(Job *job) if (s->chain_frozen) { BlockJob *bjob = &s->common; - bdrv_unfreeze_backing_chain(blk_bs(bjob->blk), s->base); + bdrv_unfreeze_backing_chain(blk_bs(bjob->blk), s->bottom); } } @@ -63,11 +63,11 @@ static int stream_prepare(Job *job) StreamBlockJob *s = container_of(job, StreamBlockJob, common.job); BlockJob *bjob = &s->common; BlockDriverState *bs = blk_bs(bjob->blk); - BlockDriverState *base = s->base; + BlockDriverState *base = backing_bs(s->bottom); Error *local_err = NULL; int ret = 0; - bdrv_unfreeze_backing_chain(bs, base); + bdrv_unfreeze_backing_chain(bs, s->bottom); s->chain_frozen = false; if (bs->backing) { @@ -110,7 +110,7 @@ static int coroutine_fn stream_run(Job *job, Error **errp) StreamBlockJob *s = container_of(job, StreamBlockJob, common.job); BlockBackend *blk = s->common.blk; BlockDriverState *bs = blk_bs(blk); - BlockDriverState *base = s->base; + bool enable_cor = !backing_bs(s->bottom); int64_t len; int64_t offset = 0; uint64_t delay_ns = 0; @@ -119,14 +119,14 @@ static int coroutine_fn stream_run(Job *job, Error **errp) int64_t n = 0; /* bytes */ void *buf; - if (!bs->backing) { - goto out; + if (bs == s->bottom) { + /* Nothing to stream */ + return 0; } len = bdrv_getlength(bs); if (len < 0) { - ret = len; - goto out; + return len; } job_progress_set_remaining(&s->common.job, len); @@ -137,7 +137,7 @@ static int coroutine_fn stream_run(Job *job, Error **errp) * backing chain since the copy-on-read operation does not take base into * account. */ - if (!base) { + if (enable_cor) { bdrv_enable_copy_on_read(bs); } @@ -160,9 +160,8 @@ static int coroutine_fn stream_run(Job *job, Error **errp) } else if (ret >= 0) { /* Copy if allocated in the intermediate images. Limit to the * known-unallocated area [offset, offset+n*BDRV_SECTOR_SIZE). */ - ret = bdrv_is_allocated_above(backing_bs(bs), base, + ret = bdrv_is_allocated_above(backing_bs(bs), s->bottom, true, offset, n, &n); - /* Finish early if end of backing file has been reached */ if (ret == 0 && n == 0) { n = len - offset; @@ -199,18 +198,14 @@ static int coroutine_fn stream_run(Job *job, Error **errp) } } - if (!base) { + if (enable_cor) { bdrv_disable_copy_on_read(bs); } - /* Do not remove the backing file if an error was there but ignored. */ - ret = error; - qemu_vfree(buf); -out: - /* Modify backing chain and close BDSes in main loop */ - return ret; + /* Do not remove the backing file if an error was there but ignored. */ + return error; } static const BlockJobDriver stream_job_driver = { @@ -235,8 +230,10 @@ void stream_start(const char *job_id, BlockDriverState *bs, StreamBlockJob *s; BlockDriverState *iter; bool bs_read_only; + int basic_flags = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED; + BlockDriverState *bottom = bdrv_find_overlay(bs, base); - if (bdrv_freeze_backing_chain(bs, base, errp) < 0) { + if (bdrv_freeze_backing_chain(bs, bottom, errp) < 0) { return; } @@ -253,10 +250,8 @@ void stream_start(const char *job_id, BlockDriverState *bs, * already have our own plans. Also don't allow resize as the image size is * queried only at the job start and then cached. */ s = block_job_create(job_id, &stream_job_driver, NULL, bs, - BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED | - BLK_PERM_GRAPH_MOD, - BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED | - BLK_PERM_WRITE, + basic_flags | BLK_PERM_GRAPH_MOD, + basic_flags | BLK_PERM_WRITE, speed, creation_flags, NULL, NULL, errp); if (!s) { goto fail; @@ -264,15 +259,18 @@ void stream_start(const char *job_id, BlockDriverState *bs, /* Block all intermediate nodes between bs and base, because they will * disappear from the chain after this operation. The streaming job reads - * every block only once, assuming that it doesn't change, so block writes - * and resizes. */ + * every block only once, assuming that it doesn't change, so forbid writes + * and resizes. Reassign the base node pointer because the backing BS of the + * bottom node might change after the call to bdrv_reopen_set_read_only() + * due to parallel block jobs running. + */ + base = backing_bs(bottom); for (iter = backing_bs(bs); iter && iter != base; iter = backing_bs(iter)) { block_job_add_bdrv(&s->common, "intermediate node", iter, 0, - BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED, - &error_abort); + basic_flags, &error_abort); } - s->base = base; + s->bottom = bottom; s->backing_file_str = g_strdup(backing_file_str); s->bs_read_only = bs_read_only; s->chain_frozen = true; @@ -6502,6 +6502,14 @@ if test "$supported_os" = "no"; then echo "us upstream at qemu-devel@nongnu.org." fi +# Note that if the Python conditional here evaluates True we will exit +# with status 1 which is a shell 'false' value. +if ! $python -c 'import sys; sys.exit(sys.version_info < (3,0))'; then + echo + echo "warning: Python 2 support is deprecated" >&2 + echo "warning: Python 3 will be required for building future versions of QEMU" >&2 +fi + config_host_mak="config-host.mak" echo "# Automatically generated by configure - do not modify" >config-all-disas.mak @@ -25,7 +25,6 @@ #include "qemu/osdep.h" #include "qemu-common.h" #include "qemu/config-file.h" -#include "cpu.h" #include "monitor/monitor.h" #include "qapi/error.h" #include "qapi/qapi-commands-misc.h" @@ -33,7 +32,6 @@ #include "qapi/qmp/qerror.h" #include "qemu/error-report.h" #include "qemu/qemu-print.h" -#include "sysemu/sysemu.h" #include "sysemu/tcg.h" #include "sysemu/block-backend.h" #include "exec/gdbstub.h" @@ -56,7 +54,6 @@ #include "tcg.h" #include "hw/nmi.h" #include "sysemu/replay.h" -#include "hw/boards.h" #ifdef CONFIG_LINUX @@ -2200,190 +2197,6 @@ void list_cpus(const char *optarg) #endif } -CpuInfoList *qmp_query_cpus(Error **errp) -{ - MachineState *ms = MACHINE(qdev_get_machine()); - MachineClass *mc = MACHINE_GET_CLASS(ms); - CpuInfoList *head = NULL, *cur_item = NULL; - CPUState *cpu; - - CPU_FOREACH(cpu) { - CpuInfoList *info; -#if defined(TARGET_I386) - X86CPU *x86_cpu = X86_CPU(cpu); - CPUX86State *env = &x86_cpu->env; -#elif defined(TARGET_PPC) - PowerPCCPU *ppc_cpu = POWERPC_CPU(cpu); - CPUPPCState *env = &ppc_cpu->env; -#elif defined(TARGET_SPARC) - SPARCCPU *sparc_cpu = SPARC_CPU(cpu); - CPUSPARCState *env = &sparc_cpu->env; -#elif defined(TARGET_RISCV) - RISCVCPU *riscv_cpu = RISCV_CPU(cpu); - CPURISCVState *env = &riscv_cpu->env; -#elif defined(TARGET_MIPS) - MIPSCPU *mips_cpu = MIPS_CPU(cpu); - CPUMIPSState *env = &mips_cpu->env; -#elif defined(TARGET_TRICORE) - TriCoreCPU *tricore_cpu = TRICORE_CPU(cpu); - CPUTriCoreState *env = &tricore_cpu->env; -#elif defined(TARGET_S390X) - S390CPU *s390_cpu = S390_CPU(cpu); - CPUS390XState *env = &s390_cpu->env; -#endif - - cpu_synchronize_state(cpu); - - info = g_malloc0(sizeof(*info)); - info->value = g_malloc0(sizeof(*info->value)); - info->value->CPU = cpu->cpu_index; - info->value->current = (cpu == first_cpu); - info->value->halted = cpu->halted; - info->value->qom_path = object_get_canonical_path(OBJECT(cpu)); - info->value->thread_id = cpu->thread_id; -#if defined(TARGET_I386) - info->value->arch = CPU_INFO_ARCH_X86; - info->value->u.x86.pc = env->eip + env->segs[R_CS].base; -#elif defined(TARGET_PPC) - info->value->arch = CPU_INFO_ARCH_PPC; - info->value->u.ppc.nip = env->nip; -#elif defined(TARGET_SPARC) - info->value->arch = CPU_INFO_ARCH_SPARC; - info->value->u.q_sparc.pc = env->pc; - info->value->u.q_sparc.npc = env->npc; -#elif defined(TARGET_MIPS) - info->value->arch = CPU_INFO_ARCH_MIPS; - info->value->u.q_mips.PC = env->active_tc.PC; -#elif defined(TARGET_TRICORE) - info->value->arch = CPU_INFO_ARCH_TRICORE; - info->value->u.tricore.PC = env->PC; -#elif defined(TARGET_S390X) - info->value->arch = CPU_INFO_ARCH_S390; - info->value->u.s390.cpu_state = env->cpu_state; -#elif defined(TARGET_RISCV) - info->value->arch = CPU_INFO_ARCH_RISCV; - info->value->u.riscv.pc = env->pc; -#else - info->value->arch = CPU_INFO_ARCH_OTHER; -#endif - info->value->has_props = !!mc->cpu_index_to_instance_props; - if (info->value->has_props) { - CpuInstanceProperties *props; - props = g_malloc0(sizeof(*props)); - *props = mc->cpu_index_to_instance_props(ms, cpu->cpu_index); - info->value->props = props; - } - - /* XXX: waiting for the qapi to support GSList */ - if (!cur_item) { - head = cur_item = info; - } else { - cur_item->next = info; - cur_item = info; - } - } - - return head; -} - -static CpuInfoArch sysemu_target_to_cpuinfo_arch(SysEmuTarget target) -{ - /* - * The @SysEmuTarget -> @CpuInfoArch mapping below is based on the - * TARGET_ARCH -> TARGET_BASE_ARCH mapping in the "configure" script. - */ - switch (target) { - case SYS_EMU_TARGET_I386: - case SYS_EMU_TARGET_X86_64: - return CPU_INFO_ARCH_X86; - - case SYS_EMU_TARGET_PPC: - case SYS_EMU_TARGET_PPC64: - return CPU_INFO_ARCH_PPC; - - case SYS_EMU_TARGET_SPARC: - case SYS_EMU_TARGET_SPARC64: - return CPU_INFO_ARCH_SPARC; - - case SYS_EMU_TARGET_MIPS: - case SYS_EMU_TARGET_MIPSEL: - case SYS_EMU_TARGET_MIPS64: - case SYS_EMU_TARGET_MIPS64EL: - return CPU_INFO_ARCH_MIPS; - - case SYS_EMU_TARGET_TRICORE: - return CPU_INFO_ARCH_TRICORE; - - case SYS_EMU_TARGET_S390X: - return CPU_INFO_ARCH_S390; - - case SYS_EMU_TARGET_RISCV32: - case SYS_EMU_TARGET_RISCV64: - return CPU_INFO_ARCH_RISCV; - - default: - return CPU_INFO_ARCH_OTHER; - } -} - -static void cpustate_to_cpuinfo_s390(CpuInfoS390 *info, const CPUState *cpu) -{ -#ifdef TARGET_S390X - S390CPU *s390_cpu = S390_CPU(cpu); - CPUS390XState *env = &s390_cpu->env; - - info->cpu_state = env->cpu_state; -#else - abort(); -#endif -} - -/* - * fast means: we NEVER interrupt vCPU threads to retrieve - * information from KVM. - */ -CpuInfoFastList *qmp_query_cpus_fast(Error **errp) -{ - MachineState *ms = MACHINE(qdev_get_machine()); - MachineClass *mc = MACHINE_GET_CLASS(ms); - CpuInfoFastList *head = NULL, *cur_item = NULL; - SysEmuTarget target = qapi_enum_parse(&SysEmuTarget_lookup, TARGET_NAME, - -1, &error_abort); - CPUState *cpu; - - CPU_FOREACH(cpu) { - CpuInfoFastList *info = g_malloc0(sizeof(*info)); - info->value = g_malloc0(sizeof(*info->value)); - - info->value->cpu_index = cpu->cpu_index; - info->value->qom_path = object_get_canonical_path(OBJECT(cpu)); - info->value->thread_id = cpu->thread_id; - - info->value->has_props = !!mc->cpu_index_to_instance_props; - if (info->value->has_props) { - CpuInstanceProperties *props; - props = g_malloc0(sizeof(*props)); - *props = mc->cpu_index_to_instance_props(ms, cpu->cpu_index); - info->value->props = props; - } - - info->value->arch = sysemu_target_to_cpuinfo_arch(target); - info->value->target = target; - if (target == SYS_EMU_TARGET_S390X) { - cpustate_to_cpuinfo_s390(&info->value->u.s390x, cpu); - } - - if (!cur_item) { - head = cur_item = info; - } else { - cur_item->next = info; - cur_item = info; - } - } - - return head; -} - void qmp_memsave(int64_t addr, int64_t size, const char *filename, bool has_cpu, int64_t cpu_index, Error **errp) { diff --git a/default-configs/aarch64-softmmu.mak b/default-configs/aarch64-softmmu.mak index 49ff415ee4..958b1e08e4 100644 --- a/default-configs/aarch64-softmmu.mak +++ b/default-configs/aarch64-softmmu.mak @@ -5,3 +5,4 @@ include arm-softmmu.mak CONFIG_XLNX_ZYNQMP_ARM=y CONFIG_XLNX_VERSAL=y +CONFIG_SBSA_REF=y diff --git a/default-configs/mips-softmmu-common.mak b/default-configs/mips-softmmu-common.mak index e10ac4b20c..da29c6c0b2 100644 --- a/default-configs/mips-softmmu-common.mak +++ b/default-configs/mips-softmmu-common.mak @@ -1,9 +1,11 @@ # Common mips*-softmmu CONFIG defines +# CONFIG_SEMIHOSTING is always required on this architecture +CONFIG_SEMIHOSTING=y + CONFIG_ISA_BUS=y CONFIG_PCI=y CONFIG_PCI_DEVICES=y -CONFIG_ESP=y CONFIG_VGA_ISA=y CONFIG_VGA_ISA_MM=y CONFIG_VGA_CIRRUS=y @@ -25,8 +27,6 @@ CONFIG_I8257=y CONFIG_PIIX4=y CONFIG_IDE_ISA=y CONFIG_IDE_PIIX=y -CONFIG_NE2000_ISA=y -CONFIG_MIPSNET=y CONFIG_PFLASH_CFI01=y CONFIG_I8259=y CONFIG_MC146818RTC=y @@ -35,7 +35,6 @@ CONFIG_MIPS_CPS=y CONFIG_MIPS_ITU=y CONFIG_R4K=y CONFIG_MALTA=y -CONFIG_SEMIHOSTING=y CONFIG_PCNET_PCI=y CONFIG_MIPSSIM=y CONFIG_ACPI_SMBUS=y diff --git a/default-configs/mips64-softmmu.mak b/default-configs/mips64-softmmu.mak index bad7496672..a169738635 100644 --- a/default-configs/mips64-softmmu.mak +++ b/default-configs/mips64-softmmu.mak @@ -1,9 +1,4 @@ # Default configuration for mips64-softmmu include mips-softmmu-common.mak -CONFIG_RC4030=y -CONFIG_DP8393X=y -CONFIG_DS1225Y=y CONFIG_JAZZ=y -CONFIG_G364FB=y -CONFIG_JAZZ_LED=y diff --git a/default-configs/mips64el-softmmu.mak b/default-configs/mips64el-softmmu.mak index a67c9517a2..8b0c9b1e15 100644 --- a/default-configs/mips64el-softmmu.mak +++ b/default-configs/mips64el-softmmu.mak @@ -2,15 +2,10 @@ include mips-softmmu-common.mak CONFIG_IDE_VIA=y -CONFIG_RC4030=y -CONFIG_DP8393X=y -CONFIG_DS1225Y=y CONFIG_FULONG=y CONFIG_ATI_VGA=y CONFIG_RTL8139_PCI=y CONFIG_JAZZ=y -CONFIG_G364FB=y -CONFIG_JAZZ_LED=y CONFIG_VT82C686=y CONFIG_AHCI=y CONFIG_MIPS_BOSTON=y diff --git a/disas/riscv.c b/disas/riscv.c index 59a9b0437a..278d9be924 100644 --- a/disas/riscv.c +++ b/disas/riscv.c @@ -504,14 +504,19 @@ typedef struct { const rvc_constraint *constraints; } rv_comp_data; +enum { + rvcd_imm_nz = 0x1 +}; + typedef struct { const char * const name; const rv_codec codec; const char * const format; const rv_comp_data *pseudo; - const int decomp_rv32; - const int decomp_rv64; - const int decomp_rv128; + const short decomp_rv32; + const short decomp_rv64; + const short decomp_rv128; + const short decomp_data; } rv_opcode_data; /* register names */ @@ -609,7 +614,8 @@ static const rvc_constraint rvcc_rdtime[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc01, r static const rvc_constraint rvcc_rdinstret[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc02, rvc_end }; static const rvc_constraint rvcc_rdcycleh[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc80, rvc_end }; static const rvc_constraint rvcc_rdtimeh[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc81, rvc_end }; -static const rvc_constraint rvcc_rdinstreth[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc80, rvc_end }; +static const rvc_constraint rvcc_rdinstreth[] = { rvc_rs1_eq_x0, + rvc_csr_eq_0xc82, rvc_end }; static const rvc_constraint rvcc_frcsr[] = { rvc_rs1_eq_x0, rvc_csr_eq_0x003, rvc_end }; static const rvc_constraint rvcc_frrm[] = { rvc_rs1_eq_x0, rvc_csr_eq_0x002, rvc_end }; static const rvc_constraint rvcc_frflags[] = { rvc_rs1_eq_x0, rvc_csr_eq_0x001, rvc_end }; @@ -1011,7 +1017,8 @@ const rv_opcode_data opcode_data[] = { { "fcvt.q.lu", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 }, { "fmv.x.q", rv_codec_r, rv_fmt_rd_frs1, NULL, 0, 0, 0 }, { "fmv.q.x", rv_codec_r, rv_fmt_frd_rs1, NULL, 0, 0, 0 }, - { "c.addi4spn", rv_codec_ciw_4spn, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi, rv_op_addi }, + { "c.addi4spn", rv_codec_ciw_4spn, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, + rv_op_addi, rv_op_addi, rvcd_imm_nz }, { "c.fld", rv_codec_cl_ld, rv_fmt_frd_offset_rs1, NULL, rv_op_fld, rv_op_fld, 0 }, { "c.lw", rv_codec_cl_lw, rv_fmt_rd_offset_rs1, NULL, rv_op_lw, rv_op_lw, rv_op_lw }, { "c.flw", rv_codec_cl_lw, rv_fmt_frd_offset_rs1, NULL, rv_op_flw, 0, 0 }, @@ -1019,14 +1026,20 @@ const rv_opcode_data opcode_data[] = { { "c.sw", rv_codec_cs_sw, rv_fmt_rs2_offset_rs1, NULL, rv_op_sw, rv_op_sw, rv_op_sw }, { "c.fsw", rv_codec_cs_sw, rv_fmt_frs2_offset_rs1, NULL, rv_op_fsw, 0, 0 }, { "c.nop", rv_codec_ci_none, rv_fmt_none, NULL, rv_op_addi, rv_op_addi, rv_op_addi }, - { "c.addi", rv_codec_ci, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi, rv_op_addi }, + { "c.addi", rv_codec_ci, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi, + rv_op_addi, rvcd_imm_nz }, { "c.jal", rv_codec_cj_jal, rv_fmt_rd_offset, NULL, rv_op_jal, 0, 0 }, { "c.li", rv_codec_ci_li, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi, rv_op_addi }, - { "c.addi16sp", rv_codec_ci_16sp, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi, rv_op_addi }, - { "c.lui", rv_codec_ci_lui, rv_fmt_rd_imm, NULL, rv_op_lui, rv_op_lui, rv_op_lui }, - { "c.srli", rv_codec_cb_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_srli, rv_op_srli, rv_op_srli }, - { "c.srai", rv_codec_cb_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_srai, rv_op_srai, rv_op_srai }, - { "c.andi", rv_codec_cb_imm, rv_fmt_rd_rs1_imm, NULL, rv_op_andi, rv_op_andi, rv_op_andi }, + { "c.addi16sp", rv_codec_ci_16sp, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, + rv_op_addi, rv_op_addi, rvcd_imm_nz }, + { "c.lui", rv_codec_ci_lui, rv_fmt_rd_imm, NULL, rv_op_lui, rv_op_lui, + rv_op_lui, rvcd_imm_nz }, + { "c.srli", rv_codec_cb_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_srli, + rv_op_srli, rv_op_srli, rvcd_imm_nz }, + { "c.srai", rv_codec_cb_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_srai, + rv_op_srai, rv_op_srai, rvcd_imm_nz }, + { "c.andi", rv_codec_cb_imm, rv_fmt_rd_rs1_imm, NULL, rv_op_andi, + rv_op_andi, rv_op_andi }, { "c.sub", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_sub, rv_op_sub, rv_op_sub }, { "c.xor", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_xor, rv_op_xor, rv_op_xor }, { "c.or", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_or, rv_op_or, rv_op_or }, @@ -1036,7 +1049,8 @@ const rv_opcode_data opcode_data[] = { { "c.j", rv_codec_cj, rv_fmt_rd_offset, NULL, rv_op_jal, rv_op_jal, rv_op_jal }, { "c.beqz", rv_codec_cb, rv_fmt_rs1_rs2_offset, NULL, rv_op_beq, rv_op_beq, rv_op_beq }, { "c.bnez", rv_codec_cb, rv_fmt_rs1_rs2_offset, NULL, rv_op_bne, rv_op_bne, rv_op_bne }, - { "c.slli", rv_codec_ci_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_slli, rv_op_slli, rv_op_slli }, + { "c.slli", rv_codec_ci_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_slli, + rv_op_slli, rv_op_slli, rvcd_imm_nz }, { "c.fldsp", rv_codec_ci_ldsp, rv_fmt_frd_offset_rs1, NULL, rv_op_fld, rv_op_fld, rv_op_fld }, { "c.lwsp", rv_codec_ci_lwsp, rv_fmt_rd_offset_rs1, NULL, rv_op_lw, rv_op_lw, rv_op_lw }, { "c.flwsp", rv_codec_ci_lwsp, rv_fmt_frd_offset_rs1, NULL, rv_op_flw, 0, 0 }, @@ -2795,8 +2809,13 @@ static void decode_inst_decompress_rv32(rv_decode *dec) { int decomp_op = opcode_data[dec->op].decomp_rv32; if (decomp_op != rv_op_illegal) { - dec->op = decomp_op; - dec->codec = opcode_data[decomp_op].codec; + if ((opcode_data[dec->op].decomp_data & rvcd_imm_nz) + && dec->imm == 0) { + dec->op = rv_op_illegal; + } else { + dec->op = decomp_op; + dec->codec = opcode_data[decomp_op].codec; + } } } @@ -2804,8 +2823,13 @@ static void decode_inst_decompress_rv64(rv_decode *dec) { int decomp_op = opcode_data[dec->op].decomp_rv64; if (decomp_op != rv_op_illegal) { - dec->op = decomp_op; - dec->codec = opcode_data[decomp_op].codec; + if ((opcode_data[dec->op].decomp_data & rvcd_imm_nz) + && dec->imm == 0) { + dec->op = rv_op_illegal; + } else { + dec->op = decomp_op; + dec->codec = opcode_data[decomp_op].codec; + } } } @@ -2813,8 +2837,13 @@ static void decode_inst_decompress_rv128(rv_decode *dec) { int decomp_op = opcode_data[dec->op].decomp_rv128; if (decomp_op != rv_op_illegal) { - dec->op = decomp_op; - dec->codec = opcode_data[decomp_op].codec; + if ((opcode_data[dec->op].decomp_data & rvcd_imm_nz) + && dec->imm == 0) { + dec->op = rv_op_illegal; + } else { + dec->op = decomp_op; + dec->codec = opcode_data[decomp_op].codec; + } } } diff --git a/docs/specs/ppc-spapr-xive.rst b/docs/specs/ppc-spapr-xive.rst index 539ce7ca4e..6159bc6eed 100644 --- a/docs/specs/ppc-spapr-xive.rst +++ b/docs/specs/ppc-spapr-xive.rst @@ -34,19 +34,118 @@ CAS Negotiation --------------- QEMU advertises the supported interrupt modes in the device tree -property "ibm,arch-vec-5-platform-support" in byte 23 and the OS -Selection for XIVE is indicated in the "ibm,architecture-vec-5" +property ``ibm,arch-vec-5-platform-support`` in byte 23 and the OS +Selection for XIVE is indicated in the ``ibm,architecture-vec-5`` property byte 23. The interrupt modes supported by the machine depend on the CPU type (POWER9 is required for XIVE) but also on the machine property ``ic-mode`` which can be set on the command line. It can take the -following values: ``xics``, ``xive``, ``dual`` and currently ``xics`` -is the default but it may change in the future. +following values: ``xics``, ``xive``, and ``dual`` which is the +default mode. ``dual`` means that both modes XICS **and** XIVE are +supported and if the guest OS supports XIVE, this mode will be +selected. The choosen interrupt mode is activated after a reconfiguration done in a machine reset. +KVM negotiation +--------------- + +When the guest starts under KVM, the capabilities of the host kernel +and QEMU are also negotiated. Depending on the version of the host +kernel, KVM will advertise the XIVE capability to QEMU or not. + +Nevertheless, the available interrupt modes in the machine should not +depend on the XIVE KVM capability of the host. On older kernels +without XIVE KVM support, QEMU will use the emulated XIVE device as a +fallback and on newer kernels (>=5.2), the KVM XIVE device. + +As a final refinement, the user can also switch the use of the KVM +device with the machine option ``kernel_irqchip``. + + +XIVE support in KVM +~~~~~~~~~~~~~~~~~~~ + +For guest OSes supporting XIVE, the resulting interrupt modes on host +kernels with XIVE KVM support are the following: + +============== ============= ============= ================ +ic-mode kernel_irqchip +-------------- ---------------------------------------------- +/ allowed off on + (default) +============== ============= ============= ================ +dual (default) XIVE KVM XIVE emul. XIVE KVM +xive XIVE KVM XIVE emul. XIVE KVM +xics XICS KVM XICS emul. XICS KVM +============== ============= ============= ================ + +For legacy guest OSes without XIVE support, the resulting interrupt +modes are the following: + +============== ============= ============= ================ +ic-mode kernel_irqchip +-------------- ---------------------------------------------- +/ allowed off on + (default) +============== ============= ============= ================ +dual (default) XICS KVM XICS emul. XICS KVM +xive QEMU error(3) QEMU error(3) QEMU error(3) +xics XICS KVM XICS emul. XICS KVM +============== ============= ============= ================ + +(3) QEMU fails at CAS with ``Guest requested unavailable interrupt + mode (XICS), either don't set the ic-mode machine property or try + ic-mode=xics or ic-mode=dual`` + + +No XIVE support in KVM +~~~~~~~~~~~~~~~~~~~~~~ + +For guest OSes supporting XIVE, the resulting interrupt modes on host +kernels without XIVE KVM support are the following: + +============== ============= ============= ================ +ic-mode kernel_irqchip +-------------- ---------------------------------------------- +/ allowed off on + (default) +============== ============= ============= ================ +dual (default) XIVE emul.(1) XIVE emul. QEMU error (2) +xive XIVE emul.(1) XIVE emul. QEMU error (2) +xics XICS KVM XICS emul. XICS KVM +============== ============= ============= ================ + + +(1) QEMU warns with ``warning: kernel_irqchip requested but unavailable: + IRQ_XIVE capability must be present for KVM`` +(2) QEMU fails with ``kernel_irqchip requested but unavailable: + IRQ_XIVE capability must be present for KVM`` + + +For legacy guest OSes without XIVE support, the resulting interrupt +modes are the following: + +============== ============= ============= ================ +ic-mode kernel_irqchip +-------------- ---------------------------------------------- +/ allowed off on + (default) +============== ============= ============= ================ +dual (default) QEMU error(4) XICS emul. QEMU error(4) +xive QEMU error(3) QEMU error(3) QEMU error(3) +xics XICS KVM XICS emul. XICS KVM +============== ============= ============= ================ + +(3) QEMU fails at CAS with ``Guest requested unavailable interrupt + mode (XICS), either don't set the ic-mode machine property or try + ic-mode=xics or ic-mode=dual`` +(4) QEMU/KVM incompatibility due to device destruction in reset. QEMU fails + with ``KVM is too old to support ic-mode=dual,kernel-irqchip=on`` + + XIVE Device tree properties --------------------------- @@ -92,10 +191,11 @@ for both interrupt mode. The different ranges are defined as follow : - ``0x0000 .. 0x0FFF`` 4K CPU IPIs (only used under XIVE) - ``0x1000 .. 0x1000`` 1 EPOW - ``0x1001 .. 0x1001`` 1 HOTPLUG +- ``0x1002 .. 0x10FF`` unused - ``0x1100 .. 0x11FF`` 256 VIO devices -- ``0x1200 .. 0x127F`` 32 PHBs devices +- ``0x1200 .. 0x127F`` 32x4 LSIs for PHB devices - ``0x1280 .. 0x12FF`` unused -- ``0x1300 .. 0x1FFF`` PHB MSIs +- ``0x1300 .. 0x1FFF`` PHB MSIs (dynamically allocated) Monitoring XIVE --------------- diff --git a/docs/specs/ppc-xive.rst b/docs/specs/ppc-xive.rst index b997dc0629..148d57eb6a 100644 --- a/docs/specs/ppc-xive.rst +++ b/docs/specs/ppc-xive.rst @@ -20,10 +20,11 @@ The XIVE IC is composed of three sub-engines, each taking care of a processing layer of external interrupts: - Interrupt Virtualization Source Engine (IVSE), or Source Controller - (SC). These are found in PCI PHBs, in the PSI host bridge - controller, but also inside the main controller for the core IPIs - and other sub-chips (NX, CAP, NPU) of the chip/processor. They are - configured to feed the IVRE with events. + (SC). These are found in PCI PHBs, in the Processor Service + Interface (PSI) host bridge Controller, but also inside the main + controller for the core IPIs and other sub-chips (NX, CAP, NPU) of + the chip/processor. They are configured to feed the IVRE with + events. - Interrupt Virtualization Routing Engine (IVRE) or Virtualization Controller (VC). It handles event coalescing and perform interrupt routing by matching an event source number with an Event diff --git a/dump/Makefile.objs b/dump/Makefile.objs new file mode 100644 index 0000000000..d2a5db3b81 --- /dev/null +++ b/dump/Makefile.objs @@ -0,0 +1,3 @@ +obj-y += dump.o +common-obj-y += dump-hmp-cmds.o +obj-$(TARGET_X86_64) += win_dump.o diff --git a/dump/dump-hmp-cmds.c b/dump/dump-hmp-cmds.c new file mode 100644 index 0000000000..3dbf44372c --- /dev/null +++ b/dump/dump-hmp-cmds.c @@ -0,0 +1,88 @@ +/* + * Human Monitor Interface commands + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "monitor/hmp.h" +#include "monitor/monitor.h" +#include "qapi/error.h" +#include "qapi/qapi-commands-dump.h" +#include "qapi/qmp/qdict.h" + +void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict) +{ + Error *err = NULL; + bool win_dmp = qdict_get_try_bool(qdict, "windmp", false); + bool paging = qdict_get_try_bool(qdict, "paging", false); + bool zlib = qdict_get_try_bool(qdict, "zlib", false); + bool lzo = qdict_get_try_bool(qdict, "lzo", false); + bool snappy = qdict_get_try_bool(qdict, "snappy", false); + const char *file = qdict_get_str(qdict, "filename"); + bool has_begin = qdict_haskey(qdict, "begin"); + bool has_length = qdict_haskey(qdict, "length"); + bool has_detach = qdict_haskey(qdict, "detach"); + int64_t begin = 0; + int64_t length = 0; + bool detach = false; + enum DumpGuestMemoryFormat dump_format = DUMP_GUEST_MEMORY_FORMAT_ELF; + char *prot; + + if (zlib + lzo + snappy + win_dmp > 1) { + error_setg(&err, "only one of '-z|-l|-s|-w' can be set"); + hmp_handle_error(mon, &err); + return; + } + + if (win_dmp) { + dump_format = DUMP_GUEST_MEMORY_FORMAT_WIN_DMP; + } + + if (zlib) { + dump_format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_ZLIB; + } + + if (lzo) { + dump_format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_LZO; + } + + if (snappy) { + dump_format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_SNAPPY; + } + + if (has_begin) { + begin = qdict_get_int(qdict, "begin"); + } + if (has_length) { + length = qdict_get_int(qdict, "length"); + } + if (has_detach) { + detach = qdict_get_bool(qdict, "detach"); + } + + prot = g_strconcat("file:", file, NULL); + + qmp_dump_guest_memory(paging, prot, true, detach, has_begin, begin, + has_length, length, true, dump_format, &err); + hmp_handle_error(mon, &err); + g_free(prot); +} + +void hmp_info_dump(Monitor *mon, const QDict *qdict) +{ + DumpQueryResult *result = qmp_query_dump(NULL); + + assert(result && result->status < DUMP_STATUS__MAX); + monitor_printf(mon, "Status: %s\n", DumpStatus_str(result->status)); + + if (result->status == DUMP_STATUS_ACTIVE) { + float percent = 0; + assert(result->total != 0); + percent = 100.0 * result->completed / result->total; + monitor_printf(mon, "Finished: %.2f %%\n", percent); + } + + qapi_free_DumpQueryResult(result); +} @@ -24,8 +24,8 @@ #include "sysemu/memory_mapping.h" #include "sysemu/cpus.h" #include "qapi/error.h" -#include "qapi/qapi-commands-misc.h" -#include "qapi/qapi-events-misc.h" +#include "qapi/qapi-commands-dump.h" +#include "qapi/qapi-events-dump.h" #include "qapi/qmp/qerror.h" #include "qemu/error-report.h" #include "hw/misc/vmcoreinfo.h" diff --git a/win_dump.c b/dump/win_dump.c index 0142655d3d..0142655d3d 100644 --- a/win_dump.c +++ b/dump/win_dump.c diff --git a/win_dump.h b/dump/win_dump.h index b8c25348f4..b8c25348f4 100644 --- a/win_dump.h +++ b/dump/win_dump.h diff --git a/hmp-commands.hx b/hmp-commands.hx index 8b7aec3e8d..bfa5681dd2 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -955,8 +955,8 @@ ETEXI { .name = "announce_self", - .args_type = "", - .params = "", + .args_type = "interfaces:s?,id:s?", + .params = "[interfaces] [id]", .help = "Trigger GARP/RARP announcements", .cmd = hmp_announce_self, }, @@ -967,6 +967,9 @@ STEXI Trigger a round of GARP/RARP broadcasts; this is useful for explicitly updating the network infrastructure after a reconfiguration or some forms of migration. The timings of the round are set by the migration announce parameters. +An optional comma separated @var{interfaces} list restricts the announce to the +named set of interfaces. An optional @var{id} can be used to start a separate announce +timer and to change the parameters of it later. ETEXI { diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 9aced9d54d..ab65ecd216 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -184,6 +184,20 @@ config REALVIEW select DS1338 # I2C RTC+NVRAM select USB_OHCI +config SBSA_REF + bool + imply PCI_DEVICES + select AHCI + select ARM_SMMUV3 + select GPIO_KEY + select PCI_EXPRESS + select PCI_EXPRESS_GENERIC_BRIDGE + select PFLASH_CFI01 + select PL011 # UART + select PL031 # RTC + select PL061 # GPIO + select USB_EHCI_SYSBUS + config SABRELITE bool select FSL_IMX6 diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs index 994e67dd0d..43ce8d5b19 100644 --- a/hw/arm/Makefile.objs +++ b/hw/arm/Makefile.objs @@ -19,6 +19,7 @@ obj-$(CONFIG_SPITZ) += spitz.o obj-$(CONFIG_TOSA) += tosa.o obj-$(CONFIG_Z2) += z2.o obj-$(CONFIG_REALVIEW) += realview.o +obj-$(CONFIG_SBSA_REF) += sbsa-ref.o obj-$(CONFIG_STELLARIS) += stellaris.o obj-$(CONFIG_COLLIE) += collie.o obj-$(CONFIG_VERSATILE) += versatilepb.o diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index d2ad2da24b..8b6d304247 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -22,17 +22,18 @@ #include "hw/misc/tmp105.h" #include "qemu/log.h" #include "sysemu/block-backend.h" +#include "sysemu/sysemu.h" #include "hw/loader.h" #include "qemu/error-report.h" #include "qemu/units.h" static struct arm_boot_info aspeed_board_binfo = { .board_id = -1, /* device-tree-only board */ - .nb_cpus = 1, }; struct AspeedBoardState { AspeedSoCState soc; + MemoryRegion ram_container; MemoryRegion ram; MemoryRegion max_ram; }; @@ -72,6 +73,17 @@ struct AspeedBoardState { SCU_AST2500_HW_STRAP_ACPI_ENABLE | \ SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_MASTER)) +/* Swift hardware value: 0xF11AD206 */ +#define SWIFT_BMC_HW_STRAP1 ( \ + AST2500_HW_STRAP1_DEFAULTS | \ + SCU_AST2500_HW_STRAP_SPI_AUTOFETCH_ENABLE | \ + SCU_AST2500_HW_STRAP_GPIO_STRAP_ENABLE | \ + SCU_AST2500_HW_STRAP_UART_DEBUG | \ + SCU_AST2500_HW_STRAP_DDR4_ENABLE | \ + SCU_H_PLL_BYPASS_EN | \ + SCU_AST2500_HW_STRAP_ACPI_ENABLE | \ + SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_MASTER)) + /* Witherspoon hardware value: 0xF10AD216 (but use romulus definition) */ #define WITHERSPOON_BMC_HW_STRAP1 ROMULUS_BMC_HW_STRAP1 @@ -159,6 +171,10 @@ static void aspeed_board_init(MachineState *machine, ram_addr_t max_ram_size; bmc = g_new0(AspeedBoardState, 1); + + memory_region_init(&bmc->ram_container, NULL, "aspeed-ram-container", + UINT32_MAX); + object_initialize_child(OBJECT(machine), "soc", &bmc->soc, (sizeof(bmc->soc)), cfg->soc_name, &error_abort, NULL); @@ -171,6 +187,8 @@ static void aspeed_board_init(MachineState *machine, &error_abort); object_property_set_int(OBJECT(&bmc->soc), cfg->num_cs, "num-cs", &error_abort); + object_property_set_int(OBJECT(&bmc->soc), smp_cpus, "num-cpus", + &error_abort); if (machine->kernel_filename) { /* * When booting with a -kernel command line there is no u-boot @@ -191,18 +209,16 @@ static void aspeed_board_init(MachineState *machine, &error_abort); memory_region_allocate_system_memory(&bmc->ram, NULL, "ram", ram_size); - memory_region_add_subregion(get_system_memory(), sc->info->sdram_base, - &bmc->ram); - object_property_add_const_link(OBJECT(&bmc->soc), "ram", OBJECT(&bmc->ram), - &error_abort); + memory_region_add_subregion(&bmc->ram_container, 0, &bmc->ram); + memory_region_add_subregion(get_system_memory(), + sc->info->memmap[ASPEED_SDRAM], + &bmc->ram_container); max_ram_size = object_property_get_uint(OBJECT(&bmc->soc), "max-ram-size", &error_abort); memory_region_init_io(&bmc->max_ram, NULL, &max_ram_ops, NULL, "max_ram", max_ram_size - ram_size); - memory_region_add_subregion(get_system_memory(), - sc->info->sdram_base + ram_size, - &bmc->max_ram); + memory_region_add_subregion(&bmc->ram_container, ram_size, &bmc->max_ram); aspeed_board_init_flashes(&bmc->soc.fmc, cfg->fmc_model, &error_abort); aspeed_board_init_flashes(&bmc->soc.spi[0], cfg->spi_model, &error_abort); @@ -229,7 +245,8 @@ static void aspeed_board_init(MachineState *machine, aspeed_board_binfo.initrd_filename = machine->initrd_filename; aspeed_board_binfo.kernel_cmdline = machine->kernel_cmdline; aspeed_board_binfo.ram_size = ram_size; - aspeed_board_binfo.loader_start = sc->info->sdram_base; + aspeed_board_binfo.loader_start = sc->info->memmap[ASPEED_SDRAM]; + aspeed_board_binfo.nb_cpus = bmc->soc.num_cpus; if (cfg->i2c_init) { cfg->i2c_init(bmc); @@ -286,6 +303,35 @@ static void romulus_bmc_i2c_init(AspeedBoardState *bmc) i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), "ds1338", 0x32); } +static void swift_bmc_i2c_init(AspeedBoardState *bmc) +{ + AspeedSoCState *soc = &bmc->soc; + + i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 3), "pca9552", 0x60); + + /* The swift board expects a TMP275 but a TMP105 is compatible */ + i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 7), "tmp105", 0x48); + /* The swift board expects a pca9551 but a pca9552 is compatible */ + i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 7), "pca9552", 0x60); + + /* The swift board expects an Epson RX8900 RTC but a ds1338 is compatible */ + i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 8), "ds1338", 0x32); + i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 8), "pca9552", 0x60); + + i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 9), "tmp423", 0x4c); + /* The swift board expects a pca9539 but a pca9552 is compatible */ + i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 9), "pca9552", 0x74); + + i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 10), "tmp423", 0x4c); + /* The swift board expects a pca9539 but a pca9552 is compatible */ + i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 10), "pca9552", + 0x74); + + /* The swift board expects a TMP275 but a TMP105 is compatible */ + i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 12), "tmp105", 0x48); + i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 12), "tmp105", 0x4a); +} + static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc) { AspeedSoCState *soc = &bmc->soc; @@ -326,7 +372,7 @@ static void aspeed_machine_class_init(ObjectClass *oc, void *data) mc->desc = board->desc; mc->init = aspeed_machine_init; - mc->max_cpus = 1; + mc->max_cpus = ASPEED_CPUS_NUM; mc->no_sdcard = 1; mc->no_floppy = 1; mc->no_cdrom = 1; @@ -377,6 +423,16 @@ static const AspeedBoardConfig aspeed_boards[] = { .i2c_init = romulus_bmc_i2c_init, .ram = 512 * MiB, }, { + .name = MACHINE_TYPE_NAME("swift-bmc"), + .desc = "OpenPOWER Swift BMC (ARM1176)", + .soc_name = "ast2500-a1", + .hw_strap1 = SWIFT_BMC_HW_STRAP1, + .fmc_model = "mx66l1g45g", + .spi_model = "mx66l1g45g", + .num_cs = 2, + .i2c_init = swift_bmc_i2c_init, + .ram = 512 * MiB, + }, { .name = MACHINE_TYPE_NAME("witherspoon-bmc"), .desc = "OpenPOWER Witherspoon BMC (ARM1176)", .soc_name = "ast2500-a1", diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c index a2ea8c7484..c6fb3700f2 100644 --- a/hw/arm/aspeed_soc.c +++ b/hw/arm/aspeed_soc.c @@ -19,36 +19,99 @@ #include "hw/char/serial.h" #include "qemu/log.h" #include "qemu/module.h" +#include "qemu/error-report.h" #include "hw/i2c/aspeed_i2c.h" #include "net/net.h" -#define ASPEED_SOC_UART_5_BASE 0x00184000 #define ASPEED_SOC_IOMEM_SIZE 0x00200000 -#define ASPEED_SOC_IOMEM_BASE 0x1E600000 -#define ASPEED_SOC_FMC_BASE 0x1E620000 -#define ASPEED_SOC_SPI_BASE 0x1E630000 -#define ASPEED_SOC_SPI2_BASE 0x1E631000 -#define ASPEED_SOC_VIC_BASE 0x1E6C0000 -#define ASPEED_SOC_SDMC_BASE 0x1E6E0000 -#define ASPEED_SOC_SCU_BASE 0x1E6E2000 -#define ASPEED_SOC_SRAM_BASE 0x1E720000 -#define ASPEED_SOC_TIMER_BASE 0x1E782000 -#define ASPEED_SOC_WDT_BASE 0x1E785000 -#define ASPEED_SOC_I2C_BASE 0x1E78A000 -#define ASPEED_SOC_ETH1_BASE 0x1E660000 -#define ASPEED_SOC_ETH2_BASE 0x1E680000 - -static const int uart_irqs[] = { 9, 32, 33, 34, 10 }; -static const int timer_irqs[] = { 16, 17, 18, 35, 36, 37, 38, 39, }; - -#define AST2400_SDRAM_BASE 0x40000000 -#define AST2500_SDRAM_BASE 0x80000000 - -static const hwaddr aspeed_soc_ast2400_spi_bases[] = { ASPEED_SOC_SPI_BASE }; -static const char *aspeed_soc_ast2400_typenames[] = { "aspeed.smc.spi" }; -static const hwaddr aspeed_soc_ast2500_spi_bases[] = { ASPEED_SOC_SPI_BASE, - ASPEED_SOC_SPI2_BASE}; +static const hwaddr aspeed_soc_ast2400_memmap[] = { + [ASPEED_IOMEM] = 0x1E600000, + [ASPEED_FMC] = 0x1E620000, + [ASPEED_SPI1] = 0x1E630000, + [ASPEED_VIC] = 0x1E6C0000, + [ASPEED_SDMC] = 0x1E6E0000, + [ASPEED_SCU] = 0x1E6E2000, + [ASPEED_XDMA] = 0x1E6E7000, + [ASPEED_ADC] = 0x1E6E9000, + [ASPEED_SRAM] = 0x1E720000, + [ASPEED_GPIO] = 0x1E780000, + [ASPEED_RTC] = 0x1E781000, + [ASPEED_TIMER1] = 0x1E782000, + [ASPEED_WDT] = 0x1E785000, + [ASPEED_PWM] = 0x1E786000, + [ASPEED_LPC] = 0x1E789000, + [ASPEED_IBT] = 0x1E789140, + [ASPEED_I2C] = 0x1E78A000, + [ASPEED_ETH1] = 0x1E660000, + [ASPEED_ETH2] = 0x1E680000, + [ASPEED_UART1] = 0x1E783000, + [ASPEED_UART5] = 0x1E784000, + [ASPEED_VUART] = 0x1E787000, + [ASPEED_SDRAM] = 0x40000000, +}; + +static const hwaddr aspeed_soc_ast2500_memmap[] = { + [ASPEED_IOMEM] = 0x1E600000, + [ASPEED_FMC] = 0x1E620000, + [ASPEED_SPI1] = 0x1E630000, + [ASPEED_SPI2] = 0x1E631000, + [ASPEED_VIC] = 0x1E6C0000, + [ASPEED_SDMC] = 0x1E6E0000, + [ASPEED_SCU] = 0x1E6E2000, + [ASPEED_XDMA] = 0x1E6E7000, + [ASPEED_ADC] = 0x1E6E9000, + [ASPEED_SRAM] = 0x1E720000, + [ASPEED_GPIO] = 0x1E780000, + [ASPEED_RTC] = 0x1E781000, + [ASPEED_TIMER1] = 0x1E782000, + [ASPEED_WDT] = 0x1E785000, + [ASPEED_PWM] = 0x1E786000, + [ASPEED_LPC] = 0x1E789000, + [ASPEED_IBT] = 0x1E789140, + [ASPEED_I2C] = 0x1E78A000, + [ASPEED_ETH1] = 0x1E660000, + [ASPEED_ETH2] = 0x1E680000, + [ASPEED_UART1] = 0x1E783000, + [ASPEED_UART5] = 0x1E784000, + [ASPEED_VUART] = 0x1E787000, + [ASPEED_SDRAM] = 0x80000000, +}; + +static const int aspeed_soc_ast2400_irqmap[] = { + [ASPEED_UART1] = 9, + [ASPEED_UART2] = 32, + [ASPEED_UART3] = 33, + [ASPEED_UART4] = 34, + [ASPEED_UART5] = 10, + [ASPEED_VUART] = 8, + [ASPEED_FMC] = 19, + [ASPEED_SDMC] = 0, + [ASPEED_SCU] = 21, + [ASPEED_ADC] = 31, + [ASPEED_GPIO] = 20, + [ASPEED_RTC] = 22, + [ASPEED_TIMER1] = 16, + [ASPEED_TIMER2] = 17, + [ASPEED_TIMER3] = 18, + [ASPEED_TIMER4] = 35, + [ASPEED_TIMER5] = 36, + [ASPEED_TIMER6] = 37, + [ASPEED_TIMER7] = 38, + [ASPEED_TIMER8] = 39, + [ASPEED_WDT] = 27, + [ASPEED_PWM] = 28, + [ASPEED_LPC] = 8, + [ASPEED_IBT] = 8, /* LPC */ + [ASPEED_I2C] = 12, + [ASPEED_ETH1] = 2, + [ASPEED_ETH2] = 3, + [ASPEED_XDMA] = 6, +}; + +#define aspeed_soc_ast2500_irqmap aspeed_soc_ast2400_irqmap + +static const char *aspeed_soc_ast2400_typenames[] = { "aspeed.smc.spi" }; static const char *aspeed_soc_ast2500_typenames[] = { "aspeed.smc.ast2500-spi1", "aspeed.smc.ast2500-spi2" }; @@ -57,57 +120,71 @@ static const AspeedSoCInfo aspeed_socs[] = { .name = "ast2400-a0", .cpu_type = ARM_CPU_TYPE_NAME("arm926"), .silicon_rev = AST2400_A0_SILICON_REV, - .sdram_base = AST2400_SDRAM_BASE, .sram_size = 0x8000, .spis_num = 1, - .spi_bases = aspeed_soc_ast2400_spi_bases, .fmc_typename = "aspeed.smc.fmc", .spi_typename = aspeed_soc_ast2400_typenames, .wdts_num = 2, + .irqmap = aspeed_soc_ast2400_irqmap, + .memmap = aspeed_soc_ast2400_memmap, + .num_cpus = 1, }, { .name = "ast2400-a1", .cpu_type = ARM_CPU_TYPE_NAME("arm926"), .silicon_rev = AST2400_A1_SILICON_REV, - .sdram_base = AST2400_SDRAM_BASE, .sram_size = 0x8000, .spis_num = 1, - .spi_bases = aspeed_soc_ast2400_spi_bases, .fmc_typename = "aspeed.smc.fmc", .spi_typename = aspeed_soc_ast2400_typenames, .wdts_num = 2, + .irqmap = aspeed_soc_ast2400_irqmap, + .memmap = aspeed_soc_ast2400_memmap, + .num_cpus = 1, }, { .name = "ast2400", .cpu_type = ARM_CPU_TYPE_NAME("arm926"), .silicon_rev = AST2400_A0_SILICON_REV, - .sdram_base = AST2400_SDRAM_BASE, .sram_size = 0x8000, .spis_num = 1, - .spi_bases = aspeed_soc_ast2400_spi_bases, .fmc_typename = "aspeed.smc.fmc", .spi_typename = aspeed_soc_ast2400_typenames, .wdts_num = 2, + .irqmap = aspeed_soc_ast2400_irqmap, + .memmap = aspeed_soc_ast2400_memmap, + .num_cpus = 1, }, { .name = "ast2500-a1", .cpu_type = ARM_CPU_TYPE_NAME("arm1176"), .silicon_rev = AST2500_A1_SILICON_REV, - .sdram_base = AST2500_SDRAM_BASE, .sram_size = 0x9000, .spis_num = 2, - .spi_bases = aspeed_soc_ast2500_spi_bases, .fmc_typename = "aspeed.smc.ast2500-fmc", .spi_typename = aspeed_soc_ast2500_typenames, .wdts_num = 3, + .irqmap = aspeed_soc_ast2500_irqmap, + .memmap = aspeed_soc_ast2500_memmap, + .num_cpus = 1, }, }; +static qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int ctrl) +{ + AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s); + + return qdev_get_gpio_in(DEVICE(&s->vic), sc->info->irqmap[ctrl]); +} + static void aspeed_soc_init(Object *obj) { AspeedSoCState *s = ASPEED_SOC(obj); AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s); int i; - object_initialize_child(obj, "cpu", OBJECT(&s->cpu), sizeof(s->cpu), - sc->info->cpu_type, &error_abort, NULL); + for (i = 0; i < sc->info->num_cpus; i++) { + object_initialize_child(obj, "cpu[*]", OBJECT(&s->cpu[i]), + sizeof(s->cpu[i]), sc->info->cpu_type, + &error_abort, NULL); + } sysbus_init_child_obj(obj, "scu", OBJECT(&s->scu), sizeof(s->scu), TYPE_ASPEED_SCU); @@ -123,6 +200,9 @@ static void aspeed_soc_init(Object *obj) sysbus_init_child_obj(obj, "vic", OBJECT(&s->vic), sizeof(s->vic), TYPE_ASPEED_VIC); + sysbus_init_child_obj(obj, "rtc", OBJECT(&s->rtc), sizeof(s->rtc), + TYPE_ASPEED_RTC); + sysbus_init_child_obj(obj, "timerctrl", OBJECT(&s->timerctrl), sizeof(s->timerctrl), TYPE_ASPEED_TIMER); object_property_add_const_link(OBJECT(&s->timerctrl), "scu", @@ -155,10 +235,17 @@ static void aspeed_soc_init(Object *obj) sizeof(s->wdt[i]), TYPE_ASPEED_WDT); qdev_prop_set_uint32(DEVICE(&s->wdt[i]), "silicon-rev", sc->info->silicon_rev); + object_property_add_const_link(OBJECT(&s->wdt[i]), "scu", + OBJECT(&s->scu), &error_abort); } - sysbus_init_child_obj(obj, "ftgmac100", OBJECT(&s->ftgmac100), - sizeof(s->ftgmac100), TYPE_FTGMAC100); + for (i = 0; i < ASPEED_MACS_NUM; i++) { + sysbus_init_child_obj(obj, "ftgmac100[*]", OBJECT(&s->ftgmac100[i]), + sizeof(s->ftgmac100[i]), TYPE_FTGMAC100); + } + + sysbus_init_child_obj(obj, "xdma", OBJECT(&s->xdma), sizeof(s->xdma), + TYPE_ASPEED_XDMA); } static void aspeed_soc_realize(DeviceState *dev, Error **errp) @@ -169,14 +256,22 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) Error *err = NULL, *local_err = NULL; /* IO space */ - create_unimplemented_device("aspeed_soc.io", - ASPEED_SOC_IOMEM_BASE, ASPEED_SOC_IOMEM_SIZE); + create_unimplemented_device("aspeed_soc.io", sc->info->memmap[ASPEED_IOMEM], + ASPEED_SOC_IOMEM_SIZE); + + if (s->num_cpus > sc->info->num_cpus) { + warn_report("%s: invalid number of CPUs %d, using default %d", + sc->info->name, s->num_cpus, sc->info->num_cpus); + s->num_cpus = sc->info->num_cpus; + } /* CPU */ - object_property_set_bool(OBJECT(&s->cpu), true, "realized", &err); - if (err) { - error_propagate(errp, err); - return; + for (i = 0; i < s->num_cpus; i++) { + object_property_set_bool(OBJECT(&s->cpu[i]), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } } /* SRAM */ @@ -186,8 +281,8 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) error_propagate(errp, err); return; } - memory_region_add_subregion(get_system_memory(), ASPEED_SOC_SRAM_BASE, - &s->sram); + memory_region_add_subregion(get_system_memory(), + sc->info->memmap[ASPEED_SRAM], &s->sram); /* SCU */ object_property_set_bool(OBJECT(&s->scu), true, "realized", &err); @@ -195,7 +290,7 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) error_propagate(errp, err); return; } - sysbus_mmio_map(SYS_BUS_DEVICE(&s->scu), 0, ASPEED_SOC_SCU_BASE); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->scu), 0, sc->info->memmap[ASPEED_SCU]); /* VIC */ object_property_set_bool(OBJECT(&s->vic), true, "realized", &err); @@ -203,29 +298,39 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) error_propagate(errp, err); return; } - sysbus_mmio_map(SYS_BUS_DEVICE(&s->vic), 0, ASPEED_SOC_VIC_BASE); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->vic), 0, sc->info->memmap[ASPEED_VIC]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->vic), 0, qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_IRQ)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->vic), 1, qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_FIQ)); + /* RTC */ + object_property_set_bool(OBJECT(&s->rtc), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->rtc), 0, sc->info->memmap[ASPEED_RTC]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->rtc), 0, + aspeed_soc_get_irq(s, ASPEED_RTC)); + /* Timer */ object_property_set_bool(OBJECT(&s->timerctrl), true, "realized", &err); if (err) { error_propagate(errp, err); return; } - sysbus_mmio_map(SYS_BUS_DEVICE(&s->timerctrl), 0, ASPEED_SOC_TIMER_BASE); - for (i = 0; i < ARRAY_SIZE(timer_irqs); i++) { - qemu_irq irq = qdev_get_gpio_in(DEVICE(&s->vic), timer_irqs[i]); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->timerctrl), 0, + sc->info->memmap[ASPEED_TIMER1]); + for (i = 0; i < ASPEED_TIMER_NR_TIMERS; i++) { + qemu_irq irq = aspeed_soc_get_irq(s, ASPEED_TIMER1 + i); sysbus_connect_irq(SYS_BUS_DEVICE(&s->timerctrl), i, irq); } /* UART - attach an 8250 to the IO space as our UART5 */ if (serial_hd(0)) { - qemu_irq uart5 = qdev_get_gpio_in(DEVICE(&s->vic), uart_irqs[4]); - serial_mm_init(get_system_memory(), - ASPEED_SOC_IOMEM_BASE + ASPEED_SOC_UART_5_BASE, 2, + qemu_irq uart5 = aspeed_soc_get_irq(s, ASPEED_UART5); + serial_mm_init(get_system_memory(), sc->info->memmap[ASPEED_UART5], 2, uart5, 38400, serial_hd(0), DEVICE_LITTLE_ENDIAN); } @@ -235,21 +340,27 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) error_propagate(errp, err); return; } - sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c), 0, ASPEED_SOC_I2C_BASE); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c), 0, sc->info->memmap[ASPEED_I2C]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c), 0, - qdev_get_gpio_in(DEVICE(&s->vic), 12)); + aspeed_soc_get_irq(s, ASPEED_I2C)); /* FMC, The number of CS is set at the board level */ + object_property_set_int(OBJECT(&s->fmc), sc->info->memmap[ASPEED_SDRAM], + "sdram-base", &err); + if (err) { + error_propagate(errp, err); + return; + } object_property_set_bool(OBJECT(&s->fmc), true, "realized", &err); if (err) { error_propagate(errp, err); return; } - sysbus_mmio_map(SYS_BUS_DEVICE(&s->fmc), 0, ASPEED_SOC_FMC_BASE); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->fmc), 0, sc->info->memmap[ASPEED_FMC]); sysbus_mmio_map(SYS_BUS_DEVICE(&s->fmc), 1, s->fmc.ctrl->flash_window_base); sysbus_connect_irq(SYS_BUS_DEVICE(&s->fmc), 0, - qdev_get_gpio_in(DEVICE(&s->vic), 19)); + aspeed_soc_get_irq(s, ASPEED_FMC)); /* SPI */ for (i = 0; i < sc->info->spis_num; i++) { @@ -261,7 +372,8 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) error_propagate(errp, err); return; } - sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0, sc->info->spi_bases[i]); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0, + sc->info->memmap[ASPEED_SPI1 + i]); sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 1, s->spi[i].ctrl->flash_window_base); } @@ -272,7 +384,7 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) error_propagate(errp, err); return; } - sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdmc), 0, ASPEED_SOC_SDMC_BASE); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdmc), 0, sc->info->memmap[ASPEED_SDMC]); /* Watch dog */ for (i = 0; i < sc->info->wdts_num; i++) { @@ -282,23 +394,42 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0, - ASPEED_SOC_WDT_BASE + i * 0x20); + sc->info->memmap[ASPEED_WDT] + i * 0x20); } /* Net */ - qdev_set_nic_properties(DEVICE(&s->ftgmac100), &nd_table[0]); - object_property_set_bool(OBJECT(&s->ftgmac100), true, "aspeed", &err); - object_property_set_bool(OBJECT(&s->ftgmac100), true, "realized", - &local_err); - error_propagate(&err, local_err); + for (i = 0; i < nb_nics; i++) { + qdev_set_nic_properties(DEVICE(&s->ftgmac100[i]), &nd_table[i]); + object_property_set_bool(OBJECT(&s->ftgmac100[i]), true, "aspeed", + &err); + object_property_set_bool(OBJECT(&s->ftgmac100[i]), true, "realized", + &local_err); + error_propagate(&err, local_err); + if (err) { + error_propagate(errp, err); + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->ftgmac100[i]), 0, + sc->info->memmap[ASPEED_ETH1 + i]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->ftgmac100[i]), 0, + aspeed_soc_get_irq(s, ASPEED_ETH1 + i)); + } + + /* XDMA */ + object_property_set_bool(OBJECT(&s->xdma), true, "realized", &err); if (err) { error_propagate(errp, err); return; } - sysbus_mmio_map(SYS_BUS_DEVICE(&s->ftgmac100), 0, ASPEED_SOC_ETH1_BASE); - sysbus_connect_irq(SYS_BUS_DEVICE(&s->ftgmac100), 0, - qdev_get_gpio_in(DEVICE(&s->vic), 2)); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->xdma), 0, + sc->info->memmap[ASPEED_XDMA]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->xdma), 0, + aspeed_soc_get_irq(s, ASPEED_XDMA)); } +static Property aspeed_soc_properties[] = { + DEFINE_PROP_UINT32("num-cpus", AspeedSoCState, num_cpus, 0), + DEFINE_PROP_END_OF_LIST(), +}; static void aspeed_soc_class_init(ObjectClass *oc, void *data) { @@ -309,6 +440,7 @@ static void aspeed_soc_class_init(ObjectClass *oc, void *data) dc->realize = aspeed_soc_realize; /* Reason: Uses serial_hds and nd_table in realize() directly */ dc->user_creatable = false; + dc->props = aspeed_soc_properties; } static const TypeInfo aspeed_soc_type_info = { diff --git a/hw/arm/boot.c b/hw/arm/boot.c index b2f93f6bef..1fb24fbef2 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -1109,10 +1109,11 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu, info->initrd_filename); exit(1); } - if (info->initrd_start + initrd_size > info->ram_size) { + if (info->initrd_start + initrd_size > ram_end) { error_report("could not load initrd '%s': " "too big to fit into RAM after the kernel", info->initrd_filename); + exit(1); } } else { initrd_size = 0; diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c index b7e3526b4f..2eddf3f25c 100644 --- a/hw/arm/fsl-imx7.c +++ b/hw/arm/fsl-imx7.c @@ -526,6 +526,17 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp) */ create_unimplemented_device("lcdif", FSL_IMX7_LCDIF_ADDR, FSL_IMX7_LCDIF_SIZE); + + /* + * DMA APBH + */ + create_unimplemented_device("dma-apbh", FSL_IMX7_DMA_APBH_ADDR, + FSL_IMX7_DMA_APBH_SIZE); + /* + * PCIe PHY + */ + create_unimplemented_device("pcie-phy", FSL_IMX7_PCIE_PHY_ADDR, + FSL_IMX7_PCIE_PHY_SIZE); } static void fsl_imx7_class_init(ObjectClass *oc, void *data) diff --git a/hw/arm/msf2-som.c b/hw/arm/msf2-som.c index 8c550a8bdd..2c9984bb3b 100644 --- a/hw/arm/msf2-som.c +++ b/hw/arm/msf2-som.c @@ -53,6 +53,7 @@ static void emcraft_sf2_s2s010_init(MachineState *machine) if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) { error_report("This board can only be used with CPU %s", mc->default_cpu_type); + exit(1); } memory_region_init_ram(ddr, NULL, "ddr-ram", DDR_SIZE, diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c new file mode 100644 index 0000000000..ee53f0ff60 --- /dev/null +++ b/hw/arm/sbsa-ref.c @@ -0,0 +1,806 @@ +/* + * ARM SBSA Reference Platform emulation + * + * Copyright (c) 2018 Linaro Limited + * Written by Hongbo Zhang <hongbo.zhang@linaro.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "qemu/units.h" +#include "sysemu/device_tree.h" +#include "sysemu/numa.h" +#include "sysemu/sysemu.h" +#include "exec/address-spaces.h" +#include "exec/hwaddr.h" +#include "kvm_arm.h" +#include "hw/arm/boot.h" +#include "hw/block/flash.h" +#include "hw/boards.h" +#include "hw/ide/internal.h" +#include "hw/ide/ahci_internal.h" +#include "hw/intc/arm_gicv3_common.h" +#include "hw/loader.h" +#include "hw/pci-host/gpex.h" +#include "hw/usb.h" +#include "net/net.h" + +#define RAMLIMIT_GB 8192 +#define RAMLIMIT_BYTES (RAMLIMIT_GB * GiB) + +#define NUM_IRQS 256 +#define NUM_SMMU_IRQS 4 +#define NUM_SATA_PORTS 6 + +#define VIRTUAL_PMU_IRQ 7 +#define ARCH_GIC_MAINT_IRQ 9 +#define ARCH_TIMER_VIRT_IRQ 11 +#define ARCH_TIMER_S_EL1_IRQ 13 +#define ARCH_TIMER_NS_EL1_IRQ 14 +#define ARCH_TIMER_NS_EL2_IRQ 10 + +enum { + SBSA_FLASH, + SBSA_MEM, + SBSA_CPUPERIPHS, + SBSA_GIC_DIST, + SBSA_GIC_REDIST, + SBSA_SMMU, + SBSA_UART, + SBSA_RTC, + SBSA_PCIE, + SBSA_PCIE_MMIO, + SBSA_PCIE_MMIO_HIGH, + SBSA_PCIE_PIO, + SBSA_PCIE_ECAM, + SBSA_GPIO, + SBSA_SECURE_UART, + SBSA_SECURE_UART_MM, + SBSA_SECURE_MEM, + SBSA_AHCI, + SBSA_EHCI, +}; + +typedef struct MemMapEntry { + hwaddr base; + hwaddr size; +} MemMapEntry; + +typedef struct { + MachineState parent; + struct arm_boot_info bootinfo; + int smp_cpus; + void *fdt; + int fdt_size; + int psci_conduit; + PFlashCFI01 *flash[2]; +} SBSAMachineState; + +#define TYPE_SBSA_MACHINE MACHINE_TYPE_NAME("sbsa-ref") +#define SBSA_MACHINE(obj) \ + OBJECT_CHECK(SBSAMachineState, (obj), TYPE_SBSA_MACHINE) + +static const MemMapEntry sbsa_ref_memmap[] = { + /* 512M boot ROM */ + [SBSA_FLASH] = { 0, 0x20000000 }, + /* 512M secure memory */ + [SBSA_SECURE_MEM] = { 0x20000000, 0x20000000 }, + /* Space reserved for CPU peripheral devices */ + [SBSA_CPUPERIPHS] = { 0x40000000, 0x00040000 }, + [SBSA_GIC_DIST] = { 0x40060000, 0x00010000 }, + [SBSA_GIC_REDIST] = { 0x40080000, 0x04000000 }, + [SBSA_UART] = { 0x60000000, 0x00001000 }, + [SBSA_RTC] = { 0x60010000, 0x00001000 }, + [SBSA_GPIO] = { 0x60020000, 0x00001000 }, + [SBSA_SECURE_UART] = { 0x60030000, 0x00001000 }, + [SBSA_SECURE_UART_MM] = { 0x60040000, 0x00001000 }, + [SBSA_SMMU] = { 0x60050000, 0x00020000 }, + /* Space here reserved for more SMMUs */ + [SBSA_AHCI] = { 0x60100000, 0x00010000 }, + [SBSA_EHCI] = { 0x60110000, 0x00010000 }, + /* Space here reserved for other devices */ + [SBSA_PCIE_PIO] = { 0x7fff0000, 0x00010000 }, + /* 32-bit address PCIE MMIO space */ + [SBSA_PCIE_MMIO] = { 0x80000000, 0x70000000 }, + /* 256M PCIE ECAM space */ + [SBSA_PCIE_ECAM] = { 0xf0000000, 0x10000000 }, + /* ~1TB PCIE MMIO space (4GB to 1024GB boundary) */ + [SBSA_PCIE_MMIO_HIGH] = { 0x100000000ULL, 0xFF00000000ULL }, + [SBSA_MEM] = { 0x10000000000ULL, RAMLIMIT_BYTES }, +}; + +static const int sbsa_ref_irqmap[] = { + [SBSA_UART] = 1, + [SBSA_RTC] = 2, + [SBSA_PCIE] = 3, /* ... to 6 */ + [SBSA_GPIO] = 7, + [SBSA_SECURE_UART] = 8, + [SBSA_SECURE_UART_MM] = 9, + [SBSA_AHCI] = 10, + [SBSA_EHCI] = 11, +}; + +/* + * Firmware on this machine only uses ACPI table to load OS, these limited + * device tree nodes are just to let firmware know the info which varies from + * command line parameters, so it is not necessary to be fully compatible + * with the kernel CPU and NUMA binding rules. + */ +static void create_fdt(SBSAMachineState *sms) +{ + void *fdt = create_device_tree(&sms->fdt_size); + const MachineState *ms = MACHINE(sms); + int cpu; + + if (!fdt) { + error_report("create_device_tree() failed"); + exit(1); + } + + sms->fdt = fdt; + + qemu_fdt_setprop_string(fdt, "/", "compatible", "linux,sbsa-ref"); + qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x2); + qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x2); + + if (have_numa_distance) { + int size = nb_numa_nodes * nb_numa_nodes * 3 * sizeof(uint32_t); + uint32_t *matrix = g_malloc0(size); + int idx, i, j; + + for (i = 0; i < nb_numa_nodes; i++) { + for (j = 0; j < nb_numa_nodes; j++) { + idx = (i * nb_numa_nodes + j) * 3; + matrix[idx + 0] = cpu_to_be32(i); + matrix[idx + 1] = cpu_to_be32(j); + matrix[idx + 2] = cpu_to_be32(numa_info[i].distance[j]); + } + } + + qemu_fdt_add_subnode(fdt, "/distance-map"); + qemu_fdt_setprop(fdt, "/distance-map", "distance-matrix", + matrix, size); + g_free(matrix); + } + + qemu_fdt_add_subnode(sms->fdt, "/cpus"); + + for (cpu = sms->smp_cpus - 1; cpu >= 0; cpu--) { + char *nodename = g_strdup_printf("/cpus/cpu@%d", cpu); + ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu)); + CPUState *cs = CPU(armcpu); + + qemu_fdt_add_subnode(sms->fdt, nodename); + + if (ms->possible_cpus->cpus[cs->cpu_index].props.has_node_id) { + qemu_fdt_setprop_cell(sms->fdt, nodename, "numa-node-id", + ms->possible_cpus->cpus[cs->cpu_index].props.node_id); + } + + g_free(nodename); + } +} + +#define SBSA_FLASH_SECTOR_SIZE (256 * KiB) + +static PFlashCFI01 *sbsa_flash_create1(SBSAMachineState *sms, + const char *name, + const char *alias_prop_name) +{ + /* + * Create a single flash device. We use the same parameters as + * the flash devices on the Versatile Express board. + */ + DeviceState *dev = qdev_create(NULL, TYPE_PFLASH_CFI01); + + qdev_prop_set_uint64(dev, "sector-length", SBSA_FLASH_SECTOR_SIZE); + qdev_prop_set_uint8(dev, "width", 4); + qdev_prop_set_uint8(dev, "device-width", 2); + qdev_prop_set_bit(dev, "big-endian", false); + qdev_prop_set_uint16(dev, "id0", 0x89); + qdev_prop_set_uint16(dev, "id1", 0x18); + qdev_prop_set_uint16(dev, "id2", 0x00); + qdev_prop_set_uint16(dev, "id3", 0x00); + qdev_prop_set_string(dev, "name", name); + object_property_add_child(OBJECT(sms), name, OBJECT(dev), + &error_abort); + object_property_add_alias(OBJECT(sms), alias_prop_name, + OBJECT(dev), "drive", &error_abort); + return PFLASH_CFI01(dev); +} + +static void sbsa_flash_create(SBSAMachineState *sms) +{ + sms->flash[0] = sbsa_flash_create1(sms, "sbsa.flash0", "pflash0"); + sms->flash[1] = sbsa_flash_create1(sms, "sbsa.flash1", "pflash1"); +} + +static void sbsa_flash_map1(PFlashCFI01 *flash, + hwaddr base, hwaddr size, + MemoryRegion *sysmem) +{ + DeviceState *dev = DEVICE(flash); + + assert(size % SBSA_FLASH_SECTOR_SIZE == 0); + assert(size / SBSA_FLASH_SECTOR_SIZE <= UINT32_MAX); + qdev_prop_set_uint32(dev, "num-blocks", size / SBSA_FLASH_SECTOR_SIZE); + qdev_init_nofail(dev); + + memory_region_add_subregion(sysmem, base, + sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), + 0)); +} + +static void sbsa_flash_map(SBSAMachineState *sms, + MemoryRegion *sysmem, + MemoryRegion *secure_sysmem) +{ + /* + * Map two flash devices to fill the SBSA_FLASH space in the memmap. + * sysmem is the system memory space. secure_sysmem is the secure view + * of the system, and the first flash device should be made visible only + * there. The second flash device is visible to both secure and nonsecure. + * If sysmem == secure_sysmem this means there is no separate Secure + * address space and both flash devices are generally visible. + */ + hwaddr flashsize = sbsa_ref_memmap[SBSA_FLASH].size / 2; + hwaddr flashbase = sbsa_ref_memmap[SBSA_FLASH].base; + + sbsa_flash_map1(sms->flash[0], flashbase, flashsize, + secure_sysmem); + sbsa_flash_map1(sms->flash[1], flashbase + flashsize, flashsize, + sysmem); +} + +static bool sbsa_firmware_init(SBSAMachineState *sms, + MemoryRegion *sysmem, + MemoryRegion *secure_sysmem) +{ + int i; + BlockBackend *pflash_blk0; + + /* Map legacy -drive if=pflash to machine properties */ + for (i = 0; i < ARRAY_SIZE(sms->flash); i++) { + pflash_cfi01_legacy_drive(sms->flash[i], + drive_get(IF_PFLASH, 0, i)); + } + + sbsa_flash_map(sms, sysmem, secure_sysmem); + + pflash_blk0 = pflash_cfi01_get_blk(sms->flash[0]); + + if (bios_name) { + char *fname; + MemoryRegion *mr; + int image_size; + + if (pflash_blk0) { + error_report("The contents of the first flash device may be " + "specified with -bios or with -drive if=pflash... " + "but you cannot use both options at once"); + exit(1); + } + + /* Fall back to -bios */ + + fname = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); + if (!fname) { + error_report("Could not find ROM image '%s'", bios_name); + exit(1); + } + mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(sms->flash[0]), 0); + image_size = load_image_mr(fname, mr); + g_free(fname); + if (image_size < 0) { + error_report("Could not load ROM image '%s'", bios_name); + exit(1); + } + } + + return pflash_blk0 || bios_name; +} + +static void create_secure_ram(SBSAMachineState *sms, + MemoryRegion *secure_sysmem) +{ + MemoryRegion *secram = g_new(MemoryRegion, 1); + hwaddr base = sbsa_ref_memmap[SBSA_SECURE_MEM].base; + hwaddr size = sbsa_ref_memmap[SBSA_SECURE_MEM].size; + + memory_region_init_ram(secram, NULL, "sbsa-ref.secure-ram", size, + &error_fatal); + memory_region_add_subregion(secure_sysmem, base, secram); +} + +static void create_gic(SBSAMachineState *sms, qemu_irq *pic) +{ + DeviceState *gicdev; + SysBusDevice *gicbusdev; + const char *gictype; + uint32_t redist0_capacity, redist0_count; + int i; + + gictype = gicv3_class_name(); + + gicdev = qdev_create(NULL, gictype); + qdev_prop_set_uint32(gicdev, "revision", 3); + qdev_prop_set_uint32(gicdev, "num-cpu", smp_cpus); + /* + * Note that the num-irq property counts both internal and external + * interrupts; there are always 32 of the former (mandated by GIC spec). + */ + qdev_prop_set_uint32(gicdev, "num-irq", NUM_IRQS + 32); + qdev_prop_set_bit(gicdev, "has-security-extensions", true); + + redist0_capacity = + sbsa_ref_memmap[SBSA_GIC_REDIST].size / GICV3_REDIST_SIZE; + redist0_count = MIN(smp_cpus, redist0_capacity); + + qdev_prop_set_uint32(gicdev, "len-redist-region-count", 1); + qdev_prop_set_uint32(gicdev, "redist-region-count[0]", redist0_count); + + qdev_init_nofail(gicdev); + gicbusdev = SYS_BUS_DEVICE(gicdev); + sysbus_mmio_map(gicbusdev, 0, sbsa_ref_memmap[SBSA_GIC_DIST].base); + sysbus_mmio_map(gicbusdev, 1, sbsa_ref_memmap[SBSA_GIC_REDIST].base); + + /* + * Wire the outputs from each CPU's generic timer and the GICv3 + * maintenance interrupt signal to the appropriate GIC PPI inputs, + * and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's inputs. + */ + for (i = 0; i < smp_cpus; i++) { + DeviceState *cpudev = DEVICE(qemu_get_cpu(i)); + int ppibase = NUM_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS; + int irq; + /* + * Mapping from the output timer irq lines from the CPU to the + * GIC PPI inputs used for this board. + */ + const int timer_irq[] = { + [GTIMER_PHYS] = ARCH_TIMER_NS_EL1_IRQ, + [GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ, + [GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ, + [GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ, + }; + + for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) { + qdev_connect_gpio_out(cpudev, irq, + qdev_get_gpio_in(gicdev, + ppibase + timer_irq[irq])); + } + + qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt", 0, + qdev_get_gpio_in(gicdev, ppibase + + ARCH_GIC_MAINT_IRQ)); + qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0, + qdev_get_gpio_in(gicdev, ppibase + + VIRTUAL_PMU_IRQ)); + + sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ)); + sysbus_connect_irq(gicbusdev, i + smp_cpus, + qdev_get_gpio_in(cpudev, ARM_CPU_FIQ)); + sysbus_connect_irq(gicbusdev, i + 2 * smp_cpus, + qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ)); + sysbus_connect_irq(gicbusdev, i + 3 * smp_cpus, + qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ)); + } + + for (i = 0; i < NUM_IRQS; i++) { + pic[i] = qdev_get_gpio_in(gicdev, i); + } +} + +static void create_uart(const SBSAMachineState *sms, qemu_irq *pic, int uart, + MemoryRegion *mem, Chardev *chr) +{ + hwaddr base = sbsa_ref_memmap[uart].base; + int irq = sbsa_ref_irqmap[uart]; + DeviceState *dev = qdev_create(NULL, "pl011"); + SysBusDevice *s = SYS_BUS_DEVICE(dev); + + qdev_prop_set_chr(dev, "chardev", chr); + qdev_init_nofail(dev); + memory_region_add_subregion(mem, base, + sysbus_mmio_get_region(s, 0)); + sysbus_connect_irq(s, 0, pic[irq]); +} + +static void create_rtc(const SBSAMachineState *sms, qemu_irq *pic) +{ + hwaddr base = sbsa_ref_memmap[SBSA_RTC].base; + int irq = sbsa_ref_irqmap[SBSA_RTC]; + + sysbus_create_simple("pl031", base, pic[irq]); +} + +static DeviceState *gpio_key_dev; +static void sbsa_ref_powerdown_req(Notifier *n, void *opaque) +{ + /* use gpio Pin 3 for power button event */ + qemu_set_irq(qdev_get_gpio_in(gpio_key_dev, 0), 1); +} + +static Notifier sbsa_ref_powerdown_notifier = { + .notify = sbsa_ref_powerdown_req +}; + +static void create_gpio(const SBSAMachineState *sms, qemu_irq *pic) +{ + DeviceState *pl061_dev; + hwaddr base = sbsa_ref_memmap[SBSA_GPIO].base; + int irq = sbsa_ref_irqmap[SBSA_GPIO]; + + pl061_dev = sysbus_create_simple("pl061", base, pic[irq]); + + gpio_key_dev = sysbus_create_simple("gpio-key", -1, + qdev_get_gpio_in(pl061_dev, 3)); + + /* connect powerdown request */ + qemu_register_powerdown_notifier(&sbsa_ref_powerdown_notifier); +} + +static void create_ahci(const SBSAMachineState *sms, qemu_irq *pic) +{ + hwaddr base = sbsa_ref_memmap[SBSA_AHCI].base; + int irq = sbsa_ref_irqmap[SBSA_AHCI]; + DeviceState *dev; + DriveInfo *hd[NUM_SATA_PORTS]; + SysbusAHCIState *sysahci; + AHCIState *ahci; + int i; + + dev = qdev_create(NULL, "sysbus-ahci"); + qdev_prop_set_uint32(dev, "num-ports", NUM_SATA_PORTS); + qdev_init_nofail(dev); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); + sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[irq]); + + sysahci = SYSBUS_AHCI(dev); + ahci = &sysahci->ahci; + ide_drive_get(hd, ARRAY_SIZE(hd)); + for (i = 0; i < ahci->ports; i++) { + if (hd[i] == NULL) { + continue; + } + ide_create_drive(&ahci->dev[i].port, 0, hd[i]); + } +} + +static void create_ehci(const SBSAMachineState *sms, qemu_irq *pic) +{ + hwaddr base = sbsa_ref_memmap[SBSA_EHCI].base; + int irq = sbsa_ref_irqmap[SBSA_EHCI]; + + sysbus_create_simple("platform-ehci-usb", base, pic[irq]); +} + +static void create_smmu(const SBSAMachineState *sms, qemu_irq *pic, + PCIBus *bus) +{ + hwaddr base = sbsa_ref_memmap[SBSA_SMMU].base; + int irq = sbsa_ref_irqmap[SBSA_SMMU]; + DeviceState *dev; + int i; + + dev = qdev_create(NULL, "arm-smmuv3"); + + object_property_set_link(OBJECT(dev), OBJECT(bus), "primary-bus", + &error_abort); + qdev_init_nofail(dev); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); + for (i = 0; i < NUM_SMMU_IRQS; i++) { + sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pic[irq + i]); + } +} + +static void create_pcie(SBSAMachineState *sms, qemu_irq *pic) +{ + hwaddr base_ecam = sbsa_ref_memmap[SBSA_PCIE_ECAM].base; + hwaddr size_ecam = sbsa_ref_memmap[SBSA_PCIE_ECAM].size; + hwaddr base_mmio = sbsa_ref_memmap[SBSA_PCIE_MMIO].base; + hwaddr size_mmio = sbsa_ref_memmap[SBSA_PCIE_MMIO].size; + hwaddr base_mmio_high = sbsa_ref_memmap[SBSA_PCIE_MMIO_HIGH].base; + hwaddr size_mmio_high = sbsa_ref_memmap[SBSA_PCIE_MMIO_HIGH].size; + hwaddr base_pio = sbsa_ref_memmap[SBSA_PCIE_PIO].base; + int irq = sbsa_ref_irqmap[SBSA_PCIE]; + MemoryRegion *mmio_alias, *mmio_alias_high, *mmio_reg; + MemoryRegion *ecam_alias, *ecam_reg; + DeviceState *dev; + PCIHostState *pci; + int i; + + dev = qdev_create(NULL, TYPE_GPEX_HOST); + qdev_init_nofail(dev); + + /* Map ECAM space */ + ecam_alias = g_new0(MemoryRegion, 1); + ecam_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); + memory_region_init_alias(ecam_alias, OBJECT(dev), "pcie-ecam", + ecam_reg, 0, size_ecam); + memory_region_add_subregion(get_system_memory(), base_ecam, ecam_alias); + + /* Map the MMIO space */ + mmio_alias = g_new0(MemoryRegion, 1); + mmio_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1); + memory_region_init_alias(mmio_alias, OBJECT(dev), "pcie-mmio", + mmio_reg, base_mmio, size_mmio); + memory_region_add_subregion(get_system_memory(), base_mmio, mmio_alias); + + /* Map the MMIO_HIGH space */ + mmio_alias_high = g_new0(MemoryRegion, 1); + memory_region_init_alias(mmio_alias_high, OBJECT(dev), "pcie-mmio-high", + mmio_reg, base_mmio_high, size_mmio_high); + memory_region_add_subregion(get_system_memory(), base_mmio_high, + mmio_alias_high); + + /* Map IO port space */ + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, base_pio); + + for (i = 0; i < GPEX_NUM_IRQS; i++) { + sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pic[irq + i]); + gpex_set_irq_num(GPEX_HOST(dev), i, irq + i); + } + + pci = PCI_HOST_BRIDGE(dev); + if (pci->bus) { + for (i = 0; i < nb_nics; i++) { + NICInfo *nd = &nd_table[i]; + + if (!nd->model) { + nd->model = g_strdup("e1000e"); + } + + pci_nic_init_nofail(nd, pci->bus, nd->model, NULL); + } + } + + pci_create_simple(pci->bus, -1, "VGA"); + + create_smmu(sms, pic, pci->bus); +} + +static void *sbsa_ref_dtb(const struct arm_boot_info *binfo, int *fdt_size) +{ + const SBSAMachineState *board = container_of(binfo, SBSAMachineState, + bootinfo); + + *fdt_size = board->fdt_size; + return board->fdt; +} + +static void sbsa_ref_init(MachineState *machine) +{ + SBSAMachineState *sms = SBSA_MACHINE(machine); + MachineClass *mc = MACHINE_GET_CLASS(machine); + MemoryRegion *sysmem = get_system_memory(); + MemoryRegion *secure_sysmem = NULL; + MemoryRegion *ram = g_new(MemoryRegion, 1); + bool firmware_loaded; + const CPUArchIdList *possible_cpus; + int n, sbsa_max_cpus; + qemu_irq pic[NUM_IRQS]; + + if (strcmp(machine->cpu_type, ARM_CPU_TYPE_NAME("cortex-a57"))) { + error_report("sbsa-ref: CPU type other than the built-in " + "cortex-a57 not supported"); + exit(1); + } + + if (kvm_enabled()) { + error_report("sbsa-ref: KVM is not supported for this machine"); + exit(1); + } + + /* + * The Secure view of the world is the same as the NonSecure, + * but with a few extra devices. Create it as a container region + * containing the system memory at low priority; any secure-only + * devices go in at higher priority and take precedence. + */ + secure_sysmem = g_new(MemoryRegion, 1); + memory_region_init(secure_sysmem, OBJECT(machine), "secure-memory", + UINT64_MAX); + memory_region_add_subregion_overlap(secure_sysmem, 0, sysmem, -1); + + firmware_loaded = sbsa_firmware_init(sms, sysmem, + secure_sysmem ?: sysmem); + + if (machine->kernel_filename && firmware_loaded) { + error_report("sbsa-ref: No fw_cfg device on this machine, " + "so -kernel option is not supported when firmware loaded, " + "please load OS from hard disk instead"); + exit(1); + } + + /* + * This machine has EL3 enabled, external firmware should supply PSCI + * implementation, so the QEMU's internal PSCI is disabled. + */ + sms->psci_conduit = QEMU_PSCI_CONDUIT_DISABLED; + + sbsa_max_cpus = sbsa_ref_memmap[SBSA_GIC_REDIST].size / GICV3_REDIST_SIZE; + + if (max_cpus > sbsa_max_cpus) { + error_report("Number of SMP CPUs requested (%d) exceeds max CPUs " + "supported by machine 'sbsa-ref' (%d)", + max_cpus, sbsa_max_cpus); + exit(1); + } + + sms->smp_cpus = smp_cpus; + + if (machine->ram_size > sbsa_ref_memmap[SBSA_MEM].size) { + error_report("sbsa-ref: cannot model more than %dGB RAM", RAMLIMIT_GB); + exit(1); + } + + possible_cpus = mc->possible_cpu_arch_ids(machine); + for (n = 0; n < possible_cpus->len; n++) { + Object *cpuobj; + CPUState *cs; + + if (n >= smp_cpus) { + break; + } + + cpuobj = object_new(possible_cpus->cpus[n].type); + object_property_set_int(cpuobj, possible_cpus->cpus[n].arch_id, + "mp-affinity", NULL); + + cs = CPU(cpuobj); + cs->cpu_index = n; + + numa_cpu_pre_plug(&possible_cpus->cpus[cs->cpu_index], DEVICE(cpuobj), + &error_fatal); + + if (object_property_find(cpuobj, "reset-cbar", NULL)) { + object_property_set_int(cpuobj, + sbsa_ref_memmap[SBSA_CPUPERIPHS].base, + "reset-cbar", &error_abort); + } + + object_property_set_link(cpuobj, OBJECT(sysmem), "memory", + &error_abort); + + object_property_set_link(cpuobj, OBJECT(secure_sysmem), + "secure-memory", &error_abort); + + object_property_set_bool(cpuobj, true, "realized", &error_fatal); + object_unref(cpuobj); + } + + memory_region_allocate_system_memory(ram, NULL, "sbsa-ref.ram", + machine->ram_size); + memory_region_add_subregion(sysmem, sbsa_ref_memmap[SBSA_MEM].base, ram); + + create_fdt(sms); + + create_secure_ram(sms, secure_sysmem); + + create_gic(sms, pic); + + create_uart(sms, pic, SBSA_UART, sysmem, serial_hd(0)); + create_uart(sms, pic, SBSA_SECURE_UART, secure_sysmem, serial_hd(1)); + /* Second secure UART for RAS and MM from EL0 */ + create_uart(sms, pic, SBSA_SECURE_UART_MM, secure_sysmem, serial_hd(2)); + + create_rtc(sms, pic); + + create_gpio(sms, pic); + + create_ahci(sms, pic); + + create_ehci(sms, pic); + + create_pcie(sms, pic); + + sms->bootinfo.ram_size = machine->ram_size; + sms->bootinfo.kernel_filename = machine->kernel_filename; + sms->bootinfo.nb_cpus = smp_cpus; + sms->bootinfo.board_id = -1; + sms->bootinfo.loader_start = sbsa_ref_memmap[SBSA_MEM].base; + sms->bootinfo.get_dtb = sbsa_ref_dtb; + sms->bootinfo.firmware_loaded = firmware_loaded; + arm_load_kernel(ARM_CPU(first_cpu), &sms->bootinfo); +} + +static uint64_t sbsa_ref_cpu_mp_affinity(SBSAMachineState *sms, int idx) +{ + uint8_t clustersz = ARM_DEFAULT_CPUS_PER_CLUSTER; + return arm_cpu_mp_affinity(idx, clustersz); +} + +static const CPUArchIdList *sbsa_ref_possible_cpu_arch_ids(MachineState *ms) +{ + SBSAMachineState *sms = SBSA_MACHINE(ms); + int n; + + if (ms->possible_cpus) { + assert(ms->possible_cpus->len == max_cpus); + return ms->possible_cpus; + } + + ms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) + + sizeof(CPUArchId) * max_cpus); + ms->possible_cpus->len = max_cpus; + for (n = 0; n < ms->possible_cpus->len; n++) { + ms->possible_cpus->cpus[n].type = ms->cpu_type; + ms->possible_cpus->cpus[n].arch_id = + sbsa_ref_cpu_mp_affinity(sms, n); + ms->possible_cpus->cpus[n].props.has_thread_id = true; + ms->possible_cpus->cpus[n].props.thread_id = n; + } + return ms->possible_cpus; +} + +static CpuInstanceProperties +sbsa_ref_cpu_index_to_props(MachineState *ms, unsigned cpu_index) +{ + MachineClass *mc = MACHINE_GET_CLASS(ms); + const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms); + + assert(cpu_index < possible_cpus->len); + return possible_cpus->cpus[cpu_index].props; +} + +static int64_t +sbsa_ref_get_default_cpu_node_id(const MachineState *ms, int idx) +{ + return idx % nb_numa_nodes; +} + +static void sbsa_ref_instance_init(Object *obj) +{ + SBSAMachineState *sms = SBSA_MACHINE(obj); + + sbsa_flash_create(sms); +} + +static void sbsa_ref_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->init = sbsa_ref_init; + mc->desc = "QEMU 'SBSA Reference' ARM Virtual Machine"; + mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a57"); + mc->max_cpus = 512; + mc->pci_allow_0_address = true; + mc->minimum_page_bits = 12; + mc->block_default_type = IF_IDE; + mc->no_cdrom = 1; + mc->default_ram_size = 1 * GiB; + mc->default_cpus = 4; + mc->possible_cpu_arch_ids = sbsa_ref_possible_cpu_arch_ids; + mc->cpu_index_to_instance_props = sbsa_ref_cpu_index_to_props; + mc->get_default_cpu_node_id = sbsa_ref_get_default_cpu_node_id; +} + +static const TypeInfo sbsa_ref_info = { + .name = TYPE_SBSA_MACHINE, + .parent = TYPE_MACHINE, + .instance_init = sbsa_ref_instance_init, + .class_init = sbsa_ref_class_init, + .instance_size = sizeof(SBSAMachineState), +}; + +static void sbsa_ref_machine_init(void) +{ + type_register_static(&sbsa_ref_info); +} + +type_init(sbsa_ref_machine_init); diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 431e2900fd..ed009fa447 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -176,6 +176,7 @@ static const int a15irqmap[] = { }; static const char *valid_cpus[] = { + ARM_CPU_TYPE_NAME("cortex-a7"), ARM_CPU_TYPE_NAME("cortex-a15"), ARM_CPU_TYPE_NAME("cortex-a53"), ARM_CPU_TYPE_NAME("cortex-a57"), diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c index 35080d915f..db4a246b22 100644 --- a/hw/block/pflash_cfi01.c +++ b/hw/block/pflash_cfi01.c @@ -248,7 +248,6 @@ static uint32_t pflash_data_read(PFlashCFI01 *pfl, hwaddr offset, switch (width) { case 1: ret = p[offset]; - trace_pflash_data_read8(offset, ret); break; case 2: if (be) { @@ -258,7 +257,6 @@ static uint32_t pflash_data_read(PFlashCFI01 *pfl, hwaddr offset, ret = p[offset]; ret |= p[offset + 1] << 8; } - trace_pflash_data_read16(offset, ret); break; case 4: if (be) { @@ -272,12 +270,12 @@ static uint32_t pflash_data_read(PFlashCFI01 *pfl, hwaddr offset, ret |= p[offset + 2] << 16; ret |= p[offset + 3] << 24; } - trace_pflash_data_read32(offset, ret); break; default: DPRINTF("BUG in %s\n", __func__); abort(); } + trace_pflash_data_read(offset, width << 1, ret); return ret; } @@ -288,7 +286,6 @@ static uint32_t pflash_read(PFlashCFI01 *pfl, hwaddr offset, uint32_t ret; ret = -1; - trace_pflash_read(offset, pfl->cmd, width, pfl->wcycle); switch (pfl->cmd) { default: /* This should never happen : reset state & treat it as a read */ @@ -391,6 +388,8 @@ static uint32_t pflash_read(PFlashCFI01 *pfl, hwaddr offset, break; } + trace_pflash_io_read(offset, width, width << 1, ret, pfl->cmd, pfl->wcycle); + return ret; } @@ -414,7 +413,7 @@ static inline void pflash_data_write(PFlashCFI01 *pfl, hwaddr offset, { uint8_t *p = pfl->storage; - trace_pflash_data_write(offset, value, width, pfl->counter); + trace_pflash_data_write(offset, width << 1, value, pfl->counter); switch (width) { case 1: p[offset] = value; @@ -453,7 +452,7 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset, cmd = value; - trace_pflash_write(offset, value, width, pfl->wcycle); + trace_pflash_io_write(offset, width, width << 1, value, pfl->wcycle); if (!pfl->wcycle) { /* Set the device in I/O access mode */ memory_region_rom_device_set_romd(&pfl->mem, false); diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c index eb106f4996..5392290c72 100644 --- a/hw/block/pflash_cfi02.c +++ b/hw/block/pflash_cfi02.c @@ -29,10 +29,7 @@ * - CFI queries * * It does not support flash interleaving. - * It does not implement boot blocs with reduced size * It does not implement software data protection as found in many real chips - * It does not implement erase suspend/resume commands - * It does not implement multiple sectors erase */ #include "qemu/osdep.h" @@ -40,6 +37,7 @@ #include "hw/block/block.h" #include "hw/block/flash.h" #include "qapi/error.h" +#include "qemu/bitmap.h" #include "qemu/timer.h" #include "sysemu/block-backend.h" #include "qemu/host-utils.h" @@ -47,26 +45,40 @@ #include "hw/sysbus.h" #include "trace.h" -//#define PFLASH_DEBUG -#ifdef PFLASH_DEBUG +#define PFLASH_DEBUG false #define DPRINTF(fmt, ...) \ do { \ - fprintf(stderr, "PFLASH: " fmt , ## __VA_ARGS__); \ + if (PFLASH_DEBUG) { \ + fprintf(stderr, "PFLASH: " fmt, ## __VA_ARGS__); \ + } \ } while (0) -#else -#define DPRINTF(fmt, ...) do { } while (0) -#endif #define PFLASH_LAZY_ROMD_THRESHOLD 42 +/* + * The size of the cfi_table indirectly depends on this and the start of the + * PRI table directly depends on it. 4 is the maximum size (and also what + * seems common) without changing the PRT table address. + */ +#define PFLASH_MAX_ERASE_REGIONS 4 + +/* Special write cycles for CFI queries. */ +enum { + WCYCLE_CFI = 7, + WCYCLE_AUTOSELECT_CFI = 8, +}; + struct PFlashCFI02 { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ BlockBackend *blk; - uint32_t sector_len; - uint32_t nb_blocs; + uint32_t uniform_nb_blocs; + uint32_t uniform_sector_len; + uint32_t total_sectors; + uint32_t nb_blocs[PFLASH_MAX_ERASE_REGIONS]; + uint32_t sector_len[PFLASH_MAX_ERASE_REGIONS]; uint32_t chip_len; uint8_t mappings; uint8_t width; @@ -83,7 +95,7 @@ struct PFlashCFI02 { uint16_t ident3; uint16_t unlock_addr0; uint16_t unlock_addr1; - uint8_t cfi_table[0x52]; + uint8_t cfi_table[0x4d]; QEMUTimer timer; /* The device replicates the flash memory across its memory space. Emulate * that by having a container (.mem) filled with an array of aliases @@ -94,11 +106,63 @@ struct PFlashCFI02 { MemoryRegion orig_mem; int rom_mode; int read_counter; /* used for lazy switch-back to rom mode */ + int sectors_to_erase; + uint64_t erase_time_remaining; + unsigned long *sector_erase_map; char *name; void *storage; }; /* + * Toggle status bit DQ7. + */ +static inline void toggle_dq7(PFlashCFI02 *pfl) +{ + pfl->status ^= 0x80; +} + +/* + * Set status bit DQ7 to bit 7 of value. + */ +static inline void set_dq7(PFlashCFI02 *pfl, uint8_t value) +{ + pfl->status &= 0x7F; + pfl->status |= value & 0x80; +} + +/* + * Toggle status bit DQ6. + */ +static inline void toggle_dq6(PFlashCFI02 *pfl) +{ + pfl->status ^= 0x40; +} + +/* + * Turn on DQ3. + */ +static inline void assert_dq3(PFlashCFI02 *pfl) +{ + pfl->status |= 0x08; +} + +/* + * Turn off DQ3. + */ +static inline void reset_dq3(PFlashCFI02 *pfl) +{ + pfl->status &= ~0x08; +} + +/* + * Toggle status bit DQ2. + */ +static inline void toggle_dq2(PFlashCFI02 *pfl) +{ + pfl->status ^= 0x04; +} + +/* * Set up replicated mappings of the same region. */ static void pflash_setup_mappings(PFlashCFI02 *pfl) @@ -121,13 +185,63 @@ static void pflash_register_memory(PFlashCFI02 *pfl, int rom_mode) pfl->rom_mode = rom_mode; } -static void pflash_timer (void *opaque) +static size_t pflash_regions_count(PFlashCFI02 *pfl) +{ + return pfl->cfi_table[0x2c]; +} + +/* + * Returns the time it takes to erase the number of sectors scheduled for + * erasure based on CFI address 0x21 which is "Typical timeout per individual + * block erase 2^N ms." + */ +static uint64_t pflash_erase_time(PFlashCFI02 *pfl) +{ + /* + * If there are no sectors to erase (which can happen if all of the sectors + * to be erased are protected), then erase takes 100 us. Protected sectors + * aren't supported so this should never happen. + */ + return ((1ULL << pfl->cfi_table[0x21]) * pfl->sectors_to_erase) * SCALE_US; +} + +/* + * Returns true if the device is currently in erase suspend mode. + */ +static inline bool pflash_erase_suspend_mode(PFlashCFI02 *pfl) +{ + return pfl->erase_time_remaining > 0; +} + +static void pflash_timer(void *opaque) { PFlashCFI02 *pfl = opaque; trace_pflash_timer_expired(pfl->cmd); + if (pfl->cmd == 0x30) { + /* + * Sector erase. If DQ3 is 0 when the timer expires, then the 50 + * us erase timeout has expired so we need to start the timer for the + * sector erase algorithm. Otherwise, the erase completed and we should + * go back to read array mode. + */ + if ((pfl->status & 0x08) == 0) { + assert_dq3(pfl); + uint64_t timeout = pflash_erase_time(pfl); + timer_mod(&pfl->timer, + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + timeout); + DPRINTF("%s: erase timeout fired; erasing %d sectors\n", + __func__, pfl->sectors_to_erase); + return; + } + DPRINTF("%s: sector erase complete\n", __func__); + bitmap_zero(pfl->sector_erase_map, pfl->total_sectors); + pfl->sectors_to_erase = 0; + reset_dq3(pfl); + } + /* Reset flash */ - pfl->status ^= 0x80; + toggle_dq7(pfl); if (pfl->bypass) { pfl->wcycle = 2; } else { @@ -137,15 +251,63 @@ static void pflash_timer (void *opaque) pfl->cmd = 0; } -static uint32_t pflash_read(PFlashCFI02 *pfl, hwaddr offset, - int width, int be) +/* + * Read data from flash. + */ +static uint64_t pflash_data_read(PFlashCFI02 *pfl, hwaddr offset, + unsigned int width) +{ + uint8_t *p = (uint8_t *)pfl->storage + offset; + uint64_t ret = pfl->be ? ldn_be_p(p, width) : ldn_le_p(p, width); + trace_pflash_data_read(offset, width << 1, ret); + return ret; +} + +typedef struct { + uint32_t len; + uint32_t num; +} SectorInfo; + +/* + * offset should be a byte offset of the QEMU device and _not_ a device + * offset. + */ +static SectorInfo pflash_sector_info(PFlashCFI02 *pfl, hwaddr offset) { + assert(offset < pfl->chip_len); + hwaddr addr = 0; + uint32_t sector_num = 0; + for (int i = 0; i < pflash_regions_count(pfl); ++i) { + uint64_t region_size = (uint64_t)pfl->nb_blocs[i] * pfl->sector_len[i]; + if (addr <= offset && offset < addr + region_size) { + return (SectorInfo) { + .len = pfl->sector_len[i], + .num = sector_num + (offset - addr) / pfl->sector_len[i], + }; + } + sector_num += pfl->nb_blocs[i]; + addr += region_size; + } + abort(); +} + +/* + * Returns true if the offset refers to a flash sector that is currently being + * erased. + */ +static bool pflash_sector_is_erasing(PFlashCFI02 *pfl, hwaddr offset) +{ + long sector_num = pflash_sector_info(pfl, offset).num; + return test_bit(sector_num, pfl->sector_erase_map); +} + +static uint64_t pflash_read(void *opaque, hwaddr offset, unsigned int width) +{ + PFlashCFI02 *pfl = opaque; hwaddr boff; - uint32_t ret; - uint8_t *p; + uint64_t ret; ret = -1; - trace_pflash_read(offset, pfl->cmd, width, pfl->wcycle); /* Lazy reset to ROMD mode after a certain amount of read accesses */ if (!pfl->rom_mode && pfl->wcycle == 0 && ++pfl->read_counter > PFLASH_LAZY_ROMD_THRESHOLD) { @@ -153,10 +315,9 @@ static uint32_t pflash_read(PFlashCFI02 *pfl, hwaddr offset, } offset &= pfl->chip_len - 1; boff = offset & 0xFF; - if (pfl->width == 2) + if (pfl->width == 2) { boff = boff >> 1; - else if (pfl->width == 4) - boff = boff >> 2; + } switch (pfl->cmd) { default: /* This should never happen : reset state & treat it as a read*/ @@ -164,45 +325,22 @@ static uint32_t pflash_read(PFlashCFI02 *pfl, hwaddr offset, pfl->wcycle = 0; pfl->cmd = 0; /* fall through to the read code */ - case 0x80: + case 0x80: /* Erase (unlock) */ /* We accept reads during second unlock sequence... */ case 0x00: - flash_read: - /* Flash area read */ - p = pfl->storage; - switch (width) { - case 1: - ret = p[offset]; - trace_pflash_data_read8(offset, ret); - break; - case 2: - if (be) { - ret = p[offset] << 8; - ret |= p[offset + 1]; - } else { - ret = p[offset]; - ret |= p[offset + 1] << 8; - } - trace_pflash_data_read16(offset, ret); - break; - case 4: - if (be) { - ret = p[offset] << 24; - ret |= p[offset + 1] << 16; - ret |= p[offset + 2] << 8; - ret |= p[offset + 3]; - } else { - ret = p[offset]; - ret |= p[offset + 1] << 8; - ret |= p[offset + 2] << 16; - ret |= p[offset + 3] << 24; - } - trace_pflash_data_read32(offset, ret); + if (pflash_erase_suspend_mode(pfl) && + pflash_sector_is_erasing(pfl, offset)) { + /* Toggle bit 2, but not 6. */ + toggle_dq2(pfl); + /* Status register read */ + ret = pfl->status; + DPRINTF("%s: status %" PRIx64 "\n", __func__, ret); break; } + /* Flash area read */ + ret = pflash_data_read(pfl, offset, width); break; - case 0x90: - /* flash ID read */ + case 0x90: /* flash ID read */ switch (boff) { case 0x00: case 0x01: @@ -214,23 +352,25 @@ static uint32_t pflash_read(PFlashCFI02 *pfl, hwaddr offset, case 0x0E: case 0x0F: ret = boff & 0x01 ? pfl->ident3 : pfl->ident2; - if (ret == (uint8_t)-1) { - goto flash_read; + if (ret != (uint8_t)-1) { + break; } - break; + /* Fall through to data read. */ default: - goto flash_read; + ret = pflash_data_read(pfl, offset, width); } - DPRINTF("%s: ID " TARGET_FMT_plx " %x\n", __func__, boff, ret); + DPRINTF("%s: ID " TARGET_FMT_plx " %" PRIx64 "\n", __func__, boff, ret); break; - case 0xA0: - case 0x10: - case 0x30: + case 0x10: /* Chip Erase */ + case 0x30: /* Sector Erase */ + /* Toggle bit 2 during erase, but not program. */ + toggle_dq2(pfl); + case 0xA0: /* Program */ + /* Toggle bit 6 */ + toggle_dq6(pfl); /* Status register read */ ret = pfl->status; - DPRINTF("%s: status %x\n", __func__, ret); - /* Toggle bit 6 */ - pfl->status ^= 0x40; + DPRINTF("%s: status %" PRIx64 "\n", __func__, ret); break; case 0x98: /* CFI query mode */ @@ -241,13 +381,13 @@ static uint32_t pflash_read(PFlashCFI02 *pfl, hwaddr offset, } break; } + trace_pflash_io_read(offset, width, width << 1, ret, pfl->cmd, pfl->wcycle); return ret; } /* update flash content on disk */ -static void pflash_update(PFlashCFI02 *pfl, int offset, - int size) +static void pflash_update(PFlashCFI02 *pfl, int offset, int size) { int offset_end; if (pfl->blk) { @@ -260,31 +400,56 @@ static void pflash_update(PFlashCFI02 *pfl, int offset, } } -static void pflash_write(PFlashCFI02 *pfl, hwaddr offset, - uint32_t value, int width, int be) +static void pflash_sector_erase(PFlashCFI02 *pfl, hwaddr offset) { + SectorInfo sector_info = pflash_sector_info(pfl, offset); + uint64_t sector_len = sector_info.len; + offset &= ~(sector_len - 1); + DPRINTF("%s: start sector erase at %0*" PRIx64 "-%0*" PRIx64 "\n", + __func__, pfl->width * 2, offset, + pfl->width * 2, offset + sector_len - 1); + if (!pfl->ro) { + uint8_t *p = pfl->storage; + memset(p + offset, 0xff, sector_len); + pflash_update(pfl, offset, sector_len); + } + set_dq7(pfl, 0x00); + ++pfl->sectors_to_erase; + set_bit(sector_info.num, pfl->sector_erase_map); + /* Set (or reset) the 50 us timer for additional erase commands. */ + timer_mod(&pfl->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 50000); +} + +static void pflash_write(void *opaque, hwaddr offset, uint64_t value, + unsigned int width) +{ + PFlashCFI02 *pfl = opaque; hwaddr boff; uint8_t *p; uint8_t cmd; + trace_pflash_io_write(offset, width, width << 1, value, pfl->wcycle); cmd = value; - if (pfl->cmd != 0xA0 && cmd == 0xF0) { -#if 0 - DPRINTF("%s: flash reset asked (%02x %02x)\n", - __func__, pfl->cmd, cmd); -#endif - goto reset_flash; + if (pfl->cmd != 0xA0) { + /* Reset does nothing during chip erase and sector erase. */ + if (cmd == 0xF0 && pfl->cmd != 0x10 && pfl->cmd != 0x30) { + if (pfl->wcycle == WCYCLE_AUTOSELECT_CFI) { + /* Return to autoselect mode. */ + pfl->wcycle = 3; + pfl->cmd = 0x90; + return; + } + goto reset_flash; + } } - trace_pflash_write(offset, value, width, pfl->wcycle); offset &= pfl->chip_len - 1; - DPRINTF("%s: offset " TARGET_FMT_plx " %08x %d\n", __func__, - offset, value, width); - boff = offset & (pfl->sector_len - 1); - if (pfl->width == 2) + boff = offset; + if (pfl->width == 2) { boff = boff >> 1; - else if (pfl->width == 4) - boff = boff >> 2; + } + /* Only the least-significant 11 bits are used in most cases. */ + boff &= 0x7FF; switch (pfl->wcycle) { case 0: /* Set the device in I/O access mode if required */ @@ -294,12 +459,30 @@ static void pflash_write(PFlashCFI02 *pfl, hwaddr offset, /* We're in read mode */ check_unlock0: if (boff == 0x55 && cmd == 0x98) { - enter_CFI_mode: /* Enter CFI query mode */ - pfl->wcycle = 7; + pfl->wcycle = WCYCLE_CFI; pfl->cmd = 0x98; return; } + /* Handle erase resume in erase suspend mode, otherwise reset. */ + if (cmd == 0x30) { /* Erase Resume */ + if (pflash_erase_suspend_mode(pfl)) { + /* Resume the erase. */ + timer_mod(&pfl->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + + pfl->erase_time_remaining); + pfl->erase_time_remaining = 0; + pfl->wcycle = 6; + pfl->cmd = 0x30; + set_dq7(pfl, 0x00); + assert_dq3(pfl); + return; + } + goto reset_flash; + } + /* Ignore erase suspend. */ + if (cmd == 0xB0) { /* Erase Suspend */ + return; + } if (boff != pfl->unlock_addr0 || cmd != 0xAA) { DPRINTF("%s: unlock0 failed " TARGET_FMT_plx " %02x %04x\n", __func__, boff, cmd, pfl->unlock_addr0); @@ -328,9 +511,9 @@ static void pflash_write(PFlashCFI02 *pfl, hwaddr offset, case 0x20: pfl->bypass = 1; goto do_bypass; - case 0x80: - case 0x90: - case 0xA0: + case 0x80: /* Erase */ + case 0x90: /* Autoselect */ + case 0xA0: /* Program */ pfl->cmd = cmd; DPRINTF("%s: starting command %02x\n", __func__, cmd); break; @@ -341,57 +524,54 @@ static void pflash_write(PFlashCFI02 *pfl, hwaddr offset, break; case 3: switch (pfl->cmd) { - case 0x80: + case 0x80: /* Erase */ /* We need another unlock sequence */ goto check_unlock0; - case 0xA0: - trace_pflash_data_write(offset, value, width, 0); - p = pfl->storage; + case 0xA0: /* Program */ + if (pflash_erase_suspend_mode(pfl) && + pflash_sector_is_erasing(pfl, offset)) { + /* Ignore writes to erasing sectors. */ + if (pfl->bypass) { + goto do_bypass; + } + goto reset_flash; + } + trace_pflash_data_write(offset, width << 1, value, 0); if (!pfl->ro) { - switch (width) { - case 1: - p[offset] &= value; - pflash_update(pfl, offset, 1); - break; - case 2: - if (be) { - p[offset] &= value >> 8; - p[offset + 1] &= value; - } else { - p[offset] &= value; - p[offset + 1] &= value >> 8; - } - pflash_update(pfl, offset, 2); - break; - case 4: - if (be) { - p[offset] &= value >> 24; - p[offset + 1] &= value >> 16; - p[offset + 2] &= value >> 8; - p[offset + 3] &= value; - } else { - p[offset] &= value; - p[offset + 1] &= value >> 8; - p[offset + 2] &= value >> 16; - p[offset + 3] &= value >> 24; - } - pflash_update(pfl, offset, 4); - break; + p = (uint8_t *)pfl->storage + offset; + if (pfl->be) { + uint64_t current = ldn_be_p(p, width); + stn_be_p(p, width, current & value); + } else { + uint64_t current = ldn_le_p(p, width); + stn_le_p(p, width, current & value); } + pflash_update(pfl, offset, width); } - pfl->status = 0x00 | ~(value & 0x80); + /* + * While programming, status bit DQ7 should hold the opposite + * value from how it was programmed. + */ + set_dq7(pfl, ~value); /* Let's pretend write is immediate */ if (pfl->bypass) goto do_bypass; goto reset_flash; - case 0x90: + case 0x90: /* Autoselect */ if (pfl->bypass && cmd == 0x00) { /* Unlock bypass reset */ goto reset_flash; } - /* We can enter CFI query mode from autoselect mode */ - if (boff == 0x55 && cmd == 0x98) - goto enter_CFI_mode; + /* + * We can enter CFI query mode from autoselect mode, but we must + * return to autoselect mode after a reset. + */ + if (boff == 0x55 && cmd == 0x98) { + /* Enter autoselect CFI query mode */ + pfl->wcycle = WCYCLE_AUTOSELECT_CFI; + pfl->cmd = 0x98; + return; + } /* No break here */ default: DPRINTF("%s: invalid write for command %02x\n", @@ -400,11 +580,11 @@ static void pflash_write(PFlashCFI02 *pfl, hwaddr offset, } case 4: switch (pfl->cmd) { - case 0xA0: + case 0xA0: /* Program */ /* Ignore writes while flash data write is occurring */ /* As we suppose write is immediate, this should never happen */ return; - case 0x80: + case 0x80: /* Erase */ goto check_unlock1; default: /* Should never happen */ @@ -414,8 +594,12 @@ static void pflash_write(PFlashCFI02 *pfl, hwaddr offset, } break; case 5: + if (pflash_erase_suspend_mode(pfl)) { + /* Erasing is not supported in erase suspend mode. */ + goto reset_flash; + } switch (cmd) { - case 0x10: + case 0x10: /* Chip Erase */ if (boff != pfl->unlock_addr0) { DPRINTF("%s: chip erase: invalid address " TARGET_FMT_plx "\n", __func__, offset); @@ -424,28 +608,16 @@ static void pflash_write(PFlashCFI02 *pfl, hwaddr offset, /* Chip erase */ DPRINTF("%s: start chip erase\n", __func__); if (!pfl->ro) { - memset(pfl->storage, 0xFF, pfl->chip_len); + memset(pfl->storage, 0xff, pfl->chip_len); pflash_update(pfl, 0, pfl->chip_len); } - pfl->status = 0x00; - /* Let's wait 5 seconds before chip erase is done */ + set_dq7(pfl, 0x00); + /* Wait the time specified at CFI address 0x22. */ timer_mod(&pfl->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + - (NANOSECONDS_PER_SECOND * 5)); + (1ULL << pfl->cfi_table[0x22]) * SCALE_MS); break; - case 0x30: - /* Sector erase */ - p = pfl->storage; - offset &= ~(pfl->sector_len - 1); - DPRINTF("%s: start sector erase at " TARGET_FMT_plx "\n", __func__, - offset); - if (!pfl->ro) { - memset(p + offset, 0xFF, pfl->sector_len); - pflash_update(pfl, offset, pfl->sector_len); - } - pfl->status = 0x00; - /* Let's wait 1/2 second before sector erase is done */ - timer_mod(&pfl->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + - (NANOSECONDS_PER_SECOND / 2)); + case 0x30: /* Sector erase */ + pflash_sector_erase(pfl, offset); break; default: DPRINTF("%s: invalid command %02x (wc 5)\n", __func__, cmd); @@ -455,11 +627,47 @@ static void pflash_write(PFlashCFI02 *pfl, hwaddr offset, break; case 6: switch (pfl->cmd) { - case 0x10: + case 0x10: /* Chip Erase */ /* Ignore writes during chip erase */ return; - case 0x30: - /* Ignore writes during sector erase */ + case 0x30: /* Sector erase */ + if (cmd == 0xB0) { + /* + * If erase suspend happens during the erase timeout (so DQ3 is + * 0), then the device suspends erasing immediately. Set the + * remaining time to be the total time to erase. Otherwise, + * there is a maximum amount of time it can take to enter + * suspend mode. Let's ignore that and suspend immediately and + * set the remaining time to the actual time remaining on the + * timer. + */ + if ((pfl->status & 0x08) == 0) { + pfl->erase_time_remaining = pflash_erase_time(pfl); + } else { + int64_t delta = timer_expire_time_ns(&pfl->timer) - + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + /* Make sure we have a positive time remaining. */ + pfl->erase_time_remaining = delta <= 0 ? 1 : delta; + } + reset_dq3(pfl); + timer_del(&pfl->timer); + pfl->wcycle = 0; + pfl->cmd = 0; + return; + } + /* + * If DQ3 is 0, additional sector erase commands can be + * written and anything else (other than an erase suspend) resets + * the device. + */ + if ((pfl->status & 0x08) == 0) { + if (cmd == 0x30) { + pflash_sector_erase(pfl, offset); + } else { + goto reset_flash; + } + } + /* Ignore writes during the actual erase. */ return; default: /* Should never happen */ @@ -468,7 +676,9 @@ static void pflash_write(PFlashCFI02 *pfl, hwaddr offset, goto reset_flash; } break; - case 7: /* Special value for CFI queries */ + /* Special values for CFI queries */ + case WCYCLE_CFI: + case WCYCLE_AUTOSELECT_CFI: DPRINTF("%s: invalid write in CFI query mode\n", __func__); goto reset_flash; default: @@ -493,39 +703,10 @@ static void pflash_write(PFlashCFI02 *pfl, hwaddr offset, pfl->cmd = 0; } -static uint64_t pflash_be_readfn(void *opaque, hwaddr addr, unsigned size) -{ - return pflash_read(opaque, addr, size, 1); -} - -static void pflash_be_writefn(void *opaque, hwaddr addr, - uint64_t value, unsigned size) -{ - pflash_write(opaque, addr, value, size, 1); -} - -static uint64_t pflash_le_readfn(void *opaque, hwaddr addr, unsigned size) -{ - return pflash_read(opaque, addr, size, 0); -} - -static void pflash_le_writefn(void *opaque, hwaddr addr, - uint64_t value, unsigned size) -{ - pflash_write(opaque, addr, value, size, 0); -} - -static const MemoryRegionOps pflash_cfi02_ops_be = { - .read = pflash_be_readfn, - .write = pflash_be_writefn, - .valid.min_access_size = 1, - .valid.max_access_size = 4, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static const MemoryRegionOps pflash_cfi02_ops_le = { - .read = pflash_le_readfn, - .write = pflash_le_writefn, +static const MemoryRegionOps pflash_cfi02_ops = { + .read = pflash_read, + .write = pflash_write, + .impl.max_access_size = 2, .valid.min_access_size = 1, .valid.max_access_size = 4, .endianness = DEVICE_NATIVE_ENDIAN, @@ -534,15 +715,14 @@ static const MemoryRegionOps pflash_cfi02_ops_le = { static void pflash_cfi02_realize(DeviceState *dev, Error **errp) { PFlashCFI02 *pfl = PFLASH_CFI02(dev); - uint32_t chip_len; int ret; Error *local_err = NULL; - if (pfl->sector_len == 0) { + if (pfl->uniform_sector_len == 0 && pfl->sector_len[0] == 0) { error_setg(errp, "attribute \"sector-length\" not specified or zero."); return; } - if (pfl->nb_blocs == 0) { + if (pfl->uniform_nb_blocs == 0 && pfl->nb_blocs[0] == 0) { error_setg(errp, "attribute \"num-blocks\" not specified or zero."); return; } @@ -551,18 +731,64 @@ static void pflash_cfi02_realize(DeviceState *dev, Error **errp) return; } - chip_len = pfl->sector_len * pfl->nb_blocs; + int nb_regions; + pfl->chip_len = 0; + pfl->total_sectors = 0; + for (nb_regions = 0; nb_regions < PFLASH_MAX_ERASE_REGIONS; ++nb_regions) { + if (pfl->nb_blocs[nb_regions] == 0) { + break; + } + pfl->total_sectors += pfl->nb_blocs[nb_regions]; + uint64_t sector_len_per_device = pfl->sector_len[nb_regions]; + + /* + * The size of each flash sector must be a power of 2 and it must be + * aligned at the same power of 2. + */ + if (sector_len_per_device & 0xff || + sector_len_per_device >= (1 << 24) || + !is_power_of_2(sector_len_per_device)) + { + error_setg(errp, "unsupported configuration: " + "sector length[%d] per device = %" PRIx64 ".", + nb_regions, sector_len_per_device); + return; + } + if (pfl->chip_len & (sector_len_per_device - 1)) { + error_setg(errp, "unsupported configuration: " + "flash region %d not correctly aligned.", + nb_regions); + return; + } + + pfl->chip_len += (uint64_t)pfl->sector_len[nb_regions] * + pfl->nb_blocs[nb_regions]; + } + + uint64_t uniform_len = (uint64_t)pfl->uniform_nb_blocs * + pfl->uniform_sector_len; + if (nb_regions == 0) { + nb_regions = 1; + pfl->nb_blocs[0] = pfl->uniform_nb_blocs; + pfl->sector_len[0] = pfl->uniform_sector_len; + pfl->chip_len = uniform_len; + pfl->total_sectors = pfl->uniform_nb_blocs; + } else if (uniform_len != 0 && uniform_len != pfl->chip_len) { + error_setg(errp, "\"num-blocks\"*\"sector-length\" " + "different from \"num-blocks0\"*\'sector-length0\" + ... + " + "\"num-blocks3\"*\"sector-length3\""); + return; + } - memory_region_init_rom_device(&pfl->orig_mem, OBJECT(pfl), pfl->be ? - &pflash_cfi02_ops_be : &pflash_cfi02_ops_le, - pfl, pfl->name, chip_len, &local_err); + memory_region_init_rom_device(&pfl->orig_mem, OBJECT(pfl), + &pflash_cfi02_ops, pfl, pfl->name, + pfl->chip_len, &local_err); if (local_err) { error_propagate(errp, local_err); return; } pfl->storage = memory_region_get_ram_ptr(&pfl->orig_mem); - pfl->chip_len = chip_len; if (pfl->blk) { uint64_t perm; @@ -577,13 +803,20 @@ static void pflash_cfi02_realize(DeviceState *dev, Error **errp) } if (pfl->blk) { - if (!blk_check_size_and_read_all(pfl->blk, pfl->storage, chip_len, - errp)) { + if (!blk_check_size_and_read_all(pfl->blk, pfl->storage, + pfl->chip_len, errp)) { vmstate_unregister_ram(&pfl->orig_mem, DEVICE(pfl)); return; } } + /* Only 11 bits are used in the comparison. */ + pfl->unlock_addr0 &= 0x7FF; + pfl->unlock_addr1 &= 0x7FF; + + /* Allocate memory for a bitmap for sectors being erased. */ + pfl->sector_erase_map = bitmap_new(pfl->total_sectors); + pflash_setup_mappings(pfl); pfl->rom_mode = 1; sysbus_init_mmio(SYS_BUS_DEVICE(dev), &pfl->mem); @@ -592,7 +825,9 @@ static void pflash_cfi02_realize(DeviceState *dev, Error **errp) pfl->wcycle = 0; pfl->cmd = 0; pfl->status = 0; + /* Hardcoded CFI table (mostly from SG29 Spansion flash) */ + const uint16_t pri_ofs = 0x40; /* Standard "QRY" string */ pfl->cfi_table[0x10] = 'Q'; pfl->cfi_table[0x11] = 'R'; @@ -601,8 +836,8 @@ static void pflash_cfi02_realize(DeviceState *dev, Error **errp) pfl->cfi_table[0x13] = 0x02; pfl->cfi_table[0x14] = 0x00; /* Primary extended table address */ - pfl->cfi_table[0x15] = 0x31; - pfl->cfi_table[0x16] = 0x00; + pfl->cfi_table[0x15] = pri_ofs; + pfl->cfi_table[0x16] = pri_ofs >> 8; /* Alternate command set (none) */ pfl->cfi_table[0x17] = 0x00; pfl->cfi_table[0x18] = 0x00; @@ -617,7 +852,7 @@ static void pflash_cfi02_realize(DeviceState *dev, Error **errp) pfl->cfi_table[0x1D] = 0x00; /* Vpp max (no Vpp pin) */ pfl->cfi_table[0x1E] = 0x00; - /* Reserved */ + /* Timeout per single byte/word write (128 ms) */ pfl->cfi_table[0x1F] = 0x07; /* Timeout for min size buffer write (NA) */ pfl->cfi_table[0x20] = 0x00; @@ -634,7 +869,7 @@ static void pflash_cfi02_realize(DeviceState *dev, Error **errp) /* Max timeout for chip erase */ pfl->cfi_table[0x26] = 0x0D; /* Device size */ - pfl->cfi_table[0x27] = ctz32(chip_len); + pfl->cfi_table[0x27] = ctz32(pfl->chip_len); /* Flash device interface (8 & 16 bits) */ pfl->cfi_table[0x28] = 0x02; pfl->cfi_table[0x29] = 0x00; @@ -643,37 +878,60 @@ static void pflash_cfi02_realize(DeviceState *dev, Error **errp) // pfl->cfi_table[0x2A] = 0x05; pfl->cfi_table[0x2A] = 0x00; pfl->cfi_table[0x2B] = 0x00; - /* Number of erase block regions (uniform) */ - pfl->cfi_table[0x2C] = 0x01; - /* Erase block region 1 */ - pfl->cfi_table[0x2D] = pfl->nb_blocs - 1; - pfl->cfi_table[0x2E] = (pfl->nb_blocs - 1) >> 8; - pfl->cfi_table[0x2F] = pfl->sector_len >> 8; - pfl->cfi_table[0x30] = pfl->sector_len >> 16; + /* Number of erase block regions */ + pfl->cfi_table[0x2c] = nb_regions; + /* Erase block regions */ + for (int i = 0; i < nb_regions; ++i) { + uint32_t sector_len_per_device = pfl->sector_len[i]; + pfl->cfi_table[0x2d + 4 * i] = pfl->nb_blocs[i] - 1; + pfl->cfi_table[0x2e + 4 * i] = (pfl->nb_blocs[i] - 1) >> 8; + pfl->cfi_table[0x2f + 4 * i] = sector_len_per_device >> 8; + pfl->cfi_table[0x30 + 4 * i] = sector_len_per_device >> 16; + } + assert(0x2c + 4 * nb_regions < pri_ofs); /* Extended */ - pfl->cfi_table[0x31] = 'P'; - pfl->cfi_table[0x32] = 'R'; - pfl->cfi_table[0x33] = 'I'; - - pfl->cfi_table[0x34] = '1'; - pfl->cfi_table[0x35] = '0'; - - pfl->cfi_table[0x36] = 0x00; - pfl->cfi_table[0x37] = 0x00; - pfl->cfi_table[0x38] = 0x00; - pfl->cfi_table[0x39] = 0x00; - - pfl->cfi_table[0x3a] = 0x00; - - pfl->cfi_table[0x3b] = 0x00; - pfl->cfi_table[0x3c] = 0x00; + pfl->cfi_table[0x00 + pri_ofs] = 'P'; + pfl->cfi_table[0x01 + pri_ofs] = 'R'; + pfl->cfi_table[0x02 + pri_ofs] = 'I'; + + /* Extended version 1.0 */ + pfl->cfi_table[0x03 + pri_ofs] = '1'; + pfl->cfi_table[0x04 + pri_ofs] = '0'; + + /* Address sensitive unlock required. */ + pfl->cfi_table[0x05 + pri_ofs] = 0x00; + /* Erase suspend to read/write. */ + pfl->cfi_table[0x06 + pri_ofs] = 0x02; + /* Sector protect not supported. */ + pfl->cfi_table[0x07 + pri_ofs] = 0x00; + /* Temporary sector unprotect not supported. */ + pfl->cfi_table[0x08 + pri_ofs] = 0x00; + + /* Sector protect/unprotect scheme. */ + pfl->cfi_table[0x09 + pri_ofs] = 0x00; + + /* Simultaneous operation not supported. */ + pfl->cfi_table[0x0a + pri_ofs] = 0x00; + /* Burst mode not supported. */ + pfl->cfi_table[0x0b + pri_ofs] = 0x00; + /* Page mode not supported. */ + pfl->cfi_table[0x0c + pri_ofs] = 0x00; + assert(0x0c + pri_ofs < ARRAY_SIZE(pfl->cfi_table)); } static Property pflash_cfi02_properties[] = { DEFINE_PROP_DRIVE("drive", PFlashCFI02, blk), - DEFINE_PROP_UINT32("num-blocks", PFlashCFI02, nb_blocs, 0), - DEFINE_PROP_UINT32("sector-length", PFlashCFI02, sector_len, 0), + DEFINE_PROP_UINT32("num-blocks", PFlashCFI02, uniform_nb_blocs, 0), + DEFINE_PROP_UINT32("sector-length", PFlashCFI02, uniform_sector_len, 0), + DEFINE_PROP_UINT32("num-blocks0", PFlashCFI02, nb_blocs[0], 0), + DEFINE_PROP_UINT32("sector-length0", PFlashCFI02, sector_len[0], 0), + DEFINE_PROP_UINT32("num-blocks1", PFlashCFI02, nb_blocs[1], 0), + DEFINE_PROP_UINT32("sector-length1", PFlashCFI02, sector_len[1], 0), + DEFINE_PROP_UINT32("num-blocks2", PFlashCFI02, nb_blocs[2], 0), + DEFINE_PROP_UINT32("sector-length2", PFlashCFI02, sector_len[2], 0), + DEFINE_PROP_UINT32("num-blocks3", PFlashCFI02, nb_blocs[3], 0), + DEFINE_PROP_UINT32("sector-length3", PFlashCFI02, sector_len[3], 0), DEFINE_PROP_UINT8("width", PFlashCFI02, width, 0), DEFINE_PROP_UINT8("mappings", PFlashCFI02, mappings, 0), DEFINE_PROP_UINT8("big-endian", PFlashCFI02, be, 0), @@ -691,6 +949,7 @@ static void pflash_cfi02_unrealize(DeviceState *dev, Error **errp) { PFlashCFI02 *pfl = PFLASH_CFI02(dev); timer_del(&pfl->timer); + g_free(pfl->sector_erase_map); } static void pflash_cfi02_class_init(ObjectClass *klass, void *data) diff --git a/hw/block/trace-events b/hw/block/trace-events index 97a17838ed..13d1b21dd4 100644 --- a/hw/block/trace-events +++ b/hw/block/trace-events @@ -7,13 +7,11 @@ fdc_ioport_write(uint8_t reg, uint8_t value) "write reg 0x%02x val 0x%02x" # pflash_cfi02.c # pflash_cfi01.c pflash_reset(void) "reset" -pflash_read(uint64_t offset, uint8_t cmd, int width, uint8_t wcycle) "offset:0x%04"PRIx64" cmd:0x%02x width:%d wcycle:%u" -pflash_write(uint64_t offset, uint32_t value, int width, uint8_t wcycle) "offset:0x%04"PRIx64" value:0x%03x width:%d wcycle:%u" pflash_timer_expired(uint8_t cmd) "command 0x%02x done" -pflash_data_read8(uint64_t offset, uint32_t value) "data offset:0x%04"PRIx64" value:0x%02x" -pflash_data_read16(uint64_t offset, uint32_t value) "data offset:0x%04"PRIx64" value:0x%04x" -pflash_data_read32(uint64_t offset, uint32_t value) "data offset:0x%04"PRIx64" value:0x%08x" -pflash_data_write(uint64_t offset, uint32_t value, int width, uint64_t counter) "data offset:0x%04"PRIx64" value:0x%08x width:%d counter:0x%016"PRIx64 +pflash_io_read(uint64_t offset, int width, int fmt_width, uint32_t value, uint8_t cmd, uint8_t wcycle) "offset:0x%04"PRIx64" width:%d value:0x%0*x cmd:0x%02x wcycle:%u" +pflash_io_write(uint64_t offset, int width, int fmt_width, uint32_t value, uint8_t wcycle) "offset:0x%04"PRIx64" width:%d value:0x%0*x wcycle:%u" +pflash_data_read(uint64_t offset, int width, uint32_t value) "data offset:0x%04"PRIx64" value:0x%0*x" +pflash_data_write(uint64_t offset, int width, uint32_t value, uint64_t counter) "data offset:0x%04"PRIx64" value:0x%0*x counter:0x%016"PRIx64 pflash_manufacturer_id(uint16_t id) "Read Manufacturer ID: 0x%04x" pflash_device_id(uint16_t id) "Read Device ID: 0x%04x" pflash_device_info(uint64_t offset) "Read Device Information offset:0x%04"PRIx64 diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c index 8f224ef81d..69d73196e2 100644 --- a/hw/block/xen-block.c +++ b/hw/block/xen-block.c @@ -11,7 +11,7 @@ #include "qemu/option.h" #include "qapi/error.h" #include "qapi/qapi-commands-block-core.h" -#include "qapi/qapi-commands-misc.h" +#include "qapi/qapi-commands-qom.h" #include "qapi/qapi-visit-block-core.h" #include "qapi/qobject-input-visitor.h" #include "qapi/visitor.h" diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs index a799c83815..585b734358 100644 --- a/hw/core/Makefile.objs +++ b/hw/core/Makefile.objs @@ -22,3 +22,7 @@ common-obj-$(CONFIG_SOFTMMU) += split-irq.o common-obj-$(CONFIG_PLATFORM_BUS) += platform-bus.o common-obj-$(CONFIG_SOFTMMU) += generic-loader.o common-obj-$(CONFIG_SOFTMMU) += null-machine.o + +obj-$(CONFIG_SOFTMMU) += machine-qmp-cmds.o +obj-$(CONFIG_SOFTMMU) += numa.o +common-obj-$(CONFIG_SOFTMMU) += machine-hmp-cmds.o diff --git a/hw/core/machine-hmp-cmds.c b/hw/core/machine-hmp-cmds.c new file mode 100644 index 0000000000..7fa6075f1e --- /dev/null +++ b/hw/core/machine-hmp-cmds.c @@ -0,0 +1,164 @@ +/* + * HMP commands related to machines and CPUs + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + * Contributions after 2012-01-13 are licensed under the terms of the + * GNU GPL, version 2 or (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "monitor/hmp.h" +#include "monitor/monitor.h" +#include "qapi/error.h" +#include "qapi/qapi-builtin-visit.h" +#include "qapi/qapi-commands-machine.h" +#include "qapi/qmp/qdict.h" +#include "qapi/string-output-visitor.h" +#include "qemu/error-report.h" +#include "sysemu/numa.h" + +void hmp_info_cpus(Monitor *mon, const QDict *qdict) +{ + CpuInfoFastList *cpu_list, *cpu; + + cpu_list = qmp_query_cpus_fast(NULL); + + for (cpu = cpu_list; cpu; cpu = cpu->next) { + int active = ' '; + + if (cpu->value->cpu_index == monitor_get_cpu_index()) { + active = '*'; + } + + monitor_printf(mon, "%c CPU #%" PRId64 ":", active, + cpu->value->cpu_index); + monitor_printf(mon, " thread_id=%" PRId64 "\n", cpu->value->thread_id); + } + + qapi_free_CpuInfoFastList(cpu_list); +} + +void hmp_cpu_add(Monitor *mon, const QDict *qdict) +{ + int cpuid; + Error *err = NULL; + + error_report("cpu_add is deprecated, please use device_add instead"); + + cpuid = qdict_get_int(qdict, "id"); + qmp_cpu_add(cpuid, &err); + hmp_handle_error(mon, &err); +} + +void hmp_hotpluggable_cpus(Monitor *mon, const QDict *qdict) +{ + Error *err = NULL; + HotpluggableCPUList *l = qmp_query_hotpluggable_cpus(&err); + HotpluggableCPUList *saved = l; + CpuInstanceProperties *c; + + if (err != NULL) { + hmp_handle_error(mon, &err); + return; + } + + monitor_printf(mon, "Hotpluggable CPUs:\n"); + while (l) { + monitor_printf(mon, " type: \"%s\"\n", l->value->type); + monitor_printf(mon, " vcpus_count: \"%" PRIu64 "\"\n", + l->value->vcpus_count); + if (l->value->has_qom_path) { + monitor_printf(mon, " qom_path: \"%s\"\n", l->value->qom_path); + } + + c = l->value->props; + monitor_printf(mon, " CPUInstance Properties:\n"); + if (c->has_node_id) { + monitor_printf(mon, " node-id: \"%" PRIu64 "\"\n", c->node_id); + } + if (c->has_socket_id) { + monitor_printf(mon, " socket-id: \"%" PRIu64 "\"\n", c->socket_id); + } + if (c->has_core_id) { + monitor_printf(mon, " core-id: \"%" PRIu64 "\"\n", c->core_id); + } + if (c->has_thread_id) { + monitor_printf(mon, " thread-id: \"%" PRIu64 "\"\n", c->thread_id); + } + + l = l->next; + } + + qapi_free_HotpluggableCPUList(saved); +} + +void hmp_info_memdev(Monitor *mon, const QDict *qdict) +{ + Error *err = NULL; + MemdevList *memdev_list = qmp_query_memdev(&err); + MemdevList *m = memdev_list; + Visitor *v; + char *str; + + while (m) { + v = string_output_visitor_new(false, &str); + visit_type_uint16List(v, NULL, &m->value->host_nodes, NULL); + monitor_printf(mon, "memory backend: %s\n", m->value->id); + monitor_printf(mon, " size: %" PRId64 "\n", m->value->size); + monitor_printf(mon, " merge: %s\n", + m->value->merge ? "true" : "false"); + monitor_printf(mon, " dump: %s\n", + m->value->dump ? "true" : "false"); + monitor_printf(mon, " prealloc: %s\n", + m->value->prealloc ? "true" : "false"); + monitor_printf(mon, " policy: %s\n", + HostMemPolicy_str(m->value->policy)); + visit_complete(v, &str); + monitor_printf(mon, " host nodes: %s\n", str); + + g_free(str); + visit_free(v); + m = m->next; + } + + monitor_printf(mon, "\n"); + + qapi_free_MemdevList(memdev_list); + hmp_handle_error(mon, &err); +} + +void hmp_info_numa(Monitor *mon, const QDict *qdict) +{ + int i; + NumaNodeMem *node_mem; + CpuInfoList *cpu_list, *cpu; + + cpu_list = qmp_query_cpus(&error_abort); + node_mem = g_new0(NumaNodeMem, nb_numa_nodes); + + query_numa_node_mem(node_mem); + monitor_printf(mon, "%d nodes\n", nb_numa_nodes); + for (i = 0; i < nb_numa_nodes; i++) { + monitor_printf(mon, "node %d cpus:", i); + for (cpu = cpu_list; cpu; cpu = cpu->next) { + if (cpu->value->has_props && cpu->value->props->has_node_id && + cpu->value->props->node_id == i) { + monitor_printf(mon, " %" PRIi64, cpu->value->CPU); + } + } + monitor_printf(mon, "\n"); + monitor_printf(mon, "node %d size: %" PRId64 " MB\n", i, + node_mem[i].node_mem >> 20); + monitor_printf(mon, "node %d plugged: %" PRId64 " MB\n", i, + node_mem[i].node_plugged_mem >> 20); + } + qapi_free_CpuInfoList(cpu_list); + g_free(node_mem); +} diff --git a/hw/core/machine-qmp-cmds.c b/hw/core/machine-qmp-cmds.c new file mode 100644 index 0000000000..1e08252af7 --- /dev/null +++ b/hw/core/machine-qmp-cmds.c @@ -0,0 +1,328 @@ +/* + * QMP commands related to machines and CPUs + * + * Copyright (C) 2014 Red Hat Inc + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "hw/boards.h" +#include "qapi/error.h" +#include "qapi/qapi-commands-machine.h" +#include "qapi/qmp/qerror.h" +#include "sysemu/hostmem.h" +#include "sysemu/hw_accel.h" +#include "sysemu/numa.h" +#include "sysemu/sysemu.h" + +CpuInfoList *qmp_query_cpus(Error **errp) +{ + MachineState *ms = MACHINE(qdev_get_machine()); + MachineClass *mc = MACHINE_GET_CLASS(ms); + CpuInfoList *head = NULL, *cur_item = NULL; + CPUState *cpu; + + CPU_FOREACH(cpu) { + CpuInfoList *info; +#if defined(TARGET_I386) + X86CPU *x86_cpu = X86_CPU(cpu); + CPUX86State *env = &x86_cpu->env; +#elif defined(TARGET_PPC) + PowerPCCPU *ppc_cpu = POWERPC_CPU(cpu); + CPUPPCState *env = &ppc_cpu->env; +#elif defined(TARGET_SPARC) + SPARCCPU *sparc_cpu = SPARC_CPU(cpu); + CPUSPARCState *env = &sparc_cpu->env; +#elif defined(TARGET_RISCV) + RISCVCPU *riscv_cpu = RISCV_CPU(cpu); + CPURISCVState *env = &riscv_cpu->env; +#elif defined(TARGET_MIPS) + MIPSCPU *mips_cpu = MIPS_CPU(cpu); + CPUMIPSState *env = &mips_cpu->env; +#elif defined(TARGET_TRICORE) + TriCoreCPU *tricore_cpu = TRICORE_CPU(cpu); + CPUTriCoreState *env = &tricore_cpu->env; +#elif defined(TARGET_S390X) + S390CPU *s390_cpu = S390_CPU(cpu); + CPUS390XState *env = &s390_cpu->env; +#endif + + cpu_synchronize_state(cpu); + + info = g_malloc0(sizeof(*info)); + info->value = g_malloc0(sizeof(*info->value)); + info->value->CPU = cpu->cpu_index; + info->value->current = (cpu == first_cpu); + info->value->halted = cpu->halted; + info->value->qom_path = object_get_canonical_path(OBJECT(cpu)); + info->value->thread_id = cpu->thread_id; +#if defined(TARGET_I386) + info->value->arch = CPU_INFO_ARCH_X86; + info->value->u.x86.pc = env->eip + env->segs[R_CS].base; +#elif defined(TARGET_PPC) + info->value->arch = CPU_INFO_ARCH_PPC; + info->value->u.ppc.nip = env->nip; +#elif defined(TARGET_SPARC) + info->value->arch = CPU_INFO_ARCH_SPARC; + info->value->u.q_sparc.pc = env->pc; + info->value->u.q_sparc.npc = env->npc; +#elif defined(TARGET_MIPS) + info->value->arch = CPU_INFO_ARCH_MIPS; + info->value->u.q_mips.PC = env->active_tc.PC; +#elif defined(TARGET_TRICORE) + info->value->arch = CPU_INFO_ARCH_TRICORE; + info->value->u.tricore.PC = env->PC; +#elif defined(TARGET_S390X) + info->value->arch = CPU_INFO_ARCH_S390; + info->value->u.s390.cpu_state = env->cpu_state; +#elif defined(TARGET_RISCV) + info->value->arch = CPU_INFO_ARCH_RISCV; + info->value->u.riscv.pc = env->pc; +#else + info->value->arch = CPU_INFO_ARCH_OTHER; +#endif + info->value->has_props = !!mc->cpu_index_to_instance_props; + if (info->value->has_props) { + CpuInstanceProperties *props; + props = g_malloc0(sizeof(*props)); + *props = mc->cpu_index_to_instance_props(ms, cpu->cpu_index); + info->value->props = props; + } + + /* XXX: waiting for the qapi to support GSList */ + if (!cur_item) { + head = cur_item = info; + } else { + cur_item->next = info; + cur_item = info; + } + } + + return head; +} + +static CpuInfoArch sysemu_target_to_cpuinfo_arch(SysEmuTarget target) +{ + /* + * The @SysEmuTarget -> @CpuInfoArch mapping below is based on the + * TARGET_ARCH -> TARGET_BASE_ARCH mapping in the "configure" script. + */ + switch (target) { + case SYS_EMU_TARGET_I386: + case SYS_EMU_TARGET_X86_64: + return CPU_INFO_ARCH_X86; + + case SYS_EMU_TARGET_PPC: + case SYS_EMU_TARGET_PPC64: + return CPU_INFO_ARCH_PPC; + + case SYS_EMU_TARGET_SPARC: + case SYS_EMU_TARGET_SPARC64: + return CPU_INFO_ARCH_SPARC; + + case SYS_EMU_TARGET_MIPS: + case SYS_EMU_TARGET_MIPSEL: + case SYS_EMU_TARGET_MIPS64: + case SYS_EMU_TARGET_MIPS64EL: + return CPU_INFO_ARCH_MIPS; + + case SYS_EMU_TARGET_TRICORE: + return CPU_INFO_ARCH_TRICORE; + + case SYS_EMU_TARGET_S390X: + return CPU_INFO_ARCH_S390; + + case SYS_EMU_TARGET_RISCV32: + case SYS_EMU_TARGET_RISCV64: + return CPU_INFO_ARCH_RISCV; + + default: + return CPU_INFO_ARCH_OTHER; + } +} + +static void cpustate_to_cpuinfo_s390(CpuInfoS390 *info, const CPUState *cpu) +{ +#ifdef TARGET_S390X + S390CPU *s390_cpu = S390_CPU(cpu); + CPUS390XState *env = &s390_cpu->env; + + info->cpu_state = env->cpu_state; +#else + abort(); +#endif +} + +/* + * fast means: we NEVER interrupt vCPU threads to retrieve + * information from KVM. + */ +CpuInfoFastList *qmp_query_cpus_fast(Error **errp) +{ + MachineState *ms = MACHINE(qdev_get_machine()); + MachineClass *mc = MACHINE_GET_CLASS(ms); + CpuInfoFastList *head = NULL, *cur_item = NULL; + SysEmuTarget target = qapi_enum_parse(&SysEmuTarget_lookup, TARGET_NAME, + -1, &error_abort); + CPUState *cpu; + + CPU_FOREACH(cpu) { + CpuInfoFastList *info = g_malloc0(sizeof(*info)); + info->value = g_malloc0(sizeof(*info->value)); + + info->value->cpu_index = cpu->cpu_index; + info->value->qom_path = object_get_canonical_path(OBJECT(cpu)); + info->value->thread_id = cpu->thread_id; + + info->value->has_props = !!mc->cpu_index_to_instance_props; + if (info->value->has_props) { + CpuInstanceProperties *props; + props = g_malloc0(sizeof(*props)); + *props = mc->cpu_index_to_instance_props(ms, cpu->cpu_index); + info->value->props = props; + } + + info->value->arch = sysemu_target_to_cpuinfo_arch(target); + info->value->target = target; + if (target == SYS_EMU_TARGET_S390X) { + cpustate_to_cpuinfo_s390(&info->value->u.s390x, cpu); + } + + if (!cur_item) { + head = cur_item = info; + } else { + cur_item->next = info; + cur_item = info; + } + } + + return head; +} + +MachineInfoList *qmp_query_machines(Error **errp) +{ + GSList *el, *machines = object_class_get_list(TYPE_MACHINE, false); + MachineInfoList *mach_list = NULL; + + for (el = machines; el; el = el->next) { + MachineClass *mc = el->data; + MachineInfoList *entry; + MachineInfo *info; + + info = g_malloc0(sizeof(*info)); + if (mc->is_default) { + info->has_is_default = true; + info->is_default = true; + } + + if (mc->alias) { + info->has_alias = true; + info->alias = g_strdup(mc->alias); + } + + info->name = g_strdup(mc->name); + info->cpu_max = !mc->max_cpus ? 1 : mc->max_cpus; + info->hotpluggable_cpus = mc->has_hotpluggable_cpus; + + entry = g_malloc0(sizeof(*entry)); + entry->value = info; + entry->next = mach_list; + mach_list = entry; + } + + g_slist_free(machines); + return mach_list; +} + +CurrentMachineParams *qmp_query_current_machine(Error **errp) +{ + CurrentMachineParams *params = g_malloc0(sizeof(*params)); + params->wakeup_suspend_support = qemu_wakeup_suspend_enabled(); + + return params; +} + +HotpluggableCPUList *qmp_query_hotpluggable_cpus(Error **errp) +{ + MachineState *ms = MACHINE(qdev_get_machine()); + MachineClass *mc = MACHINE_GET_CLASS(ms); + + if (!mc->has_hotpluggable_cpus) { + error_setg(errp, QERR_FEATURE_DISABLED, "query-hotpluggable-cpus"); + return NULL; + } + + return machine_query_hotpluggable_cpus(ms); +} + +void qmp_cpu_add(int64_t id, Error **errp) +{ + MachineClass *mc; + + mc = MACHINE_GET_CLASS(current_machine); + if (mc->hot_add_cpu) { + mc->hot_add_cpu(id, errp); + } else { + error_setg(errp, "Not supported"); + } +} + +void qmp_set_numa_node(NumaOptions *cmd, Error **errp) +{ + if (!runstate_check(RUN_STATE_PRECONFIG)) { + error_setg(errp, "The command is permitted only in '%s' state", + RunState_str(RUN_STATE_PRECONFIG)); + return; + } + + set_numa_options(MACHINE(qdev_get_machine()), cmd, errp); +} + +static int query_memdev(Object *obj, void *opaque) +{ + MemdevList **list = opaque; + MemdevList *m = NULL; + + if (object_dynamic_cast(obj, TYPE_MEMORY_BACKEND)) { + m = g_malloc0(sizeof(*m)); + + m->value = g_malloc0(sizeof(*m->value)); + + m->value->id = object_get_canonical_path_component(obj); + m->value->has_id = !!m->value->id; + + m->value->size = object_property_get_uint(obj, "size", + &error_abort); + m->value->merge = object_property_get_bool(obj, "merge", + &error_abort); + m->value->dump = object_property_get_bool(obj, "dump", + &error_abort); + m->value->prealloc = object_property_get_bool(obj, + "prealloc", + &error_abort); + m->value->policy = object_property_get_enum(obj, + "policy", + "HostMemPolicy", + &error_abort); + object_property_get_uint16List(obj, "host-nodes", + &m->value->host_nodes, + &error_abort); + + m->next = *list; + *list = m; + } + + return 0; +} + +MemdevList *qmp_query_memdev(Error **errp) +{ + Object *obj = object_get_objects_root(); + MemdevList *list = NULL; + + object_child_foreach(obj, query_memdev, &list); + return list; +} diff --git a/numa.c b/hw/core/numa.c index 955ec0c830..76c447f90a 100644 --- a/numa.c +++ b/hw/core/numa.c @@ -27,14 +27,10 @@ #include "exec/cpu-common.h" #include "exec/ramlist.h" #include "qemu/bitmap.h" -#include "qom/cpu.h" #include "qemu/error-report.h" #include "qapi/error.h" #include "qapi/opts-visitor.h" -#include "qapi/qapi-commands-misc.h" -#include "qapi/qapi-visit-misc.h" -#include "hw/boards.h" -#include "sysemu/hostmem.h" +#include "qapi/qapi-visit-machine.h" #include "hw/mem/pc-dimm.h" #include "hw/mem/memory-device.h" #include "qemu/option.h" @@ -174,7 +170,6 @@ static void parse_numa_distance(NumaDistOptions *dist, Error **errp) have_numa_distance = true; } -static void set_numa_options(MachineState *ms, NumaOptions *object, Error **errp) { Error *err = NULL; @@ -447,17 +442,6 @@ void parse_numa_opts(MachineState *ms) qemu_opts_foreach(qemu_find_opts("numa"), parse_numa, ms, &error_fatal); } -void qmp_set_numa_node(NumaOptions *cmd, Error **errp) -{ - if (!runstate_check(RUN_STATE_PRECONFIG)) { - error_setg(errp, "The command is permitted only in '%s' state", - RunState_str(RUN_STATE_PRECONFIG)); - return; - } - - set_numa_options(MACHINE(qdev_get_machine()), cmd, errp); -} - void numa_cpu_pre_plug(const CPUArchId *slot, DeviceState *dev, Error **errp) { int node_id = object_property_get_int(OBJECT(dev), "node-id", &error_abort); @@ -592,52 +576,6 @@ void query_numa_node_mem(NumaNodeMem node_mem[]) } } -static int query_memdev(Object *obj, void *opaque) -{ - MemdevList **list = opaque; - MemdevList *m = NULL; - - if (object_dynamic_cast(obj, TYPE_MEMORY_BACKEND)) { - m = g_malloc0(sizeof(*m)); - - m->value = g_malloc0(sizeof(*m->value)); - - m->value->id = object_get_canonical_path_component(obj); - m->value->has_id = !!m->value->id; - - m->value->size = object_property_get_uint(obj, "size", - &error_abort); - m->value->merge = object_property_get_bool(obj, "merge", - &error_abort); - m->value->dump = object_property_get_bool(obj, "dump", - &error_abort); - m->value->prealloc = object_property_get_bool(obj, - "prealloc", - &error_abort); - m->value->policy = object_property_get_enum(obj, - "policy", - "HostMemPolicy", - &error_abort); - object_property_get_uint16List(obj, "host-nodes", - &m->value->host_nodes, - &error_abort); - - m->next = *list; - *list = m; - } - - return 0; -} - -MemdevList *qmp_query_memdev(Error **errp) -{ - Object *obj = object_get_objects_root(); - MemdevList *list = NULL; - - object_child_foreach(obj, query_memdev, &list); - return list; -} - void ram_block_notifier_add(RAMBlockNotifier *n) { QLIST_INSERT_HEAD(&ram_list.ramblock_notifiers, n, next); diff --git a/hw/core/qdev.c b/hw/core/qdev.c index f9b6efe509..94ebc0a4a1 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -29,7 +29,7 @@ #include "hw/qdev.h" #include "sysemu/sysemu.h" #include "qapi/error.h" -#include "qapi/qapi-events-misc.h" +#include "qapi/qapi-events-qdev.h" #include "qapi/qmp/qerror.h" #include "qapi/visitor.h" #include "qemu/error-report.h" diff --git a/hw/display/ati.c b/hw/display/ati.c index 0cb1173848..c1d9d1518f 100644 --- a/hw/display/ati.c +++ b/hw/display/ati.c @@ -538,7 +538,7 @@ static void ati_mm_write(void *opaque, hwaddr addr, break; case GPIO_DVI_DDC: if (s->dev_id != PCI_DEVICE_ID_ATI_RAGE128_PF) { - s->regs.gpio_dvi_ddc = ati_i2c(s->bbi2c, data, 0); + s->regs.gpio_dvi_ddc = ati_i2c(&s->bbi2c, data, 0); } break; case GPIO_MONID ... GPIO_MONID + 3: @@ -554,7 +554,7 @@ static void ati_mm_write(void *opaque, hwaddr addr, */ if ((s->regs.gpio_monid & BIT(25)) && addr <= GPIO_MONID + 2 && addr + size > GPIO_MONID + 2) { - s->regs.gpio_monid = ati_i2c(s->bbi2c, s->regs.gpio_monid, 1); + s->regs.gpio_monid = ati_i2c(&s->bbi2c, s->regs.gpio_monid, 1); } } break; @@ -856,7 +856,7 @@ static void ati_vga_realize(PCIDevice *dev, Error **errp) /* ddc, edid */ I2CBus *i2cbus = i2c_init_bus(DEVICE(s), "ati-vga.ddc"); - s->bbi2c = bitbang_i2c_init(i2cbus); + bitbang_i2c_init(&s->bbi2c, i2cbus); I2CSlave *i2cddc = I2C_SLAVE(qdev_create(BUS(i2cbus), TYPE_I2CDDC)); i2c_set_slave_address(i2cddc, 0x50); @@ -885,7 +885,6 @@ static void ati_vga_exit(PCIDevice *dev) ATIVGAState *s = ATI_VGA(dev); graphic_console_close(s->vga.con); - g_free(s->bbi2c); } static Property ati_vga_properties[] = { diff --git a/hw/display/ati_int.h b/hw/display/ati_int.h index 9b67d0022a..31a1927b3e 100644 --- a/hw/display/ati_int.h +++ b/hw/display/ati_int.h @@ -88,7 +88,7 @@ typedef struct ATIVGAState { uint16_t cursor_size; uint32_t cursor_offset; QEMUCursor *cursor; - bitbang_i2c_interface *bbi2c; + bitbang_i2c_interface bbi2c; MemoryRegion io; MemoryRegion mm; ATIVGARegs regs; diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index 2b0f66b1d6..25d9e327fc 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -1002,6 +1002,11 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size, resource_id = qemu_get_be32(f); while (resource_id != 0) { + res = virtio_gpu_find_resource(g, resource_id); + if (res) { + return -EINVAL; + } + res = g_new0(struct virtio_gpu_simple_resource, 1); res->resource_id = resource_id; res->width = qemu_get_be32(f); @@ -1048,9 +1053,9 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size, if (res->iov[i].iov_base) { dma_memory_unmap(VIRTIO_DEVICE(g)->dma_as, res->iov[i].iov_base, - res->iov[i].iov_len, + len, DMA_DIRECTION_TO_DEVICE, - res->iov[i].iov_len); + 0); } /* ...and the mappings for previous loop iterations */ res->iov_cnt = i; diff --git a/hw/i2c/bitbang_i2c.c b/hw/i2c/bitbang_i2c.c index 3cb0509b02..60c7a9be0b 100644 --- a/hw/i2c/bitbang_i2c.c +++ b/hw/i2c/bitbang_i2c.c @@ -25,39 +25,6 @@ do { printf("bitbang_i2c: " fmt , ## __VA_ARGS__); } while (0) #define DPRINTF(fmt, ...) do {} while(0) #endif -typedef enum bitbang_i2c_state { - STOPPED = 0, - SENDING_BIT7, - SENDING_BIT6, - SENDING_BIT5, - SENDING_BIT4, - SENDING_BIT3, - SENDING_BIT2, - SENDING_BIT1, - SENDING_BIT0, - WAITING_FOR_ACK, - RECEIVING_BIT7, - RECEIVING_BIT6, - RECEIVING_BIT5, - RECEIVING_BIT4, - RECEIVING_BIT3, - RECEIVING_BIT2, - RECEIVING_BIT1, - RECEIVING_BIT0, - SENDING_ACK, - SENT_NACK -} bitbang_i2c_state; - -struct bitbang_i2c_interface { - I2CBus *bus; - bitbang_i2c_state state; - int last_data; - int last_clock; - int device_out; - uint8_t buffer; - int current_addr; -}; - static void bitbang_i2c_enter_stop(bitbang_i2c_interface *i2c) { DPRINTF("STOP\n"); @@ -184,18 +151,12 @@ int bitbang_i2c_set(bitbang_i2c_interface *i2c, int line, int level) abort(); } -bitbang_i2c_interface *bitbang_i2c_init(I2CBus *bus) +void bitbang_i2c_init(bitbang_i2c_interface *s, I2CBus *bus) { - bitbang_i2c_interface *s; - - s = g_malloc0(sizeof(bitbang_i2c_interface)); - s->bus = bus; s->last_data = 1; s->last_clock = 1; s->device_out = 1; - - return s; } /* GPIO interface. */ @@ -207,7 +168,7 @@ typedef struct GPIOI2CState { SysBusDevice parent_obj; MemoryRegion dummy_iomem; - bitbang_i2c_interface *bitbang; + bitbang_i2c_interface bitbang; int last_level; qemu_irq out; } GPIOI2CState; @@ -216,7 +177,7 @@ static void bitbang_i2c_gpio_set(void *opaque, int irq, int level) { GPIOI2CState *s = opaque; - level = bitbang_i2c_set(s->bitbang, irq, level); + level = bitbang_i2c_set(&s->bitbang, irq, level); if (level != s->last_level) { s->last_level = level; qemu_set_irq(s->out, level); @@ -234,7 +195,7 @@ static void gpio_i2c_init(Object *obj) sysbus_init_mmio(sbd, &s->dummy_iomem); bus = i2c_init_bus(dev, "i2c"); - s->bitbang = bitbang_i2c_init(bus); + bitbang_i2c_init(&s->bitbang, bus); qdev_init_gpio_in(dev, bitbang_i2c_gpio_set, 2); qdev_init_gpio_out(dev, &s->out, 1); diff --git a/hw/i2c/ppc4xx_i2c.c b/hw/i2c/ppc4xx_i2c.c index 5fb4f86c38..462729db4e 100644 --- a/hw/i2c/ppc4xx_i2c.c +++ b/hw/i2c/ppc4xx_i2c.c @@ -311,9 +311,9 @@ static void ppc4xx_i2c_writeb(void *opaque, hwaddr addr, uint64_t value, case IIC_DIRECTCNTL: i2c->directcntl = value & (IIC_DIRECTCNTL_SDAC & IIC_DIRECTCNTL_SCLC); i2c->directcntl |= (value & IIC_DIRECTCNTL_SCLC ? 1 : 0); - bitbang_i2c_set(i2c->bitbang, BITBANG_I2C_SCL, + bitbang_i2c_set(&i2c->bitbang, BITBANG_I2C_SCL, i2c->directcntl & IIC_DIRECTCNTL_MSCL); - i2c->directcntl |= bitbang_i2c_set(i2c->bitbang, BITBANG_I2C_SDA, + i2c->directcntl |= bitbang_i2c_set(&i2c->bitbang, BITBANG_I2C_SDA, (value & IIC_DIRECTCNTL_SDAC) != 0) << 1; break; default: @@ -347,7 +347,7 @@ static void ppc4xx_i2c_init(Object *o) sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem); sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq); s->bus = i2c_init_bus(DEVICE(s), "i2c"); - s->bitbang = bitbang_i2c_init(s->bus); + bitbang_i2c_init(&s->bitbang, s->bus); } static void ppc4xx_i2c_class_init(ObjectClass *klass, void *data) diff --git a/hw/i2c/versatile_i2c.c b/hw/i2c/versatile_i2c.c index 24b6e36b6d..1ac2a6f59a 100644 --- a/hw/i2c/versatile_i2c.c +++ b/hw/i2c/versatile_i2c.c @@ -35,7 +35,7 @@ typedef struct VersatileI2CState { SysBusDevice parent_obj; MemoryRegion iomem; - bitbang_i2c_interface *bitbang; + bitbang_i2c_interface bitbang; int out; int in; } VersatileI2CState; @@ -70,8 +70,8 @@ static void versatile_i2c_write(void *opaque, hwaddr offset, qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%x\n", __func__, (int)offset); } - bitbang_i2c_set(s->bitbang, BITBANG_I2C_SCL, (s->out & 1) != 0); - s->in = bitbang_i2c_set(s->bitbang, BITBANG_I2C_SDA, (s->out & 2) != 0); + bitbang_i2c_set(&s->bitbang, BITBANG_I2C_SCL, (s->out & 1) != 0); + s->in = bitbang_i2c_set(&s->bitbang, BITBANG_I2C_SDA, (s->out & 2) != 0); } static const MemoryRegionOps versatile_i2c_ops = { @@ -88,7 +88,7 @@ static void versatile_i2c_init(Object *obj) I2CBus *bus; bus = i2c_init_bus(dev, "i2c"); - s->bitbang = bitbang_i2c_init(bus); + bitbang_i2c_init(&s->bitbang, bus); memory_region_init_io(&s->iomem, obj, &versatile_i2c_ops, s, "versatile_i2c", 0x1000); sysbus_init_mmio(sbd, &s->iomem); diff --git a/hw/intc/aspeed_vic.c b/hw/intc/aspeed_vic.c index 927638d532..266a309f3b 100644 --- a/hw/intc/aspeed_vic.c +++ b/hw/intc/aspeed_vic.c @@ -104,54 +104,63 @@ static void aspeed_vic_set_irq(void *opaque, int irq, int level) static uint64_t aspeed_vic_read(void *opaque, hwaddr offset, unsigned size) { - uint64_t val; - const bool high = !!(offset & 0x4); - hwaddr n_offset = (offset & ~0x4); AspeedVICState *s = (AspeedVICState *)opaque; + hwaddr n_offset; + uint64_t val; + bool high; if (offset < AVIC_NEW_BASE_OFFSET) { - qemu_log_mask(LOG_UNIMP, "%s: Ignoring read from legacy registers " - "at 0x%" HWADDR_PRIx "[%u]\n", __func__, offset, size); - return 0; + high = false; + n_offset = offset; + } else { + high = !!(offset & 0x4); + n_offset = (offset & ~0x4); } - n_offset -= AVIC_NEW_BASE_OFFSET; - switch (n_offset) { - case 0x0: /* IRQ Status */ + case 0x80: /* IRQ Status */ + case 0x00: val = s->raw & ~s->select & s->enable; break; - case 0x08: /* FIQ Status */ + case 0x88: /* FIQ Status */ + case 0x04: val = s->raw & s->select & s->enable; break; - case 0x10: /* Raw Interrupt Status */ + case 0x90: /* Raw Interrupt Status */ + case 0x08: val = s->raw; break; - case 0x18: /* Interrupt Selection */ + case 0x98: /* Interrupt Selection */ + case 0x0c: val = s->select; break; - case 0x20: /* Interrupt Enable */ + case 0xa0: /* Interrupt Enable */ + case 0x10: val = s->enable; break; - case 0x30: /* Software Interrupt */ + case 0xb0: /* Software Interrupt */ + case 0x18: val = s->trigger; break; - case 0x40: /* Interrupt Sensitivity */ + case 0xc0: /* Interrupt Sensitivity */ + case 0x24: val = s->sense; break; - case 0x48: /* Interrupt Both Edge Trigger Control */ + case 0xc8: /* Interrupt Both Edge Trigger Control */ + case 0x28: val = s->dual_edge; break; - case 0x50: /* Interrupt Event */ + case 0xd0: /* Interrupt Event */ + case 0x2c: val = s->event; break; - case 0x60: /* Edge Triggered Interrupt Status */ + case 0xe0: /* Edge Triggered Interrupt Status */ val = s->raw & ~s->sense; break; /* Illegal */ - case 0x28: /* Interrupt Enable Clear */ - case 0x38: /* Software Interrupt Clear */ - case 0x58: /* Edge Triggered Interrupt Clear */ + case 0xa8: /* Interrupt Enable Clear */ + case 0xb8: /* Software Interrupt Clear */ + case 0xd8: /* Edge Triggered Interrupt Clear */ qemu_log_mask(LOG_GUEST_ERROR, "%s: Read of write-only register with offset 0x%" HWADDR_PRIx "\n", __func__, offset); @@ -166,6 +175,8 @@ static uint64_t aspeed_vic_read(void *opaque, hwaddr offset, unsigned size) } if (high) { val = extract64(val, 32, 19); + } else { + val = extract64(val, 0, 32); } trace_aspeed_vic_read(offset, size, val); return val; @@ -174,19 +185,18 @@ static uint64_t aspeed_vic_read(void *opaque, hwaddr offset, unsigned size) static void aspeed_vic_write(void *opaque, hwaddr offset, uint64_t data, unsigned size) { - const bool high = !!(offset & 0x4); - hwaddr n_offset = (offset & ~0x4); AspeedVICState *s = (AspeedVICState *)opaque; + hwaddr n_offset; + bool high; if (offset < AVIC_NEW_BASE_OFFSET) { - qemu_log_mask(LOG_UNIMP, - "%s: Ignoring write to legacy registers at 0x%" - HWADDR_PRIx "[%u] <- 0x%" PRIx64 "\n", __func__, offset, - size, data); - return; + high = false; + n_offset = offset; + } else { + high = !!(offset & 0x4); + n_offset = (offset & ~0x4); } - n_offset -= AVIC_NEW_BASE_OFFSET; trace_aspeed_vic_write(offset, size, data); /* Given we have members using separate enable/clear registers, deposit64() @@ -201,7 +211,8 @@ static void aspeed_vic_write(void *opaque, hwaddr offset, uint64_t data, } switch (n_offset) { - case 0x18: /* Interrupt Selection */ + case 0x98: /* Interrupt Selection */ + case 0x0c: /* Register has deposit64() semantics - overwrite requested 32 bits */ if (high) { s->select &= AVIC_L_MASK; @@ -210,21 +221,25 @@ static void aspeed_vic_write(void *opaque, hwaddr offset, uint64_t data, } s->select |= data; break; - case 0x20: /* Interrupt Enable */ + case 0xa0: /* Interrupt Enable */ + case 0x10: s->enable |= data; break; - case 0x28: /* Interrupt Enable Clear */ + case 0xa8: /* Interrupt Enable Clear */ + case 0x14: s->enable &= ~data; break; - case 0x30: /* Software Interrupt */ + case 0xb0: /* Software Interrupt */ + case 0x18: qemu_log_mask(LOG_UNIMP, "%s: Software interrupts unavailable. " "IRQs requested: 0x%016" PRIx64 "\n", __func__, data); break; - case 0x38: /* Software Interrupt Clear */ + case 0xb8: /* Software Interrupt Clear */ + case 0x1c: qemu_log_mask(LOG_UNIMP, "%s: Software interrupts unavailable. " "IRQs to be cleared: 0x%016" PRIx64 "\n", __func__, data); break; - case 0x50: /* Interrupt Event */ + case 0xd0: /* Interrupt Event */ /* Register has deposit64() semantics - overwrite the top four valid * IRQ bits, as only the top four IRQs (GPIOs) can change their event * type */ @@ -236,15 +251,21 @@ static void aspeed_vic_write(void *opaque, hwaddr offset, uint64_t data, "Ignoring invalid write to interrupt event register"); } break; - case 0x58: /* Edge Triggered Interrupt Clear */ + case 0xd8: /* Edge Triggered Interrupt Clear */ + case 0x38: s->raw &= ~(data & ~s->sense); break; - case 0x00: /* IRQ Status */ - case 0x08: /* FIQ Status */ - case 0x10: /* Raw Interrupt Status */ - case 0x40: /* Interrupt Sensitivity */ - case 0x48: /* Interrupt Both Edge Trigger Control */ - case 0x60: /* Edge Triggered Interrupt Status */ + case 0x80: /* IRQ Status */ + case 0x00: + case 0x88: /* FIQ Status */ + case 0x04: + case 0x90: /* Raw Interrupt Status */ + case 0x08: + case 0xc0: /* Interrupt Sensitivity */ + case 0x24: + case 0xc8: /* Interrupt Both Edge Trigger Control */ + case 0x28: + case 0xe0: /* Edge Triggered Interrupt Status */ qemu_log_mask(LOG_GUEST_ERROR, "%s: Write of read-only register with offset 0x%" HWADDR_PRIx "\n", __func__, offset); diff --git a/hw/intc/pnv_xive.c b/hw/intc/pnv_xive.c index a55c2bbc88..4dc92ef1e3 100644 --- a/hw/intc/pnv_xive.c +++ b/hw/intc/pnv_xive.c @@ -169,7 +169,7 @@ static uint64_t pnv_xive_vst_addr_indirect(PnvXive *xive, uint32_t type, vsd = ldq_be_dma(&address_space_memory, vsd_addr); if (!(vsd & VSD_ADDRESS_MASK)) { - xive_error(xive, "VST: invalid %s entry %x !?", info->name, 0); + xive_error(xive, "VST: invalid %s entry %x !?", info->name, idx); return 0; } @@ -190,7 +190,7 @@ static uint64_t pnv_xive_vst_addr_indirect(PnvXive *xive, uint32_t type, vsd = ldq_be_dma(&address_space_memory, vsd_addr); if (!(vsd & VSD_ADDRESS_MASK)) { - xive_error(xive, "VST: invalid %s entry %x !?", info->name, 0); + xive_error(xive, "VST: invalid %s entry %x !?", info->name, idx); return 0; } @@ -294,8 +294,12 @@ static int pnv_xive_write_end(XiveRouter *xrtr, uint8_t blk, uint32_t idx, word_number); } -static int pnv_xive_end_update(PnvXive *xive, uint8_t blk, uint32_t idx) +static int pnv_xive_end_update(PnvXive *xive) { + uint8_t blk = GETFIELD(VC_EQC_CWATCH_BLOCKID, + xive->regs[(VC_EQC_CWATCH_SPEC >> 3)]); + uint32_t idx = GETFIELD(VC_EQC_CWATCH_OFFSET, + xive->regs[(VC_EQC_CWATCH_SPEC >> 3)]); int i; uint64_t eqc_watch[4]; @@ -307,6 +311,24 @@ static int pnv_xive_end_update(PnvXive *xive, uint8_t blk, uint32_t idx) XIVE_VST_WORD_ALL); } +static void pnv_xive_end_cache_load(PnvXive *xive) +{ + uint8_t blk = GETFIELD(VC_EQC_CWATCH_BLOCKID, + xive->regs[(VC_EQC_CWATCH_SPEC >> 3)]); + uint32_t idx = GETFIELD(VC_EQC_CWATCH_OFFSET, + xive->regs[(VC_EQC_CWATCH_SPEC >> 3)]); + uint64_t eqc_watch[4] = { 0 }; + int i; + + if (pnv_xive_vst_read(xive, VST_TSEL_EQDT, blk, idx, eqc_watch)) { + xive_error(xive, "VST: no END entry %x/%x !?", blk, idx); + } + + for (i = 0; i < ARRAY_SIZE(eqc_watch); i++) { + xive->regs[(VC_EQC_CWATCH_DAT0 >> 3) + i] = be64_to_cpu(eqc_watch[i]); + } +} + static int pnv_xive_get_nvt(XiveRouter *xrtr, uint8_t blk, uint32_t idx, XiveNVT *nvt) { @@ -320,8 +342,12 @@ static int pnv_xive_write_nvt(XiveRouter *xrtr, uint8_t blk, uint32_t idx, word_number); } -static int pnv_xive_nvt_update(PnvXive *xive, uint8_t blk, uint32_t idx) +static int pnv_xive_nvt_update(PnvXive *xive) { + uint8_t blk = GETFIELD(PC_VPC_CWATCH_BLOCKID, + xive->regs[(PC_VPC_CWATCH_SPEC >> 3)]); + uint32_t idx = GETFIELD(PC_VPC_CWATCH_OFFSET, + xive->regs[(PC_VPC_CWATCH_SPEC >> 3)]); int i; uint64_t vpc_watch[8]; @@ -333,6 +359,24 @@ static int pnv_xive_nvt_update(PnvXive *xive, uint8_t blk, uint32_t idx) XIVE_VST_WORD_ALL); } +static void pnv_xive_nvt_cache_load(PnvXive *xive) +{ + uint8_t blk = GETFIELD(PC_VPC_CWATCH_BLOCKID, + xive->regs[(PC_VPC_CWATCH_SPEC >> 3)]); + uint32_t idx = GETFIELD(PC_VPC_CWATCH_OFFSET, + xive->regs[(PC_VPC_CWATCH_SPEC >> 3)]); + uint64_t vpc_watch[8] = { 0 }; + int i; + + if (pnv_xive_vst_read(xive, VST_TSEL_VPDT, blk, idx, vpc_watch)) { + xive_error(xive, "VST: no NVT entry %x/%x !?", blk, idx); + } + + for (i = 0; i < ARRAY_SIZE(vpc_watch); i++) { + xive->regs[(PC_VPC_CWATCH_DAT0 >> 3) + i] = be64_to_cpu(vpc_watch[i]); + } +} + static int pnv_xive_get_eas(XiveRouter *xrtr, uint8_t blk, uint32_t idx, XiveEAS *eas) { @@ -346,12 +390,6 @@ static int pnv_xive_get_eas(XiveRouter *xrtr, uint8_t blk, uint32_t idx, return pnv_xive_vst_read(xive, VST_TSEL_IVT, blk, idx, eas); } -static int pnv_xive_eas_update(PnvXive *xive, uint8_t blk, uint32_t idx) -{ - /* All done. */ - return 0; -} - static XiveTCTX *pnv_xive_get_tctx(XiveRouter *xrtr, CPUState *cs) { PowerPCCPU *cpu = POWERPC_CPU(cs); @@ -781,8 +819,7 @@ static void pnv_xive_ic_reg_write(void *opaque, hwaddr offset, * support recently though) */ if (val & (VC_SBC_CONF_CPLX_CIST | VC_SBC_CONF_CIST_BOTH)) { - object_property_set_int(OBJECT(&xive->ipi_source), - XIVE_SRC_STORE_EOI, "flags", &error_fatal); + xive->ipi_source.esb_flags |= XIVE_SRC_STORE_EOI; } break; @@ -951,28 +988,43 @@ static void pnv_xive_ic_reg_write(void *opaque, hwaddr offset, * XIVE PC & VC cache updates for EAS, NVT and END */ case VC_IVC_SCRUB_MASK: - break; case VC_IVC_SCRUB_TRIG: - pnv_xive_eas_update(xive, GETFIELD(PC_SCRUB_BLOCK_ID, val), - GETFIELD(VC_SCRUB_OFFSET, val)); break; - case VC_EQC_SCRUB_MASK: case VC_EQC_CWATCH_SPEC: - case VC_EQC_CWATCH_DAT0 ... VC_EQC_CWATCH_DAT3: + val &= ~VC_EQC_CWATCH_CONFLICT; /* HW resets this bit */ + break; + case VC_EQC_CWATCH_DAT1 ... VC_EQC_CWATCH_DAT3: break; + case VC_EQC_CWATCH_DAT0: + /* writing to DATA0 triggers the cache write */ + xive->regs[reg] = val; + pnv_xive_end_update(xive); + break; + case VC_EQC_SCRUB_MASK: case VC_EQC_SCRUB_TRIG: - pnv_xive_end_update(xive, GETFIELD(VC_SCRUB_BLOCK_ID, val), - GETFIELD(VC_SCRUB_OFFSET, val)); + /* + * The scrubbing registers flush the cache in RAM and can also + * invalidate. + */ break; - case PC_VPC_SCRUB_MASK: case PC_VPC_CWATCH_SPEC: - case PC_VPC_CWATCH_DAT0 ... PC_VPC_CWATCH_DAT7: + val &= ~PC_VPC_CWATCH_CONFLICT; /* HW resets this bit */ + break; + case PC_VPC_CWATCH_DAT1 ... PC_VPC_CWATCH_DAT7: break; + case PC_VPC_CWATCH_DAT0: + /* writing to DATA0 triggers the cache write */ + xive->regs[reg] = val; + pnv_xive_nvt_update(xive); + break; + case PC_VPC_SCRUB_MASK: case PC_VPC_SCRUB_TRIG: - pnv_xive_nvt_update(xive, GETFIELD(PC_SCRUB_BLOCK_ID, val), - GETFIELD(PC_SCRUB_OFFSET, val)); + /* + * The scrubbing registers flush the cache in RAM and can also + * invalidate. + */ break; @@ -1023,15 +1075,6 @@ static uint64_t pnv_xive_ic_reg_read(void *opaque, hwaddr offset, unsigned size) case PC_GLOBAL_CONFIG: case PC_VPC_SCRUB_MASK: - case PC_VPC_CWATCH_SPEC: - case PC_VPC_CWATCH_DAT0: - case PC_VPC_CWATCH_DAT1: - case PC_VPC_CWATCH_DAT2: - case PC_VPC_CWATCH_DAT3: - case PC_VPC_CWATCH_DAT4: - case PC_VPC_CWATCH_DAT5: - case PC_VPC_CWATCH_DAT6: - case PC_VPC_CWATCH_DAT7: case VC_GLOBAL_CONFIG: case VC_AIB_TX_ORDER_TAG2: @@ -1044,12 +1087,6 @@ static uint64_t pnv_xive_ic_reg_read(void *opaque, hwaddr offset, unsigned size) case VC_IRQ_CONFIG_IPI_CASC: case VC_EQC_SCRUB_MASK: - case VC_EQC_CWATCH_DAT0: - case VC_EQC_CWATCH_DAT1: - case VC_EQC_CWATCH_DAT2: - case VC_EQC_CWATCH_DAT3: - - case VC_EQC_CWATCH_SPEC: case VC_IVC_SCRUB_MASK: case VC_SBC_CONFIG: case VC_AT_MACRO_KILL_MASK: @@ -1081,6 +1118,38 @@ static uint64_t pnv_xive_ic_reg_read(void *opaque, hwaddr offset, unsigned size) /* * XIVE PC & VC cache updates for EAS, NVT and END */ + case VC_EQC_CWATCH_SPEC: + xive->regs[reg] = ~(VC_EQC_CWATCH_FULL | VC_EQC_CWATCH_CONFLICT); + val = xive->regs[reg]; + break; + case VC_EQC_CWATCH_DAT0: + /* + * Load DATA registers from cache with data requested by the + * SPEC register + */ + pnv_xive_end_cache_load(xive); + val = xive->regs[reg]; + break; + case VC_EQC_CWATCH_DAT1 ... VC_EQC_CWATCH_DAT3: + val = xive->regs[reg]; + break; + + case PC_VPC_CWATCH_SPEC: + xive->regs[reg] = ~(PC_VPC_CWATCH_FULL | PC_VPC_CWATCH_CONFLICT); + val = xive->regs[reg]; + break; + case PC_VPC_CWATCH_DAT0: + /* + * Load DATA registers from cache with data requested by the + * SPEC register + */ + pnv_xive_nvt_cache_load(xive); + val = xive->regs[reg]; + break; + case PC_VPC_CWATCH_DAT1 ... PC_VPC_CWATCH_DAT7: + val = xive->regs[reg]; + break; + case PC_VPC_SCRUB_TRIG: case VC_IVC_SCRUB_TRIG: case VC_EQC_SCRUB_TRIG: diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c index 58c2e5d890..3ae311d9ff 100644 --- a/hw/intc/spapr_xive.c +++ b/hw/intc/spapr_xive.c @@ -194,13 +194,6 @@ void spapr_xive_pic_print_info(SpaprXive *xive, Monitor *mon) } } -void spapr_xive_map_mmio(SpaprXive *xive) -{ - sysbus_mmio_map(SYS_BUS_DEVICE(xive), 0, xive->vc_base); - sysbus_mmio_map(SYS_BUS_DEVICE(xive), 1, xive->end_base); - sysbus_mmio_map(SYS_BUS_DEVICE(xive), 2, xive->tm_base); -} - void spapr_xive_mmio_set_enabled(SpaprXive *xive, bool enable) { memory_region_set_enabled(&xive->source.esb_mmio, enable); @@ -305,6 +298,7 @@ static void spapr_xive_realize(DeviceState *dev, Error **errp) error_propagate(errp, local_err); return; } + sysbus_init_mmio(SYS_BUS_DEVICE(xive), &xsrc->esb_mmio); /* * Initialize the END ESB source @@ -318,6 +312,7 @@ static void spapr_xive_realize(DeviceState *dev, Error **errp) error_propagate(errp, local_err); return; } + sysbus_init_mmio(SYS_BUS_DEVICE(xive), &end_xsrc->esb_mmio); /* Set the mapping address of the END ESB pages after the source ESBs */ xive->end_base = xive->vc_base + (1ull << xsrc->esb_shift) * xsrc->nr_irqs; @@ -333,31 +328,18 @@ static void spapr_xive_realize(DeviceState *dev, Error **errp) qemu_register_reset(spapr_xive_reset, dev); - /* Define all XIVE MMIO regions on SysBus */ - sysbus_init_mmio(SYS_BUS_DEVICE(xive), &xsrc->esb_mmio); - sysbus_init_mmio(SYS_BUS_DEVICE(xive), &end_xsrc->esb_mmio); - sysbus_init_mmio(SYS_BUS_DEVICE(xive), &xive->tm_mmio); -} - -void spapr_xive_init(SpaprXive *xive, Error **errp) -{ - XiveSource *xsrc = &xive->source; - - /* - * The emulated XIVE device can only be initialized once. If the - * ESB memory region has been already mapped, it means we have been - * through there. - */ - if (memory_region_is_mapped(&xsrc->esb_mmio)) { - return; - } - /* TIMA initialization */ memory_region_init_io(&xive->tm_mmio, OBJECT(xive), &xive_tm_ops, xive, "xive.tima", 4ull << TM_SHIFT); + sysbus_init_mmio(SYS_BUS_DEVICE(xive), &xive->tm_mmio); - /* Map all regions */ - spapr_xive_map_mmio(xive); + /* + * Map all regions. These will be enabled or disabled at reset and + * can also be overridden by KVM memory regions if active + */ + sysbus_mmio_map(SYS_BUS_DEVICE(xive), 0, xive->vc_base); + sysbus_mmio_map(SYS_BUS_DEVICE(xive), 1, xive->end_base); + sysbus_mmio_map(SYS_BUS_DEVICE(xive), 2, xive->tm_base); } static int spapr_xive_get_eas(XiveRouter *xrtr, uint8_t eas_blk, diff --git a/hw/intc/spapr_xive_kvm.c b/hw/intc/spapr_xive_kvm.c index b48f135838..3bf8e7a20e 100644 --- a/hw/intc/spapr_xive_kvm.c +++ b/hw/intc/spapr_xive_kvm.c @@ -724,12 +724,13 @@ void kvmppc_xive_connect(SpaprXive *xive, Error **errp) xsrc->esb_mmap = kvmppc_xive_mmap(xive, KVM_XIVE_ESB_PAGE_OFFSET, esb_len, &local_err); if (local_err) { - error_propagate(errp, local_err); - return; + goto fail; } - memory_region_init_ram_device_ptr(&xsrc->esb_mmio, OBJECT(xsrc), + memory_region_init_ram_device_ptr(&xsrc->esb_mmio_kvm, OBJECT(xsrc), "xive.esb", esb_len, xsrc->esb_mmap); + memory_region_add_subregion_overlap(&xsrc->esb_mmio, 0, + &xsrc->esb_mmio_kvm, 1); /* * 2. END ESB pages (No KVM support yet) @@ -741,11 +742,12 @@ void kvmppc_xive_connect(SpaprXive *xive, Error **errp) xive->tm_mmap = kvmppc_xive_mmap(xive, KVM_XIVE_TIMA_PAGE_OFFSET, tima_len, &local_err); if (local_err) { - error_propagate(errp, local_err); - return; + goto fail; } - memory_region_init_ram_device_ptr(&xive->tm_mmio, OBJECT(xive), + memory_region_init_ram_device_ptr(&xive->tm_mmio_kvm, OBJECT(xive), "xive.tima", tima_len, xive->tm_mmap); + memory_region_add_subregion_overlap(&xive->tm_mmio, 0, + &xive->tm_mmio_kvm, 1); xive->change = qemu_add_vm_change_state_handler( kvmppc_xive_change_state_handler, xive); @@ -756,24 +758,24 @@ void kvmppc_xive_connect(SpaprXive *xive, Error **errp) kvmppc_xive_cpu_connect(spapr_cpu_state(cpu)->tctx, &local_err); if (local_err) { - error_propagate(errp, local_err); - return; + goto fail; } } /* Update the KVM sources */ kvmppc_xive_source_reset(xsrc, &local_err); if (local_err) { - error_propagate(errp, local_err); - return; + goto fail; } kvm_kernel_irqchip = true; kvm_msi_via_irqfd_allowed = true; kvm_gsi_direct_mapping = true; + return; - /* Map all regions */ - spapr_xive_map_mmio(xive); +fail: + error_propagate(errp, local_err); + kvmppc_xive_disconnect(xive, NULL); } void kvmppc_xive_disconnect(SpaprXive *xive, Error **errp) @@ -795,21 +797,29 @@ void kvmppc_xive_disconnect(SpaprXive *xive, Error **errp) xsrc = &xive->source; esb_len = (1ull << xsrc->esb_shift) * xsrc->nr_irqs; - sysbus_mmio_unmap(SYS_BUS_DEVICE(xive), 0); - munmap(xsrc->esb_mmap, esb_len); - - sysbus_mmio_unmap(SYS_BUS_DEVICE(xive), 1); + if (xsrc->esb_mmap) { + memory_region_del_subregion(&xsrc->esb_mmio, &xsrc->esb_mmio_kvm); + object_unparent(OBJECT(&xsrc->esb_mmio_kvm)); + munmap(xsrc->esb_mmap, esb_len); + xsrc->esb_mmap = NULL; + } - sysbus_mmio_unmap(SYS_BUS_DEVICE(xive), 2); - munmap(xive->tm_mmap, 4ull << TM_SHIFT); + if (xive->tm_mmap) { + memory_region_del_subregion(&xive->tm_mmio, &xive->tm_mmio_kvm); + object_unparent(OBJECT(&xive->tm_mmio_kvm)); + munmap(xive->tm_mmap, 4ull << TM_SHIFT); + xive->tm_mmap = NULL; + } /* * When the KVM device fd is closed, the KVM device is destroyed * and removed from the list of devices of the VM. The VCPU * presenters are also detached from the device. */ - close(xive->fd); - xive->fd = -1; + if (xive->fd != -1) { + close(xive->fd); + xive->fd = -1; + } kvm_kernel_irqchip = false; kvm_msi_via_irqfd_allowed = false; @@ -819,5 +829,8 @@ void kvmppc_xive_disconnect(SpaprXive *xive, Error **errp) kvm_cpu_disable_all(); /* VM Change state handler is not needed anymore */ - qemu_del_vm_change_state_handler(xive->change); + if (xive->change) { + qemu_del_vm_change_state_handler(xive->change); + xive->change = NULL; + } } diff --git a/hw/intc/xics.c b/hw/intc/xics.c index 29f7d39781..faa976e2f8 100644 --- a/hw/intc/xics.c +++ b/hw/intc/xics.c @@ -267,7 +267,14 @@ static int icp_post_load(void *opaque, int version_id) ICPState *icp = opaque; if (kvm_irqchip_in_kernel()) { - return icp_set_kvm_state(icp); + Error *local_err = NULL; + int ret; + + ret = icp_set_kvm_state(icp, &local_err); + if (ret < 0) { + error_report_err(local_err); + return ret; + } } return 0; @@ -300,7 +307,12 @@ static void icp_reset_handler(void *dev) qemu_set_irq(icp->output, 0); if (kvm_irqchip_in_kernel()) { - icp_set_kvm_state(ICP(dev)); + Error *local_err = NULL; + + icp_set_kvm_state(ICP(dev), &local_err); + if (local_err) { + error_report_err(local_err); + } } } @@ -351,6 +363,7 @@ static void icp_realize(DeviceState *dev, Error **errp) return; } + /* Connect the presenter to the VCPU (required for CPU hotplug) */ if (kvm_irqchip_in_kernel()) { icp_kvm_realize(dev, &err); if (err) { @@ -563,7 +576,12 @@ static void ics_simple_reset(DeviceState *dev) icsc->parent_reset(dev); if (kvm_irqchip_in_kernel()) { - ics_set_kvm_state(ICS_BASE(dev)); + Error *local_err = NULL; + + ics_set_kvm_state(ICS_BASE(dev), &local_err); + if (local_err) { + error_report_err(local_err); + } } } @@ -679,7 +697,14 @@ static int ics_base_post_load(void *opaque, int version_id) ICSState *ics = opaque; if (kvm_irqchip_in_kernel()) { - return ics_set_kvm_state(ics); + Error *local_err = NULL; + int ret; + + ret = ics_set_kvm_state(ics, &local_err); + if (ret < 0) { + error_report_err(local_err); + return ret; + } } return 0; @@ -765,8 +790,13 @@ void ics_set_irq_type(ICSState *ics, int srcno, bool lsi) lsi ? XICS_FLAGS_IRQ_LSI : XICS_FLAGS_IRQ_MSI; if (kvm_irqchip_in_kernel()) { + Error *local_err = NULL; + ics_reset_irq(ics->irqs + srcno); - ics_set_kvm_state_one(ics, srcno); + ics_set_kvm_state_one(ics, srcno, &local_err); + if (local_err) { + error_report_err(local_err); + } } } diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c index 5ba5b77561..51433b19b0 100644 --- a/hw/intc/xics_kvm.c +++ b/hw/intc/xics_kvm.c @@ -106,7 +106,7 @@ void icp_synchronize_state(ICPState *icp) } } -int icp_set_kvm_state(ICPState *icp) +int icp_set_kvm_state(ICPState *icp, Error **errp) { uint64_t state; int ret; @@ -126,10 +126,11 @@ int icp_set_kvm_state(ICPState *icp) | ((uint64_t)icp->pending_priority << KVM_REG_PPC_ICP_PPRI_SHIFT); ret = kvm_set_one_reg(icp->cs, KVM_REG_PPC_ICP_STATE, &state); - if (ret != 0) { - error_report("Unable to restore KVM interrupt controller state (0x%" - PRIx64 ") for CPU %ld: %s", state, kvm_arch_vcpu_id(icp->cs), - strerror(errno)); + if (ret < 0) { + error_setg_errno(errp, -ret, + "Unable to restore KVM interrupt controller state (0x%" + PRIx64 ") for CPU %ld", state, + kvm_arch_vcpu_id(icp->cs)); return ret; } @@ -240,10 +241,9 @@ void ics_synchronize_state(ICSState *ics) ics_get_kvm_state(ics); } -int ics_set_kvm_state_one(ICSState *ics, int srcno) +int ics_set_kvm_state_one(ICSState *ics, int srcno, Error **errp) { uint64_t state; - Error *local_err = NULL; ICSIRQState *irq = &ics->irqs[srcno]; int ret; @@ -278,16 +278,15 @@ int ics_set_kvm_state_one(ICSState *ics, int srcno) } ret = kvm_device_access(kernel_xics_fd, KVM_DEV_XICS_GRP_SOURCES, - srcno + ics->offset, &state, true, &local_err); - if (local_err) { - error_report_err(local_err); + srcno + ics->offset, &state, true, errp); + if (ret < 0) { return ret; } return 0; } -int ics_set_kvm_state(ICSState *ics) +int ics_set_kvm_state(ICSState *ics, Error **errp) { int i; @@ -297,10 +296,12 @@ int ics_set_kvm_state(ICSState *ics) } for (i = 0; i < ics->nr_irqs; i++) { + Error *local_err = NULL; int ret; - ret = ics_set_kvm_state_one(ics, i); - if (ret) { + ret = ics_set_kvm_state_one(ics, i, &local_err); + if (ret < 0) { + error_propagate(errp, local_err); return ret; } } @@ -331,16 +332,7 @@ void ics_kvm_set_irq(ICSState *ics, int srcno, int val) } } -static void rtas_dummy(PowerPCCPU *cpu, SpaprMachineState *spapr, - uint32_t token, - uint32_t nargs, target_ulong args, - uint32_t nret, target_ulong rets) -{ - error_report("pseries: %s must never be called for in-kernel XICS", - __func__); -} - -int xics_kvm_init(SpaprMachineState *spapr, Error **errp) +int xics_kvm_connect(SpaprMachineState *spapr, Error **errp) { int rc; CPUState *cs; @@ -357,42 +349,41 @@ int xics_kvm_init(SpaprMachineState *spapr, Error **errp) if (!kvm_enabled() || !kvm_check_extension(kvm_state, KVM_CAP_IRQ_XICS)) { error_setg(errp, "KVM and IRQ_XICS capability must be present for in-kernel XICS"); - goto fail; + return -1; } - spapr_rtas_register(RTAS_IBM_SET_XIVE, "ibm,set-xive", rtas_dummy); - spapr_rtas_register(RTAS_IBM_GET_XIVE, "ibm,get-xive", rtas_dummy); - spapr_rtas_register(RTAS_IBM_INT_OFF, "ibm,int-off", rtas_dummy); - spapr_rtas_register(RTAS_IBM_INT_ON, "ibm,int-on", rtas_dummy); - rc = kvmppc_define_rtas_kernel_token(RTAS_IBM_SET_XIVE, "ibm,set-xive"); if (rc < 0) { - error_setg(errp, "kvmppc_define_rtas_kernel_token: ibm,set-xive"); + error_setg_errno(&local_err, -rc, + "kvmppc_define_rtas_kernel_token: ibm,set-xive"); goto fail; } rc = kvmppc_define_rtas_kernel_token(RTAS_IBM_GET_XIVE, "ibm,get-xive"); if (rc < 0) { - error_setg(errp, "kvmppc_define_rtas_kernel_token: ibm,get-xive"); + error_setg_errno(&local_err, -rc, + "kvmppc_define_rtas_kernel_token: ibm,get-xive"); goto fail; } rc = kvmppc_define_rtas_kernel_token(RTAS_IBM_INT_ON, "ibm,int-on"); if (rc < 0) { - error_setg(errp, "kvmppc_define_rtas_kernel_token: ibm,int-on"); + error_setg_errno(&local_err, -rc, + "kvmppc_define_rtas_kernel_token: ibm,int-on"); goto fail; } rc = kvmppc_define_rtas_kernel_token(RTAS_IBM_INT_OFF, "ibm,int-off"); if (rc < 0) { - error_setg(errp, "kvmppc_define_rtas_kernel_token: ibm,int-off"); + error_setg_errno(&local_err, -rc, + "kvmppc_define_rtas_kernel_token: ibm,int-off"); goto fail; } /* Create the KVM XICS device */ rc = kvm_create_device(kvm_state, KVM_DEV_TYPE_XICS, false); if (rc < 0) { - error_setg_errno(errp, -rc, "Error on KVM_CREATE_DEVICE for XICS"); + error_setg_errno(&local_err, -rc, "Error on KVM_CREATE_DEVICE for XICS"); goto fail; } @@ -407,27 +398,30 @@ int xics_kvm_init(SpaprMachineState *spapr, Error **errp) icp_kvm_realize(DEVICE(spapr_cpu_state(cpu)->icp), &local_err); if (local_err) { - error_propagate(errp, local_err); goto fail; } } /* Update the KVM sources */ - ics_set_kvm_state(spapr->ics); + ics_set_kvm_state(spapr->ics, &local_err); + if (local_err) { + goto fail; + } /* Connect the presenters to the initial VCPUs of the machine */ CPU_FOREACH(cs) { PowerPCCPU *cpu = POWERPC_CPU(cs); - icp_set_kvm_state(spapr_cpu_state(cpu)->icp); + icp_set_kvm_state(spapr_cpu_state(cpu)->icp, &local_err); + if (local_err) { + goto fail; + } } return 0; fail: - kvmppc_define_rtas_kernel_token(0, "ibm,set-xive"); - kvmppc_define_rtas_kernel_token(0, "ibm,get-xive"); - kvmppc_define_rtas_kernel_token(0, "ibm,int-on"); - kvmppc_define_rtas_kernel_token(0, "ibm,int-off"); + error_propagate(errp, local_err); + xics_kvm_disconnect(spapr, NULL); return -1; } @@ -451,13 +445,10 @@ void xics_kvm_disconnect(SpaprMachineState *spapr, Error **errp) * removed from the list of devices of the VM. The VCPU presenters * are also detached from the device. */ - close(kernel_xics_fd); - kernel_xics_fd = -1; - - spapr_rtas_unregister(RTAS_IBM_SET_XIVE); - spapr_rtas_unregister(RTAS_IBM_GET_XIVE); - spapr_rtas_unregister(RTAS_IBM_INT_OFF); - spapr_rtas_unregister(RTAS_IBM_INT_ON); + if (kernel_xics_fd != -1) { + close(kernel_xics_fd); + kernel_xics_fd = -1; + } kvmppc_define_rtas_kernel_token(0, "ibm,set-xive"); kvmppc_define_rtas_kernel_token(0, "ibm,get-xive"); @@ -471,3 +462,33 @@ void xics_kvm_disconnect(SpaprMachineState *spapr, Error **errp) /* Clear the presenter from the VCPUs */ kvm_disable_icps(); } + +/* + * This is a heuristic to detect older KVMs on POWER9 hosts that don't + * support destruction of a KVM XICS device while the VM is running. + * Required to start a spapr machine with ic-mode=dual,kernel-irqchip=on. + */ +bool xics_kvm_has_broken_disconnect(SpaprMachineState *spapr) +{ + int rc; + + rc = kvm_create_device(kvm_state, KVM_DEV_TYPE_XICS, false); + if (rc < 0) { + /* + * The error is ignored on purpose. The KVM XICS setup code + * will catch it again anyway. The goal here is to see if + * close() actually destroys the device or not. + */ + return false; + } + + close(rc); + + rc = kvm_create_device(kvm_state, KVM_DEV_TYPE_XICS, false); + if (rc >= 0) { + close(rc); + return false; + } + + return errno == EEXIST; +} diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c index 5a1835e8b1..7cd3c93d71 100644 --- a/hw/intc/xics_spapr.c +++ b/hw/intc/xics_spapr.c @@ -41,11 +41,32 @@ * Guest interfaces */ +static bool check_emulated_xics(SpaprMachineState *spapr, const char *func) +{ + if (spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT) || + kvm_irqchip_in_kernel()) { + error_report("pseries: %s must only be called for emulated XICS", + func); + return false; + } + + return true; +} + +#define CHECK_EMULATED_XICS_HCALL(spapr) \ + do { \ + if (!check_emulated_xics((spapr), __func__)) { \ + return H_HARDWARE; \ + } \ + } while (0) + static target_ulong h_cppr(PowerPCCPU *cpu, SpaprMachineState *spapr, target_ulong opcode, target_ulong *args) { target_ulong cppr = args[0]; + CHECK_EMULATED_XICS_HCALL(spapr); + icp_set_cppr(spapr_cpu_state(cpu)->icp, cppr); return H_SUCCESS; } @@ -56,6 +77,8 @@ static target_ulong h_ipi(PowerPCCPU *cpu, SpaprMachineState *spapr, target_ulong mfrr = args[1]; ICPState *icp = xics_icp_get(XICS_FABRIC(spapr), args[0]); + CHECK_EMULATED_XICS_HCALL(spapr); + if (!icp) { return H_PARAMETER; } @@ -69,6 +92,8 @@ static target_ulong h_xirr(PowerPCCPU *cpu, SpaprMachineState *spapr, { uint32_t xirr = icp_accept(spapr_cpu_state(cpu)->icp); + CHECK_EMULATED_XICS_HCALL(spapr); + args[0] = xirr; return H_SUCCESS; } @@ -78,6 +103,8 @@ static target_ulong h_xirr_x(PowerPCCPU *cpu, SpaprMachineState *spapr, { uint32_t xirr = icp_accept(spapr_cpu_state(cpu)->icp); + CHECK_EMULATED_XICS_HCALL(spapr); + args[0] = xirr; args[1] = cpu_get_host_ticks(); return H_SUCCESS; @@ -88,6 +115,8 @@ static target_ulong h_eoi(PowerPCCPU *cpu, SpaprMachineState *spapr, { target_ulong xirr = args[0]; + CHECK_EMULATED_XICS_HCALL(spapr); + icp_eoi(spapr_cpu_state(cpu)->icp, xirr); return H_SUCCESS; } @@ -99,6 +128,8 @@ static target_ulong h_ipoll(PowerPCCPU *cpu, SpaprMachineState *spapr, uint32_t mfrr; uint32_t xirr; + CHECK_EMULATED_XICS_HCALL(spapr); + if (!icp) { return H_PARAMETER; } @@ -111,6 +142,14 @@ static target_ulong h_ipoll(PowerPCCPU *cpu, SpaprMachineState *spapr, return H_SUCCESS; } +#define CHECK_EMULATED_XICS_RTAS(spapr, rets) \ + do { \ + if (!check_emulated_xics((spapr), __func__)) { \ + rtas_st((rets), 0, RTAS_OUT_HW_ERROR); \ + return; \ + } \ + } while (0) + static void rtas_set_xive(PowerPCCPU *cpu, SpaprMachineState *spapr, uint32_t token, uint32_t nargs, target_ulong args, @@ -119,6 +158,8 @@ static void rtas_set_xive(PowerPCCPU *cpu, SpaprMachineState *spapr, ICSState *ics = spapr->ics; uint32_t nr, srcno, server, priority; + CHECK_EMULATED_XICS_RTAS(spapr, rets); + if ((nargs != 3) || (nret != 1)) { rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); return; @@ -152,6 +193,8 @@ static void rtas_get_xive(PowerPCCPU *cpu, SpaprMachineState *spapr, ICSState *ics = spapr->ics; uint32_t nr, srcno; + CHECK_EMULATED_XICS_RTAS(spapr, rets); + if ((nargs != 1) || (nret != 3)) { rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); return; @@ -182,6 +225,8 @@ static void rtas_int_off(PowerPCCPU *cpu, SpaprMachineState *spapr, ICSState *ics = spapr->ics; uint32_t nr, srcno; + CHECK_EMULATED_XICS_RTAS(spapr, rets); + if ((nargs != 1) || (nret != 1)) { rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); return; @@ -213,6 +258,8 @@ static void rtas_int_on(PowerPCCPU *cpu, SpaprMachineState *spapr, ICSState *ics = spapr->ics; uint32_t nr, srcno; + CHECK_EMULATED_XICS_RTAS(spapr, rets); + if ((nargs != 1) || (nret != 1)) { rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); return; @@ -239,14 +286,6 @@ static void rtas_int_on(PowerPCCPU *cpu, SpaprMachineState *spapr, void xics_spapr_init(SpaprMachineState *spapr) { - /* Emulated mode can only be initialized once. */ - if (spapr->ics->init) { - return; - } - - spapr->ics->init = true; - - /* Registration of global state belongs into realize */ spapr_rtas_register(RTAS_IBM_SET_XIVE, "ibm,set-xive", rtas_set_xive); spapr_rtas_register(RTAS_IBM_GET_XIVE, "ibm,get-xive", rtas_get_xive); spapr_rtas_register(RTAS_IBM_INT_OFF, "ibm,int-off", rtas_int_off); diff --git a/hw/intc/xive.c b/hw/intc/xive.c index 6250c0414d..cf77bdb7d3 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -132,6 +132,11 @@ static void xive_tctx_set_cppr(XiveTCTX *tctx, uint8_t ring, uint8_t cppr) xive_tctx_notify(tctx, ring); } +static inline uint32_t xive_tctx_word2(uint8_t *ring) +{ + return *((uint32_t *) &ring[TM_WORD2]); +} + /* * XIVE Thread Interrupt Management Area (TIMA) */ @@ -150,11 +155,12 @@ static uint64_t xive_tm_ack_hv_reg(XiveTCTX *tctx, hwaddr offset, unsigned size) static uint64_t xive_tm_pull_pool_ctx(XiveTCTX *tctx, hwaddr offset, unsigned size) { - uint64_t ret; + uint32_t qw2w2_prev = xive_tctx_word2(&tctx->regs[TM_QW2_HV_POOL]); + uint32_t qw2w2; - ret = tctx->regs[TM_QW2_HV_POOL + TM_WORD2] & TM_QW2W2_POOL_CAM; - tctx->regs[TM_QW2_HV_POOL + TM_WORD2] &= ~TM_QW2W2_POOL_CAM; - return ret; + qw2w2 = xive_set_field32(TM_QW2W2_VP, qw2w2_prev, 0); + memcpy(&tctx->regs[TM_QW2_HV_POOL + TM_WORD2], &qw2w2, 4); + return qw2w2; } static void xive_tm_vt_push(XiveTCTX *tctx, hwaddr offset, @@ -182,31 +188,31 @@ static uint64_t xive_tm_vt_poll(XiveTCTX *tctx, hwaddr offset, unsigned size) */ static const uint8_t xive_tm_hw_view[] = { - /* QW-0 User */ 3, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, - /* QW-1 OS */ 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 0, 0, 0, 0, - /* QW-2 POOL */ 0, 0, 3, 3, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, - /* QW-3 PHYS */ 3, 3, 3, 3, 0, 3, 0, 3, 3, 0, 0, 3, 3, 3, 3, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, /* QW-0 User */ + 3, 3, 3, 3, 3, 3, 0, 2, 3, 3, 3, 3, 0, 0, 0, 0, /* QW-1 OS */ + 0, 0, 3, 3, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, /* QW-2 POOL */ + 3, 3, 3, 3, 0, 3, 0, 2, 3, 0, 0, 3, 3, 3, 3, 0, /* QW-3 PHYS */ }; static const uint8_t xive_tm_hv_view[] = { - /* QW-0 User */ 3, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, - /* QW-1 OS */ 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 0, 0, 0, 0, - /* QW-2 POOL */ 0, 0, 3, 3, 0, 0, 0, 0, 0, 3, 3, 3, 0, 0, 0, 0, - /* QW-3 PHYS */ 3, 3, 3, 3, 0, 3, 0, 3, 3, 0, 0, 3, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, /* QW-0 User */ + 3, 3, 3, 3, 3, 3, 0, 2, 3, 3, 3, 3, 0, 0, 0, 0, /* QW-1 OS */ + 0, 0, 3, 3, 0, 0, 0, 0, 0, 3, 3, 3, 0, 0, 0, 0, /* QW-2 POOL */ + 3, 3, 3, 3, 0, 3, 0, 2, 3, 0, 0, 3, 0, 0, 0, 0, /* QW-3 PHYS */ }; static const uint8_t xive_tm_os_view[] = { - /* QW-0 User */ 3, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, - /* QW-1 OS */ 2, 3, 2, 2, 2, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, - /* QW-2 POOL */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* QW-3 PHYS */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, /* QW-0 User */ + 2, 3, 2, 2, 2, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, /* QW-1 OS */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* QW-2 POOL */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* QW-3 PHYS */ }; static const uint8_t xive_tm_user_view[] = { - /* QW-0 User */ 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* QW-1 OS */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* QW-2 POOL */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* QW-3 PHYS */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* QW-0 User */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* QW-1 OS */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* QW-2 POOL */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* QW-3 PHYS */ }; /* @@ -484,11 +490,6 @@ const MemoryRegionOps xive_tm_ops = { }, }; -static inline uint32_t xive_tctx_word2(uint8_t *ring) -{ - return *((uint32_t *) &ring[TM_WORD2]); -} - static char *xive_tctx_ring_print(uint8_t *ring) { uint32_t w2 = xive_tctx_word2(ring); @@ -1229,27 +1230,16 @@ XiveTCTX *xive_router_get_tctx(XiveRouter *xrtr, CPUState *cs) } /* - * By default on P9, the HW CAM line (23bits) is hardwired to : - * - * 0x000||0b1||4Bit chip number||7Bit Thread number. + * Encode the HW CAM line in the block group mode format : * - * When the block grouping is enabled, the CAM line is changed to : - * - * 4Bit chip number||0x001||7Bit Thread number. + * chip << 19 | 0000000 0 0001 thread (7Bit) */ -static uint32_t hw_cam_line(uint8_t chip_id, uint8_t tid) -{ - return 1 << 11 | (chip_id & 0xf) << 7 | (tid & 0x7f); -} - -static bool xive_presenter_tctx_match_hw(XiveTCTX *tctx, - uint8_t nvt_blk, uint32_t nvt_idx) +static uint32_t xive_tctx_hw_cam_line(XiveTCTX *tctx) { CPUPPCState *env = &POWERPC_CPU(tctx->cs)->env; uint32_t pir = env->spr_cb[SPR_PIR].default_value; - return hw_cam_line((pir >> 8) & 0xf, pir & 0x7f) == - hw_cam_line(nvt_blk, nvt_idx); + return xive_nvt_cam_line((pir >> 8) & 0xf, 1 << 7 | (pir & 0x7f)); } /* @@ -1285,7 +1275,7 @@ static int xive_presenter_tctx_match(XiveTCTX *tctx, uint8_t format, /* PHYS ring */ if ((be32_to_cpu(qw3w2) & TM_QW3W2_VT) && - xive_presenter_tctx_match_hw(tctx, nvt_blk, nvt_idx)) { + cam == xive_tctx_hw_cam_line(tctx)) { return TM_QW3_HV_PHYS; } diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig index cdc07e59b6..62aa01b29e 100644 --- a/hw/mips/Kconfig +++ b/hw/mips/Kconfig @@ -1,14 +1,44 @@ config R4K bool + select ISA_BUS + select SERIAL_ISA + select I8259 + select I8254 + select MC146818RTC + imply VGA_ISA + imply NE2000_ISA + select IDE_ISA + select PCKBD + select PFLASH_CFI01 config MALTA bool config MIPSSIM bool + select ISA_BUS + select SERIAL_ISA + select MIPSNET config JAZZ bool + select ISA_BUS + select RC4030 + select I8259 + select I8254 + select I8257 + select PCSPK + select VGA_ISA_MM + select G364FB + select DP8393X + select ESP + select FDC + select MC146818RTC + select PCKBD + select SERIAL + select PARALLEL + select DS1225Y + select JAZZ_LED config FULONG bool diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index 77b9df9796..e9aab519a1 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -74,6 +74,7 @@ obj-$(CONFIG_ARMSSE_MHU) += armsse-mhu.o obj-$(CONFIG_PVPANIC) += pvpanic.o obj-$(CONFIG_AUX) += auxbus.o +obj-$(CONFIG_ASPEED_SOC) += aspeed_xdma.o obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o obj-$(CONFIG_MSF2) += msf2-sysreg.o obj-$(CONFIG_NRF51_SOC) += nrf51_rng.o diff --git a/hw/misc/aspeed_xdma.c b/hw/misc/aspeed_xdma.c new file mode 100644 index 0000000000..eebd4ad540 --- /dev/null +++ b/hw/misc/aspeed_xdma.c @@ -0,0 +1,165 @@ +/* + * ASPEED XDMA Controller + * Eddie James <eajames@linux.ibm.com> + * + * Copyright (C) 2019 IBM Corp + * SPDX-License-Identifer: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "hw/misc/aspeed_xdma.h" +#include "qapi/error.h" + +#include "trace.h" + +#define XDMA_BMC_CMDQ_ADDR 0x10 +#define XDMA_BMC_CMDQ_ENDP 0x14 +#define XDMA_BMC_CMDQ_WRP 0x18 +#define XDMA_BMC_CMDQ_W_MASK 0x0003FFFF +#define XDMA_BMC_CMDQ_RDP 0x1C +#define XDMA_BMC_CMDQ_RDP_MAGIC 0xEE882266 +#define XDMA_IRQ_ENG_CTRL 0x20 +#define XDMA_IRQ_ENG_CTRL_US_COMP BIT(4) +#define XDMA_IRQ_ENG_CTRL_DS_COMP BIT(5) +#define XDMA_IRQ_ENG_CTRL_W_MASK 0xBFEFF07F +#define XDMA_IRQ_ENG_STAT 0x24 +#define XDMA_IRQ_ENG_STAT_US_COMP BIT(4) +#define XDMA_IRQ_ENG_STAT_DS_COMP BIT(5) +#define XDMA_IRQ_ENG_STAT_RESET 0xF8000000 +#define XDMA_MEM_SIZE 0x1000 + +#define TO_REG(addr) ((addr) / sizeof(uint32_t)) + +static uint64_t aspeed_xdma_read(void *opaque, hwaddr addr, unsigned int size) +{ + uint32_t val = 0; + AspeedXDMAState *xdma = opaque; + + if (addr < ASPEED_XDMA_REG_SIZE) { + val = xdma->regs[TO_REG(addr)]; + } + + return (uint64_t)val; +} + +static void aspeed_xdma_write(void *opaque, hwaddr addr, uint64_t val, + unsigned int size) +{ + unsigned int idx; + uint32_t val32 = (uint32_t)val; + AspeedXDMAState *xdma = opaque; + + if (addr >= ASPEED_XDMA_REG_SIZE) { + return; + } + + switch (addr) { + case XDMA_BMC_CMDQ_ENDP: + xdma->regs[TO_REG(addr)] = val32 & XDMA_BMC_CMDQ_W_MASK; + break; + case XDMA_BMC_CMDQ_WRP: + idx = TO_REG(addr); + xdma->regs[idx] = val32 & XDMA_BMC_CMDQ_W_MASK; + xdma->regs[TO_REG(XDMA_BMC_CMDQ_RDP)] = xdma->regs[idx]; + + trace_aspeed_xdma_write(addr, val); + + if (xdma->bmc_cmdq_readp_set) { + xdma->bmc_cmdq_readp_set = 0; + } else { + xdma->regs[TO_REG(XDMA_IRQ_ENG_STAT)] |= + XDMA_IRQ_ENG_STAT_US_COMP | XDMA_IRQ_ENG_STAT_DS_COMP; + + if (xdma->regs[TO_REG(XDMA_IRQ_ENG_CTRL)] & + (XDMA_IRQ_ENG_CTRL_US_COMP | XDMA_IRQ_ENG_CTRL_DS_COMP)) + qemu_irq_raise(xdma->irq); + } + break; + case XDMA_BMC_CMDQ_RDP: + trace_aspeed_xdma_write(addr, val); + + if (val32 == XDMA_BMC_CMDQ_RDP_MAGIC) { + xdma->bmc_cmdq_readp_set = 1; + } + break; + case XDMA_IRQ_ENG_CTRL: + xdma->regs[TO_REG(addr)] = val32 & XDMA_IRQ_ENG_CTRL_W_MASK; + break; + case XDMA_IRQ_ENG_STAT: + trace_aspeed_xdma_write(addr, val); + + idx = TO_REG(addr); + if (val32 & (XDMA_IRQ_ENG_STAT_US_COMP | XDMA_IRQ_ENG_STAT_DS_COMP)) { + xdma->regs[idx] &= + ~(XDMA_IRQ_ENG_STAT_US_COMP | XDMA_IRQ_ENG_STAT_DS_COMP); + qemu_irq_lower(xdma->irq); + } + break; + default: + xdma->regs[TO_REG(addr)] = val32; + break; + } +} + +static const MemoryRegionOps aspeed_xdma_ops = { + .read = aspeed_xdma_read, + .write = aspeed_xdma_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid.min_access_size = 4, + .valid.max_access_size = 4, +}; + +static void aspeed_xdma_realize(DeviceState *dev, Error **errp) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + AspeedXDMAState *xdma = ASPEED_XDMA(dev); + + sysbus_init_irq(sbd, &xdma->irq); + memory_region_init_io(&xdma->iomem, OBJECT(xdma), &aspeed_xdma_ops, xdma, + TYPE_ASPEED_XDMA, XDMA_MEM_SIZE); + sysbus_init_mmio(sbd, &xdma->iomem); +} + +static void aspeed_xdma_reset(DeviceState *dev) +{ + AspeedXDMAState *xdma = ASPEED_XDMA(dev); + + xdma->bmc_cmdq_readp_set = 0; + memset(xdma->regs, 0, ASPEED_XDMA_REG_SIZE); + xdma->regs[TO_REG(XDMA_IRQ_ENG_STAT)] = XDMA_IRQ_ENG_STAT_RESET; + + qemu_irq_lower(xdma->irq); +} + +static const VMStateDescription aspeed_xdma_vmstate = { + .name = TYPE_ASPEED_XDMA, + .version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32_ARRAY(regs, AspeedXDMAState, ASPEED_XDMA_NUM_REGS), + VMSTATE_END_OF_LIST(), + }, +}; + +static void aspeed_xdma_class_init(ObjectClass *classp, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(classp); + + dc->realize = aspeed_xdma_realize; + dc->reset = aspeed_xdma_reset; + dc->vmsd = &aspeed_xdma_vmstate; +} + +static const TypeInfo aspeed_xdma_info = { + .name = TYPE_ASPEED_XDMA, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(AspeedXDMAState), + .class_init = aspeed_xdma_class_init, +}; + +static void aspeed_xdma_register_type(void) +{ + type_register_static(&aspeed_xdma_info); +} +type_init(aspeed_xdma_register_type); diff --git a/hw/misc/trace-events b/hw/misc/trace-events index 47e1bccf71..c1ea1aa437 100644 --- a/hw/misc/trace-events +++ b/hw/misc/trace-events @@ -140,3 +140,6 @@ armsse_cpuid_write(uint64_t offset, uint64_t data, unsigned size) "SSE-200 CPU_I # armsse-mhu.c armsse_mhu_read(uint64_t offset, uint64_t data, unsigned size) "SSE-200 MHU read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" armsse_mhu_write(uint64_t offset, uint64_t data, unsigned size) "SSE-200 MHU write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" + +# aspeed_xdma.c +aspeed_xdma_write(uint64_t offset, uint64_t data) "XDMA write: offset 0x%" PRIx64 " data 0x%" PRIx64 diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c index eb760472e5..d2cded5e94 100644 --- a/hw/net/ftgmac100.c +++ b/hw/net/ftgmac100.c @@ -1017,8 +1017,6 @@ static void ftgmac100_realize(DeviceState *dev, Error **errp) sysbus_init_irq(sbd, &s->irq); qemu_macaddr_default_if_unset(&s->conf.macaddr); - s->conf.peers.ncs[0] = nd_table[0].netdev; - s->nic = qemu_new_nic(&net_ftgmac100_info, &s->conf, object_get_typename(OBJECT(dev)), DEVICE(dev)->id, s); diff --git a/hw/net/sunhme.c b/hw/net/sunhme.c index 1ebaee3c82..8b8603e696 100644 --- a/hw/net/sunhme.c +++ b/hw/net/sunhme.c @@ -44,6 +44,7 @@ #define HME_SEBI_STAT 0x100 #define HME_SEBI_STAT_LINUXBUG 0x108 #define HME_SEB_STAT_RXTOHOST 0x10000 +#define HME_SEB_STAT_NORXD 0x20000 #define HME_SEB_STAT_MIFIRQ 0x800000 #define HME_SEB_STAT_HOSTTOTX 0x1000000 #define HME_SEB_STAT_TXALL 0x2000000 @@ -209,6 +210,8 @@ static void sunhme_update_irq(SunHMEState *s) } level = (seb ? 1 : 0); + trace_sunhme_update_irq(mifmask, mif, sebmask, seb, level); + pci_set_irq(d, level); } @@ -371,10 +374,20 @@ static void sunhme_mac_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { SunHMEState *s = SUNHME(opaque); + uint64_t oldval = s->macregs[addr >> 2]; trace_sunhme_mac_write(addr, val); s->macregs[addr >> 2] = val; + + switch (addr) { + case HME_MACI_RXCFG: + if (!(oldval & HME_MAC_RXCFG_ENABLE) && + (val & HME_MAC_RXCFG_ENABLE)) { + qemu_flush_queued_packets(qemu_get_queue(s->nic)); + } + break; + } } static uint64_t sunhme_mac_read(void *opaque, hwaddr addr, @@ -647,7 +660,7 @@ static int sunhme_can_receive(NetClientState *nc) { SunHMEState *s = qemu_get_nic_opaque(nc); - return s->macregs[HME_MAC_RXCFG_ENABLE >> 2] & HME_MAC_RXCFG_ENABLE; + return s->macregs[HME_MACI_RXCFG >> 2] & HME_MAC_RXCFG_ENABLE; } static void sunhme_link_status_changed(NetClientState *nc) @@ -716,7 +729,7 @@ static ssize_t sunhme_receive(NetClientState *nc, const uint8_t *buf, /* Do nothing if MAC RX disabled */ if (!(s->macregs[HME_MACI_RXCFG >> 2] & HME_MAC_RXCFG_ENABLE)) { - return -1; + return 0; } trace_sunhme_rx_filter_destmac(buf[0], buf[1], buf[2], @@ -745,14 +758,14 @@ static ssize_t sunhme_receive(NetClientState *nc, const uint8_t *buf, /* Didn't match hash filter */ trace_sunhme_rx_filter_hash_nomatch(); trace_sunhme_rx_filter_reject(); - return 0; + return -1; } else { trace_sunhme_rx_filter_hash_match(); } } else { /* Not for us */ trace_sunhme_rx_filter_reject(); - return 0; + return -1; } } else { trace_sunhme_rx_filter_promisc_match(); @@ -775,6 +788,14 @@ static ssize_t sunhme_receive(NetClientState *nc, const uint8_t *buf, pci_dma_read(d, rb + cr * HME_DESC_SIZE, &status, 4); pci_dma_read(d, rb + cr * HME_DESC_SIZE + 4, &buffer, 4); + /* If we don't own the current descriptor then indicate overflow error */ + if (!(status & HME_XD_OWN)) { + s->sebregs[HME_SEBI_STAT >> 2] |= HME_SEB_STAT_NORXD; + sunhme_update_irq(s); + trace_sunhme_rx_norxd(); + return -1; + } + rxoffset = (s->erxregs[HME_ERXI_CFG >> 2] & HME_ERX_CFG_BYTEOFFSET) >> HME_ERX_CFG_BYTEOFFSET_SHIFT; diff --git a/hw/net/trace-events b/hw/net/trace-events index 3cd9e122df..58665655cc 100644 --- a/hw/net/trace-events +++ b/hw/net/trace-events @@ -359,6 +359,8 @@ sunhme_rx_filter_reject(void) "rejecting incoming frame" sunhme_rx_filter_accept(void) "accepting incoming frame" sunhme_rx_desc(uint32_t addr, int offset, uint32_t status, int len, int cr, int nr) "addr 0x%"PRIx32"(+0x%x) status 0x%"PRIx32 " len %d (ring %d/%d)" sunhme_rx_xsum_calc(uint16_t xsum) "calculated incoming xsum as 0x%x" +sunhme_rx_norxd(void) "no free rx descriptors available" +sunhme_update_irq(uint32_t mifmask, uint32_t mif, uint32_t sebmask, uint32_t seb, int level) "mifmask: 0x%x mif: 0x%x sebmask: 0x%x seb: 0x%x level: %d" # virtio-net.c virtio_net_announce_notify(void) "" diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index c3f5fccfd1..b9e1cd71cf 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -2360,7 +2360,7 @@ static int virtio_net_post_load_device(void *opaque, int version_id) timer_mod(n->announce_timer.tm, qemu_clock_get_ms(n->announce_timer.type)); } else { - qemu_announce_timer_del(&n->announce_timer); + qemu_announce_timer_del(&n->announce_timer, false); } } @@ -2784,7 +2784,7 @@ static void virtio_net_device_unrealize(DeviceState *dev, Error **errp) virtio_net_del_queue(n, i); } - qemu_announce_timer_del(&n->announce_timer); + qemu_announce_timer_del(&n->announce_timer, false); g_free(n->vqs); qemu_del_nic(n->nic); virtio_net_rsc_cleanup(n); diff --git a/hw/pci-host/designware.c b/hw/pci-host/designware.c index 0fdfff5784..9ae8c0deb7 100644 --- a/hw/pci-host/designware.c +++ b/hw/pci-host/designware.c @@ -51,6 +51,8 @@ #define DESIGNWARE_PCIE_ATU_DEVFN(x) (((x) >> 16) & 0xff) #define DESIGNWARE_PCIE_ATU_UPPER_TARGET 0x91C +#define DESIGNWARE_PCIE_IRQ_MSI 3 + static DesignwarePCIEHost * designware_pcie_root_to_host(DesignwarePCIERoot *root) { @@ -67,7 +69,7 @@ static void designware_pcie_root_msi_write(void *opaque, hwaddr addr, root->msi.intr[0].status |= BIT(val) & root->msi.intr[0].enable; if (root->msi.intr[0].status & ~root->msi.intr[0].mask) { - qemu_set_irq(host->pci.irqs[0], 1); + qemu_set_irq(host->pci.irqs[DESIGNWARE_PCIE_IRQ_MSI], 1); } } @@ -290,23 +292,19 @@ static void designware_pcie_root_config_write(PCIDevice *d, uint32_t address, case DESIGNWARE_PCIE_MSI_ADDR_LO: root->msi.base &= 0xFFFFFFFF00000000ULL; root->msi.base |= val; + designware_pcie_root_update_msi_mapping(root); break; case DESIGNWARE_PCIE_MSI_ADDR_HI: root->msi.base &= 0x00000000FFFFFFFFULL; root->msi.base |= (uint64_t)val << 32; + designware_pcie_root_update_msi_mapping(root); break; - case DESIGNWARE_PCIE_MSI_INTR0_ENABLE: { - const bool update_msi_mapping = !root->msi.intr[0].enable ^ !!val; - + case DESIGNWARE_PCIE_MSI_INTR0_ENABLE: root->msi.intr[0].enable = val; - - if (update_msi_mapping) { - designware_pcie_root_update_msi_mapping(root); - } + designware_pcie_root_update_msi_mapping(root); break; - } case DESIGNWARE_PCIE_MSI_INTR0_MASK: root->msi.intr[0].mask = val; @@ -315,7 +313,7 @@ static void designware_pcie_root_config_write(PCIDevice *d, uint32_t address, case DESIGNWARE_PCIE_MSI_INTR0_STATUS: root->msi.intr[0].status ^= val; if (!root->msi.intr[0].status) { - qemu_set_irq(host->pci.irqs[0], 0); + qemu_set_irq(host->pci.irqs[DESIGNWARE_PCIE_IRQ_MSI], 0); } break; diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index 4d835f32b5..c8d3245524 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -437,13 +437,11 @@ static void ppc_core99_init(MachineState *machine) } /* The NewWorld NVRAM is not located in the MacIO device */ -#ifdef CONFIG_KVM if (kvm_enabled() && getpagesize() > 4096) { /* We can't combine read-write and read-only in a single page, so move the NVRAM out of ROM again for KVM */ nvram_addr = 0xFFE00000; } -#endif dev = qdev_create(NULL, TYPE_MACIO_NVRAM); qdev_prop_set_uint32(dev, "size", 0x2000); qdev_prop_set_uint32(dev, "it_shift", 1); @@ -488,14 +486,12 @@ static void ppc_core99_init(MachineState *machine) fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_IS_KVM, kvm_enabled()); if (kvm_enabled()) { -#ifdef CONFIG_KVM uint8_t *hypercall; hypercall = g_malloc(16); kvmppc_get_hypercall(env, hypercall, 16); fw_cfg_add_bytes(fw_cfg, FW_CFG_PPC_KVM_HC, hypercall, 16); fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_KVM_PID, getpid()); -#endif } fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, tbfreq); /* Mac OS X requires a "known good" clock-frequency value; pass it one. */ diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index eddd005a7c..da751addc4 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -345,14 +345,12 @@ static void ppc_heathrow_init(MachineState *machine) fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_IS_KVM, kvm_enabled()); if (kvm_enabled()) { -#ifdef CONFIG_KVM uint8_t *hypercall; hypercall = g_malloc(16); kvmppc_get_hypercall(env, hypercall, 16); fw_cfg_add_bytes(fw_cfg, FW_CFG_PPC_KVM_HC, hypercall, 16); fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_KVM_PID, getpid()); -#endif } fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, tbfreq); /* Mac OS X requires a "known good" clock-frequency value; pass it one. */ diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 9db43916ac..b87e01e5b9 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -860,6 +860,14 @@ static void pnv_chip_power8_realize(DeviceState *dev, Error **errp) Pnv8Psi *psi8 = &chip8->psi; Error *local_err = NULL; + /* XSCOM bridge is first */ + pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip)); + pcc->parent_realize(dev, &local_err); if (local_err) { error_propagate(errp, local_err); @@ -916,7 +924,6 @@ static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data) k->isa_create = pnv_chip_power8_isa_create; k->dt_populate = pnv_chip_power8_dt_populate; k->pic_print_info = pnv_chip_power8_pic_print_info; - k->xscom_base = 0x003fc0000000000ull; dc->desc = "PowerNV Chip POWER8E"; device_class_set_parent_realize(dc, pnv_chip_power8_realize, @@ -936,7 +943,6 @@ static void pnv_chip_power8_class_init(ObjectClass *klass, void *data) k->isa_create = pnv_chip_power8_isa_create; k->dt_populate = pnv_chip_power8_dt_populate; k->pic_print_info = pnv_chip_power8_pic_print_info; - k->xscom_base = 0x003fc0000000000ull; dc->desc = "PowerNV Chip POWER8"; device_class_set_parent_realize(dc, pnv_chip_power8_realize, @@ -956,7 +962,6 @@ static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data) k->isa_create = pnv_chip_power8nvl_isa_create; k->dt_populate = pnv_chip_power8_dt_populate; k->pic_print_info = pnv_chip_power8_pic_print_info; - k->xscom_base = 0x003fc0000000000ull; dc->desc = "PowerNV Chip POWER8NVL"; device_class_set_parent_realize(dc, pnv_chip_power8_realize, @@ -1024,6 +1029,14 @@ static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) Pnv9Psi *psi9 = &chip9->psi; Error *local_err = NULL; + /* XSCOM bridge is first */ + pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip)); + pcc->parent_realize(dev, &local_err); if (local_err) { error_propagate(errp, local_err); @@ -1099,7 +1112,6 @@ static void pnv_chip_power9_class_init(ObjectClass *klass, void *data) k->isa_create = pnv_chip_power9_isa_create; k->dt_populate = pnv_chip_power9_dt_populate; k->pic_print_info = pnv_chip_power9_pic_print_info; - k->xscom_base = 0x00603fc00000000ull; dc->desc = "PowerNV Chip POWER9"; device_class_set_parent_realize(dc, pnv_chip_power9_realize, @@ -1136,11 +1148,6 @@ static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp) } } -static void pnv_chip_instance_init(Object *obj) -{ - PNV_CHIP(obj)->xscom_base = PNV_CHIP_GET_CLASS(obj)->xscom_base; -} - static void pnv_chip_core_realize(PnvChip *chip, Error **errp) { Error *error = NULL; @@ -1206,14 +1213,6 @@ static void pnv_chip_realize(DeviceState *dev, Error **errp) PnvChip *chip = PNV_CHIP(dev); Error *error = NULL; - /* XSCOM bridge */ - pnv_xscom_realize(chip, &error); - if (error) { - error_propagate(errp, error); - return; - } - sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip)); - /* Cores */ pnv_chip_core_realize(chip, &error); if (error) { @@ -1398,7 +1397,6 @@ static const TypeInfo types[] = { .name = TYPE_PNV_CHIP, .parent = TYPE_SYS_BUS_DEVICE, .class_init = pnv_chip_class_init, - .instance_init = pnv_chip_instance_init, .instance_size = sizeof(PnvChip), .class_size = sizeof(PnvChipClass), .abstract = true, diff --git a/hw/ppc/pnv_xscom.c b/hw/ppc/pnv_xscom.c index 4e52885c9e..2b81c75f56 100644 --- a/hw/ppc/pnv_xscom.c +++ b/hw/ppc/pnv_xscom.c @@ -213,17 +213,17 @@ const MemoryRegionOps pnv_xscom_ops = { .endianness = DEVICE_BIG_ENDIAN, }; -void pnv_xscom_realize(PnvChip *chip, Error **errp) +void pnv_xscom_realize(PnvChip *chip, uint64_t size, Error **errp) { SysBusDevice *sbd = SYS_BUS_DEVICE(chip); char *name; name = g_strdup_printf("xscom-%x", chip->chip_id); memory_region_init_io(&chip->xscom_mmio, OBJECT(chip), &pnv_xscom_ops, - chip, name, PNV_XSCOM_SIZE); + chip, name, size); sysbus_init_mmio(sbd, &chip->xscom_mmio); - memory_region_init(&chip->xscom, OBJECT(chip), name, PNV_XSCOM_SIZE); + memory_region_init(&chip->xscom, OBJECT(chip), name, size); address_space_init(&chip->xscom_as, &chip->xscom, name); g_free(name); } @@ -265,12 +265,19 @@ static const char compat_p9[] = "ibm,power9-xscom\0ibm,xscom"; int pnv_dt_xscom(PnvChip *chip, void *fdt, int root_offset) { - uint64_t reg[] = { cpu_to_be64(PNV_XSCOM_BASE(chip)), - cpu_to_be64(PNV_XSCOM_SIZE) }; + uint64_t reg[2]; int xscom_offset; ForeachPopulateArgs args; char *name; + if (pnv_chip_is_power9(chip)) { + reg[0] = cpu_to_be64(PNV9_XSCOM_BASE(chip)); + reg[1] = cpu_to_be64(PNV9_XSCOM_SIZE); + } else { + reg[0] = cpu_to_be64(PNV_XSCOM_BASE(chip)); + reg[1] = cpu_to_be64(PNV_XSCOM_SIZE); + } + name = g_strdup_printf("xscom@%" PRIx64, be64_to_cpu(reg[0])); xscom_offset = fdt_add_subnode(fdt, root_offset, name); _FDT(xscom_offset); diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c index 9d91e8481b..a9e508c496 100644 --- a/hw/ppc/ppc.c +++ b/hw/ppc/ppc.c @@ -80,9 +80,7 @@ void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level) } if (old_pending != env->pending_interrupts) { -#ifdef CONFIG_KVM kvmppc_set_interrupt(cpu, n_IRQ, level); -#endif } @@ -1036,10 +1034,7 @@ static void timebase_load(PPCTimebase *tb) CPU_FOREACH(cpu) { PowerPCCPU *pcpu = POWERPC_CPU(cpu); pcpu->env.tb_env->tb_offset = tb_off_adj; -#if defined(CONFIG_KVM) - kvm_set_one_reg(cpu, KVM_REG_PPC_TB_OFFSET, - &pcpu->env.tb_env->tb_offset); -#endif + kvmppc_set_reg_tb_offset(pcpu, pcpu->env.tb_env->tb_offset); } } diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c index 2a8009e20b..a248ce480d 100644 --- a/hw/ppc/prep.c +++ b/hw/ppc/prep.c @@ -780,7 +780,6 @@ static void ibm_40p_init(MachineState *machine) fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_IS_KVM, kvm_enabled()); if (kvm_enabled()) { -#ifdef CONFIG_KVM uint8_t *hypercall; fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, kvmppc_get_tbfreq()); @@ -788,7 +787,6 @@ static void ibm_40p_init(MachineState *machine) kvmppc_get_hypercall(env, hypercall, 16); fw_cfg_add_bytes(fw_cfg, FW_CFG_PPC_KVM_HC, hypercall, 16); fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_KVM_PID, getpid()); -#endif } else { fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, NANOSECONDS_PER_SECOND); } diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c index 3156daf093..ff3df0bbd8 100644 --- a/hw/ppc/spapr_irq.c +++ b/hw/ppc/spapr_irq.c @@ -62,7 +62,7 @@ void spapr_irq_msi_reset(SpaprMachineState *spapr) bitmap_clear(spapr->irq_map, 0, spapr->irq_map_nr); } -static void spapr_irq_init_device(SpaprMachineState *spapr, +static void spapr_irq_init_kvm(SpaprMachineState *spapr, SpaprIrq *irq, Error **errp) { MachineState *machine = MACHINE(spapr); @@ -88,8 +88,6 @@ static void spapr_irq_init_device(SpaprMachineState *spapr, error_prepend(&local_err, "kernel_irqchip allowed but unavailable: "); warn_report_err(local_err); } - - irq->init_emu(spapr, errp); } /* @@ -114,6 +112,8 @@ static void spapr_irq_init_xics(SpaprMachineState *spapr, int nr_irqs, } spapr->ics = ICS_BASE(obj); + + xics_spapr_init(spapr); } #define ICS_IRQ_FREE(ics, srcno) \ @@ -222,7 +222,7 @@ static void spapr_irq_reset_xics(SpaprMachineState *spapr, Error **errp) { Error *local_err = NULL; - spapr_irq_init_device(spapr, &spapr_irq_xics, &local_err); + spapr_irq_init_kvm(spapr, &spapr_irq_xics, &local_err); if (local_err) { error_propagate(errp, local_err); return; @@ -234,15 +234,10 @@ static const char *spapr_irq_get_nodename_xics(SpaprMachineState *spapr) return XICS_NODENAME; } -static void spapr_irq_init_emu_xics(SpaprMachineState *spapr, Error **errp) -{ - xics_spapr_init(spapr); -} - static void spapr_irq_init_kvm_xics(SpaprMachineState *spapr, Error **errp) { if (kvm_enabled()) { - xics_kvm_init(spapr, errp); + xics_kvm_connect(spapr, errp); } } @@ -266,7 +261,6 @@ SpaprIrq spapr_irq_xics = { .reset = spapr_irq_reset_xics, .set_irq = spapr_irq_set_irq_xics, .get_nodename = spapr_irq_get_nodename_xics, - .init_emu = spapr_irq_init_emu_xics, .init_kvm = spapr_irq_init_kvm_xics, }; @@ -384,7 +378,7 @@ static void spapr_irq_reset_xive(SpaprMachineState *spapr, Error **errp) spapr_xive_set_tctx_os_cam(spapr_cpu_state(cpu)->tctx); } - spapr_irq_init_device(spapr, &spapr_irq_xive, &local_err); + spapr_irq_init_kvm(spapr, &spapr_irq_xive, &local_err); if (local_err) { error_propagate(errp, local_err); return; @@ -410,11 +404,6 @@ static const char *spapr_irq_get_nodename_xive(SpaprMachineState *spapr) return spapr->xive->nodename; } -static void spapr_irq_init_emu_xive(SpaprMachineState *spapr, Error **errp) -{ - spapr_xive_init(spapr->xive, errp); -} - static void spapr_irq_init_kvm_xive(SpaprMachineState *spapr, Error **errp) { if (kvm_enabled()) { @@ -446,7 +435,6 @@ SpaprIrq spapr_irq_xive = { .reset = spapr_irq_reset_xive, .set_irq = spapr_irq_set_irq_xive, .get_nodename = spapr_irq_get_nodename_xive, - .init_emu = spapr_irq_init_emu_xive, .init_kvm = spapr_irq_init_kvm_xive, }; @@ -624,7 +612,6 @@ SpaprIrq spapr_irq_dual = { .reset = spapr_irq_reset_dual, .set_irq = spapr_irq_set_irq_dual, .get_nodename = spapr_irq_get_nodename_dual, - .init_emu = NULL, /* should not be used */ .init_kvm = NULL, /* should not be used */ }; @@ -668,6 +655,19 @@ static void spapr_irq_check(SpaprMachineState *spapr, Error **errp) return; } } + + /* + * On a POWER9 host, some older KVM XICS devices cannot be destroyed and + * re-created. Detect that early to avoid QEMU to exit later when the + * guest reboots. + */ + if (kvm_enabled() && + spapr->irq == &spapr_irq_dual && + machine_kernel_irqchip_required(machine) && + xics_kvm_has_broken_disconnect(spapr)) { + error_setg(errp, "KVM is too old to support ic-mode=dual,kernel-irqchip=on"); + return; + } } /* @@ -827,6 +827,5 @@ SpaprIrq spapr_irq_xics_legacy = { .reset = spapr_irq_reset_xics, .set_irq = spapr_irq_set_irq_xics, .get_nodename = spapr_irq_get_nodename_xics, - .init_emu = spapr_irq_init_emu_xics, .init_kvm = spapr_irq_init_kvm_xics, }; diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 957ae88bbd..9003fe9010 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1343,6 +1343,7 @@ static void spapr_dt_pci_device_cb(PCIBus *bus, PCIDevice *pdev, static int spapr_dt_pci_bus(SpaprPhbState *sphb, PCIBus *bus, void *fdt, int offset) { + Object *owner; PciWalkFdt cbinfo = { .fdt = fdt, .offset = offset, @@ -1356,15 +1357,20 @@ static int spapr_dt_pci_bus(SpaprPhbState *sphb, PCIBus *bus, _FDT(fdt_setprop_cell(fdt, offset, "#size-cells", RESOURCE_CELLS_SIZE)); - if (bus) { - pci_for_each_device_reverse(bus, pci_bus_num(bus), - spapr_dt_pci_device_cb, &cbinfo); - if (cbinfo.err) { - return cbinfo.err; - } + assert(bus); + pci_for_each_device_reverse(bus, pci_bus_num(bus), + spapr_dt_pci_device_cb, &cbinfo); + if (cbinfo.err) { + return cbinfo.err; } - ret = spapr_dt_drc(fdt, offset, OBJECT(bus->parent_dev), + if (pci_bus_is_root(bus)) { + owner = OBJECT(sphb); + } else { + owner = OBJECT(pci_bridge_get_device(bus)); + } + + ret = spapr_dt_drc(fdt, offset, owner, SPAPR_DR_CONNECTOR_TYPE_PCI); if (ret) { return ret; @@ -1782,6 +1788,12 @@ static void spapr_phb_unrealize(DeviceState *dev, Error **errp) memory_region_del_subregion(&sphb->iommu_root, &sphb->msiwindow); + /* + * An attached PCI device may have memory listeners, eg. VFIO PCI. We have + * unmapped all sections. Remove the listeners now, before destroying the + * address space. + */ + address_space_remove_listeners(&sphb->iommu_as); address_space_destroy(&sphb->iommu_as); qbus_set_hotplug_handler(BUS(phb->bus), NULL, &error_abort); @@ -1945,11 +1957,9 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) * For KVM we want to ensure that this memory is a full page so that * our memory slot is of page size granularity. */ -#ifdef CONFIG_KVM if (kvm_enabled()) { msi_window_size = getpagesize(); } -#endif memory_region_init_io(&sphb->msiwindow, OBJECT(sphb), &spapr_msi_ops, spapr, "msi", msi_window_size); diff --git a/hw/ppc/spapr_rtc.c b/hw/ppc/spapr_rtc.c index af1ef30a53..6cf0113b34 100644 --- a/hw/ppc/spapr_rtc.c +++ b/hw/ppc/spapr_rtc.c @@ -32,7 +32,7 @@ #include "sysemu/sysemu.h" #include "hw/ppc/spapr.h" #include "qapi/error.h" -#include "qapi/qapi-events-target.h" +#include "qapi/qapi-events-misc-target.h" #include "qemu/cutils.h" #include "qemu/module.h" diff --git a/hw/riscv/Makefile.objs b/hw/riscv/Makefile.objs index a65027304a..eb9d4f9ffc 100644 --- a/hw/riscv/Makefile.objs +++ b/hw/riscv/Makefile.objs @@ -1,3 +1,4 @@ +obj-y += boot.o obj-$(CONFIG_SPIKE) += riscv_htif.o obj-$(CONFIG_HART) += riscv_hart.o obj-$(CONFIG_SIFIVE_E) += sifive_e.o diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c new file mode 100644 index 0000000000..ff023f42d0 --- /dev/null +++ b/hw/riscv/boot.c @@ -0,0 +1,105 @@ +/* + * QEMU RISC-V Boot Helper + * + * Copyright (c) 2017 SiFive, Inc. + * Copyright (c) 2019 Alistair Francis <alistair.francis@wdc.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "qemu/osdep.h" +#include "qemu/units.h" +#include "qemu/error-report.h" +#include "exec/cpu-defs.h" +#include "hw/loader.h" +#include "hw/riscv/boot.h" +#include "hw/boards.h" +#include "elf.h" + +#if defined(TARGET_RISCV32) +# define KERNEL_BOOT_ADDRESS 0x80400000 +#else +# define KERNEL_BOOT_ADDRESS 0x80200000 +#endif + +target_ulong riscv_load_firmware(const char *firmware_filename, + hwaddr firmware_load_addr) +{ + uint64_t firmware_entry, firmware_start, firmware_end; + + if (load_elf(firmware_filename, NULL, NULL, NULL, &firmware_entry, + &firmware_start, &firmware_end, 0, EM_RISCV, 1, 0) > 0) { + return firmware_entry; + } + + if (load_image_targphys_as(firmware_filename, firmware_load_addr, + ram_size, NULL) > 0) { + return firmware_load_addr; + } + + error_report("could not load firmware '%s'", firmware_filename); + exit(1); +} + +target_ulong riscv_load_kernel(const char *kernel_filename) +{ + uint64_t kernel_entry, kernel_high; + + if (load_elf(kernel_filename, NULL, NULL, NULL, + &kernel_entry, NULL, &kernel_high, 0, EM_RISCV, 1, 0) > 0) { + return kernel_entry; + } + + if (load_uimage_as(kernel_filename, &kernel_entry, NULL, NULL, + NULL, NULL, NULL) > 0) { + return kernel_entry; + } + + if (load_image_targphys_as(kernel_filename, KERNEL_BOOT_ADDRESS, + ram_size, NULL) > 0) { + return KERNEL_BOOT_ADDRESS; + } + + error_report("could not load kernel '%s'", kernel_filename); + exit(1); +} + +hwaddr riscv_load_initrd(const char *filename, uint64_t mem_size, + uint64_t kernel_entry, hwaddr *start) +{ + int size; + + /* + * We want to put the initrd far enough into RAM that when the + * kernel is uncompressed it will not clobber the initrd. However + * on boards without much RAM we must ensure that we still leave + * enough room for a decent sized initrd, and on boards with large + * amounts of RAM we must avoid the initrd being so far up in RAM + * that it is outside lowmem and inaccessible to the kernel. + * So for boards with less than 256MB of RAM we put the initrd + * halfway into RAM, and for boards with 256MB of RAM or more we put + * the initrd at 128MB. + */ + *start = kernel_entry + MIN(mem_size / 2, 128 * MiB); + + size = load_ramdisk(filename, *start, mem_size - *start); + if (size == -1) { + size = load_image_targphys(filename, *start, mem_size - *start); + if (size == -1) { + error_report("could not load ramdisk '%s'", filename); + exit(1); + } + } + + return *start + size; +} diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c index 80ac56fa7d..d27f626529 100644 --- a/hw/riscv/sifive_e.c +++ b/hw/riscv/sifive_e.c @@ -44,10 +44,10 @@ #include "hw/riscv/sifive_prci.h" #include "hw/riscv/sifive_uart.h" #include "hw/riscv/sifive_e.h" +#include "hw/riscv/boot.h" #include "chardev/char.h" #include "sysemu/arch_init.h" #include "exec/address-spaces.h" -#include "elf.h" static const struct MemmapEntry { hwaddr base; @@ -74,19 +74,6 @@ static const struct MemmapEntry { [SIFIVE_E_DTIM] = { 0x80000000, 0x4000 } }; -static target_ulong load_kernel(const char *kernel_filename) -{ - uint64_t kernel_entry, kernel_high; - - if (load_elf(kernel_filename, NULL, NULL, NULL, - &kernel_entry, NULL, &kernel_high, - 0, EM_RISCV, 1, 0) < 0) { - error_report("could not load kernel '%s'", kernel_filename); - exit(1); - } - return kernel_entry; -} - static void sifive_mmio_emulate(MemoryRegion *parent, const char *name, uintptr_t offset, uintptr_t length) { @@ -131,7 +118,7 @@ static void riscv_sifive_e_init(MachineState *machine) memmap[SIFIVE_E_MROM].base, &address_space_memory); if (machine->kernel_filename) { - load_kernel(machine->kernel_filename); + riscv_load_kernel(machine->kernel_filename); } } @@ -158,17 +145,15 @@ static void riscv_sifive_e_soc_realize(DeviceState *dev, Error **errp) SiFiveESoCState *s = RISCV_E_SOC(dev); MemoryRegion *sys_mem = get_system_memory(); - MemoryRegion *xip_mem = g_new(MemoryRegion, 1); - MemoryRegion *mask_rom = g_new(MemoryRegion, 1); object_property_set_bool(OBJECT(&s->cpus), true, "realized", &error_abort); /* Mask ROM */ - memory_region_init_rom(mask_rom, NULL, "riscv.sifive.e.mrom", + memory_region_init_rom(&s->mask_rom, NULL, "riscv.sifive.e.mrom", memmap[SIFIVE_E_MROM].size, &error_fatal); memory_region_add_subregion(sys_mem, - memmap[SIFIVE_E_MROM].base, mask_rom); + memmap[SIFIVE_E_MROM].base, &s->mask_rom); /* MMIO */ s->plic = sifive_plic_create(memmap[SIFIVE_E_PLIC].base, @@ -228,10 +213,11 @@ static void riscv_sifive_e_soc_realize(DeviceState *dev, Error **errp) memmap[SIFIVE_E_PWM2].base, memmap[SIFIVE_E_PWM2].size); /* Flash memory */ - memory_region_init_ram(xip_mem, NULL, "riscv.sifive.e.xip", + memory_region_init_ram(&s->xip_mem, NULL, "riscv.sifive.e.xip", memmap[SIFIVE_E_XIP].size, &error_fatal); - memory_region_set_readonly(xip_mem, true); - memory_region_add_subregion(sys_mem, memmap[SIFIVE_E_XIP].base, xip_mem); + memory_region_set_readonly(&s->xip_mem, true); + memory_region_add_subregion(sys_mem, memmap[SIFIVE_E_XIP].base, + &s->xip_mem); } static void riscv_sifive_e_machine_init(MachineClass *mc) diff --git a/hw/riscv/sifive_prci.c b/hw/riscv/sifive_prci.c index fa136b5a9f..f406682c91 100644 --- a/hw/riscv/sifive_prci.c +++ b/hw/riscv/sifive_prci.c @@ -24,15 +24,18 @@ #include "target/riscv/cpu.h" #include "hw/riscv/sifive_prci.h" -/* currently implements enough to mock freedom-e-sdk BSP clock programming */ - static uint64_t sifive_prci_read(void *opaque, hwaddr addr, unsigned int size) { - if (addr == 0 /* PRCI_HFROSCCFG */) { - return 1 << 31; /* ROSC_RDY */ - } - if (addr == 8 /* PRCI_PLLCFG */) { - return 1 << 31; /* PLL_LOCK */ + SiFivePRCIState *s = opaque; + switch (addr) { + case SIFIVE_PRCI_HFROSCCFG: + return s->hfrosccfg; + case SIFIVE_PRCI_HFXOSCCFG: + return s->hfxosccfg; + case SIFIVE_PRCI_PLLCFG: + return s->pllcfg; + case SIFIVE_PRCI_PLLOUTDIV: + return s->plloutdiv; } hw_error("%s: read: addr=0x%x\n", __func__, (int)addr); return 0; @@ -41,7 +44,30 @@ static uint64_t sifive_prci_read(void *opaque, hwaddr addr, unsigned int size) static void sifive_prci_write(void *opaque, hwaddr addr, uint64_t val64, unsigned int size) { - /* discard writes */ + SiFivePRCIState *s = opaque; + switch (addr) { + case SIFIVE_PRCI_HFROSCCFG: + s->hfrosccfg = (uint32_t) val64; + /* OSC stays ready */ + s->hfrosccfg |= SIFIVE_PRCI_HFROSCCFG_RDY; + break; + case SIFIVE_PRCI_HFXOSCCFG: + s->hfxosccfg = (uint32_t) val64; + /* OSC stays ready */ + s->hfxosccfg |= SIFIVE_PRCI_HFXOSCCFG_RDY; + break; + case SIFIVE_PRCI_PLLCFG: + s->pllcfg = (uint32_t) val64; + /* PLL stays locked */ + s->pllcfg |= SIFIVE_PRCI_PLLCFG_LOCK; + break; + case SIFIVE_PRCI_PLLOUTDIV: + s->plloutdiv = (uint32_t) val64; + break; + default: + hw_error("%s: bad write: addr=0x%x v=0x%x\n", + __func__, (int)addr, (int)val64); + } } static const MemoryRegionOps sifive_prci_ops = { @@ -61,6 +87,13 @@ static void sifive_prci_init(Object *obj) memory_region_init_io(&s->mmio, obj, &sifive_prci_ops, s, TYPE_SIFIVE_PRCI, 0x8000); sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); + + s->hfrosccfg = (SIFIVE_PRCI_HFROSCCFG_RDY | SIFIVE_PRCI_HFROSCCFG_EN); + s->hfxosccfg = (SIFIVE_PRCI_HFROSCCFG_RDY | SIFIVE_PRCI_HFROSCCFG_EN); + s->pllcfg = (SIFIVE_PRCI_PLLCFG_REFSEL | SIFIVE_PRCI_PLLCFG_BYPASS | + SIFIVE_PRCI_PLLCFG_LOCK); + s->plloutdiv = SIFIVE_PRCI_PLLOUTDIV_DIV1; + } static const TypeInfo sifive_prci_info = { diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index 5ecc47cea3..4208671552 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -41,11 +41,11 @@ #include "hw/riscv/sifive_uart.h" #include "hw/riscv/sifive_prci.h" #include "hw/riscv/sifive_u.h" +#include "hw/riscv/boot.h" #include "chardev/char.h" #include "sysemu/arch_init.h" #include "sysemu/device_tree.h" #include "exec/address-spaces.h" -#include "elf.h" #include <libfdt.h> @@ -65,19 +65,6 @@ static const struct MemmapEntry { #define GEM_REVISION 0x10070109 -static target_ulong load_kernel(const char *kernel_filename) -{ - uint64_t kernel_entry, kernel_high; - - if (load_elf(kernel_filename, NULL, NULL, NULL, - &kernel_entry, NULL, &kernel_high, - 0, EM_RISCV, 1, 0) < 0) { - error_report("could not load kernel '%s'", kernel_filename); - exit(1); - } - return kernel_entry; -} - static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, uint64_t mem_size, const char *cmdline) { @@ -86,7 +73,7 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, uint32_t *cells; char *nodename; char ethclk_names[] = "pclk\0hclk\0tx_clk"; - uint32_t plic_phandle, ethclk_phandle; + uint32_t plic_phandle, ethclk_phandle, phandle = 1; fdt = s->fdt = create_device_tree(&s->fdt_size); if (!fdt) { @@ -121,6 +108,7 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1); for (cpu = s->soc.cpus.num_harts - 1; cpu >= 0; cpu--) { + int cpu_phandle = phandle++; nodename = g_strdup_printf("/cpus/cpu@%d", cpu); char *intc = g_strdup_printf("/cpus/cpu@%d/interrupt-controller", cpu); char *isa = riscv_isa_string(&s->soc.cpus.harts[cpu]); @@ -134,8 +122,8 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, qemu_fdt_setprop_cell(fdt, nodename, "reg", cpu); qemu_fdt_setprop_string(fdt, nodename, "device_type", "cpu"); qemu_fdt_add_subnode(fdt, intc); - qemu_fdt_setprop_cell(fdt, intc, "phandle", 1); - qemu_fdt_setprop_cell(fdt, intc, "linux,phandle", 1); + qemu_fdt_setprop_cell(fdt, intc, "phandle", cpu_phandle); + qemu_fdt_setprop_cell(fdt, intc, "linux,phandle", cpu_phandle); qemu_fdt_setprop_string(fdt, intc, "compatible", "riscv,cpu-intc"); qemu_fdt_setprop(fdt, intc, "interrupt-controller", NULL, 0); qemu_fdt_setprop_cell(fdt, intc, "#interrupt-cells", 1); @@ -167,6 +155,7 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, g_free(cells); g_free(nodename); + plic_phandle = phandle++; cells = g_new0(uint32_t, s->soc.cpus.num_harts * 4); for (cpu = 0; cpu < s->soc.cpus.num_harts; cpu++) { nodename = @@ -192,20 +181,21 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, qemu_fdt_setprop_string(fdt, nodename, "reg-names", "control"); qemu_fdt_setprop_cell(fdt, nodename, "riscv,max-priority", 7); qemu_fdt_setprop_cell(fdt, nodename, "riscv,ndev", 0x35); - qemu_fdt_setprop_cells(fdt, nodename, "phandle", 2); - qemu_fdt_setprop_cells(fdt, nodename, "linux,phandle", 2); + qemu_fdt_setprop_cells(fdt, nodename, "phandle", plic_phandle); + qemu_fdt_setprop_cells(fdt, nodename, "linux,phandle", plic_phandle); plic_phandle = qemu_fdt_get_phandle(fdt, nodename); g_free(cells); g_free(nodename); + ethclk_phandle = phandle++; nodename = g_strdup_printf("/soc/ethclk"); qemu_fdt_add_subnode(fdt, nodename); qemu_fdt_setprop_string(fdt, nodename, "compatible", "fixed-clock"); qemu_fdt_setprop_cell(fdt, nodename, "#clock-cells", 0x0); qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency", SIFIVE_U_GEM_CLOCK_FREQ); - qemu_fdt_setprop_cell(fdt, nodename, "phandle", 3); - qemu_fdt_setprop_cell(fdt, nodename, "linux,phandle", 3); + qemu_fdt_setprop_cell(fdt, nodename, "phandle", ethclk_phandle); + qemu_fdt_setprop_cell(fdt, nodename, "linux,phandle", ethclk_phandle); ethclk_phandle = qemu_fdt_get_phandle(fdt, nodename); g_free(nodename); @@ -279,8 +269,12 @@ static void riscv_sifive_u_init(MachineState *machine) /* create device tree */ create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline); + if (machine->firmware) { + riscv_load_firmware(machine->firmware, memmap[SIFIVE_U_DRAM].base); + } + if (machine->kernel_filename) { - load_kernel(machine->kernel_filename); + riscv_load_kernel(machine->kernel_filename); } /* reset vector */ @@ -341,6 +335,8 @@ static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp) MemoryRegion *system_memory = get_system_memory(); MemoryRegion *mask_rom = g_new(MemoryRegion, 1); qemu_irq plic_gpios[SIFIVE_U_PLIC_NUM_SOURCES]; + char *plic_hart_config; + size_t plic_hart_config_len; int i; Error *err = NULL; NICInfo *nd = &nd_table[0]; @@ -354,9 +350,21 @@ static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp) memory_region_add_subregion(system_memory, memmap[SIFIVE_U_MROM].base, mask_rom); + /* create PLIC hart topology configuration string */ + plic_hart_config_len = (strlen(SIFIVE_U_PLIC_HART_CONFIG) + 1) * smp_cpus; + plic_hart_config = g_malloc0(plic_hart_config_len); + for (i = 0; i < smp_cpus; i++) { + if (i != 0) { + strncat(plic_hart_config, ",", plic_hart_config_len); + } + strncat(plic_hart_config, SIFIVE_U_PLIC_HART_CONFIG, + plic_hart_config_len); + plic_hart_config_len -= (strlen(SIFIVE_U_PLIC_HART_CONFIG) + 1); + } + /* MMIO */ s->plic = sifive_plic_create(memmap[SIFIVE_U_PLIC].base, - (char *)SIFIVE_U_PLIC_HART_CONFIG, + plic_hart_config, SIFIVE_U_PLIC_NUM_SOURCES, SIFIVE_U_PLIC_NUM_PRIORITIES, SIFIVE_U_PLIC_PRIORITY_BASE, diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c index 5b33d4be3b..e68be00a5f 100644 --- a/hw/riscv/spike.c +++ b/hw/riscv/spike.c @@ -36,12 +36,12 @@ #include "hw/riscv/riscv_hart.h" #include "hw/riscv/sifive_clint.h" #include "hw/riscv/spike.h" +#include "hw/riscv/boot.h" #include "chardev/char.h" #include "sysemu/arch_init.h" #include "sysemu/device_tree.h" #include "sysemu/qtest.h" #include "exec/address-spaces.h" -#include "elf.h" #include <libfdt.h> @@ -54,19 +54,6 @@ static const struct MemmapEntry { [SPIKE_DRAM] = { 0x80000000, 0x0 }, }; -static target_ulong load_kernel(const char *kernel_filename) -{ - uint64_t kernel_entry, kernel_high; - - if (load_elf_ram_sym(kernel_filename, NULL, NULL, NULL, - &kernel_entry, NULL, &kernel_high, 0, EM_RISCV, 1, 0, - NULL, true, htif_symbol_callback) < 0) { - error_report("could not load kernel '%s'", kernel_filename); - exit(1); - } - return kernel_entry; -} - static void create_fdt(SpikeState *s, const struct MemmapEntry *memmap, uint64_t mem_size, const char *cmdline) { @@ -199,7 +186,7 @@ static void spike_board_init(MachineState *machine) mask_rom); if (machine->kernel_filename) { - load_kernel(machine->kernel_filename); + riscv_load_kernel(machine->kernel_filename); } /* reset vector */ @@ -287,7 +274,7 @@ static void spike_v1_10_0_board_init(MachineState *machine) mask_rom); if (machine->kernel_filename) { - load_kernel(machine->kernel_filename); + riscv_load_kernel(machine->kernel_filename); } /* reset vector */ @@ -372,7 +359,7 @@ static void spike_v1_09_1_board_init(MachineState *machine) mask_rom); if (machine->kernel_filename) { - load_kernel(machine->kernel_filename); + riscv_load_kernel(machine->kernel_filename); } /* reset vector */ diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 84d94d0c42..d8181a4ff1 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -34,13 +34,13 @@ #include "hw/riscv/sifive_clint.h" #include "hw/riscv/sifive_test.h" #include "hw/riscv/virt.h" +#include "hw/riscv/boot.h" #include "chardev/char.h" #include "sysemu/arch_init.h" #include "sysemu/device_tree.h" #include "exec/address-spaces.h" #include "hw/pci/pci.h" #include "hw/pci-host/gpex.h" -#include "elf.h" #include <libfdt.h> @@ -61,47 +61,6 @@ static const struct MemmapEntry { [VIRT_PCIE_ECAM] = { 0x30000000, 0x10000000 }, }; -static target_ulong load_kernel(const char *kernel_filename) -{ - uint64_t kernel_entry, kernel_high; - - if (load_elf(kernel_filename, NULL, NULL, NULL, - &kernel_entry, NULL, &kernel_high, - 0, EM_RISCV, 1, 0) < 0) { - error_report("could not load kernel '%s'", kernel_filename); - exit(1); - } - return kernel_entry; -} - -static hwaddr load_initrd(const char *filename, uint64_t mem_size, - uint64_t kernel_entry, hwaddr *start) -{ - int size; - - /* We want to put the initrd far enough into RAM that when the - * kernel is uncompressed it will not clobber the initrd. However - * on boards without much RAM we must ensure that we still leave - * enough room for a decent sized initrd, and on boards with large - * amounts of RAM we must avoid the initrd being so far up in RAM - * that it is outside lowmem and inaccessible to the kernel. - * So for boards with less than 256MB of RAM we put the initrd - * halfway into RAM, and for boards with 256MB of RAM or more we put - * the initrd at 128MB. - */ - *start = kernel_entry + MIN(mem_size / 2, 128 * MiB); - - size = load_ramdisk(filename, *start, mem_size - *start); - if (size == -1) { - size = load_image_targphys(filename, *start, mem_size - *start); - if (size == -1) { - error_report("could not load ramdisk '%s'", filename); - exit(1); - } - } - return *start + size; -} - static void create_pcie_irq_map(void *fdt, char *nodename, uint32_t plic_phandle) { @@ -191,6 +150,7 @@ static void *create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap, for (cpu = s->soc.num_harts - 1; cpu >= 0; cpu--) { int cpu_phandle = phandle++; + int intc_phandle; nodename = g_strdup_printf("/cpus/cpu@%d", cpu); char *intc = g_strdup_printf("/cpus/cpu@%d/interrupt-controller", cpu); char *isa = riscv_isa_string(&s->soc.harts[cpu]); @@ -203,9 +163,12 @@ static void *create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap, qemu_fdt_setprop_string(fdt, nodename, "status", "okay"); qemu_fdt_setprop_cell(fdt, nodename, "reg", cpu); qemu_fdt_setprop_string(fdt, nodename, "device_type", "cpu"); + qemu_fdt_setprop_cell(fdt, nodename, "phandle", cpu_phandle); + qemu_fdt_setprop_cell(fdt, nodename, "linux,phandle", cpu_phandle); + intc_phandle = phandle++; qemu_fdt_add_subnode(fdt, intc); - qemu_fdt_setprop_cell(fdt, intc, "phandle", cpu_phandle); - qemu_fdt_setprop_cell(fdt, intc, "linux,phandle", cpu_phandle); + qemu_fdt_setprop_cell(fdt, intc, "phandle", intc_phandle); + qemu_fdt_setprop_cell(fdt, intc, "linux,phandle", intc_phandle); qemu_fdt_setprop_string(fdt, intc, "compatible", "riscv,cpu-intc"); qemu_fdt_setprop(fdt, intc, "interrupt-controller", NULL, 0); qemu_fdt_setprop_cell(fdt, intc, "#interrupt-cells", 1); @@ -214,6 +177,20 @@ static void *create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap, g_free(nodename); } + /* Add cpu-topology node */ + qemu_fdt_add_subnode(fdt, "/cpus/cpu-map"); + qemu_fdt_add_subnode(fdt, "/cpus/cpu-map/cluster0"); + for (cpu = s->soc.num_harts - 1; cpu >= 0; cpu--) { + char *core_nodename = g_strdup_printf("/cpus/cpu-map/cluster0/core%d", + cpu); + char *cpu_nodename = g_strdup_printf("/cpus/cpu@%d", cpu); + uint32_t intc_phandle = qemu_fdt_get_phandle(fdt, cpu_nodename); + qemu_fdt_add_subnode(fdt, core_nodename); + qemu_fdt_setprop_cell(fdt, core_nodename, "cpu", intc_phandle); + g_free(core_nodename); + g_free(cpu_nodename); + } + cells = g_new0(uint32_t, s->soc.num_harts * 4); for (cpu = 0; cpu < s->soc.num_harts; cpu++) { nodename = @@ -298,7 +275,7 @@ static void *create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap, qemu_fdt_setprop_string(fdt, nodename, "device_type", "pci"); qemu_fdt_setprop_cell(fdt, nodename, "linux,pci-domain", 0); qemu_fdt_setprop_cells(fdt, nodename, "bus-range", 0, - memmap[VIRT_PCIE_ECAM].base / + memmap[VIRT_PCIE_ECAM].size / PCIE_MMCFG_SIZE_MIN - 1); qemu_fdt_setprop(fdt, nodename, "dma-coherent", NULL, 0); qemu_fdt_setprop_cells(fdt, nodename, "reg", 0, memmap[VIRT_PCIE_ECAM].base, @@ -421,14 +398,18 @@ static void riscv_virt_board_init(MachineState *machine) memory_region_add_subregion(system_memory, memmap[VIRT_MROM].base, mask_rom); + if (machine->firmware) { + riscv_load_firmware(machine->firmware, memmap[VIRT_DRAM].base); + } + if (machine->kernel_filename) { - uint64_t kernel_entry = load_kernel(machine->kernel_filename); + uint64_t kernel_entry = riscv_load_kernel(machine->kernel_filename); if (machine->initrd_filename) { hwaddr start; - hwaddr end = load_initrd(machine->initrd_filename, - machine->ram_size, kernel_entry, - &start); + hwaddr end = riscv_load_initrd(machine->initrd_filename, + machine->ram_size, kernel_entry, + &start); qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start", start); qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", diff --git a/hw/s390x/css.c b/hw/s390x/css.c index ad310b9f94..b92395f165 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -22,6 +22,7 @@ #include "trace.h" #include "hw/s390x/s390_flic.h" #include "hw/s390x/s390-virtio-ccw.h" +#include "hw/s390x/s390-ccw.h" typedef struct CrwContainer { CRW crw; @@ -1205,6 +1206,26 @@ static void sch_handle_start_func_virtual(SubchDev *sch) } +static void sch_handle_halt_func_passthrough(SubchDev *sch) +{ + int ret; + + ret = s390_ccw_halt(sch); + if (ret == -ENOSYS) { + sch_handle_halt_func(sch); + } +} + +static void sch_handle_clear_func_passthrough(SubchDev *sch) +{ + int ret; + + ret = s390_ccw_clear(sch); + if (ret == -ENOSYS) { + sch_handle_clear_func(sch); + } +} + static IOInstEnding sch_handle_start_func_passthrough(SubchDev *sch) { SCHIB *schib = &sch->curr_status; @@ -1244,11 +1265,9 @@ IOInstEnding do_subchannel_work_passthrough(SubchDev *sch) SCHIB *schib = &sch->curr_status; if (schib->scsw.ctrl & SCSW_FCTL_CLEAR_FUNC) { - /* TODO: Clear handling */ - sch_handle_clear_func(sch); + sch_handle_clear_func_passthrough(sch); } else if (schib->scsw.ctrl & SCSW_FCTL_HALT_FUNC) { - /* TODO: Halt handling */ - sch_handle_halt_func(sch); + sch_handle_halt_func_passthrough(sch); } else if (schib->scsw.ctrl & SCSW_FCTL_START_FUNC) { return sch_handle_start_func_passthrough(sch); } diff --git a/hw/s390x/s390-ccw.c b/hw/s390x/s390-ccw.c index 8403f0e3e9..22c6878b84 100644 --- a/hw/s390x/s390-ccw.c +++ b/hw/s390x/s390-ccw.c @@ -30,6 +30,26 @@ IOInstEnding s390_ccw_cmd_request(SubchDev *sch) return cdc->handle_request(sch); } +int s390_ccw_halt(SubchDev *sch) +{ + S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(sch->driver_data); + + if (!cdc->handle_halt) { + return -ENOSYS; + } + return cdc->handle_halt(sch); +} + +int s390_ccw_clear(SubchDev *sch) +{ + S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(sch->driver_data); + + if (!cdc->handle_clear) { + return -ENOSYS; + } + return cdc->handle_clear(sch); +} + static void s390_ccw_get_dev_info(S390CCWDevice *cdev, char *sysfsdev, Error **errp) diff --git a/hw/s390x/s390-skeys.c b/hw/s390x/s390-skeys.c index daac936698..e5bd92c0c7 100644 --- a/hw/s390x/s390-skeys.c +++ b/hw/s390x/s390-skeys.c @@ -14,7 +14,7 @@ #include "hw/boards.h" #include "hw/s390x/storage-keys.h" #include "qapi/error.h" -#include "qapi/qapi-commands-target.h" +#include "qapi/qapi-commands-misc-target.h" #include "qapi/qmp/qdict.h" #include "qemu/error-report.h" #include "sysemu/kvm.h" diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index 7e4f61fc3e..99f53e87f7 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -1406,6 +1406,7 @@ static void ss5_class_init(ObjectClass *oc, void *data) mc->is_default = 1; mc->default_boot_order = "c"; mc->default_cpu_type = SPARC_CPU_TYPE_NAME("Fujitsu-MB86904"); + mc->default_display = "tcx"; } static const TypeInfo ss5_type = { @@ -1424,6 +1425,7 @@ static void ss10_class_init(ObjectClass *oc, void *data) mc->max_cpus = 4; mc->default_boot_order = "c"; mc->default_cpu_type = SPARC_CPU_TYPE_NAME("TI-SuperSparc-II"); + mc->default_display = "tcx"; } static const TypeInfo ss10_type = { @@ -1442,6 +1444,7 @@ static void ss600mp_class_init(ObjectClass *oc, void *data) mc->max_cpus = 4; mc->default_boot_order = "c"; mc->default_cpu_type = SPARC_CPU_TYPE_NAME("TI-SuperSparc-II"); + mc->default_display = "tcx"; } static const TypeInfo ss600mp_type = { @@ -1460,6 +1463,7 @@ static void ss20_class_init(ObjectClass *oc, void *data) mc->max_cpus = 4; mc->default_boot_order = "c"; mc->default_cpu_type = SPARC_CPU_TYPE_NAME("TI-SuperSparc-II"); + mc->default_display = "tcx"; } static const TypeInfo ss20_type = { @@ -1477,6 +1481,7 @@ static void voyager_class_init(ObjectClass *oc, void *data) mc->block_default_type = IF_SCSI; mc->default_boot_order = "c"; mc->default_cpu_type = SPARC_CPU_TYPE_NAME("Fujitsu-MB86904"); + mc->default_display = "tcx"; } static const TypeInfo voyager_type = { @@ -1494,6 +1499,7 @@ static void ss_lx_class_init(ObjectClass *oc, void *data) mc->block_default_type = IF_SCSI; mc->default_boot_order = "c"; mc->default_cpu_type = SPARC_CPU_TYPE_NAME("TI-MicroSparc-I"); + mc->default_display = "tcx"; } static const TypeInfo ss_lx_type = { @@ -1511,6 +1517,7 @@ static void ss4_class_init(ObjectClass *oc, void *data) mc->block_default_type = IF_SCSI; mc->default_boot_order = "c"; mc->default_cpu_type = SPARC_CPU_TYPE_NAME("Fujitsu-MB86904"); + mc->default_display = "tcx"; } static const TypeInfo ss4_type = { @@ -1528,6 +1535,7 @@ static void scls_class_init(ObjectClass *oc, void *data) mc->block_default_type = IF_SCSI; mc->default_boot_order = "c"; mc->default_cpu_type = SPARC_CPU_TYPE_NAME("TI-MicroSparc-I"); + mc->default_display = "tcx"; } static const TypeInfo scls_type = { @@ -1545,6 +1553,7 @@ static void sbook_class_init(ObjectClass *oc, void *data) mc->block_default_type = IF_SCSI; mc->default_boot_order = "c"; mc->default_cpu_type = SPARC_CPU_TYPE_NAME("TI-MicroSparc-I"); + mc->default_display = "tcx"; } static const TypeInfo sbook_type = { diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c index 9eda0d720b..81f2fb7f70 100644 --- a/hw/ssi/aspeed_smc.c +++ b/hw/ssi/aspeed_smc.c @@ -913,6 +913,7 @@ static const VMStateDescription vmstate_aspeed_smc = { static Property aspeed_smc_properties[] = { DEFINE_PROP_UINT32("num-cs", AspeedSMCState, num_cs, 1), + DEFINE_PROP_UINT64("sdram-base", AspeedSMCState, sdram_base, 0), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs index 0e9a4530f8..123d92c969 100644 --- a/hw/timer/Makefile.objs +++ b/hw/timer/Makefile.objs @@ -41,7 +41,7 @@ obj-$(CONFIG_MC146818RTC) += mc146818rtc.o obj-$(CONFIG_ALLWINNER_A10_PIT) += allwinner-a10-pit.o common-obj-$(CONFIG_STM32F2XX_TIMER) += stm32f2xx_timer.o -common-obj-$(CONFIG_ASPEED_SOC) += aspeed_timer.o +common-obj-$(CONFIG_ASPEED_SOC) += aspeed_timer.o aspeed_rtc.o common-obj-$(CONFIG_SUN4V_RTC) += sun4v-rtc.o common-obj-$(CONFIG_CMSDK_APB_TIMER) += cmsdk-apb-timer.o diff --git a/hw/timer/aspeed_rtc.c b/hw/timer/aspeed_rtc.c new file mode 100644 index 0000000000..19f061c846 --- /dev/null +++ b/hw/timer/aspeed_rtc.c @@ -0,0 +1,180 @@ +/* + * ASPEED Real Time Clock + * Joel Stanley <joel@jms.id.au> + * + * Copyright 2019 IBM Corp + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "hw/timer/aspeed_rtc.h" +#include "qemu/log.h" +#include "qemu/timer.h" + +#include "trace.h" + +#define COUNTER1 (0x00 / 4) +#define COUNTER2 (0x04 / 4) +#define ALARM (0x08 / 4) +#define CONTROL (0x10 / 4) +#define ALARM_STATUS (0x14 / 4) + +#define RTC_UNLOCKED BIT(1) +#define RTC_ENABLED BIT(0) + +static void aspeed_rtc_calc_offset(AspeedRtcState *rtc) +{ + struct tm tm; + uint32_t year, cent; + uint32_t reg1 = rtc->reg[COUNTER1]; + uint32_t reg2 = rtc->reg[COUNTER2]; + + tm.tm_mday = (reg1 >> 24) & 0x1f; + tm.tm_hour = (reg1 >> 16) & 0x1f; + tm.tm_min = (reg1 >> 8) & 0x3f; + tm.tm_sec = (reg1 >> 0) & 0x3f; + + cent = (reg2 >> 16) & 0x1f; + year = (reg2 >> 8) & 0x7f; + tm.tm_mon = ((reg2 >> 0) & 0x0f) - 1; + tm.tm_year = year + (cent * 100) - 1900; + + rtc->offset = qemu_timedate_diff(&tm); +} + +static uint32_t aspeed_rtc_get_counter(AspeedRtcState *rtc, int r) +{ + uint32_t year, cent; + struct tm now; + + qemu_get_timedate(&now, rtc->offset); + + switch (r) { + case COUNTER1: + return (now.tm_mday << 24) | (now.tm_hour << 16) | + (now.tm_min << 8) | now.tm_sec; + case COUNTER2: + cent = (now.tm_year + 1900) / 100; + year = now.tm_year % 100; + return ((cent & 0x1f) << 16) | ((year & 0x7f) << 8) | + ((now.tm_mon + 1) & 0xf); + default: + g_assert_not_reached(); + } +} + +static uint64_t aspeed_rtc_read(void *opaque, hwaddr addr, + unsigned size) +{ + AspeedRtcState *rtc = opaque; + uint64_t val; + uint32_t r = addr >> 2; + + switch (r) { + case COUNTER1: + case COUNTER2: + if (rtc->reg[CONTROL] & RTC_ENABLED) { + rtc->reg[r] = aspeed_rtc_get_counter(rtc, r); + } + /* fall through */ + case CONTROL: + val = rtc->reg[r]; + break; + case ALARM: + case ALARM_STATUS: + default: + qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx "\n", __func__, addr); + return 0; + } + + trace_aspeed_rtc_read(addr, val); + + return val; +} + +static void aspeed_rtc_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + AspeedRtcState *rtc = opaque; + uint32_t r = addr >> 2; + + switch (r) { + case COUNTER1: + case COUNTER2: + if (!(rtc->reg[CONTROL] & RTC_UNLOCKED)) { + break; + } + /* fall through */ + case CONTROL: + rtc->reg[r] = val; + aspeed_rtc_calc_offset(rtc); + break; + case ALARM: + case ALARM_STATUS: + default: + qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx "\n", __func__, addr); + break; + } + trace_aspeed_rtc_write(addr, val); +} + +static void aspeed_rtc_reset(DeviceState *d) +{ + AspeedRtcState *rtc = ASPEED_RTC(d); + + rtc->offset = 0; + memset(rtc->reg, 0, sizeof(rtc->reg)); +} + +static const MemoryRegionOps aspeed_rtc_ops = { + .read = aspeed_rtc_read, + .write = aspeed_rtc_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static const VMStateDescription vmstate_aspeed_rtc = { + .name = TYPE_ASPEED_RTC, + .version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32_ARRAY(reg, AspeedRtcState, 0x18), + VMSTATE_INT32(offset, AspeedRtcState), + VMSTATE_INT32(offset, AspeedRtcState), + VMSTATE_END_OF_LIST() + } +}; + +static void aspeed_rtc_realize(DeviceState *dev, Error **errp) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + AspeedRtcState *s = ASPEED_RTC(dev); + + sysbus_init_irq(sbd, &s->irq); + + memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_rtc_ops, s, + "aspeed-rtc", 0x18ULL); + sysbus_init_mmio(sbd, &s->iomem); +} + +static void aspeed_rtc_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = aspeed_rtc_realize; + dc->vmsd = &vmstate_aspeed_rtc; + dc->reset = aspeed_rtc_reset; +} + +static const TypeInfo aspeed_rtc_info = { + .name = TYPE_ASPEED_RTC, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(AspeedRtcState), + .class_init = aspeed_rtc_class_init, +}; + +static void aspeed_rtc_register_types(void) +{ + type_register_static(&aspeed_rtc_info); +} + +type_init(aspeed_rtc_register_types) diff --git a/hw/timer/aspeed_timer.c b/hw/timer/aspeed_timer.c index 2c3a4d0fe7..29cc5e8070 100644 --- a/hw/timer/aspeed_timer.c +++ b/hw/timer/aspeed_timer.c @@ -107,39 +107,49 @@ static inline uint64_t calculate_time(struct AspeedTimer *t, uint32_t ticks) return t->start + delta_ns; } +static inline uint32_t calculate_match(struct AspeedTimer *t, int i) +{ + return t->match[i] < t->reload ? t->match[i] : 0; +} + static uint64_t calculate_next(struct AspeedTimer *t) { - uint64_t next = 0; - uint32_t rate = calculate_rate(t); + uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + uint64_t next; - while (!next) { - /* We don't know the relationship between the values in the match - * registers, so sort using MAX/MIN/zero. We sort in that order as the - * timer counts down to zero. */ - uint64_t seq[] = { - calculate_time(t, MAX(t->match[0], t->match[1])), - calculate_time(t, MIN(t->match[0], t->match[1])), - calculate_time(t, 0), - }; - uint64_t reload_ns; - uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - - if (now < seq[0]) { - next = seq[0]; - } else if (now < seq[1]) { - next = seq[1]; - } else if (now < seq[2]) { - next = seq[2]; - } else if (t->reload) { - reload_ns = muldiv64(t->reload, NANOSECONDS_PER_SECOND, rate); - t->start = now - ((now - t->start) % reload_ns); - } else { - /* no reload value, return 0 */ - break; - } + /* + * We don't know the relationship between the values in the match + * registers, so sort using MAX/MIN/zero. We sort in that order as + * the timer counts down to zero. + */ + + next = calculate_time(t, MAX(calculate_match(t, 0), calculate_match(t, 1))); + if (now < next) { + return next; + } + + next = calculate_time(t, MIN(calculate_match(t, 0), calculate_match(t, 1))); + if (now < next) { + return next; } - return next; + next = calculate_time(t, 0); + if (now < next) { + return next; + } + + /* We've missed all deadlines, fire interrupt and try again */ + timer_del(&t->timer); + + if (timer_overflow_interrupt(t)) { + t->level = !t->level; + qemu_set_irq(t->irq, t->level); + } + + next = MAX(MAX(calculate_match(t, 0), calculate_match(t, 1)), 0); + t->start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + + return calculate_time(t, next); } static void aspeed_timer_mod(AspeedTimer *t) @@ -184,7 +194,11 @@ static uint64_t aspeed_timer_get_value(AspeedTimer *t, int reg) switch (reg) { case TIMER_REG_STATUS: - value = calculate_ticks(t, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); + if (timer_enabled(t)) { + value = calculate_ticks(t, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); + } else { + value = t->reload; + } break; case TIMER_REG_RELOAD: value = t->reload; @@ -261,7 +275,11 @@ static void aspeed_timer_set_value(AspeedTimerCtrlState *s, int timer, int reg, int64_t delta = (int64_t) value - (int64_t) calculate_ticks(t, now); uint32_t rate = calculate_rate(t); - t->start += muldiv64(delta, NANOSECONDS_PER_SECOND, rate); + if (delta >= 0) { + t->start += muldiv64(delta, NANOSECONDS_PER_SECOND, rate); + } else { + t->start -= muldiv64(-delta, NANOSECONDS_PER_SECOND, rate); + } aspeed_timer_mod(t); } break; diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c index 0d79e000d2..ce4550b6f2 100644 --- a/hw/timer/mc146818rtc.c +++ b/hw/timer/mc146818rtc.c @@ -33,8 +33,8 @@ #include "sysemu/replay.h" #include "hw/timer/mc146818rtc.h" #include "qapi/error.h" -#include "qapi/qapi-commands-target.h" -#include "qapi/qapi-events-target.h" +#include "qapi/qapi-commands-misc-target.h" +#include "qapi/qapi-events-misc-target.h" #include "qapi/visitor.h" #include "exec/address-spaces.h" diff --git a/hw/timer/trace-events b/hw/timer/trace-events index dcaf3d6da6..db02a9142c 100644 --- a/hw/timer/trace-events +++ b/hw/timer/trace-events @@ -66,6 +66,10 @@ cmsdk_apb_dualtimer_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK A cmsdk_apb_dualtimer_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB dualtimer write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" cmsdk_apb_dualtimer_reset(void) "CMSDK APB dualtimer: reset" +# hw/timer/aspeed-rtc.c +aspeed_rtc_read(uint64_t addr, uint64_t value) "addr 0x%02" PRIx64 " value 0x%08" PRIx64 +aspeed_rtc_write(uint64_t addr, uint64_t value) "addr 0x%02" PRIx64 " value 0x%08" PRIx64 + # sun4v-rtc.c sun4v_rtc_read(uint64_t addr, uint64_t value) "read: addr 0x%" PRIx64 " value 0x%" PRIx64 sun4v_rtc_write(uint64_t addr, uint64_t value) "write: addr 0x%" PRIx64 " value 0x%" PRIx64 diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c index 03a2becb3e..6d0296fe4d 100644 --- a/hw/vfio/ccw.c +++ b/hw/vfio/ccw.c @@ -2,9 +2,12 @@ * vfio based subchannel assignment support * * Copyright 2017 IBM Corp. + * Copyright 2019 Red Hat, Inc. + * * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com> * Xiao Feng Ren <renxiaof@linux.vnet.ibm.com> * Pierre Morel <pmorel@linux.vnet.ibm.com> + * Cornelia Huck <cohuck@redhat.com> * * This work is licensed under the terms of the GNU GPL, version 2 or (at * your option) any later version. See the COPYING file in the top-level @@ -33,6 +36,9 @@ struct VFIOCCWDevice { uint64_t io_region_size; uint64_t io_region_offset; struct ccw_io_region *io_region; + uint64_t async_cmd_region_size; + uint64_t async_cmd_region_offset; + struct ccw_cmd_region *async_cmd_region; EventNotifier io_notifier; bool force_orb_pfch; bool warned_orb_pfch; @@ -115,6 +121,87 @@ again: } } +static int vfio_ccw_handle_clear(SubchDev *sch) +{ + S390CCWDevice *cdev = sch->driver_data; + VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev); + struct ccw_cmd_region *region = vcdev->async_cmd_region; + int ret; + + if (!vcdev->async_cmd_region) { + /* Async command region not available, fall back to emulation */ + return -ENOSYS; + } + + memset(region, 0, sizeof(*region)); + region->command = VFIO_CCW_ASYNC_CMD_CSCH; + +again: + ret = pwrite(vcdev->vdev.fd, region, + vcdev->async_cmd_region_size, vcdev->async_cmd_region_offset); + if (ret != vcdev->async_cmd_region_size) { + if (errno == EAGAIN) { + goto again; + } + error_report("vfio-ccw: write cmd region failed with errno=%d", errno); + ret = -errno; + } else { + ret = region->ret_code; + } + switch (ret) { + case 0: + case -ENODEV: + case -EACCES: + return 0; + case -EFAULT: + default: + sch_gen_unit_exception(sch); + css_inject_io_interrupt(sch); + return 0; + } +} + +static int vfio_ccw_handle_halt(SubchDev *sch) +{ + S390CCWDevice *cdev = sch->driver_data; + VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev); + struct ccw_cmd_region *region = vcdev->async_cmd_region; + int ret; + + if (!vcdev->async_cmd_region) { + /* Async command region not available, fall back to emulation */ + return -ENOSYS; + } + + memset(region, 0, sizeof(*region)); + region->command = VFIO_CCW_ASYNC_CMD_HSCH; + +again: + ret = pwrite(vcdev->vdev.fd, region, + vcdev->async_cmd_region_size, vcdev->async_cmd_region_offset); + if (ret != vcdev->async_cmd_region_size) { + if (errno == EAGAIN) { + goto again; + } + error_report("vfio-ccw: write cmd region failed with errno=%d", errno); + ret = -errno; + } else { + ret = region->ret_code; + } + switch (ret) { + case 0: + case -EBUSY: + case -ENODEV: + case -EACCES: + return 0; + case -EFAULT: + default: + sch_gen_unit_exception(sch); + css_inject_io_interrupt(sch); + return 0; + } +} + static void vfio_ccw_reset(DeviceState *dev) { CcwDevice *ccw_dev = DO_UPCAST(CcwDevice, parent_obj, dev); @@ -198,9 +285,8 @@ static void vfio_ccw_register_io_notifier(VFIOCCWDevice *vcdev, Error **errp) { VFIODevice *vdev = &vcdev->vdev; struct vfio_irq_info *irq_info; - struct vfio_irq_set *irq_set; size_t argsz; - int32_t *pfd; + int fd; if (vdev->num_irqs < VFIO_CCW_IO_IRQ_INDEX + 1) { error_setg(errp, "vfio: unexpected number of io irqs %u", @@ -224,56 +310,32 @@ static void vfio_ccw_register_io_notifier(VFIOCCWDevice *vcdev, Error **errp) goto out_free_info; } - argsz = sizeof(*irq_set) + sizeof(*pfd); - irq_set = g_malloc0(argsz); - irq_set->argsz = argsz; - irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | - VFIO_IRQ_SET_ACTION_TRIGGER; - irq_set->index = VFIO_CCW_IO_IRQ_INDEX; - irq_set->start = 0; - irq_set->count = 1; - pfd = (int32_t *) &irq_set->data; - - *pfd = event_notifier_get_fd(&vcdev->io_notifier); - qemu_set_fd_handler(*pfd, vfio_ccw_io_notifier_handler, NULL, vcdev); - if (ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set)) { - error_setg(errp, "vfio: Failed to set up io notification"); - qemu_set_fd_handler(*pfd, NULL, NULL, vcdev); + fd = event_notifier_get_fd(&vcdev->io_notifier); + qemu_set_fd_handler(fd, vfio_ccw_io_notifier_handler, NULL, vcdev); + + if (vfio_set_irq_signaling(vdev, VFIO_CCW_IO_IRQ_INDEX, 0, + VFIO_IRQ_SET_ACTION_TRIGGER, fd, errp)) { + qemu_set_fd_handler(fd, NULL, NULL, vcdev); event_notifier_cleanup(&vcdev->io_notifier); } - g_free(irq_set); - out_free_info: g_free(irq_info); } static void vfio_ccw_unregister_io_notifier(VFIOCCWDevice *vcdev) { - struct vfio_irq_set *irq_set; - size_t argsz; - int32_t *pfd; - - argsz = sizeof(*irq_set) + sizeof(*pfd); - irq_set = g_malloc0(argsz); - irq_set->argsz = argsz; - irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | - VFIO_IRQ_SET_ACTION_TRIGGER; - irq_set->index = VFIO_CCW_IO_IRQ_INDEX; - irq_set->start = 0; - irq_set->count = 1; - pfd = (int32_t *) &irq_set->data; - *pfd = -1; + Error *err = NULL; - if (ioctl(vcdev->vdev.fd, VFIO_DEVICE_SET_IRQS, irq_set)) { - error_report("vfio: Failed to de-assign device io fd: %m"); + vfio_set_irq_signaling(&vcdev->vdev, VFIO_CCW_IO_IRQ_INDEX, 0, + VFIO_IRQ_SET_ACTION_TRIGGER, -1, &err); + if (err) { + error_reportf_err(err, VFIO_MSG_PREFIX, vcdev->vdev.name); } qemu_set_fd_handler(event_notifier_get_fd(&vcdev->io_notifier), NULL, NULL, vcdev); event_notifier_cleanup(&vcdev->io_notifier); - - g_free(irq_set); } static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp) @@ -288,9 +350,13 @@ static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp) return; } + /* + * We always expect at least the I/O region to be present. We also + * may have a variable number of regions governed by capabilities. + */ if (vdev->num_regions < VFIO_CCW_CONFIG_REGION_INDEX + 1) { - error_setg(errp, "vfio: Unexpected number of the I/O region %u", - vdev->num_regions); + error_setg(errp, "vfio: too few regions (%u), expected at least %u", + vdev->num_regions, VFIO_CCW_CONFIG_REGION_INDEX + 1); return; } @@ -310,11 +376,27 @@ static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp) vcdev->io_region_offset = info->offset; vcdev->io_region = g_malloc0(info->size); + /* check for the optional async command region */ + ret = vfio_get_dev_region_info(vdev, VFIO_REGION_TYPE_CCW, + VFIO_REGION_SUBTYPE_CCW_ASYNC_CMD, &info); + if (!ret) { + vcdev->async_cmd_region_size = info->size; + if (sizeof(*vcdev->async_cmd_region) != vcdev->async_cmd_region_size) { + error_setg(errp, "vfio: Unexpected size of the async cmd region"); + g_free(vcdev->io_region); + g_free(info); + return; + } + vcdev->async_cmd_region_offset = info->offset; + vcdev->async_cmd_region = g_malloc0(info->size); + } + g_free(info); } static void vfio_ccw_put_region(VFIOCCWDevice *vcdev) { + g_free(vcdev->async_cmd_region); g_free(vcdev->io_region); } @@ -487,6 +569,8 @@ static void vfio_ccw_class_init(ObjectClass *klass, void *data) dc->reset = vfio_ccw_reset; cdc->handle_request = vfio_ccw_handle_request; + cdc->handle_halt = vfio_ccw_handle_halt; + cdc->handle_clear = vfio_ccw_handle_clear; } static const TypeInfo vfio_ccw_info = { diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index ce3fe96efe..d7a4e1875c 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -551,9 +551,12 @@ static void vfio_msix_vector_release(PCIDevice *pdev, unsigned int nr) */ if (vector->virq >= 0) { int32_t fd = event_notifier_get_fd(&vector->interrupt); + Error *err = NULL; - vfio_set_irq_signaling(&vdev->vbasedev, VFIO_PCI_MSIX_IRQ_INDEX, nr, - VFIO_IRQ_SET_ACTION_TRIGGER, fd, NULL); + if (vfio_set_irq_signaling(&vdev->vbasedev, VFIO_PCI_MSIX_IRQ_INDEX, nr, + VFIO_IRQ_SET_ACTION_TRIGGER, fd, &err)) { + error_reportf_err(err, VFIO_MSG_PREFIX, vdev->vbasedev.name); + } } } diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c index 4a8409f0da..57fe24ae6b 100644 --- a/hw/watchdog/wdt_aspeed.c +++ b/hw/watchdog/wdt_aspeed.c @@ -44,6 +44,9 @@ #define WDT_RESTART_MAGIC 0x4755 +#define SCU_RESET_CONTROL1 (0x04 / 4) +#define SCU_RESET_SDRAM BIT(0) + static bool aspeed_wdt_is_enabled(const AspeedWDTState *s) { return s->regs[WDT_CTRL] & WDT_CTRL_ENABLE; @@ -222,6 +225,13 @@ static void aspeed_wdt_timer_expired(void *dev) { AspeedWDTState *s = ASPEED_WDT(dev); + /* Do not reset on SDRAM controller reset */ + if (s->scu->regs[SCU_RESET_CONTROL1] & SCU_RESET_SDRAM) { + timer_del(s->timer); + s->regs[WDT_CTRL] = 0; + return; + } + qemu_log_mask(CPU_LOG_RESET, "Watchdog timer expired.\n"); watchdog_perform_action(); timer_del(s->timer); @@ -233,6 +243,16 @@ static void aspeed_wdt_realize(DeviceState *dev, Error **errp) { SysBusDevice *sbd = SYS_BUS_DEVICE(dev); AspeedWDTState *s = ASPEED_WDT(dev); + Error *err = NULL; + Object *obj; + + obj = object_property_get_link(OBJECT(dev), "scu", &err); + if (!obj) { + error_propagate(errp, err); + error_prepend(errp, "required link 'scu' not found: "); + return; + } + s->scu = ASPEED_SCU(obj); if (!is_supported_silicon_rev(s->silicon_rev)) { error_setg(errp, "Unknown silicon revision: 0x%" PRIx32, diff --git a/include/block/block.h b/include/block/block.h index f9415ed740..734c9d2f76 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -449,7 +449,8 @@ int bdrv_block_status_above(BlockDriverState *bs, BlockDriverState *base, int bdrv_is_allocated(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t *pnum); int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base, - int64_t offset, int64_t bytes, int64_t *pnum); + bool include_base, int64_t offset, int64_t bytes, + int64_t *pnum); bool bdrv_is_read_only(BlockDriverState *bs); int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only, diff --git a/include/exec/memory.h b/include/exec/memory.h index e6140e8a04..2c5cdffa31 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -1758,6 +1758,16 @@ void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name); void address_space_destroy(AddressSpace *as); /** + * address_space_remove_listeners: unregister all listeners of an address space + * + * Removes all callbacks previously registered with memory_listener_register() + * for @as. + * + * @as: an initialized #AddressSpace + */ +void address_space_remove_listeners(AddressSpace *as); + +/** * address_space_rw: read from or write to an address space. * * Return a MemTxResult indicating whether the operation succeeded diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index 836b2ba8bf..cef605ad6b 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -15,7 +15,9 @@ #include "hw/intc/aspeed_vic.h" #include "hw/misc/aspeed_scu.h" #include "hw/misc/aspeed_sdmc.h" +#include "hw/misc/aspeed_xdma.h" #include "hw/timer/aspeed_timer.h" +#include "hw/timer/aspeed_rtc.h" #include "hw/i2c/aspeed_i2c.h" #include "hw/ssi/aspeed_smc.h" #include "hw/watchdog/wdt_aspeed.h" @@ -23,23 +25,28 @@ #define ASPEED_SPIS_NUM 2 #define ASPEED_WDTS_NUM 3 +#define ASPEED_CPUS_NUM 2 +#define ASPEED_MACS_NUM 2 typedef struct AspeedSoCState { /*< private >*/ DeviceState parent; /*< public >*/ - ARMCPU cpu; + ARMCPU cpu[ASPEED_CPUS_NUM]; + uint32_t num_cpus; MemoryRegion sram; AspeedVICState vic; + AspeedRtcState rtc; AspeedTimerCtrlState timerctrl; AspeedI2CState i2c; AspeedSCUState scu; + AspeedXDMAState xdma; AspeedSMCState fmc; AspeedSMCState spi[ASPEED_SPIS_NUM]; AspeedSDMCState sdmc; AspeedWDTState wdt[ASPEED_WDTS_NUM]; - FTGMAC100State ftgmac100; + FTGMAC100State ftgmac100[ASPEED_MACS_NUM]; } AspeedSoCState; #define TYPE_ASPEED_SOC "aspeed-soc" @@ -49,13 +56,14 @@ typedef struct AspeedSoCInfo { const char *name; const char *cpu_type; uint32_t silicon_rev; - hwaddr sdram_base; uint64_t sram_size; int spis_num; - const hwaddr *spi_bases; const char *fmc_typename; const char **spi_typename; int wdts_num; + const int *irqmap; + const hwaddr *memmap; + uint32_t num_cpus; } AspeedSoCInfo; typedef struct AspeedSoCClass { @@ -68,4 +76,41 @@ typedef struct AspeedSoCClass { #define ASPEED_SOC_GET_CLASS(obj) \ OBJECT_GET_CLASS(AspeedSoCClass, (obj), TYPE_ASPEED_SOC) +enum { + ASPEED_IOMEM, + ASPEED_UART1, + ASPEED_UART2, + ASPEED_UART3, + ASPEED_UART4, + ASPEED_UART5, + ASPEED_VUART, + ASPEED_FMC, + ASPEED_SPI1, + ASPEED_SPI2, + ASPEED_VIC, + ASPEED_SDMC, + ASPEED_SCU, + ASPEED_ADC, + ASPEED_SRAM, + ASPEED_GPIO, + ASPEED_RTC, + ASPEED_TIMER1, + ASPEED_TIMER2, + ASPEED_TIMER3, + ASPEED_TIMER4, + ASPEED_TIMER5, + ASPEED_TIMER6, + ASPEED_TIMER7, + ASPEED_TIMER8, + ASPEED_WDT, + ASPEED_PWM, + ASPEED_LPC, + ASPEED_IBT, + ASPEED_I2C, + ASPEED_ETH1, + ASPEED_ETH2, + ASPEED_SDRAM, + ASPEED_XDMA, +}; + #endif /* ASPEED_SOC_H */ diff --git a/include/hw/arm/fsl-imx7.h b/include/hw/arm/fsl-imx7.h index 4101f80251..8003d45d1e 100644 --- a/include/hw/arm/fsl-imx7.h +++ b/include/hw/arm/fsl-imx7.h @@ -125,6 +125,9 @@ enum FslIMX7MemoryMap { FSL_IMX7_ADC2_ADDR = 0x30620000, FSL_IMX7_ADCn_SIZE = 0x1000, + FSL_IMX7_PCIE_PHY_ADDR = 0x306D0000, + FSL_IMX7_PCIE_PHY_SIZE = 0x10000, + FSL_IMX7_GPC_ADDR = 0x303A0000, FSL_IMX7_I2C1_ADDR = 0x30A20000, @@ -179,6 +182,9 @@ enum FslIMX7MemoryMap { FSL_IMX7_PCIE_REG_SIZE = 16 * 1024, FSL_IMX7_GPR_ADDR = 0x30340000, + + FSL_IMX7_DMA_APBH_ADDR = 0x33000000, + FSL_IMX7_DMA_APBH_SIZE = 0x2000, }; enum FslIMX7IRQs { @@ -207,10 +213,10 @@ enum FslIMX7IRQs { FSL_IMX7_USB2_IRQ = 42, FSL_IMX7_USB3_IRQ = 40, - FSL_IMX7_PCI_INTA_IRQ = 122, - FSL_IMX7_PCI_INTB_IRQ = 123, - FSL_IMX7_PCI_INTC_IRQ = 124, - FSL_IMX7_PCI_INTD_IRQ = 125, + FSL_IMX7_PCI_INTA_IRQ = 125, + FSL_IMX7_PCI_INTB_IRQ = 124, + FSL_IMX7_PCI_INTC_IRQ = 123, + FSL_IMX7_PCI_INTD_IRQ = 122, FSL_IMX7_UART7_IRQ = 126, diff --git a/include/hw/boards.h b/include/hw/boards.h index eaa050a7ab..c6ad196b14 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -6,6 +6,7 @@ #include "sysemu/blockdev.h" #include "sysemu/accel.h" #include "hw/qdev.h" +#include "qapi/qapi-types-machine.h" #include "qemu/module.h" #include "qom/object.h" #include "qom/cpu.h" diff --git a/include/hw/i2c/bitbang_i2c.h b/include/hw/i2c/bitbang_i2c.h index 3a7126d5de..92334e9016 100644 --- a/include/hw/i2c/bitbang_i2c.h +++ b/include/hw/i2c/bitbang_i2c.h @@ -8,7 +8,43 @@ typedef struct bitbang_i2c_interface bitbang_i2c_interface; #define BITBANG_I2C_SDA 0 #define BITBANG_I2C_SCL 1 -bitbang_i2c_interface *bitbang_i2c_init(I2CBus *bus); +typedef enum bitbang_i2c_state { + STOPPED = 0, + SENDING_BIT7, + SENDING_BIT6, + SENDING_BIT5, + SENDING_BIT4, + SENDING_BIT3, + SENDING_BIT2, + SENDING_BIT1, + SENDING_BIT0, + WAITING_FOR_ACK, + RECEIVING_BIT7, + RECEIVING_BIT6, + RECEIVING_BIT5, + RECEIVING_BIT4, + RECEIVING_BIT3, + RECEIVING_BIT2, + RECEIVING_BIT1, + RECEIVING_BIT0, + SENDING_ACK, + SENT_NACK +} bitbang_i2c_state; + +struct bitbang_i2c_interface { + I2CBus *bus; + bitbang_i2c_state state; + int last_data; + int last_clock; + int device_out; + uint8_t buffer; + int current_addr; +}; + +/** + * bitbang_i2c_init: in-place initialize the bitbang_i2c_interface struct + */ +void bitbang_i2c_init(bitbang_i2c_interface *s, I2CBus *bus); int bitbang_i2c_set(bitbang_i2c_interface *i2c, int line, int level); #endif diff --git a/include/hw/i2c/ppc4xx_i2c.h b/include/hw/i2c/ppc4xx_i2c.h index 8437bf070b..f6f837fbec 100644 --- a/include/hw/i2c/ppc4xx_i2c.h +++ b/include/hw/i2c/ppc4xx_i2c.h @@ -41,7 +41,7 @@ typedef struct PPC4xxI2CState { I2CBus *bus; qemu_irq irq; MemoryRegion iomem; - bitbang_i2c_interface *bitbang; + bitbang_i2c_interface bitbang; int mdidx; uint8_t mdata[4]; uint8_t lmadr; diff --git a/include/hw/misc/aspeed_xdma.h b/include/hw/misc/aspeed_xdma.h new file mode 100644 index 0000000000..00b45d931f --- /dev/null +++ b/include/hw/misc/aspeed_xdma.h @@ -0,0 +1,30 @@ +/* + * ASPEED XDMA Controller + * Eddie James <eajames@linux.ibm.com> + * + * Copyright (C) 2019 IBM Corp. + * SPDX-License-Identifer: GPL-2.0-or-later + */ + +#ifndef ASPEED_XDMA_H +#define ASPEED_XDMA_H + +#include "hw/sysbus.h" + +#define TYPE_ASPEED_XDMA "aspeed.xdma" +#define ASPEED_XDMA(obj) OBJECT_CHECK(AspeedXDMAState, (obj), TYPE_ASPEED_XDMA) + +#define ASPEED_XDMA_NUM_REGS (ASPEED_XDMA_REG_SIZE / sizeof(uint32_t)) +#define ASPEED_XDMA_REG_SIZE 0x7C + +typedef struct AspeedXDMAState { + SysBusDevice parent; + + MemoryRegion iomem; + qemu_irq irq; + + char bmc_cmdq_readp_set; + uint32_t regs[ASPEED_XDMA_NUM_REGS]; +} AspeedXDMAState; + +#endif /* ASPEED_XDMA_H */ diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h index fc4678f757..fb123edc4e 100644 --- a/include/hw/ppc/pnv.h +++ b/include/hw/ppc/pnv.h @@ -56,7 +56,6 @@ typedef struct PnvChip { uint64_t cores_mask; void *cores; - hwaddr xscom_base; MemoryRegion xscom_mmio; MemoryRegion xscom; AddressSpace xscom_as; @@ -105,8 +104,6 @@ typedef struct PnvChipClass { uint64_t chip_cfam_id; uint64_t cores_mask; - hwaddr xscom_base; - DeviceRealize parent_realize; uint32_t (*core_pir)(PnvChip *chip, uint32_t core_id); @@ -199,7 +196,7 @@ void pnv_bmc_powerdown(IPMIBmc *bmc); */ #define PNV_XSCOM_SIZE 0x800000000ull #define PNV_XSCOM_BASE(chip) \ - (chip->xscom_base + ((uint64_t)(chip)->chip_id) * PNV_XSCOM_SIZE) + (0x0003fc0000000000ull + ((uint64_t)(chip)->chip_id) * PNV_XSCOM_SIZE) /* * XSCOM 0x20109CA defines the ICP BAR: @@ -256,4 +253,7 @@ void pnv_bmc_powerdown(IPMIBmc *bmc); #define PNV9_PSIHB_ESB_SIZE 0x0000000000010000ull #define PNV9_PSIHB_ESB_BASE(chip) PNV9_CHIP_BASE(chip, 0x00060302031c0000ull) +#define PNV9_XSCOM_SIZE 0x0000000400000000ull +#define PNV9_XSCOM_BASE(chip) PNV9_CHIP_BASE(chip, 0x00603fc00000000ull) + #endif /* PPC_PNV_H */ diff --git a/include/hw/ppc/pnv_xscom.h b/include/hw/ppc/pnv_xscom.h index c842d950d2..67641ed278 100644 --- a/include/hw/ppc/pnv_xscom.h +++ b/include/hw/ppc/pnv_xscom.h @@ -87,7 +87,7 @@ typedef struct PnvXScomInterfaceClass { #define PNV9_XSCOM_XIVE_BASE 0x5013000 #define PNV9_XSCOM_XIVE_SIZE 0x300 -extern void pnv_xscom_realize(PnvChip *chip, Error **errp); +extern void pnv_xscom_realize(PnvChip *chip, uint64_t size, Error **errp); extern int pnv_dt_xscom(PnvChip *chip, void *fdt, int offset); extern void pnv_xscom_add_subregion(PnvChip *chip, hwaddr offset, diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 4f5becf1f3..60553d32c4 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -676,10 +676,6 @@ typedef void (*spapr_rtas_fn)(PowerPCCPU *cpu, SpaprMachineState *sm, uint32_t nargs, target_ulong args, uint32_t nret, target_ulong rets); void spapr_rtas_register(int token, const char *name, spapr_rtas_fn fn); -static inline void spapr_rtas_unregister(int token) -{ - spapr_rtas_register(token, NULL, NULL); -} target_ulong spapr_rtas_call(PowerPCCPU *cpu, SpaprMachineState *sm, uint32_t token, uint32_t nargs, target_ulong args, uint32_t nret, target_ulong rets); diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h index 14cab73c9c..f965a58f89 100644 --- a/include/hw/ppc/spapr_irq.h +++ b/include/hw/ppc/spapr_irq.h @@ -48,7 +48,6 @@ typedef struct SpaprIrq { void (*reset)(SpaprMachineState *spapr, Error **errp); void (*set_irq)(void *opaque, int srcno, int val); const char *(*get_nodename)(SpaprMachineState *spapr); - void (*init_emu)(SpaprMachineState *spapr, Error **errp); void (*init_kvm)(SpaprMachineState *spapr, Error **errp); } SpaprIrq; diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h index b26befcf6b..7197144265 100644 --- a/include/hw/ppc/spapr_xive.h +++ b/include/hw/ppc/spapr_xive.h @@ -42,6 +42,7 @@ typedef struct SpaprXive { /* KVM support */ int fd; void *tm_mmap; + MemoryRegion tm_mmio_kvm; VMChangeStateEntry *change; } SpaprXive; @@ -66,7 +67,6 @@ void spapr_xive_map_mmio(SpaprXive *xive); int spapr_xive_end_to_target(uint8_t end_blk, uint32_t end_idx, uint32_t *out_server, uint8_t *out_prio); -void spapr_xive_init(SpaprXive *xive, Error **errp); /* * KVM XIVE device helpers diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h index d6f8e4c4c2..1eb7b5cd68 100644 --- a/include/hw/ppc/xics.h +++ b/include/hw/ppc/xics.h @@ -119,7 +119,6 @@ struct ICSState { uint32_t offset; ICSIRQState *irqs; XICSFabric *xics; - bool init; /* sPAPR ICS device initialized */ }; #define ICS_PROP_XICS "xics" @@ -191,13 +190,13 @@ Object *icp_create(Object *cpu, const char *type, XICSFabric *xi, /* KVM */ void icp_get_kvm_state(ICPState *icp); -int icp_set_kvm_state(ICPState *icp); +int icp_set_kvm_state(ICPState *icp, Error **errp); void icp_synchronize_state(ICPState *icp); void icp_kvm_realize(DeviceState *dev, Error **errp); void ics_get_kvm_state(ICSState *ics); -int ics_set_kvm_state_one(ICSState *ics, int srcno); -int ics_set_kvm_state(ICSState *ics); +int ics_set_kvm_state_one(ICSState *ics, int srcno, Error **errp); +int ics_set_kvm_state(ICSState *ics, Error **errp); void ics_synchronize_state(ICSState *ics); void ics_kvm_set_irq(ICSState *ics, int srcno, int val); diff --git a/include/hw/ppc/xics_spapr.h b/include/hw/ppc/xics_spapr.h index 2476b540ed..5dabc9a138 100644 --- a/include/hw/ppc/xics_spapr.h +++ b/include/hw/ppc/xics_spapr.h @@ -33,8 +33,9 @@ void spapr_dt_xics(SpaprMachineState *spapr, uint32_t nr_servers, void *fdt, uint32_t phandle); -int xics_kvm_init(SpaprMachineState *spapr, Error **errp); +int xics_kvm_connect(SpaprMachineState *spapr, Error **errp); void xics_kvm_disconnect(SpaprMachineState *spapr, Error **errp); +bool xics_kvm_has_broken_disconnect(SpaprMachineState *spapr); void xics_spapr_init(SpaprMachineState *spapr); #endif /* XICS_SPAPR_H */ diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h index a6ee7e831d..55c53c7417 100644 --- a/include/hw/ppc/xive.h +++ b/include/hw/ppc/xive.h @@ -197,6 +197,7 @@ typedef struct XiveSource { /* KVM support */ void *esb_mmap; + MemoryRegion esb_mmio_kvm; XiveNotifier *xive; } XiveSource; diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h new file mode 100644 index 0000000000..daa179b600 --- /dev/null +++ b/include/hw/riscv/boot.h @@ -0,0 +1,29 @@ +/* + * QEMU RISC-V Boot Helper + * + * Copyright (c) 2017 SiFive, Inc. + * Copyright (c) 2019 Alistair Francis <alistair.francis@wdc.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef RISCV_BOOT_H +#define RISCV_BOOT_H + +target_ulong riscv_load_firmware(const char *firmware_filename, + hwaddr firmware_load_addr); +target_ulong riscv_load_kernel(const char *kernel_filename); +hwaddr riscv_load_initrd(const char *filename, uint64_t mem_size, + uint64_t kernel_entry, hwaddr *start); + +#endif /* RISCV_BOOT_H */ diff --git a/include/hw/riscv/sifive_e.h b/include/hw/riscv/sifive_e.h index 3b14eb7462..d175b24cb2 100644 --- a/include/hw/riscv/sifive_e.h +++ b/include/hw/riscv/sifive_e.h @@ -33,6 +33,8 @@ typedef struct SiFiveESoCState { RISCVHartArrayState cpus; DeviceState *plic; SIFIVEGPIOState gpio; + MemoryRegion xip_mem; + MemoryRegion mask_rom; } SiFiveESoCState; typedef struct SiFiveEState { diff --git a/include/hw/riscv/sifive_prci.h b/include/hw/riscv/sifive_prci.h index b6f4c486cc..bd51c4af3c 100644 --- a/include/hw/riscv/sifive_prci.h +++ b/include/hw/riscv/sifive_prci.h @@ -19,6 +19,34 @@ #ifndef HW_SIFIVE_PRCI_H #define HW_SIFIVE_PRCI_H +enum { + SIFIVE_PRCI_HFROSCCFG = 0x0, + SIFIVE_PRCI_HFXOSCCFG = 0x4, + SIFIVE_PRCI_PLLCFG = 0x8, + SIFIVE_PRCI_PLLOUTDIV = 0xC +}; + +enum { + SIFIVE_PRCI_HFROSCCFG_RDY = (1 << 31), + SIFIVE_PRCI_HFROSCCFG_EN = (1 << 30) +}; + +enum { + SIFIVE_PRCI_HFXOSCCFG_RDY = (1 << 31), + SIFIVE_PRCI_HFXOSCCFG_EN = (1 << 30) +}; + +enum { + SIFIVE_PRCI_PLLCFG_PLLSEL = (1 << 16), + SIFIVE_PRCI_PLLCFG_REFSEL = (1 << 17), + SIFIVE_PRCI_PLLCFG_BYPASS = (1 << 18), + SIFIVE_PRCI_PLLCFG_LOCK = (1 << 31) +}; + +enum { + SIFIVE_PRCI_PLLOUTDIV_DIV1 = (1 << 8) +}; + #define TYPE_SIFIVE_PRCI "riscv.sifive.prci" #define SIFIVE_PRCI(obj) \ @@ -30,6 +58,10 @@ typedef struct SiFivePRCIState { /*< public >*/ MemoryRegion mmio; + uint32_t hfrosccfg; + uint32_t hfxosccfg; + uint32_t pllcfg; + uint32_t plloutdiv; } SiFivePRCIState; DeviceState *sifive_prci_create(hwaddr addr); diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h index 7cc183ef43..d033387fba 100644 --- a/include/hw/s390x/css.h +++ b/include/hw/s390x/css.h @@ -215,6 +215,9 @@ IOInstEnding s390_ccw_cmd_request(SubchDev *sch); IOInstEnding do_subchannel_work_virtual(SubchDev *sub); IOInstEnding do_subchannel_work_passthrough(SubchDev *sub); +int s390_ccw_halt(SubchDev *sch); +int s390_ccw_clear(SubchDev *sch); + typedef enum { CSS_IO_ADAPTER_VIRTIO = 0, CSS_IO_ADAPTER_PCI = 1, diff --git a/include/hw/s390x/s390-ccw.h b/include/hw/s390x/s390-ccw.h index 901d805d79..fffb54562f 100644 --- a/include/hw/s390x/s390-ccw.h +++ b/include/hw/s390x/s390-ccw.h @@ -35,6 +35,8 @@ typedef struct S390CCWDeviceClass { void (*realize)(S390CCWDevice *dev, char *sysfsdev, Error **errp); void (*unrealize)(S390CCWDevice *dev, Error **errp); IOInstEnding (*handle_request) (SubchDev *sch); + int (*handle_halt) (SubchDev *sch); + int (*handle_clear) (SubchDev *sch); } S390CCWDeviceClass; #endif diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h index 3b1e7fce6c..591279ba1f 100644 --- a/include/hw/ssi/aspeed_smc.h +++ b/include/hw/ssi/aspeed_smc.h @@ -97,6 +97,9 @@ typedef struct AspeedSMCState { uint8_t r_timings; uint8_t conf_enable_w0; + /* for DMA support */ + uint64_t sdram_base; + AspeedSMCFlash *flashes; uint8_t snoop_index; diff --git a/include/hw/timer/aspeed_rtc.h b/include/hw/timer/aspeed_rtc.h new file mode 100644 index 0000000000..1f1155a676 --- /dev/null +++ b/include/hw/timer/aspeed_rtc.h @@ -0,0 +1,31 @@ +/* + * ASPEED Real Time Clock + * Joel Stanley <joel@jms.id.au> + * + * Copyright 2019 IBM Corp + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef ASPEED_RTC_H +#define ASPEED_RTC_H + +#include <stdint.h> + +#include "hw/hw.h" +#include "hw/irq.h" +#include "hw/sysbus.h" + +typedef struct AspeedRtcState { + SysBusDevice parent_obj; + + MemoryRegion iomem; + qemu_irq irq; + + uint32_t reg[0x18]; + int offset; + +} AspeedRtcState; + +#define TYPE_ASPEED_RTC "aspeed.rtc" +#define ASPEED_RTC(obj) OBJECT_CHECK(AspeedRtcState, (obj), TYPE_ASPEED_RTC) + +#endif /* ASPEED_RTC_H */ diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index a88b69b675..9107bd41c0 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -74,11 +74,6 @@ typedef struct VFIOContainer { int error; bool initialized; unsigned long pgsizes; - /* - * This assumes the host IOMMU can support only a single - * contiguous IOVA window. We may need to generalize that in - * future - */ QLIST_HEAD(, VFIOGuestIOMMU) giommu_list; QLIST_HEAD(, VFIOHostDMAWindow) hostwin_list; QLIST_HEAD(, VFIOGroup) group_list; diff --git a/include/hw/watchdog/wdt_aspeed.h b/include/hw/watchdog/wdt_aspeed.h index 88d8be4f78..daef0c0e23 100644 --- a/include/hw/watchdog/wdt_aspeed.h +++ b/include/hw/watchdog/wdt_aspeed.h @@ -27,6 +27,7 @@ typedef struct AspeedWDTState { MemoryRegion iomem; uint32_t regs[ASPEED_WDT_REGS_MAX]; + AspeedSCUState *scu; uint32_t pclk_freq; uint32_t silicon_rev; uint32_t ext_pulse_width_mask; diff --git a/hmp.h b/include/monitor/hmp.h index 1d095d5837..a0e9511440 100644 --- a/hmp.h +++ b/include/monitor/hmp.h @@ -16,6 +16,8 @@ #include "qemu/readline.h" +void hmp_handle_error(Monitor *mon, Error **errp); + void hmp_info_name(Monitor *mon, const QDict *qdict); void hmp_info_version(Monitor *mon, const QDict *qdict); void hmp_info_kvm(Monitor *mon, const QDict *qdict); @@ -115,9 +117,11 @@ void hmp_cpu_add(Monitor *mon, const QDict *qdict); void hmp_object_add(Monitor *mon, const QDict *qdict); void hmp_object_del(Monitor *mon, const QDict *qdict); void hmp_info_memdev(Monitor *mon, const QDict *qdict); +void hmp_info_numa(Monitor *mon, const QDict *qdict); void hmp_info_memory_devices(Monitor *mon, const QDict *qdict); void hmp_qom_list(Monitor *mon, const QDict *qdict); void hmp_qom_set(Monitor *mon, const QDict *qdict); +void hmp_info_qom_tree(Monitor *mon, const QDict *dict); void object_add_completion(ReadLineState *rs, int nb_args, const char *str); void object_del_completion(ReadLineState *rs, int nb_args, const char *str); void device_add_completion(ReadLineState *rs, int nb_args, const char *str); diff --git a/include/monitor/qdev.h b/include/monitor/qdev.h index 0ff3331284..084799e4d9 100644 --- a/include/monitor/qdev.h +++ b/include/monitor/qdev.h @@ -7,7 +7,6 @@ void hmp_info_qtree(Monitor *mon, const QDict *qdict); void hmp_info_qdm(Monitor *mon, const QDict *qdict); -void hmp_info_qom_tree(Monitor *mon, const QDict *dict); void qmp_device_add(QDict *qdict, QObject **ret_data, Error **errp); int qdev_device_help(QemuOpts *opts); diff --git a/include/net/announce.h b/include/net/announce.h index 04a035f679..3d90c83c23 100644 --- a/include/net/announce.h +++ b/include/net/announce.h @@ -22,8 +22,12 @@ struct AnnounceTimer { /* Returns: update the timer to the next time point */ int64_t qemu_announce_timer_step(AnnounceTimer *timer); -/* Delete the underlying timer */ -void qemu_announce_timer_del(AnnounceTimer *timer); +/* + * Delete the underlying timer and other data + * If 'free_named' true and the timer is a named timer, then remove + * it from the list of named timers and free the AnnounceTimer itself. + */ +void qemu_announce_timer_del(AnnounceTimer *timer, bool free_named); /* * Under BQL/main thread diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h index d824bc0941..250143cb5a 100644 --- a/include/sysemu/dump.h +++ b/include/sysemu/dump.h @@ -14,7 +14,7 @@ #ifndef DUMP_H #define DUMP_H -#include "qapi/qapi-types-misc.h" +#include "qapi/qapi-types-dump.h" #define MAKEDUMPFILE_SIGNATURE "makedumpfile" #define MAX_SIZE_MDF_HEADER (4096) /* max size of makedumpfile_header */ diff --git a/include/sysemu/hostmem.h b/include/sysemu/hostmem.h index a023b372a4..92fa0e458c 100644 --- a/include/sysemu/hostmem.h +++ b/include/sysemu/hostmem.h @@ -14,7 +14,7 @@ #define SYSEMU_HOSTMEM_H #include "sysemu/sysemu.h" /* for MAX_NODES */ -#include "qapi/qapi-types-misc.h" +#include "qapi/qapi-types-machine.h" #include "qom/object.h" #include "exec/memory.h" #include "qemu/bitmap.h" diff --git a/include/sysemu/numa.h b/include/sysemu/numa.h index b6ac7de43e..01a263eba2 100644 --- a/include/sysemu/numa.h +++ b/include/sysemu/numa.h @@ -22,6 +22,8 @@ struct NumaNodeMem { }; extern NodeInfo numa_info[MAX_NODES]; + +void set_numa_options(MachineState *ms, NumaOptions *object, Error **errp); void parse_numa_opts(MachineState *ms); void numa_complete_configuration(MachineState *ms); void query_numa_node_mem(NumaNodeMem node_mem[]); diff --git a/linux-user/fd-trans.c b/linux-user/fd-trans.c index 612819c1b1..60077ce531 100644 --- a/linux-user/fd-trans.c +++ b/linux-user/fd-trans.c @@ -483,6 +483,12 @@ static abi_long host_to_target_data_bridge_nlattr(struct nlattr *nlattr, case QEMU_IFLA_BR_ROOT_ID: case QEMU_IFLA_BR_BRIDGE_ID: break; + /* br_boolopt_multi { uint32_t, uint32_t } */ + case QEMU_IFLA_BR_MULTI_BOOLOPT: + u32 = NLA_DATA(nlattr); + u32[0] = tswap32(u32[0]); /* optval */ + u32[1] = tswap32(u32[1]); /* optmask */ + break; default: gemu_log("Unknown QEMU_IFLA_BR type %d\n", nlattr->nla_type); break; @@ -546,12 +552,6 @@ static abi_long host_to_target_slave_data_bridge_nlattr(struct nlattr *nlattr, case QEMU_IFLA_BRPORT_ROOT_ID: case QEMU_IFLA_BRPORT_BRIDGE_ID: break; - /* br_boolopt_multi { uint32_t, uint32_t } */ - case QEMU_IFLA_BR_MULTI_BOOLOPT: - u32 = NLA_DATA(nlattr); - u32[0] = tswap32(u32[0]); /* optval */ - u32[1] = tswap32(u32[1]); /* optmask */ - break; default: gemu_log("Unknown QEMU_IFLA_BRPORT type %d\n", nlattr->nla_type); break; diff --git a/linux-user/generic/fcntl.h b/linux-user/generic/fcntl.h index a775a491e9..9f727d4df2 100644 --- a/linux-user/generic/fcntl.h +++ b/linux-user/generic/fcntl.h @@ -120,6 +120,7 @@ struct target_f_owner_ex { #define TARGET_F_SHLCK 8 #endif +#ifndef TARGET_HAVE_ARCH_STRUCT_FLOCK #ifndef TARGET_ARCH_FLOCK_PAD #define TARGET_ARCH_FLOCK_PAD #endif @@ -129,13 +130,12 @@ struct target_flock { short l_whence; abi_long l_start; abi_long l_len; -#if defined(TARGET_MIPS) - abi_long l_sysid; -#endif int l_pid; TARGET_ARCH_FLOCK_PAD }; +#endif +#ifndef TARGET_HAVE_ARCH_STRUCT_FLOCK64 #ifndef TARGET_ARCH_FLOCK64_PAD #define TARGET_ARCH_FLOCK64_PAD #endif @@ -149,3 +149,5 @@ struct target_flock64 { TARGET_ARCH_FLOCK64_PAD }; #endif + +#endif diff --git a/linux-user/mips/cpu_loop.c b/linux-user/mips/cpu_loop.c index 43ba267547..0ba894fa7a 100644 --- a/linux-user/mips/cpu_loop.c +++ b/linux-user/mips/cpu_loop.c @@ -540,6 +540,23 @@ done_syscall: info.si_code = TARGET_ILL_ILLOPC; queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); break; + case EXCP_FPE: + info.si_signo = TARGET_SIGFPE; + info.si_errno = 0; + info.si_code = TARGET_FPE_FLTUNK; + if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID) { + info.si_code = TARGET_FPE_FLTINV; + } else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_DIV0) { + info.si_code = TARGET_FPE_FLTDIV; + } else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_OVERFLOW) { + info.si_code = TARGET_FPE_FLTOVF; + } else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_UNDERFLOW) { + info.si_code = TARGET_FPE_FLTUND; + } else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INEXACT) { + info.si_code = TARGET_FPE_FLTRES; + } + queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + break; /* The code below was inspired by the MIPS Linux kernel trap * handling code in arch/mips/kernel/traps.c. */ diff --git a/linux-user/mips/target_fcntl.h b/linux-user/mips/target_fcntl.h index 000527cc95..6fc7b8a12b 100644 --- a/linux-user/mips/target_fcntl.h +++ b/linux-user/mips/target_fcntl.h @@ -27,8 +27,21 @@ #define TARGET_F_SETOWN 24 /* for sockets. */ #define TARGET_F_GETOWN 23 /* for sockets. */ -#define TARGET_ARCH_FLOCK_PAD abi_long pad[4]; -#define TARGET_ARCH_FLOCK64_PAD +#if (TARGET_ABI_BITS == 32) + +struct target_flock { + short l_type; + short l_whence; + abi_long l_start; + abi_long l_len; + abi_long l_sysid; + int l_pid; + abi_long pad[4]; +}; + +#define TARGET_HAVE_ARCH_STRUCT_FLOCK + +#endif #define TARGET_F_GETLK64 33 /* using 'struct flock64' */ #define TARGET_F_SETLK64 34 diff --git a/linux-user/riscv/syscall_nr.h b/linux-user/riscv/syscall_nr.h index dab6509e3a..5c87282209 100644 --- a/linux-user/riscv/syscall_nr.h +++ b/linux-user/riscv/syscall_nr.h @@ -72,7 +72,11 @@ #define TARGET_NR_pipe2 59 #define TARGET_NR_quotactl 60 #define TARGET_NR_getdents64 61 +#ifdef TARGET_RISCV32 +#define TARGET_NR__llseek 62 +#else #define TARGET_NR_lseek 62 +#endif #define TARGET_NR_read 63 #define TARGET_NR_write 64 #define TARGET_NR_readv 65 @@ -286,7 +290,16 @@ #define TARGET_NR_membarrier 283 #define TARGET_NR_mlock2 284 #define TARGET_NR_copy_file_range 285 +#define TARGET_NR_preadv2 286 +#define TARGET_NR_pwritev2 287 +#define TARGET_NR_pkey_mprotect 288 +#define TARGET_NR_pkey_alloc 289 +#define TARGET_NR_pkey_free 290 +#define TARGET_NR_statx 291 +#define TARGET_NR_io_pgetevents 292 +#define TARGET_NR_rseq 293 +#define TARGET_NR_kexec_file_load 294 -#define TARGET_NR_syscalls (TARGET_NR_copy_file_range + 1) +#define TARGET_NR_syscalls (TARGET_NR_kexec_file_load + 1) #endif diff --git a/linux-user/strace.c b/linux-user/strace.c index 6f72a74c09..c80e93b5db 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -976,6 +976,76 @@ UNUSED static struct flags msg_flags[] = { FLAG_END, }; +UNUSED static struct flags statx_flags[] = { +#ifdef AT_EMPTY_PATH + FLAG_GENERIC(AT_EMPTY_PATH), +#endif +#ifdef AT_NO_AUTOMOUNT + FLAG_GENERIC(AT_NO_AUTOMOUNT), +#endif +#ifdef AT_SYMLINK_NOFOLLOW + FLAG_GENERIC(AT_SYMLINK_NOFOLLOW), +#endif +#ifdef AT_STATX_SYNC_AS_STAT + FLAG_GENERIC(AT_STATX_SYNC_AS_STAT), +#endif +#ifdef AT_STATX_FORCE_SYNC + FLAG_GENERIC(AT_STATX_FORCE_SYNC), +#endif +#ifdef AT_STATX_DONT_SYNC + FLAG_GENERIC(AT_STATX_DONT_SYNC), +#endif + FLAG_END, +}; + +UNUSED static struct flags statx_mask[] = { +/* This must come first, because it includes everything. */ +#ifdef STATX_ALL + FLAG_GENERIC(STATX_ALL), +#endif +/* This must come second; it includes everything except STATX_BTIME. */ +#ifdef STATX_BASIC_STATS + FLAG_GENERIC(STATX_BASIC_STATS), +#endif +#ifdef STATX_TYPE + FLAG_GENERIC(STATX_TYPE), +#endif +#ifdef STATX_MODE + FLAG_GENERIC(STATX_MODE), +#endif +#ifdef STATX_NLINK + FLAG_GENERIC(STATX_NLINK), +#endif +#ifdef STATX_UID + FLAG_GENERIC(STATX_UID), +#endif +#ifdef STATX_GID + FLAG_GENERIC(STATX_GID), +#endif +#ifdef STATX_ATIME + FLAG_GENERIC(STATX_ATIME), +#endif +#ifdef STATX_MTIME + FLAG_GENERIC(STATX_MTIME), +#endif +#ifdef STATX_CTIME + FLAG_GENERIC(STATX_CTIME), +#endif +#ifdef STATX_INO + FLAG_GENERIC(STATX_INO), +#endif +#ifdef STATX_SIZE + FLAG_GENERIC(STATX_SIZE), +#endif +#ifdef STATX_BLOCKS + FLAG_GENERIC(STATX_BLOCKS), +#endif +#ifdef STATX_BTIME + FLAG_GENERIC(STATX_BTIME), +#endif + FLAG_END, +}; + /* * print_xxx utility functions. These are used to print syscall * parameters in certain format. All of these have parameter @@ -2611,6 +2681,22 @@ print_tgkill(const struct syscallname *name, } #endif +#ifdef TARGET_NR_statx +static void +print_statx(const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + print_syscall_prologue(name); + print_at_dirfd(arg0, 0); + print_string(arg1, 0); + print_flags(statx_flags, arg2, 0); + print_flags(statx_mask, arg3, 0); + print_pointer(arg4, 1); + print_syscall_epilogue(name); +} +#endif + /* * An array of all of the syscalls we know about */ diff --git a/linux-user/strace.list b/linux-user/strace.list index db21ce4177..63a946642d 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -1650,3 +1650,6 @@ #ifdef TARGET_NR_atomic_barrier { TARGET_NR_atomic_barrier, "atomic_barrier", NULL, NULL, NULL }, #endif +#ifdef TARGET_NR_statx +{ TARGET_NR_statx, "statx", NULL, print_statx, NULL }, +#endif diff --git a/linux-user/syscall.c b/linux-user/syscall.c index d2c9817938..39a37496fe 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -238,6 +238,7 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \ #define __NR_sys_inotify_init __NR_inotify_init #define __NR_sys_inotify_add_watch __NR_inotify_add_watch #define __NR_sys_inotify_rm_watch __NR_inotify_rm_watch +#define __NR_sys_statx __NR_statx #if defined(__alpha__) || defined(__x86_64__) || defined(__s390x__) #define __NR__llseek __NR_lseek @@ -316,6 +317,14 @@ _syscall5(int, kcmp, pid_t, pid1, pid_t, pid2, int, type, unsigned long, idx1, unsigned long, idx2) #endif +/* + * It is assumed that struct statx is architecture independent. + */ +#if defined(TARGET_NR_statx) && defined(__NR_statx) +_syscall5(int, sys_statx, int, dirfd, const char *, pathname, int, flags, + unsigned int, mask, struct target_statx *, statxbuf) +#endif + static bitmask_transtbl fcntl_flags_tbl[] = { { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, }, { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, }, @@ -6516,6 +6525,48 @@ static inline abi_long host_to_target_stat64(void *cpu_env, } #endif +#if defined(TARGET_NR_statx) && defined(__NR_statx) +static inline abi_long host_to_target_statx(struct target_statx *host_stx, + abi_ulong target_addr) +{ + struct target_statx *target_stx; + + if (!lock_user_struct(VERIFY_WRITE, target_stx, target_addr, 0)) { + return -TARGET_EFAULT; + } + memset(target_stx, 0, sizeof(*target_stx)); + + __put_user(host_stx->stx_mask, &target_stx->stx_mask); + __put_user(host_stx->stx_blksize, &target_stx->stx_blksize); + __put_user(host_stx->stx_attributes, &target_stx->stx_attributes); + __put_user(host_stx->stx_nlink, &target_stx->stx_nlink); + __put_user(host_stx->stx_uid, &target_stx->stx_uid); + __put_user(host_stx->stx_gid, &target_stx->stx_gid); + __put_user(host_stx->stx_mode, &target_stx->stx_mode); + __put_user(host_stx->stx_ino, &target_stx->stx_ino); + __put_user(host_stx->stx_size, &target_stx->stx_size); + __put_user(host_stx->stx_blocks, &target_stx->stx_blocks); + __put_user(host_stx->stx_attributes_mask, &target_stx->stx_attributes_mask); + __put_user(host_stx->stx_atime.tv_sec, &target_stx->stx_atime.tv_sec); + __put_user(host_stx->stx_atime.tv_nsec, &target_stx->stx_atime.tv_nsec); + __put_user(host_stx->stx_btime.tv_sec, &target_stx->stx_atime.tv_sec); + __put_user(host_stx->stx_btime.tv_nsec, &target_stx->stx_atime.tv_nsec); + __put_user(host_stx->stx_ctime.tv_sec, &target_stx->stx_atime.tv_sec); + __put_user(host_stx->stx_ctime.tv_nsec, &target_stx->stx_atime.tv_nsec); + __put_user(host_stx->stx_mtime.tv_sec, &target_stx->stx_atime.tv_sec); + __put_user(host_stx->stx_mtime.tv_nsec, &target_stx->stx_atime.tv_nsec); + __put_user(host_stx->stx_rdev_major, &target_stx->stx_rdev_major); + __put_user(host_stx->stx_rdev_minor, &target_stx->stx_rdev_minor); + __put_user(host_stx->stx_dev_major, &target_stx->stx_dev_major); + __put_user(host_stx->stx_dev_minor, &target_stx->stx_dev_minor); + + unlock_user_struct(target_stx, target_addr, 1); + + return 0; +} +#endif + + /* ??? Using host futex calls even when target atomic operations are not really atomic probably breaks things. However implementing futexes locally would make futexes shared between multiple processes @@ -7094,7 +7145,8 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, abi_long ret; #if defined(TARGET_NR_stat) || defined(TARGET_NR_stat64) \ || defined(TARGET_NR_lstat) || defined(TARGET_NR_lstat64) \ - || defined(TARGET_NR_fstat) || defined(TARGET_NR_fstat64) + || defined(TARGET_NR_fstat) || defined(TARGET_NR_fstat64) \ + || defined(TARGET_NR_statx) struct stat st; #endif #if defined(TARGET_NR_statfs) || defined(TARGET_NR_statfs64) \ @@ -10172,6 +10224,67 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, ret = host_to_target_stat64(cpu_env, arg3, &st); return ret; #endif +#if defined(TARGET_NR_statx) + case TARGET_NR_statx: + { + struct target_statx *target_stx; + int dirfd = arg1; + int flags = arg3; + + p = lock_user_string(arg2); + if (p == NULL) { + return -TARGET_EFAULT; + } +#if defined(__NR_statx) + { + /* + * It is assumed that struct statx is architecture independent. + */ + struct target_statx host_stx; + int mask = arg4; + + ret = get_errno(sys_statx(dirfd, p, flags, mask, &host_stx)); + if (!is_error(ret)) { + if (host_to_target_statx(&host_stx, arg5) != 0) { + unlock_user(p, arg2, 0); + return -TARGET_EFAULT; + } + } + + if (ret != -TARGET_ENOSYS) { + unlock_user(p, arg2, 0); + return ret; + } + } +#endif + ret = get_errno(fstatat(dirfd, path(p), &st, flags)); + unlock_user(p, arg2, 0); + + if (!is_error(ret)) { + if (!lock_user_struct(VERIFY_WRITE, target_stx, arg5, 0)) { + return -TARGET_EFAULT; + } + memset(target_stx, 0, sizeof(*target_stx)); + __put_user(major(st.st_dev), &target_stx->stx_dev_major); + __put_user(minor(st.st_dev), &target_stx->stx_dev_minor); + __put_user(st.st_ino, &target_stx->stx_ino); + __put_user(st.st_mode, &target_stx->stx_mode); + __put_user(st.st_uid, &target_stx->stx_uid); + __put_user(st.st_gid, &target_stx->stx_gid); + __put_user(st.st_nlink, &target_stx->stx_nlink); + __put_user(major(st.st_rdev), &target_stx->stx_rdev_major); + __put_user(minor(st.st_rdev), &target_stx->stx_rdev_minor); + __put_user(st.st_size, &target_stx->stx_size); + __put_user(st.st_blksize, &target_stx->stx_blksize); + __put_user(st.st_blocks, &target_stx->stx_blocks); + __put_user(st.st_atime, &target_stx->stx_atime.tv_sec); + __put_user(st.st_mtime, &target_stx->stx_mtime.tv_sec); + __put_user(st.st_ctime, &target_stx->stx_ctime.tv_sec); + unlock_user_struct(target_stx, arg5, 1); + } + } + return ret; +#endif #ifdef TARGET_NR_lchown case TARGET_NR_lchown: if (!(p = lock_user_string(arg1))) diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 3175440e9d..fffa89f256 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -2537,4 +2537,41 @@ struct target_user_cap_data { /* Return size of the log buffer */ #define TARGET_SYSLOG_ACTION_SIZE_BUFFER 10 +struct target_statx_timestamp { + int64_t tv_sec; + uint32_t tv_nsec; + int32_t __reserved; +}; + +struct target_statx { + /* 0x00 */ + uint32_t stx_mask; /* What results were written [uncond] */ + uint32_t stx_blksize; /* Preferred general I/O size [uncond] */ + uint64_t stx_attributes; /* Flags conveying information about the file */ + /* 0x10 */ + uint32_t stx_nlink; /* Number of hard links */ + uint32_t stx_uid; /* User ID of owner */ + uint32_t stx_gid; /* Group ID of owner */ + uint16_t stx_mode; /* File mode */ + uint16_t __spare0[1]; + /* 0x20 */ + uint64_t stx_ino; /* Inode number */ + uint64_t stx_size; /* File size */ + uint64_t stx_blocks; /* Number of 512-byte blocks allocated */ + uint64_t stx_attributes_mask; /* Mask to show what is supported */ + /* 0x40 */ + struct target_statx_timestamp stx_atime; /* Last access time */ + struct target_statx_timestamp stx_btime; /* File creation time */ + struct target_statx_timestamp stx_ctime; /* Last attribute change time */ + struct target_statx_timestamp stx_mtime; /* Last data modification time */ + /* 0x80 */ + uint32_t stx_rdev_major; /* Device ID of special file [if bdev/cdev] */ + uint32_t stx_rdev_minor; + uint32_t stx_dev_major; /* ID of device containing file [uncond] */ + uint32_t stx_dev_minor; + /* 0x90 */ + uint64_t __spare2[14]; /* Spare space for future expansion */ + /* 0x100 */ +}; + #endif @@ -2723,6 +2723,13 @@ void memory_listener_unregister(MemoryListener *listener) listener->address_space = NULL; } +void address_space_remove_listeners(AddressSpace *as) +{ + while (!QTAILQ_EMPTY(&as->listeners)) { + memory_listener_unregister(QTAILQ_FIRST(&as->listeners)); + } +} + void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name) { memory_region_ref(root); diff --git a/migration/colo.c b/migration/colo.c index 8c1644091f..9f84b1fa3c 100644 --- a/migration/colo.c +++ b/migration/colo.c @@ -259,6 +259,8 @@ ReplicationStatus *qmp_query_xen_replication_status(Error **errp) void qmp_xen_colo_do_checkpoint(Error **errp) { replication_do_checkpoint_all(errp); + /* Notify all filters of all NIC to do checkpoint */ + colo_notify_filters_event(COLO_EVENT_CHECKPOINT, errp); } #endif diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c index c283dde0e9..7cccedbd5b 100644 --- a/monitor/hmp-cmds.c +++ b/monitor/hmp-cmds.c @@ -14,7 +14,7 @@ */ #include "qemu/osdep.h" -#include "hmp.h" +#include "monitor/hmp.h" #include "net/net.h" #include "net/eth.h" #include "chardev/char.h" @@ -27,6 +27,7 @@ #include "monitor/monitor-internal.h" #include "monitor/qdev.h" #include "qapi/error.h" +#include "qapi/clone-visitor.h" #include "qapi/opts-visitor.h" #include "qapi/qapi-builtin-visit.h" #include "qapi/qapi-commands-block.h" @@ -34,10 +35,12 @@ #include "qapi/qapi-commands-migration.h" #include "qapi/qapi-commands-misc.h" #include "qapi/qapi-commands-net.h" +#include "qapi/qapi-commands-qdev.h" #include "qapi/qapi-commands-rocker.h" #include "qapi/qapi-commands-run-state.h" #include "qapi/qapi-commands-tpm.h" #include "qapi/qapi-commands-ui.h" +#include "qapi/qapi-visit-net.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qerror.h" #include "qapi/string-input-visitor.h" @@ -59,7 +62,7 @@ #include <spice/enums.h> #endif -static void hmp_handle_error(Monitor *mon, Error **errp) +void hmp_handle_error(Monitor *mon, Error **errp) { assert(errp); if (*errp) { @@ -67,6 +70,32 @@ static void hmp_handle_error(Monitor *mon, Error **errp) } } +/* + * Produce a strList from a comma separated list. + * A NULL or empty input string return NULL. + */ +static strList *strList_from_comma_list(const char *in) +{ + strList *res = NULL; + strList **hook = &res; + + while (in && in[0]) { + char *comma = strchr(in, ','); + *hook = g_new0(strList, 1); + + if (comma) { + (*hook)->value = g_strndup(in, comma - in); + in = comma + 1; /* skip the , */ + } else { + (*hook)->value = g_strdup(in); + in = NULL; + } + hook = &(*hook)->next; + } + + return res; +} + void hmp_info_name(Monitor *mon, const QDict *qdict) { NameInfo *info; @@ -455,27 +484,6 @@ void hmp_info_migrate_cache_size(Monitor *mon, const QDict *qdict) qmp_query_migrate_cache_size(NULL) >> 10); } -void hmp_info_cpus(Monitor *mon, const QDict *qdict) -{ - CpuInfoFastList *cpu_list, *cpu; - - cpu_list = qmp_query_cpus_fast(NULL); - - for (cpu = cpu_list; cpu; cpu = cpu->next) { - int active = ' '; - - if (cpu->value->cpu_index == monitor_get_cpu_index()) { - active = '*'; - } - - monitor_printf(mon, "%c CPU #%" PRId64 ":", active, - cpu->value->cpu_index); - monitor_printf(mon, " thread_id=%" PRId64 "\n", cpu->value->thread_id); - } - - qapi_free_CpuInfoFastList(cpu_list); -} - static void print_block_info(Monitor *mon, BlockInfo *info, BlockDeviceInfo *inserted, bool verbose) { @@ -1631,7 +1639,18 @@ void hmp_info_snapshots(Monitor *mon, const QDict *qdict) void hmp_announce_self(Monitor *mon, const QDict *qdict) { - qmp_announce_self(migrate_announce_params(), NULL); + const char *interfaces_str = qdict_get_try_str(qdict, "interfaces"); + const char *id = qdict_get_try_str(qdict, "id"); + AnnounceParameters *params = QAPI_CLONE(AnnounceParameters, + migrate_announce_params()); + + qapi_free_strList(params->interfaces); + params->interfaces = strList_from_comma_list(interfaces_str); + params->has_interfaces = params->interfaces != NULL; + params->id = g_strdup(id); + params->has_id = !!params->id; + qmp_announce_self(params, NULL); + qapi_free_AnnounceParameters(params); } void hmp_migrate_cancel(Monitor *mon, const QDict *qdict) @@ -2179,64 +2198,6 @@ void hmp_device_del(Monitor *mon, const QDict *qdict) hmp_handle_error(mon, &err); } -void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict) -{ - Error *err = NULL; - bool win_dmp = qdict_get_try_bool(qdict, "windmp", false); - bool paging = qdict_get_try_bool(qdict, "paging", false); - bool zlib = qdict_get_try_bool(qdict, "zlib", false); - bool lzo = qdict_get_try_bool(qdict, "lzo", false); - bool snappy = qdict_get_try_bool(qdict, "snappy", false); - const char *file = qdict_get_str(qdict, "filename"); - bool has_begin = qdict_haskey(qdict, "begin"); - bool has_length = qdict_haskey(qdict, "length"); - bool has_detach = qdict_haskey(qdict, "detach"); - int64_t begin = 0; - int64_t length = 0; - bool detach = false; - enum DumpGuestMemoryFormat dump_format = DUMP_GUEST_MEMORY_FORMAT_ELF; - char *prot; - - if (zlib + lzo + snappy + win_dmp > 1) { - error_setg(&err, "only one of '-z|-l|-s|-w' can be set"); - hmp_handle_error(mon, &err); - return; - } - - if (win_dmp) { - dump_format = DUMP_GUEST_MEMORY_FORMAT_WIN_DMP; - } - - if (zlib) { - dump_format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_ZLIB; - } - - if (lzo) { - dump_format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_LZO; - } - - if (snappy) { - dump_format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_SNAPPY; - } - - if (has_begin) { - begin = qdict_get_int(qdict, "begin"); - } - if (has_length) { - length = qdict_get_int(qdict, "length"); - } - if (has_detach) { - detach = qdict_get_bool(qdict, "detach"); - } - - prot = g_strconcat("file:", file, NULL); - - qmp_dump_guest_memory(paging, prot, true, detach, has_begin, begin, - has_length, length, true, dump_format, &err); - hmp_handle_error(mon, &err); - g_free(prot); -} - void hmp_netdev_add(Monitor *mon, const QDict *qdict) { Error *err = NULL; @@ -2470,18 +2431,6 @@ void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict) hmp_handle_error(mon, &err); } -void hmp_cpu_add(Monitor *mon, const QDict *qdict) -{ - int cpuid; - Error *err = NULL; - - error_report("cpu_add is deprecated, please use device_add instead"); - - cpuid = qdict_get_int(qdict, "id"); - qmp_cpu_add(cpuid, &err); - hmp_handle_error(mon, &err); -} - void hmp_chardev_add(Monitor *mon, const QDict *qdict) { const char *args = qdict_get_str(qdict, "args"); @@ -2613,41 +2562,6 @@ void hmp_object_del(Monitor *mon, const QDict *qdict) hmp_handle_error(mon, &err); } -void hmp_info_memdev(Monitor *mon, const QDict *qdict) -{ - Error *err = NULL; - MemdevList *memdev_list = qmp_query_memdev(&err); - MemdevList *m = memdev_list; - Visitor *v; - char *str; - - while (m) { - v = string_output_visitor_new(false, &str); - visit_type_uint16List(v, NULL, &m->value->host_nodes, NULL); - monitor_printf(mon, "memory backend: %s\n", m->value->id); - monitor_printf(mon, " size: %" PRId64 "\n", m->value->size); - monitor_printf(mon, " merge: %s\n", - m->value->merge ? "true" : "false"); - monitor_printf(mon, " dump: %s\n", - m->value->dump ? "true" : "false"); - monitor_printf(mon, " prealloc: %s\n", - m->value->prealloc ? "true" : "false"); - monitor_printf(mon, " policy: %s\n", - HostMemPolicy_str(m->value->policy)); - visit_complete(v, &str); - monitor_printf(mon, " host nodes: %s\n", str); - - g_free(str); - visit_free(v); - m = m->next; - } - - monitor_printf(mon, "\n"); - - qapi_free_MemdevList(memdev_list); - hmp_handle_error(mon, &err); -} - void hmp_info_memory_devices(Monitor *mon, const QDict *qdict) { Error *err = NULL; @@ -2713,54 +2627,6 @@ void hmp_info_iothreads(Monitor *mon, const QDict *qdict) qapi_free_IOThreadInfoList(info_list); } -void hmp_qom_list(Monitor *mon, const QDict *qdict) -{ - const char *path = qdict_get_try_str(qdict, "path"); - ObjectPropertyInfoList *list; - Error *err = NULL; - - if (path == NULL) { - monitor_printf(mon, "/\n"); - return; - } - - list = qmp_qom_list(path, &err); - if (err == NULL) { - ObjectPropertyInfoList *start = list; - while (list != NULL) { - ObjectPropertyInfo *value = list->value; - - monitor_printf(mon, "%s (%s)\n", - value->name, value->type); - list = list->next; - } - qapi_free_ObjectPropertyInfoList(start); - } - hmp_handle_error(mon, &err); -} - -void hmp_qom_set(Monitor *mon, const QDict *qdict) -{ - const char *path = qdict_get_str(qdict, "path"); - const char *property = qdict_get_str(qdict, "property"); - const char *value = qdict_get_str(qdict, "value"); - Error *err = NULL; - bool ambiguous = false; - Object *obj; - - obj = object_resolve_path(path, &ambiguous); - if (obj == NULL) { - error_set(&err, ERROR_CLASS_DEVICE_NOT_FOUND, - "Device '%s' not found", path); - } else { - if (ambiguous) { - monitor_printf(mon, "Warning: Path '%s' is ambiguous\n", path); - } - object_property_parse(obj, value, property, &err); - } - hmp_handle_error(mon, &err); -} - void hmp_rocker(Monitor *mon, const QDict *qdict) { const char *name = qdict_get_str(qdict, "name"); @@ -3063,70 +2929,11 @@ void hmp_rocker_of_dpa_groups(Monitor *mon, const QDict *qdict) qapi_free_RockerOfDpaGroupList(list); } -void hmp_info_dump(Monitor *mon, const QDict *qdict) -{ - DumpQueryResult *result = qmp_query_dump(NULL); - - assert(result && result->status < DUMP_STATUS__MAX); - monitor_printf(mon, "Status: %s\n", DumpStatus_str(result->status)); - - if (result->status == DUMP_STATUS_ACTIVE) { - float percent = 0; - assert(result->total != 0); - percent = 100.0 * result->completed / result->total; - monitor_printf(mon, "Finished: %.2f %%\n", percent); - } - - qapi_free_DumpQueryResult(result); -} - void hmp_info_ramblock(Monitor *mon, const QDict *qdict) { ram_block_dump(mon); } -void hmp_hotpluggable_cpus(Monitor *mon, const QDict *qdict) -{ - Error *err = NULL; - HotpluggableCPUList *l = qmp_query_hotpluggable_cpus(&err); - HotpluggableCPUList *saved = l; - CpuInstanceProperties *c; - - if (err != NULL) { - hmp_handle_error(mon, &err); - return; - } - - monitor_printf(mon, "Hotpluggable CPUs:\n"); - while (l) { - monitor_printf(mon, " type: \"%s\"\n", l->value->type); - monitor_printf(mon, " vcpus_count: \"%" PRIu64 "\"\n", - l->value->vcpus_count); - if (l->value->has_qom_path) { - monitor_printf(mon, " qom_path: \"%s\"\n", l->value->qom_path); - } - - c = l->value->props; - monitor_printf(mon, " CPUInstance Properties:\n"); - if (c->has_node_id) { - monitor_printf(mon, " node-id: \"%" PRIu64 "\"\n", c->node_id); - } - if (c->has_socket_id) { - monitor_printf(mon, " socket-id: \"%" PRIu64 "\"\n", c->socket_id); - } - if (c->has_core_id) { - monitor_printf(mon, " core-id: \"%" PRIu64 "\"\n", c->core_id); - } - if (c->has_thread_id) { - monitor_printf(mon, " thread-id: \"%" PRIu64 "\"\n", c->thread_id); - } - - l = l->next; - } - - qapi_free_HotpluggableCPUList(saved); -} - void hmp_info_vm_generation_id(Monitor *mon, const QDict *qdict) { Error *err = NULL; diff --git a/monitor/misc.c b/monitor/misc.c index bf9faceb86..00338c002a 100644 --- a/monitor/misc.c +++ b/monitor/misc.c @@ -36,7 +36,6 @@ #include "net/slirp.h" #include "chardev/char-mux.h" #include "ui/qemu-spice.h" -#include "sysemu/numa.h" #include "qemu/config-file.h" #include "qemu/ctype.h" #include "ui/console.h" @@ -48,6 +47,8 @@ #include "sysemu/hw_accel.h" #include "authz/list.h" #include "qapi/util.h" +#include "sysemu/blockdev.h" +#include "sysemu/sysemu.h" #include "sysemu/tcg.h" #include "sysemu/tpm.h" #include "qapi/qmp/qdict.h" @@ -56,13 +57,13 @@ #include "qom/object_interfaces.h" #include "trace/control.h" #include "monitor/hmp-target.h" +#include "monitor/hmp.h" #ifdef CONFIG_TRACE_SIMPLE #include "trace/simple.h" #endif #include "exec/memory.h" #include "exec/exec-all.h" #include "qemu/option.h" -#include "hmp.h" #include "qemu/thread.h" #include "block/qapi.h" #include "qapi/qapi-commands.h" @@ -1081,35 +1082,6 @@ static void hmp_info_mtree(Monitor *mon, const QDict *qdict) mtree_info(flatview, dispatch_tree, owner); } -static void hmp_info_numa(Monitor *mon, const QDict *qdict) -{ - int i; - NumaNodeMem *node_mem; - CpuInfoList *cpu_list, *cpu; - - cpu_list = qmp_query_cpus(&error_abort); - node_mem = g_new0(NumaNodeMem, nb_numa_nodes); - - query_numa_node_mem(node_mem); - monitor_printf(mon, "%d nodes\n", nb_numa_nodes); - for (i = 0; i < nb_numa_nodes; i++) { - monitor_printf(mon, "node %d cpus:", i); - for (cpu = cpu_list; cpu; cpu = cpu->next) { - if (cpu->value->has_props && cpu->value->props->has_node_id && - cpu->value->props->node_id == i) { - monitor_printf(mon, " %" PRIi64, cpu->value->CPU); - } - } - monitor_printf(mon, "\n"); - monitor_printf(mon, "node %d size: %" PRId64 " MB\n", i, - node_mem[i].node_mem >> 20); - monitor_printf(mon, "node %d plugged: %" PRId64 " MB\n", i, - node_mem[i].node_plugged_mem >> 20); - } - qapi_free_CpuInfoList(cpu_list); - g_free(node_mem); -} - #ifdef CONFIG_PROFILER int64_t dev_time; @@ -2338,16 +2310,3 @@ void monitor_init_globals(void) sortcmdlist(); qemu_mutex_init(&mon_fdsets_lock); } - -HotpluggableCPUList *qmp_query_hotpluggable_cpus(Error **errp) -{ - MachineState *ms = MACHINE(qdev_get_machine()); - MachineClass *mc = MACHINE_GET_CLASS(ms); - - if (!mc->has_hotpluggable_cpus) { - error_setg(errp, QERR_FEATURE_DISABLED, "query-hotpluggable-cpus"); - return NULL; - } - - return machine_query_hotpluggable_cpus(ms); -} diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c index 01ce77e129..b9ae40eec7 100644 --- a/monitor/qmp-cmds.c +++ b/monitor/qmp-cmds.c @@ -27,19 +27,15 @@ #include "ui/vnc.h" #include "sysemu/kvm.h" #include "sysemu/arch_init.h" -#include "hw/qdev.h" #include "sysemu/blockdev.h" #include "sysemu/block-backend.h" -#include "qom/qom-qobject.h" #include "qapi/error.h" #include "qapi/qapi-commands-block-core.h" +#include "qapi/qapi-commands-machine.h" #include "qapi/qapi-commands-misc.h" #include "qapi/qapi-commands-ui.h" -#include "qapi/qmp/qdict.h" #include "qapi/qmp/qerror.h" -#include "qapi/qobject-input-visitor.h" #include "hw/boards.h" -#include "qom/object_interfaces.h" #include "hw/mem/memory-device.h" #include "hw/acpi/acpi_dev_interface.h" @@ -118,18 +114,6 @@ void qmp_system_powerdown(Error **erp) qemu_system_powerdown_request(); } -void qmp_cpu_add(int64_t id, Error **errp) -{ - MachineClass *mc; - - mc = MACHINE_GET_CLASS(current_machine); - if (mc->hot_add_cpu) { - mc->hot_add_cpu(id, errp); - } else { - error_setg(errp, "Not supported"); - } -} - void qmp_x_exit_preconfig(Error **errp) { if (!runstate_check(RUN_STATE_PRECONFIG)) { @@ -201,69 +185,6 @@ void qmp_system_wakeup(Error **errp) qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, errp); } -ObjectPropertyInfoList *qmp_qom_list(const char *path, Error **errp) -{ - Object *obj; - bool ambiguous = false; - ObjectPropertyInfoList *props = NULL; - ObjectProperty *prop; - ObjectPropertyIterator iter; - - obj = object_resolve_path(path, &ambiguous); - if (obj == NULL) { - if (ambiguous) { - error_setg(errp, "Path '%s' is ambiguous", path); - } else { - error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, - "Device '%s' not found", path); - } - return NULL; - } - - object_property_iter_init(&iter, obj); - while ((prop = object_property_iter_next(&iter))) { - ObjectPropertyInfoList *entry = g_malloc0(sizeof(*entry)); - - entry->value = g_malloc0(sizeof(ObjectPropertyInfo)); - entry->next = props; - props = entry; - - entry->value->name = g_strdup(prop->name); - entry->value->type = g_strdup(prop->type); - } - - return props; -} - -void qmp_qom_set(const char *path, const char *property, QObject *value, - Error **errp) -{ - Object *obj; - - obj = object_resolve_path(path, NULL); - if (!obj) { - error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, - "Device '%s' not found", path); - return; - } - - object_property_set_qobject(obj, value, property, errp); -} - -QObject *qmp_qom_get(const char *path, const char *property, Error **errp) -{ - Object *obj; - - obj = object_resolve_path(path, NULL); - if (!obj) { - error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, - "Device '%s' not found", path); - return NULL; - } - - return object_property_get_qobject(obj, property, errp); -} - void qmp_set_password(const char *protocol, const char *password, bool has_connected, const char *connected, Error **errp) { @@ -412,208 +333,6 @@ void qmp_change(const char *device, const char *target, } } -static void qom_list_types_tramp(ObjectClass *klass, void *data) -{ - ObjectTypeInfoList *e, **pret = data; - ObjectTypeInfo *info; - ObjectClass *parent = object_class_get_parent(klass); - - info = g_malloc0(sizeof(*info)); - info->name = g_strdup(object_class_get_name(klass)); - info->has_abstract = info->abstract = object_class_is_abstract(klass); - if (parent) { - info->has_parent = true; - info->parent = g_strdup(object_class_get_name(parent)); - } - - e = g_malloc0(sizeof(*e)); - e->value = info; - e->next = *pret; - *pret = e; -} - -ObjectTypeInfoList *qmp_qom_list_types(bool has_implements, - const char *implements, - bool has_abstract, - bool abstract, - Error **errp) -{ - ObjectTypeInfoList *ret = NULL; - - object_class_foreach(qom_list_types_tramp, implements, abstract, &ret); - - return ret; -} - -/* Return a DevicePropertyInfo for a qdev property. - * - * If a qdev property with the given name does not exist, use the given default - * type. If the qdev property info should not be shown, return NULL. - * - * The caller must free the return value. - */ -static ObjectPropertyInfo *make_device_property_info(ObjectClass *klass, - const char *name, - const char *default_type, - const char *description) -{ - ObjectPropertyInfo *info; - Property *prop; - - do { - for (prop = DEVICE_CLASS(klass)->props; prop && prop->name; prop++) { - if (strcmp(name, prop->name) != 0) { - continue; - } - - /* - * TODO Properties without a parser are just for dirty hacks. - * qdev_prop_ptr is the only such PropertyInfo. It's marked - * for removal. This conditional should be removed along with - * it. - */ - if (!prop->info->set && !prop->info->create) { - return NULL; /* no way to set it, don't show */ - } - - info = g_malloc0(sizeof(*info)); - info->name = g_strdup(prop->name); - info->type = default_type ? g_strdup(default_type) - : g_strdup(prop->info->name); - info->has_description = !!prop->info->description; - info->description = g_strdup(prop->info->description); - return info; - } - klass = object_class_get_parent(klass); - } while (klass != object_class_by_name(TYPE_DEVICE)); - - /* Not a qdev property, use the default type */ - info = g_malloc0(sizeof(*info)); - info->name = g_strdup(name); - info->type = g_strdup(default_type); - info->has_description = !!description; - info->description = g_strdup(description); - - return info; -} - -ObjectPropertyInfoList *qmp_device_list_properties(const char *typename, - Error **errp) -{ - ObjectClass *klass; - Object *obj; - ObjectProperty *prop; - ObjectPropertyIterator iter; - ObjectPropertyInfoList *prop_list = NULL; - - klass = object_class_by_name(typename); - if (klass == NULL) { - error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, - "Device '%s' not found", typename); - return NULL; - } - - klass = object_class_dynamic_cast(klass, TYPE_DEVICE); - if (klass == NULL) { - error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "typename", TYPE_DEVICE); - return NULL; - } - - if (object_class_is_abstract(klass)) { - error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "typename", - "non-abstract device type"); - return NULL; - } - - obj = object_new(typename); - - object_property_iter_init(&iter, obj); - while ((prop = object_property_iter_next(&iter))) { - ObjectPropertyInfo *info; - ObjectPropertyInfoList *entry; - - /* Skip Object and DeviceState properties */ - if (strcmp(prop->name, "type") == 0 || - strcmp(prop->name, "realized") == 0 || - strcmp(prop->name, "hotpluggable") == 0 || - strcmp(prop->name, "hotplugged") == 0 || - strcmp(prop->name, "parent_bus") == 0) { - continue; - } - - /* Skip legacy properties since they are just string versions of - * properties that we already list. - */ - if (strstart(prop->name, "legacy-", NULL)) { - continue; - } - - info = make_device_property_info(klass, prop->name, prop->type, - prop->description); - if (!info) { - continue; - } - - entry = g_malloc0(sizeof(*entry)); - entry->value = info; - entry->next = prop_list; - prop_list = entry; - } - - object_unref(obj); - - return prop_list; -} - -ObjectPropertyInfoList *qmp_qom_list_properties(const char *typename, - Error **errp) -{ - ObjectClass *klass; - Object *obj = NULL; - ObjectProperty *prop; - ObjectPropertyIterator iter; - ObjectPropertyInfoList *prop_list = NULL; - - klass = object_class_by_name(typename); - if (klass == NULL) { - error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, - "Class '%s' not found", typename); - return NULL; - } - - klass = object_class_dynamic_cast(klass, TYPE_OBJECT); - if (klass == NULL) { - error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "typename", TYPE_OBJECT); - return NULL; - } - - if (object_class_is_abstract(klass)) { - object_class_property_iter_init(&iter, klass); - } else { - obj = object_new(typename); - object_property_iter_init(&iter, obj); - } - while ((prop = object_property_iter_next(&iter))) { - ObjectPropertyInfo *info; - ObjectPropertyInfoList *entry; - - info = g_malloc0(sizeof(*info)); - info->name = g_strdup(prop->name); - info->type = g_strdup(prop->type); - info->has_description = !!prop->description; - info->description = g_strdup(prop->description); - - entry = g_malloc0(sizeof(*entry)); - entry->value = info; - entry->next = prop_list; - prop_list = entry; - } - - object_unref(obj); - - return prop_list; -} - void qmp_add_client(const char *protocol, const char *fdname, bool has_skipauth, bool skipauth, bool has_tls, bool tls, Error **errp) @@ -658,38 +377,6 @@ void qmp_add_client(const char *protocol, const char *fdname, } -void qmp_object_add(const char *type, const char *id, - bool has_props, QObject *props, Error **errp) -{ - QDict *pdict; - Visitor *v; - Object *obj; - - if (props) { - pdict = qobject_to(QDict, props); - if (!pdict) { - error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "props", "dict"); - return; - } - qobject_ref(pdict); - } else { - pdict = qdict_new(); - } - - v = qobject_input_visitor_new(QOBJECT(pdict)); - obj = user_creatable_add_type(type, id, pdict, v, errp); - visit_free(v); - if (obj) { - object_unref(obj); - } - qobject_unref(pdict); -} - -void qmp_object_del(const char *id, Error **errp) -{ - user_creatable_del(id, errp); -} - MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp) { return qmp_memory_device_list(); diff --git a/net/announce.c b/net/announce.c index 91e9a6e267..db90d3bd4b 100644 --- a/net/announce.c +++ b/net/announce.c @@ -15,6 +15,8 @@ #include "qapi/qapi-commands-net.h" #include "trace.h" +static GData *named_timers; + int64_t qemu_announce_timer_step(AnnounceTimer *timer) { int64_t step; @@ -31,13 +33,38 @@ int64_t qemu_announce_timer_step(AnnounceTimer *timer) return step; } -void qemu_announce_timer_del(AnnounceTimer *timer) +/* + * If 'free_named' is true, then remove the timer from the list + * and free the timer itself. + */ +void qemu_announce_timer_del(AnnounceTimer *timer, bool free_named) { + bool free_timer = false; if (timer->tm) { timer_del(timer->tm); timer_free(timer->tm); timer->tm = NULL; } + qapi_free_strList(timer->params.interfaces); + timer->params.interfaces = NULL; + if (free_named && timer->params.has_id) { + AnnounceTimer *list_timer; + /* + * Sanity check: There should only be one timer on the list with + * the id. + */ + list_timer = g_datalist_get_data(&named_timers, timer->params.id); + assert(timer == list_timer); + free_timer = true; + g_datalist_remove_data(&named_timers, timer->params.id); + } + trace_qemu_announce_timer_del(free_named, free_timer, timer->params.id); + g_free(timer->params.id); + timer->params.id = NULL; + + if (free_timer) { + g_free(timer); + } } /* @@ -54,7 +81,7 @@ void qemu_announce_timer_reset(AnnounceTimer *timer, * We're under the BQL, so the current timer can't * be firing, so we should be able to delete it. */ - qemu_announce_timer_del(timer); + qemu_announce_timer_del(timer, false); QAPI_CLONE_MEMBERS(AnnounceParameters, &timer->params, params); timer->round = params->rounds; @@ -96,29 +123,53 @@ static int announce_self_create(uint8_t *buf, static void qemu_announce_self_iter(NICState *nic, void *opaque) { + AnnounceTimer *timer = opaque; uint8_t buf[60]; int len; + bool skip; + + if (timer->params.has_interfaces) { + strList *entry = timer->params.interfaces; + /* Skip unless we find our name in the requested list */ + skip = true; + + while (entry) { + if (!strcmp(entry->value, nic->ncs->name)) { + /* Found us */ + skip = false; + break; + } + entry = entry->next; + } + } else { + skip = false; + } + + trace_qemu_announce_self_iter(timer->params.has_id ? timer->params.id : "_", + nic->ncs->name, + qemu_ether_ntoa(&nic->conf->macaddr), skip); - trace_qemu_announce_self_iter(qemu_ether_ntoa(&nic->conf->macaddr)); - len = announce_self_create(buf, nic->conf->macaddr.a); + if (!skip) { + len = announce_self_create(buf, nic->conf->macaddr.a); - qemu_send_packet_raw(qemu_get_queue(nic), buf, len); + qemu_send_packet_raw(qemu_get_queue(nic), buf, len); - /* if the NIC provides it's own announcement support, use it as well */ - if (nic->ncs->info->announce) { - nic->ncs->info->announce(nic->ncs); + /* if the NIC provides it's own announcement support, use it as well */ + if (nic->ncs->info->announce) { + nic->ncs->info->announce(nic->ncs); + } } } static void qemu_announce_self_once(void *opaque) { AnnounceTimer *timer = (AnnounceTimer *)opaque; - qemu_foreach_nic(qemu_announce_self_iter, NULL); + qemu_foreach_nic(qemu_announce_self_iter, timer); if (--timer->round) { qemu_announce_timer_step(timer); } else { - qemu_announce_timer_del(timer); + qemu_announce_timer_del(timer, true); } } @@ -129,12 +180,24 @@ void qemu_announce_self(AnnounceTimer *timer, AnnounceParameters *params) if (params->rounds) { qemu_announce_self_once(timer); } else { - qemu_announce_timer_del(timer); + qemu_announce_timer_del(timer, true); } } void qmp_announce_self(AnnounceParameters *params, Error **errp) { - static AnnounceTimer announce_timer; - qemu_announce_self(&announce_timer, params); + AnnounceTimer *named_timer; + if (!params->has_id) { + params->id = g_strdup(""); + params->has_id = true; + } + + named_timer = g_datalist_get_data(&named_timers, params->id); + + if (!named_timer) { + named_timer = g_new0(AnnounceTimer, 1); + g_datalist_set_data(&named_timers, params->id, named_timer); + } + + qemu_announce_self(named_timer, params); } diff --git a/net/colo-compare.c b/net/colo-compare.c index 103297b7f4..909dd6c6eb 100644 --- a/net/colo-compare.c +++ b/net/colo-compare.c @@ -83,11 +83,14 @@ typedef struct CompareState { char *pri_indev; char *sec_indev; char *outdev; + char *notify_dev; CharBackend chr_pri_in; CharBackend chr_sec_in; CharBackend chr_out; + CharBackend chr_notify_dev; SocketReadState pri_rs; SocketReadState sec_rs; + SocketReadState notify_rs; bool vnet_hdr; /* @@ -117,16 +120,33 @@ enum { SECONDARY_IN, }; -static void colo_compare_inconsistency_notify(void) -{ - notifier_list_notify(&colo_compare_notifiers, - migrate_get_current()); -} static int compare_chr_send(CompareState *s, const uint8_t *buf, uint32_t size, - uint32_t vnet_hdr_len); + uint32_t vnet_hdr_len, + bool notify_remote_frame); + +static void notify_remote_frame(CompareState *s) +{ + char msg[] = "DO_CHECKPOINT"; + int ret = 0; + + ret = compare_chr_send(s, (uint8_t *)msg, strlen(msg), 0, true); + if (ret < 0) { + error_report("Notify Xen COLO-frame failed"); + } +} + +static void colo_compare_inconsistency_notify(CompareState *s) +{ + if (s->notify_dev) { + notify_remote_frame(s); + } else { + notifier_list_notify(&colo_compare_notifiers, + migrate_get_current()); + } +} static gint seq_sorter(Packet *a, Packet *b, gpointer data) { @@ -238,7 +258,8 @@ static void colo_release_primary_pkt(CompareState *s, Packet *pkt) ret = compare_chr_send(s, pkt->data, pkt->size, - pkt->vnet_hdr_len); + pkt->vnet_hdr_len, + false); if (ret < 0) { error_report("colo send primary packet failed"); } @@ -430,7 +451,7 @@ sec: qemu_hexdump((char *)spkt->data, stderr, "colo-compare spkt", spkt->size); - colo_compare_inconsistency_notify(); + colo_compare_inconsistency_notify(s); } } @@ -572,7 +593,7 @@ void colo_compare_unregister_notifier(Notifier *notify) } static int colo_old_packet_check_one_conn(Connection *conn, - void *user_data) + CompareState *s) { GList *result = NULL; int64_t check_time = REGULAR_PACKET_CHECK_MS; @@ -583,7 +604,7 @@ static int colo_old_packet_check_one_conn(Connection *conn, if (result) { /* Do checkpoint will flush old packet */ - colo_compare_inconsistency_notify(); + colo_compare_inconsistency_notify(s); return 0; } @@ -603,7 +624,7 @@ static void colo_old_packet_check(void *opaque) * If we find one old packet, stop finding job and notify * COLO frame do checkpoint. */ - g_queue_find_custom(&s->conn_list, NULL, + g_queue_find_custom(&s->conn_list, s, (GCompareFunc)colo_old_packet_check_one_conn); } @@ -632,7 +653,8 @@ static void colo_compare_packet(CompareState *s, Connection *conn, */ trace_colo_compare_main("packet different"); g_queue_push_head(&conn->primary_list, pkt); - colo_compare_inconsistency_notify(); + + colo_compare_inconsistency_notify(s); break; } } @@ -668,7 +690,8 @@ static void colo_compare_connection(void *opaque, void *user_data) static int compare_chr_send(CompareState *s, const uint8_t *buf, uint32_t size, - uint32_t vnet_hdr_len) + uint32_t vnet_hdr_len, + bool notify_remote_frame) { int ret = 0; uint32_t len = htonl(size); @@ -677,7 +700,14 @@ static int compare_chr_send(CompareState *s, return 0; } - ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)&len, sizeof(len)); + if (notify_remote_frame) { + ret = qemu_chr_fe_write_all(&s->chr_notify_dev, + (uint8_t *)&len, + sizeof(len)); + } else { + ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)&len, sizeof(len)); + } + if (ret != sizeof(len)) { goto err; } @@ -688,13 +718,26 @@ static int compare_chr_send(CompareState *s, * know how to parse net packet correctly. */ len = htonl(vnet_hdr_len); - ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)&len, sizeof(len)); + + if (!notify_remote_frame) { + ret = qemu_chr_fe_write_all(&s->chr_out, + (uint8_t *)&len, + sizeof(len)); + } + if (ret != sizeof(len)) { goto err; } } - ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)buf, size); + if (notify_remote_frame) { + ret = qemu_chr_fe_write_all(&s->chr_notify_dev, + (uint8_t *)buf, + size); + } else { + ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)buf, size); + } + if (ret != size) { goto err; } @@ -744,6 +787,19 @@ static void compare_sec_chr_in(void *opaque, const uint8_t *buf, int size) } } +static void compare_notify_chr(void *opaque, const uint8_t *buf, int size) +{ + CompareState *s = COLO_COMPARE(opaque); + int ret; + + ret = net_fill_rstate(&s->notify_rs, buf, size); + if (ret == -1) { + qemu_chr_fe_set_handlers(&s->chr_notify_dev, NULL, NULL, NULL, NULL, + NULL, NULL, true); + error_report("colo-compare notify_dev error"); + } +} + /* * Check old packet regularly so it can watch for any packets * that the secondary hasn't produced equivalents of. @@ -831,6 +887,11 @@ static void colo_compare_iothread(CompareState *s) qemu_chr_fe_set_handlers(&s->chr_sec_in, compare_chr_can_read, compare_sec_chr_in, NULL, NULL, s, s->worker_context, true); + if (s->notify_dev) { + qemu_chr_fe_set_handlers(&s->chr_notify_dev, compare_chr_can_read, + compare_notify_chr, NULL, NULL, + s, s->worker_context, true); + } colo_compare_timer_init(s); s->event_bh = qemu_bh_new(colo_compare_handle_event, s); @@ -897,6 +958,21 @@ static void compare_set_vnet_hdr(Object *obj, s->vnet_hdr = value; } +static char *compare_get_notify_dev(Object *obj, Error **errp) +{ + CompareState *s = COLO_COMPARE(obj); + + return g_strdup(s->notify_dev); +} + +static void compare_set_notify_dev(Object *obj, const char *value, Error **errp) +{ + CompareState *s = COLO_COMPARE(obj); + + g_free(s->notify_dev); + s->notify_dev = g_strdup(value); +} + static void compare_pri_rs_finalize(SocketReadState *pri_rs) { CompareState *s = container_of(pri_rs, CompareState, pri_rs); @@ -907,7 +983,8 @@ static void compare_pri_rs_finalize(SocketReadState *pri_rs) compare_chr_send(s, pri_rs->buf, pri_rs->packet_len, - pri_rs->vnet_hdr_len); + pri_rs->vnet_hdr_len, + false); } else { /* compare packet in the specified connection */ colo_compare_connection(conn, s); @@ -927,6 +1004,27 @@ static void compare_sec_rs_finalize(SocketReadState *sec_rs) } } +static void compare_notify_rs_finalize(SocketReadState *notify_rs) +{ + CompareState *s = container_of(notify_rs, CompareState, notify_rs); + + /* Get Xen colo-frame's notify and handle the message */ + char *data = g_memdup(notify_rs->buf, notify_rs->packet_len); + char msg[] = "COLO_COMPARE_GET_XEN_INIT"; + int ret; + + if (!strcmp(data, "COLO_USERSPACE_PROXY_INIT")) { + ret = compare_chr_send(s, (uint8_t *)msg, strlen(msg), 0, true); + if (ret < 0) { + error_report("Notify Xen COLO-frame INIT failed"); + } + } + + if (!strcmp(data, "COLO_CHECKPOINT")) { + /* colo-compare do checkpoint, flush pri packet and remove sec packet */ + g_queue_foreach(&s->conn_list, colo_flush_packets, s); + } +} /* * Return 0 is success. @@ -997,6 +1095,17 @@ static void colo_compare_complete(UserCreatable *uc, Error **errp) net_socket_rs_init(&s->pri_rs, compare_pri_rs_finalize, s->vnet_hdr); net_socket_rs_init(&s->sec_rs, compare_sec_rs_finalize, s->vnet_hdr); + /* Try to enable remote notify chardev, currently just for Xen COLO */ + if (s->notify_dev) { + if (find_and_check_chardev(&chr, s->notify_dev, errp) || + !qemu_chr_fe_init(&s->chr_notify_dev, chr, errp)) { + return; + } + + net_socket_rs_init(&s->notify_rs, compare_notify_rs_finalize, + s->vnet_hdr); + } + QTAILQ_INSERT_TAIL(&net_compares, s, next); g_queue_init(&s->conn_list); @@ -1024,7 +1133,8 @@ static void colo_flush_packets(void *opaque, void *user_data) compare_chr_send(s, pkt->data, pkt->size, - pkt->vnet_hdr_len); + pkt->vnet_hdr_len, + false); packet_destroy(pkt, NULL); } while (!g_queue_is_empty(&conn->secondary_list)) { @@ -1057,6 +1167,10 @@ static void colo_compare_init(Object *obj) (Object **)&s->iothread, object_property_allow_set_link, OBJ_PROP_LINK_STRONG, NULL); + /* This parameter just for Xen COLO */ + object_property_add_str(obj, "notify_dev", + compare_get_notify_dev, compare_set_notify_dev, + NULL); s->vnet_hdr = false; object_property_add_bool(obj, "vnet_hdr_support", compare_get_vnet_hdr, @@ -1071,6 +1185,10 @@ static void colo_compare_finalize(Object *obj) qemu_chr_fe_deinit(&s->chr_pri_in, false); qemu_chr_fe_deinit(&s->chr_sec_in, false); qemu_chr_fe_deinit(&s->chr_out, false); + if (s->notify_dev) { + qemu_chr_fe_deinit(&s->chr_notify_dev, false); + } + if (s->iothread) { colo_compare_timer_del(s); } @@ -1103,6 +1221,7 @@ static void colo_compare_finalize(Object *obj) g_free(s->pri_indev); g_free(s->sec_indev); g_free(s->outdev); + g_free(s->notify_dev); } static const TypeInfo colo_compare_info = { @@ -64,55 +64,42 @@ static QTAILQ_HEAD(, NetClientState) net_clients; /***********************************************************/ /* network device redirectors */ -static int get_str_sep(char *buf, int buf_size, const char **pp, int sep) -{ - const char *p, *p1; - int len; - p = *pp; - p1 = strchr(p, sep); - if (!p1) - return -1; - len = p1 - p; - p1++; - if (buf_size > 0) { - if (len > buf_size - 1) - len = buf_size - 1; - memcpy(buf, p, len); - buf[len] = '\0'; - } - *pp = p1; - return 0; -} - int parse_host_port(struct sockaddr_in *saddr, const char *str, Error **errp) { - char buf[512]; + gchar **substrings; struct hostent *he; - const char *p, *r; - int port; + const char *addr, *p, *r; + int port, ret = 0; - p = str; - if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) { + substrings = g_strsplit(str, ":", 2); + if (!substrings || !substrings[0] || !substrings[1]) { error_setg(errp, "host address '%s' doesn't contain ':' " "separating host from port", str); - return -1; + ret = -1; + goto out; } + + addr = substrings[0]; + p = substrings[1]; + saddr->sin_family = AF_INET; - if (buf[0] == '\0') { + if (addr[0] == '\0') { saddr->sin_addr.s_addr = 0; } else { - if (qemu_isdigit(buf[0])) { - if (!inet_aton(buf, &saddr->sin_addr)) { + if (qemu_isdigit(addr[0])) { + if (!inet_aton(addr, &saddr->sin_addr)) { error_setg(errp, "host address '%s' is not a valid " - "IPv4 address", buf); - return -1; + "IPv4 address", addr); + ret = -1; + goto out; } } else { - he = gethostbyname(buf); + he = gethostbyname(addr); if (he == NULL) { - error_setg(errp, "can't resolve host address '%s'", buf); - return - 1; + error_setg(errp, "can't resolve host address '%s'", addr); + ret = -1; + goto out; } saddr->sin_addr = *(struct in_addr *)he->h_addr; } @@ -120,10 +107,14 @@ int parse_host_port(struct sockaddr_in *saddr, const char *str, port = strtol(p, (char **)&r, 0); if (r == p) { error_setg(errp, "port number '%s' is invalid", p); - return -1; + ret = -1; + goto out; } saddr->sin_port = htons(port); - return 0; + +out: + g_strfreev(substrings); + return ret; } char *qemu_mac_strdup_printf(const uint8_t *macaddr) @@ -1105,6 +1096,7 @@ static void show_netdevs(void) static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp) { + gchar **substrings = NULL; void *object = NULL; Error *err = NULL; int ret = -1; @@ -1120,28 +1112,33 @@ static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp) const char *ip6_net = qemu_opt_get(opts, "ipv6-net"); if (ip6_net) { - char buf[strlen(ip6_net) + 1]; + char *prefix_addr; + unsigned long prefix_len = 64; /* Default 64bit prefix length. */ + + substrings = g_strsplit(ip6_net, "/", 2); + if (!substrings || !substrings[0]) { + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "ipv6-net", + "a valid IPv6 prefix"); + goto out; + } - if (get_str_sep(buf, sizeof(buf), &ip6_net, '/') < 0) { - /* Default 64bit prefix length. */ - qemu_opt_set(opts, "ipv6-prefix", ip6_net, &error_abort); - qemu_opt_set_number(opts, "ipv6-prefixlen", 64, &error_abort); - } else { + prefix_addr = substrings[0]; + + if (substrings[1]) { /* User-specified prefix length. */ - unsigned long len; int err; - qemu_opt_set(opts, "ipv6-prefix", buf, &error_abort); - err = qemu_strtoul(ip6_net, NULL, 10, &len); - + err = qemu_strtoul(substrings[1], NULL, 10, &prefix_len); if (err) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, - "ipv6-prefix", "a number"); - } else { - qemu_opt_set_number(opts, "ipv6-prefixlen", len, - &error_abort); + "ipv6-prefixlen", "a number"); + goto out; } } + + qemu_opt_set(opts, "ipv6-prefix", prefix_addr, &error_abort); + qemu_opt_set_number(opts, "ipv6-prefixlen", prefix_len, + &error_abort); qemu_opt_unset(opts, "ipv6-net"); } } @@ -1162,7 +1159,9 @@ static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp) qapi_free_NetLegacy(object); } +out: error_propagate(errp, err); + g_strfreev(substrings); visit_free(v); return ret; } diff --git a/net/trace-events b/net/trace-events index a7937f3f3a..ac57056497 100644 --- a/net/trace-events +++ b/net/trace-events @@ -1,7 +1,8 @@ # See docs/devel/tracing.txt for syntax documentation. # announce.c -qemu_announce_self_iter(const char *mac) "%s" +qemu_announce_self_iter(const char *id, const char *name, const char *mac, int skip) "%s:%s:%s skip: %d" +qemu_announce_timer_del(bool free_named, bool free_timer, char *id) "free named: %d free timer: %d id: %s" # vhost-user.c vhost_user_event(const char *chr, int event) "chr: %s got event: %d" diff --git a/pc-bios/openbios-ppc b/pc-bios/openbios-ppc Binary files differindex 4df553c8a3..aaeb2c6ecb 100644 --- a/pc-bios/openbios-ppc +++ b/pc-bios/openbios-ppc diff --git a/pc-bios/openbios-sparc32 b/pc-bios/openbios-sparc32 Binary files differindex 270c5000f9..b471b8739e 100644 --- a/pc-bios/openbios-sparc32 +++ b/pc-bios/openbios-sparc32 diff --git a/pc-bios/openbios-sparc64 b/pc-bios/openbios-sparc64 Binary files differindex a37a877b3e..8c77a06cff 100644 --- a/pc-bios/openbios-sparc64 +++ b/pc-bios/openbios-sparc64 diff --git a/pc-bios/spapr-rtas/Makefile b/pc-bios/spapr-rtas/Makefile index f26dd428b7..4b9bb12306 100644 --- a/pc-bios/spapr-rtas/Makefile +++ b/pc-bios/spapr-rtas/Makefile @@ -14,8 +14,11 @@ $(call set-vpath, $(SRC_PATH)/pc-bios/spapr-rtas) build-all: spapr-rtas.bin +%.o: %.S + $(call quiet-command,$(CCAS) -mbig -c -o $@ $<,"CCAS","$(TARGET_DIR)$@") + %.img: %.o - $(call quiet-command,$(CC) -nostdlib -o $@ $<,"Building","$(TARGET_DIR)$@") + $(call quiet-command,$(CC) -nostdlib -mbig -o $@ $<,"Building","$(TARGET_DIR)$@") %.bin: %.img $(call quiet-command,$(OBJCOPY) -O binary -j .text $< $@,"Building","$(TARGET_DIR)$@") diff --git a/python/qemu/__init__.py b/python/qemu/__init__.py index dbaf8a5311..6c919a3d56 100644 --- a/python/qemu/__init__.py +++ b/python/qemu/__init__.py @@ -12,17 +12,11 @@ # Based on qmp.py. # -import errno import logging import os -import subprocess -import re -import shutil -import socket -import tempfile from . import qmp - +from . import machine LOG = logging.getLogger(__name__) @@ -39,497 +33,3 @@ def kvm_available(target_arch=None): if target_arch != ADDITIONAL_ARCHES.get(host_arch): return False return os.access("/dev/kvm", os.R_OK | os.W_OK) - - -class QEMUMachineError(Exception): - """ - Exception called when an error in QEMUMachine happens. - """ - - -class QEMUMachineAddDeviceError(QEMUMachineError): - """ - Exception raised when a request to add a device can not be fulfilled - - The failures are caused by limitations, lack of information or conflicting - requests on the QEMUMachine methods. This exception does not represent - failures reported by the QEMU binary itself. - """ - -class MonitorResponseError(qmp.QMPError): - """ - Represents erroneous QMP monitor reply - """ - def __init__(self, reply): - try: - desc = reply["error"]["desc"] - except KeyError: - desc = reply - super(MonitorResponseError, self).__init__(desc) - self.reply = reply - - -class QEMUMachine(object): - """ - A QEMU VM - - Use this object as a context manager to ensure the QEMU process terminates:: - - with VM(binary) as vm: - ... - # vm is guaranteed to be shut down here - """ - - def __init__(self, binary, args=None, wrapper=None, name=None, - test_dir="/var/tmp", monitor_address=None, - socket_scm_helper=None): - ''' - Initialize a QEMUMachine - - @param binary: path to the qemu binary - @param args: list of extra arguments - @param wrapper: list of arguments used as prefix to qemu binary - @param name: prefix for socket and log file names (default: qemu-PID) - @param test_dir: where to create socket and log file - @param monitor_address: address for QMP monitor - @param socket_scm_helper: helper program, required for send_fd_scm() - @note: Qemu process is not started until launch() is used. - ''' - if args is None: - args = [] - if wrapper is None: - wrapper = [] - if name is None: - name = "qemu-%d" % os.getpid() - self._name = name - self._monitor_address = monitor_address - self._vm_monitor = None - self._qemu_log_path = None - self._qemu_log_file = None - self._popen = None - self._binary = binary - self._args = list(args) # Force copy args in case we modify them - self._wrapper = wrapper - self._events = [] - self._iolog = None - self._socket_scm_helper = socket_scm_helper - self._qmp = None - self._qemu_full_args = None - self._test_dir = test_dir - self._temp_dir = None - self._launched = False - self._machine = None - self._console_set = False - self._console_device_type = None - self._console_address = None - self._console_socket = None - - # just in case logging wasn't configured by the main script: - logging.basicConfig() - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - self.shutdown() - return False - - # This can be used to add an unused monitor instance. - def add_monitor_null(self): - self._args.append('-monitor') - self._args.append('null') - - def add_fd(self, fd, fdset, opaque, opts=''): - """ - Pass a file descriptor to the VM - """ - options = ['fd=%d' % fd, - 'set=%d' % fdset, - 'opaque=%s' % opaque] - if opts: - options.append(opts) - - # This did not exist before 3.4, but since then it is - # mandatory for our purpose - if hasattr(os, 'set_inheritable'): - os.set_inheritable(fd, True) - - self._args.append('-add-fd') - self._args.append(','.join(options)) - return self - - # Exactly one of fd and file_path must be given. - # (If it is file_path, the helper will open that file and pass its - # own fd) - def send_fd_scm(self, fd=None, file_path=None): - # In iotest.py, the qmp should always use unix socket. - assert self._qmp.is_scm_available() - if self._socket_scm_helper is None: - raise QEMUMachineError("No path to socket_scm_helper set") - if not os.path.exists(self._socket_scm_helper): - raise QEMUMachineError("%s does not exist" % - self._socket_scm_helper) - - # This did not exist before 3.4, but since then it is - # mandatory for our purpose - if hasattr(os, 'set_inheritable'): - os.set_inheritable(self._qmp.get_sock_fd(), True) - if fd is not None: - os.set_inheritable(fd, True) - - fd_param = ["%s" % self._socket_scm_helper, - "%d" % self._qmp.get_sock_fd()] - - if file_path is not None: - assert fd is None - fd_param.append(file_path) - else: - assert fd is not None - fd_param.append(str(fd)) - - devnull = open(os.path.devnull, 'rb') - proc = subprocess.Popen(fd_param, stdin=devnull, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, close_fds=False) - output = proc.communicate()[0] - if output: - LOG.debug(output) - - return proc.returncode - - @staticmethod - def _remove_if_exists(path): - """ - Remove file object at path if it exists - """ - try: - os.remove(path) - except OSError as exception: - if exception.errno == errno.ENOENT: - return - raise - - def is_running(self): - return self._popen is not None and self._popen.poll() is None - - def exitcode(self): - if self._popen is None: - return None - return self._popen.poll() - - def get_pid(self): - if not self.is_running(): - return None - return self._popen.pid - - def _load_io_log(self): - if self._qemu_log_path is not None: - with open(self._qemu_log_path, "r") as iolog: - self._iolog = iolog.read() - - def _base_args(self): - if isinstance(self._monitor_address, tuple): - moncdev = "socket,id=mon,host=%s,port=%s" % ( - self._monitor_address[0], - self._monitor_address[1]) - else: - moncdev = 'socket,id=mon,path=%s' % self._vm_monitor - args = ['-chardev', moncdev, - '-mon', 'chardev=mon,mode=control', - '-display', 'none', '-vga', 'none'] - if self._machine is not None: - args.extend(['-machine', self._machine]) - if self._console_set: - self._console_address = os.path.join(self._temp_dir, - self._name + "-console.sock") - chardev = ('socket,id=console,path=%s,server,nowait' % - self._console_address) - args.extend(['-chardev', chardev]) - if self._console_device_type is None: - args.extend(['-serial', 'chardev:console']) - else: - device = '%s,chardev=console' % self._console_device_type - args.extend(['-device', device]) - return args - - def _pre_launch(self): - self._temp_dir = tempfile.mkdtemp(dir=self._test_dir) - if self._monitor_address is not None: - self._vm_monitor = self._monitor_address - else: - self._vm_monitor = os.path.join(self._temp_dir, - self._name + "-monitor.sock") - self._qemu_log_path = os.path.join(self._temp_dir, self._name + ".log") - self._qemu_log_file = open(self._qemu_log_path, 'wb') - - self._qmp = qmp.QEMUMonitorProtocol(self._vm_monitor, - server=True) - - def _post_launch(self): - self._qmp.accept() - - def _post_shutdown(self): - if self._qemu_log_file is not None: - self._qemu_log_file.close() - self._qemu_log_file = None - - self._qemu_log_path = None - - if self._console_socket is not None: - self._console_socket.close() - self._console_socket = None - - if self._temp_dir is not None: - shutil.rmtree(self._temp_dir) - self._temp_dir = None - - def launch(self): - """ - Launch the VM and make sure we cleanup and expose the - command line/output in case of exception - """ - - if self._launched: - raise QEMUMachineError('VM already launched') - - self._iolog = None - self._qemu_full_args = None - try: - self._launch() - self._launched = True - except: - self.shutdown() - - LOG.debug('Error launching VM') - if self._qemu_full_args: - LOG.debug('Command: %r', ' '.join(self._qemu_full_args)) - if self._iolog: - LOG.debug('Output: %r', self._iolog) - raise - - def _launch(self): - """ - Launch the VM and establish a QMP connection - """ - devnull = open(os.path.devnull, 'rb') - self._pre_launch() - self._qemu_full_args = (self._wrapper + [self._binary] + - self._base_args() + self._args) - LOG.debug('VM launch command: %r', ' '.join(self._qemu_full_args)) - self._popen = subprocess.Popen(self._qemu_full_args, - stdin=devnull, - stdout=self._qemu_log_file, - stderr=subprocess.STDOUT, - shell=False, - close_fds=False) - self._post_launch() - - def wait(self): - """ - Wait for the VM to power off - """ - self._popen.wait() - self._qmp.close() - self._load_io_log() - self._post_shutdown() - - def shutdown(self): - """ - Terminate the VM and clean up - """ - if self.is_running(): - try: - self._qmp.cmd('quit') - self._qmp.close() - except: - self._popen.kill() - self._popen.wait() - - self._load_io_log() - self._post_shutdown() - - exitcode = self.exitcode() - if exitcode is not None and exitcode < 0: - msg = 'qemu received signal %i: %s' - if self._qemu_full_args: - command = ' '.join(self._qemu_full_args) - else: - command = '' - LOG.warn(msg, -exitcode, command) - - self._launched = False - - def qmp(self, cmd, conv_keys=True, **args): - """ - Invoke a QMP command and return the response dict - """ - qmp_args = dict() - for key, value in args.items(): - if conv_keys: - qmp_args[key.replace('_', '-')] = value - else: - qmp_args[key] = value - - return self._qmp.cmd(cmd, args=qmp_args) - - def command(self, cmd, conv_keys=True, **args): - """ - Invoke a QMP command. - On success return the response dict. - On failure raise an exception. - """ - reply = self.qmp(cmd, conv_keys, **args) - if reply is None: - raise qmp.QMPError("Monitor is closed") - if "error" in reply: - raise MonitorResponseError(reply) - return reply["return"] - - def get_qmp_event(self, wait=False): - """ - Poll for one queued QMP events and return it - """ - if len(self._events) > 0: - return self._events.pop(0) - return self._qmp.pull_event(wait=wait) - - def get_qmp_events(self, wait=False): - """ - Poll for queued QMP events and return a list of dicts - """ - events = self._qmp.get_events(wait=wait) - events.extend(self._events) - del self._events[:] - self._qmp.clear_events() - return events - - @staticmethod - def event_match(event, match=None): - """ - Check if an event matches optional match criteria. - - The match criteria takes the form of a matching subdict. The event is - checked to be a superset of the subdict, recursively, with matching - values whenever the subdict values are not None. - - This has a limitation that you cannot explicitly check for None values. - - Examples, with the subdict queries on the left: - - None matches any object. - - {"foo": None} matches {"foo": {"bar": 1}} - - {"foo": None} matches {"foo": 5} - - {"foo": {"abc": None}} does not match {"foo": {"bar": 1}} - - {"foo": {"rab": 2}} matches {"foo": {"bar": 1, "rab": 2}} - """ - if match is None: - return True - - try: - for key in match: - if key in event: - if not QEMUMachine.event_match(event[key], match[key]): - return False - else: - return False - return True - except TypeError: - # either match or event wasn't iterable (not a dict) - return match == event - - def event_wait(self, name, timeout=60.0, match=None): - """ - event_wait waits for and returns a named event from QMP with a timeout. - - name: The event to wait for. - timeout: QEMUMonitorProtocol.pull_event timeout parameter. - match: Optional match criteria. See event_match for details. - """ - return self.events_wait([(name, match)], timeout) - - def events_wait(self, events, timeout=60.0): - """ - events_wait waits for and returns a named event from QMP with a timeout. - - events: a sequence of (name, match_criteria) tuples. - The match criteria are optional and may be None. - See event_match for details. - timeout: QEMUMonitorProtocol.pull_event timeout parameter. - """ - def _match(event): - for name, match in events: - if (event['event'] == name and - self.event_match(event, match)): - return True - return False - - # Search cached events - for event in self._events: - if _match(event): - self._events.remove(event) - return event - - # Poll for new events - while True: - event = self._qmp.pull_event(wait=timeout) - if _match(event): - return event - self._events.append(event) - - return None - - def get_log(self): - """ - After self.shutdown or failed qemu execution, this returns the output - of the qemu process. - """ - return self._iolog - - def add_args(self, *args): - """ - Adds to the list of extra arguments to be given to the QEMU binary - """ - self._args.extend(args) - - def set_machine(self, machine_type): - """ - Sets the machine type - - If set, the machine type will be added to the base arguments - of the resulting QEMU command line. - """ - self._machine = machine_type - - def set_console(self, device_type=None): - """ - Sets the device type for a console device - - If set, the console device and a backing character device will - be added to the base arguments of the resulting QEMU command - line. - - This is a convenience method that will either use the provided - device type, or default to a "-serial chardev:console" command - line argument. - - The actual setting of command line arguments will be be done at - machine launch time, as it depends on the temporary directory - to be created. - - @param device_type: the device type, such as "isa-serial". If - None is given (the default value) a "-serial - chardev:console" command line argument will - be used instead, resorting to the machine's - default device type. - """ - self._console_set = True - self._console_device_type = device_type - - @property - def console_socket(self): - """ - Returns a socket connected to the console - """ - if self._console_socket is None: - self._console_socket = socket.socket(socket.AF_UNIX, - socket.SOCK_STREAM) - self._console_socket.connect(self._console_address) - return self._console_socket diff --git a/python/qemu/machine.py b/python/qemu/machine.py new file mode 100644 index 0000000000..49445e675b --- /dev/null +++ b/python/qemu/machine.py @@ -0,0 +1,531 @@ +""" +QEMU machine module: + +The machine module primarily provides the QEMUMachine class, +which provides facilities for managing the lifetime of a QEMU VM. +""" + +# Copyright (C) 2015-2016 Red Hat Inc. +# Copyright (C) 2012 IBM Corp. +# +# Authors: +# Fam Zheng <famz@redhat.com> +# +# This work is licensed under the terms of the GNU GPL, version 2. See +# the COPYING file in the top-level directory. +# +# Based on qmp.py. +# + +import errno +import logging +import os +import subprocess +import shutil +import socket +import tempfile + +from . import qmp + +LOG = logging.getLogger(__name__) + +class QEMUMachineError(Exception): + """ + Exception called when an error in QEMUMachine happens. + """ + + +class QEMUMachineAddDeviceError(QEMUMachineError): + """ + Exception raised when a request to add a device can not be fulfilled + + The failures are caused by limitations, lack of information or conflicting + requests on the QEMUMachine methods. This exception does not represent + failures reported by the QEMU binary itself. + """ + + +class MonitorResponseError(qmp.QMPError): + """ + Represents erroneous QMP monitor reply + """ + def __init__(self, reply): + try: + desc = reply["error"]["desc"] + except KeyError: + desc = reply + super(MonitorResponseError, self).__init__(desc) + self.reply = reply + + +class QEMUMachine(object): + """ + A QEMU VM + + Use this object as a context manager to ensure the QEMU process terminates:: + + with VM(binary) as vm: + ... + # vm is guaranteed to be shut down here + """ + + def __init__(self, binary, args=None, wrapper=None, name=None, + test_dir="/var/tmp", monitor_address=None, + socket_scm_helper=None): + ''' + Initialize a QEMUMachine + + @param binary: path to the qemu binary + @param args: list of extra arguments + @param wrapper: list of arguments used as prefix to qemu binary + @param name: prefix for socket and log file names (default: qemu-PID) + @param test_dir: where to create socket and log file + @param monitor_address: address for QMP monitor + @param socket_scm_helper: helper program, required for send_fd_scm() + @note: Qemu process is not started until launch() is used. + ''' + if args is None: + args = [] + if wrapper is None: + wrapper = [] + if name is None: + name = "qemu-%d" % os.getpid() + self._name = name + self._monitor_address = monitor_address + self._vm_monitor = None + self._qemu_log_path = None + self._qemu_log_file = None + self._popen = None + self._binary = binary + self._args = list(args) # Force copy args in case we modify them + self._wrapper = wrapper + self._events = [] + self._iolog = None + self._socket_scm_helper = socket_scm_helper + self._qmp = None + self._qemu_full_args = None + self._test_dir = test_dir + self._temp_dir = None + self._launched = False + self._machine = None + self._console_set = False + self._console_device_type = None + self._console_address = None + self._console_socket = None + + # just in case logging wasn't configured by the main script: + logging.basicConfig() + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.shutdown() + return False + + def add_monitor_null(self): + """ + This can be used to add an unused monitor instance. + """ + self._args.append('-monitor') + self._args.append('null') + + def add_fd(self, fd, fdset, opaque, opts=''): + """ + Pass a file descriptor to the VM + """ + options = ['fd=%d' % fd, + 'set=%d' % fdset, + 'opaque=%s' % opaque] + if opts: + options.append(opts) + + # This did not exist before 3.4, but since then it is + # mandatory for our purpose + if hasattr(os, 'set_inheritable'): + os.set_inheritable(fd, True) + + self._args.append('-add-fd') + self._args.append(','.join(options)) + return self + + def send_fd_scm(self, fd=None, file_path=None): + """ + Send an fd or file_path to socket_scm_helper. + + Exactly one of fd and file_path must be given. + If it is file_path, the helper will open that file and pass its own fd. + """ + # In iotest.py, the qmp should always use unix socket. + assert self._qmp.is_scm_available() + if self._socket_scm_helper is None: + raise QEMUMachineError("No path to socket_scm_helper set") + if not os.path.exists(self._socket_scm_helper): + raise QEMUMachineError("%s does not exist" % + self._socket_scm_helper) + + # This did not exist before 3.4, but since then it is + # mandatory for our purpose + if hasattr(os, 'set_inheritable'): + os.set_inheritable(self._qmp.get_sock_fd(), True) + if fd is not None: + os.set_inheritable(fd, True) + + fd_param = ["%s" % self._socket_scm_helper, + "%d" % self._qmp.get_sock_fd()] + + if file_path is not None: + assert fd is None + fd_param.append(file_path) + else: + assert fd is not None + fd_param.append(str(fd)) + + devnull = open(os.path.devnull, 'rb') + proc = subprocess.Popen(fd_param, stdin=devnull, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, close_fds=False) + output = proc.communicate()[0] + if output: + LOG.debug(output) + + return proc.returncode + + @staticmethod + def _remove_if_exists(path): + """ + Remove file object at path if it exists + """ + try: + os.remove(path) + except OSError as exception: + if exception.errno == errno.ENOENT: + return + raise + + def is_running(self): + """Returns true if the VM is running.""" + return self._popen is not None and self._popen.poll() is None + + def exitcode(self): + """Returns the exit code if possible, or None.""" + if self._popen is None: + return None + return self._popen.poll() + + def get_pid(self): + """Returns the PID of the running process, or None.""" + if not self.is_running(): + return None + return self._popen.pid + + def _load_io_log(self): + if self._qemu_log_path is not None: + with open(self._qemu_log_path, "r") as iolog: + self._iolog = iolog.read() + + def _base_args(self): + if isinstance(self._monitor_address, tuple): + moncdev = "socket,id=mon,host=%s,port=%s" % ( + self._monitor_address[0], + self._monitor_address[1]) + else: + moncdev = 'socket,id=mon,path=%s' % self._vm_monitor + args = ['-chardev', moncdev, + '-mon', 'chardev=mon,mode=control', + '-display', 'none', '-vga', 'none'] + if self._machine is not None: + args.extend(['-machine', self._machine]) + if self._console_set: + self._console_address = os.path.join(self._temp_dir, + self._name + "-console.sock") + chardev = ('socket,id=console,path=%s,server,nowait' % + self._console_address) + args.extend(['-chardev', chardev]) + if self._console_device_type is None: + args.extend(['-serial', 'chardev:console']) + else: + device = '%s,chardev=console' % self._console_device_type + args.extend(['-device', device]) + return args + + def _pre_launch(self): + self._temp_dir = tempfile.mkdtemp(dir=self._test_dir) + if self._monitor_address is not None: + self._vm_monitor = self._monitor_address + else: + self._vm_monitor = os.path.join(self._temp_dir, + self._name + "-monitor.sock") + self._qemu_log_path = os.path.join(self._temp_dir, self._name + ".log") + self._qemu_log_file = open(self._qemu_log_path, 'wb') + + self._qmp = qmp.QEMUMonitorProtocol(self._vm_monitor, + server=True) + + def _post_launch(self): + self._qmp.accept() + + def _post_shutdown(self): + if self._qemu_log_file is not None: + self._qemu_log_file.close() + self._qemu_log_file = None + + self._qemu_log_path = None + + if self._console_socket is not None: + self._console_socket.close() + self._console_socket = None + + if self._temp_dir is not None: + shutil.rmtree(self._temp_dir) + self._temp_dir = None + + def launch(self): + """ + Launch the VM and make sure we cleanup and expose the + command line/output in case of exception + """ + + if self._launched: + raise QEMUMachineError('VM already launched') + + self._iolog = None + self._qemu_full_args = None + try: + self._launch() + self._launched = True + except: + self.shutdown() + + LOG.debug('Error launching VM') + if self._qemu_full_args: + LOG.debug('Command: %r', ' '.join(self._qemu_full_args)) + if self._iolog: + LOG.debug('Output: %r', self._iolog) + raise + + def _launch(self): + """ + Launch the VM and establish a QMP connection + """ + devnull = open(os.path.devnull, 'rb') + self._pre_launch() + self._qemu_full_args = (self._wrapper + [self._binary] + + self._base_args() + self._args) + LOG.debug('VM launch command: %r', ' '.join(self._qemu_full_args)) + self._popen = subprocess.Popen(self._qemu_full_args, + stdin=devnull, + stdout=self._qemu_log_file, + stderr=subprocess.STDOUT, + shell=False, + close_fds=False) + self._post_launch() + + def wait(self): + """ + Wait for the VM to power off + """ + self._popen.wait() + self._qmp.close() + self._load_io_log() + self._post_shutdown() + + def shutdown(self): + """ + Terminate the VM and clean up + """ + if self.is_running(): + try: + self._qmp.cmd('quit') + self._qmp.close() + except: + self._popen.kill() + self._popen.wait() + + self._load_io_log() + self._post_shutdown() + + exitcode = self.exitcode() + if exitcode is not None and exitcode < 0: + msg = 'qemu received signal %i: %s' + if self._qemu_full_args: + command = ' '.join(self._qemu_full_args) + else: + command = '' + LOG.warning(msg, -exitcode, command) + + self._launched = False + + def qmp(self, cmd, conv_keys=True, **args): + """ + Invoke a QMP command and return the response dict + """ + qmp_args = dict() + for key, value in args.items(): + if conv_keys: + qmp_args[key.replace('_', '-')] = value + else: + qmp_args[key] = value + + return self._qmp.cmd(cmd, args=qmp_args) + + def command(self, cmd, conv_keys=True, **args): + """ + Invoke a QMP command. + On success return the response dict. + On failure raise an exception. + """ + reply = self.qmp(cmd, conv_keys, **args) + if reply is None: + raise qmp.QMPError("Monitor is closed") + if "error" in reply: + raise MonitorResponseError(reply) + return reply["return"] + + def get_qmp_event(self, wait=False): + """ + Poll for one queued QMP events and return it + """ + if self._events: + return self._events.pop(0) + return self._qmp.pull_event(wait=wait) + + def get_qmp_events(self, wait=False): + """ + Poll for queued QMP events and return a list of dicts + """ + events = self._qmp.get_events(wait=wait) + events.extend(self._events) + del self._events[:] + self._qmp.clear_events() + return events + + @staticmethod + def event_match(event, match=None): + """ + Check if an event matches optional match criteria. + + The match criteria takes the form of a matching subdict. The event is + checked to be a superset of the subdict, recursively, with matching + values whenever the subdict values are not None. + + This has a limitation that you cannot explicitly check for None values. + + Examples, with the subdict queries on the left: + - None matches any object. + - {"foo": None} matches {"foo": {"bar": 1}} + - {"foo": None} matches {"foo": 5} + - {"foo": {"abc": None}} does not match {"foo": {"bar": 1}} + - {"foo": {"rab": 2}} matches {"foo": {"bar": 1, "rab": 2}} + """ + if match is None: + return True + + try: + for key in match: + if key in event: + if not QEMUMachine.event_match(event[key], match[key]): + return False + else: + return False + return True + except TypeError: + # either match or event wasn't iterable (not a dict) + return match == event + + def event_wait(self, name, timeout=60.0, match=None): + """ + event_wait waits for and returns a named event from QMP with a timeout. + + name: The event to wait for. + timeout: QEMUMonitorProtocol.pull_event timeout parameter. + match: Optional match criteria. See event_match for details. + """ + return self.events_wait([(name, match)], timeout) + + def events_wait(self, events, timeout=60.0): + """ + events_wait waits for and returns a named event from QMP with a timeout. + + events: a sequence of (name, match_criteria) tuples. + The match criteria are optional and may be None. + See event_match for details. + timeout: QEMUMonitorProtocol.pull_event timeout parameter. + """ + def _match(event): + for name, match in events: + if event['event'] == name and self.event_match(event, match): + return True + return False + + # Search cached events + for event in self._events: + if _match(event): + self._events.remove(event) + return event + + # Poll for new events + while True: + event = self._qmp.pull_event(wait=timeout) + if _match(event): + return event + self._events.append(event) + + return None + + def get_log(self): + """ + After self.shutdown or failed qemu execution, this returns the output + of the qemu process. + """ + return self._iolog + + def add_args(self, *args): + """ + Adds to the list of extra arguments to be given to the QEMU binary + """ + self._args.extend(args) + + def set_machine(self, machine_type): + """ + Sets the machine type + + If set, the machine type will be added to the base arguments + of the resulting QEMU command line. + """ + self._machine = machine_type + + def set_console(self, device_type=None): + """ + Sets the device type for a console device + + If set, the console device and a backing character device will + be added to the base arguments of the resulting QEMU command + line. + + This is a convenience method that will either use the provided + device type, or default to a "-serial chardev:console" command + line argument. + + The actual setting of command line arguments will be be done at + machine launch time, as it depends on the temporary directory + to be created. + + @param device_type: the device type, such as "isa-serial". If + None is given (the default value) a "-serial + chardev:console" command line argument will + be used instead, resorting to the machine's + default device type. + """ + self._console_set = True + self._console_device_type = device_type + + @property + def console_socket(self): + """ + Returns a socket connected to the console + """ + if self._console_socket is None: + self._console_socket = socket.socket(socket.AF_UNIX, + socket.SOCK_STREAM) + self._console_socket.connect(self._console_address) + return self._console_socket diff --git a/python/qemu/qtest.py b/python/qemu/qtest.py index eb45824dd0..eebcc233ed 100644 --- a/python/qemu/qtest.py +++ b/python/qemu/qtest.py @@ -14,7 +14,7 @@ import socket import os -from . import QEMUMachine +from .machine import QEMUMachine class QEMUQtestProtocol(object): diff --git a/qapi/Makefile.objs b/qapi/Makefile.objs index 729e5185c5..c5a29e86e2 100644 --- a/qapi/Makefile.objs +++ b/qapi/Makefile.objs @@ -6,9 +6,10 @@ util-obj-y += qmp-event.o util-obj-y += qapi-util.o QAPI_COMMON_MODULES = audio authz block-core block char common crypto -QAPI_COMMON_MODULES += introspect job migration misc net rdma rocker -QAPI_COMMON_MODULES += run-state sockets tpm trace transaction ui -QAPI_TARGET_MODULES = target +QAPI_COMMON_MODULES += dump introspect job machine migration misc net +QAPI_COMMON_MODULES += qdev qom rdma rocker run-state sockets tpm +QAPI_COMMON_MODULES += trace transaction ui +QAPI_TARGET_MODULES = machine-target misc-target QAPI_MODULES = $(QAPI_COMMON_MODULES) $(QAPI_TARGET_MODULES) util-obj-y += qapi-builtin-types.o diff --git a/qapi/dump.json b/qapi/dump.json new file mode 100644 index 0000000000..2b35409a7b --- /dev/null +++ b/qapi/dump.json @@ -0,0 +1,200 @@ +# -*- Mode: Python -*- +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. + +## +# = Dump guest memory +## + +## +# @DumpGuestMemoryFormat: +# +# An enumeration of guest-memory-dump's format. +# +# @elf: elf format +# +# @kdump-zlib: kdump-compressed format with zlib-compressed +# +# @kdump-lzo: kdump-compressed format with lzo-compressed +# +# @kdump-snappy: kdump-compressed format with snappy-compressed +# +# @win-dmp: Windows full crashdump format, +# can be used instead of ELF converting (since 2.13) +# +# Since: 2.0 +## +{ 'enum': 'DumpGuestMemoryFormat', + 'data': [ 'elf', 'kdump-zlib', 'kdump-lzo', 'kdump-snappy', 'win-dmp' ] } + +## +# @dump-guest-memory: +# +# Dump guest's memory to vmcore. It is a synchronous operation that can take +# very long depending on the amount of guest memory. +# +# @paging: if true, do paging to get guest's memory mapping. This allows +# using gdb to process the core file. +# +# IMPORTANT: this option can make QEMU allocate several gigabytes +# of RAM. This can happen for a large guest, or a +# malicious guest pretending to be large. +# +# Also, paging=true has the following limitations: +# +# 1. The guest may be in a catastrophic state or can have corrupted +# memory, which cannot be trusted +# 2. The guest can be in real-mode even if paging is enabled. For +# example, the guest uses ACPI to sleep, and ACPI sleep state +# goes in real-mode +# 3. Currently only supported on i386 and x86_64. +# +# @protocol: the filename or file descriptor of the vmcore. The supported +# protocols are: +# +# 1. file: the protocol starts with "file:", and the following +# string is the file's path. +# 2. fd: the protocol starts with "fd:", and the following string +# is the fd's name. +# +# @detach: if true, QMP will return immediately rather than +# waiting for the dump to finish. The user can track progress +# using "query-dump". (since 2.6). +# +# @begin: if specified, the starting physical address. +# +# @length: if specified, the memory size, in bytes. If you don't +# want to dump all guest's memory, please specify the start @begin +# and @length +# +# @format: if specified, the format of guest memory dump. But non-elf +# format is conflict with paging and filter, ie. @paging, @begin and +# @length is not allowed to be specified with non-elf @format at the +# same time (since 2.0) +# +# Note: All boolean arguments default to false +# +# Returns: nothing on success +# +# Since: 1.2 +# +# Example: +# +# -> { "execute": "dump-guest-memory", +# "arguments": { "protocol": "fd:dump" } } +# <- { "return": {} } +# +## +{ 'command': 'dump-guest-memory', + 'data': { 'paging': 'bool', 'protocol': 'str', '*detach': 'bool', + '*begin': 'int', '*length': 'int', + '*format': 'DumpGuestMemoryFormat'} } + +## +# @DumpStatus: +# +# Describe the status of a long-running background guest memory dump. +# +# @none: no dump-guest-memory has started yet. +# +# @active: there is one dump running in background. +# +# @completed: the last dump has finished successfully. +# +# @failed: the last dump has failed. +# +# Since: 2.6 +## +{ 'enum': 'DumpStatus', + 'data': [ 'none', 'active', 'completed', 'failed' ] } + +## +# @DumpQueryResult: +# +# The result format for 'query-dump'. +# +# @status: enum of @DumpStatus, which shows current dump status +# +# @completed: bytes written in latest dump (uncompressed) +# +# @total: total bytes to be written in latest dump (uncompressed) +# +# Since: 2.6 +## +{ 'struct': 'DumpQueryResult', + 'data': { 'status': 'DumpStatus', + 'completed': 'int', + 'total': 'int' } } + +## +# @query-dump: +# +# Query latest dump status. +# +# Returns: A @DumpStatus object showing the dump status. +# +# Since: 2.6 +# +# Example: +# +# -> { "execute": "query-dump" } +# <- { "return": { "status": "active", "completed": 1024000, +# "total": 2048000 } } +# +## +{ 'command': 'query-dump', 'returns': 'DumpQueryResult' } + +## +# @DUMP_COMPLETED: +# +# Emitted when background dump has completed +# +# @result: final dump status +# +# @error: human-readable error string that provides +# hint on why dump failed. Only presents on failure. The +# user should not try to interpret the error string. +# +# Since: 2.6 +# +# Example: +# +# { "event": "DUMP_COMPLETED", +# "data": {"result": {"total": 1090650112, "status": "completed", +# "completed": 1090650112} } } +# +## +{ 'event': 'DUMP_COMPLETED' , + 'data': { 'result': 'DumpQueryResult', '*error': 'str' } } + +## +# @DumpGuestMemoryCapability: +# +# A list of the available formats for dump-guest-memory +# +# Since: 2.0 +## +{ 'struct': 'DumpGuestMemoryCapability', + 'data': { + 'formats': ['DumpGuestMemoryFormat'] } } + +## +# @query-dump-guest-memory-capability: +# +# Returns the available formats for dump-guest-memory +# +# Returns: A @DumpGuestMemoryCapability object listing available formats for +# dump-guest-memory +# +# Since: 2.0 +# +# Example: +# +# -> { "execute": "query-dump-guest-memory-capability" } +# <- { "return": { "formats": +# ["elf", "kdump-zlib", "kdump-lzo", "kdump-snappy"] } +# +## +{ 'command': 'query-dump-guest-memory-capability', + 'returns': 'DumpGuestMemoryCapability' } diff --git a/qapi/target.json b/qapi/machine-target.json index 1d4d54b600..5d7480f6ab 100644 --- a/qapi/target.json +++ b/qapi/machine-target.json @@ -1,232 +1,81 @@ # -*- Mode: Python -*- # +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. ## -# = Target-specific commands & events -## - -{ 'include': 'misc.json' } - -## -# @RTC_CHANGE: -# -# Emitted when the guest changes the RTC time. -# -# @offset: offset between base RTC clock (as specified by -rtc base), and -# new RTC clock value -# -# Note: This event is rate-limited. -# -# Since: 0.13.0 -# -# Example: -# -# <- { "event": "RTC_CHANGE", -# "data": { "offset": 78 }, -# "timestamp": { "seconds": 1267020223, "microseconds": 435656 } } -# -## -{ 'event': 'RTC_CHANGE', - 'data': { 'offset': 'int' }, - 'if': 'defined(TARGET_ALPHA) || defined(TARGET_ARM) || defined(TARGET_HPPA) || defined(TARGET_I386) || defined(TARGET_MIPS) || defined(TARGET_MIPS64) || defined(TARGET_MOXIE) || defined(TARGET_PPC) || defined(TARGET_PPC64) || defined(TARGET_S390X) || defined(TARGET_SH4) || defined(TARGET_SPARC)' } - -## -# @rtc-reset-reinjection: -# -# This command will reset the RTC interrupt reinjection backlog. -# Can be used if another mechanism to synchronize guest time -# is in effect, for example QEMU guest agent's guest-set-time -# command. -# -# Since: 2.1 -# -# Example: -# -# -> { "execute": "rtc-reset-reinjection" } -# <- { "return": {} } -# -## -{ 'command': 'rtc-reset-reinjection', - 'if': 'defined(TARGET_I386)' } - - -## -# @SevState: -# -# An enumeration of SEV state information used during @query-sev. -# -# @uninit: The guest is uninitialized. +# @CpuModelInfo: # -# @launch-update: The guest is currently being launched; plaintext data and -# register state is being imported. +# Virtual CPU model. # -# @launch-secret: The guest is currently being launched; ciphertext data -# is being imported. +# A CPU model consists of the name of a CPU definition, to which +# delta changes are applied (e.g. features added/removed). Most magic values +# that an architecture might require should be hidden behind the name. +# However, if required, architectures can expose relevant properties. # -# @running: The guest is fully launched or migrated in. -# -# @send-update: The guest is currently being migrated out to another machine. -# -# @receive-update: The guest is currently being migrated from another machine. -# -# Since: 2.12 -## -{ 'enum': 'SevState', - 'data': ['uninit', 'launch-update', 'launch-secret', 'running', - 'send-update', 'receive-update' ], - 'if': 'defined(TARGET_I386)' } - -## -# @SevInfo: -# -# Information about Secure Encrypted Virtualization (SEV) support -# -# @enabled: true if SEV is active -# -# @api-major: SEV API major version -# -# @api-minor: SEV API minor version -# -# @build-id: SEV FW build id -# -# @policy: SEV policy value -# -# @state: SEV guest state -# -# @handle: SEV firmware handle -# -# Since: 2.12 -## -{ 'struct': 'SevInfo', - 'data': { 'enabled': 'bool', - 'api-major': 'uint8', - 'api-minor' : 'uint8', - 'build-id' : 'uint8', - 'policy' : 'uint32', - 'state' : 'SevState', - 'handle' : 'uint32' - }, - 'if': 'defined(TARGET_I386)' -} - -## -# @query-sev: -# -# Returns information about SEV -# -# Returns: @SevInfo -# -# Since: 2.12 -# -# Example: -# -# -> { "execute": "query-sev" } -# <- { "return": { "enabled": true, "api-major" : 0, "api-minor" : 0, -# "build-id" : 0, "policy" : 0, "state" : "running", -# "handle" : 1 } } -# -## -{ 'command': 'query-sev', 'returns': 'SevInfo', - 'if': 'defined(TARGET_I386)' } - - -## -# @SevLaunchMeasureInfo: -# -# SEV Guest Launch measurement information -# -# @data: the measurement value encoded in base64 -# -# Since: 2.12 +# @name: the name of the CPU definition the model is based on +# @props: a dictionary of QOM properties to be applied # +# Since: 2.8.0 ## -{ 'struct': 'SevLaunchMeasureInfo', 'data': {'data': 'str'}, - 'if': 'defined(TARGET_I386)' } +{ 'struct': 'CpuModelInfo', + 'data': { 'name': 'str', + '*props': 'any' } } ## -# @query-sev-launch-measure: -# -# Query the SEV guest launch information. -# -# Returns: The @SevLaunchMeasureInfo for the guest +# @CpuModelExpansionType: # -# Since: 2.12 +# An enumeration of CPU model expansion types. # -# Example: -# -# -> { "execute": "query-sev-launch-measure" } -# <- { "return": { "data": "4l8LXeNlSPUDlXPJG5966/8%YZ" } } -# -## -{ 'command': 'query-sev-launch-measure', 'returns': 'SevLaunchMeasureInfo', - 'if': 'defined(TARGET_I386)' } +# @static: Expand to a static CPU model, a combination of a static base +# model name and property delta changes. As the static base model will +# never change, the expanded CPU model will be the same, independent of +# QEMU version, machine type, machine options, and accelerator options. +# Therefore, the resulting model can be used by tooling without having +# to specify a compatibility machine - e.g. when displaying the "host" +# model. The @static CPU models are migration-safe. - -## -# @SevCapability: -# -# The struct describes capability for a Secure Encrypted Virtualization -# feature. -# -# @pdh: Platform Diffie-Hellman key (base64 encoded) -# -# @cert-chain: PDH certificate chain (base64 encoded) -# -# @cbitpos: C-bit location in page table entry +# @full: Expand all properties. The produced model is not guaranteed to be +# migration-safe, but allows tooling to get an insight and work with +# model details. +# +# Note: When a non-migration-safe CPU model is expanded in static mode, some +# features enabled by the CPU model may be omitted, because they can't be +# implemented by a static CPU model definition (e.g. cache info passthrough and +# PMU passthrough in x86). If you need an accurate representation of the +# features enabled by a non-migration-safe CPU model, use @full. If you need a +# static representation that will keep ABI compatibility even when changing QEMU +# version or machine-type, use @static (but keep in mind that some features may +# be omitted). # -# @reduced-phys-bits: Number of physical Address bit reduction when SEV is -# enabled -# -# Since: 2.12 +# Since: 2.8.0 ## -{ 'struct': 'SevCapability', - 'data': { 'pdh': 'str', - 'cert-chain': 'str', - 'cbitpos': 'int', - 'reduced-phys-bits': 'int'}, - 'if': 'defined(TARGET_I386)' } +{ 'enum': 'CpuModelExpansionType', + 'data': [ 'static', 'full' ] } -## -# @query-sev-capabilities: -# -# This command is used to get the SEV capabilities, and is supported on AMD -# X86 platforms only. -# -# Returns: SevCapability objects. -# -# Since: 2.12 -# -# Example: -# -# -> { "execute": "query-sev-capabilities" } -# <- { "return": { "pdh": "8CCDD8DDD", "cert-chain": "888CCCDDDEE", -# "cbitpos": 47, "reduced-phys-bits": 5}} -# -## -{ 'command': 'query-sev-capabilities', 'returns': 'SevCapability', - 'if': 'defined(TARGET_I386)' } ## -# @dump-skeys: -# -# Dump guest's storage keys +# @CpuModelCompareResult: # -# @filename: the path to the file to dump to +# An enumeration of CPU model comparison results. The result is usually +# calculated using e.g. CPU features or CPU generations. # -# This command is only supported on s390 architecture. +# @incompatible: If model A is incompatible to model B, model A is not +# guaranteed to run where model B runs and the other way around. # -# Since: 2.5 +# @identical: If model A is identical to model B, model A is guaranteed to run +# where model B runs and the other way around. # -# Example: +# @superset: If model A is a superset of model B, model B is guaranteed to run +# where model A runs. There are no guarantees about the other way. # -# -> { "execute": "dump-skeys", -# "arguments": { "filename": "/tmp/skeys" } } -# <- { "return": {} } +# @subset: If model A is a subset of model B, model A is guaranteed to run +# where model B runs. There are no guarantees about the other way. # +# Since: 2.8.0 ## -{ 'command': 'dump-skeys', - 'data': { 'filename': 'str' }, - 'if': 'defined(TARGET_S390X)' } +{ 'enum': 'CpuModelCompareResult', + 'data': [ 'incompatible', 'identical', 'superset', 'subset' ] } ## # @CpuModelBaselineInfo: @@ -353,51 +202,6 @@ 'if': 'defined(TARGET_S390X)' } ## -# @GICCapability: -# -# The struct describes capability for a specific GIC (Generic -# Interrupt Controller) version. These bits are not only decided by -# QEMU/KVM software version, but also decided by the hardware that -# the program is running upon. -# -# @version: version of GIC to be described. Currently, only 2 and 3 -# are supported. -# -# @emulated: whether current QEMU/hardware supports emulated GIC -# device in user space. -# -# @kernel: whether current QEMU/hardware supports hardware -# accelerated GIC device in kernel. -# -# Since: 2.6 -## -{ 'struct': 'GICCapability', - 'data': { 'version': 'int', - 'emulated': 'bool', - 'kernel': 'bool' }, - 'if': 'defined(TARGET_ARM)' } - -## -# @query-gic-capabilities: -# -# This command is ARM-only. It will return a list of GICCapability -# objects that describe its capability bits. -# -# Returns: a list of GICCapability objects. -# -# Since: 2.6 -# -# Example: -# -# -> { "execute": "query-gic-capabilities" } -# <- { "return": [{ "version": 2, "emulated": true, "kernel": false }, -# { "version": 3, "emulated": false, "kernel": true } ] } -# -## -{ 'command': 'query-gic-capabilities', 'returns': ['GICCapability'], - 'if': 'defined(TARGET_ARM)' } - -## # @CpuModelExpansionInfo: # # The result of a cpu model expansion. diff --git a/qapi/machine.json b/qapi/machine.json new file mode 100644 index 0000000000..81849acb3a --- /dev/null +++ b/qapi/machine.json @@ -0,0 +1,697 @@ +# -*- Mode: Python -*- +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. + +## +# = Machines +## + +{ 'include': 'common.json' } + +## +# @CpuInfoArch: +# +# An enumeration of cpu types that enable additional information during +# @query-cpus and @query-cpus-fast. +# +# @s390: since 2.12 +# +# @riscv: since 2.12 +# +# Since: 2.6 +## +{ 'enum': 'CpuInfoArch', + 'data': ['x86', 'sparc', 'ppc', 'mips', 'tricore', 's390', 'riscv', 'other' ] } + +## +# @CpuInfo: +# +# Information about a virtual CPU +# +# @CPU: the index of the virtual CPU +# +# @current: this only exists for backwards compatibility and should be ignored +# +# @halted: true if the virtual CPU is in the halt state. Halt usually refers +# to a processor specific low power mode. +# +# @qom_path: path to the CPU object in the QOM tree (since 2.4) +# +# @thread_id: ID of the underlying host thread +# +# @props: properties describing to which node/socket/core/thread +# virtual CPU belongs to, provided if supported by board (since 2.10) +# +# @arch: architecture of the cpu, which determines which additional fields +# will be listed (since 2.6) +# +# Since: 0.14.0 +# +# Notes: @halted is a transient state that changes frequently. By the time the +# data is sent to the client, the guest may no longer be halted. +## +{ 'union': 'CpuInfo', + 'base': {'CPU': 'int', 'current': 'bool', 'halted': 'bool', + 'qom_path': 'str', 'thread_id': 'int', + '*props': 'CpuInstanceProperties', 'arch': 'CpuInfoArch' }, + 'discriminator': 'arch', + 'data': { 'x86': 'CpuInfoX86', + 'sparc': 'CpuInfoSPARC', + 'ppc': 'CpuInfoPPC', + 'mips': 'CpuInfoMIPS', + 'tricore': 'CpuInfoTricore', + 's390': 'CpuInfoS390', + 'riscv': 'CpuInfoRISCV' } } + +## +# @CpuInfoX86: +# +# Additional information about a virtual i386 or x86_64 CPU +# +# @pc: the 64-bit instruction pointer +# +# Since: 2.6 +## +{ 'struct': 'CpuInfoX86', 'data': { 'pc': 'int' } } + +## +# @CpuInfoSPARC: +# +# Additional information about a virtual SPARC CPU +# +# @pc: the PC component of the instruction pointer +# +# @npc: the NPC component of the instruction pointer +# +# Since: 2.6 +## +{ 'struct': 'CpuInfoSPARC', 'data': { 'pc': 'int', 'npc': 'int' } } + +## +# @CpuInfoPPC: +# +# Additional information about a virtual PPC CPU +# +# @nip: the instruction pointer +# +# Since: 2.6 +## +{ 'struct': 'CpuInfoPPC', 'data': { 'nip': 'int' } } + +## +# @CpuInfoMIPS: +# +# Additional information about a virtual MIPS CPU +# +# @PC: the instruction pointer +# +# Since: 2.6 +## +{ 'struct': 'CpuInfoMIPS', 'data': { 'PC': 'int' } } + +## +# @CpuInfoTricore: +# +# Additional information about a virtual Tricore CPU +# +# @PC: the instruction pointer +# +# Since: 2.6 +## +{ 'struct': 'CpuInfoTricore', 'data': { 'PC': 'int' } } + +## +# @CpuInfoRISCV: +# +# Additional information about a virtual RISCV CPU +# +# @pc: the instruction pointer +# +# Since 2.12 +## +{ 'struct': 'CpuInfoRISCV', 'data': { 'pc': 'int' } } + +## +# @CpuS390State: +# +# An enumeration of cpu states that can be assumed by a virtual +# S390 CPU +# +# Since: 2.12 +## +{ 'enum': 'CpuS390State', + 'prefix': 'S390_CPU_STATE', + 'data': [ 'uninitialized', 'stopped', 'check-stop', 'operating', 'load' ] } + +## +# @CpuInfoS390: +# +# Additional information about a virtual S390 CPU +# +# @cpu-state: the virtual CPU's state +# +# Since: 2.12 +## +{ 'struct': 'CpuInfoS390', 'data': { 'cpu-state': 'CpuS390State' } } + +## +# @query-cpus: +# +# Returns a list of information about each virtual CPU. +# +# This command causes vCPU threads to exit to userspace, which causes +# a small interruption to guest CPU execution. This will have a negative +# impact on realtime guests and other latency sensitive guest workloads. +# It is recommended to use @query-cpus-fast instead of this command to +# avoid the vCPU interruption. +# +# Returns: a list of @CpuInfo for each virtual CPU +# +# Since: 0.14.0 +# +# Example: +# +# -> { "execute": "query-cpus" } +# <- { "return": [ +# { +# "CPU":0, +# "current":true, +# "halted":false, +# "qom_path":"/machine/unattached/device[0]", +# "arch":"x86", +# "pc":3227107138, +# "thread_id":3134 +# }, +# { +# "CPU":1, +# "current":false, +# "halted":true, +# "qom_path":"/machine/unattached/device[2]", +# "arch":"x86", +# "pc":7108165, +# "thread_id":3135 +# } +# ] +# } +# +# Notes: This interface is deprecated (since 2.12.0), and it is strongly +# recommended that you avoid using it. Use @query-cpus-fast to +# obtain information about virtual CPUs. +# +## +{ 'command': 'query-cpus', 'returns': ['CpuInfo'] } + +## +# @CpuInfoFast: +# +# Information about a virtual CPU +# +# @cpu-index: index of the virtual CPU +# +# @qom-path: path to the CPU object in the QOM tree +# +# @thread-id: ID of the underlying host thread +# +# @props: properties describing to which node/socket/core/thread +# virtual CPU belongs to, provided if supported by board +# +# @arch: base architecture of the cpu; deprecated since 3.0.0 in favor +# of @target +# +# @target: the QEMU system emulation target, which determines which +# additional fields will be listed (since 3.0) +# +# Since: 2.12 +# +## +{ 'union' : 'CpuInfoFast', + 'base' : { 'cpu-index' : 'int', + 'qom-path' : 'str', + 'thread-id' : 'int', + '*props' : 'CpuInstanceProperties', + 'arch' : 'CpuInfoArch', + 'target' : 'SysEmuTarget' }, + 'discriminator' : 'target', + 'data' : { 's390x' : 'CpuInfoS390' } } + +## +# @query-cpus-fast: +# +# Returns information about all virtual CPUs. This command does not +# incur a performance penalty and should be used in production +# instead of query-cpus. +# +# Returns: list of @CpuInfoFast +# +# Since: 2.12 +# +# Example: +# +# -> { "execute": "query-cpus-fast" } +# <- { "return": [ +# { +# "thread-id": 25627, +# "props": { +# "core-id": 0, +# "thread-id": 0, +# "socket-id": 0 +# }, +# "qom-path": "/machine/unattached/device[0]", +# "arch":"x86", +# "target":"x86_64", +# "cpu-index": 0 +# }, +# { +# "thread-id": 25628, +# "props": { +# "core-id": 0, +# "thread-id": 0, +# "socket-id": 1 +# }, +# "qom-path": "/machine/unattached/device[2]", +# "arch":"x86", +# "target":"x86_64", +# "cpu-index": 1 +# } +# ] +# } +## +{ 'command': 'query-cpus-fast', 'returns': [ 'CpuInfoFast' ] } + +## +# @cpu-add: +# +# Adds CPU with specified ID. +# +# @id: ID of CPU to be created, valid values [0..max_cpus) +# +# Returns: Nothing on success +# +# Since: 1.5 +# +# Note: This command is deprecated. The `device_add` command should be +# used instead. See the `query-hotpluggable-cpus` command for +# details. +# +# Example: +# +# -> { "execute": "cpu-add", "arguments": { "id": 2 } } +# <- { "return": {} } +# +## +{ 'command': 'cpu-add', 'data': {'id': 'int'} } + +## +# @MachineInfo: +# +# Information describing a machine. +# +# @name: the name of the machine +# +# @alias: an alias for the machine name +# +# @is-default: whether the machine is default +# +# @cpu-max: maximum number of CPUs supported by the machine type +# (since 1.5.0) +# +# @hotpluggable-cpus: cpu hotplug via -device is supported (since 2.7.0) +# +# Since: 1.2.0 +## +{ 'struct': 'MachineInfo', + 'data': { 'name': 'str', '*alias': 'str', + '*is-default': 'bool', 'cpu-max': 'int', + 'hotpluggable-cpus': 'bool'} } + +## +# @query-machines: +# +# Return a list of supported machines +# +# Returns: a list of MachineInfo +# +# Since: 1.2.0 +## +{ 'command': 'query-machines', 'returns': ['MachineInfo'] } + +## +# @CurrentMachineParams: +# +# Information describing the running machine parameters. +# +# @wakeup-suspend-support: true if the machine supports wake up from +# suspend +# +# Since: 4.0 +## +{ 'struct': 'CurrentMachineParams', + 'data': { 'wakeup-suspend-support': 'bool'} } + +## +# @query-current-machine: +# +# Return information on the current virtual machine. +# +# Returns: CurrentMachineParams +# +# Since: 4.0 +## +{ 'command': 'query-current-machine', 'returns': 'CurrentMachineParams' } + +## +# @NumaOptionsType: +# +# @node: NUMA nodes configuration +# +# @dist: NUMA distance configuration (since 2.10) +# +# @cpu: property based CPU(s) to node mapping (Since: 2.10) +# +# Since: 2.1 +## +{ 'enum': 'NumaOptionsType', + 'data': [ 'node', 'dist', 'cpu' ] } + +## +# @NumaOptions: +# +# A discriminated record of NUMA options. (for OptsVisitor) +# +# Since: 2.1 +## +{ 'union': 'NumaOptions', + 'base': { 'type': 'NumaOptionsType' }, + 'discriminator': 'type', + 'data': { + 'node': 'NumaNodeOptions', + 'dist': 'NumaDistOptions', + 'cpu': 'NumaCpuOptions' }} + +## +# @NumaNodeOptions: +# +# Create a guest NUMA node. (for OptsVisitor) +# +# @nodeid: NUMA node ID (increase by 1 from 0 if omitted) +# +# @cpus: VCPUs belonging to this node (assign VCPUS round-robin +# if omitted) +# +# @mem: memory size of this node; mutually exclusive with @memdev. +# Equally divide total memory among nodes if both @mem and @memdev are +# omitted. +# +# @memdev: memory backend object. If specified for one node, +# it must be specified for all nodes. +# +# Since: 2.1 +## +{ 'struct': 'NumaNodeOptions', + 'data': { + '*nodeid': 'uint16', + '*cpus': ['uint16'], + '*mem': 'size', + '*memdev': 'str' }} + +## +# @NumaDistOptions: +# +# Set the distance between 2 NUMA nodes. +# +# @src: source NUMA node. +# +# @dst: destination NUMA node. +# +# @val: NUMA distance from source node to destination node. +# When a node is unreachable from another node, set the distance +# between them to 255. +# +# Since: 2.10 +## +{ 'struct': 'NumaDistOptions', + 'data': { + 'src': 'uint16', + 'dst': 'uint16', + 'val': 'uint8' }} + +## +# @X86CPURegister32: +# +# A X86 32-bit register +# +# Since: 1.5 +## +{ 'enum': 'X86CPURegister32', + 'data': [ 'EAX', 'EBX', 'ECX', 'EDX', 'ESP', 'EBP', 'ESI', 'EDI' ] } + +## +# @X86CPUFeatureWordInfo: +# +# Information about a X86 CPU feature word +# +# @cpuid-input-eax: Input EAX value for CPUID instruction for that feature word +# +# @cpuid-input-ecx: Input ECX value for CPUID instruction for that +# feature word +# +# @cpuid-register: Output register containing the feature bits +# +# @features: value of output register, containing the feature bits +# +# Since: 1.5 +## +{ 'struct': 'X86CPUFeatureWordInfo', + 'data': { 'cpuid-input-eax': 'int', + '*cpuid-input-ecx': 'int', + 'cpuid-register': 'X86CPURegister32', + 'features': 'int' } } + +## +# @DummyForceArrays: +# +# Not used by QMP; hack to let us use X86CPUFeatureWordInfoList internally +# +# Since: 2.5 +## +{ 'struct': 'DummyForceArrays', + 'data': { 'unused': ['X86CPUFeatureWordInfo'] } } + +## +# @NumaCpuOptions: +# +# Option "-numa cpu" overrides default cpu to node mapping. +# It accepts the same set of cpu properties as returned by +# query-hotpluggable-cpus[].props, where node-id could be used to +# override default node mapping. +# +# Since: 2.10 +## +{ 'struct': 'NumaCpuOptions', + 'base': 'CpuInstanceProperties', + 'data' : {} } + +## +# @HostMemPolicy: +# +# Host memory policy types +# +# @default: restore default policy, remove any nondefault policy +# +# @preferred: set the preferred host nodes for allocation +# +# @bind: a strict policy that restricts memory allocation to the +# host nodes specified +# +# @interleave: memory allocations are interleaved across the set +# of host nodes specified +# +# Since: 2.1 +## +{ 'enum': 'HostMemPolicy', + 'data': [ 'default', 'preferred', 'bind', 'interleave' ] } + +## +# @Memdev: +# +# Information about memory backend +# +# @id: backend's ID if backend has 'id' property (since 2.9) +# +# @size: memory backend size +# +# @merge: enables or disables memory merge support +# +# @dump: includes memory backend's memory in a core dump or not +# +# @prealloc: enables or disables memory preallocation +# +# @host-nodes: host nodes for its memory policy +# +# @policy: memory policy of memory backend +# +# Since: 2.1 +## +{ 'struct': 'Memdev', + 'data': { + '*id': 'str', + 'size': 'size', + 'merge': 'bool', + 'dump': 'bool', + 'prealloc': 'bool', + 'host-nodes': ['uint16'], + 'policy': 'HostMemPolicy' }} + +## +# @query-memdev: +# +# Returns information for all memory backends. +# +# Returns: a list of @Memdev. +# +# Since: 2.1 +# +# Example: +# +# -> { "execute": "query-memdev" } +# <- { "return": [ +# { +# "id": "mem1", +# "size": 536870912, +# "merge": false, +# "dump": true, +# "prealloc": false, +# "host-nodes": [0, 1], +# "policy": "bind" +# }, +# { +# "size": 536870912, +# "merge": false, +# "dump": true, +# "prealloc": true, +# "host-nodes": [2, 3], +# "policy": "preferred" +# } +# ] +# } +# +## +{ 'command': 'query-memdev', 'returns': ['Memdev'], 'allow-preconfig': true } + +## +# @CpuInstanceProperties: +# +# List of properties to be used for hotplugging a CPU instance, +# it should be passed by management with device_add command when +# a CPU is being hotplugged. +# +# @node-id: NUMA node ID the CPU belongs to +# @socket-id: socket number within node/board the CPU belongs to +# @core-id: core number within socket the CPU belongs to +# @thread-id: thread number within core the CPU belongs to +# +# Note: currently there are 4 properties that could be present +# but management should be prepared to pass through other +# properties with device_add command to allow for future +# interface extension. This also requires the filed names to be kept in +# sync with the properties passed to -device/device_add. +# +# Since: 2.7 +## +{ 'struct': 'CpuInstanceProperties', + 'data': { '*node-id': 'int', + '*socket-id': 'int', + '*core-id': 'int', + '*thread-id': 'int' + } +} + +## +# @HotpluggableCPU: +# +# @type: CPU object type for usage with device_add command +# @props: list of properties to be used for hotplugging CPU +# @vcpus-count: number of logical VCPU threads @HotpluggableCPU provides +# @qom-path: link to existing CPU object if CPU is present or +# omitted if CPU is not present. +# +# Since: 2.7 +## +{ 'struct': 'HotpluggableCPU', + 'data': { 'type': 'str', + 'vcpus-count': 'int', + 'props': 'CpuInstanceProperties', + '*qom-path': 'str' + } +} + +## +# @query-hotpluggable-cpus: +# +# TODO: Better documentation; currently there is none. +# +# Returns: a list of HotpluggableCPU objects. +# +# Since: 2.7 +# +# Example: +# +# For pseries machine type started with -smp 2,cores=2,maxcpus=4 -cpu POWER8: +# +# -> { "execute": "query-hotpluggable-cpus" } +# <- {"return": [ +# { "props": { "core": 8 }, "type": "POWER8-spapr-cpu-core", +# "vcpus-count": 1 }, +# { "props": { "core": 0 }, "type": "POWER8-spapr-cpu-core", +# "vcpus-count": 1, "qom-path": "/machine/unattached/device[0]"} +# ]}' +# +# For pc machine type started with -smp 1,maxcpus=2: +# +# -> { "execute": "query-hotpluggable-cpus" } +# <- {"return": [ +# { +# "type": "qemu64-x86_64-cpu", "vcpus-count": 1, +# "props": {"core-id": 0, "socket-id": 1, "thread-id": 0} +# }, +# { +# "qom-path": "/machine/unattached/device[0]", +# "type": "qemu64-x86_64-cpu", "vcpus-count": 1, +# "props": {"core-id": 0, "socket-id": 0, "thread-id": 0} +# } +# ]} +# +# For s390x-virtio-ccw machine type started with -smp 1,maxcpus=2 -cpu qemu +# (Since: 2.11): +# +# -> { "execute": "query-hotpluggable-cpus" } +# <- {"return": [ +# { +# "type": "qemu-s390x-cpu", "vcpus-count": 1, +# "props": { "core-id": 1 } +# }, +# { +# "qom-path": "/machine/unattached/device[0]", +# "type": "qemu-s390x-cpu", "vcpus-count": 1, +# "props": { "core-id": 0 } +# } +# ]} +# +## +{ 'command': 'query-hotpluggable-cpus', 'returns': ['HotpluggableCPU'], + 'allow-preconfig': true } + +## +# @set-numa-node: +# +# Runtime equivalent of '-numa' CLI option, available at +# preconfigure stage to configure numa mapping before initializing +# machine. +# +# Since 3.0 +## +{ 'command': 'set-numa-node', 'boxed': true, + 'data': 'NumaOptions', + 'allow-preconfig': true +} diff --git a/qapi/misc-target.json b/qapi/misc-target.json new file mode 100644 index 0000000000..a00fd821eb --- /dev/null +++ b/qapi/misc-target.json @@ -0,0 +1,268 @@ +# -*- Mode: Python -*- +# + +## +# @RTC_CHANGE: +# +# Emitted when the guest changes the RTC time. +# +# @offset: offset between base RTC clock (as specified by -rtc base), and +# new RTC clock value +# +# Note: This event is rate-limited. +# +# Since: 0.13.0 +# +# Example: +# +# <- { "event": "RTC_CHANGE", +# "data": { "offset": 78 }, +# "timestamp": { "seconds": 1267020223, "microseconds": 435656 } } +# +## +{ 'event': 'RTC_CHANGE', + 'data': { 'offset': 'int' }, + 'if': 'defined(TARGET_ALPHA) || defined(TARGET_ARM) || defined(TARGET_HPPA) || defined(TARGET_I386) || defined(TARGET_MIPS) || defined(TARGET_MIPS64) || defined(TARGET_MOXIE) || defined(TARGET_PPC) || defined(TARGET_PPC64) || defined(TARGET_S390X) || defined(TARGET_SH4) || defined(TARGET_SPARC)' } + +## +# @rtc-reset-reinjection: +# +# This command will reset the RTC interrupt reinjection backlog. +# Can be used if another mechanism to synchronize guest time +# is in effect, for example QEMU guest agent's guest-set-time +# command. +# +# Since: 2.1 +# +# Example: +# +# -> { "execute": "rtc-reset-reinjection" } +# <- { "return": {} } +# +## +{ 'command': 'rtc-reset-reinjection', + 'if': 'defined(TARGET_I386)' } + + +## +# @SevState: +# +# An enumeration of SEV state information used during @query-sev. +# +# @uninit: The guest is uninitialized. +# +# @launch-update: The guest is currently being launched; plaintext data and +# register state is being imported. +# +# @launch-secret: The guest is currently being launched; ciphertext data +# is being imported. +# +# @running: The guest is fully launched or migrated in. +# +# @send-update: The guest is currently being migrated out to another machine. +# +# @receive-update: The guest is currently being migrated from another machine. +# +# Since: 2.12 +## +{ 'enum': 'SevState', + 'data': ['uninit', 'launch-update', 'launch-secret', 'running', + 'send-update', 'receive-update' ], + 'if': 'defined(TARGET_I386)' } + +## +# @SevInfo: +# +# Information about Secure Encrypted Virtualization (SEV) support +# +# @enabled: true if SEV is active +# +# @api-major: SEV API major version +# +# @api-minor: SEV API minor version +# +# @build-id: SEV FW build id +# +# @policy: SEV policy value +# +# @state: SEV guest state +# +# @handle: SEV firmware handle +# +# Since: 2.12 +## +{ 'struct': 'SevInfo', + 'data': { 'enabled': 'bool', + 'api-major': 'uint8', + 'api-minor' : 'uint8', + 'build-id' : 'uint8', + 'policy' : 'uint32', + 'state' : 'SevState', + 'handle' : 'uint32' + }, + 'if': 'defined(TARGET_I386)' +} + +## +# @query-sev: +# +# Returns information about SEV +# +# Returns: @SevInfo +# +# Since: 2.12 +# +# Example: +# +# -> { "execute": "query-sev" } +# <- { "return": { "enabled": true, "api-major" : 0, "api-minor" : 0, +# "build-id" : 0, "policy" : 0, "state" : "running", +# "handle" : 1 } } +# +## +{ 'command': 'query-sev', 'returns': 'SevInfo', + 'if': 'defined(TARGET_I386)' } + + +## +# @SevLaunchMeasureInfo: +# +# SEV Guest Launch measurement information +# +# @data: the measurement value encoded in base64 +# +# Since: 2.12 +# +## +{ 'struct': 'SevLaunchMeasureInfo', 'data': {'data': 'str'}, + 'if': 'defined(TARGET_I386)' } + +## +# @query-sev-launch-measure: +# +# Query the SEV guest launch information. +# +# Returns: The @SevLaunchMeasureInfo for the guest +# +# Since: 2.12 +# +# Example: +# +# -> { "execute": "query-sev-launch-measure" } +# <- { "return": { "data": "4l8LXeNlSPUDlXPJG5966/8%YZ" } } +# +## +{ 'command': 'query-sev-launch-measure', 'returns': 'SevLaunchMeasureInfo', + 'if': 'defined(TARGET_I386)' } + + +## +# @SevCapability: +# +# The struct describes capability for a Secure Encrypted Virtualization +# feature. +# +# @pdh: Platform Diffie-Hellman key (base64 encoded) +# +# @cert-chain: PDH certificate chain (base64 encoded) +# +# @cbitpos: C-bit location in page table entry +# +# @reduced-phys-bits: Number of physical Address bit reduction when SEV is +# enabled +# +# Since: 2.12 +## +{ 'struct': 'SevCapability', + 'data': { 'pdh': 'str', + 'cert-chain': 'str', + 'cbitpos': 'int', + 'reduced-phys-bits': 'int'}, + 'if': 'defined(TARGET_I386)' } + +## +# @query-sev-capabilities: +# +# This command is used to get the SEV capabilities, and is supported on AMD +# X86 platforms only. +# +# Returns: SevCapability objects. +# +# Since: 2.12 +# +# Example: +# +# -> { "execute": "query-sev-capabilities" } +# <- { "return": { "pdh": "8CCDD8DDD", "cert-chain": "888CCCDDDEE", +# "cbitpos": 47, "reduced-phys-bits": 5}} +# +## +{ 'command': 'query-sev-capabilities', 'returns': 'SevCapability', + 'if': 'defined(TARGET_I386)' } + +## +# @dump-skeys: +# +# Dump guest's storage keys +# +# @filename: the path to the file to dump to +# +# This command is only supported on s390 architecture. +# +# Since: 2.5 +# +# Example: +# +# -> { "execute": "dump-skeys", +# "arguments": { "filename": "/tmp/skeys" } } +# <- { "return": {} } +# +## +{ 'command': 'dump-skeys', + 'data': { 'filename': 'str' }, + 'if': 'defined(TARGET_S390X)' } + +## +# @GICCapability: +# +# The struct describes capability for a specific GIC (Generic +# Interrupt Controller) version. These bits are not only decided by +# QEMU/KVM software version, but also decided by the hardware that +# the program is running upon. +# +# @version: version of GIC to be described. Currently, only 2 and 3 +# are supported. +# +# @emulated: whether current QEMU/hardware supports emulated GIC +# device in user space. +# +# @kernel: whether current QEMU/hardware supports hardware +# accelerated GIC device in kernel. +# +# Since: 2.6 +## +{ 'struct': 'GICCapability', + 'data': { 'version': 'int', + 'emulated': 'bool', + 'kernel': 'bool' }, + 'if': 'defined(TARGET_ARM)' } + +## +# @query-gic-capabilities: +# +# This command is ARM-only. It will return a list of GICCapability +# objects that describe its capability bits. +# +# Returns: a list of GICCapability objects. +# +# Since: 2.6 +# +# Example: +# +# -> { "execute": "query-gic-capabilities" } +# <- { "return": [{ "version": 2, "emulated": true, "kernel": false }, +# { "version": 3, "emulated": false, "kernel": true } ] } +# +## +{ 'command': 'query-gic-capabilities', 'returns': ['GICCapability'], + 'if': 'defined(TARGET_ARM)' } diff --git a/qapi/misc.json b/qapi/misc.json index dc4cf9da20..31427d45a6 100644 --- a/qapi/misc.json +++ b/qapi/misc.json @@ -343,276 +343,6 @@ { 'command': 'query-events', 'returns': ['EventInfo'] } ## -# @CpuInfoArch: -# -# An enumeration of cpu types that enable additional information during -# @query-cpus and @query-cpus-fast. -# -# @s390: since 2.12 -# -# @riscv: since 2.12 -# -# Since: 2.6 -## -{ 'enum': 'CpuInfoArch', - 'data': ['x86', 'sparc', 'ppc', 'mips', 'tricore', 's390', 'riscv', 'other' ] } - -## -# @CpuInfo: -# -# Information about a virtual CPU -# -# @CPU: the index of the virtual CPU -# -# @current: this only exists for backwards compatibility and should be ignored -# -# @halted: true if the virtual CPU is in the halt state. Halt usually refers -# to a processor specific low power mode. -# -# @qom_path: path to the CPU object in the QOM tree (since 2.4) -# -# @thread_id: ID of the underlying host thread -# -# @props: properties describing to which node/socket/core/thread -# virtual CPU belongs to, provided if supported by board (since 2.10) -# -# @arch: architecture of the cpu, which determines which additional fields -# will be listed (since 2.6) -# -# Since: 0.14.0 -# -# Notes: @halted is a transient state that changes frequently. By the time the -# data is sent to the client, the guest may no longer be halted. -## -{ 'union': 'CpuInfo', - 'base': {'CPU': 'int', 'current': 'bool', 'halted': 'bool', - 'qom_path': 'str', 'thread_id': 'int', - '*props': 'CpuInstanceProperties', 'arch': 'CpuInfoArch' }, - 'discriminator': 'arch', - 'data': { 'x86': 'CpuInfoX86', - 'sparc': 'CpuInfoSPARC', - 'ppc': 'CpuInfoPPC', - 'mips': 'CpuInfoMIPS', - 'tricore': 'CpuInfoTricore', - 's390': 'CpuInfoS390', - 'riscv': 'CpuInfoRISCV' } } - -## -# @CpuInfoX86: -# -# Additional information about a virtual i386 or x86_64 CPU -# -# @pc: the 64-bit instruction pointer -# -# Since: 2.6 -## -{ 'struct': 'CpuInfoX86', 'data': { 'pc': 'int' } } - -## -# @CpuInfoSPARC: -# -# Additional information about a virtual SPARC CPU -# -# @pc: the PC component of the instruction pointer -# -# @npc: the NPC component of the instruction pointer -# -# Since: 2.6 -## -{ 'struct': 'CpuInfoSPARC', 'data': { 'pc': 'int', 'npc': 'int' } } - -## -# @CpuInfoPPC: -# -# Additional information about a virtual PPC CPU -# -# @nip: the instruction pointer -# -# Since: 2.6 -## -{ 'struct': 'CpuInfoPPC', 'data': { 'nip': 'int' } } - -## -# @CpuInfoMIPS: -# -# Additional information about a virtual MIPS CPU -# -# @PC: the instruction pointer -# -# Since: 2.6 -## -{ 'struct': 'CpuInfoMIPS', 'data': { 'PC': 'int' } } - -## -# @CpuInfoTricore: -# -# Additional information about a virtual Tricore CPU -# -# @PC: the instruction pointer -# -# Since: 2.6 -## -{ 'struct': 'CpuInfoTricore', 'data': { 'PC': 'int' } } - -## -# @CpuInfoRISCV: -# -# Additional information about a virtual RISCV CPU -# -# @pc: the instruction pointer -# -# Since 2.12 -## -{ 'struct': 'CpuInfoRISCV', 'data': { 'pc': 'int' } } - -## -# @CpuS390State: -# -# An enumeration of cpu states that can be assumed by a virtual -# S390 CPU -# -# Since: 2.12 -## -{ 'enum': 'CpuS390State', - 'prefix': 'S390_CPU_STATE', - 'data': [ 'uninitialized', 'stopped', 'check-stop', 'operating', 'load' ] } - -## -# @CpuInfoS390: -# -# Additional information about a virtual S390 CPU -# -# @cpu-state: the virtual CPU's state -# -# Since: 2.12 -## -{ 'struct': 'CpuInfoS390', 'data': { 'cpu-state': 'CpuS390State' } } - -## -# @query-cpus: -# -# Returns a list of information about each virtual CPU. -# -# This command causes vCPU threads to exit to userspace, which causes -# a small interruption to guest CPU execution. This will have a negative -# impact on realtime guests and other latency sensitive guest workloads. -# It is recommended to use @query-cpus-fast instead of this command to -# avoid the vCPU interruption. -# -# Returns: a list of @CpuInfo for each virtual CPU -# -# Since: 0.14.0 -# -# Example: -# -# -> { "execute": "query-cpus" } -# <- { "return": [ -# { -# "CPU":0, -# "current":true, -# "halted":false, -# "qom_path":"/machine/unattached/device[0]", -# "arch":"x86", -# "pc":3227107138, -# "thread_id":3134 -# }, -# { -# "CPU":1, -# "current":false, -# "halted":true, -# "qom_path":"/machine/unattached/device[2]", -# "arch":"x86", -# "pc":7108165, -# "thread_id":3135 -# } -# ] -# } -# -# Notes: This interface is deprecated (since 2.12.0), and it is strongly -# recommended that you avoid using it. Use @query-cpus-fast to -# obtain information about virtual CPUs. -# -## -{ 'command': 'query-cpus', 'returns': ['CpuInfo'] } - -## -# @CpuInfoFast: -# -# Information about a virtual CPU -# -# @cpu-index: index of the virtual CPU -# -# @qom-path: path to the CPU object in the QOM tree -# -# @thread-id: ID of the underlying host thread -# -# @props: properties describing to which node/socket/core/thread -# virtual CPU belongs to, provided if supported by board -# -# @arch: base architecture of the cpu; deprecated since 3.0.0 in favor -# of @target -# -# @target: the QEMU system emulation target, which determines which -# additional fields will be listed (since 3.0) -# -# Since: 2.12 -# -## -{ 'union' : 'CpuInfoFast', - 'base' : { 'cpu-index' : 'int', - 'qom-path' : 'str', - 'thread-id' : 'int', - '*props' : 'CpuInstanceProperties', - 'arch' : 'CpuInfoArch', - 'target' : 'SysEmuTarget' }, - 'discriminator' : 'target', - 'data' : { 's390x' : 'CpuInfoS390' } } - -## -# @query-cpus-fast: -# -# Returns information about all virtual CPUs. This command does not -# incur a performance penalty and should be used in production -# instead of query-cpus. -# -# Returns: list of @CpuInfoFast -# -# Since: 2.12 -# -# Example: -# -# -> { "execute": "query-cpus-fast" } -# <- { "return": [ -# { -# "thread-id": 25627, -# "props": { -# "core-id": 0, -# "thread-id": 0, -# "socket-id": 0 -# }, -# "qom-path": "/machine/unattached/device[0]", -# "arch":"x86", -# "target":"x86_64", -# "cpu-index": 0 -# }, -# { -# "thread-id": 25628, -# "props": { -# "core-id": 0, -# "thread-id": 0, -# "socket-id": 1 -# }, -# "qom-path": "/machine/unattached/device[2]", -# "arch":"x86", -# "target":"x86_64", -# "cpu-index": 1 -# } -# ] -# } -## -{ 'command': 'query-cpus-fast', 'returns': [ 'CpuInfoFast' ] } - -## # @IOThreadInfo: # # Information about an iothread @@ -1106,29 +836,6 @@ { 'command': 'system_powerdown' } ## -# @cpu-add: -# -# Adds CPU with specified ID. -# -# @id: ID of CPU to be created, valid values [0..max_cpus) -# -# Returns: Nothing on success -# -# Since: 1.5 -# -# Note: This command is deprecated. The `device_add` command should be -# used instead. See the `query-hotpluggable-cpus` command for -# details. -# -# Example: -# -# -> { "execute": "cpu-add", "arguments": { "id": 2 } } -# <- { "return": {} } -# -## -{ 'command': 'cpu-add', 'data': {'id': 'int'} } - -## # @memsave: # # Save a portion of guest memory to a file. @@ -1343,140 +1050,6 @@ 'returns': 'str' } ## -# @ObjectPropertyInfo: -# -# @name: the name of the property -# -# @type: the type of the property. This will typically come in one of four -# forms: -# -# 1) A primitive type such as 'u8', 'u16', 'bool', 'str', or 'double'. -# These types are mapped to the appropriate JSON type. -# -# 2) A child type in the form 'child<subtype>' where subtype is a qdev -# device type name. Child properties create the composition tree. -# -# 3) A link type in the form 'link<subtype>' where subtype is a qdev -# device type name. Link properties form the device model graph. -# -# @description: if specified, the description of the property. -# -# Since: 1.2 -## -{ 'struct': 'ObjectPropertyInfo', - 'data': { 'name': 'str', 'type': 'str', '*description': 'str' } } - -## -# @qom-list: -# -# This command will list any properties of a object given a path in the object -# model. -# -# @path: the path within the object model. See @qom-get for a description of -# this parameter. -# -# Returns: a list of @ObjectPropertyInfo that describe the properties of the -# object. -# -# Since: 1.2 -# -# Example: -# -# -> { "execute": "qom-list", -# "arguments": { "path": "/chardevs" } } -# <- { "return": [ { "name": "type", "type": "string" }, -# { "name": "parallel0", "type": "child<chardev-vc>" }, -# { "name": "serial0", "type": "child<chardev-vc>" }, -# { "name": "mon0", "type": "child<chardev-stdio>" } ] } -# -## -{ 'command': 'qom-list', - 'data': { 'path': 'str' }, - 'returns': [ 'ObjectPropertyInfo' ], - 'allow-preconfig': true } - -## -# @qom-get: -# -# This command will get a property from a object model path and return the -# value. -# -# @path: The path within the object model. There are two forms of supported -# paths--absolute and partial paths. -# -# Absolute paths are derived from the root object and can follow child<> -# or link<> properties. Since they can follow link<> properties, they -# can be arbitrarily long. Absolute paths look like absolute filenames -# and are prefixed with a leading slash. -# -# Partial paths look like relative filenames. They do not begin -# with a prefix. The matching rules for partial paths are subtle but -# designed to make specifying objects easy. At each level of the -# composition tree, the partial path is matched as an absolute path. -# The first match is not returned. At least two matches are searched -# for. A successful result is only returned if only one match is -# found. If more than one match is found, a flag is return to -# indicate that the match was ambiguous. -# -# @property: The property name to read -# -# Returns: The property value. The type depends on the property -# type. child<> and link<> properties are returned as #str -# pathnames. All integer property types (u8, u16, etc) are -# returned as #int. -# -# Since: 1.2 -# -# Example: -# -# 1. Use absolute path -# -# -> { "execute": "qom-get", -# "arguments": { "path": "/machine/unattached/device[0]", -# "property": "hotplugged" } } -# <- { "return": false } -# -# 2. Use partial path -# -# -> { "execute": "qom-get", -# "arguments": { "path": "unattached/sysbus", -# "property": "type" } } -# <- { "return": "System" } -# -## -{ 'command': 'qom-get', - 'data': { 'path': 'str', 'property': 'str' }, - 'returns': 'any', - 'allow-preconfig': true } - -## -# @qom-set: -# -# This command will set a property from a object model path. -# -# @path: see @qom-get for a description of this parameter -# -# @property: the property name to set -# -# @value: a value who's type is appropriate for the property type. See @qom-get -# for a description of type mapping. -# -# Since: 1.2 -# -# Example: -# -# -> { "execute": "qom-set", -# "arguments": { "path": "/machine", -# "property": "graphics", -# "value": false } } -# <- { "return": {} } -# -## -{ 'command': 'qom-set', - 'data': { 'path': 'str', 'property': 'str', 'value': 'any' }, - 'allow-preconfig': true } - -## # @change: # # This command is multiple commands multiplexed together. @@ -1525,80 +1098,6 @@ 'data': {'device': 'str', 'target': 'str', '*arg': 'str'} } ## -# @ObjectTypeInfo: -# -# This structure describes a search result from @qom-list-types -# -# @name: the type name found in the search -# -# @abstract: the type is abstract and can't be directly instantiated. -# Omitted if false. (since 2.10) -# -# @parent: Name of parent type, if any (since 2.10) -# -# Since: 1.1 -## -{ 'struct': 'ObjectTypeInfo', - 'data': { 'name': 'str', '*abstract': 'bool', '*parent': 'str' } } - -## -# @qom-list-types: -# -# This command will return a list of types given search parameters -# -# @implements: if specified, only return types that implement this type name -# -# @abstract: if true, include abstract types in the results -# -# Returns: a list of @ObjectTypeInfo or an empty list if no results are found -# -# Since: 1.1 -## -{ 'command': 'qom-list-types', - 'data': { '*implements': 'str', '*abstract': 'bool' }, - 'returns': [ 'ObjectTypeInfo' ], - 'allow-preconfig': true } - -## -# @device-list-properties: -# -# List properties associated with a device. -# -# @typename: the type name of a device -# -# Returns: a list of ObjectPropertyInfo describing a devices properties -# -# Note: objects can create properties at runtime, for example to describe -# links between different devices and/or objects. These properties -# are not included in the output of this command. -# -# Since: 1.2 -## -{ 'command': 'device-list-properties', - 'data': { 'typename': 'str'}, - 'returns': [ 'ObjectPropertyInfo' ] } - -## -# @qom-list-properties: -# -# List properties associated with a QOM object. -# -# @typename: the type name of an object -# -# Note: objects can create properties at runtime, for example to describe -# links between different devices and/or objects. These properties -# are not included in the output of this command. -# -# Returns: a list of ObjectPropertyInfo describing object properties -# -# Since: 2.12 -## -{ 'command': 'qom-list-properties', - 'data': { 'typename': 'str'}, - 'returns': [ 'ObjectPropertyInfo' ], - 'allow-preconfig': true } - -## # @xen-set-global-dirty-log: # # Enable or disable the global dirty log mode. @@ -1619,341 +1118,6 @@ { 'command': 'xen-set-global-dirty-log', 'data': { 'enable': 'bool' } } ## -# @device_add: -# -# @driver: the name of the new device's driver -# -# @bus: the device's parent bus (device tree path) -# -# @id: the device's ID, must be unique -# -# Additional arguments depend on the type. -# -# Add a device. -# -# Notes: -# 1. For detailed information about this command, please refer to the -# 'docs/qdev-device-use.txt' file. -# -# 2. It's possible to list device properties by running QEMU with the -# "-device DEVICE,help" command-line argument, where DEVICE is the -# device's name -# -# Example: -# -# -> { "execute": "device_add", -# "arguments": { "driver": "e1000", "id": "net1", -# "bus": "pci.0", -# "mac": "52:54:00:12:34:56" } } -# <- { "return": {} } -# -# TODO: This command effectively bypasses QAPI completely due to its -# "additional arguments" business. It shouldn't have been added to -# the schema in this form. It should be qapified properly, or -# replaced by a properly qapified command. -# -# Since: 0.13 -## -{ 'command': 'device_add', - 'data': {'driver': 'str', '*bus': 'str', '*id': 'str'}, - 'gen': false } # so we can get the additional arguments - -## -# @device_del: -# -# Remove a device from a guest -# -# @id: the device's ID or QOM path -# -# Returns: Nothing on success -# If @id is not a valid device, DeviceNotFound -# -# Notes: When this command completes, the device may not be removed from the -# guest. Hot removal is an operation that requires guest cooperation. -# This command merely requests that the guest begin the hot removal -# process. Completion of the device removal process is signaled with a -# DEVICE_DELETED event. Guest reset will automatically complete removal -# for all devices. -# -# Since: 0.14.0 -# -# Example: -# -# -> { "execute": "device_del", -# "arguments": { "id": "net1" } } -# <- { "return": {} } -# -# -> { "execute": "device_del", -# "arguments": { "id": "/machine/peripheral-anon/device[0]" } } -# <- { "return": {} } -# -## -{ 'command': 'device_del', 'data': {'id': 'str'} } - -## -# @DEVICE_DELETED: -# -# Emitted whenever the device removal completion is acknowledged by the guest. -# At this point, it's safe to reuse the specified device ID. Device removal can -# be initiated by the guest or by HMP/QMP commands. -# -# @device: device name -# -# @path: device path -# -# Since: 1.5 -# -# Example: -# -# <- { "event": "DEVICE_DELETED", -# "data": { "device": "virtio-net-pci-0", -# "path": "/machine/peripheral/virtio-net-pci-0" }, -# "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } -# -## -{ 'event': 'DEVICE_DELETED', - 'data': { '*device': 'str', 'path': 'str' } } - -## -# @DumpGuestMemoryFormat: -# -# An enumeration of guest-memory-dump's format. -# -# @elf: elf format -# -# @kdump-zlib: kdump-compressed format with zlib-compressed -# -# @kdump-lzo: kdump-compressed format with lzo-compressed -# -# @kdump-snappy: kdump-compressed format with snappy-compressed -# -# @win-dmp: Windows full crashdump format, -# can be used instead of ELF converting (since 2.13) -# -# Since: 2.0 -## -{ 'enum': 'DumpGuestMemoryFormat', - 'data': [ 'elf', 'kdump-zlib', 'kdump-lzo', 'kdump-snappy', 'win-dmp' ] } - -## -# @dump-guest-memory: -# -# Dump guest's memory to vmcore. It is a synchronous operation that can take -# very long depending on the amount of guest memory. -# -# @paging: if true, do paging to get guest's memory mapping. This allows -# using gdb to process the core file. -# -# IMPORTANT: this option can make QEMU allocate several gigabytes -# of RAM. This can happen for a large guest, or a -# malicious guest pretending to be large. -# -# Also, paging=true has the following limitations: -# -# 1. The guest may be in a catastrophic state or can have corrupted -# memory, which cannot be trusted -# 2. The guest can be in real-mode even if paging is enabled. For -# example, the guest uses ACPI to sleep, and ACPI sleep state -# goes in real-mode -# 3. Currently only supported on i386 and x86_64. -# -# @protocol: the filename or file descriptor of the vmcore. The supported -# protocols are: -# -# 1. file: the protocol starts with "file:", and the following -# string is the file's path. -# 2. fd: the protocol starts with "fd:", and the following string -# is the fd's name. -# -# @detach: if true, QMP will return immediately rather than -# waiting for the dump to finish. The user can track progress -# using "query-dump". (since 2.6). -# -# @begin: if specified, the starting physical address. -# -# @length: if specified, the memory size, in bytes. If you don't -# want to dump all guest's memory, please specify the start @begin -# and @length -# -# @format: if specified, the format of guest memory dump. But non-elf -# format is conflict with paging and filter, ie. @paging, @begin and -# @length is not allowed to be specified with non-elf @format at the -# same time (since 2.0) -# -# Note: All boolean arguments default to false -# -# Returns: nothing on success -# -# Since: 1.2 -# -# Example: -# -# -> { "execute": "dump-guest-memory", -# "arguments": { "protocol": "fd:dump" } } -# <- { "return": {} } -# -## -{ 'command': 'dump-guest-memory', - 'data': { 'paging': 'bool', 'protocol': 'str', '*detach': 'bool', - '*begin': 'int', '*length': 'int', - '*format': 'DumpGuestMemoryFormat'} } - -## -# @DumpStatus: -# -# Describe the status of a long-running background guest memory dump. -# -# @none: no dump-guest-memory has started yet. -# -# @active: there is one dump running in background. -# -# @completed: the last dump has finished successfully. -# -# @failed: the last dump has failed. -# -# Since: 2.6 -## -{ 'enum': 'DumpStatus', - 'data': [ 'none', 'active', 'completed', 'failed' ] } - -## -# @DumpQueryResult: -# -# The result format for 'query-dump'. -# -# @status: enum of @DumpStatus, which shows current dump status -# -# @completed: bytes written in latest dump (uncompressed) -# -# @total: total bytes to be written in latest dump (uncompressed) -# -# Since: 2.6 -## -{ 'struct': 'DumpQueryResult', - 'data': { 'status': 'DumpStatus', - 'completed': 'int', - 'total': 'int' } } - -## -# @query-dump: -# -# Query latest dump status. -# -# Returns: A @DumpStatus object showing the dump status. -# -# Since: 2.6 -# -# Example: -# -# -> { "execute": "query-dump" } -# <- { "return": { "status": "active", "completed": 1024000, -# "total": 2048000 } } -# -## -{ 'command': 'query-dump', 'returns': 'DumpQueryResult' } - -## -# @DUMP_COMPLETED: -# -# Emitted when background dump has completed -# -# @result: final dump status -# -# @error: human-readable error string that provides -# hint on why dump failed. Only presents on failure. The -# user should not try to interpret the error string. -# -# Since: 2.6 -# -# Example: -# -# { "event": "DUMP_COMPLETED", -# "data": {"result": {"total": 1090650112, "status": "completed", -# "completed": 1090650112} } } -# -## -{ 'event': 'DUMP_COMPLETED' , - 'data': { 'result': 'DumpQueryResult', '*error': 'str' } } - -## -# @DumpGuestMemoryCapability: -# -# A list of the available formats for dump-guest-memory -# -# Since: 2.0 -## -{ 'struct': 'DumpGuestMemoryCapability', - 'data': { - 'formats': ['DumpGuestMemoryFormat'] } } - -## -# @query-dump-guest-memory-capability: -# -# Returns the available formats for dump-guest-memory -# -# Returns: A @DumpGuestMemoryCapability object listing available formats for -# dump-guest-memory -# -# Since: 2.0 -# -# Example: -# -# -> { "execute": "query-dump-guest-memory-capability" } -# <- { "return": { "formats": -# ["elf", "kdump-zlib", "kdump-lzo", "kdump-snappy"] } -# -## -{ 'command': 'query-dump-guest-memory-capability', - 'returns': 'DumpGuestMemoryCapability' } - -## -# @object-add: -# -# Create a QOM object. -# -# @qom-type: the class name for the object to be created -# -# @id: the name of the new object -# -# @props: a dictionary of properties to be passed to the backend -# -# Returns: Nothing on success -# Error if @qom-type is not a valid class name -# -# Since: 2.0 -# -# Example: -# -# -> { "execute": "object-add", -# "arguments": { "qom-type": "rng-random", "id": "rng1", -# "props": { "filename": "/dev/hwrng" } } } -# <- { "return": {} } -# -## -{ 'command': 'object-add', - 'data': {'qom-type': 'str', 'id': 'str', '*props': 'any'} } - -## -# @object-del: -# -# Remove a QOM object. -# -# @id: the name of the QOM object to remove -# -# Returns: Nothing on success -# Error if @id is not a valid id for a QOM object -# -# Since: 2.0 -# -# Example: -# -# -> { "execute": "object-del", "arguments": { "id": "rng1" } } -# <- { "return": {} } -# -## -{ 'command': 'object-del', 'data': {'id': 'str'} } - -## # @getfd: # # Receive a file descriptor via SCM rights and assign it a name @@ -1999,64 +1163,6 @@ { 'command': 'closefd', 'data': {'fdname': 'str'} } ## -# @MachineInfo: -# -# Information describing a machine. -# -# @name: the name of the machine -# -# @alias: an alias for the machine name -# -# @is-default: whether the machine is default -# -# @cpu-max: maximum number of CPUs supported by the machine type -# (since 1.5.0) -# -# @hotpluggable-cpus: cpu hotplug via -device is supported (since 2.7.0) -# -# Since: 1.2.0 -## -{ 'struct': 'MachineInfo', - 'data': { 'name': 'str', '*alias': 'str', - '*is-default': 'bool', 'cpu-max': 'int', - 'hotpluggable-cpus': 'bool'} } - -## -# @query-machines: -# -# Return a list of supported machines -# -# Returns: a list of MachineInfo -# -# Since: 1.2.0 -## -{ 'command': 'query-machines', 'returns': ['MachineInfo'] } - -## -# @CurrentMachineParams: -# -# Information describing the running machine parameters. -# -# @wakeup-suspend-support: true if the machine supports wake up from -# suspend -# -# Since: 4.0 -## -{ 'struct': 'CurrentMachineParams', - 'data': { 'wakeup-suspend-support': 'bool'} } - -## -# @query-current-machine: -# -# Return information on the current virtual machine. -# -# Returns: CurrentMachineParams -# -# Since: 4.0 -## -{ 'command': 'query-current-machine', 'returns': 'CurrentMachineParams' } - -## # @MemoryInfo: # # Actual memory information in bytes. @@ -2090,80 +1196,6 @@ ## -# @CpuModelInfo: -# -# Virtual CPU model. -# -# A CPU model consists of the name of a CPU definition, to which -# delta changes are applied (e.g. features added/removed). Most magic values -# that an architecture might require should be hidden behind the name. -# However, if required, architectures can expose relevant properties. -# -# @name: the name of the CPU definition the model is based on -# @props: a dictionary of QOM properties to be applied -# -# Since: 2.8.0 -## -{ 'struct': 'CpuModelInfo', - 'data': { 'name': 'str', - '*props': 'any' } } - -## -# @CpuModelExpansionType: -# -# An enumeration of CPU model expansion types. -# -# @static: Expand to a static CPU model, a combination of a static base -# model name and property delta changes. As the static base model will -# never change, the expanded CPU model will be the same, independent of -# QEMU version, machine type, machine options, and accelerator options. -# Therefore, the resulting model can be used by tooling without having -# to specify a compatibility machine - e.g. when displaying the "host" -# model. The @static CPU models are migration-safe. - -# @full: Expand all properties. The produced model is not guaranteed to be -# migration-safe, but allows tooling to get an insight and work with -# model details. -# -# Note: When a non-migration-safe CPU model is expanded in static mode, some -# features enabled by the CPU model may be omitted, because they can't be -# implemented by a static CPU model definition (e.g. cache info passthrough and -# PMU passthrough in x86). If you need an accurate representation of the -# features enabled by a non-migration-safe CPU model, use @full. If you need a -# static representation that will keep ABI compatibility even when changing QEMU -# version or machine-type, use @static (but keep in mind that some features may -# be omitted). -# -# Since: 2.8.0 -## -{ 'enum': 'CpuModelExpansionType', - 'data': [ 'static', 'full' ] } - - -## -# @CpuModelCompareResult: -# -# An enumeration of CPU model comparison results. The result is usually -# calculated using e.g. CPU features or CPU generations. -# -# @incompatible: If model A is incompatible to model B, model A is not -# guaranteed to run where model B runs and the other way around. -# -# @identical: If model A is identical to model B, model A is guaranteed to run -# where model B runs and the other way around. -# -# @superset: If model A is a superset of model B, model B is guaranteed to run -# where model A runs. There are no guarantees about the other way. -# -# @subset: If model A is a subset of model B, model A is guaranteed to run -# where model B runs. There are no guarantees about the other way. -# -# Since: 2.8.0 -## -{ 'enum': 'CpuModelCompareResult', - 'data': [ 'incompatible', 'identical', 'superset', 'subset' ] } - -## # @AddfdInfo: # # Information about a file descriptor that was added to an fd set. @@ -2484,226 +1516,6 @@ 'allow-preconfig': true } ## -# @X86CPURegister32: -# -# A X86 32-bit register -# -# Since: 1.5 -## -{ 'enum': 'X86CPURegister32', - 'data': [ 'EAX', 'EBX', 'ECX', 'EDX', 'ESP', 'EBP', 'ESI', 'EDI' ] } - -## -# @X86CPUFeatureWordInfo: -# -# Information about a X86 CPU feature word -# -# @cpuid-input-eax: Input EAX value for CPUID instruction for that feature word -# -# @cpuid-input-ecx: Input ECX value for CPUID instruction for that -# feature word -# -# @cpuid-register: Output register containing the feature bits -# -# @features: value of output register, containing the feature bits -# -# Since: 1.5 -## -{ 'struct': 'X86CPUFeatureWordInfo', - 'data': { 'cpuid-input-eax': 'int', - '*cpuid-input-ecx': 'int', - 'cpuid-register': 'X86CPURegister32', - 'features': 'int' } } - -## -# @DummyForceArrays: -# -# Not used by QMP; hack to let us use X86CPUFeatureWordInfoList internally -# -# Since: 2.5 -## -{ 'struct': 'DummyForceArrays', - 'data': { 'unused': ['X86CPUFeatureWordInfo'] } } - - -## -# @NumaOptionsType: -# -# @node: NUMA nodes configuration -# -# @dist: NUMA distance configuration (since 2.10) -# -# @cpu: property based CPU(s) to node mapping (Since: 2.10) -# -# Since: 2.1 -## -{ 'enum': 'NumaOptionsType', - 'data': [ 'node', 'dist', 'cpu' ] } - -## -# @NumaOptions: -# -# A discriminated record of NUMA options. (for OptsVisitor) -# -# Since: 2.1 -## -{ 'union': 'NumaOptions', - 'base': { 'type': 'NumaOptionsType' }, - 'discriminator': 'type', - 'data': { - 'node': 'NumaNodeOptions', - 'dist': 'NumaDistOptions', - 'cpu': 'NumaCpuOptions' }} - -## -# @NumaNodeOptions: -# -# Create a guest NUMA node. (for OptsVisitor) -# -# @nodeid: NUMA node ID (increase by 1 from 0 if omitted) -# -# @cpus: VCPUs belonging to this node (assign VCPUS round-robin -# if omitted) -# -# @mem: memory size of this node; mutually exclusive with @memdev. -# Equally divide total memory among nodes if both @mem and @memdev are -# omitted. -# -# @memdev: memory backend object. If specified for one node, -# it must be specified for all nodes. -# -# Since: 2.1 -## -{ 'struct': 'NumaNodeOptions', - 'data': { - '*nodeid': 'uint16', - '*cpus': ['uint16'], - '*mem': 'size', - '*memdev': 'str' }} - -## -# @NumaDistOptions: -# -# Set the distance between 2 NUMA nodes. -# -# @src: source NUMA node. -# -# @dst: destination NUMA node. -# -# @val: NUMA distance from source node to destination node. -# When a node is unreachable from another node, set the distance -# between them to 255. -# -# Since: 2.10 -## -{ 'struct': 'NumaDistOptions', - 'data': { - 'src': 'uint16', - 'dst': 'uint16', - 'val': 'uint8' }} - -## -# @NumaCpuOptions: -# -# Option "-numa cpu" overrides default cpu to node mapping. -# It accepts the same set of cpu properties as returned by -# query-hotpluggable-cpus[].props, where node-id could be used to -# override default node mapping. -# -# Since: 2.10 -## -{ 'struct': 'NumaCpuOptions', - 'base': 'CpuInstanceProperties', - 'data' : {} } - -## -# @HostMemPolicy: -# -# Host memory policy types -# -# @default: restore default policy, remove any nondefault policy -# -# @preferred: set the preferred host nodes for allocation -# -# @bind: a strict policy that restricts memory allocation to the -# host nodes specified -# -# @interleave: memory allocations are interleaved across the set -# of host nodes specified -# -# Since: 2.1 -## -{ 'enum': 'HostMemPolicy', - 'data': [ 'default', 'preferred', 'bind', 'interleave' ] } - -## -# @Memdev: -# -# Information about memory backend -# -# @id: backend's ID if backend has 'id' property (since 2.9) -# -# @size: memory backend size -# -# @merge: enables or disables memory merge support -# -# @dump: includes memory backend's memory in a core dump or not -# -# @prealloc: enables or disables memory preallocation -# -# @host-nodes: host nodes for its memory policy -# -# @policy: memory policy of memory backend -# -# Since: 2.1 -## -{ 'struct': 'Memdev', - 'data': { - '*id': 'str', - 'size': 'size', - 'merge': 'bool', - 'dump': 'bool', - 'prealloc': 'bool', - 'host-nodes': ['uint16'], - 'policy': 'HostMemPolicy' }} - -## -# @query-memdev: -# -# Returns information for all memory backends. -# -# Returns: a list of @Memdev. -# -# Since: 2.1 -# -# Example: -# -# -> { "execute": "query-memdev" } -# <- { "return": [ -# { -# "id": "mem1", -# "size": 536870912, -# "merge": false, -# "dump": true, -# "prealloc": false, -# "host-nodes": [0, 1], -# "policy": "bind" -# }, -# { -# "size": 536870912, -# "merge": false, -# "dump": true, -# "prealloc": true, -# "host-nodes": [2, 3], -# "policy": "preferred" -# } -# ] -# } -# -## -{ 'command': 'query-memdev', 'returns': ['Memdev'], 'allow-preconfig': true } - -## # @PCDIMMDeviceInfo: # # PCDIMMDevice state information @@ -2912,109 +1724,6 @@ { 'command': 'xen-load-devices-state', 'data': {'filename': 'str'} } ## -# @CpuInstanceProperties: -# -# List of properties to be used for hotplugging a CPU instance, -# it should be passed by management with device_add command when -# a CPU is being hotplugged. -# -# @node-id: NUMA node ID the CPU belongs to -# @socket-id: socket number within node/board the CPU belongs to -# @core-id: core number within socket the CPU belongs to -# @thread-id: thread number within core the CPU belongs to -# -# Note: currently there are 4 properties that could be present -# but management should be prepared to pass through other -# properties with device_add command to allow for future -# interface extension. This also requires the filed names to be kept in -# sync with the properties passed to -device/device_add. -# -# Since: 2.7 -## -{ 'struct': 'CpuInstanceProperties', - 'data': { '*node-id': 'int', - '*socket-id': 'int', - '*core-id': 'int', - '*thread-id': 'int' - } -} - -## -# @HotpluggableCPU: -# -# @type: CPU object type for usage with device_add command -# @props: list of properties to be used for hotplugging CPU -# @vcpus-count: number of logical VCPU threads @HotpluggableCPU provides -# @qom-path: link to existing CPU object if CPU is present or -# omitted if CPU is not present. -# -# Since: 2.7 -## -{ 'struct': 'HotpluggableCPU', - 'data': { 'type': 'str', - 'vcpus-count': 'int', - 'props': 'CpuInstanceProperties', - '*qom-path': 'str' - } -} - -## -# @query-hotpluggable-cpus: -# -# TODO: Better documentation; currently there is none. -# -# Returns: a list of HotpluggableCPU objects. -# -# Since: 2.7 -# -# Example: -# -# For pseries machine type started with -smp 2,cores=2,maxcpus=4 -cpu POWER8: -# -# -> { "execute": "query-hotpluggable-cpus" } -# <- {"return": [ -# { "props": { "core": 8 }, "type": "POWER8-spapr-cpu-core", -# "vcpus-count": 1 }, -# { "props": { "core": 0 }, "type": "POWER8-spapr-cpu-core", -# "vcpus-count": 1, "qom-path": "/machine/unattached/device[0]"} -# ]}' -# -# For pc machine type started with -smp 1,maxcpus=2: -# -# -> { "execute": "query-hotpluggable-cpus" } -# <- {"return": [ -# { -# "type": "qemu64-x86_64-cpu", "vcpus-count": 1, -# "props": {"core-id": 0, "socket-id": 1, "thread-id": 0} -# }, -# { -# "qom-path": "/machine/unattached/device[0]", -# "type": "qemu64-x86_64-cpu", "vcpus-count": 1, -# "props": {"core-id": 0, "socket-id": 0, "thread-id": 0} -# } -# ]} -# -# For s390x-virtio-ccw machine type started with -smp 1,maxcpus=2 -cpu qemu -# (Since: 2.11): -# -# -> { "execute": "query-hotpluggable-cpus" } -# <- {"return": [ -# { -# "type": "qemu-s390x-cpu", "vcpus-count": 1, -# "props": { "core-id": 1 } -# }, -# { -# "qom-path": "/machine/unattached/device[0]", -# "type": "qemu-s390x-cpu", "vcpus-count": 1, -# "props": { "core-id": 0 } -# } -# ]} -# -## -{ 'command': 'query-hotpluggable-cpus', 'returns': ['HotpluggableCPU'], - 'allow-preconfig': true } - -## # @GuidInfo: # # GUID information. @@ -3034,16 +1743,3 @@ ## { 'command': 'query-vm-generation-id', 'returns': 'GuidInfo' } -## -# @set-numa-node: -# -# Runtime equivalent of '-numa' CLI option, available at -# preconfigure stage to configure numa mapping before initializing -# machine. -# -# Since 3.0 -## -{ 'command': 'set-numa-node', 'boxed': true, - 'data': 'NumaOptions', - 'allow-preconfig': true -} diff --git a/qapi/net.json b/qapi/net.json index 5f7bff1637..728990f4fb 100644 --- a/qapi/net.json +++ b/qapi/net.json @@ -699,6 +699,13 @@ # # @step: Delay increase (in ms) after each self-announcement attempt # +# @interfaces: An optional list of interface names, which restricts the +# announcement to the listed interfaces. (Since 4.1) +# +# @id: A name to be used to identify an instance of announce-timers +# and to allow it to modified later. Not for use as +# part of the migration parameters. (Since 4.1) +# # Since: 4.0 ## @@ -706,7 +713,9 @@ 'data': { 'initial': 'int', 'max': 'int', 'rounds': 'int', - 'step': 'int' } } + 'step': 'int', + '*interfaces': ['str'], + '*id' : 'str' } } ## # @announce-self: @@ -718,9 +727,10 @@ # # Example: # -# -> { "execute": "announce-self" +# -> { "execute": "announce-self", # "arguments": { -# "initial": 50, "max": 550, "rounds": 10, "step": 50 } } +# "initial": 50, "max": 550, "rounds": 10, "step": 50, +# "interfaces": ["vn2", "vn3"], "id": "bob" } } # <- { "return": {} } # # Since: 4.0 diff --git a/qapi/qapi-schema.json b/qapi/qapi-schema.json index 4bd1223637..38af54d6b3 100644 --- a/qapi/qapi-schema.json +++ b/qapi/qapi-schema.json @@ -86,6 +86,7 @@ { 'include': 'crypto.json' } { 'include': 'block.json' } { 'include': 'char.json' } +{ 'include': 'dump.json' } { 'include': 'job.json' } { 'include': 'net.json' } { 'include': 'rdma.json' } @@ -97,6 +98,10 @@ { 'include': 'transaction.json' } { 'include': 'trace.json' } { 'include': 'introspect.json' } +{ 'include': 'qom.json' } +{ 'include': 'qdev.json' } +{ 'include': 'machine.json' } +{ 'include': 'machine-target.json' } { 'include': 'misc.json' } -{ 'include': 'target.json' } +{ 'include': 'misc-target.json' } { 'include': 'audio.json' } diff --git a/qapi/qdev.json b/qapi/qdev.json new file mode 100644 index 0000000000..c6d05032f4 --- /dev/null +++ b/qapi/qdev.json @@ -0,0 +1,125 @@ +# -*- Mode: Python -*- +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. + +## +# = Device infrastructure (qdev) +## + +{ 'include': 'qom.json' } + +## +# @device-list-properties: +# +# List properties associated with a device. +# +# @typename: the type name of a device +# +# Returns: a list of ObjectPropertyInfo describing a devices properties +# +# Note: objects can create properties at runtime, for example to describe +# links between different devices and/or objects. These properties +# are not included in the output of this command. +# +# Since: 1.2 +## +{ 'command': 'device-list-properties', + 'data': { 'typename': 'str'}, + 'returns': [ 'ObjectPropertyInfo' ] } + +## +# @device_add: +# +# @driver: the name of the new device's driver +# +# @bus: the device's parent bus (device tree path) +# +# @id: the device's ID, must be unique +# +# Additional arguments depend on the type. +# +# Add a device. +# +# Notes: +# 1. For detailed information about this command, please refer to the +# 'docs/qdev-device-use.txt' file. +# +# 2. It's possible to list device properties by running QEMU with the +# "-device DEVICE,help" command-line argument, where DEVICE is the +# device's name +# +# Example: +# +# -> { "execute": "device_add", +# "arguments": { "driver": "e1000", "id": "net1", +# "bus": "pci.0", +# "mac": "52:54:00:12:34:56" } } +# <- { "return": {} } +# +# TODO: This command effectively bypasses QAPI completely due to its +# "additional arguments" business. It shouldn't have been added to +# the schema in this form. It should be qapified properly, or +# replaced by a properly qapified command. +# +# Since: 0.13 +## +{ 'command': 'device_add', + 'data': {'driver': 'str', '*bus': 'str', '*id': 'str'}, + 'gen': false } # so we can get the additional arguments + +## +# @device_del: +# +# Remove a device from a guest +# +# @id: the device's ID or QOM path +# +# Returns: Nothing on success +# If @id is not a valid device, DeviceNotFound +# +# Notes: When this command completes, the device may not be removed from the +# guest. Hot removal is an operation that requires guest cooperation. +# This command merely requests that the guest begin the hot removal +# process. Completion of the device removal process is signaled with a +# DEVICE_DELETED event. Guest reset will automatically complete removal +# for all devices. +# +# Since: 0.14.0 +# +# Example: +# +# -> { "execute": "device_del", +# "arguments": { "id": "net1" } } +# <- { "return": {} } +# +# -> { "execute": "device_del", +# "arguments": { "id": "/machine/peripheral-anon/device[0]" } } +# <- { "return": {} } +# +## +{ 'command': 'device_del', 'data': {'id': 'str'} } + +## +# @DEVICE_DELETED: +# +# Emitted whenever the device removal completion is acknowledged by the guest. +# At this point, it's safe to reuse the specified device ID. Device removal can +# be initiated by the guest or by HMP/QMP commands. +# +# @device: device name +# +# @path: device path +# +# Since: 1.5 +# +# Example: +# +# <- { "event": "DEVICE_DELETED", +# "data": { "device": "virtio-net-pci-0", +# "path": "/machine/peripheral/virtio-net-pci-0" }, +# "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } +# +## +{ 'event': 'DEVICE_DELETED', + 'data': { '*device': 'str', 'path': 'str' } } diff --git a/qapi/qom.json b/qapi/qom.json new file mode 100644 index 0000000000..32db96ffc4 --- /dev/null +++ b/qapi/qom.json @@ -0,0 +1,244 @@ +# -*- Mode: Python -*- +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. + +## +# = QEMU Object Model (QOM) +## + +## +# @ObjectPropertyInfo: +# +# @name: the name of the property +# +# @type: the type of the property. This will typically come in one of four +# forms: +# +# 1) A primitive type such as 'u8', 'u16', 'bool', 'str', or 'double'. +# These types are mapped to the appropriate JSON type. +# +# 2) A child type in the form 'child<subtype>' where subtype is a qdev +# device type name. Child properties create the composition tree. +# +# 3) A link type in the form 'link<subtype>' where subtype is a qdev +# device type name. Link properties form the device model graph. +# +# @description: if specified, the description of the property. +# +# Since: 1.2 +## +{ 'struct': 'ObjectPropertyInfo', + 'data': { 'name': 'str', 'type': 'str', '*description': 'str' } } + +## +# @qom-list: +# +# This command will list any properties of a object given a path in the object +# model. +# +# @path: the path within the object model. See @qom-get for a description of +# this parameter. +# +# Returns: a list of @ObjectPropertyInfo that describe the properties of the +# object. +# +# Since: 1.2 +# +# Example: +# +# -> { "execute": "qom-list", +# "arguments": { "path": "/chardevs" } } +# <- { "return": [ { "name": "type", "type": "string" }, +# { "name": "parallel0", "type": "child<chardev-vc>" }, +# { "name": "serial0", "type": "child<chardev-vc>" }, +# { "name": "mon0", "type": "child<chardev-stdio>" } ] } +# +## +{ 'command': 'qom-list', + 'data': { 'path': 'str' }, + 'returns': [ 'ObjectPropertyInfo' ], + 'allow-preconfig': true } + +## +# @qom-get: +# +# This command will get a property from a object model path and return the +# value. +# +# @path: The path within the object model. There are two forms of supported +# paths--absolute and partial paths. +# +# Absolute paths are derived from the root object and can follow child<> +# or link<> properties. Since they can follow link<> properties, they +# can be arbitrarily long. Absolute paths look like absolute filenames +# and are prefixed with a leading slash. +# +# Partial paths look like relative filenames. They do not begin +# with a prefix. The matching rules for partial paths are subtle but +# designed to make specifying objects easy. At each level of the +# composition tree, the partial path is matched as an absolute path. +# The first match is not returned. At least two matches are searched +# for. A successful result is only returned if only one match is +# found. If more than one match is found, a flag is return to +# indicate that the match was ambiguous. +# +# @property: The property name to read +# +# Returns: The property value. The type depends on the property +# type. child<> and link<> properties are returned as #str +# pathnames. All integer property types (u8, u16, etc) are +# returned as #int. +# +# Since: 1.2 +# +# Example: +# +# 1. Use absolute path +# +# -> { "execute": "qom-get", +# "arguments": { "path": "/machine/unattached/device[0]", +# "property": "hotplugged" } } +# <- { "return": false } +# +# 2. Use partial path +# +# -> { "execute": "qom-get", +# "arguments": { "path": "unattached/sysbus", +# "property": "type" } } +# <- { "return": "System" } +# +## +{ 'command': 'qom-get', + 'data': { 'path': 'str', 'property': 'str' }, + 'returns': 'any', + 'allow-preconfig': true } + +## +# @qom-set: +# +# This command will set a property from a object model path. +# +# @path: see @qom-get for a description of this parameter +# +# @property: the property name to set +# +# @value: a value who's type is appropriate for the property type. See @qom-get +# for a description of type mapping. +# +# Since: 1.2 +# +# Example: +# +# -> { "execute": "qom-set", +# "arguments": { "path": "/machine", +# "property": "graphics", +# "value": false } } +# <- { "return": {} } +# +## +{ 'command': 'qom-set', + 'data': { 'path': 'str', 'property': 'str', 'value': 'any' }, + 'allow-preconfig': true } + +## +# @ObjectTypeInfo: +# +# This structure describes a search result from @qom-list-types +# +# @name: the type name found in the search +# +# @abstract: the type is abstract and can't be directly instantiated. +# Omitted if false. (since 2.10) +# +# @parent: Name of parent type, if any (since 2.10) +# +# Since: 1.1 +## +{ 'struct': 'ObjectTypeInfo', + 'data': { 'name': 'str', '*abstract': 'bool', '*parent': 'str' } } + +## +# @qom-list-types: +# +# This command will return a list of types given search parameters +# +# @implements: if specified, only return types that implement this type name +# +# @abstract: if true, include abstract types in the results +# +# Returns: a list of @ObjectTypeInfo or an empty list if no results are found +# +# Since: 1.1 +## +{ 'command': 'qom-list-types', + 'data': { '*implements': 'str', '*abstract': 'bool' }, + 'returns': [ 'ObjectTypeInfo' ], + 'allow-preconfig': true } + +## +# @qom-list-properties: +# +# List properties associated with a QOM object. +# +# @typename: the type name of an object +# +# Note: objects can create properties at runtime, for example to describe +# links between different devices and/or objects. These properties +# are not included in the output of this command. +# +# Returns: a list of ObjectPropertyInfo describing object properties +# +# Since: 2.12 +## +{ 'command': 'qom-list-properties', + 'data': { 'typename': 'str'}, + 'returns': [ 'ObjectPropertyInfo' ], + 'allow-preconfig': true } + +## +# @object-add: +# +# Create a QOM object. +# +# @qom-type: the class name for the object to be created +# +# @id: the name of the new object +# +# @props: a dictionary of properties to be passed to the backend +# +# Returns: Nothing on success +# Error if @qom-type is not a valid class name +# +# Since: 2.0 +# +# Example: +# +# -> { "execute": "object-add", +# "arguments": { "qom-type": "rng-random", "id": "rng1", +# "props": { "filename": "/dev/hwrng" } } } +# <- { "return": {} } +# +## +{ 'command': 'object-add', + 'data': {'qom-type': 'str', 'id': 'str', '*props': 'any'} } + +## +# @object-del: +# +# Remove a QOM object. +# +# @id: the name of the QOM object to remove +# +# Returns: Nothing on success +# Error if @id is not a valid id for a QOM object +# +# Since: 2.0 +# +# Example: +# +# -> { "execute": "object-del", "arguments": { "id": "rng1" } } +# <- { "return": {} } +# +## +{ 'command': 'object-del', 'data': {'id': 'str'} } diff --git a/qdev-monitor.c b/qdev-monitor.c index 373b9ad445..58222c2211 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -24,7 +24,7 @@ #include "monitor/qdev.h" #include "sysemu/arch_init.h" #include "qapi/error.h" -#include "qapi/qapi-commands-misc.h" +#include "qapi/qapi-commands-qdev.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qerror.h" #include "qemu/config-file.h" @@ -739,63 +739,6 @@ void hmp_info_qdm(Monitor *mon, const QDict *qdict) qdev_print_devinfos(true); } -typedef struct QOMCompositionState { - Monitor *mon; - int indent; -} QOMCompositionState; - -static void print_qom_composition(Monitor *mon, Object *obj, int indent); - -static int print_qom_composition_child(Object *obj, void *opaque) -{ - QOMCompositionState *s = opaque; - - print_qom_composition(s->mon, obj, s->indent); - - return 0; -} - -static void print_qom_composition(Monitor *mon, Object *obj, int indent) -{ - QOMCompositionState s = { - .mon = mon, - .indent = indent + 2, - }; - char *name; - - if (obj == object_get_root()) { - name = g_strdup(""); - } else { - name = object_get_canonical_path_component(obj); - } - monitor_printf(mon, "%*s/%s (%s)\n", indent, "", name, - object_get_typename(obj)); - g_free(name); - object_child_foreach(obj, print_qom_composition_child, &s); -} - -void hmp_info_qom_tree(Monitor *mon, const QDict *dict) -{ - const char *path = qdict_get_try_str(dict, "path"); - Object *obj; - bool ambiguous = false; - - if (path) { - obj = object_resolve_path(path, &ambiguous); - if (!obj) { - monitor_printf(mon, "Path '%s' could not be resolved.\n", path); - return; - } - if (ambiguous) { - monitor_printf(mon, "Warning: Path '%s' is ambiguous.\n", path); - return; - } - } else { - obj = qdev_get_machine(); - } - print_qom_composition(mon, obj, 0); -} - void qmp_device_add(QDict *qdict, QObject **ret_data, Error **errp) { Error *local_err = NULL; diff --git a/qemu-bridge-helper.c b/qemu-bridge-helper.c index f9940deefd..95624bc300 100644 --- a/qemu-bridge-helper.c +++ b/qemu-bridge-helper.c @@ -10,7 +10,17 @@ * * This work is licensed under the terms of the GNU GPL, version 2. See * the COPYING file in the top-level directory. - * + */ + +/* + * Known shortcomings: + * - There is no manual page + * - The syntax of the ACL file is not documented anywhere + * - parse_acl_file() doesn't report fopen() failure properly, fails + * to check ferror() after fgets() failure, arbitrarily truncates + * long lines, handles whitespace inconsistently, error messages + * don't point to the offending file and line, errors in included + * files are reported, but otherwise ignored, ... */ #include "qemu/osdep.h" diff --git a/qemu-deprecated.texi b/qemu-deprecated.texi index df04f2840b..40c017b426 100644 --- a/qemu-deprecated.texi +++ b/qemu-deprecated.texi @@ -144,6 +144,14 @@ The ``acl_show'', ``acl_reset'', ``acl_policy'', ``acl_add'', and ``acl_remove'' commands are deprecated with no replacement. Authorization for VNC should be performed using the pluggable QAuthZ objects. +@section Guest Emulator ISAs + +@subsection RISC-V ISA privledge specification version 1.09.1 (since 4.1) + +The RISC-V ISA privledge specification version 1.09.1 has been deprecated. +QEMU supports both the newer version 1.10.0 and the ratified version 1.11.0, these +should be used instead of the 1.09.1 version. + @section System emulator CPUS @subsection RISC-V ISA CPUs (since 4.1) @@ -243,3 +251,11 @@ Note that if you are exposing the export via /dev/nbd0, it is easier to just export the entire image and then mount only /dev/nbd0p1 than it is to reinvoke @command{qemu-nbd -c /dev/nbd0} limited to just a subset of the image. + +@section Build system + +@subsection Python 2 support (since 4.1.0) + +In the future, QEMU will require Python 3 to be available at +build time. Support for Python 2 in scripts shipped with QEMU +is deprecated. diff --git a/qemu-img.c b/qemu-img.c index 158b3a505f..79983772de 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -3518,7 +3518,7 @@ static int img_rebase(int argc, char **argv) * to take action */ ret = bdrv_is_allocated_above(backing_bs(bs), prefix_chain_bs, - offset, n, &n); + false, offset, n, &n); if (ret < 0) { error_report("error while reading image metadata: %s", strerror(-ret)); diff --git a/qemu-options.hx b/qemu-options.hx index 0d8beb4afd..c18b79099a 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -4477,7 +4477,7 @@ Dump the network traffic on netdev @var{dev} to the file specified by The file format is libpcap, so it can be analyzed with tools such as tcpdump or Wireshark. -@item -object colo-compare,id=@var{id},primary_in=@var{chardevid},secondary_in=@var{chardevid},outdev=@var{chardevid},iothread=@var{id}[,vnet_hdr_support] +@item -object colo-compare,id=@var{id},primary_in=@var{chardevid},secondary_in=@var{chardevid},outdev=@var{chardevid},iothread=@var{id}[,vnet_hdr_support][,notify_dev=@var{id}] Colo-compare gets packet from primary_in@var{chardevid} and secondary_in@var{chardevid}, than compare primary packet with secondary packet. If the packets are same, we will output primary @@ -4486,11 +4486,15 @@ do checkpoint and send primary packet to outdev@var{chardevid}. In order to improve efficiency, we need to put the task of comparison in another thread. If it has the vnet_hdr_support flag, colo compare will send/recv packet with vnet_hdr_len. +If you want to use Xen COLO, will need the notify_dev to notify Xen +colo-frame to do checkpoint. we must use it with the help of filter-mirror and filter-redirector. @example +KVM COLO + primary: -netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown -device e1000,id=e0,netdev=hn0,mac=52:a4:00:12:78:66 @@ -4514,6 +4518,33 @@ secondary: -object filter-redirector,id=f1,netdev=hn0,queue=tx,indev=red0 -object filter-redirector,id=f2,netdev=hn0,queue=rx,outdev=red1 + +Xen COLO + +primary: +-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown +-device e1000,id=e0,netdev=hn0,mac=52:a4:00:12:78:66 +-chardev socket,id=mirror0,host=3.3.3.3,port=9003,server,nowait +-chardev socket,id=compare1,host=3.3.3.3,port=9004,server,nowait +-chardev socket,id=compare0,host=3.3.3.3,port=9001,server,nowait +-chardev socket,id=compare0-0,host=3.3.3.3,port=9001 +-chardev socket,id=compare_out,host=3.3.3.3,port=9005,server,nowait +-chardev socket,id=compare_out0,host=3.3.3.3,port=9005 +-chardev socket,id=notify_way,host=3.3.3.3,port=9009,server,nowait +-object filter-mirror,id=m0,netdev=hn0,queue=tx,outdev=mirror0 +-object filter-redirector,netdev=hn0,id=redire0,queue=rx,indev=compare_out +-object filter-redirector,netdev=hn0,id=redire1,queue=rx,outdev=compare0 +-object iothread,id=iothread1 +-object colo-compare,id=comp0,primary_in=compare0-0,secondary_in=compare1,outdev=compare_out0,notify_dev=nofity_way,iothread=iothread1 + +secondary: +-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,down script=/etc/qemu-ifdown +-device e1000,netdev=hn0,mac=52:a4:00:12:78:66 +-chardev socket,id=red0,host=3.3.3.3,port=9003 +-chardev socket,id=red1,host=3.3.3.3,port=9004 +-object filter-redirector,id=f1,netdev=hn0,queue=tx,indev=red0 +-object filter-redirector,id=f2,netdev=hn0,queue=rx,outdev=red1 + @end example If you want to know the detail of above command line, you can read diff --git a/qom/Makefile.objs b/qom/Makefile.objs index 516349eec3..aae478fc21 100644 --- a/qom/Makefile.objs +++ b/qom/Makefile.objs @@ -2,3 +2,4 @@ qom-obj-y = object.o container.o qom-qobject.o qom-obj-y += object_interfaces.o common-obj-y = cpu.o +common-obj-$(CONFIG_SOFTMMU) += qom-hmp-cmds.o qom-qmp-cmds.o diff --git a/qom/qom-hmp-cmds.c b/qom/qom-hmp-cmds.c new file mode 100644 index 0000000000..a268e01eb4 --- /dev/null +++ b/qom/qom-hmp-cmds.c @@ -0,0 +1,120 @@ +/* + * HMP commands related to QOM + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * later. See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "hw/qdev-core.h" +#include "monitor/hmp.h" +#include "monitor/monitor.h" +#include "qapi/error.h" +#include "qapi/qapi-commands-qom.h" +#include "qapi/qmp/qdict.h" +#include "qom/object.h" + +void hmp_qom_list(Monitor *mon, const QDict *qdict) +{ + const char *path = qdict_get_try_str(qdict, "path"); + ObjectPropertyInfoList *list; + Error *err = NULL; + + if (path == NULL) { + monitor_printf(mon, "/\n"); + return; + } + + list = qmp_qom_list(path, &err); + if (err == NULL) { + ObjectPropertyInfoList *start = list; + while (list != NULL) { + ObjectPropertyInfo *value = list->value; + + monitor_printf(mon, "%s (%s)\n", + value->name, value->type); + list = list->next; + } + qapi_free_ObjectPropertyInfoList(start); + } + hmp_handle_error(mon, &err); +} + +void hmp_qom_set(Monitor *mon, const QDict *qdict) +{ + const char *path = qdict_get_str(qdict, "path"); + const char *property = qdict_get_str(qdict, "property"); + const char *value = qdict_get_str(qdict, "value"); + Error *err = NULL; + bool ambiguous = false; + Object *obj; + + obj = object_resolve_path(path, &ambiguous); + if (obj == NULL) { + error_set(&err, ERROR_CLASS_DEVICE_NOT_FOUND, + "Device '%s' not found", path); + } else { + if (ambiguous) { + monitor_printf(mon, "Warning: Path '%s' is ambiguous\n", path); + } + object_property_parse(obj, value, property, &err); + } + hmp_handle_error(mon, &err); +} + +typedef struct QOMCompositionState { + Monitor *mon; + int indent; +} QOMCompositionState; + +static void print_qom_composition(Monitor *mon, Object *obj, int indent); + +static int print_qom_composition_child(Object *obj, void *opaque) +{ + QOMCompositionState *s = opaque; + + print_qom_composition(s->mon, obj, s->indent); + + return 0; +} + +static void print_qom_composition(Monitor *mon, Object *obj, int indent) +{ + QOMCompositionState s = { + .mon = mon, + .indent = indent + 2, + }; + char *name; + + if (obj == object_get_root()) { + name = g_strdup(""); + } else { + name = object_get_canonical_path_component(obj); + } + monitor_printf(mon, "%*s/%s (%s)\n", indent, "", name, + object_get_typename(obj)); + g_free(name); + object_child_foreach(obj, print_qom_composition_child, &s); +} + +void hmp_info_qom_tree(Monitor *mon, const QDict *dict) +{ + const char *path = qdict_get_try_str(dict, "path"); + Object *obj; + bool ambiguous = false; + + if (path) { + obj = object_resolve_path(path, &ambiguous); + if (!obj) { + monitor_printf(mon, "Path '%s' could not be resolved.\n", path); + return; + } + if (ambiguous) { + monitor_printf(mon, "Warning: Path '%s' is ambiguous.\n", path); + return; + } + } else { + obj = qdev_get_machine(); + } + print_qom_composition(mon, obj, 0); +} diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c new file mode 100644 index 0000000000..e046a0f190 --- /dev/null +++ b/qom/qom-qmp-cmds.c @@ -0,0 +1,323 @@ +/* + * QMP commands related to QOM + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + * Contributions after 2012-01-13 are licensed under the terms of the + * GNU GPL, version 2 or (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "hw/qdev.h" +#include "qapi/error.h" +#include "qapi/qapi-commands-qdev.h" +#include "qapi/qapi-commands-qom.h" +#include "qapi/qmp/qdict.h" +#include "qapi/qmp/qerror.h" +#include "qapi/qobject-input-visitor.h" +#include "qemu/cutils.h" +#include "qom/object_interfaces.h" +#include "qom/qom-qobject.h" + +ObjectPropertyInfoList *qmp_qom_list(const char *path, Error **errp) +{ + Object *obj; + bool ambiguous = false; + ObjectPropertyInfoList *props = NULL; + ObjectProperty *prop; + ObjectPropertyIterator iter; + + obj = object_resolve_path(path, &ambiguous); + if (obj == NULL) { + if (ambiguous) { + error_setg(errp, "Path '%s' is ambiguous", path); + } else { + error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, + "Device '%s' not found", path); + } + return NULL; + } + + object_property_iter_init(&iter, obj); + while ((prop = object_property_iter_next(&iter))) { + ObjectPropertyInfoList *entry = g_malloc0(sizeof(*entry)); + + entry->value = g_malloc0(sizeof(ObjectPropertyInfo)); + entry->next = props; + props = entry; + + entry->value->name = g_strdup(prop->name); + entry->value->type = g_strdup(prop->type); + } + + return props; +} + +void qmp_qom_set(const char *path, const char *property, QObject *value, + Error **errp) +{ + Object *obj; + + obj = object_resolve_path(path, NULL); + if (!obj) { + error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, + "Device '%s' not found", path); + return; + } + + object_property_set_qobject(obj, value, property, errp); +} + +QObject *qmp_qom_get(const char *path, const char *property, Error **errp) +{ + Object *obj; + + obj = object_resolve_path(path, NULL); + if (!obj) { + error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, + "Device '%s' not found", path); + return NULL; + } + + return object_property_get_qobject(obj, property, errp); +} + +static void qom_list_types_tramp(ObjectClass *klass, void *data) +{ + ObjectTypeInfoList *e, **pret = data; + ObjectTypeInfo *info; + ObjectClass *parent = object_class_get_parent(klass); + + info = g_malloc0(sizeof(*info)); + info->name = g_strdup(object_class_get_name(klass)); + info->has_abstract = info->abstract = object_class_is_abstract(klass); + if (parent) { + info->has_parent = true; + info->parent = g_strdup(object_class_get_name(parent)); + } + + e = g_malloc0(sizeof(*e)); + e->value = info; + e->next = *pret; + *pret = e; +} + +ObjectTypeInfoList *qmp_qom_list_types(bool has_implements, + const char *implements, + bool has_abstract, + bool abstract, + Error **errp) +{ + ObjectTypeInfoList *ret = NULL; + + object_class_foreach(qom_list_types_tramp, implements, abstract, &ret); + + return ret; +} + +/* Return a DevicePropertyInfo for a qdev property. + * + * If a qdev property with the given name does not exist, use the given default + * type. If the qdev property info should not be shown, return NULL. + * + * The caller must free the return value. + */ +static ObjectPropertyInfo *make_device_property_info(ObjectClass *klass, + const char *name, + const char *default_type, + const char *description) +{ + ObjectPropertyInfo *info; + Property *prop; + + do { + for (prop = DEVICE_CLASS(klass)->props; prop && prop->name; prop++) { + if (strcmp(name, prop->name) != 0) { + continue; + } + + /* + * TODO Properties without a parser are just for dirty hacks. + * qdev_prop_ptr is the only such PropertyInfo. It's marked + * for removal. This conditional should be removed along with + * it. + */ + if (!prop->info->set && !prop->info->create) { + return NULL; /* no way to set it, don't show */ + } + + info = g_malloc0(sizeof(*info)); + info->name = g_strdup(prop->name); + info->type = default_type ? g_strdup(default_type) + : g_strdup(prop->info->name); + info->has_description = !!prop->info->description; + info->description = g_strdup(prop->info->description); + return info; + } + klass = object_class_get_parent(klass); + } while (klass != object_class_by_name(TYPE_DEVICE)); + + /* Not a qdev property, use the default type */ + info = g_malloc0(sizeof(*info)); + info->name = g_strdup(name); + info->type = g_strdup(default_type); + info->has_description = !!description; + info->description = g_strdup(description); + + return info; +} + +ObjectPropertyInfoList *qmp_device_list_properties(const char *typename, + Error **errp) +{ + ObjectClass *klass; + Object *obj; + ObjectProperty *prop; + ObjectPropertyIterator iter; + ObjectPropertyInfoList *prop_list = NULL; + + klass = object_class_by_name(typename); + if (klass == NULL) { + error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, + "Device '%s' not found", typename); + return NULL; + } + + klass = object_class_dynamic_cast(klass, TYPE_DEVICE); + if (klass == NULL) { + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "typename", TYPE_DEVICE); + return NULL; + } + + if (object_class_is_abstract(klass)) { + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "typename", + "non-abstract device type"); + return NULL; + } + + obj = object_new(typename); + + object_property_iter_init(&iter, obj); + while ((prop = object_property_iter_next(&iter))) { + ObjectPropertyInfo *info; + ObjectPropertyInfoList *entry; + + /* Skip Object and DeviceState properties */ + if (strcmp(prop->name, "type") == 0 || + strcmp(prop->name, "realized") == 0 || + strcmp(prop->name, "hotpluggable") == 0 || + strcmp(prop->name, "hotplugged") == 0 || + strcmp(prop->name, "parent_bus") == 0) { + continue; + } + + /* Skip legacy properties since they are just string versions of + * properties that we already list. + */ + if (strstart(prop->name, "legacy-", NULL)) { + continue; + } + + info = make_device_property_info(klass, prop->name, prop->type, + prop->description); + if (!info) { + continue; + } + + entry = g_malloc0(sizeof(*entry)); + entry->value = info; + entry->next = prop_list; + prop_list = entry; + } + + object_unref(obj); + + return prop_list; +} + +ObjectPropertyInfoList *qmp_qom_list_properties(const char *typename, + Error **errp) +{ + ObjectClass *klass; + Object *obj = NULL; + ObjectProperty *prop; + ObjectPropertyIterator iter; + ObjectPropertyInfoList *prop_list = NULL; + + klass = object_class_by_name(typename); + if (klass == NULL) { + error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, + "Class '%s' not found", typename); + return NULL; + } + + klass = object_class_dynamic_cast(klass, TYPE_OBJECT); + if (klass == NULL) { + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "typename", TYPE_OBJECT); + return NULL; + } + + if (object_class_is_abstract(klass)) { + object_class_property_iter_init(&iter, klass); + } else { + obj = object_new(typename); + object_property_iter_init(&iter, obj); + } + while ((prop = object_property_iter_next(&iter))) { + ObjectPropertyInfo *info; + ObjectPropertyInfoList *entry; + + info = g_malloc0(sizeof(*info)); + info->name = g_strdup(prop->name); + info->type = g_strdup(prop->type); + info->has_description = !!prop->description; + info->description = g_strdup(prop->description); + + entry = g_malloc0(sizeof(*entry)); + entry->value = info; + entry->next = prop_list; + prop_list = entry; + } + + object_unref(obj); + + return prop_list; +} + +void qmp_object_add(const char *type, const char *id, + bool has_props, QObject *props, Error **errp) +{ + QDict *pdict; + Visitor *v; + Object *obj; + + if (props) { + pdict = qobject_to(QDict, props); + if (!pdict) { + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "props", "dict"); + return; + } + qobject_ref(pdict); + } else { + pdict = qdict_new(); + } + + v = qobject_input_visitor_new(QOBJECT(pdict)); + obj = user_creatable_add_type(type, id, pdict, v, errp); + visit_free(v); + if (obj) { + object_unref(obj); + } + qobject_unref(pdict); +} + +void qmp_object_del(const char *id, Error **errp) +{ + user_creatable_del(id, errp); +} diff --git a/roms/openbios b/roms/openbios -Subproject 3464681b2b5983df80086a40179d324102347da +Subproject c79e0ecb84f4f1ee3f73f521622e264edd1bf17 diff --git a/scripts/device-crash-test b/scripts/device-crash-test index a6748910ad..15f213a6cd 100755 --- a/scripts/device-crash-test +++ b/scripts/device-crash-test @@ -36,7 +36,7 @@ import argparse from itertools import chain sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'python')) -from qemu import QEMUMachine +from qemu.machine import QEMUMachine logger = logging.getLogger('device-crash-test') dbg = logger.debug diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell index 7776c7b141..f1cddeafbc 100755 --- a/scripts/qmp/qmp-shell +++ b/scripts/qmp/qmp-shell @@ -78,6 +78,9 @@ import re sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python')) from qemu import qmp +if sys.version_info[0] == 2: + input = raw_input + class QMPCompleter(list): def complete(self, text, state): for cmd in self: @@ -308,7 +311,7 @@ class QMPShell(qmp.QEMUMonitorProtocol): @return True if execution was ok, return False if disconnected. """ try: - cmdline = raw_input(prompt) + cmdline = input(prompt) except EOFError: print() return False diff --git a/scripts/render_block_graph.py b/scripts/render_block_graph.py index 3e9d282a49..656f0388ad 100755 --- a/scripts/render_block_graph.py +++ b/scripts/render_block_graph.py @@ -25,7 +25,7 @@ import json from graphviz import Digraph sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'python')) -from qemu import MonitorResponseError +from qemu.machine import MonitorResponseError def perm(arr): diff --git a/target/arm/Makefile.objs b/target/arm/Makefile.objs index dfa736a375..5c154f01c5 100644 --- a/target/arm/Makefile.objs +++ b/target/arm/Makefile.objs @@ -1,16 +1,15 @@ obj-y += arm-semi.o -obj-$(CONFIG_SOFTMMU) += machine.o psci.o arch_dump.o monitor.o +obj-y += helper.o vfp_helper.o +obj-y += cpu.o gdbstub.o +obj-$(TARGET_AARCH64) += cpu64.o gdbstub64.o + +obj-$(CONFIG_SOFTMMU) += machine.o arch_dump.o monitor.o +obj-$(CONFIG_SOFTMMU) += arm-powerctl.o + obj-$(CONFIG_KVM) += kvm.o obj-$(call land,$(CONFIG_KVM),$(call lnot,$(TARGET_AARCH64))) += kvm32.o obj-$(call land,$(CONFIG_KVM),$(TARGET_AARCH64)) += kvm64.o obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o -obj-y += translate.o op_helper.o helper.o cpu.o -obj-y += neon_helper.o iwmmxt_helper.o vec_helper.o vfp_helper.o -obj-y += gdbstub.o -obj-$(TARGET_AARCH64) += cpu64.o translate-a64.o helper-a64.o gdbstub64.o -obj-$(TARGET_AARCH64) += pauth_helper.o -obj-y += crypto_helper.o -obj-$(CONFIG_SOFTMMU) += arm-powerctl.o DECODETREE = $(SRC_PATH)/scripts/decodetree.py @@ -33,4 +32,13 @@ target/arm/translate-sve.o: target/arm/decode-sve.inc.c target/arm/translate.o: target/arm/decode-vfp.inc.c target/arm/translate.o: target/arm/decode-vfp-uncond.inc.c +obj-y += tlb_helper.o +obj-y += translate.o op_helper.o +obj-y += crypto_helper.o +obj-y += iwmmxt_helper.o vec_helper.o neon_helper.o + +obj-$(CONFIG_SOFTMMU) += psci.o + +obj-$(TARGET_AARCH64) += translate-a64.o helper-a64.o obj-$(TARGET_AARCH64) += translate-sve.o sve_helper.o +obj-$(TARGET_AARCH64) += pauth_helper.o diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 376db154f0..f21261c8ff 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -19,6 +19,7 @@ */ #include "qemu/osdep.h" +#include "qemu/qemu-print.h" #include "qemu-common.h" #include "target/arm/idau.h" #include "qemu/module.h" @@ -676,6 +677,231 @@ static void arm_disas_set_info(CPUState *cpu, disassemble_info *info) #endif } +#ifdef TARGET_AARCH64 + +static void aarch64_cpu_dump_state(CPUState *cs, FILE *f, int flags) +{ + ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; + uint32_t psr = pstate_read(env); + int i; + int el = arm_current_el(env); + const char *ns_status; + + qemu_fprintf(f, " PC=%016" PRIx64 " ", env->pc); + for (i = 0; i < 32; i++) { + if (i == 31) { + qemu_fprintf(f, " SP=%016" PRIx64 "\n", env->xregs[i]); + } else { + qemu_fprintf(f, "X%02d=%016" PRIx64 "%s", i, env->xregs[i], + (i + 2) % 3 ? " " : "\n"); + } + } + + if (arm_feature(env, ARM_FEATURE_EL3) && el != 3) { + ns_status = env->cp15.scr_el3 & SCR_NS ? "NS " : "S "; + } else { + ns_status = ""; + } + qemu_fprintf(f, "PSTATE=%08x %c%c%c%c %sEL%d%c", + psr, + psr & PSTATE_N ? 'N' : '-', + psr & PSTATE_Z ? 'Z' : '-', + psr & PSTATE_C ? 'C' : '-', + psr & PSTATE_V ? 'V' : '-', + ns_status, + el, + psr & PSTATE_SP ? 'h' : 't'); + + if (cpu_isar_feature(aa64_bti, cpu)) { + qemu_fprintf(f, " BTYPE=%d", (psr & PSTATE_BTYPE) >> 10); + } + if (!(flags & CPU_DUMP_FPU)) { + qemu_fprintf(f, "\n"); + return; + } + if (fp_exception_el(env, el) != 0) { + qemu_fprintf(f, " FPU disabled\n"); + return; + } + qemu_fprintf(f, " FPCR=%08x FPSR=%08x\n", + vfp_get_fpcr(env), vfp_get_fpsr(env)); + + if (cpu_isar_feature(aa64_sve, cpu) && sve_exception_el(env, el) == 0) { + int j, zcr_len = sve_zcr_len_for_el(env, el); + + for (i = 0; i <= FFR_PRED_NUM; i++) { + bool eol; + if (i == FFR_PRED_NUM) { + qemu_fprintf(f, "FFR="); + /* It's last, so end the line. */ + eol = true; + } else { + qemu_fprintf(f, "P%02d=", i); + switch (zcr_len) { + case 0: + eol = i % 8 == 7; + break; + case 1: + eol = i % 6 == 5; + break; + case 2: + case 3: + eol = i % 3 == 2; + break; + default: + /* More than one quadword per predicate. */ + eol = true; + break; + } + } + for (j = zcr_len / 4; j >= 0; j--) { + int digits; + if (j * 4 + 4 <= zcr_len + 1) { + digits = 16; + } else { + digits = (zcr_len % 4 + 1) * 4; + } + qemu_fprintf(f, "%0*" PRIx64 "%s", digits, + env->vfp.pregs[i].p[j], + j ? ":" : eol ? "\n" : " "); + } + } + + for (i = 0; i < 32; i++) { + if (zcr_len == 0) { + qemu_fprintf(f, "Z%02d=%016" PRIx64 ":%016" PRIx64 "%s", + i, env->vfp.zregs[i].d[1], + env->vfp.zregs[i].d[0], i & 1 ? "\n" : " "); + } else if (zcr_len == 1) { + qemu_fprintf(f, "Z%02d=%016" PRIx64 ":%016" PRIx64 + ":%016" PRIx64 ":%016" PRIx64 "\n", + i, env->vfp.zregs[i].d[3], env->vfp.zregs[i].d[2], + env->vfp.zregs[i].d[1], env->vfp.zregs[i].d[0]); + } else { + for (j = zcr_len; j >= 0; j--) { + bool odd = (zcr_len - j) % 2 != 0; + if (j == zcr_len) { + qemu_fprintf(f, "Z%02d[%x-%x]=", i, j, j - 1); + } else if (!odd) { + if (j > 0) { + qemu_fprintf(f, " [%x-%x]=", j, j - 1); + } else { + qemu_fprintf(f, " [%x]=", j); + } + } + qemu_fprintf(f, "%016" PRIx64 ":%016" PRIx64 "%s", + env->vfp.zregs[i].d[j * 2 + 1], + env->vfp.zregs[i].d[j * 2], + odd || j == 0 ? "\n" : ":"); + } + } + } + } else { + for (i = 0; i < 32; i++) { + uint64_t *q = aa64_vfp_qreg(env, i); + qemu_fprintf(f, "Q%02d=%016" PRIx64 ":%016" PRIx64 "%s", + i, q[1], q[0], (i & 1 ? "\n" : " ")); + } + } +} + +#else + +static inline void aarch64_cpu_dump_state(CPUState *cs, FILE *f, int flags) +{ + g_assert_not_reached(); +} + +#endif + +static void arm_cpu_dump_state(CPUState *cs, FILE *f, int flags) +{ + ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; + int i; + + if (is_a64(env)) { + aarch64_cpu_dump_state(cs, f, flags); + return; + } + + for (i = 0; i < 16; i++) { + qemu_fprintf(f, "R%02d=%08x", i, env->regs[i]); + if ((i % 4) == 3) { + qemu_fprintf(f, "\n"); + } else { + qemu_fprintf(f, " "); + } + } + + if (arm_feature(env, ARM_FEATURE_M)) { + uint32_t xpsr = xpsr_read(env); + const char *mode; + const char *ns_status = ""; + + if (arm_feature(env, ARM_FEATURE_M_SECURITY)) { + ns_status = env->v7m.secure ? "S " : "NS "; + } + + if (xpsr & XPSR_EXCP) { + mode = "handler"; + } else { + if (env->v7m.control[env->v7m.secure] & R_V7M_CONTROL_NPRIV_MASK) { + mode = "unpriv-thread"; + } else { + mode = "priv-thread"; + } + } + + qemu_fprintf(f, "XPSR=%08x %c%c%c%c %c %s%s\n", + xpsr, + xpsr & XPSR_N ? 'N' : '-', + xpsr & XPSR_Z ? 'Z' : '-', + xpsr & XPSR_C ? 'C' : '-', + xpsr & XPSR_V ? 'V' : '-', + xpsr & XPSR_T ? 'T' : 'A', + ns_status, + mode); + } else { + uint32_t psr = cpsr_read(env); + const char *ns_status = ""; + + if (arm_feature(env, ARM_FEATURE_EL3) && + (psr & CPSR_M) != ARM_CPU_MODE_MON) { + ns_status = env->cp15.scr_el3 & SCR_NS ? "NS " : "S "; + } + + qemu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%s%d\n", + psr, + psr & CPSR_N ? 'N' : '-', + psr & CPSR_Z ? 'Z' : '-', + psr & CPSR_C ? 'C' : '-', + psr & CPSR_V ? 'V' : '-', + psr & CPSR_T ? 'T' : 'A', + ns_status, + aarch32_mode_name(psr), (psr & 0x10) ? 32 : 26); + } + + if (flags & CPU_DUMP_FPU) { + int numvfpregs = 0; + if (arm_feature(env, ARM_FEATURE_VFP)) { + numvfpregs += 16; + } + if (arm_feature(env, ARM_FEATURE_VFP3)) { + numvfpregs += 16; + } + for (i = 0; i < numvfpregs; i++) { + uint64_t v = *aa32_vfp_dreg(env, i); + qemu_fprintf(f, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64 "\n", + i * 2, (uint32_t)v, + i * 2 + 1, (uint32_t)(v >> 32), + i, v); + } + qemu_fprintf(f, "FPSCR: %08x\n", vfp_get_fpscr(env)); + } +} + uint64_t arm_cpu_mp_affinity(int idx, uint8_t clustersz) { uint32_t Aff1 = idx / clustersz; @@ -2340,8 +2566,6 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data) cc->gdb_write_register = arm_cpu_gdb_write_register; #ifndef CONFIG_USER_ONLY cc->do_interrupt = arm_cpu_do_interrupt; - cc->do_unaligned_access = arm_cpu_do_unaligned_access; - cc->do_transaction_failed = arm_cpu_do_transaction_failed; cc->get_phys_page_attrs_debug = arm_cpu_get_phys_page_attrs_debug; cc->asidx_from_attrs = arm_asidx_from_attrs; cc->vmsd = &vmstate_arm_cpu; @@ -2364,6 +2588,10 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data) #ifdef CONFIG_TCG cc->tcg_initialize = arm_translate_init; cc->tlb_fill = arm_cpu_tlb_fill; +#if !defined(CONFIG_USER_ONLY) + cc->do_unaligned_access = arm_cpu_do_unaligned_access; + cc->do_transaction_failed = arm_cpu_do_transaction_failed; +#endif /* CONFIG_TCG && !CONFIG_USER_ONLY */ #endif } diff --git a/target/arm/cpu.h b/target/arm/cpu.h index f9da672be5..a9be18660f 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -929,8 +929,6 @@ void arm_cpu_do_interrupt(CPUState *cpu); void arm_v7m_cpu_do_interrupt(CPUState *cpu); bool arm_cpu_exec_interrupt(CPUState *cpu, int int_req); -void arm_cpu_dump_state(CPUState *cs, FILE *f, int flags); - hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cpu, vaddr addr, MemTxAttrs *attrs); diff --git a/target/arm/helper.c b/target/arm/helper.c index df4276f5f6..9a1fe3b72e 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -1,3 +1,10 @@ +/* + * ARM generic helpers. + * + * This code is licensed under the GNU GPL v2 or later. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ #include "qemu/osdep.h" #include "qemu/units.h" #include "target/arm/idau.h" @@ -7,7 +14,6 @@ #include "exec/gdbstub.h" #include "exec/helper-proto.h" #include "qemu/host-utils.h" -#include "sysemu/arch_init.h" #include "sysemu/sysemu.h" #include "qemu/bitops.h" #include "qemu/crc32c.h" @@ -19,47 +25,20 @@ #include "hw/semihosting/semihost.h" #include "sysemu/cpus.h" #include "sysemu/kvm.h" -#include "fpu/softfloat.h" #include "qemu/range.h" -#include "qapi/qapi-commands-target.h" +#include "qapi/qapi-commands-machine-target.h" #include "qapi/error.h" #include "qemu/guest-random.h" #define ARM_CPU_FREQ 1000000000 /* FIXME: 1 GHz, should be configurable */ #ifndef CONFIG_USER_ONLY -/* Cacheability and shareability attributes for a memory access */ -typedef struct ARMCacheAttrs { - unsigned int attrs:8; /* as in the MAIR register encoding */ - unsigned int shareability:2; /* as in the SH field of the VMSAv8-64 PTEs */ -} ARMCacheAttrs; - -static bool get_phys_addr(CPUARMState *env, target_ulong address, - MMUAccessType access_type, ARMMMUIdx mmu_idx, - hwaddr *phys_ptr, MemTxAttrs *attrs, int *prot, - target_ulong *page_size, - ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs); static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address, MMUAccessType access_type, ARMMMUIdx mmu_idx, hwaddr *phys_ptr, MemTxAttrs *txattrs, int *prot, target_ulong *page_size_ptr, ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs); - -/* Security attributes for an address, as returned by v8m_security_lookup. */ -typedef struct V8M_SAttributes { - bool subpage; /* true if these attrs don't cover the whole TARGET_PAGE */ - bool ns; - bool nsc; - uint8_t sregion; - bool srvalid; - uint8_t iregion; - bool irvalid; -} V8M_SAttributes; - -static void v8m_security_lookup(CPUARMState *env, uint32_t address, - MMUAccessType access_type, ARMMMUIdx mmu_idx, - V8M_SAttributes *sattrs); #endif static void switch_mode(CPUARMState *env, int mode); @@ -7524,7 +7503,8 @@ void HELPER(v7m_vlldm)(CPUARMState *env, uint32_t fptr) uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op) { - /* The TT instructions can be used by unprivileged code, but in + /* + * The TT instructions can be used by unprivileged code, but in * user-only emulation we don't have the MPU. * Luckily since we know we are NonSecure unprivileged (and that in * turn means that the A flag wasn't specified), all the bits in the @@ -7700,22 +7680,41 @@ uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx, return target_el; } -/* - * Return true if the v7M CPACR permits access to the FPU for the specified - * security state and privilege level. - */ -static bool v7m_cpacr_pass(CPUARMState *env, bool is_secure, bool is_priv) +void arm_log_exception(int idx) { - switch (extract32(env->v7m.cpacr[is_secure], 20, 2)) { - case 0: - case 2: /* UNPREDICTABLE: we treat like 0 */ - return false; - case 1: - return is_priv; - case 3: - return true; - default: - g_assert_not_reached(); + if (qemu_loglevel_mask(CPU_LOG_INT)) { + const char *exc = NULL; + static const char * const excnames[] = { + [EXCP_UDEF] = "Undefined Instruction", + [EXCP_SWI] = "SVC", + [EXCP_PREFETCH_ABORT] = "Prefetch Abort", + [EXCP_DATA_ABORT] = "Data Abort", + [EXCP_IRQ] = "IRQ", + [EXCP_FIQ] = "FIQ", + [EXCP_BKPT] = "Breakpoint", + [EXCP_EXCEPTION_EXIT] = "QEMU v7M exception exit", + [EXCP_KERNEL_TRAP] = "QEMU intercept of kernel commpage", + [EXCP_HVC] = "Hypervisor Call", + [EXCP_HYP_TRAP] = "Hypervisor Trap", + [EXCP_SMC] = "Secure Monitor Call", + [EXCP_VIRQ] = "Virtual IRQ", + [EXCP_VFIQ] = "Virtual FIQ", + [EXCP_SEMIHOST] = "Semihosting call", + [EXCP_NOCP] = "v7M NOCP UsageFault", + [EXCP_INVSTATE] = "v7M INVSTATE UsageFault", + [EXCP_STKOF] = "v8M STKOF UsageFault", + [EXCP_LAZYFP] = "v7M exception during lazy FP stacking", + [EXCP_LSERR] = "v8M LSERR UsageFault", + [EXCP_UNALIGNED] = "v7M UNALIGNED UsageFault", + }; + + if (idx >= 0 && idx < ARRAY_SIZE(excnames)) { + exc = excnames[idx]; + } + if (!exc) { + exc = "unknown"; + } + qemu_log_mask(CPU_LOG_INT, "Taking exception %d [%s]\n", idx, exc); } } @@ -7796,7 +7795,8 @@ static bool v7m_stack_write(ARMCPU *cpu, uint32_t addr, uint32_t value, return true; pend_fault: - /* By pending the exception at this point we are making + /* + * By pending the exception at this point we are making * the IMPDEF choice "overridden exceptions pended" (see the * MergeExcInfo() pseudocode). The other choice would be to not * pend them now and then make a choice about which to throw away @@ -7871,7 +7871,8 @@ static bool v7m_stack_read(ARMCPU *cpu, uint32_t *dest, uint32_t addr, return true; pend_fault: - /* By pending the exception at this point we are making + /* + * By pending the exception at this point we are making * the IMPDEF choice "overridden exceptions pended" (see the * MergeExcInfo() pseudocode). The other choice would be to not * pend them now and then make a choice about which to throw away @@ -7972,7 +7973,8 @@ void HELPER(v7m_preserve_fp_state)(CPUARMState *env) */ } -/* Write to v7M CONTROL.SPSEL bit for the specified security bank. +/* + * Write to v7M CONTROL.SPSEL bit for the specified security bank. * This may change the current stack pointer between Main and Process * stack pointers if it is done for the CONTROL register for the current * security state. @@ -8000,7 +8002,8 @@ static void write_v7m_control_spsel_for_secstate(CPUARMState *env, } } -/* Write to v7M CONTROL.SPSEL bit. This may change the current +/* + * Write to v7M CONTROL.SPSEL bit. This may change the current * stack pointer between Main and Process stack pointers. */ static void write_v7m_control_spsel(CPUARMState *env, bool new_spsel) @@ -8010,7 +8013,8 @@ static void write_v7m_control_spsel(CPUARMState *env, bool new_spsel) void write_v7m_exception(CPUARMState *env, uint32_t new_exc) { - /* Write a new value to v7m.exception, thus transitioning into or out + /* + * Write a new value to v7m.exception, thus transitioning into or out * of Handler mode; this may result in a change of active stack pointer. */ bool new_is_psp, old_is_psp = v7m_using_psp(env); @@ -8036,7 +8040,8 @@ static void switch_v7m_security_state(CPUARMState *env, bool new_secstate) return; } - /* All the banked state is accessed by looking at env->v7m.secure + /* + * All the banked state is accessed by looking at env->v7m.secure * except for the stack pointer; rearrange the SP appropriately. */ new_ss_msp = env->v7m.other_ss_msp; @@ -8063,7 +8068,8 @@ static void switch_v7m_security_state(CPUARMState *env, bool new_secstate) void HELPER(v7m_bxns)(CPUARMState *env, uint32_t dest) { - /* Handle v7M BXNS: + /* + * Handle v7M BXNS: * - if the return value is a magic value, do exception return (like BX) * - otherwise bit 0 of the return value is the target security state */ @@ -8078,7 +8084,8 @@ void HELPER(v7m_bxns)(CPUARMState *env, uint32_t dest) } if (dest >= min_magic) { - /* This is an exception return magic value; put it where + /* + * This is an exception return magic value; put it where * do_v7m_exception_exit() expects and raise EXCEPTION_EXIT. * Note that if we ever add gen_ss_advance() singlestep support to * M profile this should count as an "instruction execution complete" @@ -8103,7 +8110,8 @@ void HELPER(v7m_bxns)(CPUARMState *env, uint32_t dest) void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest) { - /* Handle v7M BLXNS: + /* + * Handle v7M BLXNS: * - bit 0 of the destination address is the target security state */ @@ -8116,7 +8124,8 @@ void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest) assert(env->v7m.secure); if (dest & 1) { - /* target is Secure, so this is just a normal BLX, + /* + * Target is Secure, so this is just a normal BLX, * except that the low bit doesn't indicate Thumb/not. */ env->regs[14] = nextinst; @@ -8147,7 +8156,8 @@ void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest) env->regs[13] = sp; env->regs[14] = 0xfeffffff; if (arm_v7m_is_handler_mode(env)) { - /* Write a dummy value to IPSR, to avoid leaking the current secure + /* + * Write a dummy value to IPSR, to avoid leaking the current secure * exception number to non-secure code. This is guaranteed not * to cause write_v7m_exception() to actually change stacks. */ @@ -8162,7 +8172,8 @@ void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest) static uint32_t *get_v7m_sp_ptr(CPUARMState *env, bool secure, bool threadmode, bool spsel) { - /* Return a pointer to the location where we currently store the + /* + * Return a pointer to the location where we currently store the * stack pointer for the requested security state and thread mode. * This pointer will become invalid if the CPU state is updated * such that the stack pointers are switched around (eg changing @@ -8208,7 +8219,8 @@ static bool arm_v7m_load_vector(ARMCPU *cpu, int exc, bool targets_secure, mmu_idx = arm_v7m_mmu_idx_for_secstate_and_priv(env, targets_secure, true); - /* We don't do a get_phys_addr() here because the rules for vector + /* + * We don't do a get_phys_addr() here because the rules for vector * loads are special: they always use the default memory map, and * the default memory map permits reads from all addresses. * Since there's no easy way to pass through to pmsav8_mpu_lookup() @@ -8239,7 +8251,8 @@ static bool arm_v7m_load_vector(ARMCPU *cpu, int exc, bool targets_secure, return true; load_fail: - /* All vector table fetch fails are reported as HardFault, with + /* + * All vector table fetch fails are reported as HardFault, with * HFSR.VECTTBL and .FORCED set. (FORCED is set because * technically the underlying exception is a MemManage or BusFault * that is escalated to HardFault.) This is a terminal exception, @@ -8271,7 +8284,8 @@ static uint32_t v7m_integrity_sig(CPUARMState *env, uint32_t lr) static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain, bool ignore_faults) { - /* For v8M, push the callee-saves register part of the stack frame. + /* + * For v8M, push the callee-saves register part of the stack frame. * Compare the v8M pseudocode PushCalleeStack(). * In the tailchaining case this may not be the current stack. */ @@ -8322,7 +8336,8 @@ static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain, return true; } - /* Write as much of the stack frame as we can. A write failure may + /* + * Write as much of the stack frame as we can. A write failure may * cause us to pend a derived exception. */ sig = v7m_integrity_sig(env, lr); @@ -8346,7 +8361,8 @@ static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain, static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain, bool ignore_stackfaults) { - /* Do the "take the exception" parts of exception entry, + /* + * Do the "take the exception" parts of exception entry, * but not the pushing of state to the stack. This is * similar to the pseudocode ExceptionTaken() function. */ @@ -8371,13 +8387,15 @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain, if (arm_feature(env, ARM_FEATURE_V8)) { if (arm_feature(env, ARM_FEATURE_M_SECURITY) && (lr & R_V7M_EXCRET_S_MASK)) { - /* The background code (the owner of the registers in the + /* + * The background code (the owner of the registers in the * exception frame) is Secure. This means it may either already * have or now needs to push callee-saves registers. */ if (targets_secure) { if (dotailchain && !(lr & R_V7M_EXCRET_ES_MASK)) { - /* We took an exception from Secure to NonSecure + /* + * We took an exception from Secure to NonSecure * (which means the callee-saved registers got stacked) * and are now tailchaining to a Secure exception. * Clear DCRS so eventual return from this Secure @@ -8386,7 +8404,8 @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain, lr &= ~R_V7M_EXCRET_DCRS_MASK; } } else { - /* We're going to a non-secure exception; push the + /* + * We're going to a non-secure exception; push the * callee-saves registers to the stack now, if they're * not already saved. */ @@ -8408,14 +8427,16 @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain, lr |= R_V7M_EXCRET_SPSEL_MASK; } - /* Clear registers if necessary to prevent non-secure exception + /* + * Clear registers if necessary to prevent non-secure exception * code being able to see register values from secure code. * Where register values become architecturally UNKNOWN we leave * them with their previous values. */ if (arm_feature(env, ARM_FEATURE_M_SECURITY)) { if (!targets_secure) { - /* Always clear the caller-saved registers (they have been + /* + * Always clear the caller-saved registers (they have been * pushed to the stack earlier in v7m_push_stack()). * Clear callee-saved registers if the background code is * Secure (in which case these regs were saved in @@ -8436,7 +8457,8 @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain, } if (push_failed && !ignore_stackfaults) { - /* Derived exception on callee-saves register stacking: + /* + * Derived exception on callee-saves register stacking: * we might now want to take a different exception which * targets a different security state, so try again from the top. */ @@ -8453,7 +8475,8 @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain, return; } - /* Now we've done everything that might cause a derived exception + /* + * Now we've done everything that might cause a derived exception * we can go ahead and activate whichever exception we're going to * take (which might now be the derived exception). */ @@ -8656,7 +8679,8 @@ void HELPER(v7m_vlldm)(CPUARMState *env, uint32_t fptr) static bool v7m_push_stack(ARMCPU *cpu) { - /* Do the "set up stack frame" part of exception entry, + /* + * Do the "set up stack frame" part of exception entry, * similar to pseudocode PushStack(). * Return true if we generate a derived exception (and so * should ignore further stack faults trying to process @@ -8724,7 +8748,8 @@ static bool v7m_push_stack(ARMCPU *cpu) } } - /* Write as much of the stack frame as we can. If we fail a stack + /* + * Write as much of the stack frame as we can. If we fail a stack * write this will result in a derived exception being pended * (which may be taken in preference to the one we started with * if it has higher priority). @@ -8841,7 +8866,8 @@ static void do_v7m_exception_exit(ARMCPU *cpu) bool ftype; bool restore_s16_s31; - /* If we're not in Handler mode then jumps to magic exception-exit + /* + * If we're not in Handler mode then jumps to magic exception-exit * addresses don't have magic behaviour. However for the v8M * security extensions the magic secure-function-return has to * work in thread mode too, so to avoid doing an extra check in @@ -8855,7 +8881,8 @@ static void do_v7m_exception_exit(ARMCPU *cpu) return; } - /* In the spec pseudocode ExceptionReturn() is called directly + /* + * In the spec pseudocode ExceptionReturn() is called directly * from BXWritePC() and gets the full target PC value including * bit zero. In QEMU's implementation we treat it as a normal * jump-to-register (which is then caught later on), and so split @@ -8888,7 +8915,8 @@ static void do_v7m_exception_exit(ARMCPU *cpu) } if (arm_feature(env, ARM_FEATURE_M_SECURITY)) { - /* EXC_RETURN.ES validation check (R_SMFL). We must do this before + /* + * EXC_RETURN.ES validation check (R_SMFL). We must do this before * we pick which FAULTMASK to clear. */ if (!env->v7m.secure && @@ -8902,7 +8930,8 @@ static void do_v7m_exception_exit(ARMCPU *cpu) } if (env->v7m.exception != ARMV7M_EXCP_NMI) { - /* Auto-clear FAULTMASK on return from other than NMI. + /* + * Auto-clear FAULTMASK on return from other than NMI. * If the security extension is implemented then this only * happens if the raw execution priority is >= 0; the * value of the ES bit in the exception return value indicates @@ -8927,7 +8956,8 @@ static void do_v7m_exception_exit(ARMCPU *cpu) /* still an irq active now */ break; case 1: - /* we returned to base exception level, no nesting. + /* + * We returned to base exception level, no nesting. * (In the pseudocode this is written using "NestedActivation != 1" * where we have 'rettobase == false'.) */ @@ -8944,7 +8974,8 @@ static void do_v7m_exception_exit(ARMCPU *cpu) if (arm_feature(env, ARM_FEATURE_V8)) { if (!arm_feature(env, ARM_FEATURE_M_SECURITY)) { - /* UNPREDICTABLE if S == 1 or DCRS == 0 or ES == 1 (R_XLCP); + /* + * UNPREDICTABLE if S == 1 or DCRS == 0 or ES == 1 (R_XLCP); * we choose to take the UsageFault. */ if ((excret & R_V7M_EXCRET_S_MASK) || @@ -8963,7 +8994,8 @@ static void do_v7m_exception_exit(ARMCPU *cpu) break; case 13: /* Return to Thread using Process stack */ case 9: /* Return to Thread using Main stack */ - /* We only need to check NONBASETHRDENA for v7M, because in + /* + * We only need to check NONBASETHRDENA for v7M, because in * v8M this bit does not exist (it is RES1). */ if (!rettobase && @@ -9021,7 +9053,8 @@ static void do_v7m_exception_exit(ARMCPU *cpu) } if (ufault) { - /* Bad exception return: instead of popping the exception + /* + * Bad exception return: instead of popping the exception * stack, directly take a usage fault on the current stack. */ env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_INVPC_MASK; @@ -9051,7 +9084,8 @@ static void do_v7m_exception_exit(ARMCPU *cpu) switch_v7m_security_state(env, return_to_secure); { - /* The stack pointer we should be reading the exception frame from + /* + * The stack pointer we should be reading the exception frame from * depends on bits in the magic exception return type value (and * for v8M isn't necessarily the stack pointer we will eventually * end up resuming execution with). Get a pointer to the location @@ -9124,7 +9158,8 @@ static void do_v7m_exception_exit(ARMCPU *cpu) v7m_stack_read(cpu, &xpsr, frameptr + 0x1c, mmu_idx); if (!pop_ok) { - /* v7m_stack_read() pended a fault, so take it (as a tail + /* + * v7m_stack_read() pended a fault, so take it (as a tail * chained exception on the same stack frame) */ qemu_log_mask(CPU_LOG_INT, "...derived exception on unstacking\n"); @@ -9132,7 +9167,8 @@ static void do_v7m_exception_exit(ARMCPU *cpu) return; } - /* Returning from an exception with a PC with bit 0 set is defined + /* + * Returning from an exception with a PC with bit 0 set is defined * behaviour on v8M (bit 0 is ignored), but for v7M it was specified * to be UNPREDICTABLE. In practice actual v7M hardware seems to ignore * the lsbit, and there are several RTOSes out there which incorrectly @@ -9150,13 +9186,15 @@ static void do_v7m_exception_exit(ARMCPU *cpu) } if (arm_feature(env, ARM_FEATURE_V8)) { - /* For v8M we have to check whether the xPSR exception field + /* + * For v8M we have to check whether the xPSR exception field * matches the EXCRET value for return to handler/thread * before we commit to changing the SP and xPSR. */ bool will_be_handler = (xpsr & XPSR_EXCP) != 0; if (return_to_handler != will_be_handler) { - /* Take an INVPC UsageFault on the current stack. + /* + * Take an INVPC UsageFault on the current stack. * By this point we will have switched to the security state * for the background state, so this UsageFault will target * that state. @@ -9271,7 +9309,8 @@ static void do_v7m_exception_exit(ARMCPU *cpu) frameptr += 0x40; } } - /* Undo stack alignment (the SPREALIGN bit indicates that the original + /* + * Undo stack alignment (the SPREALIGN bit indicates that the original * pre-exception SP was not 8-aligned and we added a padding word to * align it, so we undo this by ORing in the bit that increases it * from the current 8-aligned value to the 8-unaligned value. (Adding 4 @@ -9297,13 +9336,15 @@ static void do_v7m_exception_exit(ARMCPU *cpu) V7M_CONTROL, SFPA, sfpa); } - /* The restored xPSR exception field will be zero if we're + /* + * The restored xPSR exception field will be zero if we're * resuming in Thread mode. If that doesn't match what the * exception return excret specified then this is a UsageFault. * v7M requires we make this check here; v8M did it earlier. */ if (return_to_handler != arm_v7m_is_handler_mode(env)) { - /* Take an INVPC UsageFault by pushing the stack again; + /* + * Take an INVPC UsageFault by pushing the stack again; * we know we're v7M so this is never a Secure UsageFault. */ bool ignore_stackfaults; @@ -9325,7 +9366,8 @@ static void do_v7m_exception_exit(ARMCPU *cpu) static bool do_v7m_function_return(ARMCPU *cpu) { - /* v8M security extensions magic function return. + /* + * v8M security extensions magic function return. * We may either: * (1) throw an exception (longjump) * (2) return true if we successfully handled the function return @@ -9355,7 +9397,8 @@ static bool do_v7m_function_return(ARMCPU *cpu) frame_sp_p = get_v7m_sp_ptr(env, true, threadmode, spsel); frameptr = *frame_sp_p; - /* These loads may throw an exception (for MPU faults). We want to + /* + * These loads may throw an exception (for MPU faults). We want to * do them as secure, so work out what MMU index that is. */ mmu_idx = arm_v7m_mmu_idx_for_secstate(env, true); @@ -9395,48 +9438,11 @@ static bool do_v7m_function_return(ARMCPU *cpu) return true; } -static void arm_log_exception(int idx) -{ - if (qemu_loglevel_mask(CPU_LOG_INT)) { - const char *exc = NULL; - static const char * const excnames[] = { - [EXCP_UDEF] = "Undefined Instruction", - [EXCP_SWI] = "SVC", - [EXCP_PREFETCH_ABORT] = "Prefetch Abort", - [EXCP_DATA_ABORT] = "Data Abort", - [EXCP_IRQ] = "IRQ", - [EXCP_FIQ] = "FIQ", - [EXCP_BKPT] = "Breakpoint", - [EXCP_EXCEPTION_EXIT] = "QEMU v7M exception exit", - [EXCP_KERNEL_TRAP] = "QEMU intercept of kernel commpage", - [EXCP_HVC] = "Hypervisor Call", - [EXCP_HYP_TRAP] = "Hypervisor Trap", - [EXCP_SMC] = "Secure Monitor Call", - [EXCP_VIRQ] = "Virtual IRQ", - [EXCP_VFIQ] = "Virtual FIQ", - [EXCP_SEMIHOST] = "Semihosting call", - [EXCP_NOCP] = "v7M NOCP UsageFault", - [EXCP_INVSTATE] = "v7M INVSTATE UsageFault", - [EXCP_STKOF] = "v8M STKOF UsageFault", - [EXCP_LAZYFP] = "v7M exception during lazy FP stacking", - [EXCP_LSERR] = "v8M LSERR UsageFault", - [EXCP_UNALIGNED] = "v7M UNALIGNED UsageFault", - }; - - if (idx >= 0 && idx < ARRAY_SIZE(excnames)) { - exc = excnames[idx]; - } - if (!exc) { - exc = "unknown"; - } - qemu_log_mask(CPU_LOG_INT, "Taking exception %d [%s]\n", idx, exc); - } -} - static bool v7m_read_half_insn(ARMCPU *cpu, ARMMMUIdx mmu_idx, uint32_t addr, uint16_t *insn) { - /* Load a 16-bit portion of a v7M instruction, returning true on success, + /* + * Load a 16-bit portion of a v7M instruction, returning true on success, * or false on failure (in which case we will have pended the appropriate * exception). * We need to do the instruction fetch's MPU and SAU checks @@ -9459,7 +9465,8 @@ static bool v7m_read_half_insn(ARMCPU *cpu, ARMMMUIdx mmu_idx, v8m_security_lookup(env, addr, MMU_INST_FETCH, mmu_idx, &sattrs); if (!sattrs.nsc || sattrs.ns) { - /* This must be the second half of the insn, and it straddles a + /* + * This must be the second half of the insn, and it straddles a * region boundary with the second half not being S&NSC. */ env->v7m.sfsr |= R_V7M_SFSR_INVEP_MASK; @@ -9489,7 +9496,8 @@ static bool v7m_read_half_insn(ARMCPU *cpu, ARMMMUIdx mmu_idx, static bool v7m_handle_execute_nsc(ARMCPU *cpu) { - /* Check whether this attempt to execute code in a Secure & NS-Callable + /* + * Check whether this attempt to execute code in a Secure & NS-Callable * memory region is for an SG instruction; if so, then emulate the * effect of the SG instruction and return true. Otherwise pend * the correct kind of exception and return false. @@ -9498,7 +9506,8 @@ static bool v7m_handle_execute_nsc(ARMCPU *cpu) ARMMMUIdx mmu_idx; uint16_t insn; - /* We should never get here unless get_phys_addr_pmsav8() caused + /* + * We should never get here unless get_phys_addr_pmsav8() caused * an exception for NS executing in S&NSC memory. */ assert(!env->v7m.secure); @@ -9516,7 +9525,8 @@ static bool v7m_handle_execute_nsc(ARMCPU *cpu) } if (insn != 0xe97f) { - /* Not an SG instruction first half (we choose the IMPDEF + /* + * Not an SG instruction first half (we choose the IMPDEF * early-SG-check option). */ goto gen_invep; @@ -9527,13 +9537,15 @@ static bool v7m_handle_execute_nsc(ARMCPU *cpu) } if (insn != 0xe97f) { - /* Not an SG instruction second half (yes, both halves of the SG + /* + * Not an SG instruction second half (yes, both halves of the SG * insn have the same hex value) */ goto gen_invep; } - /* OK, we have confirmed that we really have an SG instruction. + /* + * OK, we have confirmed that we really have an SG instruction. * We know we're NS in S memory so don't need to repeat those checks. */ qemu_log_mask(CPU_LOG_INT, "...really an SG instruction at 0x%08" PRIx32 @@ -9562,8 +9574,10 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs) arm_log_exception(cs->exception_index); - /* For exceptions we just mark as pending on the NVIC, and let that - handle it. */ + /* + * For exceptions we just mark as pending on the NVIC, and let that + * handle it. + */ switch (cs->exception_index) { case EXCP_UDEF: armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, env->v7m.secure); @@ -9609,13 +9623,15 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs) break; case EXCP_PREFETCH_ABORT: case EXCP_DATA_ABORT: - /* Note that for M profile we don't have a guest facing FSR, but + /* + * Note that for M profile we don't have a guest facing FSR, but * the env->exception.fsr will be populated by the code that * raises the fault, in the A profile short-descriptor format. */ switch (env->exception.fsr & 0xf) { case M_FAKE_FSR_NSC_EXEC: - /* Exception generated when we try to execute code at an address + /* + * Exception generated when we try to execute code at an address * which is marked as Secure & Non-Secure Callable and the CPU * is in the Non-Secure state. The only instruction which can * be executed like this is SG (and that only if both halves of @@ -9628,7 +9644,8 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs) } break; case M_FAKE_FSR_SFAULT: - /* Various flavours of SecureFault for attempts to execute or + /* + * Various flavours of SecureFault for attempts to execute or * access data in the wrong security state. */ switch (cs->exception_index) { @@ -9670,7 +9687,8 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs) armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_BUS, false); break; default: - /* All other FSR values are either MPU faults or "can't happen + /* + * All other FSR values are either MPU faults or "can't happen * for M profile" cases. */ switch (cs->exception_index) { @@ -9736,7 +9754,8 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs) if (arm_feature(env, ARM_FEATURE_V8)) { lr = R_V7M_EXCRET_RES1_MASK | R_V7M_EXCRET_DCRS_MASK; - /* The S bit indicates whether we should return to Secure + /* + * The S bit indicates whether we should return to Secure * or NonSecure (ie our current state). * The ES bit indicates whether we're taking this exception * to Secure or NonSecure (ie our target state). We set it @@ -9771,7 +9790,8 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs) v7m_exception_taken(cpu, lr, false, ignore_stackfaults); } -/* Function used to synchronize QEMU's AArch64 register set with AArch32 +/* + * Function used to synchronize QEMU's AArch64 register set with AArch32 * register set. This is necessary when switching between AArch32 and AArch64 * execution state. */ @@ -9785,7 +9805,8 @@ void aarch64_sync_32_to_64(CPUARMState *env) env->xregs[i] = env->regs[i]; } - /* Unless we are in FIQ mode, x8-x12 come from the user registers r8-r12. + /* + * Unless we are in FIQ mode, x8-x12 come from the user registers r8-r12. * Otherwise, they come from the banked user regs. */ if (mode == ARM_CPU_MODE_FIQ) { @@ -9798,7 +9819,8 @@ void aarch64_sync_32_to_64(CPUARMState *env) } } - /* Registers x13-x23 are the various mode SP and FP registers. Registers + /* + * Registers x13-x23 are the various mode SP and FP registers. Registers * r13 and r14 are only copied if we are in that mode, otherwise we copy * from the mode banked register. */ @@ -9853,7 +9875,8 @@ void aarch64_sync_32_to_64(CPUARMState *env) env->xregs[23] = env->banked_r13[bank_number(ARM_CPU_MODE_UND)]; } - /* Registers x24-x30 are mapped to r8-r14 in FIQ mode. If we are in FIQ + /* + * Registers x24-x30 are mapped to r8-r14 in FIQ mode. If we are in FIQ * mode, then we can copy from r8-r14. Otherwise, we copy from the * FIQ bank for r8-r14. */ @@ -9872,7 +9895,8 @@ void aarch64_sync_32_to_64(CPUARMState *env) env->pc = env->regs[15]; } -/* Function used to synchronize QEMU's AArch32 register set with AArch64 +/* + * Function used to synchronize QEMU's AArch32 register set with AArch64 * register set. This is necessary when switching between AArch32 and AArch64 * execution state. */ @@ -9886,7 +9910,8 @@ void aarch64_sync_64_to_32(CPUARMState *env) env->regs[i] = env->xregs[i]; } - /* Unless we are in FIQ mode, r8-r12 come from the user registers x8-x12. + /* + * Unless we are in FIQ mode, r8-r12 come from the user registers x8-x12. * Otherwise, we copy x8-x12 into the banked user regs. */ if (mode == ARM_CPU_MODE_FIQ) { @@ -9899,7 +9924,8 @@ void aarch64_sync_64_to_32(CPUARMState *env) } } - /* Registers r13 & r14 depend on the current mode. + /* + * Registers r13 & r14 depend on the current mode. * If we are in a given mode, we copy the corresponding x registers to r13 * and r14. Otherwise, we copy the x register to the banked r13 and r14 * for the mode. @@ -9910,7 +9936,8 @@ void aarch64_sync_64_to_32(CPUARMState *env) } else { env->banked_r13[bank_number(ARM_CPU_MODE_USR)] = env->xregs[13]; - /* HYP is an exception in that it does not have its own banked r14 but + /* + * HYP is an exception in that it does not have its own banked r14 but * shares the USR r14 */ if (mode == ARM_CPU_MODE_HYP) { @@ -12056,7 +12083,7 @@ static bool v8m_is_sau_exempt(CPUARMState *env, (address >= 0xe00ff000 && address <= 0xe00fffff); } -static void v8m_security_lookup(CPUARMState *env, uint32_t address, +void v8m_security_lookup(CPUARMState *env, uint32_t address, MMUAccessType access_type, ARMMMUIdx mmu_idx, V8M_SAttributes *sattrs) { @@ -12163,7 +12190,7 @@ static void v8m_security_lookup(CPUARMState *env, uint32_t address, } } -static bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, +bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, MMUAccessType access_type, ARMMMUIdx mmu_idx, hwaddr *phys_ptr, MemTxAttrs *txattrs, int *prot, bool *is_subpage, @@ -12567,11 +12594,11 @@ static ARMCacheAttrs combine_cacheattrs(ARMCacheAttrs s1, ARMCacheAttrs s2) * @fi: set to fault info if the translation fails * @cacheattrs: (if non-NULL) set to the cacheability/shareability attributes */ -static bool get_phys_addr(CPUARMState *env, target_ulong address, - MMUAccessType access_type, ARMMMUIdx mmu_idx, - hwaddr *phys_ptr, MemTxAttrs *attrs, int *prot, - target_ulong *page_size, - ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs) +bool get_phys_addr(CPUARMState *env, target_ulong address, + MMUAccessType access_type, ARMMMUIdx mmu_idx, + hwaddr *phys_ptr, MemTxAttrs *attrs, int *prot, + target_ulong *page_size, + ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs) { if (mmu_idx == ARMMMUIdx_S12NSE0 || mmu_idx == ARMMMUIdx_S12NSE1) { /* Call ourselves recursively to do the stage 1 and then stage 2 @@ -12753,7 +12780,8 @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg) return value; } case 0x94: /* CONTROL_NS */ - /* We have to handle this here because unprivileged Secure code + /* + * We have to handle this here because unprivileged Secure code * can read the NS CONTROL register. */ if (!env->v7m.secure) { @@ -12806,7 +12834,8 @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg) return env->v7m.faultmask[M_REG_NS]; case 0x98: /* SP_NS */ { - /* This gives the non-secure SP selected based on whether we're + /* + * This gives the non-secure SP selected based on whether we're * currently in handler mode or not, using the NS CONTROL.SPSEL. */ bool spsel = env->v7m.control[M_REG_NS] & R_V7M_CONTROL_SPSEL_MASK; @@ -12857,7 +12886,8 @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg) void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val) { - /* We're passed bits [11..0] of the instruction; extract + /* + * We're passed bits [11..0] of the instruction; extract * SYSm and the mask bits. * Invalid combinations of SYSm and mask are UNPREDICTABLE; * we choose to treat them as if the mask bits were valid. @@ -12943,7 +12973,8 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val) return; case 0x98: /* SP_NS */ { - /* This gives the non-secure SP selected based on whether we're + /* + * This gives the non-secure SP selected based on whether we're * currently in handler mode or not, using the NS CONTROL.SPSEL. */ bool spsel = env->v7m.control[M_REG_NS] & R_V7M_CONTROL_SPSEL_MASK; @@ -13104,7 +13135,8 @@ uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op) bool targetsec = env->v7m.secure; bool is_subpage; - /* Work out what the security state and privilege level we're + /* + * Work out what the security state and privilege level we're * interested in is... */ if (alt) { @@ -13121,12 +13153,14 @@ uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op) /* ...and then figure out which MMU index this is */ mmu_idx = arm_v7m_mmu_idx_for_secstate_and_priv(env, targetsec, targetpriv); - /* We know that the MPU and SAU don't care about the access type + /* + * We know that the MPU and SAU don't care about the access type * for our purposes beyond that we don't want to claim to be * an insn fetch, so we arbitrarily call this a read. */ - /* MPU region info only available for privileged or if + /* + * MPU region info only available for privileged or if * inspecting the other MPU state. */ if (arm_current_el(env) != 0 || alt) { @@ -13176,146 +13210,6 @@ uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op) #endif -bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size, - MMUAccessType access_type, int mmu_idx, - bool probe, uintptr_t retaddr) -{ - ARMCPU *cpu = ARM_CPU(cs); - -#ifdef CONFIG_USER_ONLY - cpu->env.exception.vaddress = address; - if (access_type == MMU_INST_FETCH) { - cs->exception_index = EXCP_PREFETCH_ABORT; - } else { - cs->exception_index = EXCP_DATA_ABORT; - } - cpu_loop_exit_restore(cs, retaddr); -#else - hwaddr phys_addr; - target_ulong page_size; - int prot, ret; - MemTxAttrs attrs = {}; - ARMMMUFaultInfo fi = {}; - - /* - * Walk the page table and (if the mapping exists) add the page - * to the TLB. On success, return true. Otherwise, if probing, - * return false. Otherwise populate fsr with ARM DFSR/IFSR fault - * register format, and signal the fault. - */ - ret = get_phys_addr(&cpu->env, address, access_type, - core_to_arm_mmu_idx(&cpu->env, mmu_idx), - &phys_addr, &attrs, &prot, &page_size, &fi, NULL); - if (likely(!ret)) { - /* - * Map a single [sub]page. Regions smaller than our declared - * target page size are handled specially, so for those we - * pass in the exact addresses. - */ - if (page_size >= TARGET_PAGE_SIZE) { - phys_addr &= TARGET_PAGE_MASK; - address &= TARGET_PAGE_MASK; - } - tlb_set_page_with_attrs(cs, address, phys_addr, attrs, - prot, mmu_idx, page_size); - return true; - } else if (probe) { - return false; - } else { - /* now we have a real cpu fault */ - cpu_restore_state(cs, retaddr, true); - arm_deliver_fault(cpu, address, access_type, mmu_idx, &fi); - } -#endif -} - -void HELPER(dc_zva)(CPUARMState *env, uint64_t vaddr_in) -{ - /* Implement DC ZVA, which zeroes a fixed-length block of memory. - * Note that we do not implement the (architecturally mandated) - * alignment fault for attempts to use this on Device memory - * (which matches the usual QEMU behaviour of not implementing either - * alignment faults or any memory attribute handling). - */ - - ARMCPU *cpu = env_archcpu(env); - uint64_t blocklen = 4 << cpu->dcz_blocksize; - uint64_t vaddr = vaddr_in & ~(blocklen - 1); - -#ifndef CONFIG_USER_ONLY - { - /* Slightly awkwardly, QEMU's TARGET_PAGE_SIZE may be less than - * the block size so we might have to do more than one TLB lookup. - * We know that in fact for any v8 CPU the page size is at least 4K - * and the block size must be 2K or less, but TARGET_PAGE_SIZE is only - * 1K as an artefact of legacy v5 subpage support being present in the - * same QEMU executable. So in practice the hostaddr[] array has - * two entries, given the current setting of TARGET_PAGE_BITS_MIN. - */ - int maxidx = DIV_ROUND_UP(blocklen, TARGET_PAGE_SIZE); - void *hostaddr[DIV_ROUND_UP(2 * KiB, 1 << TARGET_PAGE_BITS_MIN)]; - int try, i; - unsigned mmu_idx = cpu_mmu_index(env, false); - TCGMemOpIdx oi = make_memop_idx(MO_UB, mmu_idx); - - assert(maxidx <= ARRAY_SIZE(hostaddr)); - - for (try = 0; try < 2; try++) { - - for (i = 0; i < maxidx; i++) { - hostaddr[i] = tlb_vaddr_to_host(env, - vaddr + TARGET_PAGE_SIZE * i, - 1, mmu_idx); - if (!hostaddr[i]) { - break; - } - } - if (i == maxidx) { - /* If it's all in the TLB it's fair game for just writing to; - * we know we don't need to update dirty status, etc. - */ - for (i = 0; i < maxidx - 1; i++) { - memset(hostaddr[i], 0, TARGET_PAGE_SIZE); - } - memset(hostaddr[i], 0, blocklen - (i * TARGET_PAGE_SIZE)); - return; - } - /* OK, try a store and see if we can populate the tlb. This - * might cause an exception if the memory isn't writable, - * in which case we will longjmp out of here. We must for - * this purpose use the actual register value passed to us - * so that we get the fault address right. - */ - helper_ret_stb_mmu(env, vaddr_in, 0, oi, GETPC()); - /* Now we can populate the other TLB entries, if any */ - for (i = 0; i < maxidx; i++) { - uint64_t va = vaddr + TARGET_PAGE_SIZE * i; - if (va != (vaddr_in & TARGET_PAGE_MASK)) { - helper_ret_stb_mmu(env, va, 0, oi, GETPC()); - } - } - } - - /* Slow path (probably attempt to do this to an I/O device or - * similar, or clearing of a block of code we have translations - * cached for). Just do a series of byte writes as the architecture - * demands. It's not worth trying to use a cpu_physical_memory_map(), - * memset(), unmap() sequence here because: - * + we'd need to account for the blocksize being larger than a page - * + the direct-RAM access case is almost always going to be dealt - * with in the fastpath code above, so there's no speed benefit - * + we would have to deal with the map returning NULL because the - * bounce buffer was in use - */ - for (i = 0; i < blocklen; i++) { - helper_ret_stb_mmu(env, vaddr + i, 0, oi, GETPC()); - } - } -#else - memset(g2h(vaddr), 0, blocklen); -#endif -} - /* Note that signed overflow is undefined in C. The following routines are careful to use unsigned types where modulo arithmetic is required. Failure to do so _will_ break on newer gcc. */ diff --git a/target/arm/internals.h b/target/arm/internals.h index 5a02f458f3..232d963875 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -529,11 +529,15 @@ vaddr arm_adjust_watchpoint_address(CPUState *cs, vaddr addr, int len); /* Callback function for when a watchpoint or breakpoint triggers. */ void arm_debug_excp_handler(CPUState *cs); -#ifdef CONFIG_USER_ONLY +#if defined(CONFIG_USER_ONLY) || !defined(CONFIG_TCG) static inline bool arm_is_psci_call(ARMCPU *cpu, int excp_type) { return false; } +static inline void arm_handle_psci_call(ARMCPU *cpu) +{ + g_assert_not_reached(); +} #else /* Return true if the r0/x0 value indicates that this SMC/HVC is a PSCI call. */ bool arm_is_psci_call(ARMCPU *cpu, int excp_type); @@ -765,9 +769,6 @@ bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size, MMUAccessType access_type, int mmu_idx, bool probe, uintptr_t retaddr); -void arm_deliver_fault(ARMCPU *cpu, vaddr addr, MMUAccessType access_type, - int mmu_idx, ARMMMUFaultInfo *fi) QEMU_NORETURN; - /* Return true if the stage 1 translation regime is using LPAE format page * tables */ bool arm_s1_regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx); @@ -892,6 +893,27 @@ static inline uint32_t v7m_sp_limit(CPUARMState *env) } /** + * v7m_cpacr_pass: + * Return true if the v7M CPACR permits access to the FPU for the specified + * security state and privilege level. + */ +static inline bool v7m_cpacr_pass(CPUARMState *env, + bool is_secure, bool is_priv) +{ + switch (extract32(env->v7m.cpacr[is_secure], 20, 2)) { + case 0: + case 2: /* UNPREDICTABLE: we treat like 0 */ + return false; + case 1: + return is_priv; + case 3: + return true; + default: + g_assert_not_reached(); + } +} + +/** * aarch32_mode_name(): Return name of the AArch32 CPU mode * @psr: Program Status Register indicating CPU mode * @@ -985,4 +1007,43 @@ static inline int exception_target_el(CPUARMState *env) return target_el; } +#ifndef CONFIG_USER_ONLY + +/* Security attributes for an address, as returned by v8m_security_lookup. */ +typedef struct V8M_SAttributes { + bool subpage; /* true if these attrs don't cover the whole TARGET_PAGE */ + bool ns; + bool nsc; + uint8_t sregion; + bool srvalid; + uint8_t iregion; + bool irvalid; +} V8M_SAttributes; + +void v8m_security_lookup(CPUARMState *env, uint32_t address, + MMUAccessType access_type, ARMMMUIdx mmu_idx, + V8M_SAttributes *sattrs); + +bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, + MMUAccessType access_type, ARMMMUIdx mmu_idx, + hwaddr *phys_ptr, MemTxAttrs *txattrs, + int *prot, bool *is_subpage, + ARMMMUFaultInfo *fi, uint32_t *mregion); + +/* Cacheability and shareability attributes for a memory access */ +typedef struct ARMCacheAttrs { + unsigned int attrs:8; /* as in the MAIR register encoding */ + unsigned int shareability:2; /* as in the SH field of the VMSAv8-64 PTEs */ +} ARMCacheAttrs; + +bool get_phys_addr(CPUARMState *env, target_ulong address, + MMUAccessType access_type, ARMMMUIdx mmu_idx, + hwaddr *phys_ptr, MemTxAttrs *attrs, int *prot, + target_ulong *page_size, + ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs); + +void arm_log_exception(int idx); + +#endif /* !CONFIG_USER_ONLY */ + #endif diff --git a/target/arm/monitor.c b/target/arm/monitor.c index 41b32b94b2..6ec6dd04ac 100644 --- a/target/arm/monitor.c +++ b/target/arm/monitor.c @@ -23,7 +23,7 @@ #include "qemu/osdep.h" #include "hw/boards.h" #include "kvm_arm.h" -#include "qapi/qapi-commands-target.h" +#include "qapi/qapi-commands-misc-target.h" static GICCapability *gic_cap_new(int version) { diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c index 4db254876d..9850993c11 100644 --- a/target/arm/op_helper.c +++ b/target/arm/op_helper.c @@ -17,6 +17,7 @@ * License along with this library; if not, see <http://www.gnu.org/licenses/>. */ #include "qemu/osdep.h" +#include "qemu/units.h" #include "qemu/log.h" #include "qemu/main-loop.h" #include "cpu.h" @@ -87,136 +88,6 @@ uint32_t HELPER(neon_tbl)(uint32_t ireg, uint32_t def, void *vn, return val; } -#if !defined(CONFIG_USER_ONLY) - -static inline uint32_t merge_syn_data_abort(uint32_t template_syn, - unsigned int target_el, - bool same_el, bool ea, - bool s1ptw, bool is_write, - int fsc) -{ - uint32_t syn; - - /* ISV is only set for data aborts routed to EL2 and - * never for stage-1 page table walks faulting on stage 2. - * - * Furthermore, ISV is only set for certain kinds of load/stores. - * If the template syndrome does not have ISV set, we should leave - * it cleared. - * - * See ARMv8 specs, D7-1974: - * ISS encoding for an exception from a Data Abort, the - * ISV field. - */ - if (!(template_syn & ARM_EL_ISV) || target_el != 2 || s1ptw) { - syn = syn_data_abort_no_iss(same_el, - ea, 0, s1ptw, is_write, fsc); - } else { - /* Fields: IL, ISV, SAS, SSE, SRT, SF and AR come from the template - * syndrome created at translation time. - * Now we create the runtime syndrome with the remaining fields. - */ - syn = syn_data_abort_with_iss(same_el, - 0, 0, 0, 0, 0, - ea, 0, s1ptw, is_write, fsc, - false); - /* Merge the runtime syndrome with the template syndrome. */ - syn |= template_syn; - } - return syn; -} - -void arm_deliver_fault(ARMCPU *cpu, vaddr addr, MMUAccessType access_type, - int mmu_idx, ARMMMUFaultInfo *fi) -{ - CPUARMState *env = &cpu->env; - int target_el; - bool same_el; - uint32_t syn, exc, fsr, fsc; - ARMMMUIdx arm_mmu_idx = core_to_arm_mmu_idx(env, mmu_idx); - - target_el = exception_target_el(env); - if (fi->stage2) { - target_el = 2; - env->cp15.hpfar_el2 = extract64(fi->s2addr, 12, 47) << 4; - } - same_el = (arm_current_el(env) == target_el); - - if (target_el == 2 || arm_el_is_aa64(env, target_el) || - arm_s1_regime_using_lpae_format(env, arm_mmu_idx)) { - /* LPAE format fault status register : bottom 6 bits are - * status code in the same form as needed for syndrome - */ - fsr = arm_fi_to_lfsc(fi); - fsc = extract32(fsr, 0, 6); - } else { - fsr = arm_fi_to_sfsc(fi); - /* Short format FSR : this fault will never actually be reported - * to an EL that uses a syndrome register. Use a (currently) - * reserved FSR code in case the constructed syndrome does leak - * into the guest somehow. - */ - fsc = 0x3f; - } - - if (access_type == MMU_INST_FETCH) { - syn = syn_insn_abort(same_el, fi->ea, fi->s1ptw, fsc); - exc = EXCP_PREFETCH_ABORT; - } else { - syn = merge_syn_data_abort(env->exception.syndrome, target_el, - same_el, fi->ea, fi->s1ptw, - access_type == MMU_DATA_STORE, - fsc); - if (access_type == MMU_DATA_STORE - && arm_feature(env, ARM_FEATURE_V6)) { - fsr |= (1 << 11); - } - exc = EXCP_DATA_ABORT; - } - - env->exception.vaddress = addr; - env->exception.fsr = fsr; - raise_exception(env, exc, syn, target_el); -} - -/* Raise a data fault alignment exception for the specified virtual address */ -void arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr, - MMUAccessType access_type, - int mmu_idx, uintptr_t retaddr) -{ - ARMCPU *cpu = ARM_CPU(cs); - ARMMMUFaultInfo fi = {}; - - /* now we have a real cpu fault */ - cpu_restore_state(cs, retaddr, true); - - fi.type = ARMFault_Alignment; - arm_deliver_fault(cpu, vaddr, access_type, mmu_idx, &fi); -} - -/* arm_cpu_do_transaction_failed: handle a memory system error response - * (eg "no device/memory present at address") by raising an external abort - * exception - */ -void arm_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, - vaddr addr, unsigned size, - MMUAccessType access_type, - int mmu_idx, MemTxAttrs attrs, - MemTxResult response, uintptr_t retaddr) -{ - ARMCPU *cpu = ARM_CPU(cs); - ARMMMUFaultInfo fi = {}; - - /* now we have a real cpu fault */ - cpu_restore_state(cs, retaddr, true); - - fi.ea = arm_extabort_type(response); - fi.type = ARMFault_SyncExternal; - arm_deliver_fault(cpu, addr, access_type, mmu_idx, &fi); -} - -#endif /* !defined(CONFIG_USER_ONLY) */ - void HELPER(v8m_stackcheck)(CPUARMState *env, uint32_t newvalue) { /* @@ -970,7 +841,8 @@ static bool linked_bp_matches(ARMCPU *cpu, int lbn) int bt; uint32_t contextidr; - /* Links to unimplemented or non-context aware breakpoints are + /* + * Links to unimplemented or non-context aware breakpoints are * CONSTRAINED UNPREDICTABLE: either behave as if disabled, or * as if linked to an UNKNOWN context-aware breakpoint (in which * case DBGWCR<n>_EL1.LBN must indicate that breakpoint). @@ -989,7 +861,8 @@ static bool linked_bp_matches(ARMCPU *cpu, int lbn) bt = extract64(bcr, 20, 4); - /* We match the whole register even if this is AArch32 using the + /* + * We match the whole register even if this is AArch32 using the * short descriptor format (in which case it holds both PROCID and ASID), * since we don't implement the optional v7 context ID masking. */ @@ -1006,7 +879,8 @@ static bool linked_bp_matches(ARMCPU *cpu, int lbn) case 9: /* linked VMID match (reserved if no EL2) */ case 11: /* linked context ID and VMID match (reserved if no EL2) */ default: - /* Links to Unlinked context breakpoints must generate no + /* + * Links to Unlinked context breakpoints must generate no * events; we choose to do the same for reserved values too. */ return false; @@ -1020,7 +894,8 @@ static bool bp_wp_matches(ARMCPU *cpu, int n, bool is_wp) CPUARMState *env = &cpu->env; uint64_t cr; int pac, hmc, ssc, wt, lbn; - /* Note that for watchpoints the check is against the CPU security + /* + * Note that for watchpoints the check is against the CPU security * state, not the S/NS attribute on the offending data access. */ bool is_secure = arm_is_secure(env); @@ -1034,7 +909,8 @@ static bool bp_wp_matches(ARMCPU *cpu, int n, bool is_wp) } cr = env->cp15.dbgwcr[n]; if (wp->hitattrs.user) { - /* The LDRT/STRT/LDT/STT "unprivileged access" instructions should + /* + * The LDRT/STRT/LDT/STT "unprivileged access" instructions should * match watchpoints as if they were accesses done at EL0, even if * the CPU is at EL1 or higher. */ @@ -1048,7 +924,8 @@ static bool bp_wp_matches(ARMCPU *cpu, int n, bool is_wp) } cr = env->cp15.dbgbcr[n]; } - /* The WATCHPOINT_HIT flag guarantees us that the watchpoint is + /* + * The WATCHPOINT_HIT flag guarantees us that the watchpoint is * enabled and that the address and access type match; for breakpoints * we know the address matched; check the remaining fields, including * linked breakpoints. We rely on WCR and BCR having the same layout @@ -1116,7 +993,8 @@ static bool check_watchpoints(ARMCPU *cpu) CPUARMState *env = &cpu->env; int n; - /* If watchpoints are disabled globally or we can't take debug + /* + * If watchpoints are disabled globally or we can't take debug * exceptions here then watchpoint firings are ignored. */ if (extract32(env->cp15.mdscr_el1, 15, 1) == 0 @@ -1137,7 +1015,8 @@ static bool check_breakpoints(ARMCPU *cpu) CPUARMState *env = &cpu->env; int n; - /* If breakpoints are disabled globally or we can't take debug + /* + * If breakpoints are disabled globally or we can't take debug * exceptions here then breakpoint firings are ignored. */ if (extract32(env->cp15.mdscr_el1, 15, 1) == 0 @@ -1164,7 +1043,8 @@ void HELPER(check_breakpoints)(CPUARMState *env) bool arm_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp) { - /* Called by core code when a CPU watchpoint fires; need to check if this + /* + * Called by core code when a CPU watchpoint fires; need to check if this * is also an architectural watchpoint match. */ ARMCPU *cpu = ARM_CPU(cs); @@ -1177,7 +1057,8 @@ vaddr arm_adjust_watchpoint_address(CPUState *cs, vaddr addr, int len) ARMCPU *cpu = ARM_CPU(cs); CPUARMState *env = &cpu->env; - /* In BE32 system mode, target memory is stored byteswapped (on a + /* + * In BE32 system mode, target memory is stored byteswapped (on a * little-endian host system), and by the time we reach here (via an * opcode helper) the addresses of subword accesses have been adjusted * to account for that, which means that watchpoints will not match. @@ -1196,7 +1077,8 @@ vaddr arm_adjust_watchpoint_address(CPUState *cs, vaddr addr, int len) void arm_debug_excp_handler(CPUState *cs) { - /* Called by core code when a watchpoint or breakpoint fires; + /* + * Called by core code when a watchpoint or breakpoint fires; * need to check which one and raise the appropriate exception. */ ARMCPU *cpu = ARM_CPU(cs); @@ -1220,7 +1102,8 @@ void arm_debug_excp_handler(CPUState *cs) uint64_t pc = is_a64(env) ? env->pc : env->regs[15]; bool same_el = (arm_debug_target_el(env) == arm_current_el(env)); - /* (1) GDB breakpoints should be handled first. + /* + * (1) GDB breakpoints should be handled first. * (2) Do not raise a CPU exception if no CPU breakpoint has fired, * since singlestep is also done by generating a debug internal * exception. @@ -1231,7 +1114,8 @@ void arm_debug_excp_handler(CPUState *cs) } env->exception.fsr = arm_debug_exception_fsr(env); - /* FAR is UNKNOWN: clear vaddress to avoid potentially exposing + /* + * FAR is UNKNOWN: clear vaddress to avoid potentially exposing * values to the guest that it shouldn't be able to see at its * exception/security level. */ @@ -1307,3 +1191,95 @@ uint32_t HELPER(ror_cc)(CPUARMState *env, uint32_t x, uint32_t i) return ((uint32_t)x >> shift) | (x << (32 - shift)); } } + +void HELPER(dc_zva)(CPUARMState *env, uint64_t vaddr_in) +{ + /* + * Implement DC ZVA, which zeroes a fixed-length block of memory. + * Note that we do not implement the (architecturally mandated) + * alignment fault for attempts to use this on Device memory + * (which matches the usual QEMU behaviour of not implementing either + * alignment faults or any memory attribute handling). + */ + + ARMCPU *cpu = env_archcpu(env); + uint64_t blocklen = 4 << cpu->dcz_blocksize; + uint64_t vaddr = vaddr_in & ~(blocklen - 1); + +#ifndef CONFIG_USER_ONLY + { + /* + * Slightly awkwardly, QEMU's TARGET_PAGE_SIZE may be less than + * the block size so we might have to do more than one TLB lookup. + * We know that in fact for any v8 CPU the page size is at least 4K + * and the block size must be 2K or less, but TARGET_PAGE_SIZE is only + * 1K as an artefact of legacy v5 subpage support being present in the + * same QEMU executable. So in practice the hostaddr[] array has + * two entries, given the current setting of TARGET_PAGE_BITS_MIN. + */ + int maxidx = DIV_ROUND_UP(blocklen, TARGET_PAGE_SIZE); + void *hostaddr[DIV_ROUND_UP(2 * KiB, 1 << TARGET_PAGE_BITS_MIN)]; + int try, i; + unsigned mmu_idx = cpu_mmu_index(env, false); + TCGMemOpIdx oi = make_memop_idx(MO_UB, mmu_idx); + + assert(maxidx <= ARRAY_SIZE(hostaddr)); + + for (try = 0; try < 2; try++) { + + for (i = 0; i < maxidx; i++) { + hostaddr[i] = tlb_vaddr_to_host(env, + vaddr + TARGET_PAGE_SIZE * i, + 1, mmu_idx); + if (!hostaddr[i]) { + break; + } + } + if (i == maxidx) { + /* + * If it's all in the TLB it's fair game for just writing to; + * we know we don't need to update dirty status, etc. + */ + for (i = 0; i < maxidx - 1; i++) { + memset(hostaddr[i], 0, TARGET_PAGE_SIZE); + } + memset(hostaddr[i], 0, blocklen - (i * TARGET_PAGE_SIZE)); + return; + } + /* + * OK, try a store and see if we can populate the tlb. This + * might cause an exception if the memory isn't writable, + * in which case we will longjmp out of here. We must for + * this purpose use the actual register value passed to us + * so that we get the fault address right. + */ + helper_ret_stb_mmu(env, vaddr_in, 0, oi, GETPC()); + /* Now we can populate the other TLB entries, if any */ + for (i = 0; i < maxidx; i++) { + uint64_t va = vaddr + TARGET_PAGE_SIZE * i; + if (va != (vaddr_in & TARGET_PAGE_MASK)) { + helper_ret_stb_mmu(env, va, 0, oi, GETPC()); + } + } + } + + /* + * Slow path (probably attempt to do this to an I/O device or + * similar, or clearing of a block of code we have translations + * cached for). Just do a series of byte writes as the architecture + * demands. It's not worth trying to use a cpu_physical_memory_map(), + * memset(), unmap() sequence here because: + * + we'd need to account for the blocksize being larger than a page + * + the direct-RAM access case is almost always going to be dealt + * with in the fastpath code above, so there's no speed benefit + * + we would have to deal with the map returning NULL because the + * bounce buffer was in use + */ + for (i = 0; i < blocklen; i++) { + helper_ret_stb_mmu(env, vaddr + i, 0, oi, GETPC()); + } + } +#else + memset(g2h(vaddr), 0, blocklen); +#endif +} diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c new file mode 100644 index 0000000000..5feb312941 --- /dev/null +++ b/target/arm/tlb_helper.c @@ -0,0 +1,200 @@ +/* + * ARM TLB (Translation lookaside buffer) helpers. + * + * This code is licensed under the GNU GPL v2 or later. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#include "qemu/osdep.h" +#include "cpu.h" +#include "internals.h" +#include "exec/exec-all.h" + +#if !defined(CONFIG_USER_ONLY) + +static inline uint32_t merge_syn_data_abort(uint32_t template_syn, + unsigned int target_el, + bool same_el, bool ea, + bool s1ptw, bool is_write, + int fsc) +{ + uint32_t syn; + + /* + * ISV is only set for data aborts routed to EL2 and + * never for stage-1 page table walks faulting on stage 2. + * + * Furthermore, ISV is only set for certain kinds of load/stores. + * If the template syndrome does not have ISV set, we should leave + * it cleared. + * + * See ARMv8 specs, D7-1974: + * ISS encoding for an exception from a Data Abort, the + * ISV field. + */ + if (!(template_syn & ARM_EL_ISV) || target_el != 2 || s1ptw) { + syn = syn_data_abort_no_iss(same_el, + ea, 0, s1ptw, is_write, fsc); + } else { + /* + * Fields: IL, ISV, SAS, SSE, SRT, SF and AR come from the template + * syndrome created at translation time. + * Now we create the runtime syndrome with the remaining fields. + */ + syn = syn_data_abort_with_iss(same_el, + 0, 0, 0, 0, 0, + ea, 0, s1ptw, is_write, fsc, + false); + /* Merge the runtime syndrome with the template syndrome. */ + syn |= template_syn; + } + return syn; +} + +static void QEMU_NORETURN arm_deliver_fault(ARMCPU *cpu, vaddr addr, + MMUAccessType access_type, + int mmu_idx, ARMMMUFaultInfo *fi) +{ + CPUARMState *env = &cpu->env; + int target_el; + bool same_el; + uint32_t syn, exc, fsr, fsc; + ARMMMUIdx arm_mmu_idx = core_to_arm_mmu_idx(env, mmu_idx); + + target_el = exception_target_el(env); + if (fi->stage2) { + target_el = 2; + env->cp15.hpfar_el2 = extract64(fi->s2addr, 12, 47) << 4; + } + same_el = (arm_current_el(env) == target_el); + + if (target_el == 2 || arm_el_is_aa64(env, target_el) || + arm_s1_regime_using_lpae_format(env, arm_mmu_idx)) { + /* + * LPAE format fault status register : bottom 6 bits are + * status code in the same form as needed for syndrome + */ + fsr = arm_fi_to_lfsc(fi); + fsc = extract32(fsr, 0, 6); + } else { + fsr = arm_fi_to_sfsc(fi); + /* + * Short format FSR : this fault will never actually be reported + * to an EL that uses a syndrome register. Use a (currently) + * reserved FSR code in case the constructed syndrome does leak + * into the guest somehow. + */ + fsc = 0x3f; + } + + if (access_type == MMU_INST_FETCH) { + syn = syn_insn_abort(same_el, fi->ea, fi->s1ptw, fsc); + exc = EXCP_PREFETCH_ABORT; + } else { + syn = merge_syn_data_abort(env->exception.syndrome, target_el, + same_el, fi->ea, fi->s1ptw, + access_type == MMU_DATA_STORE, + fsc); + if (access_type == MMU_DATA_STORE + && arm_feature(env, ARM_FEATURE_V6)) { + fsr |= (1 << 11); + } + exc = EXCP_DATA_ABORT; + } + + env->exception.vaddress = addr; + env->exception.fsr = fsr; + raise_exception(env, exc, syn, target_el); +} + +/* Raise a data fault alignment exception for the specified virtual address */ +void arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr, + MMUAccessType access_type, + int mmu_idx, uintptr_t retaddr) +{ + ARMCPU *cpu = ARM_CPU(cs); + ARMMMUFaultInfo fi = {}; + + /* now we have a real cpu fault */ + cpu_restore_state(cs, retaddr, true); + + fi.type = ARMFault_Alignment; + arm_deliver_fault(cpu, vaddr, access_type, mmu_idx, &fi); +} + +/* + * arm_cpu_do_transaction_failed: handle a memory system error response + * (eg "no device/memory present at address") by raising an external abort + * exception + */ +void arm_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, + vaddr addr, unsigned size, + MMUAccessType access_type, + int mmu_idx, MemTxAttrs attrs, + MemTxResult response, uintptr_t retaddr) +{ + ARMCPU *cpu = ARM_CPU(cs); + ARMMMUFaultInfo fi = {}; + + /* now we have a real cpu fault */ + cpu_restore_state(cs, retaddr, true); + + fi.ea = arm_extabort_type(response); + fi.type = ARMFault_SyncExternal; + arm_deliver_fault(cpu, addr, access_type, mmu_idx, &fi); +} + +#endif /* !defined(CONFIG_USER_ONLY) */ + +bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) +{ + ARMCPU *cpu = ARM_CPU(cs); + +#ifdef CONFIG_USER_ONLY + cpu->env.exception.vaddress = address; + if (access_type == MMU_INST_FETCH) { + cs->exception_index = EXCP_PREFETCH_ABORT; + } else { + cs->exception_index = EXCP_DATA_ABORT; + } + cpu_loop_exit_restore(cs, retaddr); +#else + hwaddr phys_addr; + target_ulong page_size; + int prot, ret; + MemTxAttrs attrs = {}; + ARMMMUFaultInfo fi = {}; + + /* + * Walk the page table and (if the mapping exists) add the page + * to the TLB. On success, return true. Otherwise, if probing, + * return false. Otherwise populate fsr with ARM DFSR/IFSR fault + * register format, and signal the fault. + */ + ret = get_phys_addr(&cpu->env, address, access_type, + core_to_arm_mmu_idx(&cpu->env, mmu_idx), + &phys_addr, &attrs, &prot, &page_size, &fi, NULL); + if (likely(!ret)) { + /* + * Map a single [sub]page. Regions smaller than our declared + * target page size are handled specially, so for those we + * pass in the exact addresses. + */ + if (page_size >= TARGET_PAGE_SIZE) { + phys_addr &= TARGET_PAGE_MASK; + address &= TARGET_PAGE_MASK; + } + tlb_set_page_with_attrs(cs, address, phys_addr, attrs, + prot, mmu_idx, page_size); + return true; + } else if (probe) { + return false; + } else { + /* now we have a real cpu fault */ + cpu_restore_state(cs, retaddr, true); + arm_deliver_fault(cpu, address, access_type, mmu_idx, &fi); + } +#endif +} diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 97f4164fbb..d3231477a2 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -27,7 +27,6 @@ #include "translate.h" #include "internals.h" #include "qemu/host-utils.h" -#include "qemu/qemu-print.h" #include "hw/semihosting/semihost.h" #include "exec/gen-icount.h" @@ -152,133 +151,6 @@ static void set_btype(DisasContext *s, int val) s->btype = -1; } -void aarch64_cpu_dump_state(CPUState *cs, FILE *f, int flags) -{ - ARMCPU *cpu = ARM_CPU(cs); - CPUARMState *env = &cpu->env; - uint32_t psr = pstate_read(env); - int i; - int el = arm_current_el(env); - const char *ns_status; - - qemu_fprintf(f, " PC=%016" PRIx64 " ", env->pc); - for (i = 0; i < 32; i++) { - if (i == 31) { - qemu_fprintf(f, " SP=%016" PRIx64 "\n", env->xregs[i]); - } else { - qemu_fprintf(f, "X%02d=%016" PRIx64 "%s", i, env->xregs[i], - (i + 2) % 3 ? " " : "\n"); - } - } - - if (arm_feature(env, ARM_FEATURE_EL3) && el != 3) { - ns_status = env->cp15.scr_el3 & SCR_NS ? "NS " : "S "; - } else { - ns_status = ""; - } - qemu_fprintf(f, "PSTATE=%08x %c%c%c%c %sEL%d%c", - psr, - psr & PSTATE_N ? 'N' : '-', - psr & PSTATE_Z ? 'Z' : '-', - psr & PSTATE_C ? 'C' : '-', - psr & PSTATE_V ? 'V' : '-', - ns_status, - el, - psr & PSTATE_SP ? 'h' : 't'); - - if (cpu_isar_feature(aa64_bti, cpu)) { - qemu_fprintf(f, " BTYPE=%d", (psr & PSTATE_BTYPE) >> 10); - } - if (!(flags & CPU_DUMP_FPU)) { - qemu_fprintf(f, "\n"); - return; - } - if (fp_exception_el(env, el) != 0) { - qemu_fprintf(f, " FPU disabled\n"); - return; - } - qemu_fprintf(f, " FPCR=%08x FPSR=%08x\n", - vfp_get_fpcr(env), vfp_get_fpsr(env)); - - if (cpu_isar_feature(aa64_sve, cpu) && sve_exception_el(env, el) == 0) { - int j, zcr_len = sve_zcr_len_for_el(env, el); - - for (i = 0; i <= FFR_PRED_NUM; i++) { - bool eol; - if (i == FFR_PRED_NUM) { - qemu_fprintf(f, "FFR="); - /* It's last, so end the line. */ - eol = true; - } else { - qemu_fprintf(f, "P%02d=", i); - switch (zcr_len) { - case 0: - eol = i % 8 == 7; - break; - case 1: - eol = i % 6 == 5; - break; - case 2: - case 3: - eol = i % 3 == 2; - break; - default: - /* More than one quadword per predicate. */ - eol = true; - break; - } - } - for (j = zcr_len / 4; j >= 0; j--) { - int digits; - if (j * 4 + 4 <= zcr_len + 1) { - digits = 16; - } else { - digits = (zcr_len % 4 + 1) * 4; - } - qemu_fprintf(f, "%0*" PRIx64 "%s", digits, - env->vfp.pregs[i].p[j], - j ? ":" : eol ? "\n" : " "); - } - } - - for (i = 0; i < 32; i++) { - if (zcr_len == 0) { - qemu_fprintf(f, "Z%02d=%016" PRIx64 ":%016" PRIx64 "%s", - i, env->vfp.zregs[i].d[1], - env->vfp.zregs[i].d[0], i & 1 ? "\n" : " "); - } else if (zcr_len == 1) { - qemu_fprintf(f, "Z%02d=%016" PRIx64 ":%016" PRIx64 - ":%016" PRIx64 ":%016" PRIx64 "\n", - i, env->vfp.zregs[i].d[3], env->vfp.zregs[i].d[2], - env->vfp.zregs[i].d[1], env->vfp.zregs[i].d[0]); - } else { - for (j = zcr_len; j >= 0; j--) { - bool odd = (zcr_len - j) % 2 != 0; - if (j == zcr_len) { - qemu_fprintf(f, "Z%02d[%x-%x]=", i, j, j - 1); - } else if (!odd) { - if (j > 0) { - qemu_fprintf(f, " [%x-%x]=", j, j - 1); - } else { - qemu_fprintf(f, " [%x]=", j); - } - } - qemu_fprintf(f, "%016" PRIx64 ":%016" PRIx64 "%s", - env->vfp.zregs[i].d[j * 2 + 1], - env->vfp.zregs[i].d[j * 2], - odd || j == 0 ? "\n" : ":"); - } - } - } - } else { - for (i = 0; i < 32; i++) { - uint64_t *q = aa64_vfp_qreg(env, i); - qemu_fprintf(f, "Q%02d=%016" PRIx64 ":%016" PRIx64 "%s", - i, q[1], q[0], (i & 1 ? "\n" : " ")); - } - } -} - void gen_a64_set_pc_im(uint64_t val) { tcg_gen_movi_i64(cpu_pc, val); diff --git a/target/arm/translate.c b/target/arm/translate.c index 4750b9fa1b..a5d7723423 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -28,7 +28,6 @@ #include "tcg-op-gvec.h" #include "qemu/log.h" #include "qemu/bitops.h" -#include "qemu/qemu-print.h" #include "arm_ldst.h" #include "hw/semihosting/semihost.h" @@ -9109,7 +9108,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) loaded_base = 0; loaded_var = NULL; n = 0; - for(i=0;i<16;i++) { + for (i = 0; i < 16; i++) { if (insn & (1 << i)) n++; } @@ -9132,7 +9131,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) } } j = 0; - for(i=0;i<16;i++) { + for (i = 0; i < 16; i++) { if (insn & (1 << i)) { if (is_load) { /* load */ @@ -12342,92 +12341,6 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns) translator_loop(ops, &dc.base, cpu, tb, max_insns); } -void arm_cpu_dump_state(CPUState *cs, FILE *f, int flags) -{ - ARMCPU *cpu = ARM_CPU(cs); - CPUARMState *env = &cpu->env; - int i; - - if (is_a64(env)) { - aarch64_cpu_dump_state(cs, f, flags); - return; - } - - for(i=0;i<16;i++) { - qemu_fprintf(f, "R%02d=%08x", i, env->regs[i]); - if ((i % 4) == 3) - qemu_fprintf(f, "\n"); - else - qemu_fprintf(f, " "); - } - - if (arm_feature(env, ARM_FEATURE_M)) { - uint32_t xpsr = xpsr_read(env); - const char *mode; - const char *ns_status = ""; - - if (arm_feature(env, ARM_FEATURE_M_SECURITY)) { - ns_status = env->v7m.secure ? "S " : "NS "; - } - - if (xpsr & XPSR_EXCP) { - mode = "handler"; - } else { - if (env->v7m.control[env->v7m.secure] & R_V7M_CONTROL_NPRIV_MASK) { - mode = "unpriv-thread"; - } else { - mode = "priv-thread"; - } - } - - qemu_fprintf(f, "XPSR=%08x %c%c%c%c %c %s%s\n", - xpsr, - xpsr & XPSR_N ? 'N' : '-', - xpsr & XPSR_Z ? 'Z' : '-', - xpsr & XPSR_C ? 'C' : '-', - xpsr & XPSR_V ? 'V' : '-', - xpsr & XPSR_T ? 'T' : 'A', - ns_status, - mode); - } else { - uint32_t psr = cpsr_read(env); - const char *ns_status = ""; - - if (arm_feature(env, ARM_FEATURE_EL3) && - (psr & CPSR_M) != ARM_CPU_MODE_MON) { - ns_status = env->cp15.scr_el3 & SCR_NS ? "NS " : "S "; - } - - qemu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%s%d\n", - psr, - psr & CPSR_N ? 'N' : '-', - psr & CPSR_Z ? 'Z' : '-', - psr & CPSR_C ? 'C' : '-', - psr & CPSR_V ? 'V' : '-', - psr & CPSR_T ? 'T' : 'A', - ns_status, - aarch32_mode_name(psr), (psr & 0x10) ? 32 : 26); - } - - if (flags & CPU_DUMP_FPU) { - int numvfpregs = 0; - if (arm_feature(env, ARM_FEATURE_VFP)) { - numvfpregs += 16; - } - if (arm_feature(env, ARM_FEATURE_VFP3)) { - numvfpregs += 16; - } - for (i = 0; i < numvfpregs; i++) { - uint64_t v = *aa32_vfp_dreg(env, i); - qemu_fprintf(f, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64 "\n", - i * 2, (uint32_t)v, - i * 2 + 1, (uint32_t)(v >> 32), - i, v); - } - qemu_fprintf(f, "FPSCR: %08x\n", vfp_get_fpscr(env)); - } -} - void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, target_ulong *data) { diff --git a/target/arm/translate.h b/target/arm/translate.h index bc1617809d..a20f6e2056 100644 --- a/target/arm/translate.h +++ b/target/arm/translate.h @@ -169,7 +169,6 @@ static inline void disas_set_insn_syndrome(DisasContext *s, uint32_t syn) #ifdef TARGET_AARCH64 void a64_translate_init(void); void gen_a64_set_pc_im(uint64_t val); -void aarch64_cpu_dump_state(CPUState *cs, FILE *f, int flags); extern const TranslatorOps aarch64_translator_ops; #else static inline void a64_translate_init(void) @@ -179,10 +178,6 @@ static inline void a64_translate_init(void) static inline void gen_a64_set_pc_im(uint64_t val) { } - -static inline void aarch64_cpu_dump_state(CPUState *cs, FILE *f, int flags) -{ -} #endif void arm_test_cc(DisasCompare *cmp, int cc); diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c index d3e83b627b..46041e3294 100644 --- a/target/arm/vfp_helper.c +++ b/target/arm/vfp_helper.c @@ -18,121 +18,88 @@ */ #include "qemu/osdep.h" -#include "qemu/log.h" #include "cpu.h" #include "exec/helper-proto.h" -#include "fpu/softfloat.h" #include "internals.h" - +#ifdef CONFIG_TCG +#include "qemu/log.h" +#include "fpu/softfloat.h" +#endif /* VFP support. We follow the convention used for VFP instructions: Single precision routines have a "s" suffix, double precision a "d" suffix. */ +#ifdef CONFIG_TCG + /* Convert host exception flags to vfp form. */ static inline int vfp_exceptbits_from_host(int host_bits) { int target_bits = 0; - if (host_bits & float_flag_invalid) + if (host_bits & float_flag_invalid) { target_bits |= 1; - if (host_bits & float_flag_divbyzero) + } + if (host_bits & float_flag_divbyzero) { target_bits |= 2; - if (host_bits & float_flag_overflow) + } + if (host_bits & float_flag_overflow) { target_bits |= 4; - if (host_bits & (float_flag_underflow | float_flag_output_denormal)) + } + if (host_bits & (float_flag_underflow | float_flag_output_denormal)) { target_bits |= 8; - if (host_bits & float_flag_inexact) + } + if (host_bits & float_flag_inexact) { target_bits |= 0x10; - if (host_bits & float_flag_input_denormal) + } + if (host_bits & float_flag_input_denormal) { target_bits |= 0x80; + } return target_bits; } -uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env) -{ - uint32_t i, fpscr; - - fpscr = env->vfp.xregs[ARM_VFP_FPSCR] - | (env->vfp.vec_len << 16) - | (env->vfp.vec_stride << 20); - - i = get_float_exception_flags(&env->vfp.fp_status); - i |= get_float_exception_flags(&env->vfp.standard_fp_status); - /* FZ16 does not generate an input denormal exception. */ - i |= (get_float_exception_flags(&env->vfp.fp_status_f16) - & ~float_flag_input_denormal); - fpscr |= vfp_exceptbits_from_host(i); - - i = env->vfp.qc[0] | env->vfp.qc[1] | env->vfp.qc[2] | env->vfp.qc[3]; - fpscr |= i ? FPCR_QC : 0; - - return fpscr; -} - -uint32_t vfp_get_fpscr(CPUARMState *env) -{ - return HELPER(vfp_get_fpscr)(env); -} - /* Convert vfp exception flags to target form. */ static inline int vfp_exceptbits_to_host(int target_bits) { int host_bits = 0; - if (target_bits & 1) + if (target_bits & 1) { host_bits |= float_flag_invalid; - if (target_bits & 2) + } + if (target_bits & 2) { host_bits |= float_flag_divbyzero; - if (target_bits & 4) + } + if (target_bits & 4) { host_bits |= float_flag_overflow; - if (target_bits & 8) + } + if (target_bits & 8) { host_bits |= float_flag_underflow; - if (target_bits & 0x10) + } + if (target_bits & 0x10) { host_bits |= float_flag_inexact; - if (target_bits & 0x80) + } + if (target_bits & 0x80) { host_bits |= float_flag_input_denormal; + } return host_bits; } -void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val) +static uint32_t vfp_get_fpscr_from_host(CPUARMState *env) { - int i; - uint32_t changed = env->vfp.xregs[ARM_VFP_FPSCR]; - - /* When ARMv8.2-FP16 is not supported, FZ16 is RES0. */ - if (!cpu_isar_feature(aa64_fp16, env_archcpu(env))) { - val &= ~FPCR_FZ16; - } - - if (arm_feature(env, ARM_FEATURE_M)) { - /* - * M profile FPSCR is RES0 for the QC, STRIDE, FZ16, LEN bits - * and also for the trapped-exception-handling bits IxE. - */ - val &= 0xf7c0009f; - } + uint32_t i; - /* - * We don't implement trapped exception handling, so the - * trap enable bits, IDE|IXE|UFE|OFE|DZE|IOE are all RAZ/WI (not RES0!) - * - * If we exclude the exception flags, IOC|DZC|OFC|UFC|IXC|IDC - * (which are stored in fp_status), and the other RES0 bits - * in between, then we clear all of the low 16 bits. - */ - env->vfp.xregs[ARM_VFP_FPSCR] = val & 0xf7c80000; - env->vfp.vec_len = (val >> 16) & 7; - env->vfp.vec_stride = (val >> 20) & 3; + i = get_float_exception_flags(&env->vfp.fp_status); + i |= get_float_exception_flags(&env->vfp.standard_fp_status); + /* FZ16 does not generate an input denormal exception. */ + i |= (get_float_exception_flags(&env->vfp.fp_status_f16) + & ~float_flag_input_denormal); + return vfp_exceptbits_from_host(i); +} - /* - * The bit we set within fpscr_q is arbitrary; the register as a - * whole being zero/non-zero is what counts. - */ - env->vfp.qc[0] = val & FPCR_QC; - env->vfp.qc[1] = 0; - env->vfp.qc[2] = 0; - env->vfp.qc[3] = 0; +static void vfp_set_fpscr_to_host(CPUARMState *env, uint32_t val) +{ + int i; + uint32_t changed = env->vfp.xregs[ARM_VFP_FPSCR]; changed ^= val; if (changed & (3 << 22)) { @@ -170,7 +137,8 @@ void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val) set_default_nan_mode(dnan_enabled, &env->vfp.fp_status_f16); } - /* The exception flags are ORed together when we read fpscr so we + /* + * The exception flags are ORed together when we read fpscr so we * only need to preserve the current state in one of our * float_status values. */ @@ -180,11 +148,86 @@ void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val) set_float_exception_flags(0, &env->vfp.standard_fp_status); } +#else + +static uint32_t vfp_get_fpscr_from_host(CPUARMState *env) +{ + return 0; +} + +static void vfp_set_fpscr_to_host(CPUARMState *env, uint32_t val) +{ +} + +#endif + +uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env) +{ + uint32_t i, fpscr; + + fpscr = env->vfp.xregs[ARM_VFP_FPSCR] + | (env->vfp.vec_len << 16) + | (env->vfp.vec_stride << 20); + + fpscr |= vfp_get_fpscr_from_host(env); + + i = env->vfp.qc[0] | env->vfp.qc[1] | env->vfp.qc[2] | env->vfp.qc[3]; + fpscr |= i ? FPCR_QC : 0; + + return fpscr; +} + +uint32_t vfp_get_fpscr(CPUARMState *env) +{ + return HELPER(vfp_get_fpscr)(env); +} + +void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val) +{ + /* When ARMv8.2-FP16 is not supported, FZ16 is RES0. */ + if (!cpu_isar_feature(aa64_fp16, env_archcpu(env))) { + val &= ~FPCR_FZ16; + } + + if (arm_feature(env, ARM_FEATURE_M)) { + /* + * M profile FPSCR is RES0 for the QC, STRIDE, FZ16, LEN bits + * and also for the trapped-exception-handling bits IxE. + */ + val &= 0xf7c0009f; + } + + /* + * We don't implement trapped exception handling, so the + * trap enable bits, IDE|IXE|UFE|OFE|DZE|IOE are all RAZ/WI (not RES0!) + * + * If we exclude the exception flags, IOC|DZC|OFC|UFC|IXC|IDC + * (which are stored in fp_status), and the other RES0 bits + * in between, then we clear all of the low 16 bits. + */ + env->vfp.xregs[ARM_VFP_FPSCR] = val & 0xf7c80000; + env->vfp.vec_len = (val >> 16) & 7; + env->vfp.vec_stride = (val >> 20) & 3; + + /* + * The bit we set within fpscr_q is arbitrary; the register as a + * whole being zero/non-zero is what counts. + */ + env->vfp.qc[0] = val & FPCR_QC; + env->vfp.qc[1] = 0; + env->vfp.qc[2] = 0; + env->vfp.qc[3] = 0; + + vfp_set_fpscr_to_host(env, val); +} + void vfp_set_fpscr(CPUARMState *env, uint32_t val) { HELPER(vfp_set_fpscr)(env, val); } +#ifdef CONFIG_TCG + #define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p)) #define VFP_BINOP(name) \ @@ -1278,3 +1321,5 @@ float64 HELPER(frint64_d)(float64 f, void *fpst) { return frint_d(f, fpst, 64); } + +#endif diff --git a/target/i386/cpu.c b/target/i386/cpu.c index da6eb67cfb..2a9f4e2d12 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -36,14 +36,14 @@ #include "qemu/option.h" #include "qemu/config-file.h" #include "qapi/error.h" -#include "qapi/qapi-visit-misc.h" +#include "qapi/qapi-visit-machine.h" #include "qapi/qapi-visit-run-state.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qerror.h" #include "qapi/visitor.h" #include "qom/qom-qobject.h" #include "sysemu/arch_init.h" -#include "qapi/qapi-commands-target.h" +#include "qapi/qapi-commands-machine-target.h" #include "standard-headers/asm-x86/kvm_para.h" diff --git a/target/i386/monitor.c b/target/i386/monitor.c index 56e2dbece7..1f3b532fc2 100644 --- a/target/i386/monitor.c +++ b/target/i386/monitor.c @@ -26,11 +26,11 @@ #include "cpu.h" #include "monitor/monitor.h" #include "monitor/hmp-target.h" +#include "monitor/hmp.h" #include "qapi/qmp/qdict.h" #include "hw/i386/pc.h" #include "sysemu/kvm.h" #include "sysemu/sev.h" -#include "hmp.h" #include "qapi/error.h" #include "sev_i386.h" #include "qapi/qapi-commands-misc.h" diff --git a/target/i386/sev_i386.h b/target/i386/sev_i386.h index c0f9373beb..55313441ae 100644 --- a/target/i386/sev_i386.h +++ b/target/i386/sev_i386.h @@ -19,7 +19,7 @@ #include "sysemu/kvm.h" #include "sysemu/sev.h" #include "qemu/error-report.h" -#include "qapi/qapi-commands-target.h" +#include "qapi/qapi-commands-misc-target.h" #define SEV_POLICY_NODBG 0x1 #define SEV_POLICY_NOKS 0x2 diff --git a/target/mips/helper.c b/target/mips/helper.c index 6e6a44292f..a2b6459b05 100644 --- a/target/mips/helper.c +++ b/target/mips/helper.c @@ -24,7 +24,7 @@ #include "exec/cpu_ldst.h" #include "exec/log.h" #include "hw/mips/cpudevs.h" -#include "qapi/qapi-commands-target.h" +#include "qapi/qapi-commands-machine-target.h" enum { TLBRET_XI = -6, diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c index 8bad636501..a383c40ece 100644 --- a/target/mips/msa_helper.c +++ b/target/mips/msa_helper.c @@ -72,9 +72,6 @@ * -------- * * +---------------+----------------------------------------------------------+ - * | BMNZ.V | Vector Bit Move If Not Zero | - * | BMZ.V | Vector Bit Move If Zero | - * | BSEL.V | Vector Bit Select | * | BINSL.B | Vector Bit Insert Left (byte) | * | BINSL.H | Vector Bit Insert Left (halfword) | * | BINSL.W | Vector Bit Insert Left (word) | @@ -83,6 +80,9 @@ * | BINSR.H | Vector Bit Insert Right (halfword) | * | BINSR.W | Vector Bit Insert Right (word) | * | BINSR.D | Vector Bit Insert Right (doubleword) | + * | BMNZ.V | Vector Bit Move If Not Zero | + * | BMZ.V | Vector Bit Move If Zero | + * | BSEL.V | Vector Bit Select | * +---------------+----------------------------------------------------------+ */ @@ -179,12 +179,12 @@ * | ADDV.H | Vector Add (halfword) | * | ADDV.W | Vector Add (word) | * | ADDV.D | Vector Add (doubleword) | - * | HSUB_S.H | Vector Signed Horizontal Add (halfword) | - * | HSUB_S.W | Vector Signed Horizontal Add (word) | - * | HSUB_S.D | Vector Signed Horizontal Add (doubleword) | - * | HSUB_U.H | Vector Unigned Horizontal Add (halfword) | - * | HSUB_U.W | Vector Unigned Horizontal Add (word) | - * | HSUB_U.D | Vector Unigned Horizontal Add (doubleword) | + * | HADD_S.H | Vector Signed Horizontal Add (halfword) | + * | HADD_S.W | Vector Signed Horizontal Add (word) | + * | HADD_S.D | Vector Signed Horizontal Add (doubleword) | + * | HADD_U.H | Vector Unigned Horizontal Add (halfword) | + * | HADD_U.W | Vector Unigned Horizontal Add (word) | + * | HADD_U.D | Vector Unigned Horizontal Add (doubleword) | * +---------------+----------------------------------------------------------+ */ @@ -279,6 +279,18 @@ * | DOTP_U.H | Vector Unsigned Dot Product (halfword) | * | DOTP_U.W | Vector Unsigned Dot Product (word) | * | DOTP_U.D | Vector Unsigned Dot Product (doubleword) | + * | DPADD_S.H | Vector Signed Dot Product (halfword) | + * | DPADD_S.W | Vector Signed Dot Product (word) | + * | DPADD_S.D | Vector Signed Dot Product (doubleword) | + * | DPADD_U.H | Vector Unsigned Dot Product (halfword) | + * | DPADD_U.W | Vector Unsigned Dot Product (word) | + * | DPADD_U.D | Vector Unsigned Dot Product (doubleword) | + * | DPSUB_S.H | Vector Signed Dot Product (halfword) | + * | DPSUB_S.W | Vector Signed Dot Product (word) | + * | DPSUB_S.D | Vector Signed Dot Product (doubleword) | + * | DPSUB_U.H | Vector Unsigned Dot Product (halfword) | + * | DPSUB_U.W | Vector Unsigned Dot Product (word) | + * | DPSUB_U.D | Vector Unsigned Dot Product (doubleword) | * +---------------+----------------------------------------------------------+ */ @@ -389,14 +401,14 @@ * | SUBS_U.H | Vector Unsigned Saturated Subtract (of Uns.) (halfword) | * | SUBS_U.W | Vector Unsigned Saturated Subtract (of Uns.) (word) | * | SUBS_U.D | Vector Unsigned Saturated Subtract (of Uns.) (doubleword)| - * | SUBSUS_S.B | Vector Uns. Sat. Subtract (of S. from Uns.) (byte) | - * | SUBSUS_S.H | Vector Uns. Sat. Subtract (of S. from Uns.) (halfword) | - * | SUBSUS_S.W | Vector Uns. Sat. Subtract (of S. from Uns.) (word) | - * | SUBSUS_S.D | Vector Uns. Sat. Subtract (of S. from Uns.) (doubleword) | - * | SUBSUU_U.B | Vector Signed Saturated Subtract (of Uns.) (byte) | - * | SUBSUU_U.H | Vector Signed Saturated Subtract (of Uns.) (halfword) | - * | SUBSUU_U.W | Vector Signed Saturated Subtract (of Uns.) (word) | - * | SUBSUU_U.D | Vector Signed Saturated Subtract (of Uns.) (doubleword) | + * | SUBSUS_U.B | Vector Uns. Sat. Subtract (of S. from Uns.) (byte) | + * | SUBSUS_U.H | Vector Uns. Sat. Subtract (of S. from Uns.) (halfword) | + * | SUBSUS_U.W | Vector Uns. Sat. Subtract (of S. from Uns.) (word) | + * | SUBSUS_U.D | Vector Uns. Sat. Subtract (of S. from Uns.) (doubleword) | + * | SUBSUU_S.B | Vector Signed Saturated Subtract (of Uns.) (byte) | + * | SUBSUU_S.H | Vector Signed Saturated Subtract (of Uns.) (halfword) | + * | SUBSUU_S.W | Vector Signed Saturated Subtract (of Uns.) (word) | + * | SUBSUU_S.D | Vector Signed Saturated Subtract (of Uns.) (doubleword) | * | SUBV.B | Vector Subtract (byte) | * | SUBV.H | Vector Subtract (halfword) | * | SUBV.W | Vector Subtract (word) | @@ -450,6 +462,18 @@ /* + * Move + * ---- + * + * +---------------+----------------------------------------------------------+ + * | MOVE.V | Vector Move | + * +---------------+----------------------------------------------------------+ + */ + +/* TODO: insert Move group helpers here */ + + +/* * Pack * ---- * @@ -3826,35 +3850,65 @@ void helper_msa_fmin_df(CPUMIPSState *env, uint32_t df, uint32_t wd, wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - uint32_t i; clear_msacsr_cause(env); - switch (df) { - case DF_WORD: - for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { - if (NUMBER_QNAN_PAIR(pws->w[i], pwt->w[i], 32, status)) { - MSA_FLOAT_MAXOP(pwx->w[i], min, pws->w[i], pws->w[i], 32); - } else if (NUMBER_QNAN_PAIR(pwt->w[i], pws->w[i], 32, status)) { - MSA_FLOAT_MAXOP(pwx->w[i], min, pwt->w[i], pwt->w[i], 32); - } else { - MSA_FLOAT_MAXOP(pwx->w[i], min, pws->w[i], pwt->w[i], 32); - } + if (df == DF_WORD) { + + if (NUMBER_QNAN_PAIR(pws->w[0], pwt->w[0], 32, status)) { + MSA_FLOAT_MAXOP(pwx->w[0], min, pws->w[0], pws->w[0], 32); + } else if (NUMBER_QNAN_PAIR(pwt->w[0], pws->w[0], 32, status)) { + MSA_FLOAT_MAXOP(pwx->w[0], min, pwt->w[0], pwt->w[0], 32); + } else { + MSA_FLOAT_MAXOP(pwx->w[0], min, pws->w[0], pwt->w[0], 32); } - break; - case DF_DOUBLE: - for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { - if (NUMBER_QNAN_PAIR(pws->d[i], pwt->d[i], 64, status)) { - MSA_FLOAT_MAXOP(pwx->d[i], min, pws->d[i], pws->d[i], 64); - } else if (NUMBER_QNAN_PAIR(pwt->d[i], pws->d[i], 64, status)) { - MSA_FLOAT_MAXOP(pwx->d[i], min, pwt->d[i], pwt->d[i], 64); - } else { - MSA_FLOAT_MAXOP(pwx->d[i], min, pws->d[i], pwt->d[i], 64); - } + + if (NUMBER_QNAN_PAIR(pws->w[1], pwt->w[1], 32, status)) { + MSA_FLOAT_MAXOP(pwx->w[1], min, pws->w[1], pws->w[1], 32); + } else if (NUMBER_QNAN_PAIR(pwt->w[1], pws->w[1], 32, status)) { + MSA_FLOAT_MAXOP(pwx->w[1], min, pwt->w[1], pwt->w[1], 32); + } else { + MSA_FLOAT_MAXOP(pwx->w[1], min, pws->w[1], pwt->w[1], 32); } - break; - default: + + if (NUMBER_QNAN_PAIR(pws->w[2], pwt->w[2], 32, status)) { + MSA_FLOAT_MAXOP(pwx->w[2], min, pws->w[2], pws->w[2], 32); + } else if (NUMBER_QNAN_PAIR(pwt->w[2], pws->w[2], 32, status)) { + MSA_FLOAT_MAXOP(pwx->w[2], min, pwt->w[2], pwt->w[2], 32); + } else { + MSA_FLOAT_MAXOP(pwx->w[2], min, pws->w[2], pwt->w[2], 32); + } + + if (NUMBER_QNAN_PAIR(pws->w[3], pwt->w[3], 32, status)) { + MSA_FLOAT_MAXOP(pwx->w[3], min, pws->w[3], pws->w[3], 32); + } else if (NUMBER_QNAN_PAIR(pwt->w[3], pws->w[3], 32, status)) { + MSA_FLOAT_MAXOP(pwx->w[3], min, pwt->w[3], pwt->w[3], 32); + } else { + MSA_FLOAT_MAXOP(pwx->w[3], min, pws->w[3], pwt->w[3], 32); + } + + } else if (df == DF_DOUBLE) { + + if (NUMBER_QNAN_PAIR(pws->d[0], pwt->d[0], 64, status)) { + MSA_FLOAT_MAXOP(pwx->d[0], min, pws->d[0], pws->d[0], 64); + } else if (NUMBER_QNAN_PAIR(pwt->d[0], pws->d[0], 64, status)) { + MSA_FLOAT_MAXOP(pwx->d[0], min, pwt->d[0], pwt->d[0], 64); + } else { + MSA_FLOAT_MAXOP(pwx->d[0], min, pws->d[0], pwt->d[0], 64); + } + + if (NUMBER_QNAN_PAIR(pws->d[1], pwt->d[1], 64, status)) { + MSA_FLOAT_MAXOP(pwx->d[1], min, pws->d[1], pws->d[1], 64); + } else if (NUMBER_QNAN_PAIR(pwt->d[1], pws->d[1], 64, status)) { + MSA_FLOAT_MAXOP(pwx->d[1], min, pwt->d[1], pwt->d[1], 64); + } else { + MSA_FLOAT_MAXOP(pwx->d[1], min, pws->d[1], pwt->d[1], 64); + } + + } else { + assert(0); + } check_msacsr_cause(env, GETPC()); @@ -3870,22 +3924,18 @@ void helper_msa_fmin_a_df(CPUMIPSState *env, uint32_t df, uint32_t wd, wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - uint32_t i; clear_msacsr_cause(env); - switch (df) { - case DF_WORD: - for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { - FMAXMIN_A(min, max, pwx->w[i], pws->w[i], pwt->w[i], 32, status); - } - break; - case DF_DOUBLE: - for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { - FMAXMIN_A(min, max, pwx->d[i], pws->d[i], pwt->d[i], 64, status); - } - break; - default: + if (df == DF_WORD) { + FMAXMIN_A(min, max, pwx->w[0], pws->w[0], pwt->w[0], 32, status); + FMAXMIN_A(min, max, pwx->w[1], pws->w[1], pwt->w[1], 32, status); + FMAXMIN_A(min, max, pwx->w[2], pws->w[2], pwt->w[2], 32, status); + FMAXMIN_A(min, max, pwx->w[3], pws->w[3], pwt->w[3], 32, status); + } else if (df == DF_DOUBLE) { + FMAXMIN_A(min, max, pwx->d[0], pws->d[0], pwt->d[0], 64, status); + FMAXMIN_A(min, max, pwx->d[1], pws->d[1], pwt->d[1], 64, status); + } else { assert(0); } @@ -3897,40 +3947,70 @@ void helper_msa_fmin_a_df(CPUMIPSState *env, uint32_t df, uint32_t wd, void helper_msa_fmax_df(CPUMIPSState *env, uint32_t df, uint32_t wd, uint32_t ws, uint32_t wt) { - float_status *status = &env->active_tc.msa_fp_status; + float_status *status = &env->active_tc.msa_fp_status; wr_t wx, *pwx = &wx; wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - uint32_t i; clear_msacsr_cause(env); - switch (df) { - case DF_WORD: - for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { - if (NUMBER_QNAN_PAIR(pws->w[i], pwt->w[i], 32, status)) { - MSA_FLOAT_MAXOP(pwx->w[i], max, pws->w[i], pws->w[i], 32); - } else if (NUMBER_QNAN_PAIR(pwt->w[i], pws->w[i], 32, status)) { - MSA_FLOAT_MAXOP(pwx->w[i], max, pwt->w[i], pwt->w[i], 32); - } else { - MSA_FLOAT_MAXOP(pwx->w[i], max, pws->w[i], pwt->w[i], 32); - } + if (df == DF_WORD) { + + if (NUMBER_QNAN_PAIR(pws->w[0], pwt->w[0], 32, status)) { + MSA_FLOAT_MAXOP(pwx->w[0], max, pws->w[0], pws->w[0], 32); + } else if (NUMBER_QNAN_PAIR(pwt->w[0], pws->w[0], 32, status)) { + MSA_FLOAT_MAXOP(pwx->w[0], max, pwt->w[0], pwt->w[0], 32); + } else { + MSA_FLOAT_MAXOP(pwx->w[0], max, pws->w[0], pwt->w[0], 32); } - break; - case DF_DOUBLE: - for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { - if (NUMBER_QNAN_PAIR(pws->d[i], pwt->d[i], 64, status)) { - MSA_FLOAT_MAXOP(pwx->d[i], max, pws->d[i], pws->d[i], 64); - } else if (NUMBER_QNAN_PAIR(pwt->d[i], pws->d[i], 64, status)) { - MSA_FLOAT_MAXOP(pwx->d[i], max, pwt->d[i], pwt->d[i], 64); - } else { - MSA_FLOAT_MAXOP(pwx->d[i], max, pws->d[i], pwt->d[i], 64); - } + + if (NUMBER_QNAN_PAIR(pws->w[1], pwt->w[1], 32, status)) { + MSA_FLOAT_MAXOP(pwx->w[1], max, pws->w[1], pws->w[1], 32); + } else if (NUMBER_QNAN_PAIR(pwt->w[1], pws->w[1], 32, status)) { + MSA_FLOAT_MAXOP(pwx->w[1], max, pwt->w[1], pwt->w[1], 32); + } else { + MSA_FLOAT_MAXOP(pwx->w[1], max, pws->w[1], pwt->w[1], 32); } - break; - default: + + if (NUMBER_QNAN_PAIR(pws->w[2], pwt->w[2], 32, status)) { + MSA_FLOAT_MAXOP(pwx->w[2], max, pws->w[2], pws->w[2], 32); + } else if (NUMBER_QNAN_PAIR(pwt->w[2], pws->w[2], 32, status)) { + MSA_FLOAT_MAXOP(pwx->w[2], max, pwt->w[2], pwt->w[2], 32); + } else { + MSA_FLOAT_MAXOP(pwx->w[2], max, pws->w[2], pwt->w[2], 32); + } + + if (NUMBER_QNAN_PAIR(pws->w[3], pwt->w[3], 32, status)) { + MSA_FLOAT_MAXOP(pwx->w[3], max, pws->w[3], pws->w[3], 32); + } else if (NUMBER_QNAN_PAIR(pwt->w[3], pws->w[3], 32, status)) { + MSA_FLOAT_MAXOP(pwx->w[3], max, pwt->w[3], pwt->w[3], 32); + } else { + MSA_FLOAT_MAXOP(pwx->w[3], max, pws->w[3], pwt->w[3], 32); + } + + } else if (df == DF_DOUBLE) { + + if (NUMBER_QNAN_PAIR(pws->d[0], pwt->d[0], 64, status)) { + MSA_FLOAT_MAXOP(pwx->d[0], max, pws->d[0], pws->d[0], 64); + } else if (NUMBER_QNAN_PAIR(pwt->d[0], pws->d[0], 64, status)) { + MSA_FLOAT_MAXOP(pwx->d[0], max, pwt->d[0], pwt->d[0], 64); + } else { + MSA_FLOAT_MAXOP(pwx->d[0], max, pws->d[0], pwt->d[0], 64); + } + + if (NUMBER_QNAN_PAIR(pws->d[1], pwt->d[1], 64, status)) { + MSA_FLOAT_MAXOP(pwx->d[1], max, pws->d[1], pws->d[1], 64); + } else if (NUMBER_QNAN_PAIR(pwt->d[1], pws->d[1], 64, status)) { + MSA_FLOAT_MAXOP(pwx->d[1], max, pwt->d[1], pwt->d[1], 64); + } else { + MSA_FLOAT_MAXOP(pwx->d[1], max, pws->d[1], pwt->d[1], 64); + } + + } else { + assert(0); + } check_msacsr_cause(env, GETPC()); @@ -3946,22 +4026,18 @@ void helper_msa_fmax_a_df(CPUMIPSState *env, uint32_t df, uint32_t wd, wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - uint32_t i; clear_msacsr_cause(env); - switch (df) { - case DF_WORD: - for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { - FMAXMIN_A(max, min, pwx->w[i], pws->w[i], pwt->w[i], 32, status); - } - break; - case DF_DOUBLE: - for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { - FMAXMIN_A(max, min, pwx->d[i], pws->d[i], pwt->d[i], 64, status); - } - break; - default: + if (df == DF_WORD) { + FMAXMIN_A(max, min, pwx->w[0], pws->w[0], pwt->w[0], 32, status); + FMAXMIN_A(max, min, pwx->w[1], pws->w[1], pwt->w[1], 32, status); + FMAXMIN_A(max, min, pwx->w[2], pws->w[2], pwt->w[2], 32, status); + FMAXMIN_A(max, min, pwx->w[3], pws->w[3], pwt->w[3], 32, status); + } else if (df == DF_DOUBLE) { + FMAXMIN_A(max, min, pwx->d[0], pws->d[0], pwt->d[0], 64, status); + FMAXMIN_A(max, min, pwx->d[1], pws->d[1], pwt->d[1], 64, status); + } else { assert(0); } @@ -3982,9 +4058,11 @@ void helper_msa_fclass_df(CPUMIPSState *env, uint32_t df, pwd->w[1] = float_class_s(pws->w[1], status); pwd->w[2] = float_class_s(pws->w[2], status); pwd->w[3] = float_class_s(pws->w[3], status); - } else { + } else if (df == DF_DOUBLE) { pwd->d[0] = float_class_d(pws->d[0], status); pwd->d[1] = float_class_d(pws->d[1], status); + } else { + assert(0); } } diff --git a/target/mips/translate.c b/target/mips/translate.c index e3a0f08dea..f96f141cdf 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -259,8 +259,10 @@ enum { OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL, }; -/* R6 Multiply and Divide instructions have the same Opcode - and function field as legacy OPC_MULT[U]/OPC_DIV[U] */ +/* + * R6 Multiply and Divide instructions have the same opcode + * and function field as legacy OPC_MULT[U]/OPC_DIV[U] + */ #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff))) enum { @@ -2923,10 +2925,11 @@ static inline void check_cp1_enabled(DisasContext *ctx) } } -/* Verify that the processor is running with COP1X instructions enabled. - This is associated with the nabla symbol in the MIPS32 and MIPS64 - opcode tables. */ - +/* + * Verify that the processor is running with COP1X instructions enabled. + * This is associated with the nabla symbol in the MIPS32 and MIPS64 + * opcode tables. + */ static inline void check_cop1x(DisasContext *ctx) { if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) { @@ -2934,9 +2937,10 @@ static inline void check_cop1x(DisasContext *ctx) } } -/* Verify that the processor is running with 64-bit floating-point - operations enabled. */ - +/* + * Verify that the processor is running with 64-bit floating-point + * operations enabled. + */ static inline void check_cp1_64bitmode(DisasContext *ctx) { if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) { @@ -2962,10 +2966,10 @@ static inline void check_cp1_registers(DisasContext *ctx, int regs) } } -/* Verify that the processor is running with DSP instructions enabled. - This is enabled by CP0 Status register MX(24) bit. +/* + * Verify that the processor is running with DSP instructions enabled. + * This is enabled by CP0 Status register MX(24) bit. */ - static inline void check_dsp(DisasContext *ctx) { if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) { @@ -2999,8 +3003,10 @@ static inline void check_dsp_r3(DisasContext *ctx) } } -/* This code generates a "reserved instruction" exception if the - CPU does not support the instruction set corresponding to flags. */ +/* + * This code generates a "reserved instruction" exception if the + * CPU does not support the instruction set corresponding to flags. + */ static inline void check_insn(DisasContext *ctx, uint64_t flags) { if (unlikely(!(ctx->insn_flags & flags))) { @@ -3008,9 +3014,11 @@ static inline void check_insn(DisasContext *ctx, uint64_t flags) } } -/* This code generates a "reserved instruction" exception if the - CPU has corresponding flag set which indicates that the instruction - has been removed. */ +/* + * This code generates a "reserved instruction" exception if the + * CPU has corresponding flag set which indicates that the instruction + * has been removed. + */ static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags) { if (unlikely(ctx->insn_flags & flags)) { @@ -3033,8 +3041,10 @@ static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags) #endif } -/* This code generates a "reserved instruction" exception if the - CPU does not support 64-bit paired-single (PS) floating point data type */ +/* + * This code generates a "reserved instruction" exception if the + * CPU does not support 64-bit paired-single (PS) floating point data type. + */ static inline void check_ps(DisasContext *ctx) { if (unlikely(!ctx->ps)) { @@ -3044,8 +3054,10 @@ static inline void check_ps(DisasContext *ctx) } #ifdef TARGET_MIPS64 -/* This code generates a "reserved instruction" exception if 64-bit - instructions are not enabled. */ +/* + * This code generates a "reserved instruction" exception if 64-bit + * instructions are not enabled. + */ static inline void check_mips_64(DisasContext *ctx) { if (unlikely(!(ctx->hflags & MIPS_HFLAG_64))) { @@ -3157,10 +3169,12 @@ static inline void check_eva(DisasContext *ctx) } -/* Define small wrappers for gen_load_fpr* so that we have a uniform - calling interface for 32 and 64-bit FPRs. No sense in changing - all callers for gen_load_fpr32 when we need the CTX parameter for - this one use. */ +/* + * Define small wrappers for gen_load_fpr* so that we have a uniform + * calling interface for 32 and 64-bit FPRs. No sense in changing + * all callers for gen_load_fpr32 when we need the CTX parameter for + * this one use. + */ #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y) #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y) #define FOP_CONDS(type, abs, fmt, ifmt, bits) \ @@ -3405,9 +3419,11 @@ static void gen_ld(DisasContext *ctx, uint32_t opc, int mem_idx = ctx->mem_idx; if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) { - /* Loongson CPU uses a load to zero register for prefetch. - We emulate it as a NOP. On other CPU we must perform the - actual memory access. */ + /* + * Loongson CPU uses a load to zero register for prefetch. + * We emulate it as a NOP. On other CPU we must perform the + * actual memory access. + */ return; } @@ -3433,8 +3449,10 @@ static void gen_ld(DisasContext *ctx, uint32_t opc, break; case OPC_LDL: t1 = tcg_temp_new(); - /* Do a byte access to possibly trigger a page - fault with the unaligned address. */ + /* + * Do a byte access to possibly trigger a page + * fault with the unaligned address. + */ tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB); tcg_gen_andi_tl(t1, t0, 7); #ifndef TARGET_WORDS_BIGENDIAN @@ -3455,8 +3473,10 @@ static void gen_ld(DisasContext *ctx, uint32_t opc, break; case OPC_LDR: t1 = tcg_temp_new(); - /* Do a byte access to possibly trigger a page - fault with the unaligned address. */ + /* + * Do a byte access to possibly trigger a page + * fault with the unaligned address. + */ tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB); tcg_gen_andi_tl(t1, t0, 7); #ifdef TARGET_WORDS_BIGENDIAN @@ -3534,8 +3554,10 @@ static void gen_ld(DisasContext *ctx, uint32_t opc, /* fall through */ case OPC_LWL: t1 = tcg_temp_new(); - /* Do a byte access to possibly trigger a page - fault with the unaligned address. */ + /* + * Do a byte access to possibly trigger a page + * fault with the unaligned address. + */ tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB); tcg_gen_andi_tl(t1, t0, 3); #ifndef TARGET_WORDS_BIGENDIAN @@ -3560,8 +3582,10 @@ static void gen_ld(DisasContext *ctx, uint32_t opc, /* fall through */ case OPC_LWR: t1 = tcg_temp_new(); - /* Do a byte access to possibly trigger a page - fault with the unaligned address. */ + /* + * Do a byte access to possibly trigger a page + * fault with the unaligned address. + */ tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB); tcg_gen_andi_tl(t1, t0, 3); #ifdef TARGET_WORDS_BIGENDIAN @@ -3762,8 +3786,10 @@ static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset, static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft, TCGv t0) { - /* Don't do NOP if destination is zero: we must perform the actual - memory access. */ + /* + * Don't do NOP if destination is zero: we must perform the actual + * memory access. + */ switch (opc) { case OPC_LWC1: { @@ -3837,8 +3863,10 @@ static void gen_arith_imm(DisasContext *ctx, uint32_t opc, target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */ if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) { - /* If no destination, treat it as a NOP. - For addi, we must generate the overflow exception when needed. */ + /* + * If no destination, treat it as a NOP. + * For addi, we must generate the overflow exception when needed. + */ return; } switch (opc) { @@ -4064,8 +4092,10 @@ static void gen_arith(DisasContext *ctx, uint32_t opc, { if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB && opc != OPC_DADD && opc != OPC_DSUB) { - /* If no destination, treat it as a NOP. - For add & sub, we must generate the overflow exception when needed. */ + /* + * If no destination, treat it as a NOP. + * For add & sub, we must generate the overflow exception when needed. + */ return; } @@ -4123,7 +4153,10 @@ static void gen_arith(DisasContext *ctx, uint32_t opc, tcg_temp_free(t2); tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1); tcg_temp_free(t1); - /* operands of different sign, first operand and result different sign */ + /* + * operands of different sign, first operand and the result + * of different sign + */ generate_exception(ctx, EXCP_OVERFLOW); gen_set_label(l1); gen_store_gpr(t0, rd); @@ -4346,8 +4379,10 @@ static void gen_shift(DisasContext *ctx, uint32_t opc, TCGv t0, t1; if (rd == 0) { - /* If no destination, treat it as a NOP. - For add & sub, we must generate the overflow exception when needed. */ + /* + * If no destination, treat it as a NOP. + * For add & sub, we must generate the overflow exception when needed. + */ return; } @@ -5643,8 +5678,10 @@ static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt) break; case OPC_SRA_CP2: case OPC_DSRA_CP2: - /* Since SRA is UndefinedResult without sign-extended inputs, - we can treat SRA and DSRA the same. */ + /* + * Since SRA is UndefinedResult without sign-extended inputs, + * we can treat SRA and DSRA the same. + */ tcg_gen_sar_i64(t0, t0, t1); break; case OPC_SRL_CP2: @@ -5720,8 +5757,10 @@ static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt) case OPC_SLT_CP2: case OPC_SLEU_CP2: case OPC_SLE_CP2: - /* ??? Document is unclear: Set FCC[CC]. Does that mean the - FD field is the CC field? */ + /* + * ??? Document is unclear: Set FCC[CC]. Does that mean the + * FD field is the CC field? + */ default: MIPS_INVAL("loongson_cp2"); generate_exception_end(ctx, EXCP_RI); @@ -5935,8 +5974,10 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, case OPC_JALR: /* Jump to register */ if (offset != 0 && offset != 16) { - /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the - others are reserved. */ + /* + * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the + * others are reserved. + */ MIPS_INVAL("jump hint"); generate_exception_end(ctx, EXCP_RI); goto out; @@ -5972,8 +6013,10 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, /* Treat as NOP. */ goto out; case OPC_BLTZAL: /* 0 < 0 */ - /* Handle as an unconditional branch to get correct delay - slot checking. */ + /* + * Handle as an unconditional branch to get correct delay + * slot checking. + */ blink = 31; btgt = ctx->base.pc_next + insn_bytes + delayslot_size; ctx->hflags |= MIPS_HFLAG_B; @@ -6151,8 +6194,10 @@ static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc, case OPC_JALR: /* Jump to register */ if (offset != 0 && offset != 16) { - /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the - others are reserved. */ + /* + * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the + * others are reserved. + */ MIPS_INVAL("jump hint"); generate_exception_end(ctx, EXCP_RI); goto out; @@ -6249,8 +6294,10 @@ static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt, if (msb != 31) { tcg_gen_extract_tl(t0, t1, lsb, msb + 1); } else { - /* The two checks together imply that lsb == 0, - so this is a simple sign-extension. */ + /* + * The two checks together imply that lsb == 0, + * so this is a simple sign-extension. + */ tcg_gen_ext32s_tl(t0, t1); } break; @@ -6701,10 +6748,12 @@ static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel) case CP0_REGISTER_17: switch (sel) { case 0: - /* LLAddr is read-only (the only exception is bit 0 if LLB is - supported); the CP0_LLAddr_rw_bitmask does not seem to be - relevant for modern MIPS cores supporting MTHC0, therefore - treating MTHC0 to LLAddr as NOP. */ + /* + * LLAddr is read-only (the only exception is bit 0 if LLB is + * supported); the CP0_LLAddr_rw_bitmask does not seem to be + * relevant for modern MIPS cores supporting MTHC0, therefore + * treating MTHC0 to LLAddr as NOP. + */ register_name = "LLAddr"; break; case 1: @@ -6928,7 +6977,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) register_name = "Context"; break; case 1: -// gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */ + /* gen_helper_mfc0_contextconfig(arg); - SmartMIPS ASE */ register_name = "ContextConfig"; goto cp0_unimplemented; case 2: @@ -7079,9 +7128,11 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { gen_io_end(); } - /* Break the TB to be able to take timer interrupts immediately - after reading count. DISAS_STOP isn't sufficient, we need to - ensure we break completely out of translated code. */ + /* + * Break the TB to be able to take timer interrupts immediately + * after reading count. DISAS_STOP isn't sufficient, we need to + * ensure we break completely out of translated code. + */ gen_save_pc(ctx->base.pc_next + 4); ctx->base.is_jmp = DISAS_EXIT; register_name = "Count"; @@ -7361,31 +7412,31 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) register_name = "Performance0"; break; case 1: -// gen_helper_mfc0_performance1(arg); + /* gen_helper_mfc0_performance1(arg); */ register_name = "Performance1"; goto cp0_unimplemented; case 2: -// gen_helper_mfc0_performance2(arg); + /* gen_helper_mfc0_performance2(arg); */ register_name = "Performance2"; goto cp0_unimplemented; case 3: -// gen_helper_mfc0_performance3(arg); + /* gen_helper_mfc0_performance3(arg); */ register_name = "Performance3"; goto cp0_unimplemented; case 4: -// gen_helper_mfc0_performance4(arg); + /* gen_helper_mfc0_performance4(arg); */ register_name = "Performance4"; goto cp0_unimplemented; case 5: -// gen_helper_mfc0_performance5(arg); + /* gen_helper_mfc0_performance5(arg); */ register_name = "Performance5"; goto cp0_unimplemented; case 6: -// gen_helper_mfc0_performance6(arg); + /* gen_helper_mfc0_performance6(arg); */ register_name = "Performance6"; goto cp0_unimplemented; case 7: -// gen_helper_mfc0_performance7(arg); + /* gen_helper_mfc0_performance7(arg); */ register_name = "Performance7"; goto cp0_unimplemented; default: @@ -7877,9 +7928,11 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) case 0: save_cpu_state(ctx, 1); gen_helper_mtc0_cause(cpu_env, arg); - /* Stop translation as we may have triggered an interrupt. + /* + * Stop translation as we may have triggered an interrupt. * DISAS_STOP isn't sufficient, we need to ensure we break out of - * translated code to check for pending interrupts. */ + * translated code to check for pending interrupts. + */ gen_save_pc(ctx->base.pc_next + 4); ctx->base.is_jmp = DISAS_EXIT; register_name = "Cause"; @@ -8104,31 +8157,31 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) register_name = "Performance0"; break; case 1: -// gen_helper_mtc0_performance1(arg); + /* gen_helper_mtc0_performance1(arg); */ register_name = "Performance1"; goto cp0_unimplemented; case 2: -// gen_helper_mtc0_performance2(arg); + /* gen_helper_mtc0_performance2(arg); */ register_name = "Performance2"; goto cp0_unimplemented; case 3: -// gen_helper_mtc0_performance3(arg); + /* gen_helper_mtc0_performance3(arg); */ register_name = "Performance3"; goto cp0_unimplemented; case 4: -// gen_helper_mtc0_performance4(arg); + /* gen_helper_mtc0_performance4(arg); */ register_name = "Performance4"; goto cp0_unimplemented; case 5: -// gen_helper_mtc0_performance5(arg); + /* gen_helper_mtc0_performance5(arg); */ register_name = "Performance5"; goto cp0_unimplemented; case 6: -// gen_helper_mtc0_performance6(arg); + /* gen_helper_mtc0_performance6(arg); */ register_name = "Performance6"; goto cp0_unimplemented; case 7: -// gen_helper_mtc0_performance7(arg); + /* gen_helper_mtc0_performance7(arg); */ register_name = "Performance7"; goto cp0_unimplemented; default: @@ -8240,8 +8293,10 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) /* For simplicity assume that all writes can cause interrupts. */ if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { gen_io_end(); - /* DISAS_STOP isn't sufficient, we need to ensure we break out of - * translated code to check for pending interrupts. */ + /* + * DISAS_STOP isn't sufficient, we need to ensure we break out of + * translated code to check for pending interrupts. + */ gen_save_pc(ctx->base.pc_next + 4); ctx->base.is_jmp = DISAS_EXIT; } @@ -8551,9 +8606,11 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel) if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { gen_io_end(); } - /* Break the TB to be able to take timer interrupts immediately - after reading count. DISAS_STOP isn't sufficient, we need to - ensure we break completely out of translated code. */ + /* + * Break the TB to be able to take timer interrupts immediately + * after reading count. DISAS_STOP isn't sufficient, we need to + * ensure we break completely out of translated code. + */ gen_save_pc(ctx->base.pc_next + 4); ctx->base.is_jmp = DISAS_EXIT; register_name = "Count"; @@ -8825,31 +8882,31 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel) register_name = "Performance0"; break; case 1: -// gen_helper_dmfc0_performance1(arg); + /* gen_helper_dmfc0_performance1(arg); */ register_name = "Performance1"; goto cp0_unimplemented; case 2: -// gen_helper_dmfc0_performance2(arg); + /* gen_helper_dmfc0_performance2(arg); */ register_name = "Performance2"; goto cp0_unimplemented; case 3: -// gen_helper_dmfc0_performance3(arg); + /* gen_helper_dmfc0_performance3(arg); */ register_name = "Performance3"; goto cp0_unimplemented; case 4: -// gen_helper_dmfc0_performance4(arg); + /* gen_helper_dmfc0_performance4(arg); */ register_name = "Performance4"; goto cp0_unimplemented; case 5: -// gen_helper_dmfc0_performance5(arg); + /* gen_helper_dmfc0_performance5(arg); */ register_name = "Performance5"; goto cp0_unimplemented; case 6: -// gen_helper_dmfc0_performance6(arg); + /* gen_helper_dmfc0_performance6(arg); */ register_name = "Performance6"; goto cp0_unimplemented; case 7: -// gen_helper_dmfc0_performance7(arg); + /* gen_helper_dmfc0_performance7(arg); */ register_name = "Performance7"; goto cp0_unimplemented; default: @@ -9336,9 +9393,11 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) case 0: save_cpu_state(ctx, 1); gen_helper_mtc0_cause(cpu_env, arg); - /* Stop translation as we may have triggered an interrupt. + /* + * Stop translation as we may have triggered an interrupt. * DISAS_STOP isn't sufficient, we need to ensure we break out of - * translated code to check for pending interrupts. */ + * translated code to check for pending interrupts. + */ gen_save_pc(ctx->base.pc_next + 4); ctx->base.is_jmp = DISAS_EXIT; register_name = "Cause"; @@ -9550,31 +9609,31 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) register_name = "Performance0"; break; case 1: -// gen_helper_mtc0_performance1(cpu_env, arg); + /* gen_helper_mtc0_performance1(cpu_env, arg); */ register_name = "Performance1"; goto cp0_unimplemented; case 2: -// gen_helper_mtc0_performance2(cpu_env, arg); + /* gen_helper_mtc0_performance2(cpu_env, arg); */ register_name = "Performance2"; goto cp0_unimplemented; case 3: -// gen_helper_mtc0_performance3(cpu_env, arg); + /* gen_helper_mtc0_performance3(cpu_env, arg); */ register_name = "Performance3"; goto cp0_unimplemented; case 4: -// gen_helper_mtc0_performance4(cpu_env, arg); + /* gen_helper_mtc0_performance4(cpu_env, arg); */ register_name = "Performance4"; goto cp0_unimplemented; case 5: -// gen_helper_mtc0_performance5(cpu_env, arg); + /* gen_helper_mtc0_performance5(cpu_env, arg); */ register_name = "Performance5"; goto cp0_unimplemented; case 6: -// gen_helper_mtc0_performance6(cpu_env, arg); + /* gen_helper_mtc0_performance6(cpu_env, arg); */ register_name = "Performance6"; goto cp0_unimplemented; case 7: -// gen_helper_mtc0_performance7(cpu_env, arg); + /* gen_helper_mtc0_performance7(cpu_env, arg); */ register_name = "Performance7"; goto cp0_unimplemented; default: @@ -9686,8 +9745,10 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) /* For simplicity assume that all writes can cause interrupts. */ if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { gen_io_end(); - /* DISAS_STOP isn't sufficient, we need to ensure we break out of - * translated code to check for pending interrupts. */ + /* + * DISAS_STOP isn't sufficient, we need to ensure we break out of + * translated code to check for pending interrupts. + */ gen_save_pc(ctx->base.pc_next + 4); ctx->base.is_jmp = DISAS_EXIT; } @@ -9933,10 +9994,12 @@ static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt, if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 && ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) != (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) { - /* NOP */ ; + /* NOP */ + ; } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) > (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) { - /* NOP */ ; + /* NOP */ + ; } else if (u == 0) { switch (rd) { case 1: @@ -12389,8 +12452,10 @@ static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc, } else { gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]); } - /* Don't do NOP if destination is zero: we must perform the actual - memory access. */ + /* + * Don't do NOP if destination is zero: we must perform the actual + * memory access. + */ switch (opc) { case OPC_LWXC1: check_cop1x(ctx); @@ -12718,8 +12783,10 @@ static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel) TCGv t0; #if !defined(CONFIG_USER_ONLY) - /* The Linux kernel will emulate rdhwr if it's not supported natively. - Therefore only check the ISA in system mode. */ + /* + * The Linux kernel will emulate rdhwr if it's not supported natively. + * Therefore only check the ISA in system mode. + */ check_insn(ctx, ISA_MIPS32R2); #endif t0 = tcg_temp_new(); @@ -12742,9 +12809,11 @@ static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel) gen_io_end(); } gen_store_gpr(t0, rt); - /* Break the TB to be able to take timer interrupts immediately - after reading count. DISAS_STOP isn't sufficient, we need to ensure - we break completely out of translated code. */ + /* + * Break the TB to be able to take timer interrupts immediately + * after reading count. DISAS_STOP isn't sufficient, we need to ensure + * we break completely out of translated code. + */ gen_save_pc(ctx->base.pc_next + 4); ctx->base.is_jmp = DISAS_EXIT; break; @@ -12755,7 +12824,8 @@ static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel) case 4: check_insn(ctx, ISA_MIPS32R6); if (sel != 0) { - /* Performance counter registers are not implemented other than + /* + * Performance counter registers are not implemented other than * control register 0. */ generate_exception(ctx, EXCP_RI); @@ -12799,8 +12869,10 @@ static inline void clear_branch_hflags(DisasContext *ctx) if (ctx->base.is_jmp == DISAS_NEXT) { save_cpu_state(ctx, 0); } else { - /* it is not safe to save ctx->hflags as hflags may be changed - in execution time by the instruction in delay / forbidden slot. */ + /* + * It is not safe to save ctx->hflags as hflags may be changed + * in execution time by the instruction in delay / forbidden slot. + */ tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK); } } @@ -13599,8 +13671,10 @@ static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx) | ((ctx->opcode >> 21) & 0x3f) << 5 | (ctx->opcode & 0x1f)); - /* The extended opcodes cleverly reuse the opcodes from their 16-bit - counterparts. */ + /* + * The extended opcodes cleverly reuse the opcodes from their 16-bit + * counterparts. + */ switch (op) { case M16_OPC_ADDIUSP: gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm); @@ -14099,7 +14173,8 @@ static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx) if (is_uhi(extract32(ctx->opcode, 5, 6))) { gen_helper_do_semihosting(cpu_env); } else { - /* XXX: not clear which exception should be raised + /* + * XXX: not clear which exception should be raised * when in debug mode... */ check_insn(ctx, ISA_MIPS32); @@ -14407,8 +14482,10 @@ enum { /* POOL32A encoding of minor opcode field */ enum { - /* These opcodes are distinguished only by bits 9..6; those bits are - * what are recorded below. */ + /* + * These opcodes are distinguished only by bits 9..6; those bits are + * what are recorded below. + */ SLL32 = 0x0, SRL32 = 0x1, SRA = 0x2, @@ -15056,8 +15133,10 @@ static void gen_pool16c_insn(DisasContext *ctx) { int reg = ctx->opcode & 0x1f; gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0); - /* Let normal delay slot handling in our caller take us - to the branch target. */ + /* + * Let normal delay slot handling in our caller take us + * to the branch target. + */ } break; case JALR16 + 0: @@ -15085,7 +15164,8 @@ static void gen_pool16c_insn(DisasContext *ctx) if (is_uhi(extract32(ctx->opcode, 0, 4))) { gen_helper_do_semihosting(cpu_env); } else { - /* XXX: not clear which exception should be raised + /* + * XXX: not clear which exception should be raised * when in debug mode... */ check_insn(ctx, ISA_MIPS32); @@ -15098,8 +15178,10 @@ static void gen_pool16c_insn(DisasContext *ctx) int imm = ZIMM(ctx->opcode, 0, 5); gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0); gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2); - /* Let normal delay slot handling in our caller take us - to the branch target. */ + /* + * Let normal delay slot handling in our caller take us + * to the branch target. + */ } break; default: @@ -15595,8 +15677,10 @@ static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs) save_cpu_state(ctx, 1); gen_helper_ei(t0, cpu_env); gen_store_gpr(t0, rs); - /* DISAS_STOP isn't sufficient, we need to ensure we break out - of translated code to check for pending interrupts. */ + /* + * DISAS_STOP isn't sufficient, we need to ensure we break out + * of translated code to check for pending interrupts. + */ gen_save_pc(ctx->base.pc_next + 4); ctx->base.is_jmp = DISAS_EXIT; tcg_temp_free(t0); @@ -15676,9 +15760,10 @@ static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs) } } -/* Values for microMIPS fmt field. Variable-width, depending on which - formats the instruction supports. */ - +/* + * Values for microMIPS fmt field. Variable-width, depending on which + * formats the instruction supports. + */ enum { FMT_SD_S = 0, FMT_SD_D = 1, @@ -16751,8 +16836,10 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx) case TNEI: /* SYNCI */ if (ctx->insn_flags & ISA_MIPS32R6) { /* SYNCI */ - /* Break the TB to be able to sync copied instructions - immediately */ + /* + * Break the TB to be able to sync copied instructions + * immediately. + */ ctx->base.is_jmp = DISAS_STOP; } else { /* TNEI */ @@ -16772,9 +16859,11 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx) check_insn_opc_removed(ctx, ISA_MIPS32R6); gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ, 4, rs, 0, imm << 1, 0); - /* Compact branches don't have a delay slot, so just let - the normal delay slot handling take us to the branch - target. */ + /* + * Compact branches don't have a delay slot, so just let + * the normal delay slot handling take us to the branch + * target. + */ break; case LUI: check_insn_opc_removed(ctx, ISA_MIPS32R6); @@ -16782,8 +16871,10 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx) break; case SYNCI: check_insn_opc_removed(ctx, ISA_MIPS32R6); - /* Break the TB to be able to sync copied instructions - immediately */ + /* + * Break the TB to be able to sync copied instructions + * immediately. + */ ctx->base.is_jmp = DISAS_STOP; break; case BC2F: @@ -17358,7 +17449,8 @@ static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx) break; } if (ctx->insn_flags & ISA_MIPS32R6) { - /* In the Release 6 the register number location in + /* + * In the Release 6, the register number location in * the instruction encoding has changed. */ gen_arith(ctx, opc, rs1, rd, rs2); @@ -21083,9 +21175,11 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx) gen_p_lsx(ctx, rd, rs, rt); break; case NM_LSA: - /* In nanoMIPS, the shift field directly encodes the shift + /* + * In nanoMIPS, the shift field directly encodes the shift * amount, meaning that the supported shift values are in - * the range 0 to 3 (instead of 1 to 4 in MIPSR6). */ + * the range 0 to 3 (instead of 1 to 4 in MIPSR6). + */ gen_lsa(ctx, OPC_LSA, rd, rs, rt, extract32(ctx->opcode, 9, 2) - 1); break; @@ -21440,8 +21534,10 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx) case NM_P_PREFU12: if (rt == 31) { /* SYNCI */ - /* Break the TB to be able to sync copied instructions - immediately */ + /* + * Break the TB to be able to sync copied instructions + * immediately. + */ ctx->base.is_jmp = DISAS_STOP; } else { /* PREF */ @@ -21537,8 +21633,10 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx) case NM_P_PREFS9: if (rt == 31) { /* SYNCI */ - /* Break the TB to be able to sync copied instructions - immediately */ + /* + * Break the TB to be able to sync copied instructions + * immediately. + */ ctx->base.is_jmp = DISAS_STOP; } else { /* PREF */ @@ -21630,8 +21728,10 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx) /* case NM_SYNCIE */ check_eva(ctx); check_cp0_enabled(ctx); - /* Break the TB to be able to sync copied instructions - immediately */ + /* + * Break the TB to be able to sync copied instructions + * immediately. + */ ctx->base.is_jmp = DISAS_STOP; } else { /* case NM_PREFE */ @@ -23026,8 +23126,10 @@ static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2, gen_load_gpr(v2_t, v2); switch (op1) { - /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have - * the same mask and op1. */ + /* + * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have + * the same mask and op1. + */ case OPC_MULT_G_2E: check_dsp_r2(ctx); switch (op2) { @@ -23996,8 +24098,10 @@ static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx) case R6_OPC_CLO: case R6_OPC_CLZ: if (rt == 0 && sa == 1) { - /* Major opcode and function field is shared with preR6 MFHI/MTHI. - We need additionally to check other fields */ + /* + * Major opcode and function field is shared with preR6 MFHI/MTHI. + * We need additionally to check other fields. + */ gen_cl(ctx, op1, rd, rs); } else { generate_exception_end(ctx, EXCP_RI); @@ -24022,8 +24126,10 @@ static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx) case R6_OPC_DCLO: case R6_OPC_DCLZ: if (rt == 0 && sa == 1) { - /* Major opcode and function field is shared with preR6 MFHI/MTHI. - We need additionally to check other fields */ + /* + * Major opcode and function field is shared with preR6 MFHI/MTHI. + * We need additionally to check other fields. + */ check_mips_64(ctx); gen_cl(ctx, op1, rd, rs); } else { @@ -25939,7 +26045,7 @@ static void decode_opc_mxu__pool07(CPUMIPSState *env, DisasContext *ctx) * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL08| * +-----------+---------+-+-------------------+-------+-----------+ * -*/ + */ static void decode_opc_mxu__pool08(CPUMIPSState *env, DisasContext *ctx) { uint32_t opcode = extract32(ctx->opcode, 20, 1); @@ -26835,7 +26941,8 @@ static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx) if (is_uhi(extract32(ctx->opcode, 6, 20))) { gen_helper_do_semihosting(cpu_env); } else { - /* XXX: not clear which exception should be raised + /* + * XXX: not clear which exception should be raised * when in debug mode... */ check_insn(ctx, ISA_MIPS32); @@ -26977,8 +27084,10 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx) case OPC_MODU_G_2E: case OPC_MULT_G_2E: case OPC_MULTU_G_2E: - /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have - * the same mask and op1. */ + /* + * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have + * the same mask and op1. + */ if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) { op2 = MASK_ADDUH_QB(ctx->opcode); switch (op2) { @@ -29165,8 +29274,10 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) break; case OPC_SYNCI: check_insn(ctx, ISA_MIPS32R2); - /* Break the TB to be able to sync copied instructions - immediately */ + /* + * Break the TB to be able to sync copied instructions + * immediately. + */ ctx->base.is_jmp = DISAS_STOP; break; case OPC_BPOSGE32: /* MIPS DSP branch */ @@ -29283,8 +29394,10 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) save_cpu_state(ctx, 1); gen_helper_di(t0, cpu_env); gen_store_gpr(t0, rt); - /* Stop translation as we may have switched - the execution mode. */ + /* + * Stop translation as we may have switched + * the execution mode. + */ ctx->base.is_jmp = DISAS_STOP; break; case OPC_EI: @@ -29292,8 +29405,10 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) save_cpu_state(ctx, 1); gen_helper_ei(t0, cpu_env); gen_store_gpr(t0, rt); - /* DISAS_STOP isn't sufficient, we need to ensure we break - out of translated code to check for pending interrupts */ + /* + * DISAS_STOP isn't sufficient, we need to ensure we break + * out of translated code to check for pending interrupts. + */ gen_save_pc(ctx->base.pc_next + 4); ctx->base.is_jmp = DISAS_EXIT; break; @@ -29876,10 +29991,12 @@ static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, save_cpu_state(ctx, 1); ctx->base.is_jmp = DISAS_NORETURN; gen_helper_raise_exception_debug(cpu_env); - /* The address covered by the breakpoint must be included in - [tb->pc, tb->pc + tb->size) in order to for it to be - properly cleared -- thus we increment the PC here so that - the logic setting tb->size below does the right thing. */ + /* + * The address covered by the breakpoint must be included in + * [tb->pc, tb->pc + tb->size) in order to for it to be + * properly cleared -- thus we increment the PC here so that + * the logic setting tb->size below does the right thing. + */ ctx->base.pc_next += 4; return true; } @@ -29914,14 +30031,18 @@ static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) if (ctx->hflags & MIPS_HFLAG_BMASK) { if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 | MIPS_HFLAG_FBNSLOT))) { - /* force to generate branch as there is neither delay nor - forbidden slot */ + /* + * Force to generate branch as there is neither delay nor + * forbidden slot. + */ is_slot = 1; } if ((ctx->hflags & MIPS_HFLAG_M16) && (ctx->hflags & MIPS_HFLAG_FBNSLOT)) { - /* Force to generate branch as microMIPS R6 doesn't restrict - branches in the forbidden slot. */ + /* + * Force to generate branch as microMIPS R6 doesn't restrict + * branches in the forbidden slot. + */ is_slot = 1; } } @@ -29933,10 +30054,12 @@ static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) if (ctx->base.is_jmp != DISAS_NEXT) { return; } - /* Execute a branch and its delay slot as a single instruction. - This is what GDB expects and is consistent with what the - hardware does (e.g. if a delay slot instruction faults, the - reported PC is the PC of the branch). */ + /* + * Execute a branch and its delay slot as a single instruction. + * This is what GDB expects and is consistent with what the + * hardware does (e.g. if a delay slot instruction faults, the + * reported PC is the PC of the branch). + */ if (ctx->base.singlestep_enabled && (ctx->hflags & MIPS_HFLAG_BMASK) == 0) { ctx->base.is_jmp = DISAS_TOO_MANY; @@ -30088,8 +30211,10 @@ void mips_tcg_init(void) int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]); msa_wr_d[i * 2] = tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]); - /* The scalar floating-point unit (FPU) registers are mapped on - * the MSA vector registers. */ + /* + * The scalar floating-point unit (FPU) registers are mapped on + * the MSA vector registers. + */ fpu_f64[i] = msa_wr_d[i * 2]; off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]); msa_wr_d[i * 2 + 1] = @@ -30247,8 +30372,10 @@ void cpu_state_reset(CPUMIPSState *env) /* Enable 64-bit address mode. */ env->CP0_Status |= (1 << CP0St_UX); # endif - /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR - hardware registers. */ + /* + * Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR + * hardware registers. + */ env->CP0_HWREna |= 0x0000000F; if (env->CP0_Config1 & (1 << CP0C1_FP)) { env->CP0_Status |= (1 << CP0St_CU1); @@ -30265,8 +30392,10 @@ void cpu_state_reset(CPUMIPSState *env) # endif #else if (env->hflags & MIPS_HFLAG_BMASK) { - /* If the exception was raised from a delay slot, - come back to the jump. */ + /* + * If the exception was raised from a delay slot, + * come back to the jump. + */ env->CP0_ErrorEPC = (env->active_tc.PC - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4)); } else { @@ -30289,8 +30418,10 @@ void cpu_state_reset(CPUMIPSState *env) env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ? 0x3ff : 0xff; env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL); - /* vectored interrupts not implemented, timer on int 7, - no performance counters. */ + /* + * Vectored interrupts not implemented, timer on int 7, + * no performance counters. + */ env->CP0_IntCtl = 0xe0000000; { int i; diff --git a/target/nios2/monitor.c b/target/nios2/monitor.c index d5e3393716..6646836df5 100644 --- a/target/nios2/monitor.c +++ b/target/nios2/monitor.c @@ -25,7 +25,7 @@ #include "cpu.h" #include "monitor/monitor.h" #include "monitor/hmp-target.h" -#include "hmp.h" +#include "monitor/hmp.h" void hmp_info_tlb(Monitor *mon, const QDict *qdict) { diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c index ffbd19afa1..f437c88aad 100644 --- a/target/ppc/fpu_helper.c +++ b/target/ppc/fpu_helper.c @@ -1801,37 +1801,35 @@ uint32_t helper_efdcmpeq(CPUPPCState *env, uint64_t op1, uint64_t op2) * sfprf - set FPRF */ #define VSX_ADD_SUB(name, op, nels, tp, fld, sfprf, r2sp) \ -void helper_##name(CPUPPCState *env, uint32_t opcode) \ +void helper_##name(CPUPPCState *env, ppc_vsr_t *xt, \ + ppc_vsr_t *xa, ppc_vsr_t *xb) \ { \ - ppc_vsr_t xt, xa, xb; \ + ppc_vsr_t t = *xt; \ int i; \ \ - getVSR(xA(opcode), &xa, env); \ - getVSR(xB(opcode), &xb, env); \ - getVSR(xT(opcode), &xt, env); \ helper_reset_fpstatus(env); \ \ for (i = 0; i < nels; i++) { \ float_status tstat = env->fp_status; \ set_float_exception_flags(0, &tstat); \ - xt.fld = tp##_##op(xa.fld, xb.fld, &tstat); \ + t.fld = tp##_##op(xa->fld, xb->fld, &tstat); \ env->fp_status.float_exception_flags |= tstat.float_exception_flags; \ \ if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \ float_invalid_op_addsub(env, sfprf, GETPC(), \ - tp##_classify(xa.fld) | \ - tp##_classify(xb.fld)); \ + tp##_classify(xa->fld) | \ + tp##_classify(xb->fld)); \ } \ \ if (r2sp) { \ - xt.fld = helper_frsp(env, xt.fld); \ + t.fld = helper_frsp(env, t.fld); \ } \ \ if (sfprf) { \ - helper_compute_fprf_float64(env, xt.fld); \ + helper_compute_fprf_float64(env, t.fld); \ } \ } \ - putVSR(xT(opcode), &xt, env); \ + *xt = t; \ do_float_check_status(env, GETPC()); \ } @@ -1844,14 +1842,12 @@ VSX_ADD_SUB(xssubsp, sub, 1, float64, VsrD(0), 1, 1) VSX_ADD_SUB(xvsubdp, sub, 2, float64, VsrD(i), 0, 0) VSX_ADD_SUB(xvsubsp, sub, 4, float32, VsrW(i), 0, 0) -void helper_xsaddqp(CPUPPCState *env, uint32_t opcode) +void helper_xsaddqp(CPUPPCState *env, uint32_t opcode, + ppc_vsr_t *xt, ppc_vsr_t *xa, ppc_vsr_t *xb) { - ppc_vsr_t xt, xa, xb; + ppc_vsr_t t = *xt; float_status tstat; - getVSR(rA(opcode) + 32, &xa, env); - getVSR(rB(opcode) + 32, &xb, env); - getVSR(rD(opcode) + 32, &xt, env); helper_reset_fpstatus(env); tstat = env->fp_status; @@ -1860,18 +1856,18 @@ void helper_xsaddqp(CPUPPCState *env, uint32_t opcode) } set_float_exception_flags(0, &tstat); - xt.f128 = float128_add(xa.f128, xb.f128, &tstat); + t.f128 = float128_add(xa->f128, xb->f128, &tstat); env->fp_status.float_exception_flags |= tstat.float_exception_flags; if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { float_invalid_op_addsub(env, 1, GETPC(), - float128_classify(xa.f128) | - float128_classify(xb.f128)); + float128_classify(xa->f128) | + float128_classify(xb->f128)); } - helper_compute_fprf_float128(env, xt.f128); + helper_compute_fprf_float128(env, t.f128); - putVSR(rD(opcode) + 32, &xt, env); + *xt = t; do_float_check_status(env, GETPC()); } @@ -1884,38 +1880,36 @@ void helper_xsaddqp(CPUPPCState *env, uint32_t opcode) * sfprf - set FPRF */ #define VSX_MUL(op, nels, tp, fld, sfprf, r2sp) \ -void helper_##op(CPUPPCState *env, uint32_t opcode) \ +void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, \ + ppc_vsr_t *xa, ppc_vsr_t *xb) \ { \ - ppc_vsr_t xt, xa, xb; \ + ppc_vsr_t t = *xt; \ int i; \ \ - getVSR(xA(opcode), &xa, env); \ - getVSR(xB(opcode), &xb, env); \ - getVSR(xT(opcode), &xt, env); \ helper_reset_fpstatus(env); \ \ for (i = 0; i < nels; i++) { \ float_status tstat = env->fp_status; \ set_float_exception_flags(0, &tstat); \ - xt.fld = tp##_mul(xa.fld, xb.fld, &tstat); \ + t.fld = tp##_mul(xa->fld, xb->fld, &tstat); \ env->fp_status.float_exception_flags |= tstat.float_exception_flags; \ \ if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \ float_invalid_op_mul(env, sfprf, GETPC(), \ - tp##_classify(xa.fld) | \ - tp##_classify(xb.fld)); \ + tp##_classify(xa->fld) | \ + tp##_classify(xb->fld)); \ } \ \ if (r2sp) { \ - xt.fld = helper_frsp(env, xt.fld); \ + t.fld = helper_frsp(env, t.fld); \ } \ \ if (sfprf) { \ - helper_compute_fprf_float64(env, xt.fld); \ + helper_compute_fprf_float64(env, t.fld); \ } \ } \ \ - putVSR(xT(opcode), &xt, env); \ + *xt = t; \ do_float_check_status(env, GETPC()); \ } @@ -1924,15 +1918,12 @@ VSX_MUL(xsmulsp, 1, float64, VsrD(0), 1, 1) VSX_MUL(xvmuldp, 2, float64, VsrD(i), 0, 0) VSX_MUL(xvmulsp, 4, float32, VsrW(i), 0, 0) -void helper_xsmulqp(CPUPPCState *env, uint32_t opcode) +void helper_xsmulqp(CPUPPCState *env, uint32_t opcode, + ppc_vsr_t *xt, ppc_vsr_t *xa, ppc_vsr_t *xb) { - ppc_vsr_t xt, xa, xb; + ppc_vsr_t t = *xt; float_status tstat; - getVSR(rA(opcode) + 32, &xa, env); - getVSR(rB(opcode) + 32, &xb, env); - getVSR(rD(opcode) + 32, &xt, env); - helper_reset_fpstatus(env); tstat = env->fp_status; if (unlikely(Rc(opcode) != 0)) { @@ -1940,17 +1931,17 @@ void helper_xsmulqp(CPUPPCState *env, uint32_t opcode) } set_float_exception_flags(0, &tstat); - xt.f128 = float128_mul(xa.f128, xb.f128, &tstat); + t.f128 = float128_mul(xa->f128, xb->f128, &tstat); env->fp_status.float_exception_flags |= tstat.float_exception_flags; if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { float_invalid_op_mul(env, 1, GETPC(), - float128_classify(xa.f128) | - float128_classify(xb.f128)); + float128_classify(xa->f128) | + float128_classify(xb->f128)); } - helper_compute_fprf_float128(env, xt.f128); + helper_compute_fprf_float128(env, t.f128); - putVSR(rD(opcode) + 32, &xt, env); + *xt = t; do_float_check_status(env, GETPC()); } @@ -1963,41 +1954,39 @@ void helper_xsmulqp(CPUPPCState *env, uint32_t opcode) * sfprf - set FPRF */ #define VSX_DIV(op, nels, tp, fld, sfprf, r2sp) \ -void helper_##op(CPUPPCState *env, uint32_t opcode) \ +void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, \ + ppc_vsr_t *xa, ppc_vsr_t *xb) \ { \ - ppc_vsr_t xt, xa, xb; \ + ppc_vsr_t t = *xt; \ int i; \ \ - getVSR(xA(opcode), &xa, env); \ - getVSR(xB(opcode), &xb, env); \ - getVSR(xT(opcode), &xt, env); \ helper_reset_fpstatus(env); \ \ for (i = 0; i < nels; i++) { \ float_status tstat = env->fp_status; \ set_float_exception_flags(0, &tstat); \ - xt.fld = tp##_div(xa.fld, xb.fld, &tstat); \ + t.fld = tp##_div(xa->fld, xb->fld, &tstat); \ env->fp_status.float_exception_flags |= tstat.float_exception_flags; \ \ if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \ float_invalid_op_div(env, sfprf, GETPC(), \ - tp##_classify(xa.fld) | \ - tp##_classify(xb.fld)); \ + tp##_classify(xa->fld) | \ + tp##_classify(xb->fld)); \ } \ if (unlikely(tstat.float_exception_flags & float_flag_divbyzero)) { \ float_zero_divide_excp(env, GETPC()); \ } \ \ if (r2sp) { \ - xt.fld = helper_frsp(env, xt.fld); \ + t.fld = helper_frsp(env, t.fld); \ } \ \ if (sfprf) { \ - helper_compute_fprf_float64(env, xt.fld); \ + helper_compute_fprf_float64(env, t.fld); \ } \ } \ \ - putVSR(xT(opcode), &xt, env); \ + *xt = t; \ do_float_check_status(env, GETPC()); \ } @@ -2006,15 +1995,12 @@ VSX_DIV(xsdivsp, 1, float64, VsrD(0), 1, 1) VSX_DIV(xvdivdp, 2, float64, VsrD(i), 0, 0) VSX_DIV(xvdivsp, 4, float32, VsrW(i), 0, 0) -void helper_xsdivqp(CPUPPCState *env, uint32_t opcode) +void helper_xsdivqp(CPUPPCState *env, uint32_t opcode, + ppc_vsr_t *xt, ppc_vsr_t *xa, ppc_vsr_t *xb) { - ppc_vsr_t xt, xa, xb; + ppc_vsr_t t = *xt; float_status tstat; - getVSR(rA(opcode) + 32, &xa, env); - getVSR(rB(opcode) + 32, &xb, env); - getVSR(rD(opcode) + 32, &xt, env); - helper_reset_fpstatus(env); tstat = env->fp_status; if (unlikely(Rc(opcode) != 0)) { @@ -2022,20 +2008,20 @@ void helper_xsdivqp(CPUPPCState *env, uint32_t opcode) } set_float_exception_flags(0, &tstat); - xt.f128 = float128_div(xa.f128, xb.f128, &tstat); + t.f128 = float128_div(xa->f128, xb->f128, &tstat); env->fp_status.float_exception_flags |= tstat.float_exception_flags; if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { float_invalid_op_div(env, 1, GETPC(), - float128_classify(xa.f128) | - float128_classify(xb.f128)); + float128_classify(xa->f128) | + float128_classify(xb->f128)); } if (unlikely(tstat.float_exception_flags & float_flag_divbyzero)) { float_zero_divide_excp(env, GETPC()); } - helper_compute_fprf_float128(env, xt.f128); - putVSR(rD(opcode) + 32, &xt, env); + helper_compute_fprf_float128(env, t.f128); + *xt = t; do_float_check_status(env, GETPC()); } @@ -2048,31 +2034,29 @@ void helper_xsdivqp(CPUPPCState *env, uint32_t opcode) * sfprf - set FPRF */ #define VSX_RE(op, nels, tp, fld, sfprf, r2sp) \ -void helper_##op(CPUPPCState *env, uint32_t opcode) \ +void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \ { \ - ppc_vsr_t xt, xb; \ + ppc_vsr_t t = *xt; \ int i; \ \ - getVSR(xB(opcode), &xb, env); \ - getVSR(xT(opcode), &xt, env); \ helper_reset_fpstatus(env); \ \ for (i = 0; i < nels; i++) { \ - if (unlikely(tp##_is_signaling_nan(xb.fld, &env->fp_status))) { \ + if (unlikely(tp##_is_signaling_nan(xb->fld, &env->fp_status))) { \ float_invalid_op_vxsnan(env, GETPC()); \ } \ - xt.fld = tp##_div(tp##_one, xb.fld, &env->fp_status); \ + t.fld = tp##_div(tp##_one, xb->fld, &env->fp_status); \ \ if (r2sp) { \ - xt.fld = helper_frsp(env, xt.fld); \ + t.fld = helper_frsp(env, t.fld); \ } \ \ if (sfprf) { \ - helper_compute_fprf_float64(env, xt.fld); \ + helper_compute_fprf_float64(env, t.fld); \ } \ } \ \ - putVSR(xT(opcode), &xt, env); \ + *xt = t; \ do_float_check_status(env, GETPC()); \ } @@ -2090,39 +2074,37 @@ VSX_RE(xvresp, 4, float32, VsrW(i), 0, 0) * sfprf - set FPRF */ #define VSX_SQRT(op, nels, tp, fld, sfprf, r2sp) \ -void helper_##op(CPUPPCState *env, uint32_t opcode) \ +void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \ { \ - ppc_vsr_t xt, xb; \ + ppc_vsr_t t = *xt; \ int i; \ \ - getVSR(xB(opcode), &xb, env); \ - getVSR(xT(opcode), &xt, env); \ helper_reset_fpstatus(env); \ \ for (i = 0; i < nels; i++) { \ float_status tstat = env->fp_status; \ set_float_exception_flags(0, &tstat); \ - xt.fld = tp##_sqrt(xb.fld, &tstat); \ + t.fld = tp##_sqrt(xb->fld, &tstat); \ env->fp_status.float_exception_flags |= tstat.float_exception_flags; \ \ if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \ - if (tp##_is_neg(xb.fld) && !tp##_is_zero(xb.fld)) { \ + if (tp##_is_neg(xb->fld) && !tp##_is_zero(xb->fld)) { \ float_invalid_op_vxsqrt(env, sfprf, GETPC()); \ - } else if (tp##_is_signaling_nan(xb.fld, &tstat)) { \ + } else if (tp##_is_signaling_nan(xb->fld, &tstat)) { \ float_invalid_op_vxsnan(env, GETPC()); \ } \ } \ \ if (r2sp) { \ - xt.fld = helper_frsp(env, xt.fld); \ + t.fld = helper_frsp(env, t.fld); \ } \ \ if (sfprf) { \ - helper_compute_fprf_float64(env, xt.fld); \ + helper_compute_fprf_float64(env, t.fld); \ } \ } \ \ - putVSR(xT(opcode), &xt, env); \ + *xt = t; \ do_float_check_status(env, GETPC()); \ } @@ -2140,40 +2122,38 @@ VSX_SQRT(xvsqrtsp, 4, float32, VsrW(i), 0, 0) * sfprf - set FPRF */ #define VSX_RSQRTE(op, nels, tp, fld, sfprf, r2sp) \ -void helper_##op(CPUPPCState *env, uint32_t opcode) \ +void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \ { \ - ppc_vsr_t xt, xb; \ + ppc_vsr_t t = *xt; \ int i; \ \ - getVSR(xB(opcode), &xb, env); \ - getVSR(xT(opcode), &xt, env); \ helper_reset_fpstatus(env); \ \ for (i = 0; i < nels; i++) { \ float_status tstat = env->fp_status; \ set_float_exception_flags(0, &tstat); \ - xt.fld = tp##_sqrt(xb.fld, &tstat); \ - xt.fld = tp##_div(tp##_one, xt.fld, &tstat); \ + t.fld = tp##_sqrt(xb->fld, &tstat); \ + t.fld = tp##_div(tp##_one, t.fld, &tstat); \ env->fp_status.float_exception_flags |= tstat.float_exception_flags; \ \ if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \ - if (tp##_is_neg(xb.fld) && !tp##_is_zero(xb.fld)) { \ + if (tp##_is_neg(xb->fld) && !tp##_is_zero(xb->fld)) { \ float_invalid_op_vxsqrt(env, sfprf, GETPC()); \ - } else if (tp##_is_signaling_nan(xb.fld, &tstat)) { \ + } else if (tp##_is_signaling_nan(xb->fld, &tstat)) { \ float_invalid_op_vxsnan(env, GETPC()); \ } \ } \ \ if (r2sp) { \ - xt.fld = helper_frsp(env, xt.fld); \ + t.fld = helper_frsp(env, t.fld); \ } \ \ if (sfprf) { \ - helper_compute_fprf_float64(env, xt.fld); \ + helper_compute_fprf_float64(env, t.fld); \ } \ } \ \ - putVSR(xT(opcode), &xt, env); \ + *xt = t; \ do_float_check_status(env, GETPC()); \ } @@ -2193,39 +2173,36 @@ VSX_RSQRTE(xvrsqrtesp, 4, float32, VsrW(i), 0, 0) * nbits - number of fraction bits */ #define VSX_TDIV(op, nels, tp, fld, emin, emax, nbits) \ -void helper_##op(CPUPPCState *env, uint32_t opcode) \ +void helper_##op(CPUPPCState *env, uint32_t opcode, \ + ppc_vsr_t *xa, ppc_vsr_t *xb) \ { \ - ppc_vsr_t xa, xb; \ int i; \ int fe_flag = 0; \ int fg_flag = 0; \ \ - getVSR(xA(opcode), &xa, env); \ - getVSR(xB(opcode), &xb, env); \ - \ for (i = 0; i < nels; i++) { \ - if (unlikely(tp##_is_infinity(xa.fld) || \ - tp##_is_infinity(xb.fld) || \ - tp##_is_zero(xb.fld))) { \ + if (unlikely(tp##_is_infinity(xa->fld) || \ + tp##_is_infinity(xb->fld) || \ + tp##_is_zero(xb->fld))) { \ fe_flag = 1; \ fg_flag = 1; \ } else { \ - int e_a = ppc_##tp##_get_unbiased_exp(xa.fld); \ - int e_b = ppc_##tp##_get_unbiased_exp(xb.fld); \ + int e_a = ppc_##tp##_get_unbiased_exp(xa->fld); \ + int e_b = ppc_##tp##_get_unbiased_exp(xb->fld); \ \ - if (unlikely(tp##_is_any_nan(xa.fld) || \ - tp##_is_any_nan(xb.fld))) { \ + if (unlikely(tp##_is_any_nan(xa->fld) || \ + tp##_is_any_nan(xb->fld))) { \ fe_flag = 1; \ } else if ((e_b <= emin) || (e_b >= (emax - 2))) { \ fe_flag = 1; \ - } else if (!tp##_is_zero(xa.fld) && \ + } else if (!tp##_is_zero(xa->fld) && \ (((e_a - e_b) >= emax) || \ ((e_a - e_b) <= (emin + 1)) || \ (e_a <= (emin + nbits)))) { \ fe_flag = 1; \ } \ \ - if (unlikely(tp##_is_zero_or_denormal(xb.fld))) { \ + if (unlikely(tp##_is_zero_or_denormal(xb->fld))) { \ /* \ * XB is not zero because of the above check and so \ * must be denormalized. \ @@ -2253,36 +2230,32 @@ VSX_TDIV(xvtdivsp, 4, float32, VsrW(i), -126, 127, 23) * nbits - number of fraction bits */ #define VSX_TSQRT(op, nels, tp, fld, emin, nbits) \ -void helper_##op(CPUPPCState *env, uint32_t opcode) \ +void helper_##op(CPUPPCState *env, uint32_t opcode, ppc_vsr_t *xb) \ { \ - ppc_vsr_t xa, xb; \ int i; \ int fe_flag = 0; \ int fg_flag = 0; \ \ - getVSR(xA(opcode), &xa, env); \ - getVSR(xB(opcode), &xb, env); \ - \ for (i = 0; i < nels; i++) { \ - if (unlikely(tp##_is_infinity(xb.fld) || \ - tp##_is_zero(xb.fld))) { \ + if (unlikely(tp##_is_infinity(xb->fld) || \ + tp##_is_zero(xb->fld))) { \ fe_flag = 1; \ fg_flag = 1; \ } else { \ - int e_b = ppc_##tp##_get_unbiased_exp(xb.fld); \ + int e_b = ppc_##tp##_get_unbiased_exp(xb->fld); \ \ - if (unlikely(tp##_is_any_nan(xb.fld))) { \ + if (unlikely(tp##_is_any_nan(xb->fld))) { \ fe_flag = 1; \ - } else if (unlikely(tp##_is_zero(xb.fld))) { \ + } else if (unlikely(tp##_is_zero(xb->fld))) { \ fe_flag = 1; \ - } else if (unlikely(tp##_is_neg(xb.fld))) { \ + } else if (unlikely(tp##_is_neg(xb->fld))) { \ fe_flag = 1; \ - } else if (!tp##_is_zero(xb.fld) && \ + } else if (!tp##_is_zero(xb->fld) && \ (e_b <= (emin + nbits))) { \ fe_flag = 1; \ } \ \ - if (unlikely(tp##_is_zero_or_denormal(xb.fld))) { \ + if (unlikely(tp##_is_zero_or_denormal(xb->fld))) { \ /* \ * XB is not zero because of the above check and \ * therefore must be denormalized. \ @@ -2307,30 +2280,15 @@ VSX_TSQRT(xvtsqrtsp, 4, float32, VsrW(i), -126, 23) * fld - vsr_t field (VsrD(*) or VsrW(*)) * maddflgs - flags for the float*muladd routine that control the * various forms (madd, msub, nmadd, nmsub) - * afrm - A form (1=A, 0=M) * sfprf - set FPRF */ -#define VSX_MADD(op, nels, tp, fld, maddflgs, afrm, sfprf, r2sp) \ -void helper_##op(CPUPPCState *env, uint32_t opcode) \ +#define VSX_MADD(op, nels, tp, fld, maddflgs, sfprf, r2sp) \ +void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, \ + ppc_vsr_t *xa, ppc_vsr_t *b, ppc_vsr_t *c) \ { \ - ppc_vsr_t xt_in, xa, xb, xt_out; \ - ppc_vsr_t *b, *c; \ + ppc_vsr_t t = *xt; \ int i; \ \ - if (afrm) { /* AxB + T */ \ - b = &xb; \ - c = &xt_in; \ - } else { /* AxT + B */ \ - b = &xt_in; \ - c = &xb; \ - } \ - \ - getVSR(xA(opcode), &xa, env); \ - getVSR(xB(opcode), &xb, env); \ - getVSR(xT(opcode), &xt_in, env); \ - \ - xt_out = xt_in; \ - \ helper_reset_fpstatus(env); \ \ for (i = 0; i < nels; i++) { \ @@ -2342,68 +2300,51 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \ * result to odd. \ */ \ set_float_rounding_mode(float_round_to_zero, &tstat); \ - xt_out.fld = tp##_muladd(xa.fld, b->fld, c->fld, \ - maddflgs, &tstat); \ - xt_out.fld |= (get_float_exception_flags(&tstat) & \ - float_flag_inexact) != 0; \ + t.fld = tp##_muladd(xa->fld, b->fld, c->fld, \ + maddflgs, &tstat); \ + t.fld |= (get_float_exception_flags(&tstat) & \ + float_flag_inexact) != 0; \ } else { \ - xt_out.fld = tp##_muladd(xa.fld, b->fld, c->fld, \ - maddflgs, &tstat); \ + t.fld = tp##_muladd(xa->fld, b->fld, c->fld, \ + maddflgs, &tstat); \ } \ env->fp_status.float_exception_flags |= tstat.float_exception_flags; \ \ if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \ - tp##_maddsub_update_excp(env, xa.fld, b->fld, \ + tp##_maddsub_update_excp(env, xa->fld, b->fld, \ c->fld, maddflgs, GETPC()); \ } \ \ if (r2sp) { \ - xt_out.fld = helper_frsp(env, xt_out.fld); \ + t.fld = helper_frsp(env, t.fld); \ } \ \ if (sfprf) { \ - helper_compute_fprf_float64(env, xt_out.fld); \ + helper_compute_fprf_float64(env, t.fld); \ } \ } \ - putVSR(xT(opcode), &xt_out, env); \ + *xt = t; \ do_float_check_status(env, GETPC()); \ } -VSX_MADD(xsmaddadp, 1, float64, VsrD(0), MADD_FLGS, 1, 1, 0) -VSX_MADD(xsmaddmdp, 1, float64, VsrD(0), MADD_FLGS, 0, 1, 0) -VSX_MADD(xsmsubadp, 1, float64, VsrD(0), MSUB_FLGS, 1, 1, 0) -VSX_MADD(xsmsubmdp, 1, float64, VsrD(0), MSUB_FLGS, 0, 1, 0) -VSX_MADD(xsnmaddadp, 1, float64, VsrD(0), NMADD_FLGS, 1, 1, 0) -VSX_MADD(xsnmaddmdp, 1, float64, VsrD(0), NMADD_FLGS, 0, 1, 0) -VSX_MADD(xsnmsubadp, 1, float64, VsrD(0), NMSUB_FLGS, 1, 1, 0) -VSX_MADD(xsnmsubmdp, 1, float64, VsrD(0), NMSUB_FLGS, 0, 1, 0) - -VSX_MADD(xsmaddasp, 1, float64, VsrD(0), MADD_FLGS, 1, 1, 1) -VSX_MADD(xsmaddmsp, 1, float64, VsrD(0), MADD_FLGS, 0, 1, 1) -VSX_MADD(xsmsubasp, 1, float64, VsrD(0), MSUB_FLGS, 1, 1, 1) -VSX_MADD(xsmsubmsp, 1, float64, VsrD(0), MSUB_FLGS, 0, 1, 1) -VSX_MADD(xsnmaddasp, 1, float64, VsrD(0), NMADD_FLGS, 1, 1, 1) -VSX_MADD(xsnmaddmsp, 1, float64, VsrD(0), NMADD_FLGS, 0, 1, 1) -VSX_MADD(xsnmsubasp, 1, float64, VsrD(0), NMSUB_FLGS, 1, 1, 1) -VSX_MADD(xsnmsubmsp, 1, float64, VsrD(0), NMSUB_FLGS, 0, 1, 1) - -VSX_MADD(xvmaddadp, 2, float64, VsrD(i), MADD_FLGS, 1, 0, 0) -VSX_MADD(xvmaddmdp, 2, float64, VsrD(i), MADD_FLGS, 0, 0, 0) -VSX_MADD(xvmsubadp, 2, float64, VsrD(i), MSUB_FLGS, 1, 0, 0) -VSX_MADD(xvmsubmdp, 2, float64, VsrD(i), MSUB_FLGS, 0, 0, 0) -VSX_MADD(xvnmaddadp, 2, float64, VsrD(i), NMADD_FLGS, 1, 0, 0) -VSX_MADD(xvnmaddmdp, 2, float64, VsrD(i), NMADD_FLGS, 0, 0, 0) -VSX_MADD(xvnmsubadp, 2, float64, VsrD(i), NMSUB_FLGS, 1, 0, 0) -VSX_MADD(xvnmsubmdp, 2, float64, VsrD(i), NMSUB_FLGS, 0, 0, 0) - -VSX_MADD(xvmaddasp, 4, float32, VsrW(i), MADD_FLGS, 1, 0, 0) -VSX_MADD(xvmaddmsp, 4, float32, VsrW(i), MADD_FLGS, 0, 0, 0) -VSX_MADD(xvmsubasp, 4, float32, VsrW(i), MSUB_FLGS, 1, 0, 0) -VSX_MADD(xvmsubmsp, 4, float32, VsrW(i), MSUB_FLGS, 0, 0, 0) -VSX_MADD(xvnmaddasp, 4, float32, VsrW(i), NMADD_FLGS, 1, 0, 0) -VSX_MADD(xvnmaddmsp, 4, float32, VsrW(i), NMADD_FLGS, 0, 0, 0) -VSX_MADD(xvnmsubasp, 4, float32, VsrW(i), NMSUB_FLGS, 1, 0, 0) -VSX_MADD(xvnmsubmsp, 4, float32, VsrW(i), NMSUB_FLGS, 0, 0, 0) +VSX_MADD(xsmadddp, 1, float64, VsrD(0), MADD_FLGS, 1, 0) +VSX_MADD(xsmsubdp, 1, float64, VsrD(0), MSUB_FLGS, 1, 0) +VSX_MADD(xsnmadddp, 1, float64, VsrD(0), NMADD_FLGS, 1, 0) +VSX_MADD(xsnmsubdp, 1, float64, VsrD(0), NMSUB_FLGS, 1, 0) +VSX_MADD(xsmaddsp, 1, float64, VsrD(0), MADD_FLGS, 1, 1) +VSX_MADD(xsmsubsp, 1, float64, VsrD(0), MSUB_FLGS, 1, 1) +VSX_MADD(xsnmaddsp, 1, float64, VsrD(0), NMADD_FLGS, 1, 1) +VSX_MADD(xsnmsubsp, 1, float64, VsrD(0), NMSUB_FLGS, 1, 1) + +VSX_MADD(xvmadddp, 2, float64, VsrD(i), MADD_FLGS, 0, 0) +VSX_MADD(xvmsubdp, 2, float64, VsrD(i), MSUB_FLGS, 0, 0) +VSX_MADD(xvnmadddp, 2, float64, VsrD(i), NMADD_FLGS, 0, 0) +VSX_MADD(xvnmsubdp, 2, float64, VsrD(i), NMSUB_FLGS, 0, 0) + +VSX_MADD(xvmaddsp, 4, float32, VsrW(i), MADD_FLGS, 0, 0) +VSX_MADD(xvmsubsp, 4, float32, VsrW(i), MSUB_FLGS, 0, 0) +VSX_MADD(xvnmaddsp, 4, float32, VsrW(i), NMADD_FLGS, 0, 0) +VSX_MADD(xvnmsubsp, 4, float32, VsrW(i), NMSUB_FLGS, 0, 0) /* * VSX_SCALAR_CMP_DP - VSX scalar floating point compare double precision @@ -2413,24 +2354,21 @@ VSX_MADD(xvnmsubmsp, 4, float32, VsrW(i), NMSUB_FLGS, 0, 0, 0) * svxvc - set VXVC bit */ #define VSX_SCALAR_CMP_DP(op, cmp, exp, svxvc) \ -void helper_##op(CPUPPCState *env, uint32_t opcode) \ +void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, \ + ppc_vsr_t *xa, ppc_vsr_t *xb) \ { \ - ppc_vsr_t xt, xa, xb; \ + ppc_vsr_t t = *xt; \ bool vxsnan_flag = false, vxvc_flag = false, vex_flag = false; \ \ - getVSR(xA(opcode), &xa, env); \ - getVSR(xB(opcode), &xb, env); \ - getVSR(xT(opcode), &xt, env); \ - \ - if (float64_is_signaling_nan(xa.VsrD(0), &env->fp_status) || \ - float64_is_signaling_nan(xb.VsrD(0), &env->fp_status)) { \ + if (float64_is_signaling_nan(xa->VsrD(0), &env->fp_status) || \ + float64_is_signaling_nan(xb->VsrD(0), &env->fp_status)) { \ vxsnan_flag = true; \ if (fpscr_ve == 0 && svxvc) { \ vxvc_flag = true; \ } \ } else if (svxvc) { \ - vxvc_flag = float64_is_quiet_nan(xa.VsrD(0), &env->fp_status) || \ - float64_is_quiet_nan(xb.VsrD(0), &env->fp_status); \ + vxvc_flag = float64_is_quiet_nan(xa->VsrD(0), &env->fp_status) || \ + float64_is_quiet_nan(xb->VsrD(0), &env->fp_status); \ } \ if (vxsnan_flag) { \ float_invalid_op_vxsnan(env, GETPC()); \ @@ -2441,15 +2379,16 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \ vex_flag = fpscr_ve && (vxvc_flag || vxsnan_flag); \ \ if (!vex_flag) { \ - if (float64_##cmp(xb.VsrD(0), xa.VsrD(0), &env->fp_status) == exp) { \ - xt.VsrD(0) = -1; \ - xt.VsrD(1) = 0; \ + if (float64_##cmp(xb->VsrD(0), xa->VsrD(0), \ + &env->fp_status) == exp) { \ + t.VsrD(0) = -1; \ + t.VsrD(1) = 0; \ } else { \ - xt.VsrD(0) = 0; \ - xt.VsrD(1) = 0; \ + t.VsrD(0) = 0; \ + t.VsrD(1) = 0; \ } \ } \ - putVSR(xT(opcode), &xt, env); \ + *xt = t; \ do_float_check_status(env, GETPC()); \ } @@ -2458,20 +2397,17 @@ VSX_SCALAR_CMP_DP(xscmpgedp, le, 1, 1) VSX_SCALAR_CMP_DP(xscmpgtdp, lt, 1, 1) VSX_SCALAR_CMP_DP(xscmpnedp, eq, 0, 0) -void helper_xscmpexpdp(CPUPPCState *env, uint32_t opcode) +void helper_xscmpexpdp(CPUPPCState *env, uint32_t opcode, + ppc_vsr_t *xa, ppc_vsr_t *xb) { - ppc_vsr_t xa, xb; int64_t exp_a, exp_b; uint32_t cc; - getVSR(xA(opcode), &xa, env); - getVSR(xB(opcode), &xb, env); - - exp_a = extract64(xa.VsrD(0), 52, 11); - exp_b = extract64(xb.VsrD(0), 52, 11); + exp_a = extract64(xa->VsrD(0), 52, 11); + exp_b = extract64(xb->VsrD(0), 52, 11); - if (unlikely(float64_is_any_nan(xa.VsrD(0)) || - float64_is_any_nan(xb.VsrD(0)))) { + if (unlikely(float64_is_any_nan(xa->VsrD(0)) || + float64_is_any_nan(xb->VsrD(0)))) { cc = CRF_SO; } else { if (exp_a < exp_b) { @@ -2490,20 +2426,17 @@ void helper_xscmpexpdp(CPUPPCState *env, uint32_t opcode) do_float_check_status(env, GETPC()); } -void helper_xscmpexpqp(CPUPPCState *env, uint32_t opcode) +void helper_xscmpexpqp(CPUPPCState *env, uint32_t opcode, + ppc_vsr_t *xa, ppc_vsr_t *xb) { - ppc_vsr_t xa, xb; int64_t exp_a, exp_b; uint32_t cc; - getVSR(rA(opcode) + 32, &xa, env); - getVSR(rB(opcode) + 32, &xb, env); + exp_a = extract64(xa->VsrD(0), 48, 15); + exp_b = extract64(xb->VsrD(0), 48, 15); - exp_a = extract64(xa.VsrD(0), 48, 15); - exp_b = extract64(xb.VsrD(0), 48, 15); - - if (unlikely(float128_is_any_nan(xa.f128) || - float128_is_any_nan(xb.f128))) { + if (unlikely(float128_is_any_nan(xa->f128) || + float128_is_any_nan(xb->f128))) { cc = CRF_SO; } else { if (exp_a < exp_b) { @@ -2523,25 +2456,23 @@ void helper_xscmpexpqp(CPUPPCState *env, uint32_t opcode) } #define VSX_SCALAR_CMP(op, ordered) \ -void helper_##op(CPUPPCState *env, uint32_t opcode) \ +void helper_##op(CPUPPCState *env, uint32_t opcode, \ + ppc_vsr_t *xa, ppc_vsr_t *xb) \ { \ - ppc_vsr_t xa, xb; \ uint32_t cc = 0; \ bool vxsnan_flag = false, vxvc_flag = false; \ \ helper_reset_fpstatus(env); \ - getVSR(xA(opcode), &xa, env); \ - getVSR(xB(opcode), &xb, env); \ \ - if (float64_is_signaling_nan(xa.VsrD(0), &env->fp_status) || \ - float64_is_signaling_nan(xb.VsrD(0), &env->fp_status)) { \ + if (float64_is_signaling_nan(xa->VsrD(0), &env->fp_status) || \ + float64_is_signaling_nan(xb->VsrD(0), &env->fp_status)) { \ vxsnan_flag = true; \ cc = CRF_SO; \ if (fpscr_ve == 0 && ordered) { \ vxvc_flag = true; \ } \ - } else if (float64_is_quiet_nan(xa.VsrD(0), &env->fp_status) || \ - float64_is_quiet_nan(xb.VsrD(0), &env->fp_status)) { \ + } else if (float64_is_quiet_nan(xa->VsrD(0), &env->fp_status) || \ + float64_is_quiet_nan(xb->VsrD(0), &env->fp_status)) { \ cc = CRF_SO; \ if (ordered) { \ vxvc_flag = true; \ @@ -2554,9 +2485,9 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \ float_invalid_op_vxvc(env, 0, GETPC()); \ } \ \ - if (float64_lt(xa.VsrD(0), xb.VsrD(0), &env->fp_status)) { \ + if (float64_lt(xa->VsrD(0), xb->VsrD(0), &env->fp_status)) { \ cc |= CRF_LT; \ - } else if (!float64_le(xa.VsrD(0), xb.VsrD(0), &env->fp_status)) { \ + } else if (!float64_le(xa->VsrD(0), xb->VsrD(0), &env->fp_status)) { \ cc |= CRF_GT; \ } else { \ cc |= CRF_EQ; \ @@ -2573,25 +2504,23 @@ VSX_SCALAR_CMP(xscmpodp, 1) VSX_SCALAR_CMP(xscmpudp, 0) #define VSX_SCALAR_CMPQ(op, ordered) \ -void helper_##op(CPUPPCState *env, uint32_t opcode) \ +void helper_##op(CPUPPCState *env, uint32_t opcode, \ + ppc_vsr_t *xa, ppc_vsr_t *xb) \ { \ - ppc_vsr_t xa, xb; \ uint32_t cc = 0; \ bool vxsnan_flag = false, vxvc_flag = false; \ \ helper_reset_fpstatus(env); \ - getVSR(rA(opcode) + 32, &xa, env); \ - getVSR(rB(opcode) + 32, &xb, env); \ \ - if (float128_is_signaling_nan(xa.f128, &env->fp_status) || \ - float128_is_signaling_nan(xb.f128, &env->fp_status)) { \ + if (float128_is_signaling_nan(xa->f128, &env->fp_status) || \ + float128_is_signaling_nan(xb->f128, &env->fp_status)) { \ vxsnan_flag = true; \ cc = CRF_SO; \ if (fpscr_ve == 0 && ordered) { \ vxvc_flag = true; \ } \ - } else if (float128_is_quiet_nan(xa.f128, &env->fp_status) || \ - float128_is_quiet_nan(xb.f128, &env->fp_status)) { \ + } else if (float128_is_quiet_nan(xa->f128, &env->fp_status) || \ + float128_is_quiet_nan(xb->f128, &env->fp_status)) { \ cc = CRF_SO; \ if (ordered) { \ vxvc_flag = true; \ @@ -2604,9 +2533,9 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \ float_invalid_op_vxvc(env, 0, GETPC()); \ } \ \ - if (float128_lt(xa.f128, xb.f128, &env->fp_status)) { \ + if (float128_lt(xa->f128, xb->f128, &env->fp_status)) { \ cc |= CRF_LT; \ - } else if (!float128_le(xa.f128, xb.f128, &env->fp_status)) { \ + } else if (!float128_le(xa->f128, xb->f128, &env->fp_status)) { \ cc |= CRF_GT; \ } else { \ cc |= CRF_EQ; \ @@ -2631,24 +2560,21 @@ VSX_SCALAR_CMPQ(xscmpuqp, 0) * fld - vsr_t field (VsrD(*) or VsrW(*)) */ #define VSX_MAX_MIN(name, op, nels, tp, fld) \ -void helper_##name(CPUPPCState *env, uint32_t opcode) \ +void helper_##name(CPUPPCState *env, ppc_vsr_t *xt, \ + ppc_vsr_t *xa, ppc_vsr_t *xb) \ { \ - ppc_vsr_t xt, xa, xb; \ + ppc_vsr_t t = *xt; \ int i; \ \ - getVSR(xA(opcode), &xa, env); \ - getVSR(xB(opcode), &xb, env); \ - getVSR(xT(opcode), &xt, env); \ - \ for (i = 0; i < nels; i++) { \ - xt.fld = tp##_##op(xa.fld, xb.fld, &env->fp_status); \ - if (unlikely(tp##_is_signaling_nan(xa.fld, &env->fp_status) || \ - tp##_is_signaling_nan(xb.fld, &env->fp_status))) { \ + t.fld = tp##_##op(xa->fld, xb->fld, &env->fp_status); \ + if (unlikely(tp##_is_signaling_nan(xa->fld, &env->fp_status) || \ + tp##_is_signaling_nan(xb->fld, &env->fp_status))) { \ float_invalid_op_vxsnan(env, GETPC()); \ } \ } \ \ - putVSR(xT(opcode), &xt, env); \ + *xt = t; \ do_float_check_status(env, GETPC()); \ } @@ -2660,29 +2586,26 @@ VSX_MAX_MIN(xvmindp, minnum, 2, float64, VsrD(i)) VSX_MAX_MIN(xvminsp, minnum, 4, float32, VsrW(i)) #define VSX_MAX_MINC(name, max) \ -void helper_##name(CPUPPCState *env, uint32_t opcode) \ +void helper_##name(CPUPPCState *env, uint32_t opcode, \ + ppc_vsr_t *xt, ppc_vsr_t *xa, ppc_vsr_t *xb) \ { \ - ppc_vsr_t xt, xa, xb; \ + ppc_vsr_t t = *xt; \ bool vxsnan_flag = false, vex_flag = false; \ \ - getVSR(rA(opcode) + 32, &xa, env); \ - getVSR(rB(opcode) + 32, &xb, env); \ - getVSR(rD(opcode) + 32, &xt, env); \ - \ - if (unlikely(float64_is_any_nan(xa.VsrD(0)) || \ - float64_is_any_nan(xb.VsrD(0)))) { \ - if (float64_is_signaling_nan(xa.VsrD(0), &env->fp_status) || \ - float64_is_signaling_nan(xb.VsrD(0), &env->fp_status)) { \ + if (unlikely(float64_is_any_nan(xa->VsrD(0)) || \ + float64_is_any_nan(xb->VsrD(0)))) { \ + if (float64_is_signaling_nan(xa->VsrD(0), &env->fp_status) || \ + float64_is_signaling_nan(xb->VsrD(0), &env->fp_status)) { \ vxsnan_flag = true; \ } \ - xt.VsrD(0) = xb.VsrD(0); \ + t.VsrD(0) = xb->VsrD(0); \ } else if ((max && \ - !float64_lt(xa.VsrD(0), xb.VsrD(0), &env->fp_status)) || \ + !float64_lt(xa->VsrD(0), xb->VsrD(0), &env->fp_status)) || \ (!max && \ - float64_lt(xa.VsrD(0), xb.VsrD(0), &env->fp_status))) { \ - xt.VsrD(0) = xa.VsrD(0); \ + float64_lt(xa->VsrD(0), xb->VsrD(0), &env->fp_status))) { \ + t.VsrD(0) = xa->VsrD(0); \ } else { \ - xt.VsrD(0) = xb.VsrD(0); \ + t.VsrD(0) = xb->VsrD(0); \ } \ \ vex_flag = fpscr_ve & vxsnan_flag; \ @@ -2690,7 +2613,7 @@ void helper_##name(CPUPPCState *env, uint32_t opcode) \ float_invalid_op_vxsnan(env, GETPC()); \ } \ if (!vex_flag) { \ - putVSR(rD(opcode) + 32, &xt, env); \ + *xt = t; \ } \ } \ @@ -2698,46 +2621,46 @@ VSX_MAX_MINC(xsmaxcdp, 1); VSX_MAX_MINC(xsmincdp, 0); #define VSX_MAX_MINJ(name, max) \ -void helper_##name(CPUPPCState *env, uint32_t opcode) \ +void helper_##name(CPUPPCState *env, uint32_t opcode, \ + ppc_vsr_t *xt, ppc_vsr_t *xa, ppc_vsr_t *xb) \ { \ - ppc_vsr_t xt, xa, xb; \ + ppc_vsr_t t = *xt; \ bool vxsnan_flag = false, vex_flag = false; \ \ - getVSR(rA(opcode) + 32, &xa, env); \ - getVSR(rB(opcode) + 32, &xb, env); \ - getVSR(rD(opcode) + 32, &xt, env); \ - \ - if (unlikely(float64_is_any_nan(xa.VsrD(0)))) { \ - if (float64_is_signaling_nan(xa.VsrD(0), &env->fp_status)) { \ + if (unlikely(float64_is_any_nan(xa->VsrD(0)))) { \ + if (float64_is_signaling_nan(xa->VsrD(0), &env->fp_status)) { \ vxsnan_flag = true; \ } \ - xt.VsrD(0) = xa.VsrD(0); \ - } else if (unlikely(float64_is_any_nan(xb.VsrD(0)))) { \ - if (float64_is_signaling_nan(xb.VsrD(0), &env->fp_status)) { \ + t.VsrD(0) = xa->VsrD(0); \ + } else if (unlikely(float64_is_any_nan(xb->VsrD(0)))) { \ + if (float64_is_signaling_nan(xb->VsrD(0), &env->fp_status)) { \ vxsnan_flag = true; \ } \ - xt.VsrD(0) = xb.VsrD(0); \ - } else if (float64_is_zero(xa.VsrD(0)) && float64_is_zero(xb.VsrD(0))) { \ + t.VsrD(0) = xb->VsrD(0); \ + } else if (float64_is_zero(xa->VsrD(0)) && \ + float64_is_zero(xb->VsrD(0))) { \ if (max) { \ - if (!float64_is_neg(xa.VsrD(0)) || !float64_is_neg(xb.VsrD(0))) { \ - xt.VsrD(0) = 0ULL; \ + if (!float64_is_neg(xa->VsrD(0)) || \ + !float64_is_neg(xb->VsrD(0))) { \ + t.VsrD(0) = 0ULL; \ } else { \ - xt.VsrD(0) = 0x8000000000000000ULL; \ + t.VsrD(0) = 0x8000000000000000ULL; \ } \ } else { \ - if (float64_is_neg(xa.VsrD(0)) || float64_is_neg(xb.VsrD(0))) { \ - xt.VsrD(0) = 0x8000000000000000ULL; \ + if (float64_is_neg(xa->VsrD(0)) || \ + float64_is_neg(xb->VsrD(0))) { \ + t.VsrD(0) = 0x8000000000000000ULL; \ } else { \ - xt.VsrD(0) = 0ULL; \ + t.VsrD(0) = 0ULL; \ } \ } \ } else if ((max && \ - !float64_lt(xa.VsrD(0), xb.VsrD(0), &env->fp_status)) || \ + !float64_lt(xa->VsrD(0), xb->VsrD(0), &env->fp_status)) || \ (!max && \ - float64_lt(xa.VsrD(0), xb.VsrD(0), &env->fp_status))) { \ - xt.VsrD(0) = xa.VsrD(0); \ + float64_lt(xa->VsrD(0), xb->VsrD(0), &env->fp_status))) { \ + t.VsrD(0) = xa->VsrD(0); \ } else { \ - xt.VsrD(0) = xb.VsrD(0); \ + t.VsrD(0) = xb->VsrD(0); \ } \ \ vex_flag = fpscr_ve & vxsnan_flag; \ @@ -2745,7 +2668,7 @@ void helper_##name(CPUPPCState *env, uint32_t opcode) \ float_invalid_op_vxsnan(env, GETPC()); \ } \ if (!vex_flag) { \ - putVSR(rD(opcode) + 32, &xt, env); \ + *xt = t; \ } \ } \ @@ -2763,46 +2686,42 @@ VSX_MAX_MINJ(xsminjdp, 0); * exp - expected result of comparison */ #define VSX_CMP(op, nels, tp, fld, cmp, svxvc, exp) \ -void helper_##op(CPUPPCState *env, uint32_t opcode) \ +uint32_t helper_##op(CPUPPCState *env, ppc_vsr_t *xt, \ + ppc_vsr_t *xa, ppc_vsr_t *xb) \ { \ - ppc_vsr_t xt, xa, xb; \ + ppc_vsr_t t = *xt; \ + uint32_t crf6 = 0; \ int i; \ int all_true = 1; \ int all_false = 1; \ \ - getVSR(xA(opcode), &xa, env); \ - getVSR(xB(opcode), &xb, env); \ - getVSR(xT(opcode), &xt, env); \ - \ for (i = 0; i < nels; i++) { \ - if (unlikely(tp##_is_any_nan(xa.fld) || \ - tp##_is_any_nan(xb.fld))) { \ - if (tp##_is_signaling_nan(xa.fld, &env->fp_status) || \ - tp##_is_signaling_nan(xb.fld, &env->fp_status)) { \ + if (unlikely(tp##_is_any_nan(xa->fld) || \ + tp##_is_any_nan(xb->fld))) { \ + if (tp##_is_signaling_nan(xa->fld, &env->fp_status) || \ + tp##_is_signaling_nan(xb->fld, &env->fp_status)) { \ float_invalid_op_vxsnan(env, GETPC()); \ } \ if (svxvc) { \ float_invalid_op_vxvc(env, 0, GETPC()); \ } \ - xt.fld = 0; \ + t.fld = 0; \ all_true = 0; \ } else { \ - if (tp##_##cmp(xb.fld, xa.fld, &env->fp_status) == exp) { \ - xt.fld = -1; \ + if (tp##_##cmp(xb->fld, xa->fld, &env->fp_status) == exp) { \ + t.fld = -1; \ all_false = 0; \ } else { \ - xt.fld = 0; \ + t.fld = 0; \ all_true = 0; \ } \ } \ } \ \ - putVSR(xT(opcode), &xt, env); \ - if ((opcode >> (31 - 21)) & 1) { \ - env->crf[6] = (all_true ? 0x8 : 0) | (all_false ? 0x2 : 0); \ - } \ - do_float_check_status(env, GETPC()); \ - } + *xt = t; \ + crf6 = (all_true ? 0x8 : 0) | (all_false ? 0x2 : 0); \ + return crf6; \ +} VSX_CMP(xvcmpeqdp, 2, float64, VsrD(i), eq, 0, 1) VSX_CMP(xvcmpgedp, 2, float64, VsrD(i), le, 1, 1) @@ -2824,27 +2743,24 @@ VSX_CMP(xvcmpnesp, 4, float32, VsrW(i), eq, 0, 0) * sfprf - set FPRF */ #define VSX_CVT_FP_TO_FP(op, nels, stp, ttp, sfld, tfld, sfprf) \ -void helper_##op(CPUPPCState *env, uint32_t opcode) \ +void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \ { \ - ppc_vsr_t xt, xb; \ + ppc_vsr_t t = *xt; \ int i; \ \ - getVSR(xB(opcode), &xb, env); \ - getVSR(xT(opcode), &xt, env); \ - \ for (i = 0; i < nels; i++) { \ - xt.tfld = stp##_to_##ttp(xb.sfld, &env->fp_status); \ - if (unlikely(stp##_is_signaling_nan(xb.sfld, \ + t.tfld = stp##_to_##ttp(xb->sfld, &env->fp_status); \ + if (unlikely(stp##_is_signaling_nan(xb->sfld, \ &env->fp_status))) { \ float_invalid_op_vxsnan(env, GETPC()); \ - xt.tfld = ttp##_snan_to_qnan(xt.tfld); \ + t.tfld = ttp##_snan_to_qnan(t.tfld); \ } \ if (sfprf) { \ - helper_compute_fprf_##ttp(env, xt.tfld); \ + helper_compute_fprf_##ttp(env, t.tfld); \ } \ } \ \ - putVSR(xT(opcode), &xt, env); \ + *xt = t; \ do_float_check_status(env, GETPC()); \ } @@ -2864,27 +2780,25 @@ VSX_CVT_FP_TO_FP(xvcvspdp, 2, float32, float64, VsrW(2 * i), VsrD(i), 0) * sfprf - set FPRF */ #define VSX_CVT_FP_TO_FP_VECTOR(op, nels, stp, ttp, sfld, tfld, sfprf) \ -void helper_##op(CPUPPCState *env, uint32_t opcode) \ +void helper_##op(CPUPPCState *env, uint32_t opcode, \ + ppc_vsr_t *xt, ppc_vsr_t *xb) \ { \ - ppc_vsr_t xt, xb; \ + ppc_vsr_t t = *xt; \ int i; \ \ - getVSR(rB(opcode) + 32, &xb, env); \ - getVSR(rD(opcode) + 32, &xt, env); \ - \ for (i = 0; i < nels; i++) { \ - xt.tfld = stp##_to_##ttp(xb.sfld, &env->fp_status); \ - if (unlikely(stp##_is_signaling_nan(xb.sfld, \ + t.tfld = stp##_to_##ttp(xb->sfld, &env->fp_status); \ + if (unlikely(stp##_is_signaling_nan(xb->sfld, \ &env->fp_status))) { \ float_invalid_op_vxsnan(env, GETPC()); \ - xt.tfld = ttp##_snan_to_qnan(xt.tfld); \ + t.tfld = ttp##_snan_to_qnan(t.tfld); \ } \ if (sfprf) { \ - helper_compute_fprf_##ttp(env, xt.tfld); \ + helper_compute_fprf_##ttp(env, t.tfld); \ } \ } \ \ - putVSR(rD(opcode) + 32, &xt, env); \ + *xt = t; \ do_float_check_status(env, GETPC()); \ } @@ -2902,27 +2816,24 @@ VSX_CVT_FP_TO_FP_VECTOR(xscvdpqp, 1, float64, float128, VsrD(0), f128, 1) * sfprf - set FPRF */ #define VSX_CVT_FP_TO_FP_HP(op, nels, stp, ttp, sfld, tfld, sfprf) \ -void helper_##op(CPUPPCState *env, uint32_t opcode) \ +void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \ { \ - ppc_vsr_t xt, xb; \ + ppc_vsr_t t = { }; \ int i; \ \ - getVSR(xB(opcode), &xb, env); \ - memset(&xt, 0, sizeof(xt)); \ - \ for (i = 0; i < nels; i++) { \ - xt.tfld = stp##_to_##ttp(xb.sfld, 1, &env->fp_status); \ - if (unlikely(stp##_is_signaling_nan(xb.sfld, \ + t.tfld = stp##_to_##ttp(xb->sfld, 1, &env->fp_status); \ + if (unlikely(stp##_is_signaling_nan(xb->sfld, \ &env->fp_status))) { \ float_invalid_op_vxsnan(env, GETPC()); \ - xt.tfld = ttp##_snan_to_qnan(xt.tfld); \ + t.tfld = ttp##_snan_to_qnan(t.tfld); \ } \ if (sfprf) { \ - helper_compute_fprf_##ttp(env, xt.tfld); \ + helper_compute_fprf_##ttp(env, t.tfld); \ } \ } \ \ - putVSR(xT(opcode), &xt, env); \ + *xt = t; \ do_float_check_status(env, GETPC()); \ } @@ -2935,28 +2846,26 @@ VSX_CVT_FP_TO_FP_HP(xvcvhpsp, 4, float16, float32, VsrH(2 * i + 1), VsrW(i), 0) * xscvqpdp isn't using VSX_CVT_FP_TO_FP() because xscvqpdpo will be * added to this later. */ -void helper_xscvqpdp(CPUPPCState *env, uint32_t opcode) +void helper_xscvqpdp(CPUPPCState *env, uint32_t opcode, + ppc_vsr_t *xt, ppc_vsr_t *xb) { - ppc_vsr_t xt, xb; + ppc_vsr_t t = { }; float_status tstat; - getVSR(rB(opcode) + 32, &xb, env); - memset(&xt, 0, sizeof(xt)); - tstat = env->fp_status; if (unlikely(Rc(opcode) != 0)) { tstat.float_rounding_mode = float_round_to_odd; } - xt.VsrD(0) = float128_to_float64(xb.f128, &tstat); + t.VsrD(0) = float128_to_float64(xb->f128, &tstat); env->fp_status.float_exception_flags |= tstat.float_exception_flags; - if (unlikely(float128_is_signaling_nan(xb.f128, &tstat))) { + if (unlikely(float128_is_signaling_nan(xb->f128, &tstat))) { float_invalid_op_vxsnan(env, GETPC()); - xt.VsrD(0) = float64_snan_to_qnan(xt.VsrD(0)); + t.VsrD(0) = float64_snan_to_qnan(t.VsrD(0)); } - helper_compute_fprf_float64(env, xt.VsrD(0)); + helper_compute_fprf_float64(env, t.VsrD(0)); - putVSR(rD(opcode) + 32, &xt, env); + *xt = t; do_float_check_status(env, GETPC()); } @@ -2987,27 +2896,24 @@ uint64_t helper_xscvspdpn(CPUPPCState *env, uint64_t xb) * rnan - resulting NaN */ #define VSX_CVT_FP_TO_INT(op, nels, stp, ttp, sfld, tfld, rnan) \ -void helper_##op(CPUPPCState *env, uint32_t opcode) \ +void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \ { \ int all_flags = env->fp_status.float_exception_flags, flags; \ - ppc_vsr_t xt, xb; \ + ppc_vsr_t t = *xt; \ int i; \ \ - getVSR(xB(opcode), &xb, env); \ - getVSR(xT(opcode), &xt, env); \ - \ for (i = 0; i < nels; i++) { \ env->fp_status.float_exception_flags = 0; \ - xt.tfld = stp##_to_##ttp##_round_to_zero(xb.sfld, &env->fp_status); \ + t.tfld = stp##_to_##ttp##_round_to_zero(xb->sfld, &env->fp_status); \ flags = env->fp_status.float_exception_flags; \ if (unlikely(flags & float_flag_invalid)) { \ - float_invalid_cvt(env, 0, GETPC(), stp##_classify(xb.sfld)); \ - xt.tfld = rnan; \ + float_invalid_cvt(env, 0, GETPC(), stp##_classify(xb->sfld)); \ + t.tfld = rnan; \ } \ all_flags |= flags; \ } \ \ - putVSR(xT(opcode), &xt, env); \ + *xt = t; \ env->fp_status.float_exception_flags = all_flags; \ do_float_check_status(env, GETPC()); \ } @@ -3040,20 +2946,18 @@ VSX_CVT_FP_TO_INT(xvcvspuxws, 4, float32, uint32, VsrW(i), VsrW(i), 0U) * rnan - resulting NaN */ #define VSX_CVT_FP_TO_INT_VECTOR(op, stp, ttp, sfld, tfld, rnan) \ -void helper_##op(CPUPPCState *env, uint32_t opcode) \ +void helper_##op(CPUPPCState *env, uint32_t opcode, \ + ppc_vsr_t *xt, ppc_vsr_t *xb) \ { \ - ppc_vsr_t xt, xb; \ + ppc_vsr_t t = { }; \ \ - getVSR(rB(opcode) + 32, &xb, env); \ - memset(&xt, 0, sizeof(xt)); \ - \ - xt.tfld = stp##_to_##ttp##_round_to_zero(xb.sfld, &env->fp_status); \ + t.tfld = stp##_to_##ttp##_round_to_zero(xb->sfld, &env->fp_status); \ if (env->fp_status.float_exception_flags & float_flag_invalid) { \ - float_invalid_cvt(env, 0, GETPC(), stp##_classify(xb.sfld)); \ - xt.tfld = rnan; \ + float_invalid_cvt(env, 0, GETPC(), stp##_classify(xb->sfld)); \ + t.tfld = rnan; \ } \ \ - putVSR(rD(opcode) + 32, &xt, env); \ + *xt = t; \ do_float_check_status(env, GETPC()); \ } @@ -3077,25 +2981,22 @@ VSX_CVT_FP_TO_INT_VECTOR(xscvqpuwz, float128, uint32, f128, VsrD(0), 0x0ULL) * sfprf - set FPRF */ #define VSX_CVT_INT_TO_FP(op, nels, stp, ttp, sfld, tfld, sfprf, r2sp) \ -void helper_##op(CPUPPCState *env, uint32_t opcode) \ +void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \ { \ - ppc_vsr_t xt, xb; \ + ppc_vsr_t t = *xt; \ int i; \ \ - getVSR(xB(opcode), &xb, env); \ - getVSR(xT(opcode), &xt, env); \ - \ for (i = 0; i < nels; i++) { \ - xt.tfld = stp##_to_##ttp(xb.sfld, &env->fp_status); \ + t.tfld = stp##_to_##ttp(xb->sfld, &env->fp_status); \ if (r2sp) { \ - xt.tfld = helper_frsp(env, xt.tfld); \ + t.tfld = helper_frsp(env, t.tfld); \ } \ if (sfprf) { \ - helper_compute_fprf_float64(env, xt.tfld); \ + helper_compute_fprf_float64(env, t.tfld); \ } \ } \ \ - putVSR(xT(opcode), &xt, env); \ + *xt = t; \ do_float_check_status(env, GETPC()); \ } @@ -3121,17 +3022,15 @@ VSX_CVT_INT_TO_FP(xvcvuxwsp, 4, uint32, float32, VsrW(i), VsrW(i), 0, 0) * tfld - target vsr_t field */ #define VSX_CVT_INT_TO_FP_VECTOR(op, stp, ttp, sfld, tfld) \ -void helper_##op(CPUPPCState *env, uint32_t opcode) \ +void helper_##op(CPUPPCState *env, uint32_t opcode, \ + ppc_vsr_t *xt, ppc_vsr_t *xb) \ { \ - ppc_vsr_t xt, xb; \ + ppc_vsr_t t = *xt; \ \ - getVSR(rB(opcode) + 32, &xb, env); \ - getVSR(rD(opcode) + 32, &xt, env); \ + t.tfld = stp##_to_##ttp(xb->sfld, &env->fp_status); \ + helper_compute_fprf_##ttp(env, t.tfld); \ \ - xt.tfld = stp##_to_##ttp(xb.sfld, &env->fp_status); \ - helper_compute_fprf_##ttp(env, xt.tfld); \ - \ - putVSR(xT(opcode) + 32, &xt, env); \ + *xt = t; \ do_float_check_status(env, GETPC()); \ } @@ -3155,27 +3054,25 @@ VSX_CVT_INT_TO_FP_VECTOR(xscvudqp, uint64, float128, VsrD(0), f128) * sfprf - set FPRF */ #define VSX_ROUND(op, nels, tp, fld, rmode, sfprf) \ -void helper_##op(CPUPPCState *env, uint32_t opcode) \ +void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \ { \ - ppc_vsr_t xt, xb; \ + ppc_vsr_t t = *xt; \ int i; \ - getVSR(xB(opcode), &xb, env); \ - getVSR(xT(opcode), &xt, env); \ \ if (rmode != FLOAT_ROUND_CURRENT) { \ set_float_rounding_mode(rmode, &env->fp_status); \ } \ \ for (i = 0; i < nels; i++) { \ - if (unlikely(tp##_is_signaling_nan(xb.fld, \ + if (unlikely(tp##_is_signaling_nan(xb->fld, \ &env->fp_status))) { \ float_invalid_op_vxsnan(env, GETPC()); \ - xt.fld = tp##_snan_to_qnan(xb.fld); \ + t.fld = tp##_snan_to_qnan(xb->fld); \ } else { \ - xt.fld = tp##_round_to_int(xb.fld, &env->fp_status); \ + t.fld = tp##_round_to_int(xb->fld, &env->fp_status); \ } \ if (sfprf) { \ - helper_compute_fprf_float64(env, xt.fld); \ + helper_compute_fprf_float64(env, t.fld); \ } \ } \ \ @@ -3189,7 +3086,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \ env->fp_status.float_exception_flags &= ~float_flag_inexact; \ } \ \ - putVSR(xT(opcode), &xt, env); \ + *xt = t; \ do_float_check_status(env, GETPC()); \ } @@ -3223,46 +3120,41 @@ uint64_t helper_xsrsp(CPUPPCState *env, uint64_t xb) } #define VSX_XXPERM(op, indexed) \ -void helper_##op(CPUPPCState *env, uint32_t opcode) \ +void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, \ + ppc_vsr_t *xa, ppc_vsr_t *pcv) \ { \ - ppc_vsr_t xt, xa, pcv, xto; \ + ppc_vsr_t t = *xt; \ int i, idx; \ \ - getVSR(xA(opcode), &xa, env); \ - getVSR(xT(opcode), &xt, env); \ - getVSR(xB(opcode), &pcv, env); \ - \ for (i = 0; i < 16; i++) { \ - idx = pcv.VsrB(i) & 0x1F; \ + idx = pcv->VsrB(i) & 0x1F; \ if (indexed) { \ idx = 31 - idx; \ } \ - xto.VsrB(i) = (idx <= 15) ? xa.VsrB(idx) : xt.VsrB(idx - 16); \ + t.VsrB(i) = (idx <= 15) ? xa->VsrB(idx) \ + : xt->VsrB(idx - 16); \ } \ - putVSR(xT(opcode), &xto, env); \ + *xt = t; \ } VSX_XXPERM(xxperm, 0) VSX_XXPERM(xxpermr, 1) -void helper_xvxsigsp(CPUPPCState *env, uint32_t opcode) +void helper_xvxsigsp(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) { - ppc_vsr_t xt, xb; + ppc_vsr_t t = { }; uint32_t exp, i, fraction; - getVSR(xB(opcode), &xb, env); - memset(&xt, 0, sizeof(xt)); - for (i = 0; i < 4; i++) { - exp = (xb.VsrW(i) >> 23) & 0xFF; - fraction = xb.VsrW(i) & 0x7FFFFF; + exp = (xb->VsrW(i) >> 23) & 0xFF; + fraction = xb->VsrW(i) & 0x7FFFFF; if (exp != 0 && exp != 255) { - xt.VsrW(i) = fraction | 0x00800000; + t.VsrW(i) = fraction | 0x00800000; } else { - xt.VsrW(i) = fraction; + t.VsrW(i) = fraction; } } - putVSR(xT(opcode), &xt, env); + *xt = t; } /* @@ -3279,27 +3171,28 @@ void helper_xvxsigsp(CPUPPCState *env, uint32_t opcode) #define VSX_TEST_DC(op, nels, xbn, tp, fld, tfld, fld_max, scrf) \ void helper_##op(CPUPPCState *env, uint32_t opcode) \ { \ - ppc_vsr_t xt, xb; \ + ppc_vsr_t *xt = &env->vsr[xT(opcode)]; \ + ppc_vsr_t *xb = &env->vsr[xbn]; \ + ppc_vsr_t t = { }; \ uint32_t i, sign, dcmx; \ uint32_t cc, match = 0; \ \ - getVSR(xbn, &xb, env); \ if (!scrf) { \ - memset(&xt, 0, sizeof(xt)); \ dcmx = DCMX_XV(opcode); \ } else { \ + t = *xt; \ dcmx = DCMX(opcode); \ } \ \ for (i = 0; i < nels; i++) { \ - sign = tp##_is_neg(xb.fld); \ - if (tp##_is_any_nan(xb.fld)) { \ + sign = tp##_is_neg(xb->fld); \ + if (tp##_is_any_nan(xb->fld)) { \ match = extract32(dcmx, 6, 1); \ - } else if (tp##_is_infinity(xb.fld)) { \ + } else if (tp##_is_infinity(xb->fld)) { \ match = extract32(dcmx, 4 + !sign, 1); \ - } else if (tp##_is_zero(xb.fld)) { \ + } else if (tp##_is_zero(xb->fld)) { \ match = extract32(dcmx, 2 + !sign, 1); \ - } else if (tp##_is_zero_or_denormal(xb.fld)) { \ + } else if (tp##_is_zero_or_denormal(xb->fld)) { \ match = extract32(dcmx, 0 + !sign, 1); \ } \ \ @@ -3309,12 +3202,12 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \ env->fpscr |= cc << FPSCR_FPRF; \ env->crf[BF(opcode)] = cc; \ } else { \ - xt.tfld = match ? fld_max : 0; \ + t.tfld = match ? fld_max : 0; \ } \ match = 0; \ } \ if (!scrf) { \ - putVSR(xT(opcode), &xt, env); \ + *xt = t; \ } \ } @@ -3323,31 +3216,29 @@ VSX_TEST_DC(xvtstdcsp, 4, xB(opcode), float32, VsrW(i), VsrW(i), UINT32_MAX, 0) VSX_TEST_DC(xststdcdp, 1, xB(opcode), float64, VsrD(0), VsrD(0), 0, 1) VSX_TEST_DC(xststdcqp, 1, (rB(opcode) + 32), float128, f128, VsrD(0), 0, 1) -void helper_xststdcsp(CPUPPCState *env, uint32_t opcode) +void helper_xststdcsp(CPUPPCState *env, uint32_t opcode, ppc_vsr_t *xb) { - ppc_vsr_t xb; uint32_t dcmx, sign, exp; uint32_t cc, match = 0, not_sp = 0; - getVSR(xB(opcode), &xb, env); dcmx = DCMX(opcode); - exp = (xb.VsrD(0) >> 52) & 0x7FF; + exp = (xb->VsrD(0) >> 52) & 0x7FF; - sign = float64_is_neg(xb.VsrD(0)); - if (float64_is_any_nan(xb.VsrD(0))) { + sign = float64_is_neg(xb->VsrD(0)); + if (float64_is_any_nan(xb->VsrD(0))) { match = extract32(dcmx, 6, 1); - } else if (float64_is_infinity(xb.VsrD(0))) { + } else if (float64_is_infinity(xb->VsrD(0))) { match = extract32(dcmx, 4 + !sign, 1); - } else if (float64_is_zero(xb.VsrD(0))) { + } else if (float64_is_zero(xb->VsrD(0))) { match = extract32(dcmx, 2 + !sign, 1); - } else if (float64_is_zero_or_denormal(xb.VsrD(0)) || + } else if (float64_is_zero_or_denormal(xb->VsrD(0)) || (exp > 0 && exp < 0x381)) { match = extract32(dcmx, 0 + !sign, 1); } - not_sp = !float64_eq(xb.VsrD(0), + not_sp = !float64_eq(xb->VsrD(0), float32_to_float64( - float64_to_float32(xb.VsrD(0), &env->fp_status), + float64_to_float32(xb->VsrD(0), &env->fp_status), &env->fp_status), &env->fp_status); cc = sign << CRF_LT_BIT | match << CRF_EQ_BIT | not_sp << CRF_SO_BIT; @@ -3356,18 +3247,16 @@ void helper_xststdcsp(CPUPPCState *env, uint32_t opcode) env->crf[BF(opcode)] = cc; } -void helper_xsrqpi(CPUPPCState *env, uint32_t opcode) +void helper_xsrqpi(CPUPPCState *env, uint32_t opcode, + ppc_vsr_t *xt, ppc_vsr_t *xb) { - ppc_vsr_t xb; - ppc_vsr_t xt; + ppc_vsr_t t = { }; uint8_t r = Rrm(opcode); uint8_t ex = Rc(opcode); uint8_t rmc = RMC(opcode); uint8_t rmode = 0; float_status tstat; - getVSR(rB(opcode) + 32, &xb, env); - memset(&xt, 0, sizeof(xt)); helper_reset_fpstatus(env); if (r == 0 && rmc == 0) { @@ -3396,13 +3285,13 @@ void helper_xsrqpi(CPUPPCState *env, uint32_t opcode) tstat = env->fp_status; set_float_exception_flags(0, &tstat); set_float_rounding_mode(rmode, &tstat); - xt.f128 = float128_round_to_int(xb.f128, &tstat); + t.f128 = float128_round_to_int(xb->f128, &tstat); env->fp_status.float_exception_flags |= tstat.float_exception_flags; if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { - if (float128_is_signaling_nan(xb.f128, &tstat)) { + if (float128_is_signaling_nan(xb->f128, &tstat)) { float_invalid_op_vxsnan(env, GETPC()); - xt.f128 = float128_snan_to_qnan(xt.f128); + t.f128 = float128_snan_to_qnan(t.f128); } } @@ -3410,23 +3299,21 @@ void helper_xsrqpi(CPUPPCState *env, uint32_t opcode) env->fp_status.float_exception_flags &= ~float_flag_inexact; } - helper_compute_fprf_float128(env, xt.f128); + helper_compute_fprf_float128(env, t.f128); do_float_check_status(env, GETPC()); - putVSR(rD(opcode) + 32, &xt, env); + *xt = t; } -void helper_xsrqpxp(CPUPPCState *env, uint32_t opcode) +void helper_xsrqpxp(CPUPPCState *env, uint32_t opcode, + ppc_vsr_t *xt, ppc_vsr_t *xb) { - ppc_vsr_t xb; - ppc_vsr_t xt; + ppc_vsr_t t = { }; uint8_t r = Rrm(opcode); uint8_t rmc = RMC(opcode); uint8_t rmode = 0; floatx80 round_res; float_status tstat; - getVSR(rB(opcode) + 32, &xb, env); - memset(&xt, 0, sizeof(xt)); helper_reset_fpstatus(env); if (r == 0 && rmc == 0) { @@ -3455,30 +3342,28 @@ void helper_xsrqpxp(CPUPPCState *env, uint32_t opcode) tstat = env->fp_status; set_float_exception_flags(0, &tstat); set_float_rounding_mode(rmode, &tstat); - round_res = float128_to_floatx80(xb.f128, &tstat); - xt.f128 = floatx80_to_float128(round_res, &tstat); + round_res = float128_to_floatx80(xb->f128, &tstat); + t.f128 = floatx80_to_float128(round_res, &tstat); env->fp_status.float_exception_flags |= tstat.float_exception_flags; if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { - if (float128_is_signaling_nan(xb.f128, &tstat)) { + if (float128_is_signaling_nan(xb->f128, &tstat)) { float_invalid_op_vxsnan(env, GETPC()); - xt.f128 = float128_snan_to_qnan(xt.f128); + t.f128 = float128_snan_to_qnan(t.f128); } } - helper_compute_fprf_float128(env, xt.f128); - putVSR(rD(opcode) + 32, &xt, env); + helper_compute_fprf_float128(env, t.f128); + *xt = t; do_float_check_status(env, GETPC()); } -void helper_xssqrtqp(CPUPPCState *env, uint32_t opcode) +void helper_xssqrtqp(CPUPPCState *env, uint32_t opcode, + ppc_vsr_t *xt, ppc_vsr_t *xb) { - ppc_vsr_t xb; - ppc_vsr_t xt; + ppc_vsr_t t = { }; float_status tstat; - getVSR(rB(opcode) + 32, &xb, env); - memset(&xt, 0, sizeof(xt)); helper_reset_fpstatus(env); tstat = env->fp_status; @@ -3487,34 +3372,32 @@ void helper_xssqrtqp(CPUPPCState *env, uint32_t opcode) } set_float_exception_flags(0, &tstat); - xt.f128 = float128_sqrt(xb.f128, &tstat); + t.f128 = float128_sqrt(xb->f128, &tstat); env->fp_status.float_exception_flags |= tstat.float_exception_flags; if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { - if (float128_is_signaling_nan(xb.f128, &tstat)) { + if (float128_is_signaling_nan(xb->f128, &tstat)) { float_invalid_op_vxsnan(env, GETPC()); - xt.f128 = float128_snan_to_qnan(xb.f128); - } else if (float128_is_quiet_nan(xb.f128, &tstat)) { - xt.f128 = xb.f128; - } else if (float128_is_neg(xb.f128) && !float128_is_zero(xb.f128)) { + t.f128 = float128_snan_to_qnan(xb->f128); + } else if (float128_is_quiet_nan(xb->f128, &tstat)) { + t.f128 = xb->f128; + } else if (float128_is_neg(xb->f128) && !float128_is_zero(xb->f128)) { float_invalid_op_vxsqrt(env, 1, GETPC()); - xt.f128 = float128_default_nan(&env->fp_status); + t.f128 = float128_default_nan(&env->fp_status); } } - helper_compute_fprf_float128(env, xt.f128); - putVSR(rD(opcode) + 32, &xt, env); + helper_compute_fprf_float128(env, t.f128); + *xt = t; do_float_check_status(env, GETPC()); } -void helper_xssubqp(CPUPPCState *env, uint32_t opcode) +void helper_xssubqp(CPUPPCState *env, uint32_t opcode, + ppc_vsr_t *xt, ppc_vsr_t *xa, ppc_vsr_t *xb) { - ppc_vsr_t xt, xa, xb; + ppc_vsr_t t = *xt; float_status tstat; - getVSR(rA(opcode) + 32, &xa, env); - getVSR(rB(opcode) + 32, &xb, env); - getVSR(rD(opcode) + 32, &xt, env); helper_reset_fpstatus(env); tstat = env->fp_status; @@ -3523,16 +3406,16 @@ void helper_xssubqp(CPUPPCState *env, uint32_t opcode) } set_float_exception_flags(0, &tstat); - xt.f128 = float128_sub(xa.f128, xb.f128, &tstat); + t.f128 = float128_sub(xa->f128, xb->f128, &tstat); env->fp_status.float_exception_flags |= tstat.float_exception_flags; if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { float_invalid_op_addsub(env, 1, GETPC(), - float128_classify(xa.f128) | - float128_classify(xb.f128)); + float128_classify(xa->f128) | + float128_classify(xb->f128)); } - helper_compute_fprf_float128(env, xt.f128); - putVSR(rD(opcode) + 32, &xt, env); + helper_compute_fprf_float128(env, t.f128); + *xt = t; do_float_check_status(env, GETPC()); } diff --git a/target/ppc/helper.h b/target/ppc/helper.h index 02b67a333e..380c9b1e2a 100644 --- a/target/ppc/helper.h +++ b/target/ppc/helper.h @@ -108,6 +108,10 @@ DEF_HELPER_FLAGS_1(ftsqrt, TCG_CALL_NO_RWG_SE, i32, i64) #define dh_ctype_avr ppc_avr_t * #define dh_is_signed_avr dh_is_signed_ptr +#define dh_alias_vsr ptr +#define dh_ctype_vsr ppc_vsr_t * +#define dh_is_signed_vsr dh_is_signed_ptr + DEF_HELPER_3(vavgub, void, avr, avr, avr) DEF_HELPER_3(vavguh, void, avr, avr, avr) DEF_HELPER_3(vavguw, void, avr, avr, avr) @@ -275,10 +279,10 @@ DEF_HELPER_3(stvebx, void, env, avr, tl) DEF_HELPER_3(stvehx, void, env, avr, tl) DEF_HELPER_3(stvewx, void, env, avr, tl) #if defined(TARGET_PPC64) -DEF_HELPER_4(lxvl, void, env, tl, tl, tl) -DEF_HELPER_4(lxvll, void, env, tl, tl, tl) -DEF_HELPER_4(stxvl, void, env, tl, tl, tl) -DEF_HELPER_4(stxvll, void, env, tl, tl, tl) +DEF_HELPER_4(lxvl, void, env, tl, vsr, tl) +DEF_HELPER_4(lxvll, void, env, tl, vsr, tl) +DEF_HELPER_4(stxvl, void, env, tl, vsr, tl) +DEF_HELPER_4(stxvll, void, env, tl, vsr, tl) #endif DEF_HELPER_4(vsumsws, void, env, avr, avr, avr) DEF_HELPER_4(vsum2sws, void, env, avr, avr, avr) @@ -361,178 +365,162 @@ DEF_HELPER_4(bcdsr, i32, avr, avr, avr, i32) DEF_HELPER_4(bcdtrunc, i32, avr, avr, avr, i32) DEF_HELPER_4(bcdutrunc, i32, avr, avr, avr, i32) -DEF_HELPER_2(xsadddp, void, env, i32) -DEF_HELPER_2(xsaddqp, void, env, i32) -DEF_HELPER_2(xssubdp, void, env, i32) -DEF_HELPER_2(xsmuldp, void, env, i32) -DEF_HELPER_2(xsmulqp, void, env, i32) -DEF_HELPER_2(xsdivdp, void, env, i32) -DEF_HELPER_2(xsdivqp, void, env, i32) -DEF_HELPER_2(xsredp, void, env, i32) -DEF_HELPER_2(xssqrtdp, void, env, i32) -DEF_HELPER_2(xsrsqrtedp, void, env, i32) -DEF_HELPER_2(xstdivdp, void, env, i32) -DEF_HELPER_2(xstsqrtdp, void, env, i32) -DEF_HELPER_2(xsmaddadp, void, env, i32) -DEF_HELPER_2(xsmaddmdp, void, env, i32) -DEF_HELPER_2(xsmsubadp, void, env, i32) -DEF_HELPER_2(xsmsubmdp, void, env, i32) -DEF_HELPER_2(xsnmaddadp, void, env, i32) -DEF_HELPER_2(xsnmaddmdp, void, env, i32) -DEF_HELPER_2(xsnmsubadp, void, env, i32) -DEF_HELPER_2(xsnmsubmdp, void, env, i32) -DEF_HELPER_2(xscmpeqdp, void, env, i32) -DEF_HELPER_2(xscmpgtdp, void, env, i32) -DEF_HELPER_2(xscmpgedp, void, env, i32) -DEF_HELPER_2(xscmpnedp, void, env, i32) -DEF_HELPER_2(xscmpexpdp, void, env, i32) -DEF_HELPER_2(xscmpexpqp, void, env, i32) -DEF_HELPER_2(xscmpodp, void, env, i32) -DEF_HELPER_2(xscmpudp, void, env, i32) -DEF_HELPER_2(xscmpoqp, void, env, i32) -DEF_HELPER_2(xscmpuqp, void, env, i32) -DEF_HELPER_2(xsmaxdp, void, env, i32) -DEF_HELPER_2(xsmindp, void, env, i32) -DEF_HELPER_2(xsmaxcdp, void, env, i32) -DEF_HELPER_2(xsmincdp, void, env, i32) -DEF_HELPER_2(xsmaxjdp, void, env, i32) -DEF_HELPER_2(xsminjdp, void, env, i32) -DEF_HELPER_2(xscvdphp, void, env, i32) -DEF_HELPER_2(xscvdpqp, void, env, i32) -DEF_HELPER_2(xscvdpsp, void, env, i32) +DEF_HELPER_4(xsadddp, void, env, vsr, vsr, vsr) +DEF_HELPER_5(xsaddqp, void, env, i32, vsr, vsr, vsr) +DEF_HELPER_4(xssubdp, void, env, vsr, vsr, vsr) +DEF_HELPER_4(xsmuldp, void, env, vsr, vsr, vsr) +DEF_HELPER_5(xsmulqp, void, env, i32, vsr, vsr, vsr) +DEF_HELPER_4(xsdivdp, void, env, vsr, vsr, vsr) +DEF_HELPER_5(xsdivqp, void, env, i32, vsr, vsr, vsr) +DEF_HELPER_3(xsredp, void, env, vsr, vsr) +DEF_HELPER_3(xssqrtdp, void, env, vsr, vsr) +DEF_HELPER_3(xsrsqrtedp, void, env, vsr, vsr) +DEF_HELPER_4(xstdivdp, void, env, i32, vsr, vsr) +DEF_HELPER_3(xstsqrtdp, void, env, i32, vsr) +DEF_HELPER_5(xsmadddp, void, env, vsr, vsr, vsr, vsr) +DEF_HELPER_5(xsmsubdp, void, env, vsr, vsr, vsr, vsr) +DEF_HELPER_5(xsnmadddp, void, env, vsr, vsr, vsr, vsr) +DEF_HELPER_5(xsnmsubdp, void, env, vsr, vsr, vsr, vsr) +DEF_HELPER_4(xscmpeqdp, void, env, vsr, vsr, vsr) +DEF_HELPER_4(xscmpgtdp, void, env, vsr, vsr, vsr) +DEF_HELPER_4(xscmpgedp, void, env, vsr, vsr, vsr) +DEF_HELPER_4(xscmpnedp, void, env, vsr, vsr, vsr) +DEF_HELPER_4(xscmpexpdp, void, env, i32, vsr, vsr) +DEF_HELPER_4(xscmpexpqp, void, env, i32, vsr, vsr) +DEF_HELPER_4(xscmpodp, void, env, i32, vsr, vsr) +DEF_HELPER_4(xscmpudp, void, env, i32, vsr, vsr) +DEF_HELPER_4(xscmpoqp, void, env, i32, vsr, vsr) +DEF_HELPER_4(xscmpuqp, void, env, i32, vsr, vsr) +DEF_HELPER_4(xsmaxdp, void, env, vsr, vsr, vsr) +DEF_HELPER_4(xsmindp, void, env, vsr, vsr, vsr) +DEF_HELPER_5(xsmaxcdp, void, env, i32, vsr, vsr, vsr) +DEF_HELPER_5(xsmincdp, void, env, i32, vsr, vsr, vsr) +DEF_HELPER_5(xsmaxjdp, void, env, i32, vsr, vsr, vsr) +DEF_HELPER_5(xsminjdp, void, env, i32, vsr, vsr, vsr) +DEF_HELPER_3(xscvdphp, void, env, vsr, vsr) +DEF_HELPER_4(xscvdpqp, void, env, i32, vsr, vsr) +DEF_HELPER_3(xscvdpsp, void, env, vsr, vsr) DEF_HELPER_2(xscvdpspn, i64, env, i64) -DEF_HELPER_2(xscvqpdp, void, env, i32) -DEF_HELPER_2(xscvqpsdz, void, env, i32) -DEF_HELPER_2(xscvqpswz, void, env, i32) -DEF_HELPER_2(xscvqpudz, void, env, i32) -DEF_HELPER_2(xscvqpuwz, void, env, i32) -DEF_HELPER_2(xscvhpdp, void, env, i32) -DEF_HELPER_2(xscvsdqp, void, env, i32) -DEF_HELPER_2(xscvspdp, void, env, i32) +DEF_HELPER_4(xscvqpdp, void, env, i32, vsr, vsr) +DEF_HELPER_4(xscvqpsdz, void, env, i32, vsr, vsr) +DEF_HELPER_4(xscvqpswz, void, env, i32, vsr, vsr) +DEF_HELPER_4(xscvqpudz, void, env, i32, vsr, vsr) +DEF_HELPER_4(xscvqpuwz, void, env, i32, vsr, vsr) +DEF_HELPER_3(xscvhpdp, void, env, vsr, vsr) +DEF_HELPER_4(xscvsdqp, void, env, i32, vsr, vsr) +DEF_HELPER_3(xscvspdp, void, env, vsr, vsr) DEF_HELPER_2(xscvspdpn, i64, env, i64) -DEF_HELPER_2(xscvdpsxds, void, env, i32) -DEF_HELPER_2(xscvdpsxws, void, env, i32) -DEF_HELPER_2(xscvdpuxds, void, env, i32) -DEF_HELPER_2(xscvdpuxws, void, env, i32) -DEF_HELPER_2(xscvsxddp, void, env, i32) -DEF_HELPER_2(xscvuxdsp, void, env, i32) -DEF_HELPER_2(xscvsxdsp, void, env, i32) -DEF_HELPER_2(xscvudqp, void, env, i32) -DEF_HELPER_2(xscvuxddp, void, env, i32) -DEF_HELPER_2(xststdcsp, void, env, i32) +DEF_HELPER_3(xscvdpsxds, void, env, vsr, vsr) +DEF_HELPER_3(xscvdpsxws, void, env, vsr, vsr) +DEF_HELPER_3(xscvdpuxds, void, env, vsr, vsr) +DEF_HELPER_3(xscvdpuxws, void, env, vsr, vsr) +DEF_HELPER_3(xscvsxddp, void, env, vsr, vsr) +DEF_HELPER_3(xscvuxdsp, void, env, vsr, vsr) +DEF_HELPER_3(xscvsxdsp, void, env, vsr, vsr) +DEF_HELPER_4(xscvudqp, void, env, i32, vsr, vsr) +DEF_HELPER_3(xscvuxddp, void, env, vsr, vsr) +DEF_HELPER_3(xststdcsp, void, env, i32, vsr) DEF_HELPER_2(xststdcdp, void, env, i32) DEF_HELPER_2(xststdcqp, void, env, i32) -DEF_HELPER_2(xsrdpi, void, env, i32) -DEF_HELPER_2(xsrdpic, void, env, i32) -DEF_HELPER_2(xsrdpim, void, env, i32) -DEF_HELPER_2(xsrdpip, void, env, i32) -DEF_HELPER_2(xsrdpiz, void, env, i32) -DEF_HELPER_2(xsrqpi, void, env, i32) -DEF_HELPER_2(xsrqpxp, void, env, i32) -DEF_HELPER_2(xssqrtqp, void, env, i32) -DEF_HELPER_2(xssubqp, void, env, i32) +DEF_HELPER_3(xsrdpi, void, env, vsr, vsr) +DEF_HELPER_3(xsrdpic, void, env, vsr, vsr) +DEF_HELPER_3(xsrdpim, void, env, vsr, vsr) +DEF_HELPER_3(xsrdpip, void, env, vsr, vsr) +DEF_HELPER_3(xsrdpiz, void, env, vsr, vsr) +DEF_HELPER_4(xsrqpi, void, env, i32, vsr, vsr) +DEF_HELPER_4(xsrqpxp, void, env, i32, vsr, vsr) +DEF_HELPER_4(xssqrtqp, void, env, i32, vsr, vsr) +DEF_HELPER_5(xssubqp, void, env, i32, vsr, vsr, vsr) -DEF_HELPER_2(xsaddsp, void, env, i32) -DEF_HELPER_2(xssubsp, void, env, i32) -DEF_HELPER_2(xsmulsp, void, env, i32) -DEF_HELPER_2(xsdivsp, void, env, i32) -DEF_HELPER_2(xsresp, void, env, i32) +DEF_HELPER_4(xsaddsp, void, env, vsr, vsr, vsr) +DEF_HELPER_4(xssubsp, void, env, vsr, vsr, vsr) +DEF_HELPER_4(xsmulsp, void, env, vsr, vsr, vsr) +DEF_HELPER_4(xsdivsp, void, env, vsr, vsr, vsr) +DEF_HELPER_3(xsresp, void, env, vsr, vsr) DEF_HELPER_2(xsrsp, i64, env, i64) -DEF_HELPER_2(xssqrtsp, void, env, i32) -DEF_HELPER_2(xsrsqrtesp, void, env, i32) -DEF_HELPER_2(xsmaddasp, void, env, i32) -DEF_HELPER_2(xsmaddmsp, void, env, i32) -DEF_HELPER_2(xsmsubasp, void, env, i32) -DEF_HELPER_2(xsmsubmsp, void, env, i32) -DEF_HELPER_2(xsnmaddasp, void, env, i32) -DEF_HELPER_2(xsnmaddmsp, void, env, i32) -DEF_HELPER_2(xsnmsubasp, void, env, i32) -DEF_HELPER_2(xsnmsubmsp, void, env, i32) +DEF_HELPER_3(xssqrtsp, void, env, vsr, vsr) +DEF_HELPER_3(xsrsqrtesp, void, env, vsr, vsr) +DEF_HELPER_5(xsmaddsp, void, env, vsr, vsr, vsr, vsr) +DEF_HELPER_5(xsmsubsp, void, env, vsr, vsr, vsr, vsr) +DEF_HELPER_5(xsnmaddsp, void, env, vsr, vsr, vsr, vsr) +DEF_HELPER_5(xsnmsubsp, void, env, vsr, vsr, vsr, vsr) -DEF_HELPER_2(xvadddp, void, env, i32) -DEF_HELPER_2(xvsubdp, void, env, i32) -DEF_HELPER_2(xvmuldp, void, env, i32) -DEF_HELPER_2(xvdivdp, void, env, i32) -DEF_HELPER_2(xvredp, void, env, i32) -DEF_HELPER_2(xvsqrtdp, void, env, i32) -DEF_HELPER_2(xvrsqrtedp, void, env, i32) -DEF_HELPER_2(xvtdivdp, void, env, i32) -DEF_HELPER_2(xvtsqrtdp, void, env, i32) -DEF_HELPER_2(xvmaddadp, void, env, i32) -DEF_HELPER_2(xvmaddmdp, void, env, i32) -DEF_HELPER_2(xvmsubadp, void, env, i32) -DEF_HELPER_2(xvmsubmdp, void, env, i32) -DEF_HELPER_2(xvnmaddadp, void, env, i32) -DEF_HELPER_2(xvnmaddmdp, void, env, i32) -DEF_HELPER_2(xvnmsubadp, void, env, i32) -DEF_HELPER_2(xvnmsubmdp, void, env, i32) -DEF_HELPER_2(xvmaxdp, void, env, i32) -DEF_HELPER_2(xvmindp, void, env, i32) -DEF_HELPER_2(xvcmpeqdp, void, env, i32) -DEF_HELPER_2(xvcmpgedp, void, env, i32) -DEF_HELPER_2(xvcmpgtdp, void, env, i32) -DEF_HELPER_2(xvcmpnedp, void, env, i32) -DEF_HELPER_2(xvcvdpsp, void, env, i32) -DEF_HELPER_2(xvcvdpsxds, void, env, i32) -DEF_HELPER_2(xvcvdpsxws, void, env, i32) -DEF_HELPER_2(xvcvdpuxds, void, env, i32) -DEF_HELPER_2(xvcvdpuxws, void, env, i32) -DEF_HELPER_2(xvcvsxddp, void, env, i32) -DEF_HELPER_2(xvcvuxddp, void, env, i32) -DEF_HELPER_2(xvcvsxwdp, void, env, i32) -DEF_HELPER_2(xvcvuxwdp, void, env, i32) -DEF_HELPER_2(xvrdpi, void, env, i32) -DEF_HELPER_2(xvrdpic, void, env, i32) -DEF_HELPER_2(xvrdpim, void, env, i32) -DEF_HELPER_2(xvrdpip, void, env, i32) -DEF_HELPER_2(xvrdpiz, void, env, i32) +DEF_HELPER_4(xvadddp, void, env, vsr, vsr, vsr) +DEF_HELPER_4(xvsubdp, void, env, vsr, vsr, vsr) +DEF_HELPER_4(xvmuldp, void, env, vsr, vsr, vsr) +DEF_HELPER_4(xvdivdp, void, env, vsr, vsr, vsr) +DEF_HELPER_3(xvredp, void, env, vsr, vsr) +DEF_HELPER_3(xvsqrtdp, void, env, vsr, vsr) +DEF_HELPER_3(xvrsqrtedp, void, env, vsr, vsr) +DEF_HELPER_4(xvtdivdp, void, env, i32, vsr, vsr) +DEF_HELPER_3(xvtsqrtdp, void, env, i32, vsr) +DEF_HELPER_5(xvmadddp, void, env, vsr, vsr, vsr, vsr) +DEF_HELPER_5(xvmsubdp, void, env, vsr, vsr, vsr, vsr) +DEF_HELPER_5(xvnmadddp, void, env, vsr, vsr, vsr, vsr) +DEF_HELPER_5(xvnmsubdp, void, env, vsr, vsr, vsr, vsr) +DEF_HELPER_4(xvmaxdp, void, env, vsr, vsr, vsr) +DEF_HELPER_4(xvmindp, void, env, vsr, vsr, vsr) +DEF_HELPER_FLAGS_4(xvcmpeqdp, TCG_CALL_NO_RWG, i32, env, vsr, vsr, vsr) +DEF_HELPER_FLAGS_4(xvcmpgedp, TCG_CALL_NO_RWG, i32, env, vsr, vsr, vsr) +DEF_HELPER_FLAGS_4(xvcmpgtdp, TCG_CALL_NO_RWG, i32, env, vsr, vsr, vsr) +DEF_HELPER_FLAGS_4(xvcmpnedp, TCG_CALL_NO_RWG, i32, env, vsr, vsr, vsr) +DEF_HELPER_3(xvcvdpsp, void, env, vsr, vsr) +DEF_HELPER_3(xvcvdpsxds, void, env, vsr, vsr) +DEF_HELPER_3(xvcvdpsxws, void, env, vsr, vsr) +DEF_HELPER_3(xvcvdpuxds, void, env, vsr, vsr) +DEF_HELPER_3(xvcvdpuxws, void, env, vsr, vsr) +DEF_HELPER_3(xvcvsxddp, void, env, vsr, vsr) +DEF_HELPER_3(xvcvuxddp, void, env, vsr, vsr) +DEF_HELPER_3(xvcvsxwdp, void, env, vsr, vsr) +DEF_HELPER_3(xvcvuxwdp, void, env, vsr, vsr) +DEF_HELPER_3(xvrdpi, void, env, vsr, vsr) +DEF_HELPER_3(xvrdpic, void, env, vsr, vsr) +DEF_HELPER_3(xvrdpim, void, env, vsr, vsr) +DEF_HELPER_3(xvrdpip, void, env, vsr, vsr) +DEF_HELPER_3(xvrdpiz, void, env, vsr, vsr) -DEF_HELPER_2(xvaddsp, void, env, i32) -DEF_HELPER_2(xvsubsp, void, env, i32) -DEF_HELPER_2(xvmulsp, void, env, i32) -DEF_HELPER_2(xvdivsp, void, env, i32) -DEF_HELPER_2(xvresp, void, env, i32) -DEF_HELPER_2(xvsqrtsp, void, env, i32) -DEF_HELPER_2(xvrsqrtesp, void, env, i32) -DEF_HELPER_2(xvtdivsp, void, env, i32) -DEF_HELPER_2(xvtsqrtsp, void, env, i32) -DEF_HELPER_2(xvmaddasp, void, env, i32) -DEF_HELPER_2(xvmaddmsp, void, env, i32) -DEF_HELPER_2(xvmsubasp, void, env, i32) -DEF_HELPER_2(xvmsubmsp, void, env, i32) -DEF_HELPER_2(xvnmaddasp, void, env, i32) -DEF_HELPER_2(xvnmaddmsp, void, env, i32) -DEF_HELPER_2(xvnmsubasp, void, env, i32) -DEF_HELPER_2(xvnmsubmsp, void, env, i32) -DEF_HELPER_2(xvmaxsp, void, env, i32) -DEF_HELPER_2(xvminsp, void, env, i32) -DEF_HELPER_2(xvcmpeqsp, void, env, i32) -DEF_HELPER_2(xvcmpgesp, void, env, i32) -DEF_HELPER_2(xvcmpgtsp, void, env, i32) -DEF_HELPER_2(xvcmpnesp, void, env, i32) -DEF_HELPER_2(xvcvspdp, void, env, i32) -DEF_HELPER_2(xvcvsphp, void, env, i32) -DEF_HELPER_2(xvcvhpsp, void, env, i32) -DEF_HELPER_2(xvcvspsxds, void, env, i32) -DEF_HELPER_2(xvcvspsxws, void, env, i32) -DEF_HELPER_2(xvcvspuxds, void, env, i32) -DEF_HELPER_2(xvcvspuxws, void, env, i32) -DEF_HELPER_2(xvcvsxdsp, void, env, i32) -DEF_HELPER_2(xvcvuxdsp, void, env, i32) -DEF_HELPER_2(xvcvsxwsp, void, env, i32) -DEF_HELPER_2(xvcvuxwsp, void, env, i32) +DEF_HELPER_4(xvaddsp, void, env, vsr, vsr, vsr) +DEF_HELPER_4(xvsubsp, void, env, vsr, vsr, vsr) +DEF_HELPER_4(xvmulsp, void, env, vsr, vsr, vsr) +DEF_HELPER_4(xvdivsp, void, env, vsr, vsr, vsr) +DEF_HELPER_3(xvresp, void, env, vsr, vsr) +DEF_HELPER_3(xvsqrtsp, void, env, vsr, vsr) +DEF_HELPER_3(xvrsqrtesp, void, env, vsr, vsr) +DEF_HELPER_4(xvtdivsp, void, env, i32, vsr, vsr) +DEF_HELPER_3(xvtsqrtsp, void, env, i32, vsr) +DEF_HELPER_5(xvmaddsp, void, env, vsr, vsr, vsr, vsr) +DEF_HELPER_5(xvmsubsp, void, env, vsr, vsr, vsr, vsr) +DEF_HELPER_5(xvnmaddsp, void, env, vsr, vsr, vsr, vsr) +DEF_HELPER_5(xvnmsubsp, void, env, vsr, vsr, vsr, vsr) +DEF_HELPER_4(xvmaxsp, void, env, vsr, vsr, vsr) +DEF_HELPER_4(xvminsp, void, env, vsr, vsr, vsr) +DEF_HELPER_FLAGS_4(xvcmpeqsp, TCG_CALL_NO_RWG, i32, env, vsr, vsr, vsr) +DEF_HELPER_FLAGS_4(xvcmpgesp, TCG_CALL_NO_RWG, i32, env, vsr, vsr, vsr) +DEF_HELPER_FLAGS_4(xvcmpgtsp, TCG_CALL_NO_RWG, i32, env, vsr, vsr, vsr) +DEF_HELPER_FLAGS_4(xvcmpnesp, TCG_CALL_NO_RWG, i32, env, vsr, vsr, vsr) +DEF_HELPER_3(xvcvspdp, void, env, vsr, vsr) +DEF_HELPER_3(xvcvsphp, void, env, vsr, vsr) +DEF_HELPER_3(xvcvhpsp, void, env, vsr, vsr) +DEF_HELPER_3(xvcvspsxds, void, env, vsr, vsr) +DEF_HELPER_3(xvcvspsxws, void, env, vsr, vsr) +DEF_HELPER_3(xvcvspuxds, void, env, vsr, vsr) +DEF_HELPER_3(xvcvspuxws, void, env, vsr, vsr) +DEF_HELPER_3(xvcvsxdsp, void, env, vsr, vsr) +DEF_HELPER_3(xvcvuxdsp, void, env, vsr, vsr) +DEF_HELPER_3(xvcvsxwsp, void, env, vsr, vsr) +DEF_HELPER_3(xvcvuxwsp, void, env, vsr, vsr) DEF_HELPER_2(xvtstdcsp, void, env, i32) DEF_HELPER_2(xvtstdcdp, void, env, i32) -DEF_HELPER_2(xvrspi, void, env, i32) -DEF_HELPER_2(xvrspic, void, env, i32) -DEF_HELPER_2(xvrspim, void, env, i32) -DEF_HELPER_2(xvrspip, void, env, i32) -DEF_HELPER_2(xvrspiz, void, env, i32) -DEF_HELPER_2(xxperm, void, env, i32) -DEF_HELPER_2(xxpermr, void, env, i32) -DEF_HELPER_4(xxextractuw, void, env, tl, tl, i32) -DEF_HELPER_4(xxinsertw, void, env, tl, tl, i32) -DEF_HELPER_2(xvxsigsp, void, env, i32) +DEF_HELPER_3(xvrspi, void, env, vsr, vsr) +DEF_HELPER_3(xvrspic, void, env, vsr, vsr) +DEF_HELPER_3(xvrspim, void, env, vsr, vsr) +DEF_HELPER_3(xvrspip, void, env, vsr, vsr) +DEF_HELPER_3(xvrspiz, void, env, vsr, vsr) +DEF_HELPER_4(xxperm, void, env, vsr, vsr, vsr) +DEF_HELPER_4(xxpermr, void, env, vsr, vsr, vsr) +DEF_HELPER_4(xxextractuw, void, env, vsr, vsr, i32) +DEF_HELPER_4(xxinsertw, void, env, vsr, vsr, i32) +DEF_HELPER_3(xvxsigsp, void, env, vsr, vsr) DEF_HELPER_2(efscfsi, i32, env, i32) DEF_HELPER_2(efscfui, i32, env, i32) diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c index 8ce89f2ad9..5c07ef3e4d 100644 --- a/target/ppc/int_helper.c +++ b/target/ppc/int_helper.c @@ -1899,41 +1899,35 @@ VEXTRACT(uw, u32) VEXTRACT(d, u64) #undef VEXTRACT -void helper_xxextractuw(CPUPPCState *env, target_ulong xtn, - target_ulong xbn, uint32_t index) +void helper_xxextractuw(CPUPPCState *env, ppc_vsr_t *xt, + ppc_vsr_t *xb, uint32_t index) { - ppc_vsr_t xt, xb; + ppc_vsr_t t = { }; size_t es = sizeof(uint32_t); uint32_t ext_index; int i; - getVSR(xbn, &xb, env); - memset(&xt, 0, sizeof(xt)); - ext_index = index; for (i = 0; i < es; i++, ext_index++) { - xt.VsrB(8 - es + i) = xb.VsrB(ext_index % 16); + t.VsrB(8 - es + i) = xb->VsrB(ext_index % 16); } - putVSR(xtn, &xt, env); + *xt = t; } -void helper_xxinsertw(CPUPPCState *env, target_ulong xtn, - target_ulong xbn, uint32_t index) +void helper_xxinsertw(CPUPPCState *env, ppc_vsr_t *xt, + ppc_vsr_t *xb, uint32_t index) { - ppc_vsr_t xt, xb; + ppc_vsr_t t = *xt; size_t es = sizeof(uint32_t); int ins_index, i = 0; - getVSR(xbn, &xb, env); - getVSR(xtn, &xt, env); - ins_index = index; for (i = 0; i < es && ins_index < 16; i++, ins_index++) { - xt.VsrB(ins_index) = xb.VsrB(8 - es + i); + t.VsrB(ins_index) = xb->VsrB(8 - es + i); } - putVSR(xtn, &xt, env); + *xt = t; } #define VEXT_SIGNED(name, element, cast) \ diff --git a/target/ppc/internal.h b/target/ppc/internal.h index fb6f64ed1e..d3d327e548 100644 --- a/target/ppc/internal.h +++ b/target/ppc/internal.h @@ -204,18 +204,6 @@ EXTRACT_HELPER(IMM8, 11, 8); EXTRACT_HELPER(DCMX, 16, 7); EXTRACT_HELPER_SPLIT_3(DCMX_XV, 5, 16, 0, 1, 2, 5, 1, 6, 6); -static inline void getVSR(int n, ppc_vsr_t *vsr, CPUPPCState *env) -{ - vsr->VsrD(0) = env->vsr[n].VsrD(0); - vsr->VsrD(1) = env->vsr[n].VsrD(1); -} - -static inline void putVSR(int n, ppc_vsr_t *vsr, CPUPPCState *env) -{ - env->vsr[n].VsrD(0) = vsr->VsrD(0); - env->vsr[n].VsrD(1) = vsr->VsrD(1); -} - void helper_compute_fprf_float16(CPUPPCState *env, float16 arg); void helper_compute_fprf_float32(CPUPPCState *env, float32 arg); void helper_compute_fprf_float128(CPUPPCState *env, float128 arg); diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index 4b4989c0af..8a06d3171e 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -2650,7 +2650,7 @@ int kvmppc_define_rtas_kernel_token(uint32_t token, const char *function) return -ENOENT; } - strncpy(args.name, function, sizeof(args.name)); + strncpy(args.name, function, sizeof(args.name) - 1); return kvm_vm_ioctl(kvm_state, KVM_PPC_RTAS_DEFINE_TOKEN, &args); } @@ -2944,3 +2944,12 @@ void kvmppc_set_reg_ppc_online(PowerPCCPU *cpu, unsigned int online) kvm_set_one_reg(cs, KVM_REG_PPC_ONLINE, &online); } } + +void kvmppc_set_reg_tb_offset(PowerPCCPU *cpu, int64_t tb_offset) +{ + CPUState *cs = CPU(cpu); + + if (kvm_enabled()) { + kvm_set_one_reg(cs, KVM_REG_PPC_TB_OFFSET, &tb_offset); + } +} diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h index 45776cad79..98bd7d5da6 100644 --- a/target/ppc/kvm_ppc.h +++ b/target/ppc/kvm_ppc.h @@ -80,6 +80,7 @@ bool kvmppc_pvr_workaround_required(PowerPCCPU *cpu); bool kvmppc_hpt_needs_host_contiguous_pages(void); void kvm_check_mmu(PowerPCCPU *cpu, Error **errp); void kvmppc_set_reg_ppc_online(PowerPCCPU *cpu, unsigned int online); +void kvmppc_set_reg_tb_offset(PowerPCCPU *cpu, int64_t tb_offset); #else @@ -206,6 +207,10 @@ static inline void kvmppc_set_reg_ppc_online(PowerPCCPU *cpu, return; } +static inline void kvmppc_set_reg_tb_offset(PowerPCCPU *cpu, int64_t tb_offset) +{ +} + #ifndef CONFIG_USER_ONLY static inline bool kvmppc_spapr_use_multitce(void) { @@ -394,6 +399,11 @@ static inline int kvmppc_resize_hpt_commit(PowerPCCPU *cpu, return -ENOSYS; } +static inline bool kvmppc_pvr_workaround_required(PowerPCCPU *cpu) +{ + return false; +} + #endif #ifndef CONFIG_KVM diff --git a/target/ppc/machine.c b/target/ppc/machine.c index 5ad7b40f45..e82f5de9db 100644 --- a/target/ppc/machine.c +++ b/target/ppc/machine.c @@ -378,11 +378,9 @@ static int cpu_post_load(void *opaque, int version_id) * receive the PVR it expects as a workaround. * */ -#if defined(CONFIG_KVM) if (kvmppc_pvr_workaround_required(cpu)) { env->spr[SPR_PVR] = env->spr_cb[SPR_PVR].default_value; } -#endif env->lr = env->spr[SPR_LR]; env->ctr = env->spr[SPR_CTR]; diff --git a/target/ppc/mem_helper.c b/target/ppc/mem_helper.c index 5b0f9ee50d..6f4ffa3661 100644 --- a/target/ppc/mem_helper.c +++ b/target/ppc/mem_helper.c @@ -415,28 +415,28 @@ STVE(stvewx, cpu_stl_data_ra, bswap32, u32) #define VSX_LXVL(name, lj) \ void helper_##name(CPUPPCState *env, target_ulong addr, \ - target_ulong xt_num, target_ulong rb) \ + ppc_vsr_t *xt, target_ulong rb) \ { \ - int i; \ - ppc_vsr_t xt; \ + ppc_vsr_t t; \ uint64_t nb = GET_NB(rb); \ + int i; \ \ - xt.s128 = int128_zero(); \ + t.s128 = int128_zero(); \ if (nb) { \ nb = (nb >= 16) ? 16 : nb; \ if (msr_le && !lj) { \ for (i = 16; i > 16 - nb; i--) { \ - xt.VsrB(i - 1) = cpu_ldub_data_ra(env, addr, GETPC()); \ + t.VsrB(i - 1) = cpu_ldub_data_ra(env, addr, GETPC()); \ addr = addr_add(env, addr, 1); \ } \ } else { \ for (i = 0; i < nb; i++) { \ - xt.VsrB(i) = cpu_ldub_data_ra(env, addr, GETPC()); \ + t.VsrB(i) = cpu_ldub_data_ra(env, addr, GETPC()); \ addr = addr_add(env, addr, 1); \ } \ } \ } \ - putVSR(xt_num, &xt, env); \ + *xt = t; \ } VSX_LXVL(lxvl, 0) @@ -445,25 +445,24 @@ VSX_LXVL(lxvll, 1) #define VSX_STXVL(name, lj) \ void helper_##name(CPUPPCState *env, target_ulong addr, \ - target_ulong xt_num, target_ulong rb) \ + ppc_vsr_t *xt, target_ulong rb) \ { \ - int i; \ - ppc_vsr_t xt; \ target_ulong nb = GET_NB(rb); \ + int i; \ \ if (!nb) { \ return; \ } \ - getVSR(xt_num, &xt, env); \ + \ nb = (nb >= 16) ? 16 : nb; \ if (msr_le && !lj) { \ for (i = 16; i > 16 - nb; i--) { \ - cpu_stb_data_ra(env, addr, xt.VsrB(i - 1), GETPC()); \ + cpu_stb_data_ra(env, addr, xt->VsrB(i - 1), GETPC()); \ addr = addr_add(env, addr, 1); \ } \ } else { \ for (i = 0; i < nb; i++) { \ - cpu_stb_data_ra(env, addr, xt.VsrB(i), GETPC()); \ + cpu_stb_data_ra(env, addr, xt->VsrB(i), GETPC()); \ addr = addr_add(env, addr, 1); \ } \ } \ diff --git a/target/ppc/monitor.c b/target/ppc/monitor.c index 7f8360d903..a5a177d717 100644 --- a/target/ppc/monitor.c +++ b/target/ppc/monitor.c @@ -27,7 +27,7 @@ #include "monitor/monitor.h" #include "qemu/ctype.h" #include "monitor/hmp-target.h" -#include "hmp.h" +#include "monitor/hmp.h" static target_long monitor_get_ccr(const struct MonitorDef *md, int val) { diff --git a/target/ppc/translate/vsx-impl.inc.c b/target/ppc/translate/vsx-impl.inc.c index e9b7562f84..3922686ad6 100644 --- a/target/ppc/translate/vsx-impl.inc.c +++ b/target/ppc/translate/vsx-impl.inc.c @@ -20,6 +20,13 @@ static inline void set_cpu_vsrl(int n, TCGv_i64 src) tcg_gen_st_i64(src, cpu_env, vsr64_offset(n, false)); } +static inline TCGv_ptr gen_vsr_ptr(int reg) +{ + TCGv_ptr r = tcg_temp_new_ptr(); + tcg_gen_addi_ptr(r, cpu_env, vsr_full_offset(reg)); + return r; +} + #define VSX_LOAD_SCALAR(name, operation) \ static void gen_##name(DisasContext *ctx) \ { \ @@ -337,29 +344,30 @@ VSX_VECTOR_STORE(stxv, st_i64, 0) VSX_VECTOR_STORE(stxvx, st_i64, 1) #ifdef TARGET_PPC64 -#define VSX_VECTOR_LOAD_STORE_LENGTH(name) \ -static void gen_##name(DisasContext *ctx) \ -{ \ - TCGv EA, xt; \ - \ - if (xT(ctx->opcode) < 32) { \ - if (unlikely(!ctx->vsx_enabled)) { \ - gen_exception(ctx, POWERPC_EXCP_VSXU); \ - return; \ - } \ - } else { \ - if (unlikely(!ctx->altivec_enabled)) { \ - gen_exception(ctx, POWERPC_EXCP_VPU); \ - return; \ - } \ - } \ - EA = tcg_temp_new(); \ - xt = tcg_const_tl(xT(ctx->opcode)); \ - gen_set_access_type(ctx, ACCESS_INT); \ - gen_addr_register(ctx, EA); \ - gen_helper_##name(cpu_env, EA, xt, cpu_gpr[rB(ctx->opcode)]); \ - tcg_temp_free(EA); \ - tcg_temp_free(xt); \ +#define VSX_VECTOR_LOAD_STORE_LENGTH(name) \ +static void gen_##name(DisasContext *ctx) \ +{ \ + TCGv EA; \ + TCGv_ptr xt; \ + \ + if (xT(ctx->opcode) < 32) { \ + if (unlikely(!ctx->vsx_enabled)) { \ + gen_exception(ctx, POWERPC_EXCP_VSXU); \ + return; \ + } \ + } else { \ + if (unlikely(!ctx->altivec_enabled)) { \ + gen_exception(ctx, POWERPC_EXCP_VPU); \ + return; \ + } \ + } \ + EA = tcg_temp_new(); \ + xt = gen_vsr_ptr(xT(ctx->opcode)); \ + gen_set_access_type(ctx, ACCESS_INT); \ + gen_addr_register(ctx, EA); \ + gen_helper_##name(cpu_env, EA, xt, cpu_gpr[rB(ctx->opcode)]); \ + tcg_temp_free(EA); \ + tcg_temp_free_ptr(xt); \ } VSX_VECTOR_LOAD_STORE_LENGTH(lxvl) @@ -958,6 +966,57 @@ VSX_VECTOR_MOVE(xvnabssp, OP_NABS, SGN_MASK_SP) VSX_VECTOR_MOVE(xvnegsp, OP_NEG, SGN_MASK_SP) VSX_VECTOR_MOVE(xvcpsgnsp, OP_CPSGN, SGN_MASK_SP) +#define VSX_CMP(name, op1, op2, inval, type) \ +static void gen_##name(DisasContext *ctx) \ +{ \ + TCGv_i32 ignored; \ + TCGv_ptr xt, xa, xb; \ + if (unlikely(!ctx->vsx_enabled)) { \ + gen_exception(ctx, POWERPC_EXCP_VSXU); \ + return; \ + } \ + xt = gen_vsr_ptr(xT(ctx->opcode)); \ + xa = gen_vsr_ptr(xA(ctx->opcode)); \ + xb = gen_vsr_ptr(xB(ctx->opcode)); \ + if ((ctx->opcode >> (31 - 21)) & 1) { \ + gen_helper_##name(cpu_crf[6], cpu_env, xt, xa, xb); \ + } else { \ + ignored = tcg_temp_new_i32(); \ + gen_helper_##name(ignored, cpu_env, xt, xa, xb); \ + tcg_temp_free_i32(ignored); \ + } \ + gen_helper_float_check_status(cpu_env); \ + tcg_temp_free_ptr(xt); \ + tcg_temp_free_ptr(xa); \ + tcg_temp_free_ptr(xb); \ +} + +VSX_CMP(xvcmpeqdp, 0x0C, 0x0C, 0, PPC2_VSX) +VSX_CMP(xvcmpgedp, 0x0C, 0x0E, 0, PPC2_VSX) +VSX_CMP(xvcmpgtdp, 0x0C, 0x0D, 0, PPC2_VSX) +VSX_CMP(xvcmpnedp, 0x0C, 0x0F, 0, PPC2_ISA300) +VSX_CMP(xvcmpeqsp, 0x0C, 0x08, 0, PPC2_VSX) +VSX_CMP(xvcmpgesp, 0x0C, 0x0A, 0, PPC2_VSX) +VSX_CMP(xvcmpgtsp, 0x0C, 0x09, 0, PPC2_VSX) +VSX_CMP(xvcmpnesp, 0x0C, 0x0B, 0, PPC2_VSX) + +static void gen_xscvqpdp(DisasContext *ctx) +{ + TCGv_i32 opc; + TCGv_ptr xt, xb; + if (unlikely(!ctx->vsx_enabled)) { + gen_exception(ctx, POWERPC_EXCP_VSXU); + return; + } + opc = tcg_const_i32(ctx->opcode); + xt = gen_vsr_ptr(xT(ctx->opcode)); + xb = gen_vsr_ptr(xB(ctx->opcode)); + gen_helper_xscvqpdp(cpu_env, opc, xt, xb); + tcg_temp_free_i32(opc); + tcg_temp_free_ptr(xt); + tcg_temp_free_ptr(xb); +} + #define GEN_VSX_HELPER_2(name, op1, op2, inval, type) \ static void gen_##name(DisasContext *ctx) \ { \ @@ -971,6 +1030,128 @@ static void gen_##name(DisasContext *ctx) \ tcg_temp_free_i32(opc); \ } +#define GEN_VSX_HELPER_X3(name, op1, op2, inval, type) \ +static void gen_##name(DisasContext *ctx) \ +{ \ + TCGv_ptr xt, xa, xb; \ + if (unlikely(!ctx->vsx_enabled)) { \ + gen_exception(ctx, POWERPC_EXCP_VSXU); \ + return; \ + } \ + xt = gen_vsr_ptr(xT(ctx->opcode)); \ + xa = gen_vsr_ptr(xA(ctx->opcode)); \ + xb = gen_vsr_ptr(xB(ctx->opcode)); \ + gen_helper_##name(cpu_env, xt, xa, xb); \ + tcg_temp_free_ptr(xt); \ + tcg_temp_free_ptr(xa); \ + tcg_temp_free_ptr(xb); \ +} + +#define GEN_VSX_HELPER_X2(name, op1, op2, inval, type) \ +static void gen_##name(DisasContext *ctx) \ +{ \ + TCGv_ptr xt, xb; \ + if (unlikely(!ctx->vsx_enabled)) { \ + gen_exception(ctx, POWERPC_EXCP_VSXU); \ + return; \ + } \ + xt = gen_vsr_ptr(xT(ctx->opcode)); \ + xb = gen_vsr_ptr(xB(ctx->opcode)); \ + gen_helper_##name(cpu_env, xt, xb); \ + tcg_temp_free_ptr(xt); \ + tcg_temp_free_ptr(xb); \ +} + +#define GEN_VSX_HELPER_X2_AB(name, op1, op2, inval, type) \ +static void gen_##name(DisasContext *ctx) \ +{ \ + TCGv_i32 opc; \ + TCGv_ptr xa, xb; \ + if (unlikely(!ctx->vsx_enabled)) { \ + gen_exception(ctx, POWERPC_EXCP_VSXU); \ + return; \ + } \ + opc = tcg_const_i32(ctx->opcode); \ + xa = gen_vsr_ptr(xA(ctx->opcode)); \ + xb = gen_vsr_ptr(xB(ctx->opcode)); \ + gen_helper_##name(cpu_env, opc, xa, xb); \ + tcg_temp_free_i32(opc); \ + tcg_temp_free_ptr(xa); \ + tcg_temp_free_ptr(xb); \ +} + +#define GEN_VSX_HELPER_X1(name, op1, op2, inval, type) \ +static void gen_##name(DisasContext *ctx) \ +{ \ + TCGv_i32 opc; \ + TCGv_ptr xb; \ + if (unlikely(!ctx->vsx_enabled)) { \ + gen_exception(ctx, POWERPC_EXCP_VSXU); \ + return; \ + } \ + opc = tcg_const_i32(ctx->opcode); \ + xb = gen_vsr_ptr(xB(ctx->opcode)); \ + gen_helper_##name(cpu_env, opc, xb); \ + tcg_temp_free_i32(opc); \ + tcg_temp_free_ptr(xb); \ +} + +#define GEN_VSX_HELPER_R3(name, op1, op2, inval, type) \ +static void gen_##name(DisasContext *ctx) \ +{ \ + TCGv_i32 opc; \ + TCGv_ptr xt, xa, xb; \ + if (unlikely(!ctx->vsx_enabled)) { \ + gen_exception(ctx, POWERPC_EXCP_VSXU); \ + return; \ + } \ + opc = tcg_const_i32(ctx->opcode); \ + xt = gen_vsr_ptr(rD(ctx->opcode) + 32); \ + xa = gen_vsr_ptr(rA(ctx->opcode) + 32); \ + xb = gen_vsr_ptr(rB(ctx->opcode) + 32); \ + gen_helper_##name(cpu_env, opc, xt, xa, xb); \ + tcg_temp_free_i32(opc); \ + tcg_temp_free_ptr(xt); \ + tcg_temp_free_ptr(xa); \ + tcg_temp_free_ptr(xb); \ +} + +#define GEN_VSX_HELPER_R2(name, op1, op2, inval, type) \ +static void gen_##name(DisasContext *ctx) \ +{ \ + TCGv_i32 opc; \ + TCGv_ptr xt, xb; \ + if (unlikely(!ctx->vsx_enabled)) { \ + gen_exception(ctx, POWERPC_EXCP_VSXU); \ + return; \ + } \ + opc = tcg_const_i32(ctx->opcode); \ + xt = gen_vsr_ptr(rD(ctx->opcode) + 32); \ + xb = gen_vsr_ptr(rB(ctx->opcode) + 32); \ + gen_helper_##name(cpu_env, opc, xt, xb); \ + tcg_temp_free_i32(opc); \ + tcg_temp_free_ptr(xt); \ + tcg_temp_free_ptr(xb); \ +} + +#define GEN_VSX_HELPER_R2_AB(name, op1, op2, inval, type) \ +static void gen_##name(DisasContext *ctx) \ +{ \ + TCGv_i32 opc; \ + TCGv_ptr xa, xb; \ + if (unlikely(!ctx->vsx_enabled)) { \ + gen_exception(ctx, POWERPC_EXCP_VSXU); \ + return; \ + } \ + opc = tcg_const_i32(ctx->opcode); \ + xa = gen_vsr_ptr(rA(ctx->opcode) + 32); \ + xb = gen_vsr_ptr(rB(ctx->opcode) + 32); \ + gen_helper_##name(cpu_env, opc, xa, xb); \ + tcg_temp_free_i32(opc); \ + tcg_temp_free_ptr(xa); \ + tcg_temp_free_ptr(xb); \ +} + #define GEN_VSX_HELPER_XT_XB_ENV(name, op1, op2, inval, type) \ static void gen_##name(DisasContext *ctx) \ { \ @@ -989,176 +1170,180 @@ static void gen_##name(DisasContext *ctx) \ tcg_temp_free_i64(t1); \ } -GEN_VSX_HELPER_2(xsadddp, 0x00, 0x04, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xsaddqp, 0x04, 0x00, 0, PPC2_ISA300) -GEN_VSX_HELPER_2(xssubdp, 0x00, 0x05, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xsmuldp, 0x00, 0x06, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xsmulqp, 0x04, 0x01, 0, PPC2_ISA300) -GEN_VSX_HELPER_2(xsdivdp, 0x00, 0x07, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xsdivqp, 0x04, 0x11, 0, PPC2_ISA300) -GEN_VSX_HELPER_2(xsredp, 0x14, 0x05, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xssqrtdp, 0x16, 0x04, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xsrsqrtedp, 0x14, 0x04, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xstdivdp, 0x14, 0x07, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xstsqrtdp, 0x14, 0x06, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xsmaddadp, 0x04, 0x04, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xsmaddmdp, 0x04, 0x05, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xsmsubadp, 0x04, 0x06, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xsmsubmdp, 0x04, 0x07, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xsnmaddadp, 0x04, 0x14, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xsnmaddmdp, 0x04, 0x15, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xsnmsubadp, 0x04, 0x16, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xsnmsubmdp, 0x04, 0x17, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xscmpeqdp, 0x0C, 0x00, 0, PPC2_ISA300) -GEN_VSX_HELPER_2(xscmpgtdp, 0x0C, 0x01, 0, PPC2_ISA300) -GEN_VSX_HELPER_2(xscmpgedp, 0x0C, 0x02, 0, PPC2_ISA300) -GEN_VSX_HELPER_2(xscmpnedp, 0x0C, 0x03, 0, PPC2_ISA300) -GEN_VSX_HELPER_2(xscmpexpdp, 0x0C, 0x07, 0, PPC2_ISA300) -GEN_VSX_HELPER_2(xscmpexpqp, 0x04, 0x05, 0, PPC2_ISA300) -GEN_VSX_HELPER_2(xscmpodp, 0x0C, 0x05, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xscmpudp, 0x0C, 0x04, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xscmpoqp, 0x04, 0x04, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xscmpuqp, 0x04, 0x14, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xsmaxdp, 0x00, 0x14, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xsmindp, 0x00, 0x15, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xsmaxcdp, 0x00, 0x10, 0, PPC2_ISA300) -GEN_VSX_HELPER_2(xsmincdp, 0x00, 0x11, 0, PPC2_ISA300) -GEN_VSX_HELPER_2(xsmaxjdp, 0x00, 0x12, 0, PPC2_ISA300) -GEN_VSX_HELPER_2(xsminjdp, 0x00, 0x12, 0, PPC2_ISA300) -GEN_VSX_HELPER_2(xscvdphp, 0x16, 0x15, 0x11, PPC2_ISA300) -GEN_VSX_HELPER_2(xscvdpsp, 0x12, 0x10, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xscvdpqp, 0x04, 0x1A, 0x16, PPC2_ISA300) +GEN_VSX_HELPER_X3(xsadddp, 0x00, 0x04, 0, PPC2_VSX) +GEN_VSX_HELPER_R3(xsaddqp, 0x04, 0x00, 0, PPC2_ISA300) +GEN_VSX_HELPER_X3(xssubdp, 0x00, 0x05, 0, PPC2_VSX) +GEN_VSX_HELPER_X3(xsmuldp, 0x00, 0x06, 0, PPC2_VSX) +GEN_VSX_HELPER_R3(xsmulqp, 0x04, 0x01, 0, PPC2_ISA300) +GEN_VSX_HELPER_X3(xsdivdp, 0x00, 0x07, 0, PPC2_VSX) +GEN_VSX_HELPER_R3(xsdivqp, 0x04, 0x11, 0, PPC2_ISA300) +GEN_VSX_HELPER_X2(xsredp, 0x14, 0x05, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xssqrtdp, 0x16, 0x04, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xsrsqrtedp, 0x14, 0x04, 0, PPC2_VSX) +GEN_VSX_HELPER_X2_AB(xstdivdp, 0x14, 0x07, 0, PPC2_VSX) +GEN_VSX_HELPER_X1(xstsqrtdp, 0x14, 0x06, 0, PPC2_VSX) +GEN_VSX_HELPER_X3(xscmpeqdp, 0x0C, 0x00, 0, PPC2_ISA300) +GEN_VSX_HELPER_X3(xscmpgtdp, 0x0C, 0x01, 0, PPC2_ISA300) +GEN_VSX_HELPER_X3(xscmpgedp, 0x0C, 0x02, 0, PPC2_ISA300) +GEN_VSX_HELPER_X3(xscmpnedp, 0x0C, 0x03, 0, PPC2_ISA300) +GEN_VSX_HELPER_X2_AB(xscmpexpdp, 0x0C, 0x07, 0, PPC2_ISA300) +GEN_VSX_HELPER_R2_AB(xscmpexpqp, 0x04, 0x05, 0, PPC2_ISA300) +GEN_VSX_HELPER_X2_AB(xscmpodp, 0x0C, 0x05, 0, PPC2_VSX) +GEN_VSX_HELPER_X2_AB(xscmpudp, 0x0C, 0x04, 0, PPC2_VSX) +GEN_VSX_HELPER_R2_AB(xscmpoqp, 0x04, 0x04, 0, PPC2_VSX) +GEN_VSX_HELPER_R2_AB(xscmpuqp, 0x04, 0x14, 0, PPC2_VSX) +GEN_VSX_HELPER_X3(xsmaxdp, 0x00, 0x14, 0, PPC2_VSX) +GEN_VSX_HELPER_X3(xsmindp, 0x00, 0x15, 0, PPC2_VSX) +GEN_VSX_HELPER_R3(xsmaxcdp, 0x00, 0x10, 0, PPC2_ISA300) +GEN_VSX_HELPER_R3(xsmincdp, 0x00, 0x11, 0, PPC2_ISA300) +GEN_VSX_HELPER_R3(xsmaxjdp, 0x00, 0x12, 0, PPC2_ISA300) +GEN_VSX_HELPER_R3(xsminjdp, 0x00, 0x12, 0, PPC2_ISA300) +GEN_VSX_HELPER_X2(xscvdphp, 0x16, 0x15, 0x11, PPC2_ISA300) +GEN_VSX_HELPER_X2(xscvdpsp, 0x12, 0x10, 0, PPC2_VSX) +GEN_VSX_HELPER_R2(xscvdpqp, 0x04, 0x1A, 0x16, PPC2_ISA300) GEN_VSX_HELPER_XT_XB_ENV(xscvdpspn, 0x16, 0x10, 0, PPC2_VSX207) -GEN_VSX_HELPER_2(xscvqpdp, 0x04, 0x1A, 0x14, PPC2_ISA300) -GEN_VSX_HELPER_2(xscvqpsdz, 0x04, 0x1A, 0x19, PPC2_ISA300) -GEN_VSX_HELPER_2(xscvqpswz, 0x04, 0x1A, 0x09, PPC2_ISA300) -GEN_VSX_HELPER_2(xscvqpudz, 0x04, 0x1A, 0x11, PPC2_ISA300) -GEN_VSX_HELPER_2(xscvqpuwz, 0x04, 0x1A, 0x01, PPC2_ISA300) -GEN_VSX_HELPER_2(xscvhpdp, 0x16, 0x15, 0x10, PPC2_ISA300) -GEN_VSX_HELPER_2(xscvsdqp, 0x04, 0x1A, 0x0A, PPC2_ISA300) -GEN_VSX_HELPER_2(xscvspdp, 0x12, 0x14, 0, PPC2_VSX) +GEN_VSX_HELPER_R2(xscvqpsdz, 0x04, 0x1A, 0x19, PPC2_ISA300) +GEN_VSX_HELPER_R2(xscvqpswz, 0x04, 0x1A, 0x09, PPC2_ISA300) +GEN_VSX_HELPER_R2(xscvqpudz, 0x04, 0x1A, 0x11, PPC2_ISA300) +GEN_VSX_HELPER_R2(xscvqpuwz, 0x04, 0x1A, 0x01, PPC2_ISA300) +GEN_VSX_HELPER_X2(xscvhpdp, 0x16, 0x15, 0x10, PPC2_ISA300) +GEN_VSX_HELPER_R2(xscvsdqp, 0x04, 0x1A, 0x0A, PPC2_ISA300) +GEN_VSX_HELPER_X2(xscvspdp, 0x12, 0x14, 0, PPC2_VSX) GEN_VSX_HELPER_XT_XB_ENV(xscvspdpn, 0x16, 0x14, 0, PPC2_VSX207) -GEN_VSX_HELPER_2(xscvdpsxds, 0x10, 0x15, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xscvdpsxws, 0x10, 0x05, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xscvdpuxds, 0x10, 0x14, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xscvdpuxws, 0x10, 0x04, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xscvsxddp, 0x10, 0x17, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xscvudqp, 0x04, 0x1A, 0x02, PPC2_ISA300) -GEN_VSX_HELPER_2(xscvuxddp, 0x10, 0x16, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xsrdpi, 0x12, 0x04, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xsrdpic, 0x16, 0x06, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xsrdpim, 0x12, 0x07, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xsrdpip, 0x12, 0x06, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xsrdpiz, 0x12, 0x05, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xscvdpsxds, 0x10, 0x15, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xscvdpsxws, 0x10, 0x05, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xscvdpuxds, 0x10, 0x14, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xscvdpuxws, 0x10, 0x04, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xscvsxddp, 0x10, 0x17, 0, PPC2_VSX) +GEN_VSX_HELPER_R2(xscvudqp, 0x04, 0x1A, 0x02, PPC2_ISA300) +GEN_VSX_HELPER_X2(xscvuxddp, 0x10, 0x16, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xsrdpi, 0x12, 0x04, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xsrdpic, 0x16, 0x06, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xsrdpim, 0x12, 0x07, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xsrdpip, 0x12, 0x06, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xsrdpiz, 0x12, 0x05, 0, PPC2_VSX) GEN_VSX_HELPER_XT_XB_ENV(xsrsp, 0x12, 0x11, 0, PPC2_VSX207) - -GEN_VSX_HELPER_2(xsrqpi, 0x05, 0x00, 0, PPC2_ISA300) -GEN_VSX_HELPER_2(xsrqpxp, 0x05, 0x01, 0, PPC2_ISA300) -GEN_VSX_HELPER_2(xssqrtqp, 0x04, 0x19, 0x1B, PPC2_ISA300) -GEN_VSX_HELPER_2(xssubqp, 0x04, 0x10, 0, PPC2_ISA300) - -GEN_VSX_HELPER_2(xsaddsp, 0x00, 0x00, 0, PPC2_VSX207) -GEN_VSX_HELPER_2(xssubsp, 0x00, 0x01, 0, PPC2_VSX207) -GEN_VSX_HELPER_2(xsmulsp, 0x00, 0x02, 0, PPC2_VSX207) -GEN_VSX_HELPER_2(xsdivsp, 0x00, 0x03, 0, PPC2_VSX207) -GEN_VSX_HELPER_2(xsresp, 0x14, 0x01, 0, PPC2_VSX207) -GEN_VSX_HELPER_2(xssqrtsp, 0x16, 0x00, 0, PPC2_VSX207) -GEN_VSX_HELPER_2(xsrsqrtesp, 0x14, 0x00, 0, PPC2_VSX207) -GEN_VSX_HELPER_2(xsmaddasp, 0x04, 0x00, 0, PPC2_VSX207) -GEN_VSX_HELPER_2(xsmaddmsp, 0x04, 0x01, 0, PPC2_VSX207) -GEN_VSX_HELPER_2(xsmsubasp, 0x04, 0x02, 0, PPC2_VSX207) -GEN_VSX_HELPER_2(xsmsubmsp, 0x04, 0x03, 0, PPC2_VSX207) -GEN_VSX_HELPER_2(xsnmaddasp, 0x04, 0x10, 0, PPC2_VSX207) -GEN_VSX_HELPER_2(xsnmaddmsp, 0x04, 0x11, 0, PPC2_VSX207) -GEN_VSX_HELPER_2(xsnmsubasp, 0x04, 0x12, 0, PPC2_VSX207) -GEN_VSX_HELPER_2(xsnmsubmsp, 0x04, 0x13, 0, PPC2_VSX207) -GEN_VSX_HELPER_2(xscvsxdsp, 0x10, 0x13, 0, PPC2_VSX207) -GEN_VSX_HELPER_2(xscvuxdsp, 0x10, 0x12, 0, PPC2_VSX207) -GEN_VSX_HELPER_2(xststdcsp, 0x14, 0x12, 0, PPC2_ISA300) +GEN_VSX_HELPER_R2(xsrqpi, 0x05, 0x00, 0, PPC2_ISA300) +GEN_VSX_HELPER_R2(xsrqpxp, 0x05, 0x01, 0, PPC2_ISA300) +GEN_VSX_HELPER_R2(xssqrtqp, 0x04, 0x19, 0x1B, PPC2_ISA300) +GEN_VSX_HELPER_R3(xssubqp, 0x04, 0x10, 0, PPC2_ISA300) +GEN_VSX_HELPER_X3(xsaddsp, 0x00, 0x00, 0, PPC2_VSX207) +GEN_VSX_HELPER_X3(xssubsp, 0x00, 0x01, 0, PPC2_VSX207) +GEN_VSX_HELPER_X3(xsmulsp, 0x00, 0x02, 0, PPC2_VSX207) +GEN_VSX_HELPER_X3(xsdivsp, 0x00, 0x03, 0, PPC2_VSX207) +GEN_VSX_HELPER_X2(xsresp, 0x14, 0x01, 0, PPC2_VSX207) +GEN_VSX_HELPER_X2(xssqrtsp, 0x16, 0x00, 0, PPC2_VSX207) +GEN_VSX_HELPER_X2(xsrsqrtesp, 0x14, 0x00, 0, PPC2_VSX207) +GEN_VSX_HELPER_X2(xscvsxdsp, 0x10, 0x13, 0, PPC2_VSX207) +GEN_VSX_HELPER_X2(xscvuxdsp, 0x10, 0x12, 0, PPC2_VSX207) +GEN_VSX_HELPER_X1(xststdcsp, 0x14, 0x12, 0, PPC2_ISA300) GEN_VSX_HELPER_2(xststdcdp, 0x14, 0x16, 0, PPC2_ISA300) GEN_VSX_HELPER_2(xststdcqp, 0x04, 0x16, 0, PPC2_ISA300) -GEN_VSX_HELPER_2(xvadddp, 0x00, 0x0C, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvsubdp, 0x00, 0x0D, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvmuldp, 0x00, 0x0E, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvdivdp, 0x00, 0x0F, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvredp, 0x14, 0x0D, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvsqrtdp, 0x16, 0x0C, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvrsqrtedp, 0x14, 0x0C, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvtdivdp, 0x14, 0x0F, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvtsqrtdp, 0x14, 0x0E, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvmaddadp, 0x04, 0x0C, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvmaddmdp, 0x04, 0x0D, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvmsubadp, 0x04, 0x0E, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvmsubmdp, 0x04, 0x0F, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvnmaddadp, 0x04, 0x1C, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvnmaddmdp, 0x04, 0x1D, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvnmsubadp, 0x04, 0x1E, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvnmsubmdp, 0x04, 0x1F, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvmaxdp, 0x00, 0x1C, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvmindp, 0x00, 0x1D, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvcmpeqdp, 0x0C, 0x0C, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvcmpgtdp, 0x0C, 0x0D, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvcmpgedp, 0x0C, 0x0E, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvcmpnedp, 0x0C, 0x0F, 0, PPC2_ISA300) -GEN_VSX_HELPER_2(xvcvdpsp, 0x12, 0x18, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvcvdpsxds, 0x10, 0x1D, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvcvdpsxws, 0x10, 0x0D, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvcvdpuxds, 0x10, 0x1C, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvcvdpuxws, 0x10, 0x0C, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvcvsxddp, 0x10, 0x1F, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvcvuxddp, 0x10, 0x1E, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvcvsxwdp, 0x10, 0x0F, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvcvuxwdp, 0x10, 0x0E, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvrdpi, 0x12, 0x0C, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvrdpic, 0x16, 0x0E, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvrdpim, 0x12, 0x0F, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvrdpip, 0x12, 0x0E, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvrdpiz, 0x12, 0x0D, 0, PPC2_VSX) - -GEN_VSX_HELPER_2(xvaddsp, 0x00, 0x08, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvsubsp, 0x00, 0x09, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvmulsp, 0x00, 0x0A, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvdivsp, 0x00, 0x0B, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvresp, 0x14, 0x09, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvsqrtsp, 0x16, 0x08, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvrsqrtesp, 0x14, 0x08, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvtdivsp, 0x14, 0x0B, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvtsqrtsp, 0x14, 0x0A, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvmaddasp, 0x04, 0x08, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvmaddmsp, 0x04, 0x09, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvmsubasp, 0x04, 0x0A, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvmsubmsp, 0x04, 0x0B, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvnmaddasp, 0x04, 0x18, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvnmaddmsp, 0x04, 0x19, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvnmsubasp, 0x04, 0x1A, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvnmsubmsp, 0x04, 0x1B, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvmaxsp, 0x00, 0x18, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvminsp, 0x00, 0x19, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvcmpeqsp, 0x0C, 0x08, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvcmpgtsp, 0x0C, 0x09, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvcmpgesp, 0x0C, 0x0A, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvcmpnesp, 0x0C, 0x0B, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvcvspdp, 0x12, 0x1C, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvcvhpsp, 0x16, 0x1D, 0x18, PPC2_ISA300) -GEN_VSX_HELPER_2(xvcvsphp, 0x16, 0x1D, 0x19, PPC2_ISA300) -GEN_VSX_HELPER_2(xvcvspsxds, 0x10, 0x19, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvcvspsxws, 0x10, 0x09, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvcvspuxds, 0x10, 0x18, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvcvspuxws, 0x10, 0x08, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvcvsxdsp, 0x10, 0x1B, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvcvuxdsp, 0x10, 0x1A, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvcvsxwsp, 0x10, 0x0B, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvcvuxwsp, 0x10, 0x0A, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvrspi, 0x12, 0x08, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvrspic, 0x16, 0x0A, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvrspim, 0x12, 0x0B, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvrspip, 0x12, 0x0A, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xvrspiz, 0x12, 0x09, 0, PPC2_VSX) +GEN_VSX_HELPER_X3(xvadddp, 0x00, 0x0C, 0, PPC2_VSX) +GEN_VSX_HELPER_X3(xvsubdp, 0x00, 0x0D, 0, PPC2_VSX) +GEN_VSX_HELPER_X3(xvmuldp, 0x00, 0x0E, 0, PPC2_VSX) +GEN_VSX_HELPER_X3(xvdivdp, 0x00, 0x0F, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvredp, 0x14, 0x0D, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvsqrtdp, 0x16, 0x0C, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvrsqrtedp, 0x14, 0x0C, 0, PPC2_VSX) +GEN_VSX_HELPER_X2_AB(xvtdivdp, 0x14, 0x0F, 0, PPC2_VSX) +GEN_VSX_HELPER_X1(xvtsqrtdp, 0x14, 0x0E, 0, PPC2_VSX) +GEN_VSX_HELPER_X3(xvmaxdp, 0x00, 0x1C, 0, PPC2_VSX) +GEN_VSX_HELPER_X3(xvmindp, 0x00, 0x1D, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvcvdpsp, 0x12, 0x18, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvcvdpsxds, 0x10, 0x1D, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvcvdpsxws, 0x10, 0x0D, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvcvdpuxds, 0x10, 0x1C, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvcvdpuxws, 0x10, 0x0C, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvcvsxddp, 0x10, 0x1F, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvcvuxddp, 0x10, 0x1E, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvcvsxwdp, 0x10, 0x0F, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvcvuxwdp, 0x10, 0x0E, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvrdpi, 0x12, 0x0C, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvrdpic, 0x16, 0x0E, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvrdpim, 0x12, 0x0F, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvrdpip, 0x12, 0x0E, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvrdpiz, 0x12, 0x0D, 0, PPC2_VSX) + +GEN_VSX_HELPER_X3(xvaddsp, 0x00, 0x08, 0, PPC2_VSX) +GEN_VSX_HELPER_X3(xvsubsp, 0x00, 0x09, 0, PPC2_VSX) +GEN_VSX_HELPER_X3(xvmulsp, 0x00, 0x0A, 0, PPC2_VSX) +GEN_VSX_HELPER_X3(xvdivsp, 0x00, 0x0B, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvresp, 0x14, 0x09, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvsqrtsp, 0x16, 0x08, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvrsqrtesp, 0x14, 0x08, 0, PPC2_VSX) +GEN_VSX_HELPER_X2_AB(xvtdivsp, 0x14, 0x0B, 0, PPC2_VSX) +GEN_VSX_HELPER_X1(xvtsqrtsp, 0x14, 0x0A, 0, PPC2_VSX) +GEN_VSX_HELPER_X3(xvmaxsp, 0x00, 0x18, 0, PPC2_VSX) +GEN_VSX_HELPER_X3(xvminsp, 0x00, 0x19, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvcvspdp, 0x12, 0x1C, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvcvhpsp, 0x16, 0x1D, 0x18, PPC2_ISA300) +GEN_VSX_HELPER_X2(xvcvsphp, 0x16, 0x1D, 0x19, PPC2_ISA300) +GEN_VSX_HELPER_X2(xvcvspsxds, 0x10, 0x19, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvcvspsxws, 0x10, 0x09, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvcvspuxds, 0x10, 0x18, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvcvspuxws, 0x10, 0x08, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvcvsxdsp, 0x10, 0x1B, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvcvuxdsp, 0x10, 0x1A, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvcvsxwsp, 0x10, 0x0B, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvcvuxwsp, 0x10, 0x0A, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvrspi, 0x12, 0x08, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvrspic, 0x16, 0x0A, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvrspim, 0x12, 0x0B, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvrspip, 0x12, 0x0A, 0, PPC2_VSX) +GEN_VSX_HELPER_X2(xvrspiz, 0x12, 0x09, 0, PPC2_VSX) GEN_VSX_HELPER_2(xvtstdcsp, 0x14, 0x1A, 0, PPC2_VSX) GEN_VSX_HELPER_2(xvtstdcdp, 0x14, 0x1E, 0, PPC2_VSX) -GEN_VSX_HELPER_2(xxperm, 0x08, 0x03, 0, PPC2_ISA300) -GEN_VSX_HELPER_2(xxpermr, 0x08, 0x07, 0, PPC2_ISA300) +GEN_VSX_HELPER_X3(xxperm, 0x08, 0x03, 0, PPC2_ISA300) +GEN_VSX_HELPER_X3(xxpermr, 0x08, 0x07, 0, PPC2_ISA300) + +#define GEN_VSX_HELPER_VSX_MADD(name, op1, aop, mop, inval, type) \ +static void gen_##name(DisasContext *ctx) \ +{ \ + TCGv_ptr xt, xa, b, c; \ + if (unlikely(!ctx->vsx_enabled)) { \ + gen_exception(ctx, POWERPC_EXCP_VSXU); \ + return; \ + } \ + xt = gen_vsr_ptr(xT(ctx->opcode)); \ + xa = gen_vsr_ptr(xA(ctx->opcode)); \ + if (ctx->opcode & PPC_BIT(25)) { \ + /* \ + * AxT + B \ + */ \ + b = gen_vsr_ptr(xT(ctx->opcode)); \ + c = gen_vsr_ptr(xB(ctx->opcode)); \ + } else { \ + /* \ + * AxB + T \ + */ \ + b = gen_vsr_ptr(xB(ctx->opcode)); \ + c = gen_vsr_ptr(xT(ctx->opcode)); \ + } \ + gen_helper_##name(cpu_env, xt, xa, b, c); \ + tcg_temp_free_ptr(xt); \ + tcg_temp_free_ptr(xa); \ + tcg_temp_free_ptr(b); \ + tcg_temp_free_ptr(c); \ +} + +GEN_VSX_HELPER_VSX_MADD(xsmadddp, 0x04, 0x04, 0x05, 0, PPC2_VSX) +GEN_VSX_HELPER_VSX_MADD(xsmsubdp, 0x04, 0x06, 0x07, 0, PPC2_VSX) +GEN_VSX_HELPER_VSX_MADD(xsnmadddp, 0x04, 0x14, 0x15, 0, PPC2_VSX) +GEN_VSX_HELPER_VSX_MADD(xsnmsubdp, 0x04, 0x16, 0x17, 0, PPC2_VSX) +GEN_VSX_HELPER_VSX_MADD(xsmaddsp, 0x04, 0x00, 0x01, 0, PPC2_VSX207) +GEN_VSX_HELPER_VSX_MADD(xsmsubsp, 0x04, 0x02, 0x03, 0, PPC2_VSX207) +GEN_VSX_HELPER_VSX_MADD(xsnmaddsp, 0x04, 0x10, 0x11, 0, PPC2_VSX207) +GEN_VSX_HELPER_VSX_MADD(xsnmsubsp, 0x04, 0x12, 0x13, 0, PPC2_VSX207) +GEN_VSX_HELPER_VSX_MADD(xvmadddp, 0x04, 0x0C, 0x0D, 0, PPC2_VSX) +GEN_VSX_HELPER_VSX_MADD(xvmsubdp, 0x04, 0x0E, 0x0F, 0, PPC2_VSX) +GEN_VSX_HELPER_VSX_MADD(xvnmadddp, 0x04, 0x1C, 0x1D, 0, PPC2_VSX) +GEN_VSX_HELPER_VSX_MADD(xvnmsubdp, 0x04, 0x1E, 0x1F, 0, PPC2_VSX) +GEN_VSX_HELPER_VSX_MADD(xvmaddsp, 0x04, 0x08, 0x09, 0, PPC2_VSX) +GEN_VSX_HELPER_VSX_MADD(xvmsubsp, 0x04, 0x0A, 0x0B, 0, PPC2_VSX) +GEN_VSX_HELPER_VSX_MADD(xvnmaddsp, 0x04, 0x18, 0x19, 0, PPC2_VSX) +GEN_VSX_HELPER_VSX_MADD(xvnmsubsp, 0x04, 0x1A, 0x1B, 0, PPC2_VSX) static void gen_xxbrd(DisasContext *ctx) { @@ -1460,7 +1645,7 @@ static void gen_xxsldwi(DisasContext *ctx) #define VSX_EXTRACT_INSERT(name) \ static void gen_##name(DisasContext *ctx) \ { \ - TCGv xt, xb; \ + TCGv_ptr xt, xb; \ TCGv_i32 t0; \ TCGv_i64 t1; \ uint8_t uimm = UIMM4(ctx->opcode); \ @@ -1469,8 +1654,8 @@ static void gen_##name(DisasContext *ctx) \ gen_exception(ctx, POWERPC_EXCP_VSXU); \ return; \ } \ - xt = tcg_const_tl(xT(ctx->opcode)); \ - xb = tcg_const_tl(xB(ctx->opcode)); \ + xt = gen_vsr_ptr(xT(ctx->opcode)); \ + xb = gen_vsr_ptr(xB(ctx->opcode)); \ t0 = tcg_temp_new_i32(); \ t1 = tcg_temp_new_i64(); \ /* \ @@ -1485,8 +1670,8 @@ static void gen_##name(DisasContext *ctx) \ } \ tcg_gen_movi_i32(t0, uimm); \ gen_helper_##name(cpu_env, xt, xb, t0); \ - tcg_temp_free(xb); \ - tcg_temp_free(xt); \ + tcg_temp_free_ptr(xb); \ + tcg_temp_free_ptr(xt); \ tcg_temp_free_i32(t0); \ tcg_temp_free_i64(t1); \ } @@ -1813,7 +1998,7 @@ static void gen_xvxexpdp(DisasContext *ctx) tcg_temp_free_i64(xbl); } -GEN_VSX_HELPER_2(xvxsigsp, 0x00, 0x04, 0, PPC2_ISA300) +GEN_VSX_HELPER_X2(xvxsigsp, 0x00, 0x04, 0, PPC2_ISA300) static void gen_xvxsigdp(DisasContext *ctx) { diff --git a/target/ppc/translate/vsx-ops.inc.c b/target/ppc/translate/vsx-ops.inc.c index 5030c4aceb..7fd3942b84 100644 --- a/target/ppc/translate/vsx-ops.inc.c +++ b/target/ppc/translate/vsx-ops.inc.c @@ -63,6 +63,12 @@ GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 1, opc3, 0, PPC_NONE, fl2), \ GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 2, opc3, 0, PPC_NONE, fl2), \ GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 3, opc3, 0, PPC_NONE, fl2) +#define GEN_XX3FORM_NAME(name, opcname, opc2, opc3, fl2) \ +GEN_HANDLER2_E(name, opcname, 0x3C, opc2 | 0, opc3, 0, PPC_NONE, fl2), \ +GEN_HANDLER2_E(name, opcname, 0x3C, opc2 | 1, opc3, 0, PPC_NONE, fl2), \ +GEN_HANDLER2_E(name, opcname, 0x3C, opc2 | 2, opc3, 0, PPC_NONE, fl2), \ +GEN_HANDLER2_E(name, opcname, 0x3C, opc2 | 3, opc3, 0, PPC_NONE, fl2) + #define GEN_XX2IFORM(name, opc2, opc3, fl2) \ GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0, opc3, 1, PPC_NONE, fl2), \ GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 1, opc3, 1, PPC_NONE, fl2), \ @@ -182,14 +188,14 @@ GEN_XX2FORM(xssqrtdp, 0x16, 0x04, PPC2_VSX), GEN_XX2FORM(xsrsqrtedp, 0x14, 0x04, PPC2_VSX), GEN_XX3FORM(xstdivdp, 0x14, 0x07, PPC2_VSX), GEN_XX2FORM(xstsqrtdp, 0x14, 0x06, PPC2_VSX), -GEN_XX3FORM(xsmaddadp, 0x04, 0x04, PPC2_VSX), -GEN_XX3FORM(xsmaddmdp, 0x04, 0x05, PPC2_VSX), -GEN_XX3FORM(xsmsubadp, 0x04, 0x06, PPC2_VSX), -GEN_XX3FORM(xsmsubmdp, 0x04, 0x07, PPC2_VSX), -GEN_XX3FORM(xsnmaddadp, 0x04, 0x14, PPC2_VSX), -GEN_XX3FORM(xsnmaddmdp, 0x04, 0x15, PPC2_VSX), -GEN_XX3FORM(xsnmsubadp, 0x04, 0x16, PPC2_VSX), -GEN_XX3FORM(xsnmsubmdp, 0x04, 0x17, PPC2_VSX), +GEN_XX3FORM_NAME(xsmadddp, "xsmaddadp", 0x04, 0x04, PPC2_VSX), +GEN_XX3FORM_NAME(xsmadddp, "xsmaddmdp", 0x04, 0x05, PPC2_VSX), +GEN_XX3FORM_NAME(xsmsubdp, "xsmsubadp", 0x04, 0x06, PPC2_VSX), +GEN_XX3FORM_NAME(xsmsubdp, "xsmsubmdp", 0x04, 0x07, PPC2_VSX), +GEN_XX3FORM_NAME(xsnmadddp, "xsnmaddadp", 0x04, 0x14, PPC2_VSX), +GEN_XX3FORM_NAME(xsnmadddp, "xsnmaddmdp", 0x04, 0x15, PPC2_VSX), +GEN_XX3FORM_NAME(xsnmsubdp, "xsnmsubadp", 0x04, 0x16, PPC2_VSX), +GEN_XX3FORM_NAME(xsnmsubdp, "xsnmsubmdp", 0x04, 0x17, PPC2_VSX), GEN_XX3FORM(xscmpeqdp, 0x0C, 0x00, PPC2_ISA300), GEN_XX3FORM(xscmpgtdp, 0x0C, 0x01, PPC2_ISA300), GEN_XX3FORM(xscmpgedp, 0x0C, 0x02, PPC2_ISA300), @@ -235,14 +241,14 @@ GEN_XX2FORM(xsresp, 0x14, 0x01, PPC2_VSX207), GEN_XX2FORM(xsrsp, 0x12, 0x11, PPC2_VSX207), GEN_XX2FORM(xssqrtsp, 0x16, 0x00, PPC2_VSX207), GEN_XX2FORM(xsrsqrtesp, 0x14, 0x00, PPC2_VSX207), -GEN_XX3FORM(xsmaddasp, 0x04, 0x00, PPC2_VSX207), -GEN_XX3FORM(xsmaddmsp, 0x04, 0x01, PPC2_VSX207), -GEN_XX3FORM(xsmsubasp, 0x04, 0x02, PPC2_VSX207), -GEN_XX3FORM(xsmsubmsp, 0x04, 0x03, PPC2_VSX207), -GEN_XX3FORM(xsnmaddasp, 0x04, 0x10, PPC2_VSX207), -GEN_XX3FORM(xsnmaddmsp, 0x04, 0x11, PPC2_VSX207), -GEN_XX3FORM(xsnmsubasp, 0x04, 0x12, PPC2_VSX207), -GEN_XX3FORM(xsnmsubmsp, 0x04, 0x13, PPC2_VSX207), +GEN_XX3FORM_NAME(xsmaddsp, "xsmaddasp", 0x04, 0x00, PPC2_VSX207), +GEN_XX3FORM_NAME(xsmaddsp, "xsmaddmsp", 0x04, 0x01, PPC2_VSX207), +GEN_XX3FORM_NAME(xsmsubsp, "xsmsubasp", 0x04, 0x02, PPC2_VSX207), +GEN_XX3FORM_NAME(xsmsubsp, "xsmsubmsp", 0x04, 0x03, PPC2_VSX207), +GEN_XX3FORM_NAME(xsnmaddsp, "xsnmaddasp", 0x04, 0x10, PPC2_VSX207), +GEN_XX3FORM_NAME(xsnmaddsp, "xsnmaddmsp", 0x04, 0x11, PPC2_VSX207), +GEN_XX3FORM_NAME(xsnmsubsp, "xsnmsubasp", 0x04, 0x12, PPC2_VSX207), +GEN_XX3FORM_NAME(xsnmsubsp, "xsnmsubmsp", 0x04, 0x13, PPC2_VSX207), GEN_XX2FORM(xscvsxdsp, 0x10, 0x13, PPC2_VSX207), GEN_XX2FORM(xscvuxdsp, 0x10, 0x12, PPC2_VSX207), @@ -255,14 +261,14 @@ GEN_XX2FORM(xvsqrtdp, 0x16, 0x0C, PPC2_VSX), GEN_XX2FORM(xvrsqrtedp, 0x14, 0x0C, PPC2_VSX), GEN_XX3FORM(xvtdivdp, 0x14, 0x0F, PPC2_VSX), GEN_XX2FORM(xvtsqrtdp, 0x14, 0x0E, PPC2_VSX), -GEN_XX3FORM(xvmaddadp, 0x04, 0x0C, PPC2_VSX), -GEN_XX3FORM(xvmaddmdp, 0x04, 0x0D, PPC2_VSX), -GEN_XX3FORM(xvmsubadp, 0x04, 0x0E, PPC2_VSX), -GEN_XX3FORM(xvmsubmdp, 0x04, 0x0F, PPC2_VSX), -GEN_XX3FORM(xvnmaddadp, 0x04, 0x1C, PPC2_VSX), -GEN_XX3FORM(xvnmaddmdp, 0x04, 0x1D, PPC2_VSX), -GEN_XX3FORM(xvnmsubadp, 0x04, 0x1E, PPC2_VSX), -GEN_XX3FORM(xvnmsubmdp, 0x04, 0x1F, PPC2_VSX), +GEN_XX3FORM_NAME(xvmadddp, "xvmaddadp", 0x04, 0x0C, PPC2_VSX), +GEN_XX3FORM_NAME(xvmadddp, "xvmaddmdp", 0x04, 0x0D, PPC2_VSX), +GEN_XX3FORM_NAME(xvmsubdp, "xvmsubadp", 0x04, 0x0E, PPC2_VSX), +GEN_XX3FORM_NAME(xvmsubdp, "xvmsubmdp", 0x04, 0x0F, PPC2_VSX), +GEN_XX3FORM_NAME(xvnmadddp, "xvnmaddadp", 0x04, 0x1C, PPC2_VSX), +GEN_XX3FORM_NAME(xvnmadddp, "xvnmaddmdp", 0x04, 0x1D, PPC2_VSX), +GEN_XX3FORM_NAME(xvnmsubdp, "xvnmsubadp", 0x04, 0x1E, PPC2_VSX), +GEN_XX3FORM_NAME(xvnmsubdp, "xvnmsubmdp", 0x04, 0x1F, PPC2_VSX), GEN_XX3FORM(xvmaxdp, 0x00, 0x1C, PPC2_VSX), GEN_XX3FORM(xvmindp, 0x00, 0x1D, PPC2_VSX), GEN_XX3_RC_FORM(xvcmpeqdp, 0x0C, 0x0C, PPC2_VSX), @@ -293,14 +299,14 @@ GEN_XX2FORM(xvsqrtsp, 0x16, 0x08, PPC2_VSX), GEN_XX2FORM(xvrsqrtesp, 0x14, 0x08, PPC2_VSX), GEN_XX3FORM(xvtdivsp, 0x14, 0x0B, PPC2_VSX), GEN_XX2FORM(xvtsqrtsp, 0x14, 0x0A, PPC2_VSX), -GEN_XX3FORM(xvmaddasp, 0x04, 0x08, PPC2_VSX), -GEN_XX3FORM(xvmaddmsp, 0x04, 0x09, PPC2_VSX), -GEN_XX3FORM(xvmsubasp, 0x04, 0x0A, PPC2_VSX), -GEN_XX3FORM(xvmsubmsp, 0x04, 0x0B, PPC2_VSX), -GEN_XX3FORM(xvnmaddasp, 0x04, 0x18, PPC2_VSX), -GEN_XX3FORM(xvnmaddmsp, 0x04, 0x19, PPC2_VSX), -GEN_XX3FORM(xvnmsubasp, 0x04, 0x1A, PPC2_VSX), -GEN_XX3FORM(xvnmsubmsp, 0x04, 0x1B, PPC2_VSX), +GEN_XX3FORM_NAME(xvmaddsp, "xvmaddasp", 0x04, 0x08, PPC2_VSX), +GEN_XX3FORM_NAME(xvmaddsp, "xvmaddmsp", 0x04, 0x09, PPC2_VSX), +GEN_XX3FORM_NAME(xvmsubsp, "xvmsubasp", 0x04, 0x0A, PPC2_VSX), +GEN_XX3FORM_NAME(xvmsubsp, "xvmsubmsp", 0x04, 0x0B, PPC2_VSX), +GEN_XX3FORM_NAME(xvnmaddsp, "xvnmaddasp", 0x04, 0x18, PPC2_VSX), +GEN_XX3FORM_NAME(xvnmaddsp, "xvnmaddmsp", 0x04, 0x19, PPC2_VSX), +GEN_XX3FORM_NAME(xvnmsubsp, "xvnmsubasp", 0x04, 0x1A, PPC2_VSX), +GEN_XX3FORM_NAME(xvnmsubsp, "xvnmsubmsp", 0x04, 0x1B, PPC2_VSX), GEN_XX3FORM(xvmaxsp, 0x00, 0x18, PPC2_VSX), GEN_XX3FORM(xvminsp, 0x00, 0x19, PPC2_VSX), GEN_XX3_RC_FORM(xvcmpeqsp, 0x0C, 0x08, PPC2_VSX), diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c index 03cb6d0521..86fc8f2e31 100644 --- a/target/ppc/translate_init.inc.c +++ b/target/ppc/translate_init.inc.c @@ -41,7 +41,7 @@ #include "qemu/cutils.h" #include "disas/capstone.h" #include "fpu/softfloat.h" -#include "qapi/qapi-commands-target.h" +#include "qapi/qapi-commands-machine-target.h" /* #define PPC_DUMP_CPU */ /* #define PPC_DEBUG_SPR */ diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 6f2b644220..f8d07bd20a 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -24,6 +24,7 @@ #include "cpu.h" #include "exec/exec-all.h" #include "qapi/error.h" +#include "qemu/error-report.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" @@ -88,9 +89,8 @@ static void set_misa(CPURISCVState *env, target_ulong misa) env->misa_mask = env->misa = misa; } -static void set_versions(CPURISCVState *env, int user_ver, int priv_ver) +static void set_priv_version(CPURISCVState *env, int priv_ver) { - env->user_ver = user_ver; env->priv_ver = priv_ver; } @@ -110,7 +110,7 @@ static void riscv_any_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; set_misa(env, RVXLEN | RVI | RVM | RVA | RVF | RVD | RVC | RVU); - set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_10_0); + set_priv_version(env, PRIV_VERSION_1_11_0); set_resetvec(env, DEFAULT_RSTVEC); } @@ -119,14 +119,15 @@ static void riscv_any_cpu_init(Object *obj) static void riscv_base32_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; - set_misa(env, RV32 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU); + /* We set this in the realise function */ + set_misa(env, 0); } static void rv32gcsu_priv1_09_1_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; set_misa(env, RV32 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU); - set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_09_1); + set_priv_version(env, PRIV_VERSION_1_09_1); set_resetvec(env, DEFAULT_RSTVEC); set_feature(env, RISCV_FEATURE_MMU); set_feature(env, RISCV_FEATURE_PMP); @@ -136,7 +137,7 @@ static void rv32gcsu_priv1_10_0_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; set_misa(env, RV32 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU); - set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_10_0); + set_priv_version(env, PRIV_VERSION_1_10_0); set_resetvec(env, DEFAULT_RSTVEC); set_feature(env, RISCV_FEATURE_MMU); set_feature(env, RISCV_FEATURE_PMP); @@ -146,7 +147,7 @@ static void rv32imacu_nommu_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; set_misa(env, RV32 | RVI | RVM | RVA | RVC | RVU); - set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_10_0); + set_priv_version(env, PRIV_VERSION_1_10_0); set_resetvec(env, DEFAULT_RSTVEC); set_feature(env, RISCV_FEATURE_PMP); } @@ -156,14 +157,15 @@ static void rv32imacu_nommu_cpu_init(Object *obj) static void riscv_base64_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; - set_misa(env, RV64 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU); + /* We set this in the realise function */ + set_misa(env, 0); } static void rv64gcsu_priv1_09_1_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; set_misa(env, RV64 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU); - set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_09_1); + set_priv_version(env, PRIV_VERSION_1_09_1); set_resetvec(env, DEFAULT_RSTVEC); set_feature(env, RISCV_FEATURE_MMU); set_feature(env, RISCV_FEATURE_PMP); @@ -173,7 +175,7 @@ static void rv64gcsu_priv1_10_0_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; set_misa(env, RV64 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU); - set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_10_0); + set_priv_version(env, PRIV_VERSION_1_10_0); set_resetvec(env, DEFAULT_RSTVEC); set_feature(env, RISCV_FEATURE_MMU); set_feature(env, RISCV_FEATURE_PMP); @@ -183,7 +185,7 @@ static void rv64imacu_nommu_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; set_misa(env, RV64 | RVI | RVM | RVA | RVC | RVU); - set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_10_0); + set_priv_version(env, PRIV_VERSION_1_10_0); set_resetvec(env, DEFAULT_RSTVEC); set_feature(env, RISCV_FEATURE_PMP); } @@ -295,6 +297,7 @@ static void riscv_cpu_reset(CPUState *cs) env->pc = env->resetvec; #endif cs->exception_index = EXCP_NONE; + env->load_res = -1; set_default_nan_mode(1, &env->fp_status); } @@ -313,8 +316,8 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) RISCVCPU *cpu = RISCV_CPU(dev); CPURISCVState *env = &cpu->env; RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev); - int priv_version = PRIV_VERSION_1_10_0; - int user_version = USER_VERSION_2_02_0; + int priv_version = PRIV_VERSION_1_11_0; + target_ulong target_misa = 0; Error *local_err = NULL; cpu_exec_realizefn(cs, &local_err); @@ -324,7 +327,9 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) } if (cpu->cfg.priv_spec) { - if (!g_strcmp0(cpu->cfg.priv_spec, "v1.10.0")) { + if (!g_strcmp0(cpu->cfg.priv_spec, "v1.11.0")) { + priv_version = PRIV_VERSION_1_11_0; + } else if (!g_strcmp0(cpu->cfg.priv_spec, "v1.10.0")) { priv_version = PRIV_VERSION_1_10_0; } else if (!g_strcmp0(cpu->cfg.priv_spec, "v1.9.1")) { priv_version = PRIV_VERSION_1_09_1; @@ -336,18 +341,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) } } - if (cpu->cfg.user_spec) { - if (!g_strcmp0(cpu->cfg.user_spec, "v2.02.0")) { - user_version = USER_VERSION_2_02_0; - } else { - error_setg(errp, - "Unsupported user spec version '%s'", - cpu->cfg.user_spec); - return; - } - } - - set_versions(env, user_version, priv_version); + set_priv_version(env, priv_version); set_resetvec(env, DEFAULT_RSTVEC); if (cpu->cfg.mmu) { @@ -358,6 +352,64 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) set_feature(env, RISCV_FEATURE_PMP); } + /* If misa isn't set (rv32 and rv64 machines) set it here */ + if (!env->misa) { + /* Do some ISA extension error checking */ + if (cpu->cfg.ext_i && cpu->cfg.ext_e) { + error_setg(errp, + "I and E extensions are incompatible"); + return; + } + + if (!cpu->cfg.ext_i && !cpu->cfg.ext_e) { + error_setg(errp, + "Either I or E extension must be set"); + return; + } + + if (cpu->cfg.ext_g && !(cpu->cfg.ext_i & cpu->cfg.ext_m & + cpu->cfg.ext_a & cpu->cfg.ext_f & + cpu->cfg.ext_d)) { + warn_report("Setting G will also set IMAFD"); + cpu->cfg.ext_i = true; + cpu->cfg.ext_m = true; + cpu->cfg.ext_a = true; + cpu->cfg.ext_f = true; + cpu->cfg.ext_d = true; + } + + /* Set the ISA extensions, checks should have happened above */ + if (cpu->cfg.ext_i) { + target_misa |= RVI; + } + if (cpu->cfg.ext_e) { + target_misa |= RVE; + } + if (cpu->cfg.ext_m) { + target_misa |= RVM; + } + if (cpu->cfg.ext_a) { + target_misa |= RVA; + } + if (cpu->cfg.ext_f) { + target_misa |= RVF; + } + if (cpu->cfg.ext_d) { + target_misa |= RVD; + } + if (cpu->cfg.ext_c) { + target_misa |= RVC; + } + if (cpu->cfg.ext_s) { + target_misa |= RVS; + } + if (cpu->cfg.ext_u) { + target_misa |= RVU; + } + + set_misa(env, RVXLEN | target_misa); + } + riscv_cpu_register_gdb_regs_for_features(cs); qemu_init_vcpu(cs); @@ -379,8 +431,20 @@ static const VMStateDescription vmstate_riscv_cpu = { }; static Property riscv_cpu_properties[] = { + DEFINE_PROP_BOOL("i", RISCVCPU, cfg.ext_i, true), + DEFINE_PROP_BOOL("e", RISCVCPU, cfg.ext_e, false), + DEFINE_PROP_BOOL("g", RISCVCPU, cfg.ext_g, true), + DEFINE_PROP_BOOL("m", RISCVCPU, cfg.ext_m, true), + DEFINE_PROP_BOOL("a", RISCVCPU, cfg.ext_a, true), + DEFINE_PROP_BOOL("f", RISCVCPU, cfg.ext_f, true), + DEFINE_PROP_BOOL("d", RISCVCPU, cfg.ext_d, true), + DEFINE_PROP_BOOL("c", RISCVCPU, cfg.ext_c, true), + DEFINE_PROP_BOOL("s", RISCVCPU, cfg.ext_s, true), + DEFINE_PROP_BOOL("u", RISCVCPU, cfg.ext_u, true), + DEFINE_PROP_BOOL("Counters", RISCVCPU, cfg.ext_counters, true), + DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true), + DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true), DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec), - DEFINE_PROP_STRING("user_spec", RISCVCPU, cfg.user_spec), DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true), DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true), DEFINE_PROP_END_OF_LIST(), @@ -416,6 +480,7 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data) cc->gdb_stop_before_watchpoint = true; cc->disas_set_info = riscv_cpu_disas_set_info; #ifndef CONFIG_USER_ONLY + cc->do_unassigned_access = riscv_cpu_unassigned_access; cc->do_unaligned_access = riscv_cpu_do_unaligned_access; cc->get_phys_page_debug = riscv_cpu_get_phys_page_debug; #endif @@ -492,18 +557,20 @@ static const TypeInfo riscv_cpu_type_infos[] = { DEFINE_CPU(TYPE_RISCV_CPU_ANY, riscv_any_cpu_init), #if defined(TARGET_RISCV32) DEFINE_CPU(TYPE_RISCV_CPU_BASE32, riscv_base32_cpu_init), - DEFINE_CPU(TYPE_RISCV_CPU_RV32GCSU_V1_09_1, rv32gcsu_priv1_09_1_cpu_init), - DEFINE_CPU(TYPE_RISCV_CPU_RV32GCSU_V1_10_0, rv32gcsu_priv1_10_0_cpu_init), - DEFINE_CPU(TYPE_RISCV_CPU_RV32IMACU_NOMMU, rv32imacu_nommu_cpu_init), DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E31, rv32imacu_nommu_cpu_init), - DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U34, rv32gcsu_priv1_10_0_cpu_init) + DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U34, rv32gcsu_priv1_10_0_cpu_init), + /* Depreacted */ + DEFINE_CPU(TYPE_RISCV_CPU_RV32IMACU_NOMMU, rv32imacu_nommu_cpu_init), + DEFINE_CPU(TYPE_RISCV_CPU_RV32GCSU_V1_09_1, rv32gcsu_priv1_09_1_cpu_init), + DEFINE_CPU(TYPE_RISCV_CPU_RV32GCSU_V1_10_0, rv32gcsu_priv1_10_0_cpu_init) #elif defined(TARGET_RISCV64) DEFINE_CPU(TYPE_RISCV_CPU_BASE64, riscv_base64_cpu_init), - DEFINE_CPU(TYPE_RISCV_CPU_RV64GCSU_V1_09_1, rv64gcsu_priv1_09_1_cpu_init), - DEFINE_CPU(TYPE_RISCV_CPU_RV64GCSU_V1_10_0, rv64gcsu_priv1_10_0_cpu_init), - DEFINE_CPU(TYPE_RISCV_CPU_RV64IMACU_NOMMU, rv64imacu_nommu_cpu_init), DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E51, rv64imacu_nommu_cpu_init), - DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U54, rv64gcsu_priv1_10_0_cpu_init) + DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U54, rv64gcsu_priv1_10_0_cpu_init), + /* Deprecated */ + DEFINE_CPU(TYPE_RISCV_CPU_RV64IMACU_NOMMU, rv64imacu_nommu_cpu_init), + DEFINE_CPU(TYPE_RISCV_CPU_RV64GCSU_V1_09_1, rv64gcsu_priv1_09_1_cpu_init), + DEFINE_CPU(TYPE_RISCV_CPU_RV64GCSU_V1_10_0, rv64gcsu_priv1_10_0_cpu_init) #endif }; diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 6c5de37b25..0adb307f32 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -35,16 +35,17 @@ #define TYPE_RISCV_CPU_ANY RISCV_CPU_TYPE_NAME("any") #define TYPE_RISCV_CPU_BASE32 RISCV_CPU_TYPE_NAME("rv32") #define TYPE_RISCV_CPU_BASE64 RISCV_CPU_TYPE_NAME("rv64") -#define TYPE_RISCV_CPU_RV32GCSU_V1_09_1 RISCV_CPU_TYPE_NAME("rv32gcsu-v1.9.1") -#define TYPE_RISCV_CPU_RV32GCSU_V1_10_0 RISCV_CPU_TYPE_NAME("rv32gcsu-v1.10.0") -#define TYPE_RISCV_CPU_RV32IMACU_NOMMU RISCV_CPU_TYPE_NAME("rv32imacu-nommu") -#define TYPE_RISCV_CPU_RV64GCSU_V1_09_1 RISCV_CPU_TYPE_NAME("rv64gcsu-v1.9.1") -#define TYPE_RISCV_CPU_RV64GCSU_V1_10_0 RISCV_CPU_TYPE_NAME("rv64gcsu-v1.10.0") -#define TYPE_RISCV_CPU_RV64IMACU_NOMMU RISCV_CPU_TYPE_NAME("rv64imacu-nommu") #define TYPE_RISCV_CPU_SIFIVE_E31 RISCV_CPU_TYPE_NAME("sifive-e31") #define TYPE_RISCV_CPU_SIFIVE_E51 RISCV_CPU_TYPE_NAME("sifive-e51") #define TYPE_RISCV_CPU_SIFIVE_U34 RISCV_CPU_TYPE_NAME("sifive-u34") #define TYPE_RISCV_CPU_SIFIVE_U54 RISCV_CPU_TYPE_NAME("sifive-u54") +/* Deprecated */ +#define TYPE_RISCV_CPU_RV32IMACU_NOMMU RISCV_CPU_TYPE_NAME("rv32imacu-nommu") +#define TYPE_RISCV_CPU_RV32GCSU_V1_09_1 RISCV_CPU_TYPE_NAME("rv32gcsu-v1.9.1") +#define TYPE_RISCV_CPU_RV32GCSU_V1_10_0 RISCV_CPU_TYPE_NAME("rv32gcsu-v1.10.0") +#define TYPE_RISCV_CPU_RV64IMACU_NOMMU RISCV_CPU_TYPE_NAME("rv64imacu-nommu") +#define TYPE_RISCV_CPU_RV64GCSU_V1_09_1 RISCV_CPU_TYPE_NAME("rv64gcsu-v1.9.1") +#define TYPE_RISCV_CPU_RV64GCSU_V1_10_0 RISCV_CPU_TYPE_NAME("rv64gcsu-v1.10.0") #define RV32 ((target_ulong)1 << (TARGET_LONG_BITS - 2)) #define RV64 ((target_ulong)2 << (TARGET_LONG_BITS - 2)) @@ -77,10 +78,11 @@ enum { RISCV_FEATURE_MISA }; -#define USER_VERSION_2_02_0 0x00020200 #define PRIV_VERSION_1_09_1 0x00010901 #define PRIV_VERSION_1_10_0 0x00011000 +#define PRIV_VERSION_1_11_0 0x00011100 +#define TRANSLATE_PMP_FAIL 2 #define TRANSLATE_FAIL 1 #define TRANSLATE_SUCCESS 0 #define MMU_USER_IDX 3 @@ -102,7 +104,6 @@ struct CPURISCVState { target_ulong badaddr; - target_ulong user_ver; target_ulong priv_ver; target_ulong misa; target_ulong misa_mask; @@ -211,6 +212,20 @@ typedef struct RISCVCPU { /* Configuration Settings */ struct { + bool ext_i; + bool ext_e; + bool ext_g; + bool ext_m; + bool ext_a; + bool ext_f; + bool ext_d; + bool ext_c; + bool ext_s; + bool ext_u; + bool ext_counters; + bool ext_ifencei; + bool ext_icsr; + char *priv_spec; char *user_spec; bool mmu; @@ -248,6 +263,8 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr, bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, MMUAccessType access_type, int mmu_idx, bool probe, uintptr_t retaddr); +void riscv_cpu_unassigned_access(CPUState *cpu, hwaddr addr, bool is_write, + bool is_exec, int unused, unsigned size); char *riscv_isa_string(RISCVCPU *cpu); void riscv_cpu_list(void); diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 47450a3cdb..11f971ad5d 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -136,6 +136,7 @@ #define CSR_MCOUNTEREN 0x306 /* Legacy Counter Setup (priv v1.9.1) */ +/* Update to #define CSR_MCOUNTINHIBIT 0x320 for 1.11.0 */ #define CSR_MUCOUNTEREN 0x320 #define CSR_MSCOUNTEREN 0x321 #define CSR_MHCOUNTEREN 0x322 diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 8b6754b917..e32b6126af 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -132,6 +132,16 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv) } /* tlb_flush is unnecessary as mode is contained in mmu_idx */ env->priv = newpriv; + + /* + * Clear the load reservation - otherwise a reservation placed in one + * context/process can be used by another, resulting in an SC succeeding + * incorrectly. Version 2.2 of the ISA specification explicitly requires + * this behaviour, while later revisions say that the kernel "should" use + * an SC instruction to force the yielding of a load reservation on a + * preemptive context switch. As a result, do both. + */ + env->load_res = -1; } /* get_physical_address - get the physical address for this virtual address @@ -230,6 +240,12 @@ restart: /* check that physical address of PTE is legal */ target_ulong pte_addr = base + idx * ptesize; + + if (riscv_feature(env, RISCV_FEATURE_PMP) && + !pmp_hart_has_privs(env, pte_addr, sizeof(target_ulong), + 1 << MMU_DATA_LOAD, PRV_S)) { + return TRANSLATE_PMP_FAIL; + } #if defined(TARGET_RISCV32) target_ulong pte = ldl_phys(cs->as, pte_addr); #elif defined(TARGET_RISCV64) @@ -337,12 +353,13 @@ restart: } static void raise_mmu_exception(CPURISCVState *env, target_ulong address, - MMUAccessType access_type) + MMUAccessType access_type, bool pmp_violation) { CPUState *cs = env_cpu(env); int page_fault_exceptions = (env->priv_ver >= PRIV_VERSION_1_10_0) && - get_field(env->satp, SATP_MODE) != VM_1_10_MBARE; + get_field(env->satp, SATP_MODE) != VM_1_10_MBARE && + !pmp_violation; switch (access_type) { case MMU_INST_FETCH: cs->exception_index = page_fault_exceptions ? @@ -375,6 +392,22 @@ hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) return phys_addr; } +void riscv_cpu_unassigned_access(CPUState *cs, hwaddr addr, bool is_write, + bool is_exec, int unused, unsigned size) +{ + RISCVCPU *cpu = RISCV_CPU(cs); + CPURISCVState *env = &cpu->env; + + if (is_write) { + cs->exception_index = RISCV_EXCP_STORE_AMO_ACCESS_FAULT; + } else { + cs->exception_index = RISCV_EXCP_LOAD_ACCESS_FAULT; + } + + env->badaddr = addr; + riscv_raise_exception(&cpu->env, cs->exception_index, GETPC()); +} + void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr, MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) @@ -408,20 +441,32 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, CPURISCVState *env = &cpu->env; hwaddr pa = 0; int prot; + bool pmp_violation = false; int ret = TRANSLATE_FAIL; + int mode = mmu_idx; qemu_log_mask(CPU_LOG_MMU, "%s ad %" VADDR_PRIx " rw %d mmu_idx %d\n", __func__, address, access_type, mmu_idx); ret = get_physical_address(env, &pa, &prot, address, access_type, mmu_idx); + if (mode == PRV_M && access_type != MMU_INST_FETCH) { + if (get_field(env->mstatus, MSTATUS_MPRV)) { + mode = get_field(env->mstatus, MSTATUS_MPP); + } + } + qemu_log_mask(CPU_LOG_MMU, "%s address=%" VADDR_PRIx " ret %d physical " TARGET_FMT_plx " prot %d\n", __func__, address, ret, pa, prot); if (riscv_feature(env, RISCV_FEATURE_PMP) && - !pmp_hart_has_privs(env, pa, TARGET_PAGE_SIZE, 1 << access_type)) { - ret = TRANSLATE_FAIL; + (ret == TRANSLATE_SUCCESS) && + !pmp_hart_has_privs(env, pa, size, 1 << access_type, mode)) { + ret = TRANSLATE_PMP_FAIL; + } + if (ret == TRANSLATE_PMP_FAIL) { + pmp_violation = true; } if (ret == TRANSLATE_SUCCESS) { tlb_set_page(cs, address & TARGET_PAGE_MASK, pa & TARGET_PAGE_MASK, @@ -430,7 +475,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, } else if (probe) { return false; } else { - raise_mmu_exception(env, address, access_type); + raise_mmu_exception(env, address, access_type, pmp_violation); riscv_raise_exception(env, cs->exception_index, retaddr); } #else diff --git a/target/riscv/csr.c b/target/riscv/csr.c index c67d29e206..e0d4586760 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -56,8 +56,24 @@ static int fs(CPURISCVState *env, int csrno) static int ctr(CPURISCVState *env, int csrno) { #if !defined(CONFIG_USER_ONLY) + CPUState *cs = env_cpu(env); + RISCVCPU *cpu = RISCV_CPU(cs); uint32_t ctr_en = ~0u; + if (!cpu->cfg.ext_counters) { + /* The Counters extensions is not enabled */ + return -1; + } + + /* + * The counters are always enabled at run time on newer priv specs, as the + * CSR has changed from controlling that the counters can be read to + * controlling that the counters increment. + */ + if (env->priv_ver > PRIV_VERSION_1_09_1) { + return 0; + } + if (env->priv < PRV_M) { ctr_en &= env->mcounteren; } @@ -461,18 +477,22 @@ static int write_mcounteren(CPURISCVState *env, int csrno, target_ulong val) return 0; } +/* This regiser is replaced with CSR_MCOUNTINHIBIT in 1.11.0 */ static int read_mscounteren(CPURISCVState *env, int csrno, target_ulong *val) { - if (env->priv_ver > PRIV_VERSION_1_09_1) { + if (env->priv_ver > PRIV_VERSION_1_09_1 + && env->priv_ver < PRIV_VERSION_1_11_0) { return -1; } *val = env->mcounteren; return 0; } +/* This regiser is replaced with CSR_MCOUNTINHIBIT in 1.11.0 */ static int write_mscounteren(CPURISCVState *env, int csrno, target_ulong val) { - if (env->priv_ver > PRIV_VERSION_1_09_1) { + if (env->priv_ver > PRIV_VERSION_1_09_1 + && env->priv_ver < PRIV_VERSION_1_11_0) { return -1; } env->mcounteren = val; @@ -773,6 +793,7 @@ int riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value, { int ret; target_ulong old_value; + RISCVCPU *cpu = env_archcpu(env); /* check privileges and return -1 if check fails */ #if !defined(CONFIG_USER_ONLY) @@ -783,6 +804,11 @@ int riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value, } #endif + /* ensure the CSR extension is enabled. */ + if (!cpu->cfg.ext_icsr) { + return -1; + } + /* check predicate */ if (!csr_ops[csrno].predicate || csr_ops[csrno].predicate(env, csrno) < 0) { return -1; diff --git a/target/riscv/insn_trans/trans_privileged.inc.c b/target/riscv/insn_trans/trans_privileged.inc.c index 664d6ba3f2..c5e4b3e49a 100644 --- a/target/riscv/insn_trans/trans_privileged.inc.c +++ b/target/riscv/insn_trans/trans_privileged.inc.c @@ -90,7 +90,7 @@ static bool trans_wfi(DisasContext *ctx, arg_wfi *a) static bool trans_sfence_vma(DisasContext *ctx, arg_sfence_vma *a) { #ifndef CONFIG_USER_ONLY - if (ctx->priv_ver == PRIV_VERSION_1_10_0) { + if (ctx->priv_ver >= PRIV_VERSION_1_10_0) { gen_helper_tlb_flush(cpu_env); return true; } diff --git a/target/riscv/insn_trans/trans_rva.inc.c b/target/riscv/insn_trans/trans_rva.inc.c index f6dbbc065e..fadd88849e 100644 --- a/target/riscv/insn_trans/trans_rva.inc.c +++ b/target/riscv/insn_trans/trans_rva.inc.c @@ -61,7 +61,7 @@ static inline bool gen_sc(DisasContext *ctx, arg_atomic *a, TCGMemOp mop) gen_set_label(l1); /* - * Address comparion failure. However, we still need to + * Address comparison failure. However, we still need to * provide the memory barrier implied by AQ/RL. */ tcg_gen_mb(TCG_MO_ALL + a->aq * TCG_BAR_LDAQ + a->rl * TCG_BAR_STRL); @@ -69,6 +69,12 @@ static inline bool gen_sc(DisasContext *ctx, arg_atomic *a, TCGMemOp mop) gen_set_gpr(a->rd, dat); gen_set_label(l2); + /* + * Clear the load reservation, since an SC must fail if there is + * an SC to any address, in between an LR and SC pair. + */ + tcg_gen_movi_tl(load_res, -1); + tcg_temp_free(dat); tcg_temp_free(src1); tcg_temp_free(src2); diff --git a/target/riscv/insn_trans/trans_rvi.inc.c b/target/riscv/insn_trans/trans_rvi.inc.c index 6cda078ed6..ea6473111c 100644 --- a/target/riscv/insn_trans/trans_rvi.inc.c +++ b/target/riscv/insn_trans/trans_rvi.inc.c @@ -484,6 +484,10 @@ static bool trans_fence(DisasContext *ctx, arg_fence *a) static bool trans_fence_i(DisasContext *ctx, arg_fence_i *a) { + if (!ctx->ext_ifencei) { + return false; + } + /* * FENCE_I is a no-op in QEMU, * however we need to end the translation block diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c index fed1c3c030..958c7502a0 100644 --- a/target/riscv/pmp.c +++ b/target/riscv/pmp.c @@ -228,7 +228,7 @@ static int pmp_is_in_range(CPURISCVState *env, int pmp_index, target_ulong addr) * Check if the address has required RWX privs to complete desired operation */ bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr, - target_ulong size, pmp_priv_t privs) + target_ulong size, pmp_priv_t privs, target_ulong mode) { int i = 0; int ret = -1; @@ -245,7 +245,7 @@ bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr, from low to high */ for (i = 0; i < MAX_RISCV_PMPS; i++) { s = pmp_is_in_range(env, i, addr); - e = pmp_is_in_range(env, i, addr + size); + e = pmp_is_in_range(env, i, addr + size - 1); /* partially inside */ if ((s + e) == 1) { @@ -258,13 +258,14 @@ bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr, /* fully inside */ const uint8_t a_field = pmp_get_a_field(env->pmp_state.pmp[i].cfg_reg); - if ((s + e) == 2) { - if (PMP_AMATCH_OFF == a_field) { - return 1; - } + /* + * If the PMP entry is not off and the address is in range, do the priv + * check + */ + if (((s + e) == 2) && (PMP_AMATCH_OFF != a_field)) { allowed_privs = PMP_READ | PMP_WRITE | PMP_EXEC; - if ((env->priv != PRV_M) || pmp_is_locked(env, i)) { + if ((mode != PRV_M) || pmp_is_locked(env, i)) { allowed_privs &= env->pmp_state.pmp[i].cfg_reg; } @@ -280,7 +281,7 @@ bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr, /* No rule matched */ if (ret == -1) { - if (env->priv == PRV_M) { + if (mode == PRV_M) { ret = 1; /* Privileged spec v1.10 states if no PMP entry matches an * M-Mode access, the access succeeds */ } else { diff --git a/target/riscv/pmp.h b/target/riscv/pmp.h index 66790950eb..8e19793132 100644 --- a/target/riscv/pmp.h +++ b/target/riscv/pmp.h @@ -59,6 +59,6 @@ void pmpaddr_csr_write(CPURISCVState *env, uint32_t addr_index, target_ulong val); target_ulong pmpaddr_csr_read(CPURISCVState *env, uint32_t addr_index); bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr, - target_ulong size, pmp_priv_t priv); + target_ulong size, pmp_priv_t priv, target_ulong mode); #endif diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 313c27b700..8d6ab73258 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -54,6 +54,7 @@ typedef struct DisasContext { to any system register, which includes CSR_FRM, so we do not have to reset this known value. */ int frm; + bool ext_ifencei; } DisasContext; #ifdef TARGET_RISCV64 @@ -752,6 +753,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) { DisasContext *ctx = container_of(dcbase, DisasContext, base); CPURISCVState *env = cs->env_ptr; + RISCVCPU *cpu = RISCV_CPU(cs); ctx->pc_succ_insn = ctx->base.pc_first; ctx->mem_idx = ctx->base.tb->flags & TB_FLAGS_MMU_MASK; @@ -759,6 +761,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) ctx->priv_ver = env->priv_ver; ctx->misa = env->misa; ctx->frm = -1; /* unknown rounding mode */ + ctx->ext_ifencei = cpu->cfg.ext_ifencei; } static void riscv_tr_tb_start(DisasContextBase *db, CPUState *cpu) diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c index f2d93644d5..8540e7a2cb 100644 --- a/target/s390x/cpu.c +++ b/target/s390x/cpu.c @@ -31,7 +31,7 @@ #include "qemu/module.h" #include "trace.h" #include "qapi/visitor.h" -#include "qapi/qapi-visit-misc.h" +#include "qapi/qapi-types-machine.h" #include "qapi/qapi-visit-run-state.h" #include "sysemu/hw_accel.h" #include "hw/qdev-properties.h" diff --git a/target/s390x/cpu_features.c b/target/s390x/cpu_features.c index f64f581c86..9f817e3cfa 100644 --- a/target/s390x/cpu_features.c +++ b/target/s390x/cpu_features.c @@ -2,8 +2,9 @@ * CPU features/facilities for s390x * * Copyright IBM Corp. 2016, 2018 + * Copyright Red Hat, Inc. 2019 * - * Author(s): David Hildenbrand <dahi@linux.vnet.ibm.com> + * Author(s): David Hildenbrand <david@redhat.com> * * This work is licensed under the terms of the GNU GPL, version 2 or (at * your option) any later version. See the COPYING file in the top-level @@ -14,346 +15,17 @@ #include "qemu/module.h" #include "cpu_features.h" -#define FEAT_INIT(_name, _type, _bit, _desc) \ - { \ - .name = _name, \ - .type = _type, \ - .bit = _bit, \ - .desc = _desc, \ - } - -/* S390FeatDef.bit is not applicable as there is no feature block. */ -#define FEAT_INIT_MISC(_name, _desc) \ - FEAT_INIT(_name, S390_FEAT_TYPE_MISC, 0, _desc) - -/* indexed by feature number for easy lookup */ -static const S390FeatDef s390_features[] = { - FEAT_INIT("esan3", S390_FEAT_TYPE_STFL, 0, "Instructions marked as n3"), - FEAT_INIT("zarch", S390_FEAT_TYPE_STFL, 1, "z/Architecture architectural mode"), - FEAT_INIT("dateh", S390_FEAT_TYPE_STFL, 3, "DAT-enhancement facility"), - FEAT_INIT("idtes", S390_FEAT_TYPE_STFL, 4, "IDTE selective TLB segment-table clearing"), - FEAT_INIT("idter", S390_FEAT_TYPE_STFL, 5, "IDTE selective TLB region-table clearing"), - FEAT_INIT("asnlxr", S390_FEAT_TYPE_STFL, 6, "ASN-and-LX reuse facility"), - FEAT_INIT("stfle", S390_FEAT_TYPE_STFL, 7, "Store-facility-list-extended facility"), - FEAT_INIT("edat", S390_FEAT_TYPE_STFL, 8, "Enhanced-DAT facility"), - FEAT_INIT("srs", S390_FEAT_TYPE_STFL, 9, "Sense-running-status facility"), - FEAT_INIT("csske", S390_FEAT_TYPE_STFL, 10, "Conditional-SSKE facility"), - FEAT_INIT("ctop", S390_FEAT_TYPE_STFL, 11, "Configuration-topology facility"), - FEAT_INIT("apqci", S390_FEAT_TYPE_STFL, 12, "Query AP Configuration Information facility"), - FEAT_INIT("ipter", S390_FEAT_TYPE_STFL, 13, "IPTE-range facility"), - FEAT_INIT("nonqks", S390_FEAT_TYPE_STFL, 14, "Nonquiescing key-setting facility"), - FEAT_INIT("apft", S390_FEAT_TYPE_STFL, 15, "AP Facilities Test facility"), - FEAT_INIT("etf2", S390_FEAT_TYPE_STFL, 16, "Extended-translation facility 2"), - FEAT_INIT("msa-base", S390_FEAT_TYPE_STFL, 17, "Message-security-assist facility (excluding subfunctions)"), - FEAT_INIT("ldisp", S390_FEAT_TYPE_STFL, 18, "Long-displacement facility"), - FEAT_INIT("ldisphp", S390_FEAT_TYPE_STFL, 19, "Long-displacement facility has high performance"), - FEAT_INIT("hfpm", S390_FEAT_TYPE_STFL, 20, "HFP-multiply-add/subtract facility"), - FEAT_INIT("eimm", S390_FEAT_TYPE_STFL, 21, "Extended-immediate facility"), - FEAT_INIT("etf3", S390_FEAT_TYPE_STFL, 22, "Extended-translation facility 3"), - FEAT_INIT("hfpue", S390_FEAT_TYPE_STFL, 23, "HFP-unnormalized-extension facility"), - FEAT_INIT("etf2eh", S390_FEAT_TYPE_STFL, 24, "ETF2-enhancement facility"), - FEAT_INIT("stckf", S390_FEAT_TYPE_STFL, 25, "Store-clock-fast facility"), - FEAT_INIT("parseh", S390_FEAT_TYPE_STFL, 26, "Parsing-enhancement facility"), - FEAT_INIT("mvcos", S390_FEAT_TYPE_STFL, 27, "Move-with-optional-specification facility"), - FEAT_INIT("tods-base", S390_FEAT_TYPE_STFL, 28, "TOD-clock-steering facility (excluding subfunctions)"), - FEAT_INIT("etf3eh", S390_FEAT_TYPE_STFL, 30, "ETF3-enhancement facility"), - FEAT_INIT("ectg", S390_FEAT_TYPE_STFL, 31, "Extract-CPU-time facility"), - FEAT_INIT("csst", S390_FEAT_TYPE_STFL, 32, "Compare-and-swap-and-store facility"), - FEAT_INIT("csst2", S390_FEAT_TYPE_STFL, 33, "Compare-and-swap-and-store facility 2"), - FEAT_INIT("ginste", S390_FEAT_TYPE_STFL, 34, "General-instructions-extension facility"), - FEAT_INIT("exrl", S390_FEAT_TYPE_STFL, 35, "Execute-extensions facility"), - FEAT_INIT("emon", S390_FEAT_TYPE_STFL, 36, "Enhanced-monitor facility"), - FEAT_INIT("fpe", S390_FEAT_TYPE_STFL, 37, "Floating-point extension facility"), - FEAT_INIT("opc", S390_FEAT_TYPE_STFL, 38, "Order Preserving Compression facility"), - FEAT_INIT("sprogp", S390_FEAT_TYPE_STFL, 40, "Set-program-parameters facility"), - FEAT_INIT("fpseh", S390_FEAT_TYPE_STFL, 41, "Floating-point-support-enhancement facilities"), - FEAT_INIT("dfp", S390_FEAT_TYPE_STFL, 42, "DFP (decimal-floating-point) facility"), - FEAT_INIT("dfphp", S390_FEAT_TYPE_STFL, 43, "DFP (decimal-floating-point) facility has high performance"), - FEAT_INIT("pfpo", S390_FEAT_TYPE_STFL, 44, "PFPO instruction"), - FEAT_INIT("stfle45", S390_FEAT_TYPE_STFL, 45, "Various facilities introduced with z196"), - FEAT_INIT("cmpsceh", S390_FEAT_TYPE_STFL, 47, "CMPSC-enhancement facility"), - FEAT_INIT("dfpzc", S390_FEAT_TYPE_STFL, 48, "Decimal-floating-point zoned-conversion facility"), - FEAT_INIT("stfle49", S390_FEAT_TYPE_STFL, 49, "Various facilities introduced with zEC12"), - FEAT_INIT("cte", S390_FEAT_TYPE_STFL, 50, "Constrained transactional-execution facility"), - FEAT_INIT("ltlbc", S390_FEAT_TYPE_STFL, 51, "Local-TLB-clearing facility"), - FEAT_INIT("iacc2", S390_FEAT_TYPE_STFL, 52, "Interlocked-access facility 2"), - FEAT_INIT("stfle53", S390_FEAT_TYPE_STFL, 53, "Various facilities introduced with z13"), - FEAT_INIT("eec", S390_FEAT_TYPE_STFL, 54, "Entropy encoding compression facility"), - FEAT_INIT("msa5-base", S390_FEAT_TYPE_STFL, 57, "Message-security-assist-extension-5 facility (excluding subfunctions)"), - FEAT_INIT("minste2", S390_FEAT_TYPE_STFL, 58, "Miscellaneous-instruction-extensions facility 2"), - FEAT_INIT("sema", S390_FEAT_TYPE_STFL, 59, "Semaphore-assist facility"), - FEAT_INIT("tsi", S390_FEAT_TYPE_STFL, 60, "Time-slice Instrumentation facility"), - FEAT_INIT("minste3", S390_FEAT_TYPE_STFL, 61, "Miscellaneous-Instruction-Extensions Facility 3"), - FEAT_INIT("ri", S390_FEAT_TYPE_STFL, 64, "CPU runtime-instrumentation facility"), - FEAT_INIT("zpci", S390_FEAT_TYPE_STFL, 69, "z/PCI facility"), - FEAT_INIT("aen", S390_FEAT_TYPE_STFL, 71, "General-purpose-adapter-event-notification facility"), - FEAT_INIT("ais", S390_FEAT_TYPE_STFL, 72, "General-purpose-adapter-interruption-suppression facility"), - FEAT_INIT("te", S390_FEAT_TYPE_STFL, 73, "Transactional-execution facility"), - FEAT_INIT("sthyi", S390_FEAT_TYPE_STFL, 74, "Store-hypervisor-information facility"), - FEAT_INIT("aefsi", S390_FEAT_TYPE_STFL, 75, "Access-exception-fetch/store-indication facility"), - FEAT_INIT("msa3-base", S390_FEAT_TYPE_STFL, 76, "Message-security-assist-extension-3 facility (excluding subfunctions)"), - FEAT_INIT("msa4-base", S390_FEAT_TYPE_STFL, 77, "Message-security-assist-extension-4 facility (excluding subfunctions)"), - FEAT_INIT("edat2", S390_FEAT_TYPE_STFL, 78, "Enhanced-DAT facility 2"), - FEAT_INIT("dfppc", S390_FEAT_TYPE_STFL, 80, "Decimal-floating-point packed-conversion facility"), - FEAT_INIT("ppa15", S390_FEAT_TYPE_STFL, 81, "PPA15 is installed"), - FEAT_INIT("bpb", S390_FEAT_TYPE_STFL, 82, "Branch prediction blocking"), - FEAT_INIT("vx", S390_FEAT_TYPE_STFL, 129, "Vector facility"), - FEAT_INIT("iep", S390_FEAT_TYPE_STFL, 130, "Instruction-execution-protection facility"), - FEAT_INIT("sea_esop2", S390_FEAT_TYPE_STFL, 131, "Side-effect-access facility and Enhanced-suppression-on-protection facility 2"), - FEAT_INIT("gs", S390_FEAT_TYPE_STFL, 133, "Guarded-storage facility"), - FEAT_INIT("vxpd", S390_FEAT_TYPE_STFL, 134, "Vector packed decimal facility"), - FEAT_INIT("vxeh", S390_FEAT_TYPE_STFL, 135, "Vector enhancements facility"), - FEAT_INIT("mepoch", S390_FEAT_TYPE_STFL, 139, "Multiple-epoch facility"), - FEAT_INIT("tpei", S390_FEAT_TYPE_STFL, 144, "Test-pending-external-interruption facility"), - FEAT_INIT("irbm", S390_FEAT_TYPE_STFL, 145, "Insert-reference-bits-multiple facility"), - FEAT_INIT("msa8-base", S390_FEAT_TYPE_STFL, 146, "Message-security-assist-extension-8 facility (excluding subfunctions)"), - FEAT_INIT("cmmnt", S390_FEAT_TYPE_STFL, 147, "CMM: ESSA-enhancement (no translate) facility"), - FEAT_INIT("vxeh2", S390_FEAT_TYPE_STFL, 148, "Vector Enhancements facility 2"), - FEAT_INIT("esort-base", S390_FEAT_TYPE_STFL, 150, "Enhanced-sort facility (excluding subfunctions)"), - FEAT_INIT("deflate-base", S390_FEAT_TYPE_STFL, 151, "Deflate-conversion facility (excluding subfunctions)"), - FEAT_INIT("vxbeh", S390_FEAT_TYPE_STFL, 152, "Vector BCD enhancements facility 1"), - FEAT_INIT("msa9-base", S390_FEAT_TYPE_STFL, 155, "Message-security-assist-extension-9 facility (excluding subfunctions)"), - FEAT_INIT("etoken", S390_FEAT_TYPE_STFL, 156, "Etoken facility"), - - /* SCLP SCCB Byte 80 - 98 (bit numbers relative to byte-80) */ - FEAT_INIT("gsls", S390_FEAT_TYPE_SCLP_CONF_CHAR, 40, "SIE: Guest-storage-limit-suppression facility"), - FEAT_INIT("esop", S390_FEAT_TYPE_SCLP_CONF_CHAR, 46, "Enhanced-suppression-on-protection facility"), - FEAT_INIT("hpma2", S390_FEAT_TYPE_SCLP_CONF_CHAR, 90, "Host page management assist 2 Facility"), /* 91-2 */ - FEAT_INIT("kss", S390_FEAT_TYPE_SCLP_CONF_CHAR, 151, "SIE: Keyless-subset facility"), /* 98-7 */ - - /* SCLP SCCB Byte 116 - 119 (bit numbers relative to byte-116) */ - FEAT_INIT("64bscao", S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT, 0, "SIE: 64-bit-SCAO facility"), - FEAT_INIT("cmma", S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT, 1, "SIE: Collaborative-memory-management assist"), - FEAT_INIT("pfmfi", S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT, 9, "SIE: PFMF interpretation facility"), - FEAT_INIT("ibs", S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT, 10, "SIE: Interlock-and-broadcast-suppression facility"), - - FEAT_INIT("sief2", S390_FEAT_TYPE_SCLP_CPU, 4, "SIE: interception format 2 (Virtual SIE)"), - FEAT_INIT("skey", S390_FEAT_TYPE_SCLP_CPU, 5, "SIE: Storage-key facility"), - FEAT_INIT("gpereh", S390_FEAT_TYPE_SCLP_CPU, 10, "SIE: Guest-PER enhancement facility"), - FEAT_INIT("siif", S390_FEAT_TYPE_SCLP_CPU, 11, "SIE: Shared IPTE-interlock facility"), - FEAT_INIT("sigpif", S390_FEAT_TYPE_SCLP_CPU, 12, "SIE: SIGP interpretation facility"), - FEAT_INIT("ib", S390_FEAT_TYPE_SCLP_CPU, 42, "SIE: Intervention bypass facility"), - FEAT_INIT("cei", S390_FEAT_TYPE_SCLP_CPU, 43, "SIE: Conditional-external-interception facility"), - - FEAT_INIT_MISC("dateh2", "DAT-enhancement facility 2"), - FEAT_INIT_MISC("cmm", "Collaborative-memory-management facility"), - FEAT_INIT_MISC("ap", "AP instructions installed"), - - FEAT_INIT("plo-cl", S390_FEAT_TYPE_PLO, 0, "PLO Compare and load (32 bit in general registers)"), - FEAT_INIT("plo-clg", S390_FEAT_TYPE_PLO, 1, "PLO Compare and load (64 bit in parameter list)"), - FEAT_INIT("plo-clgr", S390_FEAT_TYPE_PLO, 2, "PLO Compare and load (32 bit in general registers)"), - FEAT_INIT("plo-clx", S390_FEAT_TYPE_PLO, 3, "PLO Compare and load (128 bit in parameter list)"), - FEAT_INIT("plo-cs", S390_FEAT_TYPE_PLO, 4, "PLO Compare and swap (32 bit in general registers)"), - FEAT_INIT("plo-csg", S390_FEAT_TYPE_PLO, 5, "PLO Compare and swap (64 bit in parameter list)"), - FEAT_INIT("plo-csgr", S390_FEAT_TYPE_PLO, 6, "PLO Compare and swap (32 bit in general registers)"), - FEAT_INIT("plo-csx", S390_FEAT_TYPE_PLO, 7, "PLO Compare and swap (128 bit in parameter list)"), - FEAT_INIT("plo-dcs", S390_FEAT_TYPE_PLO, 8, "PLO Double compare and swap (32 bit in general registers)"), - FEAT_INIT("plo-dcsg", S390_FEAT_TYPE_PLO, 9, "PLO Double compare and swap (64 bit in parameter list)"), - FEAT_INIT("plo-dcsgr", S390_FEAT_TYPE_PLO, 10, "PLO Double compare and swap (32 bit in general registers)"), - FEAT_INIT("plo-dcsx", S390_FEAT_TYPE_PLO, 11, "PLO Double compare and swap (128 bit in parameter list)"), - FEAT_INIT("plo-csst", S390_FEAT_TYPE_PLO, 12, "PLO Compare and swap and store (32 bit in general registers)"), - FEAT_INIT("plo-csstg", S390_FEAT_TYPE_PLO, 13, "PLO Compare and swap and store (64 bit in parameter list)"), - FEAT_INIT("plo-csstgr", S390_FEAT_TYPE_PLO, 14, "PLO Compare and swap and store (32 bit in general registers)"), - FEAT_INIT("plo-csstx", S390_FEAT_TYPE_PLO, 15, "PLO Compare and swap and store (128 bit in parameter list)"), - FEAT_INIT("plo-csdst", S390_FEAT_TYPE_PLO, 16, "PLO Compare and swap and double store (32 bit in general registers)"), - FEAT_INIT("plo-csdstg", S390_FEAT_TYPE_PLO, 17, "PLO Compare and swap and double store (64 bit in parameter list)"), - FEAT_INIT("plo-csdstgr", S390_FEAT_TYPE_PLO, 18, "PLO Compare and swap and double store (32 bit in general registers)"), - FEAT_INIT("plo-csdstx", S390_FEAT_TYPE_PLO, 19, "PLO Compare and swap and double store (128 bit in parameter list)"), - FEAT_INIT("plo-cstst", S390_FEAT_TYPE_PLO, 20, "PLO Compare and swap and triple store (32 bit in general registers)"), - FEAT_INIT("plo-cststg", S390_FEAT_TYPE_PLO, 21, "PLO Compare and swap and triple store (64 bit in parameter list)"), - FEAT_INIT("plo-cststgr", S390_FEAT_TYPE_PLO, 22, "PLO Compare and swap and triple store (32 bit in general registers)"), - FEAT_INIT("plo-cststx", S390_FEAT_TYPE_PLO, 23, "PLO Compare and swap and triple store (128 bit in parameter list)"), - - FEAT_INIT("ptff-qto", S390_FEAT_TYPE_PTFF, 1, "PTFF Query TOD Offset"), - FEAT_INIT("ptff-qsi", S390_FEAT_TYPE_PTFF, 2, "PTFF Query Steering Information"), - FEAT_INIT("ptff-qpc", S390_FEAT_TYPE_PTFF, 3, "PTFF Query Physical Clock"), - FEAT_INIT("ptff-qui", S390_FEAT_TYPE_PTFF, 4, "PTFF Query UTC Information"), - FEAT_INIT("ptff-qtou", S390_FEAT_TYPE_PTFF, 5, "PTFF Query TOD Offset User"), - FEAT_INIT("ptff-qsie", S390_FEAT_TYPE_PTFF, 10, "PTFF Query Steering Information Extended"), - FEAT_INIT("ptff-qtoue", S390_FEAT_TYPE_PTFF, 13, "PTFF Query TOD Offset User Extended"), - FEAT_INIT("ptff-sto", S390_FEAT_TYPE_PTFF, 65, "PTFF Set TOD Offset"), - FEAT_INIT("ptff-stou", S390_FEAT_TYPE_PTFF, 69, "PTFF Set TOD Offset User"), - FEAT_INIT("ptff-stoe", S390_FEAT_TYPE_PTFF, 73, "PTFF Set TOD Offset Extended"), - FEAT_INIT("ptff-stoue", S390_FEAT_TYPE_PTFF, 77, "PTFF Set TOD Offset User Extended"), - - FEAT_INIT("kmac-dea", S390_FEAT_TYPE_KMAC, 1, "KMAC DEA"), - FEAT_INIT("kmac-tdea-128", S390_FEAT_TYPE_KMAC, 2, "KMAC TDEA-128"), - FEAT_INIT("kmac-tdea-192", S390_FEAT_TYPE_KMAC, 3, "KMAC TDEA-192"), - FEAT_INIT("kmac-edea", S390_FEAT_TYPE_KMAC, 9, "KMAC Encrypted-DEA"), - FEAT_INIT("kmac-etdea-128", S390_FEAT_TYPE_KMAC, 10, "KMAC Encrypted-TDEA-128"), - FEAT_INIT("kmac-etdea-192", S390_FEAT_TYPE_KMAC, 11, "KMAC Encrypted-TDEA-192"), - FEAT_INIT("kmac-aes-128", S390_FEAT_TYPE_KMAC, 18, "KMAC AES-128"), - FEAT_INIT("kmac-aes-192", S390_FEAT_TYPE_KMAC, 19, "KMAC AES-192"), - FEAT_INIT("kmac-aes-256", S390_FEAT_TYPE_KMAC, 20, "KMAC AES-256"), - FEAT_INIT("kmac-eaes-128", S390_FEAT_TYPE_KMAC, 26, "KMAC Encrypted-AES-128"), - FEAT_INIT("kmac-eaes-192", S390_FEAT_TYPE_KMAC, 27, "KMAC Encrypted-AES-192"), - FEAT_INIT("kmac-eaes-256", S390_FEAT_TYPE_KMAC, 28, "KMAC Encrypted-AES-256"), - - FEAT_INIT("kmc-dea", S390_FEAT_TYPE_KMC, 1, "KMC DEA"), - FEAT_INIT("kmc-tdea-128", S390_FEAT_TYPE_KMC, 2, "KMC TDEA-128"), - FEAT_INIT("kmc-tdea-192", S390_FEAT_TYPE_KMC, 3, "KMC TDEA-192"), - FEAT_INIT("kmc-edea", S390_FEAT_TYPE_KMC, 9, "KMC Encrypted-DEA"), - FEAT_INIT("kmc-etdea-128", S390_FEAT_TYPE_KMC, 10, "KMC Encrypted-TDEA-128"), - FEAT_INIT("kmc-etdea-192", S390_FEAT_TYPE_KMC, 11, "KMC Encrypted-TDEA-192"), - FEAT_INIT("kmc-aes-128", S390_FEAT_TYPE_KMC, 18, "KMC AES-128"), - FEAT_INIT("kmc-aes-192", S390_FEAT_TYPE_KMC, 19, "KMC AES-192"), - FEAT_INIT("kmc-aes-256", S390_FEAT_TYPE_KMC, 20, "KMC AES-256"), - FEAT_INIT("kmc-eaes-128", S390_FEAT_TYPE_KMC, 26, "KMC Encrypted-AES-128"), - FEAT_INIT("kmc-eaes-192", S390_FEAT_TYPE_KMC, 27, "KMC Encrypted-AES-192"), - FEAT_INIT("kmc-eaes-256", S390_FEAT_TYPE_KMC, 28, "KMC Encrypted-AES-256"), - FEAT_INIT("kmc-prng", S390_FEAT_TYPE_KMC, 67, "KMC PRNG"), - - FEAT_INIT("km-dea", S390_FEAT_TYPE_KM, 1, "KM DEA"), - FEAT_INIT("km-tdea-128", S390_FEAT_TYPE_KM, 2, "KM TDEA-128"), - FEAT_INIT("km-tdea-192", S390_FEAT_TYPE_KM, 3, "KM TDEA-192"), - FEAT_INIT("km-edea", S390_FEAT_TYPE_KM, 9, "KM Encrypted-DEA"), - FEAT_INIT("km-etdea-128", S390_FEAT_TYPE_KM, 10, "KM Encrypted-TDEA-128"), - FEAT_INIT("km-etdea-192", S390_FEAT_TYPE_KM, 11, "KM Encrypted-TDEA-192"), - FEAT_INIT("km-aes-128", S390_FEAT_TYPE_KM, 18, "KM AES-128"), - FEAT_INIT("km-aes-192", S390_FEAT_TYPE_KM, 19, "KM AES-192"), - FEAT_INIT("km-aes-256", S390_FEAT_TYPE_KM, 20, "KM AES-256"), - FEAT_INIT("km-eaes-128", S390_FEAT_TYPE_KM, 26, "KM Encrypted-AES-128"), - FEAT_INIT("km-eaes-192", S390_FEAT_TYPE_KM, 27, "KM Encrypted-AES-192"), - FEAT_INIT("km-eaes-256", S390_FEAT_TYPE_KM, 28, "KM Encrypted-AES-256"), - FEAT_INIT("km-xts-aes-128", S390_FEAT_TYPE_KM, 50, "KM XTS-AES-128"), - FEAT_INIT("km-xts-aes-256", S390_FEAT_TYPE_KM, 52, "KM XTS-AES-256"), - FEAT_INIT("km-xts-eaes-128", S390_FEAT_TYPE_KM, 58, "KM XTS-Encrypted-AES-128"), - FEAT_INIT("km-xts-eaes-256", S390_FEAT_TYPE_KM, 60, "KM XTS-Encrypted-AES-256"), - - FEAT_INIT("kimd-sha-1", S390_FEAT_TYPE_KIMD, 1, "KIMD SHA-1"), - FEAT_INIT("kimd-sha-256", S390_FEAT_TYPE_KIMD, 2, "KIMD SHA-256"), - FEAT_INIT("kimd-sha-512", S390_FEAT_TYPE_KIMD, 3, "KIMD SHA-512"), - FEAT_INIT("kimd-sha3-224", S390_FEAT_TYPE_KIMD, 32, "KIMD SHA3-224"), - FEAT_INIT("kimd-sha3-256", S390_FEAT_TYPE_KIMD, 33, "KIMD SHA3-256"), - FEAT_INIT("kimd-sha3-384", S390_FEAT_TYPE_KIMD, 34, "KIMD SHA3-384"), - FEAT_INIT("kimd-sha3-512", S390_FEAT_TYPE_KIMD, 35, "KIMD SHA3-512"), - FEAT_INIT("kimd-shake-128", S390_FEAT_TYPE_KIMD, 36, "KIMD SHAKE-128"), - FEAT_INIT("kimd-shake-256", S390_FEAT_TYPE_KIMD, 37, "KIMD SHAKE-256"), - FEAT_INIT("kimd-ghash", S390_FEAT_TYPE_KIMD, 65, "KIMD GHASH"), - - FEAT_INIT("klmd-sha-1", S390_FEAT_TYPE_KLMD, 1, "KLMD SHA-1"), - FEAT_INIT("klmd-sha-256", S390_FEAT_TYPE_KLMD, 2, "KLMD SHA-256"), - FEAT_INIT("klmd-sha-512", S390_FEAT_TYPE_KLMD, 3, "KLMD SHA-512"), - FEAT_INIT("klmd-sha3-224", S390_FEAT_TYPE_KLMD, 32, "KLMD SHA3-224"), - FEAT_INIT("klmd-sha3-256", S390_FEAT_TYPE_KLMD, 33, "KLMD SHA3-256"), - FEAT_INIT("klmd-sha3-384", S390_FEAT_TYPE_KLMD, 34, "KLMD SHA3-384"), - FEAT_INIT("klmd-sha3-512", S390_FEAT_TYPE_KLMD, 35, "KLMD SHA3-512"), - FEAT_INIT("klmd-shake-128", S390_FEAT_TYPE_KLMD, 36, "KLMD SHAKE-128"), - FEAT_INIT("klmd-shake-256", S390_FEAT_TYPE_KLMD, 37, "KLMD SHAKE-256"), - - FEAT_INIT("pckmo-edea", S390_FEAT_TYPE_PCKMO, 1, "PCKMO Encrypted-DEA-Key"), - FEAT_INIT("pckmo-etdea-128", S390_FEAT_TYPE_PCKMO, 2, "PCKMO Encrypted-TDEA-128-Key"), - FEAT_INIT("pckmo-etdea-192", S390_FEAT_TYPE_PCKMO, 3, "PCKMO Encrypted-TDEA-192-Key"), - FEAT_INIT("pckmo-aes-128", S390_FEAT_TYPE_PCKMO, 18, "PCKMO Encrypted-AES-128-Key"), - FEAT_INIT("pckmo-aes-192", S390_FEAT_TYPE_PCKMO, 19, "PCKMO Encrypted-AES-192-Key"), - FEAT_INIT("pckmo-aes-256", S390_FEAT_TYPE_PCKMO, 20, "PCKMO Encrypted-AES-256-Key"), - FEAT_INIT("pckmo-ecc-p256", S390_FEAT_TYPE_PCKMO, 32, "PCKMO Encrypt-ECC-P256-Key"), - FEAT_INIT("pckmo-ecc-p384", S390_FEAT_TYPE_PCKMO, 33, "PCKMO Encrypt-ECC-P384-Key"), - FEAT_INIT("pckmo-ecc-p521", S390_FEAT_TYPE_PCKMO, 34, "PCKMO Encrypt-ECC-P521-Key"), - FEAT_INIT("pckmo-ecc-ed25519", S390_FEAT_TYPE_PCKMO, 40 , "PCKMO Encrypt-ECC-Ed25519-Key"), - FEAT_INIT("pckmo-ecc-ed448", S390_FEAT_TYPE_PCKMO, 41 , "PCKMO Encrypt-ECC-Ed448-Key"), - - FEAT_INIT("kmctr-dea", S390_FEAT_TYPE_KMCTR, 1, "KMCTR DEA"), - FEAT_INIT("kmctr-tdea-128", S390_FEAT_TYPE_KMCTR, 2, "KMCTR TDEA-128"), - FEAT_INIT("kmctr-tdea-192", S390_FEAT_TYPE_KMCTR, 3, "KMCTR TDEA-192"), - FEAT_INIT("kmctr-edea", S390_FEAT_TYPE_KMCTR, 9, "KMCTR Encrypted-DEA"), - FEAT_INIT("kmctr-etdea-128", S390_FEAT_TYPE_KMCTR, 10, "KMCTR Encrypted-TDEA-128"), - FEAT_INIT("kmctr-etdea-192", S390_FEAT_TYPE_KMCTR, 11, "KMCTR Encrypted-TDEA-192"), - FEAT_INIT("kmctr-aes-128", S390_FEAT_TYPE_KMCTR, 18, "KMCTR AES-128"), - FEAT_INIT("kmctr-aes-192", S390_FEAT_TYPE_KMCTR, 19, "KMCTR AES-192"), - FEAT_INIT("kmctr-aes-256", S390_FEAT_TYPE_KMCTR, 20, "KMCTR AES-256"), - FEAT_INIT("kmctr-eaes-128", S390_FEAT_TYPE_KMCTR, 26, "KMCTR Encrypted-AES-128"), - FEAT_INIT("kmctr-eaes-192", S390_FEAT_TYPE_KMCTR, 27, "KMCTR Encrypted-AES-192"), - FEAT_INIT("kmctr-eaes-256", S390_FEAT_TYPE_KMCTR, 28, "KMCTR Encrypted-AES-256"), - - FEAT_INIT("kmf-dea", S390_FEAT_TYPE_KMF, 1, "KMF DEA"), - FEAT_INIT("kmf-tdea-128", S390_FEAT_TYPE_KMF, 2, "KMF TDEA-128"), - FEAT_INIT("kmf-tdea-192", S390_FEAT_TYPE_KMF, 3, "KMF TDEA-192"), - FEAT_INIT("kmf-edea", S390_FEAT_TYPE_KMF, 9, "KMF Encrypted-DEA"), - FEAT_INIT("kmf-etdea-128", S390_FEAT_TYPE_KMF, 10, "KMF Encrypted-TDEA-128"), - FEAT_INIT("kmf-etdea-192", S390_FEAT_TYPE_KMF, 11, "KMF Encrypted-TDEA-192"), - FEAT_INIT("kmf-aes-128", S390_FEAT_TYPE_KMF, 18, "KMF AES-128"), - FEAT_INIT("kmf-aes-192", S390_FEAT_TYPE_KMF, 19, "KMF AES-192"), - FEAT_INIT("kmf-aes-256", S390_FEAT_TYPE_KMF, 20, "KMF AES-256"), - FEAT_INIT("kmf-eaes-128", S390_FEAT_TYPE_KMF, 26, "KMF Encrypted-AES-128"), - FEAT_INIT("kmf-eaes-192", S390_FEAT_TYPE_KMF, 27, "KMF Encrypted-AES-192"), - FEAT_INIT("kmf-eaes-256", S390_FEAT_TYPE_KMF, 28, "KMF Encrypted-AES-256"), - - FEAT_INIT("kmo-dea", S390_FEAT_TYPE_KMO, 1, "KMO DEA"), - FEAT_INIT("kmo-tdea-128", S390_FEAT_TYPE_KMO, 2, "KMO TDEA-128"), - FEAT_INIT("kmo-tdea-192", S390_FEAT_TYPE_KMO, 3, "KMO TDEA-192"), - FEAT_INIT("kmo-edea", S390_FEAT_TYPE_KMO, 9, "KMO Encrypted-DEA"), - FEAT_INIT("kmo-etdea-128", S390_FEAT_TYPE_KMO, 10, "KMO Encrypted-TDEA-128"), - FEAT_INIT("kmo-etdea-192", S390_FEAT_TYPE_KMO, 11, "KMO Encrypted-TDEA-192"), - FEAT_INIT("kmo-aes-128", S390_FEAT_TYPE_KMO, 18, "KMO AES-128"), - FEAT_INIT("kmo-aes-192", S390_FEAT_TYPE_KMO, 19, "KMO AES-192"), - FEAT_INIT("kmo-aes-256", S390_FEAT_TYPE_KMO, 20, "KMO AES-256"), - FEAT_INIT("kmo-eaes-128", S390_FEAT_TYPE_KMO, 26, "KMO Encrypted-AES-128"), - FEAT_INIT("kmo-eaes-192", S390_FEAT_TYPE_KMO, 27, "KMO Encrypted-AES-192"), - FEAT_INIT("kmo-eaes-256", S390_FEAT_TYPE_KMO, 28, "KMO Encrypted-AES-256"), - - FEAT_INIT("pcc-cmac-dea", S390_FEAT_TYPE_PCC, 1, "PCC Compute-Last-Block-CMAC-Using-DEA"), - FEAT_INIT("pcc-cmac-tdea-128", S390_FEAT_TYPE_PCC, 2, "PCC Compute-Last-Block-CMAC-Using-TDEA-128"), - FEAT_INIT("pcc-cmac-tdea-192", S390_FEAT_TYPE_PCC, 3, "PCC Compute-Last-Block-CMAC-Using-TDEA-192"), - FEAT_INIT("pcc-cmac-edea", S390_FEAT_TYPE_PCC, 9, "PCC Compute-Last-Block-CMAC-Using-Encrypted-DEA"), - FEAT_INIT("pcc-cmac-etdea-128", S390_FEAT_TYPE_PCC, 10, "PCC Compute-Last-Block-CMAC-Using-Encrypted-TDEA-128"), - FEAT_INIT("pcc-cmac-etdea-192", S390_FEAT_TYPE_PCC, 11, "PCC Compute-Last-Block-CMAC-Using-EncryptedTDEA-192"), - FEAT_INIT("pcc-cmac-aes-128", S390_FEAT_TYPE_PCC, 18, "PCC Compute-Last-Block-CMAC-Using-AES-128"), - FEAT_INIT("pcc-cmac-aes-192", S390_FEAT_TYPE_PCC, 19, "PCC Compute-Last-Block-CMAC-Using-AES-192"), - FEAT_INIT("pcc-cmac-eaes-256", S390_FEAT_TYPE_PCC, 20, "PCC Compute-Last-Block-CMAC-Using-AES-256"), - FEAT_INIT("pcc-cmac-eaes-128", S390_FEAT_TYPE_PCC, 26, "PCC Compute-Last-Block-CMAC-Using-Encrypted-AES-128"), - FEAT_INIT("pcc-cmac-eaes-192", S390_FEAT_TYPE_PCC, 27, "PCC Compute-Last-Block-CMAC-Using-Encrypted-AES-192"), - FEAT_INIT("pcc-cmac-eaes-256", S390_FEAT_TYPE_PCC, 28, "PCC Compute-Last-Block-CMAC-Using-Encrypted-AES-256"), - FEAT_INIT("pcc-xts-aes-128", S390_FEAT_TYPE_PCC, 50, "PCC Compute-XTS-Parameter-Using-AES-128"), - FEAT_INIT("pcc-xts-aes-256", S390_FEAT_TYPE_PCC, 52, "PCC Compute-XTS-Parameter-Using-AES-256"), - FEAT_INIT("pcc-xts-eaes-128", S390_FEAT_TYPE_PCC, 58, "PCC Compute-XTS-Parameter-Using-Encrypted-AES-128"), - FEAT_INIT("pcc-xts-eaes-256", S390_FEAT_TYPE_PCC, 60, "PCC Compute-XTS-Parameter-Using-Encrypted-AES-256"), - FEAT_INIT("pcc-scalar-mult-p256", S390_FEAT_TYPE_PCC, 64, "PCC Scalar-Multiply-P256"), - FEAT_INIT("pcc-scalar-mult-p384", S390_FEAT_TYPE_PCC, 65, "PCC Scalar-Multiply-P384"), - FEAT_INIT("pcc-scalar-mult-p521", S390_FEAT_TYPE_PCC, 66, "PCC Scalar-Multiply-P521"), - FEAT_INIT("pcc-scalar-mult-ed25519", S390_FEAT_TYPE_PCC, 72, "PCC Scalar-Multiply-Ed25519"), - FEAT_INIT("pcc-scalar-mult-ed448", S390_FEAT_TYPE_PCC, 73, "PCC Scalar-Multiply-Ed448"), - FEAT_INIT("pcc-scalar-mult-x25519", S390_FEAT_TYPE_PCC, 80, "PCC Scalar-Multiply-X25519"), - FEAT_INIT("pcc-scalar-mult-x448", S390_FEAT_TYPE_PCC, 81, "PCC Scalar-Multiply-X448"), - - FEAT_INIT("ppno-sha-512-drng", S390_FEAT_TYPE_PPNO, 3, "PPNO SHA-512-DRNG"), - FEAT_INIT("prno-trng-qrtcr", S390_FEAT_TYPE_PPNO, 112, "PRNO TRNG-Query-Raw-to-Conditioned-Ratio"), - FEAT_INIT("prno-trng", S390_FEAT_TYPE_PPNO, 114, "PRNO TRNG"), - - FEAT_INIT("kma-gcm-aes-128", S390_FEAT_TYPE_KMA, 18, "KMA GCM-AES-128"), - FEAT_INIT("kma-gcm-aes-192", S390_FEAT_TYPE_KMA, 19, "KMA GCM-AES-192"), - FEAT_INIT("kma-gcm-aes-256", S390_FEAT_TYPE_KMA, 20, "KMA GCM-AES-256"), - FEAT_INIT("kma-gcm-eaes-128", S390_FEAT_TYPE_KMA, 26, "KMA GCM-Encrypted-AES-128"), - FEAT_INIT("kma-gcm-eaes-192", S390_FEAT_TYPE_KMA, 27, "KMA GCM-Encrypted-AES-192"), - FEAT_INIT("kma-gcm-eaes-256", S390_FEAT_TYPE_KMA, 28, "KMA GCM-Encrypted-AES-256"), - - FEAT_INIT("kdsa-ecdsa-verify-p256", S390_FEAT_TYPE_KDSA, 1, "KDSA ECDSA-Verify-P256"), - FEAT_INIT("kdsa-ecdsa-verify-p384", S390_FEAT_TYPE_KDSA, 2, "KDSA ECDSA-Verify-P384"), - FEAT_INIT("kdsa-ecdsa-verify-p521", S390_FEAT_TYPE_KDSA, 3, "KDSA ECDSA-Verify-P521"), - FEAT_INIT("kdsa-ecdsa-sign-p256", S390_FEAT_TYPE_KDSA, 9, "KDSA ECDSA-Sign-P256"), - FEAT_INIT("kdsa-ecdsa-sign-p384", S390_FEAT_TYPE_KDSA, 10, "KDSA ECDSA-Sign-P384"), - FEAT_INIT("kdsa-ecdsa-sign-p521", S390_FEAT_TYPE_KDSA, 11, "KDSA ECDSA-Sign-P521"), - FEAT_INIT("kdsa-eecdsa-sign-p256", S390_FEAT_TYPE_KDSA, 17, "KDSA Encrypted-ECDSA-Sign-P256"), - FEAT_INIT("kdsa-eecdsa-sign-p384", S390_FEAT_TYPE_KDSA, 18, "KDSA Encrypted-ECDSA-Sign-P384"), - FEAT_INIT("kdsa-eecdsa-sign-p521", S390_FEAT_TYPE_KDSA, 19, "KDSA Encrypted-ECDSA-Sign-P521"), - FEAT_INIT("kdsa-eddsa-verify-ed25519", S390_FEAT_TYPE_KDSA, 32, "KDSA EdDSA-Verify-Ed25519"), - FEAT_INIT("kdsa-eddsa-verify-ed448", S390_FEAT_TYPE_KDSA, 36, "KDSA EdDSA-Verify-Ed448"), - FEAT_INIT("kdsa-eddsa-sign-ed25519", S390_FEAT_TYPE_KDSA, 40, "KDSA EdDSA-Sign-Ed25519"), - FEAT_INIT("kdsa-eddsa-sign-ed448", S390_FEAT_TYPE_KDSA, 44, "KDSA EdDSA-Sign-Ed448"), - FEAT_INIT("kdsa-eeddsa-sign-ed25519", S390_FEAT_TYPE_KDSA, 48, "KDSA Encrypted-EdDSA-Sign-Ed25519"), - FEAT_INIT("kdsa-eeddsa-sign-ed448", S390_FEAT_TYPE_KDSA, 52, "KDSA Encrypted-EdDSA-Sign-Ed448"), - - FEAT_INIT("sortl-sflr", S390_FEAT_TYPE_SORTL, 1, "SORTL SFLR"), - FEAT_INIT("sortl-svlr", S390_FEAT_TYPE_SORTL, 2, "SORTL SVLR"), - FEAT_INIT("sortl-32", S390_FEAT_TYPE_SORTL, 130, "SORTL 32 input lists"), - FEAT_INIT("sortl-128", S390_FEAT_TYPE_SORTL, 132, "SORTL 128 input lists"), - FEAT_INIT("sortl-f0", S390_FEAT_TYPE_SORTL, 192, "SORTL format 0 parameter-block"), - - FEAT_INIT("dfltcc-gdht", S390_FEAT_TYPE_DFLTCC, 1, "DFLTCC GDHT"), - FEAT_INIT("dfltcc-cmpr", S390_FEAT_TYPE_DFLTCC, 2, "DFLTCC CMPR"), - FEAT_INIT("dfltcc-xpnd", S390_FEAT_TYPE_DFLTCC, 4, "DFLTCC XPND"), - FEAT_INIT("dfltcc-f0", S390_FEAT_TYPE_DFLTCC, 192, "DFLTCC format 0 parameter-block"), +#define DEF_FEAT(_FEAT, _NAME, _TYPE, _BIT, _DESC) \ + [S390_FEAT_##_FEAT] = { \ + .name = _NAME, \ + .type = S390_FEAT_TYPE_##_TYPE, \ + .bit = _BIT, \ + .desc = _DESC, \ + }, +static const S390FeatDef s390_features[S390_FEAT_MAX] = { + #include "cpu_features_def.inc.h" }; +#undef DEF_FEAT const S390FeatDef *s390_feat_def(S390Feat feat) { diff --git a/target/s390x/cpu_features_def.h b/target/s390x/cpu_features_def.h index 292b17b35d..412d356feb 100644 --- a/target/s390x/cpu_features_def.h +++ b/target/s390x/cpu_features_def.h @@ -2,9 +2,10 @@ * CPU features/facilities for s390 * * Copyright IBM Corp. 2016, 2018 + * Copyright Red Hat, Inc. 2019 * * Author(s): Michael Mueller <mimu@linux.vnet.ibm.com> - * David Hildenbrand <dahi@linux.vnet.ibm.com> + * David Hildenbrand <david@redhat.com> * * This work is licensed under the terms of the GNU GPL, version 2 or (at * your option) any later version. See the COPYING file in the top-level @@ -14,354 +15,11 @@ #ifndef TARGET_S390X_CPU_FEATURES_DEF_H #define TARGET_S390X_CPU_FEATURES_DEF_H +#define DEF_FEAT(_FEAT, ...) S390_FEAT_##_FEAT, typedef enum { - /* Stfle */ - S390_FEAT_ESAN3 = 0, - S390_FEAT_ZARCH, - S390_FEAT_DAT_ENH, - S390_FEAT_IDTE_SEGMENT, - S390_FEAT_IDTE_REGION, - S390_FEAT_ASN_LX_REUSE, - S390_FEAT_STFLE, - S390_FEAT_EDAT, - S390_FEAT_SENSE_RUNNING_STATUS, - S390_FEAT_CONDITIONAL_SSKE, - S390_FEAT_CONFIGURATION_TOPOLOGY, - S390_FEAT_AP_QUERY_CONFIG_INFO, - S390_FEAT_IPTE_RANGE, - S390_FEAT_NONQ_KEY_SETTING, - S390_FEAT_AP_FACILITIES_TEST, - S390_FEAT_EXTENDED_TRANSLATION_2, - S390_FEAT_MSA, - S390_FEAT_LONG_DISPLACEMENT, - S390_FEAT_LONG_DISPLACEMENT_FAST, - S390_FEAT_HFP_MADDSUB, - S390_FEAT_EXTENDED_IMMEDIATE, - S390_FEAT_EXTENDED_TRANSLATION_3, - S390_FEAT_HFP_UNNORMALIZED_EXT, - S390_FEAT_ETF2_ENH, - S390_FEAT_STORE_CLOCK_FAST, - S390_FEAT_PARSING_ENH, - S390_FEAT_MOVE_WITH_OPTIONAL_SPEC, - S390_FEAT_TOD_CLOCK_STEERING, - S390_FEAT_ETF3_ENH, - S390_FEAT_EXTRACT_CPU_TIME, - S390_FEAT_COMPARE_AND_SWAP_AND_STORE, - S390_FEAT_COMPARE_AND_SWAP_AND_STORE_2, - S390_FEAT_GENERAL_INSTRUCTIONS_EXT, - S390_FEAT_EXECUTE_EXT, - S390_FEAT_ENHANCED_MONITOR, - S390_FEAT_FLOATING_POINT_EXT, - S390_FEAT_ORDER_PRESERVING_COMPRESSION, - S390_FEAT_SET_PROGRAM_PARAMETERS, - S390_FEAT_FLOATING_POINT_SUPPPORT_ENH, - S390_FEAT_DFP, - S390_FEAT_DFP_FAST, - S390_FEAT_PFPO, - S390_FEAT_STFLE_45, - S390_FEAT_CMPSC_ENH, - S390_FEAT_DFP_ZONED_CONVERSION, - S390_FEAT_STFLE_49, - S390_FEAT_CONSTRAINT_TRANSACTIONAL_EXE, - S390_FEAT_LOCAL_TLB_CLEARING, - S390_FEAT_INTERLOCKED_ACCESS_2, - S390_FEAT_STFLE_53, - S390_FEAT_ENTROPY_ENC_COMP, - S390_FEAT_MSA_EXT_5, - S390_FEAT_MISC_INSTRUCTION_EXT, - S390_FEAT_SEMAPHORE_ASSIST, - S390_FEAT_TIME_SLICE_INSTRUMENTATION, - S390_FEAT_MISC_INSTRUCTION_EXT3, - S390_FEAT_RUNTIME_INSTRUMENTATION, - S390_FEAT_ZPCI, - S390_FEAT_ADAPTER_EVENT_NOTIFICATION, - S390_FEAT_ADAPTER_INT_SUPPRESSION, - S390_FEAT_TRANSACTIONAL_EXE, - S390_FEAT_STORE_HYPERVISOR_INFO, - S390_FEAT_ACCESS_EXCEPTION_FS_INDICATION, - S390_FEAT_MSA_EXT_3, - S390_FEAT_MSA_EXT_4, - S390_FEAT_EDAT_2, - S390_FEAT_DFP_PACKED_CONVERSION, - S390_FEAT_PPA15, - S390_FEAT_BPB, - S390_FEAT_VECTOR, - S390_FEAT_INSTRUCTION_EXEC_PROT, - S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2, - S390_FEAT_GUARDED_STORAGE, - S390_FEAT_VECTOR_PACKED_DECIMAL, - S390_FEAT_VECTOR_ENH, - S390_FEAT_MULTIPLE_EPOCH, - S390_FEAT_TEST_PENDING_EXT_INTERRUPTION, - S390_FEAT_INSERT_REFERENCE_BITS_MULT, - S390_FEAT_MSA_EXT_8, - S390_FEAT_CMM_NT, - S390_FEAT_VECTOR_ENH2, - S390_FEAT_ESORT_BASE, - S390_FEAT_DEFLATE_BASE, - S390_FEAT_VECTOR_BCD_ENH, - S390_FEAT_MSA_EXT_9, - S390_FEAT_ETOKEN, - - /* Sclp Conf Char */ - S390_FEAT_SIE_GSLS, - S390_FEAT_ESOP, - S390_FEAT_HPMA2, - S390_FEAT_SIE_KSS, - - /* Sclp Conf Char Ext */ - S390_FEAT_SIE_64BSCAO, - S390_FEAT_SIE_CMMA, - S390_FEAT_SIE_PFMFI, - S390_FEAT_SIE_IBS, - - /* Sclp Cpu */ - S390_FEAT_SIE_F2, - S390_FEAT_SIE_SKEY, - S390_FEAT_SIE_GPERE, - S390_FEAT_SIE_SIIF, - S390_FEAT_SIE_SIGPIF, - S390_FEAT_SIE_IB, - S390_FEAT_SIE_CEI, - - /* Misc */ - S390_FEAT_DAT_ENH_2, - S390_FEAT_CMM, - S390_FEAT_AP, - - /* PLO */ - S390_FEAT_PLO_CL, - S390_FEAT_PLO_CLG, - S390_FEAT_PLO_CLGR, - S390_FEAT_PLO_CLX, - S390_FEAT_PLO_CS, - S390_FEAT_PLO_CSG, - S390_FEAT_PLO_CSGR, - S390_FEAT_PLO_CSX, - S390_FEAT_PLO_DCS, - S390_FEAT_PLO_DCSG, - S390_FEAT_PLO_DCSGR, - S390_FEAT_PLO_DCSX, - S390_FEAT_PLO_CSST, - S390_FEAT_PLO_CSSTG, - S390_FEAT_PLO_CSSTGR, - S390_FEAT_PLO_CSSTX, - S390_FEAT_PLO_CSDST, - S390_FEAT_PLO_CSDSTG, - S390_FEAT_PLO_CSDSTGR, - S390_FEAT_PLO_CSDSTX, - S390_FEAT_PLO_CSTST, - S390_FEAT_PLO_CSTSTG, - S390_FEAT_PLO_CSTSTGR, - S390_FEAT_PLO_CSTSTX, - - /* PTFF */ - S390_FEAT_PTFF_QTO, - S390_FEAT_PTFF_QSI, - S390_FEAT_PTFF_QPT, - S390_FEAT_PTFF_QUI, - S390_FEAT_PTFF_QTOU, - S390_FEAT_PTFF_QSIE, - S390_FEAT_PTFF_QTOUE, - S390_FEAT_PTFF_STO, - S390_FEAT_PTFF_STOU, - S390_FEAT_PTFF_STOE, - S390_FEAT_PTFF_STOUE, - - /* KMAC */ - S390_FEAT_KMAC_DEA, - S390_FEAT_KMAC_TDEA_128, - S390_FEAT_KMAC_TDEA_192, - S390_FEAT_KMAC_EDEA, - S390_FEAT_KMAC_ETDEA_128, - S390_FEAT_KMAC_ETDEA_192, - S390_FEAT_KMAC_AES_128, - S390_FEAT_KMAC_AES_192, - S390_FEAT_KMAC_AES_256, - S390_FEAT_KMAC_EAES_128, - S390_FEAT_KMAC_EAES_192, - S390_FEAT_KMAC_EAES_256, - - /* KMC */ - S390_FEAT_KMC_DEA, - S390_FEAT_KMC_TDEA_128, - S390_FEAT_KMC_TDEA_192, - S390_FEAT_KMC_EDEA, - S390_FEAT_KMC_ETDEA_128, - S390_FEAT_KMC_ETDEA_192, - S390_FEAT_KMC_AES_128, - S390_FEAT_KMC_AES_192, - S390_FEAT_KMC_AES_256, - S390_FEAT_KMC_EAES_128, - S390_FEAT_KMC_EAES_192, - S390_FEAT_KMC_EAES_256, - S390_FEAT_KMC_PRNG, - - /* KM */ - S390_FEAT_KM_DEA, - S390_FEAT_KM_TDEA_128, - S390_FEAT_KM_TDEA_192, - S390_FEAT_KM_EDEA, - S390_FEAT_KM_ETDEA_128, - S390_FEAT_KM_ETDEA_192, - S390_FEAT_KM_AES_128, - S390_FEAT_KM_AES_192, - S390_FEAT_KM_AES_256, - S390_FEAT_KM_EAES_128, - S390_FEAT_KM_EAES_192, - S390_FEAT_KM_EAES_256, - S390_FEAT_KM_XTS_AES_128, - S390_FEAT_KM_XTS_AES_256, - S390_FEAT_KM_XTS_EAES_128, - S390_FEAT_KM_XTS_EAES_256, - - /* KIMD */ - S390_FEAT_KIMD_SHA_1, - S390_FEAT_KIMD_SHA_256, - S390_FEAT_KIMD_SHA_512, - S390_FEAT_KIMD_SHA3_224, - S390_FEAT_KIMD_SHA3_256, - S390_FEAT_KIMD_SHA3_384, - S390_FEAT_KIMD_SHA3_512, - S390_FEAT_KIMD_SHAKE_128, - S390_FEAT_KIMD_SHAKE_256, - S390_FEAT_KIMD_GHASH, - - /* KLMD */ - S390_FEAT_KLMD_SHA_1, - S390_FEAT_KLMD_SHA_256, - S390_FEAT_KLMD_SHA_512, - S390_FEAT_KLMD_SHA3_224, - S390_FEAT_KLMD_SHA3_256, - S390_FEAT_KLMD_SHA3_384, - S390_FEAT_KLMD_SHA3_512, - S390_FEAT_KLMD_SHAKE_128, - S390_FEAT_KLMD_SHAKE_256, - - /* PCKMO */ - S390_FEAT_PCKMO_EDEA, - S390_FEAT_PCKMO_ETDEA_128, - S390_FEAT_PCKMO_ETDEA_256, - S390_FEAT_PCKMO_AES_128, - S390_FEAT_PCKMO_AES_192, - S390_FEAT_PCKMO_AES_256, - S390_FEAT_PCKMO_ECC_P256, - S390_FEAT_PCKMO_ECC_P384, - S390_FEAT_PCKMO_ECC_P521, - S390_FEAT_PCKMO_ECC_ED25519, - S390_FEAT_PCKMO_ECC_ED448, - - /* KMCTR */ - S390_FEAT_KMCTR_DEA, - S390_FEAT_KMCTR_TDEA_128, - S390_FEAT_KMCTR_TDEA_192, - S390_FEAT_KMCTR_EDEA, - S390_FEAT_KMCTR_ETDEA_128, - S390_FEAT_KMCTR_ETDEA_192, - S390_FEAT_KMCTR_AES_128, - S390_FEAT_KMCTR_AES_192, - S390_FEAT_KMCTR_AES_256, - S390_FEAT_KMCTR_EAES_128, - S390_FEAT_KMCTR_EAES_192, - S390_FEAT_KMCTR_EAES_256, - - /* KMF */ - S390_FEAT_KMF_DEA, - S390_FEAT_KMF_TDEA_128, - S390_FEAT_KMF_TDEA_192, - S390_FEAT_KMF_EDEA, - S390_FEAT_KMF_ETDEA_128, - S390_FEAT_KMF_ETDEA_192, - S390_FEAT_KMF_AES_128, - S390_FEAT_KMF_AES_192, - S390_FEAT_KMF_AES_256, - S390_FEAT_KMF_EAES_128, - S390_FEAT_KMF_EAES_192, - S390_FEAT_KMF_EAES_256, - - /* KMO */ - S390_FEAT_KMO_DEA, - S390_FEAT_KMO_TDEA_128, - S390_FEAT_KMO_TDEA_192, - S390_FEAT_KMO_EDEA, - S390_FEAT_KMO_ETDEA_128, - S390_FEAT_KMO_ETDEA_192, - S390_FEAT_KMO_AES_128, - S390_FEAT_KMO_AES_192, - S390_FEAT_KMO_AES_256, - S390_FEAT_KMO_EAES_128, - S390_FEAT_KMO_EAES_192, - S390_FEAT_KMO_EAES_256, - - /* PCC */ - S390_FEAT_PCC_CMAC_DEA, - S390_FEAT_PCC_CMAC_TDEA_128, - S390_FEAT_PCC_CMAC_TDEA_192, - S390_FEAT_PCC_CMAC_ETDEA_128, - S390_FEAT_PCC_CMAC_ETDEA_192, - S390_FEAT_PCC_CMAC_TDEA, - S390_FEAT_PCC_CMAC_AES_128, - S390_FEAT_PCC_CMAC_AES_192, - S390_FEAT_PCC_CMAC_AES_256, - S390_FEAT_PCC_CMAC_EAES_128, - S390_FEAT_PCC_CMAC_EAES_192, - S390_FEAT_PCC_CMAC_EAES_256, - S390_FEAT_PCC_XTS_AES_128, - S390_FEAT_PCC_XTS_AES_256, - S390_FEAT_PCC_XTS_EAES_128, - S390_FEAT_PCC_XTS_EAES_256, - S390_FEAT_PCC_SCALAR_MULT_P256, - S390_FEAT_PCC_SCALAR_MULT_P384, - S390_FEAT_PCC_SCALAR_MULT_P512, - S390_FEAT_PCC_SCALAR_MULT_ED25519, - S390_FEAT_PCC_SCALAR_MULT_ED448, - S390_FEAT_PCC_SCALAR_MULT_X25519, - S390_FEAT_PCC_SCALAR_MULT_X448, - - /* PPNO/PRNO */ - S390_FEAT_PPNO_SHA_512_DRNG, - S390_FEAT_PRNO_TRNG_QRTCR, - S390_FEAT_PRNO_TRNG, - - /* KMA */ - S390_FEAT_KMA_GCM_AES_128, - S390_FEAT_KMA_GCM_AES_192, - S390_FEAT_KMA_GCM_AES_256 , - S390_FEAT_KMA_GCM_EAES_128, - S390_FEAT_KMA_GCM_EAES_192, - S390_FEAT_KMA_GCM_EAES_256, - - /* KDSA */ - S390_FEAT_ECDSA_VERIFY_P256, - S390_FEAT_ECDSA_VERIFY_P384, - S390_FEAT_ECDSA_VERIFY_P512, - S390_FEAT_ECDSA_SIGN_P256, - S390_FEAT_ECDSA_SIGN_P384, - S390_FEAT_ECDSA_SIGN_P512, - S390_FEAT_EECDSA_SIGN_P256, - S390_FEAT_EECDSA_SIGN_P384, - S390_FEAT_EECDSA_SIGN_P512, - S390_FEAT_EDDSA_VERIFY_ED25519, - S390_FEAT_EDDSA_VERIFY_ED448, - S390_FEAT_EDDSA_SIGN_ED25519, - S390_FEAT_EDDSA_SIGN_ED448, - S390_FEAT_EEDDSA_SIGN_ED25519, - S390_FEAT_EEDDSA_SIGN_ED448, - - /* SORTL */ - S390_FEAT_SORTL_SFLR, - S390_FEAT_SORTL_SVLR, - S390_FEAT_SORTL_32, - S390_FEAT_SORTL_128, - S390_FEAT_SORTL_F0, - - /* DEFLATE */ - S390_FEAT_DEFLATE_GHDT, - S390_FEAT_DEFLATE_CMPR, - S390_FEAT_DEFLATE_XPND, - S390_FEAT_DEFLATE_F0, - + #include "cpu_features_def.inc.h" S390_FEAT_MAX, } S390Feat; +#undef DEF_FEAT #endif /* TARGET_S390X_CPU_FEATURES_DEF_H */ diff --git a/target/s390x/cpu_features_def.inc.h b/target/s390x/cpu_features_def.inc.h new file mode 100644 index 0000000000..c20c780f2e --- /dev/null +++ b/target/s390x/cpu_features_def.inc.h @@ -0,0 +1,369 @@ +/* + * RAW s390x CPU feature definitions: + * + * DEF_FEAT(_FEAT, _NAME, _TYPE, _BIT, _DESC): + * - _FEAT: Feature (enum) name used internally (S390_FEAT_##_FEAT) + * - _NAME: Feature name exposed to the user. + * - _TYPE: Feature type (S390_FEAT_TYPE_##_TYPE). + * - _BIT: Feature bit number within feature type block (unused for MISC). + * - _DESC: Feature description, exposed to the user. + * + * Copyright IBM Corp. 2016, 2018 + * Copyright Red Hat, Inc. 2019 + * + * Author(s): Michael Mueller <mimu@linux.vnet.ibm.com> + * David Hildenbrand <david@redhat.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +/* Features exposed via the STFL(E) instruction. */ +DEF_FEAT(ESAN3, "esan3", STFL, 0, "Instructions marked as n3") +DEF_FEAT(ZARCH, "zarch", STFL, 1, "z/Architecture architectural mode") +DEF_FEAT(DAT_ENH, "dateh", STFL, 3, "DAT-enhancement facility") +DEF_FEAT(IDTE_SEGMENT, "idtes", STFL, 4, "IDTE selective TLB segment-table clearing") +DEF_FEAT(IDTE_REGION, "idter", STFL, 5, "IDTE selective TLB region-table clearing") +DEF_FEAT(ASN_LX_REUSE, "asnlxr", STFL, 6, "ASN-and-LX reuse facility") +DEF_FEAT(STFLE, "stfle", STFL, 7, "Store-facility-list-extended facility") +DEF_FEAT(EDAT, "edat", STFL, 8, "Enhanced-DAT facility") +DEF_FEAT(SENSE_RUNNING_STATUS, "srs", STFL, 9, "Sense-running-status facility") +DEF_FEAT(CONDITIONAL_SSKE, "csske", STFL, 10, "Conditional-SSKE facility") +DEF_FEAT(CONFIGURATION_TOPOLOGY, "ctop", STFL, 11, "Configuration-topology facility") +DEF_FEAT(AP_QUERY_CONFIG_INFO, "apqci", STFL, 12, "Query AP Configuration Information facility") +DEF_FEAT(IPTE_RANGE, "ipter", STFL, 13, "IPTE-range facility") +DEF_FEAT(NONQ_KEY_SETTING, "nonqks", STFL, 14, "Nonquiescing key-setting facility") +DEF_FEAT(AP_FACILITIES_TEST, "apft", STFL, 15, "AP Facilities Test facility") +DEF_FEAT(EXTENDED_TRANSLATION_2, "etf2", STFL, 16, "Extended-translation facility 2") +DEF_FEAT(MSA, "msa-base", STFL, 17, "Message-security-assist facility (excluding subfunctions)") +DEF_FEAT(LONG_DISPLACEMENT, "ldisp", STFL, 18, "Long-displacement facility") +DEF_FEAT(LONG_DISPLACEMENT_FAST, "ldisphp", STFL, 19, "Long-displacement facility has high performance") +DEF_FEAT(HFP_MADDSUB, "hfpm", STFL, 20, "HFP-multiply-add/subtract facility") +DEF_FEAT(EXTENDED_IMMEDIATE, "eimm", STFL, 21, "Extended-immediate facility") +DEF_FEAT(EXTENDED_TRANSLATION_3, "etf3", STFL, 22, "Extended-translation facility 3") +DEF_FEAT(HFP_UNNORMALIZED_EXT, "hfpue", STFL, 23, "HFP-unnormalized-extension facility") +DEF_FEAT(ETF2_ENH, "etf2eh", STFL, 24, "ETF2-enhancement facility") +DEF_FEAT(STORE_CLOCK_FAST, "stckf", STFL, 25, "Store-clock-fast facility") +DEF_FEAT(PARSING_ENH, "parseh", STFL, 26, "Parsing-enhancement facility") +DEF_FEAT(MOVE_WITH_OPTIONAL_SPEC, "mvcos", STFL, 27, "Move-with-optional-specification facility") +DEF_FEAT(TOD_CLOCK_STEERING, "tods-base", STFL, 28, "TOD-clock-steering facility (excluding subfunctions)") +DEF_FEAT(ETF3_ENH, "etf3eh", STFL, 30, "ETF3-enhancement facility") +DEF_FEAT(EXTRACT_CPU_TIME, "ectg", STFL, 31, "Extract-CPU-time facility") +DEF_FEAT(COMPARE_AND_SWAP_AND_STORE, "csst", STFL, 32, "Compare-and-swap-and-store facility") +DEF_FEAT(COMPARE_AND_SWAP_AND_STORE_2, "csst2", STFL, 33, "Compare-and-swap-and-store facility 2") +DEF_FEAT(GENERAL_INSTRUCTIONS_EXT, "ginste", STFL, 34, "General-instructions-extension facility") +DEF_FEAT(EXECUTE_EXT, "exrl", STFL, 35, "Execute-extensions facility") +DEF_FEAT(ENHANCED_MONITOR, "emon", STFL, 36, "Enhanced-monitor facility") +DEF_FEAT(FLOATING_POINT_EXT, "fpe", STFL, 37, "Floating-point extension facility") +DEF_FEAT(ORDER_PRESERVING_COMPRESSION, "opc", STFL, 38, "Order Preserving Compression facility") +DEF_FEAT(SET_PROGRAM_PARAMETERS, "sprogp", STFL, 40, "Set-program-parameters facility") +DEF_FEAT(FLOATING_POINT_SUPPPORT_ENH, "fpseh", STFL, 41, "Floating-point-support-enhancement facilities") +DEF_FEAT(DFP, "dfp", STFL, 42, "DFP (decimal-floating-point) facility") +DEF_FEAT(DFP_FAST, "dfphp", STFL, 43, "DFP (decimal-floating-point) facility has high performance") +DEF_FEAT(PFPO, "pfpo", STFL, 44, "PFPO instruction") +DEF_FEAT(STFLE_45, "stfle45", STFL, 45, "Various facilities introduced with z196") +DEF_FEAT(CMPSC_ENH, "cmpsceh", STFL, 47, "CMPSC-enhancement facility") +DEF_FEAT(DFP_ZONED_CONVERSION, "dfpzc", STFL, 48, "Decimal-floating-point zoned-conversion facility") +DEF_FEAT(STFLE_49, "stfle49", STFL, 49, "Various facilities introduced with zEC12") +DEF_FEAT(CONSTRAINT_TRANSACTIONAL_EXE, "cte", STFL, 50, "Constrained transactional-execution facility") +DEF_FEAT(LOCAL_TLB_CLEARING, "ltlbc", STFL, 51, "Local-TLB-clearing facility") +DEF_FEAT(INTERLOCKED_ACCESS_2, "iacc2", STFL, 52, "Interlocked-access facility 2") +DEF_FEAT(STFLE_53, "stfle53", STFL, 53, "Various facilities introduced with z13") +DEF_FEAT(ENTROPY_ENC_COMP, "eec", STFL, 54, "Entropy encoding compression facility") +DEF_FEAT(MSA_EXT_5, "msa5-base", STFL, 57, "Message-security-assist-extension-5 facility (excluding subfunctions)") +DEF_FEAT(MISC_INSTRUCTION_EXT, "minste2", STFL, 58, "Miscellaneous-instruction-extensions facility 2") +DEF_FEAT(SEMAPHORE_ASSIST, "sema", STFL, 59, "Semaphore-assist facility") +DEF_FEAT(TIME_SLICE_INSTRUMENTATION, "tsi", STFL, 60, "Time-slice Instrumentation facility") +DEF_FEAT(MISC_INSTRUCTION_EXT3, "minste3", STFL, 61, "Miscellaneous-Instruction-Extensions Facility 3") +DEF_FEAT(RUNTIME_INSTRUMENTATION, "ri", STFL, 64, "CPU runtime-instrumentation facility") +DEF_FEAT(ZPCI, "zpci", STFL, 69, "z/PCI facility") +DEF_FEAT(ADAPTER_EVENT_NOTIFICATION, "aen", STFL, 71, "General-purpose-adapter-event-notification facility") +DEF_FEAT(ADAPTER_INT_SUPPRESSION, "ais", STFL, 72, "General-purpose-adapter-interruption-suppression facility") +DEF_FEAT(TRANSACTIONAL_EXE, "te", STFL, 73, "Transactional-execution facility") +DEF_FEAT(STORE_HYPERVISOR_INFO, "sthyi", STFL, 74, "Store-hypervisor-information facility") +DEF_FEAT(ACCESS_EXCEPTION_FS_INDICATION, "aefsi", STFL, 75, "Access-exception-fetch/store-indication facility") +DEF_FEAT(MSA_EXT_3, "msa3-base", STFL, 76, "Message-security-assist-extension-3 facility (excluding subfunctions)") +DEF_FEAT(MSA_EXT_4, "msa4-base", STFL, 77, "Message-security-assist-extension-4 facility (excluding subfunctions)") +DEF_FEAT(EDAT_2, "edat2", STFL, 78, "Enhanced-DAT facility 2") +DEF_FEAT(DFP_PACKED_CONVERSION, "dfppc", STFL, 80, "Decimal-floating-point packed-conversion facility") +DEF_FEAT(PPA15, "ppa15", STFL, 81, "PPA15 is installed") +DEF_FEAT(BPB, "bpb", STFL, 82, "Branch prediction blocking") +DEF_FEAT(VECTOR, "vx", STFL, 129, "Vector facility") +DEF_FEAT(INSTRUCTION_EXEC_PROT, "iep", STFL, 130, "Instruction-execution-protection facility") +DEF_FEAT(SIDE_EFFECT_ACCESS_ESOP2, "sea_esop2", STFL, 131, "Side-effect-access facility and Enhanced-suppression-on-protection facility 2") +DEF_FEAT(GUARDED_STORAGE, "gs", STFL, 133, "Guarded-storage facility") +DEF_FEAT(VECTOR_PACKED_DECIMAL, "vxpd", STFL, 134, "Vector packed decimal facility") +DEF_FEAT(VECTOR_ENH, "vxeh", STFL, 135, "Vector enhancements facility") +DEF_FEAT(MULTIPLE_EPOCH, "mepoch", STFL, 139, "Multiple-epoch facility") +DEF_FEAT(TEST_PENDING_EXT_INTERRUPTION, "tpei", STFL, 144, "Test-pending-external-interruption facility") +DEF_FEAT(INSERT_REFERENCE_BITS_MULT, "irbm", STFL, 145, "Insert-reference-bits-multiple facility") +DEF_FEAT(MSA_EXT_8, "msa8-base", STFL, 146, "Message-security-assist-extension-8 facility (excluding subfunctions)") +DEF_FEAT(CMM_NT, "cmmnt", STFL, 147, "CMM: ESSA-enhancement (no translate) facility") +DEF_FEAT(VECTOR_ENH2, "vxeh2", STFL, 148, "Vector Enhancements facility 2") +DEF_FEAT(ESORT_BASE, "esort-base", STFL, 150, "Enhanced-sort facility (excluding subfunctions)") +DEF_FEAT(DEFLATE_BASE, "deflate-base", STFL, 151, "Deflate-conversion facility (excluding subfunctions)") +DEF_FEAT(VECTOR_BCD_ENH, "vxbeh", STFL, 152, "Vector BCD enhancements facility 1") +DEF_FEAT(MSA_EXT_9, "msa9-base", STFL, 155, "Message-security-assist-extension-9 facility (excluding subfunctions)") +DEF_FEAT(ETOKEN, "etoken", STFL, 156, "Etoken facility") + +/* Features exposed via SCLP SCCB Byte 80 - 98 (bit numbers relative to byte-80) */ +DEF_FEAT(SIE_GSLS, "gsls", SCLP_CONF_CHAR, 40, "SIE: Guest-storage-limit-suppression facility") +DEF_FEAT(ESOP, "esop", SCLP_CONF_CHAR, 46, "Enhanced-suppression-on-protection facility") +DEF_FEAT(HPMA2, "hpma2", SCLP_CONF_CHAR, 90, "Host page management assist 2 Facility") /* 91-2 */ +DEF_FEAT(SIE_KSS, "kss", SCLP_CONF_CHAR, 151, "SIE: Keyless-subset facility") /* 98-7 */ + +/* Features exposed via SCLP SCCB Byte 116 - 119 (bit numbers relative to byte-116) */ +DEF_FEAT(SIE_64BSCAO, "64bscao", SCLP_CONF_CHAR_EXT, 0, "SIE: 64-bit-SCAO facility") +DEF_FEAT(SIE_CMMA, "cmma", SCLP_CONF_CHAR_EXT, 1, "SIE: Collaborative-memory-management assist") +DEF_FEAT(SIE_PFMFI, "pfmfi", SCLP_CONF_CHAR_EXT, 9, "SIE: PFMF interpretation facility") +DEF_FEAT(SIE_IBS, "ibs", SCLP_CONF_CHAR_EXT, 10, "SIE: Interlock-and-broadcast-suppression facility") + +/* Features exposed via SCLP CPU info. */ +DEF_FEAT(SIE_F2, "sief2", SCLP_CPU, 4, "SIE: interception format 2 (Virtual SIE)") +DEF_FEAT(SIE_SKEY, "skey", SCLP_CPU, 5, "SIE: Storage-key facility") +DEF_FEAT(SIE_GPERE, "gpereh", SCLP_CPU, 10, "SIE: Guest-PER enhancement facility") +DEF_FEAT(SIE_SIIF, "siif", SCLP_CPU, 11, "SIE: Shared IPTE-interlock facility") +DEF_FEAT(SIE_SIGPIF, "sigpif", SCLP_CPU, 12, "SIE: SIGP interpretation facility") +DEF_FEAT(SIE_IB, "ib", SCLP_CPU, 42, "SIE: Intervention bypass facility") +DEF_FEAT(SIE_CEI, "cei", SCLP_CPU, 43, "SIE: Conditional-external-interception facility") + +/* + * Features exposed via no feature bit (but e.g., instruction sensing) + * -> the feature bit number is irrelavant + */ +DEF_FEAT(DAT_ENH_2, "dateh2", MISC, 0, "DAT-enhancement facility 2") +DEF_FEAT(CMM, "cmm", MISC, 0, "Collaborative-memory-management facility") +DEF_FEAT(AP, "ap", MISC, 0, "AP instructions installed") + +/* Features exposed via the PLO instruction. */ +DEF_FEAT(PLO_CL, "plo-cl", PLO, 0, "PLO Compare and load (32 bit in general registers)") +DEF_FEAT(PLO_CLG, "plo-clg", PLO, 1, "PLO Compare and load (64 bit in parameter list)") +DEF_FEAT(PLO_CLGR, "plo-clgr", PLO, 2, "PLO Compare and load (32 bit in general registers)") +DEF_FEAT(PLO_CLX, "plo-clx", PLO, 3, "PLO Compare and load (128 bit in parameter list)") +DEF_FEAT(PLO_CS, "plo-cs", PLO, 4, "PLO Compare and swap (32 bit in general registers)") +DEF_FEAT(PLO_CSG, "plo-csg", PLO, 5, "PLO Compare and swap (64 bit in parameter list)") +DEF_FEAT(PLO_CSGR, "plo-csgr", PLO, 6, "PLO Compare and swap (32 bit in general registers)") +DEF_FEAT(PLO_CSX, "plo-csx", PLO, 7, "PLO Compare and swap (128 bit in parameter list)") +DEF_FEAT(PLO_DCS, "plo-dcs", PLO, 8, "PLO Double compare and swap (32 bit in general registers)") +DEF_FEAT(PLO_DCSG, "plo-dcsg", PLO, 9, "PLO Double compare and swap (64 bit in parameter list)") +DEF_FEAT(PLO_DCSGR, "plo-dcsgr", PLO, 10, "PLO Double compare and swap (32 bit in general registers)") +DEF_FEAT(PLO_DCSX, "plo-dcsx", PLO, 11, "PLO Double compare and swap (128 bit in parameter list)") +DEF_FEAT(PLO_CSST, "plo-csst", PLO, 12, "PLO Compare and swap and store (32 bit in general registers)") +DEF_FEAT(PLO_CSSTG, "plo-csstg", PLO, 13, "PLO Compare and swap and store (64 bit in parameter list)") +DEF_FEAT(PLO_CSSTGR, "plo-csstgr", PLO, 14, "PLO Compare and swap and store (32 bit in general registers)") +DEF_FEAT(PLO_CSSTX, "plo-csstx", PLO, 15, "PLO Compare and swap and store (128 bit in parameter list)") +DEF_FEAT(PLO_CSDST, "plo-csdst", PLO, 16, "PLO Compare and swap and double store (32 bit in general registers)") +DEF_FEAT(PLO_CSDSTG, "plo-csdstg", PLO, 17, "PLO Compare and swap and double store (64 bit in parameter list)") +DEF_FEAT(PLO_CSDSTGR, "plo-csdstgr", PLO, 18, "PLO Compare and swap and double store (32 bit in general registers)") +DEF_FEAT(PLO_CSDSTX, "plo-csdstx", PLO, 19, "PLO Compare and swap and double store (128 bit in parameter list)") +DEF_FEAT(PLO_CSTST, "plo-cstst", PLO, 20, "PLO Compare and swap and triple store (32 bit in general registers)") +DEF_FEAT(PLO_CSTSTG, "plo-cststg", PLO, 21, "PLO Compare and swap and triple store (64 bit in parameter list)") +DEF_FEAT(PLO_CSTSTGR, "plo-cststgr", PLO, 22, "PLO Compare and swap and triple store (32 bit in general registers)") +DEF_FEAT(PLO_CSTSTX, "plo-cststx", PLO, 23, "PLO Compare and swap and triple store (128 bit in parameter list)") + +/* Features exposed via the PTFF instruction. */ +DEF_FEAT(PTFF_QTO, "ptff-qto", PTFF, 1, "PTFF Query TOD Offset") +DEF_FEAT(PTFF_QSI, "ptff-qsi", PTFF, 2, "PTFF Query Steering Information") +DEF_FEAT(PTFF_QPT, "ptff-qpc", PTFF, 3, "PTFF Query Physical Clock") +DEF_FEAT(PTFF_QUI, "ptff-qui", PTFF, 4, "PTFF Query UTC Information") +DEF_FEAT(PTFF_QTOU, "ptff-qtou", PTFF, 5, "PTFF Query TOD Offset User") +DEF_FEAT(PTFF_QSIE, "ptff-qsie", PTFF, 10, "PTFF Query Steering Information Extended") +DEF_FEAT(PTFF_QTOUE, "ptff-qtoue", PTFF, 13, "PTFF Query TOD Offset User Extended") +DEF_FEAT(PTFF_STO, "ptff-sto", PTFF, 65, "PTFF Set TOD Offset") +DEF_FEAT(PTFF_STOU, "ptff-stou", PTFF, 69, "PTFF Set TOD Offset User") +DEF_FEAT(PTFF_STOE, "ptff-stoe", PTFF, 73, "PTFF Set TOD Offset Extended") +DEF_FEAT(PTFF_STOUE, "ptff-stoue", PTFF, 77, "PTFF Set TOD Offset User Extended") + +/* Features exposed via the KMAC instruction. */ +DEF_FEAT(KMAC_DEA, "kmac-dea", KMAC, 1, "KMAC DEA") +DEF_FEAT(KMAC_TDEA_128, "kmac-tdea-128", KMAC, 2, "KMAC TDEA-128") +DEF_FEAT(KMAC_TDEA_192, "kmac-tdea-192", KMAC, 3, "KMAC TDEA-192") +DEF_FEAT(KMAC_EDEA, "kmac-edea", KMAC, 9, "KMAC Encrypted-DEA") +DEF_FEAT(KMAC_ETDEA_128, "kmac-etdea-128", KMAC, 10, "KMAC Encrypted-TDEA-128") +DEF_FEAT(KMAC_ETDEA_192, "kmac-etdea-192", KMAC, 11, "KMAC Encrypted-TDEA-192") +DEF_FEAT(KMAC_AES_128, "kmac-aes-128", KMAC, 18, "KMAC AES-128") +DEF_FEAT(KMAC_AES_192, "kmac-aes-192", KMAC, 19, "KMAC AES-192") +DEF_FEAT(KMAC_AES_256, "kmac-aes-256", KMAC, 20, "KMAC AES-256") +DEF_FEAT(KMAC_EAES_128, "kmac-eaes-128", KMAC, 26, "KMAC Encrypted-AES-128") +DEF_FEAT(KMAC_EAES_192, "kmac-eaes-192", KMAC, 27, "KMAC Encrypted-AES-192") +DEF_FEAT(KMAC_EAES_256, "kmac-eaes-256", KMAC, 28, "KMAC Encrypted-AES-256") + +/* Features exposed via the KMC instruction. */ +DEF_FEAT(KMC_DEA, "kmc-dea", KMC, 1, "KMC DEA") +DEF_FEAT(KMC_TDEA_128, "kmc-tdea-128", KMC, 2, "KMC TDEA-128") +DEF_FEAT(KMC_TDEA_192, "kmc-tdea-192", KMC, 3, "KMC TDEA-192") +DEF_FEAT(KMC_EDEA, "kmc-edea", KMC, 9, "KMC Encrypted-DEA") +DEF_FEAT(KMC_ETDEA_128, "kmc-etdea-128", KMC, 10, "KMC Encrypted-TDEA-128") +DEF_FEAT(KMC_ETDEA_192, "kmc-etdea-192", KMC, 11, "KMC Encrypted-TDEA-192") +DEF_FEAT(KMC_AES_128, "kmc-aes-128", KMC, 18, "KMC AES-128") +DEF_FEAT(KMC_AES_192, "kmc-aes-192", KMC, 19, "KMC AES-192") +DEF_FEAT(KMC_AES_256, "kmc-aes-256", KMC, 20, "KMC AES-256") +DEF_FEAT(KMC_EAES_128, "kmc-eaes-128", KMC, 26, "KMC Encrypted-AES-128") +DEF_FEAT(KMC_EAES_192, "kmc-eaes-192", KMC, 27, "KMC Encrypted-AES-192") +DEF_FEAT(KMC_EAES_256, "kmc-eaes-256", KMC, 28, "KMC Encrypted-AES-256") +DEF_FEAT(KMC_PRNG, "kmc-prng", KMC, 67, "KMC PRNG") + +/* Features exposed via the KM instruction. */ +DEF_FEAT(KM_DEA, "km-dea", KM, 1, "KM DEA") +DEF_FEAT(KM_TDEA_128, "km-tdea-128", KM, 2, "KM TDEA-128") +DEF_FEAT(KM_TDEA_192, "km-tdea-192", KM, 3, "KM TDEA-192") +DEF_FEAT(KM_EDEA, "km-edea", KM, 9, "KM Encrypted-DEA") +DEF_FEAT(KM_ETDEA_128, "km-etdea-128", KM, 10, "KM Encrypted-TDEA-128") +DEF_FEAT(KM_ETDEA_192, "km-etdea-192", KM, 11, "KM Encrypted-TDEA-192") +DEF_FEAT(KM_AES_128, "km-aes-128", KM, 18, "KM AES-128") +DEF_FEAT(KM_AES_192, "km-aes-192", KM, 19, "KM AES-192") +DEF_FEAT(KM_AES_256, "km-aes-256", KM, 20, "KM AES-256") +DEF_FEAT(KM_EAES_128, "km-eaes-128", KM, 26, "KM Encrypted-AES-128") +DEF_FEAT(KM_EAES_192, "km-eaes-192", KM, 27, "KM Encrypted-AES-192") +DEF_FEAT(KM_EAES_256, "km-eaes-256", KM, 28, "KM Encrypted-AES-256") +DEF_FEAT(KM_XTS_AES_128, "km-xts-aes-128", KM, 50, "KM XTS-AES-128") +DEF_FEAT(KM_XTS_AES_256, "km-xts-aes-256", KM, 52, "KM XTS-AES-256") +DEF_FEAT(KM_XTS_EAES_128, "km-xts-eaes-128", KM, 58, "KM XTS-Encrypted-AES-128") +DEF_FEAT(KM_XTS_EAES_256, "km-xts-eaes-256", KM, 60, "KM XTS-Encrypted-AES-256") + +/* Features exposed via the KIMD instruction. */ +DEF_FEAT(KIMD_SHA_1, "kimd-sha-1", KIMD, 1, "KIMD SHA-1") +DEF_FEAT(KIMD_SHA_256, "kimd-sha-256", KIMD, 2, "KIMD SHA-256") +DEF_FEAT(KIMD_SHA_512, "kimd-sha-512", KIMD, 3, "KIMD SHA-512") +DEF_FEAT(KIMD_SHA3_224, "kimd-sha3-224", KIMD, 32, "KIMD SHA3-224") +DEF_FEAT(KIMD_SHA3_256, "kimd-sha3-256", KIMD, 33, "KIMD SHA3-256") +DEF_FEAT(KIMD_SHA3_384, "kimd-sha3-384", KIMD, 34, "KIMD SHA3-384") +DEF_FEAT(KIMD_SHA3_512, "kimd-sha3-512", KIMD, 35, "KIMD SHA3-512") +DEF_FEAT(KIMD_SHAKE_128, "kimd-shake-128", KIMD, 36, "KIMD SHAKE-128") +DEF_FEAT(KIMD_SHAKE_256, "kimd-shake-256", KIMD, 37, "KIMD SHAKE-256") +DEF_FEAT(KIMD_GHASH, "kimd-ghash", KIMD, 65, "KIMD GHASH") + +/* Features exposed via the KLMD instruction. */ +DEF_FEAT(KLMD_SHA_1, "klmd-sha-1", KLMD, 1, "KLMD SHA-1") +DEF_FEAT(KLMD_SHA_256, "klmd-sha-256", KLMD, 2, "KLMD SHA-256") +DEF_FEAT(KLMD_SHA_512, "klmd-sha-512", KLMD, 3, "KLMD SHA-512") +DEF_FEAT(KLMD_SHA3_224, "klmd-sha3-224", KLMD, 32, "KLMD SHA3-224") +DEF_FEAT(KLMD_SHA3_256, "klmd-sha3-256", KLMD, 33, "KLMD SHA3-256") +DEF_FEAT(KLMD_SHA3_384, "klmd-sha3-384", KLMD, 34, "KLMD SHA3-384") +DEF_FEAT(KLMD_SHA3_512, "klmd-sha3-512", KLMD, 35, "KLMD SHA3-512") +DEF_FEAT(KLMD_SHAKE_128, "klmd-shake-128", KLMD, 36, "KLMD SHAKE-128") +DEF_FEAT(KLMD_SHAKE_256, "klmd-shake-256", KLMD, 37, "KLMD SHAKE-256") + +/* Features exposed via the PCKMO instruction. */ +DEF_FEAT(PCKMO_EDEA, "pckmo-edea", PCKMO, 1, "PCKMO Encrypted-DEA-Key") +DEF_FEAT(PCKMO_ETDEA_128, "pckmo-etdea-128", PCKMO, 2, "PCKMO Encrypted-TDEA-128-Key") +DEF_FEAT(PCKMO_ETDEA_256, "pckmo-etdea-192", PCKMO, 3, "PCKMO Encrypted-TDEA-192-Key") +DEF_FEAT(PCKMO_AES_128, "pckmo-aes-128", PCKMO, 18, "PCKMO Encrypted-AES-128-Key") +DEF_FEAT(PCKMO_AES_192, "pckmo-aes-192", PCKMO, 19, "PCKMO Encrypted-AES-192-Key") +DEF_FEAT(PCKMO_AES_256, "pckmo-aes-256", PCKMO, 20, "PCKMO Encrypted-AES-256-Key") +DEF_FEAT(PCKMO_ECC_P256, "pckmo-ecc-p256", PCKMO, 32, "PCKMO Encrypt-ECC-P256-Key") +DEF_FEAT(PCKMO_ECC_P384, "pckmo-ecc-p384", PCKMO, 33, "PCKMO Encrypt-ECC-P384-Key") +DEF_FEAT(PCKMO_ECC_P521, "pckmo-ecc-p521", PCKMO, 34, "PCKMO Encrypt-ECC-P521-Key") +DEF_FEAT(PCKMO_ECC_ED25519, "pckmo-ecc-ed25519", PCKMO, 40 , "PCKMO Encrypt-ECC-Ed25519-Key") +DEF_FEAT(PCKMO_ECC_ED448, "pckmo-ecc-ed448", PCKMO, 41 , "PCKMO Encrypt-ECC-Ed448-Key") + +/* Features exposed via the KMCTR instruction. */ +DEF_FEAT(KMCTR_DEA, "kmctr-dea", KMCTR, 1, "KMCTR DEA") +DEF_FEAT(KMCTR_TDEA_128, "kmctr-tdea-128", KMCTR, 2, "KMCTR TDEA-128") +DEF_FEAT(KMCTR_TDEA_192, "kmctr-tdea-192", KMCTR, 3, "KMCTR TDEA-192") +DEF_FEAT(KMCTR_EDEA, "kmctr-edea", KMCTR, 9, "KMCTR Encrypted-DEA") +DEF_FEAT(KMCTR_ETDEA_128, "kmctr-etdea-128", KMCTR, 10, "KMCTR Encrypted-TDEA-128") +DEF_FEAT(KMCTR_ETDEA_192, "kmctr-etdea-192", KMCTR, 11, "KMCTR Encrypted-TDEA-192") +DEF_FEAT(KMCTR_AES_128, "kmctr-aes-128", KMCTR, 18, "KMCTR AES-128") +DEF_FEAT(KMCTR_AES_192, "kmctr-aes-192", KMCTR, 19, "KMCTR AES-192") +DEF_FEAT(KMCTR_AES_256, "kmctr-aes-256", KMCTR, 20, "KMCTR AES-256") +DEF_FEAT(KMCTR_EAES_128, "kmctr-eaes-128", KMCTR, 26, "KMCTR Encrypted-AES-128") +DEF_FEAT(KMCTR_EAES_192, "kmctr-eaes-192", KMCTR, 27, "KMCTR Encrypted-AES-192") +DEF_FEAT(KMCTR_EAES_256, "kmctr-eaes-256", KMCTR, 28, "KMCTR Encrypted-AES-256") + +/* Features exposed via the KMF instruction. */ +DEF_FEAT(KMF_DEA, "kmf-dea", KMF, 1, "KMF DEA") +DEF_FEAT(KMF_TDEA_128, "kmf-tdea-128", KMF, 2, "KMF TDEA-128") +DEF_FEAT(KMF_TDEA_192, "kmf-tdea-192", KMF, 3, "KMF TDEA-192") +DEF_FEAT(KMF_EDEA, "kmf-edea", KMF, 9, "KMF Encrypted-DEA") +DEF_FEAT(KMF_ETDEA_128, "kmf-etdea-128", KMF, 10, "KMF Encrypted-TDEA-128") +DEF_FEAT(KMF_ETDEA_192, "kmf-etdea-192", KMF, 11, "KMF Encrypted-TDEA-192") +DEF_FEAT(KMF_AES_128, "kmf-aes-128", KMF, 18, "KMF AES-128") +DEF_FEAT(KMF_AES_192, "kmf-aes-192", KMF, 19, "KMF AES-192") +DEF_FEAT(KMF_AES_256, "kmf-aes-256", KMF, 20, "KMF AES-256") +DEF_FEAT(KMF_EAES_128, "kmf-eaes-128", KMF, 26, "KMF Encrypted-AES-128") +DEF_FEAT(KMF_EAES_192, "kmf-eaes-192", KMF, 27, "KMF Encrypted-AES-192") +DEF_FEAT(KMF_EAES_256, "kmf-eaes-256", KMF, 28, "KMF Encrypted-AES-256") + +/* Features exposed via the KMO instruction. */ +DEF_FEAT(KMO_DEA, "kmo-dea", KMO, 1, "KMO DEA") +DEF_FEAT(KMO_TDEA_128, "kmo-tdea-128", KMO, 2, "KMO TDEA-128") +DEF_FEAT(KMO_TDEA_192, "kmo-tdea-192", KMO, 3, "KMO TDEA-192") +DEF_FEAT(KMO_EDEA, "kmo-edea", KMO, 9, "KMO Encrypted-DEA") +DEF_FEAT(KMO_ETDEA_128, "kmo-etdea-128", KMO, 10, "KMO Encrypted-TDEA-128") +DEF_FEAT(KMO_ETDEA_192, "kmo-etdea-192", KMO, 11, "KMO Encrypted-TDEA-192") +DEF_FEAT(KMO_AES_128, "kmo-aes-128", KMO, 18, "KMO AES-128") +DEF_FEAT(KMO_AES_192, "kmo-aes-192", KMO, 19, "KMO AES-192") +DEF_FEAT(KMO_AES_256, "kmo-aes-256", KMO, 20, "KMO AES-256") +DEF_FEAT(KMO_EAES_128, "kmo-eaes-128", KMO, 26, "KMO Encrypted-AES-128") +DEF_FEAT(KMO_EAES_192, "kmo-eaes-192", KMO, 27, "KMO Encrypted-AES-192") +DEF_FEAT(KMO_EAES_256, "kmo-eaes-256", KMO, 28, "KMO Encrypted-AES-256") + +/* Features exposed via the PCC instruction. */ +DEF_FEAT(PCC_CMAC_DEA, "pcc-cmac-dea", PCC, 1, "PCC Compute-Last-Block-CMAC-Using-DEA") +DEF_FEAT(PCC_CMAC_TDEA_128, "pcc-cmac-tdea-128", PCC, 2, "PCC Compute-Last-Block-CMAC-Using-TDEA-128") +DEF_FEAT(PCC_CMAC_TDEA_192, "pcc-cmac-tdea-192", PCC, 3, "PCC Compute-Last-Block-CMAC-Using-TDEA-192") +DEF_FEAT(PCC_CMAC_ETDEA_128, "pcc-cmac-edea", PCC, 9, "PCC Compute-Last-Block-CMAC-Using-Encrypted-DEA") +DEF_FEAT(PCC_CMAC_ETDEA_192, "pcc-cmac-etdea-128", PCC, 10, "PCC Compute-Last-Block-CMAC-Using-Encrypted-TDEA-128") +DEF_FEAT(PCC_CMAC_TDEA, "pcc-cmac-etdea-192", PCC, 11, "PCC Compute-Last-Block-CMAC-Using-EncryptedTDEA-192") +DEF_FEAT(PCC_CMAC_AES_128, "pcc-cmac-aes-128", PCC, 18, "PCC Compute-Last-Block-CMAC-Using-AES-128") +DEF_FEAT(PCC_CMAC_AES_192, "pcc-cmac-aes-192", PCC, 19, "PCC Compute-Last-Block-CMAC-Using-AES-192") +DEF_FEAT(PCC_CMAC_AES_256, "pcc-cmac-eaes-256", PCC, 20, "PCC Compute-Last-Block-CMAC-Using-AES-256") +DEF_FEAT(PCC_CMAC_EAES_128, "pcc-cmac-eaes-128", PCC, 26, "PCC Compute-Last-Block-CMAC-Using-Encrypted-AES-128") +DEF_FEAT(PCC_CMAC_EAES_192, "pcc-cmac-eaes-192", PCC, 27, "PCC Compute-Last-Block-CMAC-Using-Encrypted-AES-192") +DEF_FEAT(PCC_CMAC_EAES_256, "pcc-cmac-eaes-256", PCC, 28, "PCC Compute-Last-Block-CMAC-Using-Encrypted-AES-256") +DEF_FEAT(PCC_XTS_AES_128, "pcc-xts-aes-128", PCC, 50, "PCC Compute-XTS-Parameter-Using-AES-128") +DEF_FEAT(PCC_XTS_AES_256, "pcc-xts-aes-256", PCC, 52, "PCC Compute-XTS-Parameter-Using-AES-256") +DEF_FEAT(PCC_XTS_EAES_128, "pcc-xts-eaes-128", PCC, 58, "PCC Compute-XTS-Parameter-Using-Encrypted-AES-128") +DEF_FEAT(PCC_XTS_EAES_256, "pcc-xts-eaes-256", PCC, 60, "PCC Compute-XTS-Parameter-Using-Encrypted-AES-256") +DEF_FEAT(PCC_SCALAR_MULT_P256, "pcc-scalar-mult-p256", PCC, 64, "PCC Scalar-Multiply-P256") +DEF_FEAT(PCC_SCALAR_MULT_P384, "pcc-scalar-mult-p384", PCC, 65, "PCC Scalar-Multiply-P384") +DEF_FEAT(PCC_SCALAR_MULT_P512, "pcc-scalar-mult-p521", PCC, 66, "PCC Scalar-Multiply-P521") +DEF_FEAT(PCC_SCALAR_MULT_ED25519, "pcc-scalar-mult-ed25519", PCC, 72, "PCC Scalar-Multiply-Ed25519") +DEF_FEAT(PCC_SCALAR_MULT_ED448, "pcc-scalar-mult-ed448", PCC, 73, "PCC Scalar-Multiply-Ed448") +DEF_FEAT(PCC_SCALAR_MULT_X25519, "pcc-scalar-mult-x25519", PCC, 80, "PCC Scalar-Multiply-X25519") +DEF_FEAT(PCC_SCALAR_MULT_X448, "pcc-scalar-mult-x448", PCC, 81, "PCC Scalar-Multiply-X448") + +/* Features exposed via the PPNO/PRNO instruction. */ +DEF_FEAT(PPNO_SHA_512_DRNG, "ppno-sha-512-drng", PPNO, 3, "PPNO SHA-512-DRNG") +DEF_FEAT(PRNO_TRNG_QRTCR, "prno-trng-qrtcr", PPNO, 112, "PRNO TRNG-Query-Raw-to-Conditioned-Ratio") +DEF_FEAT(PRNO_TRNG, "prno-trng", PPNO, 114, "PRNO TRNG") + +/* Features exposed via the KMA instruction. */ +DEF_FEAT(KMA_GCM_AES_128, "kma-gcm-aes-128", KMA, 18, "KMA GCM-AES-128") +DEF_FEAT(KMA_GCM_AES_192, "kma-gcm-aes-192", KMA, 19, "KMA GCM-AES-192") +DEF_FEAT(KMA_GCM_AES_256, "kma-gcm-aes-256", KMA, 20, "KMA GCM-AES-256") +DEF_FEAT(KMA_GCM_EAES_128, "kma-gcm-eaes-128", KMA, 26, "KMA GCM-Encrypted-AES-128") +DEF_FEAT(KMA_GCM_EAES_192, "kma-gcm-eaes-192", KMA, 27, "KMA GCM-Encrypted-AES-192") +DEF_FEAT(KMA_GCM_EAES_256, "kma-gcm-eaes-256", KMA, 28, "KMA GCM-Encrypted-AES-256") + +/* Features exposed via the KDSA instruction. */ +DEF_FEAT(KDSA_ECDSA_VERIFY_P256, "kdsa-ecdsa-verify-p256", KDSA, 1, "KDSA ECDSA-Verify-P256") +DEF_FEAT(KDSA_ECDSA_VERIFY_P384, "kdsa-ecdsa-verify-p384", KDSA, 2, "KDSA ECDSA-Verify-P384") +DEF_FEAT(KDSA_ECDSA_VERIFY_P512, "kdsa-ecdsa-verify-p521", KDSA, 3, "KDSA ECDSA-Verify-P521") +DEF_FEAT(KDSA_ECDSA_SIGN_P256, "kdsa-ecdsa-sign-p256", KDSA, 9, "KDSA ECDSA-Sign-P256") +DEF_FEAT(KDSA_ECDSA_SIGN_P384, "kdsa-ecdsa-sign-p384", KDSA, 10, "KDSA ECDSA-Sign-P384") +DEF_FEAT(KDSA_ECDSA_SIGN_P512, "kdsa-ecdsa-sign-p521", KDSA, 11, "KDSA ECDSA-Sign-P521") +DEF_FEAT(KDSA_EECDSA_SIGN_P256, "kdsa-eecdsa-sign-p256", KDSA, 17, "KDSA Encrypted-ECDSA-Sign-P256") +DEF_FEAT(KDSA_EECDSA_SIGN_P384, "kdsa-eecdsa-sign-p384", KDSA, 18, "KDSA Encrypted-ECDSA-Sign-P384") +DEF_FEAT(KDSA_EECDSA_SIGN_P512, "kdsa-eecdsa-sign-p521", KDSA, 19, "KDSA Encrypted-ECDSA-Sign-P521") +DEF_FEAT(KDSA_EDDSA_VERIFY_ED25519, "kdsa-eddsa-verify-ed25519", KDSA, 32, "KDSA EdDSA-Verify-Ed25519") +DEF_FEAT(KDSA_EDDSA_VERIFY_ED448, "kdsa-eddsa-verify-ed448", KDSA, 36, "KDSA EdDSA-Verify-Ed448") +DEF_FEAT(KDSA_EDDSA_SIGN_ED25519, "kdsa-eddsa-sign-ed25519", KDSA, 40, "KDSA EdDSA-Sign-Ed25519") +DEF_FEAT(KDSA_EDDSA_SIGN_ED448, "kdsa-eddsa-sign-ed448", KDSA, 44, "KDSA EdDSA-Sign-Ed448") +DEF_FEAT(KDSA_EEDDSA_SIGN_ED25519, "kdsa-eeddsa-sign-ed25519", KDSA, 48, "KDSA Encrypted-EdDSA-Sign-Ed25519") +DEF_FEAT(KDSA_EEDDSA_SIGN_ED448, "kdsa-eeddsa-sign-ed448", KDSA, 52, "KDSA Encrypted-EdDSA-Sign-Ed448") + +/* Features exposed via the SORTL instruction. */ +DEF_FEAT(SORTL_SFLR, "sortl-sflr", SORTL, 1, "SORTL SFLR") +DEF_FEAT(SORTL_SVLR, "sortl-svlr", SORTL, 2, "SORTL SVLR") +DEF_FEAT(SORTL_32, "sortl-32", SORTL, 130, "SORTL 32 input lists") +DEF_FEAT(SORTL_128, "sortl-128", SORTL, 132, "SORTL 128 input lists") +DEF_FEAT(SORTL_F0, "sortl-f0", SORTL, 192, "SORTL format 0 parameter-block") + +/* Features exposed via the DEFLATE instruction. */ +DEF_FEAT(DEFLATE_GHDT, "dfltcc-gdht", DFLTCC, 1, "DFLTCC GDHT") +DEF_FEAT(DEFLATE_CMPR, "dfltcc-cmpr", DFLTCC, 2, "DFLTCC CMPR") +DEF_FEAT(DEFLATE_XPND, "dfltcc-xpnd", DFLTCC, 4, "DFLTCC XPND") +DEF_FEAT(DEFLATE_F0, "dfltcc-f0", DFLTCC, 192, "DFLTCC format 0 parameter-block") diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c index 19ebde14db..2cb09c0780 100644 --- a/target/s390x/cpu_models.c +++ b/target/s390x/cpu_models.c @@ -28,7 +28,7 @@ #include "sysemu/arch_init.h" #include "hw/pci/pci.h" #endif -#include "qapi/qapi-commands-target.h" +#include "qapi/qapi-commands-machine-target.h" #define CPUDEF_INIT(_type, _gen, _ec_ga, _mha_pow, _hmfai, _name, _desc) \ { \ diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c index dc320a06c2..af06be3e3b 100644 --- a/target/s390x/gen-features.c +++ b/target/s390x/gen-features.c @@ -216,21 +216,21 @@ #define S390_FEAT_GROUP_MSA_EXT_9 \ S390_FEAT_MSA_EXT_9, \ - S390_FEAT_ECDSA_VERIFY_P256, \ - S390_FEAT_ECDSA_VERIFY_P384, \ - S390_FEAT_ECDSA_VERIFY_P512, \ - S390_FEAT_ECDSA_SIGN_P256, \ - S390_FEAT_ECDSA_SIGN_P384, \ - S390_FEAT_ECDSA_SIGN_P512, \ - S390_FEAT_EECDSA_SIGN_P256, \ - S390_FEAT_EECDSA_SIGN_P384, \ - S390_FEAT_EECDSA_SIGN_P512, \ - S390_FEAT_EDDSA_VERIFY_ED25519, \ - S390_FEAT_EDDSA_VERIFY_ED448, \ - S390_FEAT_EDDSA_SIGN_ED25519, \ - S390_FEAT_EDDSA_SIGN_ED448, \ - S390_FEAT_EEDDSA_SIGN_ED25519, \ - S390_FEAT_EEDDSA_SIGN_ED448, \ + S390_FEAT_KDSA_ECDSA_VERIFY_P256, \ + S390_FEAT_KDSA_ECDSA_VERIFY_P384, \ + S390_FEAT_KDSA_ECDSA_VERIFY_P512, \ + S390_FEAT_KDSA_ECDSA_SIGN_P256, \ + S390_FEAT_KDSA_ECDSA_SIGN_P384, \ + S390_FEAT_KDSA_ECDSA_SIGN_P512, \ + S390_FEAT_KDSA_EECDSA_SIGN_P256, \ + S390_FEAT_KDSA_EECDSA_SIGN_P384, \ + S390_FEAT_KDSA_EECDSA_SIGN_P512, \ + S390_FEAT_KDSA_EDDSA_VERIFY_ED25519, \ + S390_FEAT_KDSA_EDDSA_VERIFY_ED448, \ + S390_FEAT_KDSA_EDDSA_SIGN_ED25519, \ + S390_FEAT_KDSA_EDDSA_SIGN_ED448, \ + S390_FEAT_KDSA_EEDDSA_SIGN_ED25519, \ + S390_FEAT_KDSA_EEDDSA_SIGN_ED448, \ S390_FEAT_PCC_SCALAR_MULT_P256, \ S390_FEAT_PCC_SCALAR_MULT_P384, \ S390_FEAT_PCC_SCALAR_MULT_P512, \ diff --git a/target/s390x/sigp.c b/target/s390x/sigp.c index ce49a792fc..8348b7035e 100644 --- a/target/s390x/sigp.c +++ b/target/s390x/sigp.c @@ -17,7 +17,7 @@ #include "sysemu/sysemu.h" #include "sysemu/tcg.h" #include "trace.h" -#include "qapi/qapi-types-misc.h" +#include "qapi/qapi-types-machine.h" QemuMutex qemu_sigp_mutex; diff --git a/target/sh4/monitor.c b/target/sh4/monitor.c index 4c7f36c9cc..918a5ccfc6 100644 --- a/target/sh4/monitor.c +++ b/target/sh4/monitor.c @@ -25,7 +25,7 @@ #include "cpu.h" #include "monitor/monitor.h" #include "monitor/hmp-target.h" -#include "hmp.h" +#include "monitor/hmp.h" static void print_tlb(Monitor *mon, int idx, tlb_t *tlb) { diff --git a/target/sparc/monitor.c b/target/sparc/monitor.c index 3ec3b51a3d..a7ea287cbc 100644 --- a/target/sparc/monitor.c +++ b/target/sparc/monitor.c @@ -25,7 +25,7 @@ #include "cpu.h" #include "monitor/monitor.h" #include "monitor/hmp-target.h" -#include "hmp.h" +#include "monitor/hmp.h" void hmp_info_tlb(Monitor *mon, const QDict *qdict) diff --git a/target/xtensa/monitor.c b/target/xtensa/monitor.c index cf7957bb63..608173c238 100644 --- a/target/xtensa/monitor.c +++ b/target/xtensa/monitor.c @@ -25,7 +25,7 @@ #include "cpu.h" #include "monitor/monitor.h" #include "monitor/hmp-target.h" -#include "hmp.h" +#include "monitor/hmp.h" void hmp_info_tlb(Monitor *mon, const QDict *qdict) { diff --git a/tests/Makefile.include b/tests/Makefile.include index b54fea1bb4..a983dd32da 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -261,6 +261,7 @@ check-qtest-arm-y += tests/m25p80-test$(EXESUF) check-qtest-arm-y += tests/test-arm-mptimer$(EXESUF) check-qtest-arm-y += tests/boot-serial-test$(EXESUF) check-qtest-arm-y += tests/hexloader-test$(EXESUF) +check-qtest-arm-$(CONFIG_PFLASH_CFI02) += tests/pflash-cfi02-test$(EXESUF) check-qtest-aarch64-y = tests/numa-test$(EXESUF) check-qtest-aarch64-y += tests/boot-serial-test$(EXESUF) @@ -768,6 +769,7 @@ tests/device-introspect-test$(EXESUF): tests/device-introspect-test.o tests/rtc-test$(EXESUF): tests/rtc-test.o tests/m48t59-test$(EXESUF): tests/m48t59-test.o tests/hexloader-test$(EXESUF): tests/hexloader-test.o +tests/pflash-cfi02$(EXESUF): tests/pflash-cfi02-test.o tests/endianness-test$(EXESUF): tests/endianness-test.o tests/prom-env-test$(EXESUF): tests/prom-env-test.o $(libqos-obj-y) tests/rtas-test$(EXESUF): tests/rtas-test.o $(libqos-spapr-obj-y) diff --git a/tests/acceptance/avocado_qemu/__init__.py b/tests/acceptance/avocado_qemu/__init__.py index 2b236a1cf0..aee5d820ed 100644 --- a/tests/acceptance/avocado_qemu/__init__.py +++ b/tests/acceptance/avocado_qemu/__init__.py @@ -17,7 +17,7 @@ import avocado SRC_ROOT_DIR = os.path.join(os.path.dirname(__file__), '..', '..', '..') sys.path.append(os.path.join(SRC_ROOT_DIR, 'python')) -from qemu import QEMUMachine +from qemu.machine import QEMUMachine def is_readable_executable_file(path): return os.path.isfile(path) and os.access(path, os.R_OK | os.X_OK) diff --git a/tests/acceptance/virtio_version.py b/tests/acceptance/virtio_version.py index 8b97453ff8..33593c29dd 100644 --- a/tests/acceptance/virtio_version.py +++ b/tests/acceptance/virtio_version.py @@ -12,7 +12,7 @@ import sys import os sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python')) -from qemu import QEMUMachine +from qemu.machine import QEMUMachine from avocado_qemu import Test # Virtio Device IDs: diff --git a/tests/machine-none-test.c b/tests/machine-none-test.c index 4c6d470798..5953d31755 100644 --- a/tests/machine-none-test.c +++ b/tests/machine-none-test.c @@ -36,9 +36,9 @@ static struct arch2cpu cpus_map[] = { /* FIXME: { "microblaze", "any" }, doesn't work with -M none -cpu any */ /* FIXME: { "microblazeel", "any" }, doesn't work with -M none -cpu any */ { "mips", "4Kc" }, - { "mipsel", "4Kc" }, + { "mipsel", "I7200" }, { "mips64", "20Kc" }, - { "mips64el", "20Kc" }, + { "mips64el", "I6500" }, { "moxie", "MoxieLite" }, { "nios2", "FIXME" }, { "or1k", "or1200" }, diff --git a/tests/migration/guestperf/engine.py b/tests/migration/guestperf/engine.py index 0e304660b8..f13dbea800 100644 --- a/tests/migration/guestperf/engine.py +++ b/tests/migration/guestperf/engine.py @@ -30,7 +30,7 @@ from guestperf.timings import TimingRecord, Timings sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'python')) -import qemu +from qemu.machine import QEMUMachine class Engine(object): @@ -386,17 +386,17 @@ class Engine(object): dstmonaddr = "/var/tmp/qemu-dst-%d-monitor.sock" % os.getpid() srcmonaddr = "/var/tmp/qemu-src-%d-monitor.sock" % os.getpid() - src = qemu.QEMUMachine(self._binary, - args=self._get_src_args(hardware), - wrapper=self._get_src_wrapper(hardware), - name="qemu-src-%d" % os.getpid(), - monitor_address=srcmonaddr) - - dst = qemu.QEMUMachine(self._binary, - args=self._get_dst_args(hardware, uri), - wrapper=self._get_dst_wrapper(hardware), - name="qemu-dst-%d" % os.getpid(), - monitor_address=dstmonaddr) + src = QEMUMachine(self._binary, + args=self._get_src_args(hardware), + wrapper=self._get_src_wrapper(hardware), + name="qemu-src-%d" % os.getpid(), + monitor_address=srcmonaddr) + + dst = QEMUMachine(self._binary, + args=self._get_dst_args(hardware, uri), + wrapper=self._get_dst_wrapper(hardware), + name="qemu-dst-%d" % os.getpid(), + monitor_address=dstmonaddr) try: src.launch() diff --git a/tests/pflash-cfi02-test.c b/tests/pflash-cfi02-test.c new file mode 100644 index 0000000000..d3b23f4f66 --- /dev/null +++ b/tests/pflash-cfi02-test.c @@ -0,0 +1,681 @@ +/* + * QTest testcase for parallel flash with AMD command set + * + * Copyright (c) 2019 Stephen Checkoway + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "libqtest.h" + +/* + * To test the pflash_cfi02 device, we run QEMU with the musicpal machine with + * a pflash drive. This enables us to test some flash configurations, but not + * all. In particular, we're limited to a 16-bit wide flash device. + */ + +#define MP_FLASH_SIZE_MAX (32 * 1024 * 1024) +#define BASE_ADDR (0x100000000ULL - MP_FLASH_SIZE_MAX) + +#define UNIFORM_FLASH_SIZE (8 * 1024 * 1024) +#define UNIFORM_FLASH_SECTOR_SIZE (64 * 1024) + +/* Use a newtype to keep flash addresses separate from byte addresses. */ +typedef struct { + uint64_t addr; +} faddr; +#define FLASH_ADDR(x) ((faddr) { .addr = (x) }) + +#define CFI_ADDR FLASH_ADDR(0x55) +#define UNLOCK0_ADDR FLASH_ADDR(0x555) +#define UNLOCK1_ADDR FLASH_ADDR(0x2AA) + +#define CFI_CMD 0x98 +#define UNLOCK0_CMD 0xAA +#define UNLOCK1_CMD 0x55 +#define SECOND_UNLOCK_CMD 0x80 +#define AUTOSELECT_CMD 0x90 +#define RESET_CMD 0xF0 +#define PROGRAM_CMD 0xA0 +#define SECTOR_ERASE_CMD 0x30 +#define CHIP_ERASE_CMD 0x10 +#define UNLOCK_BYPASS_CMD 0x20 +#define UNLOCK_BYPASS_RESET_CMD 0x00 +#define ERASE_SUSPEND_CMD 0xB0 +#define ERASE_RESUME_CMD SECTOR_ERASE_CMD + +typedef struct { + int bank_width; + + /* Nonuniform block size. */ + int nb_blocs[4]; + int sector_len[4]; + + QTestState *qtest; +} FlashConfig; + +static char image_path[] = "/tmp/qtest.XXXXXX"; + +/* + * The pflash implementation allows some parameters to be unspecified. We want + * to test those configurations but we also need to know the real values in + * our testing code. So after we launch qemu, we'll need a new FlashConfig + * with the correct values filled in. + */ +static FlashConfig expand_config_defaults(const FlashConfig *c) +{ + FlashConfig ret = *c; + + if (ret.bank_width == 0) { + ret.bank_width = 2; + } + if (ret.nb_blocs[0] == 0 && ret.sector_len[0] == 0) { + ret.sector_len[0] = UNIFORM_FLASH_SECTOR_SIZE; + ret.nb_blocs[0] = UNIFORM_FLASH_SIZE / UNIFORM_FLASH_SECTOR_SIZE; + } + + /* XXX: Limitations of test harness. */ + assert(ret.bank_width == 2); + return ret; +} + +/* + * Return a bit mask suitable for extracting the least significant + * status/query response from an interleaved response. + */ +static inline uint64_t device_mask(const FlashConfig *c) +{ + return (uint64_t)-1; +} + +/* + * Return a bit mask exactly as long as the bank_width. + */ +static inline uint64_t bank_mask(const FlashConfig *c) +{ + if (c->bank_width == 8) { + return (uint64_t)-1; + } + return (1ULL << (c->bank_width * 8)) - 1ULL; +} + +static inline void flash_write(const FlashConfig *c, uint64_t byte_addr, + uint64_t data) +{ + /* Sanity check our tests. */ + assert((data & ~bank_mask(c)) == 0); + uint64_t addr = BASE_ADDR + byte_addr; + switch (c->bank_width) { + case 1: + qtest_writeb(c->qtest, addr, data); + break; + case 2: + qtest_writew(c->qtest, addr, data); + break; + case 4: + qtest_writel(c->qtest, addr, data); + break; + case 8: + qtest_writeq(c->qtest, addr, data); + break; + default: + abort(); + } +} + +static inline uint64_t flash_read(const FlashConfig *c, uint64_t byte_addr) +{ + uint64_t addr = BASE_ADDR + byte_addr; + switch (c->bank_width) { + case 1: + return qtest_readb(c->qtest, addr); + case 2: + return qtest_readw(c->qtest, addr); + case 4: + return qtest_readl(c->qtest, addr); + case 8: + return qtest_readq(c->qtest, addr); + default: + abort(); + } +} + +/* + * Convert a flash address expressed in the maximum width of the device as a + * byte address. + */ +static inline uint64_t as_byte_addr(const FlashConfig *c, faddr flash_addr) +{ + /* + * Command addresses are always given as addresses in the maximum + * supported bus size for the flash chip. So an x8/x16 chip in x8 mode + * uses addresses 0xAAA and 0x555 to unlock because the least significant + * bit is ignored. (0x555 rather than 0x554 is traditional.) + * + * In general we need to multiply by the maximum device width. + */ + return flash_addr.addr * c->bank_width; +} + +/* + * Return the command value or expected status replicated across all devices. + */ +static inline uint64_t replicate(const FlashConfig *c, uint64_t data) +{ + /* Sanity check our tests. */ + assert((data & ~device_mask(c)) == 0); + return data; +} + +static inline void flash_cmd(const FlashConfig *c, faddr cmd_addr, + uint8_t cmd) +{ + flash_write(c, as_byte_addr(c, cmd_addr), replicate(c, cmd)); +} + +static inline uint64_t flash_query(const FlashConfig *c, faddr query_addr) +{ + return flash_read(c, as_byte_addr(c, query_addr)); +} + +static inline uint64_t flash_query_1(const FlashConfig *c, faddr query_addr) +{ + return flash_query(c, query_addr) & device_mask(c); +} + +static void unlock(const FlashConfig *c) +{ + flash_cmd(c, UNLOCK0_ADDR, UNLOCK0_CMD); + flash_cmd(c, UNLOCK1_ADDR, UNLOCK1_CMD); +} + +static void reset(const FlashConfig *c) +{ + flash_cmd(c, FLASH_ADDR(0), RESET_CMD); +} + +static void sector_erase(const FlashConfig *c, uint64_t byte_addr) +{ + unlock(c); + flash_cmd(c, UNLOCK0_ADDR, SECOND_UNLOCK_CMD); + unlock(c); + flash_write(c, byte_addr, replicate(c, SECTOR_ERASE_CMD)); +} + +static void wait_for_completion(const FlashConfig *c, uint64_t byte_addr) +{ + /* If DQ6 is toggling, step the clock and ensure the toggle stops. */ + const uint64_t dq6 = replicate(c, 0x40); + if ((flash_read(c, byte_addr) & dq6) ^ (flash_read(c, byte_addr) & dq6)) { + /* Wait for erase or program to finish. */ + qtest_clock_step_next(c->qtest); + /* Ensure that DQ6 has stopped toggling. */ + g_assert_cmphex(flash_read(c, byte_addr), ==, flash_read(c, byte_addr)); + } +} + +static void bypass_program(const FlashConfig *c, uint64_t byte_addr, + uint16_t data) +{ + flash_cmd(c, UNLOCK0_ADDR, PROGRAM_CMD); + flash_write(c, byte_addr, data); + /* + * Data isn't valid until DQ6 stops toggling. We don't model this as + * writes are immediate, but if this changes in the future, we can wait + * until the program is complete. + */ + wait_for_completion(c, byte_addr); +} + +static void program(const FlashConfig *c, uint64_t byte_addr, uint16_t data) +{ + unlock(c); + bypass_program(c, byte_addr, data); +} + +static void chip_erase(const FlashConfig *c) +{ + unlock(c); + flash_cmd(c, UNLOCK0_ADDR, SECOND_UNLOCK_CMD); + unlock(c); + flash_cmd(c, UNLOCK0_ADDR, CHIP_ERASE_CMD); +} + +static void erase_suspend(const FlashConfig *c) +{ + flash_cmd(c, FLASH_ADDR(0), ERASE_SUSPEND_CMD); +} + +static void erase_resume(const FlashConfig *c) +{ + flash_cmd(c, FLASH_ADDR(0), ERASE_RESUME_CMD); +} + +/* + * Test flash commands with a variety of device geometry. + */ +static void test_geometry(const void *opaque) +{ + const FlashConfig *config = opaque; + QTestState *qtest; + qtest = qtest_initf("-M musicpal,accel=qtest" + " -drive if=pflash,file=%s,format=raw,copy-on-read" + /* Device geometry properties. */ + " -global driver=cfi.pflash02," + "property=num-blocks0,value=%d" + " -global driver=cfi.pflash02," + "property=sector-length0,value=%d" + " -global driver=cfi.pflash02," + "property=num-blocks1,value=%d" + " -global driver=cfi.pflash02," + "property=sector-length1,value=%d" + " -global driver=cfi.pflash02," + "property=num-blocks2,value=%d" + " -global driver=cfi.pflash02," + "property=sector-length2,value=%d" + " -global driver=cfi.pflash02," + "property=num-blocks3,value=%d" + " -global driver=cfi.pflash02," + "property=sector-length3,value=%d", + image_path, + config->nb_blocs[0], + config->sector_len[0], + config->nb_blocs[1], + config->sector_len[1], + config->nb_blocs[2], + config->sector_len[2], + config->nb_blocs[3], + config->sector_len[3]); + FlashConfig explicit_config = expand_config_defaults(config); + explicit_config.qtest = qtest; + const FlashConfig *c = &explicit_config; + + /* Check the IDs. */ + unlock(c); + flash_cmd(c, UNLOCK0_ADDR, AUTOSELECT_CMD); + g_assert_cmphex(flash_query(c, FLASH_ADDR(0)), ==, replicate(c, 0xBF)); + if (c->bank_width >= 2) { + /* + * XXX: The ID returned by the musicpal flash chip is 16 bits which + * wouldn't happen with an 8-bit device. It would probably be best to + * prohibit addresses larger than the device width in pflash_cfi02.c, + * but then we couldn't test smaller device widths at all. + */ + g_assert_cmphex(flash_query(c, FLASH_ADDR(1)), ==, + replicate(c, 0x236D)); + } + reset(c); + + /* Check the erase blocks. */ + flash_cmd(c, CFI_ADDR, CFI_CMD); + g_assert_cmphex(flash_query(c, FLASH_ADDR(0x10)), ==, replicate(c, 'Q')); + g_assert_cmphex(flash_query(c, FLASH_ADDR(0x11)), ==, replicate(c, 'R')); + g_assert_cmphex(flash_query(c, FLASH_ADDR(0x12)), ==, replicate(c, 'Y')); + + /* Num erase regions. */ + int nb_erase_regions = flash_query_1(c, FLASH_ADDR(0x2C)); + g_assert_cmphex(nb_erase_regions, ==, + !!c->nb_blocs[0] + !!c->nb_blocs[1] + !!c->nb_blocs[2] + + !!c->nb_blocs[3]); + + /* Check device length. */ + uint32_t device_len = 1 << flash_query_1(c, FLASH_ADDR(0x27)); + g_assert_cmphex(device_len, ==, UNIFORM_FLASH_SIZE); + + /* Check that erase suspend to read/write is supported. */ + uint16_t pri = flash_query_1(c, FLASH_ADDR(0x15)) + + (flash_query_1(c, FLASH_ADDR(0x16)) << 8); + g_assert_cmpint(pri, >=, 0x2D + 4 * nb_erase_regions); + g_assert_cmpint(flash_query(c, FLASH_ADDR(pri + 0)), ==, replicate(c, 'P')); + g_assert_cmpint(flash_query(c, FLASH_ADDR(pri + 1)), ==, replicate(c, 'R')); + g_assert_cmpint(flash_query(c, FLASH_ADDR(pri + 2)), ==, replicate(c, 'I')); + g_assert_cmpint(flash_query_1(c, FLASH_ADDR(pri + 6)), ==, 2); /* R/W */ + reset(c); + + const uint64_t dq7 = replicate(c, 0x80); + const uint64_t dq6 = replicate(c, 0x40); + const uint64_t dq3 = replicate(c, 0x08); + const uint64_t dq2 = replicate(c, 0x04); + + uint64_t byte_addr = 0; + for (int region = 0; region < nb_erase_regions; ++region) { + uint64_t base = 0x2D + 4 * region; + flash_cmd(c, CFI_ADDR, CFI_CMD); + uint32_t nb_sectors = flash_query_1(c, FLASH_ADDR(base + 0)) + + (flash_query_1(c, FLASH_ADDR(base + 1)) << 8) + 1; + uint32_t sector_len = (flash_query_1(c, FLASH_ADDR(base + 2)) << 8) + + (flash_query_1(c, FLASH_ADDR(base + 3)) << 16); + g_assert_cmphex(nb_sectors, ==, c->nb_blocs[region]); + g_assert_cmphex(sector_len, ==, c->sector_len[region]); + reset(c); + + /* Erase and program sector. */ + for (uint32_t i = 0; i < nb_sectors; ++i) { + sector_erase(c, byte_addr); + + /* Check that DQ3 is 0. */ + g_assert_cmphex(flash_read(c, byte_addr) & dq3, ==, 0); + qtest_clock_step_next(c->qtest); /* Step over the 50 us timeout. */ + + /* Check that DQ3 is 1. */ + uint64_t status0 = flash_read(c, byte_addr); + g_assert_cmphex(status0 & dq3, ==, dq3); + + /* DQ7 is 0 during an erase. */ + g_assert_cmphex(status0 & dq7, ==, 0); + uint64_t status1 = flash_read(c, byte_addr); + + /* DQ6 toggles during an erase. */ + g_assert_cmphex(status0 & dq6, ==, ~status1 & dq6); + + /* Wait for erase to complete. */ + wait_for_completion(c, byte_addr); + + /* Ensure DQ6 has stopped toggling. */ + g_assert_cmphex(flash_read(c, byte_addr), ==, + flash_read(c, byte_addr)); + + /* Now the data should be valid. */ + g_assert_cmphex(flash_read(c, byte_addr), ==, bank_mask(c)); + + /* Program a bit pattern. */ + program(c, byte_addr, 0x55); + g_assert_cmphex(flash_read(c, byte_addr) & 0xFF, ==, 0x55); + program(c, byte_addr, 0xA5); + g_assert_cmphex(flash_read(c, byte_addr) & 0xFF, ==, 0x05); + byte_addr += sector_len; + } + } + + /* Erase the chip. */ + chip_erase(c); + /* Read toggle. */ + uint64_t status0 = flash_read(c, 0); + /* DQ7 is 0 during an erase. */ + g_assert_cmphex(status0 & dq7, ==, 0); + uint64_t status1 = flash_read(c, 0); + /* DQ6 toggles during an erase. */ + g_assert_cmphex(status0 & dq6, ==, ~status1 & dq6); + /* Wait for erase to complete. */ + qtest_clock_step_next(c->qtest); + /* Ensure DQ6 has stopped toggling. */ + g_assert_cmphex(flash_read(c, 0), ==, flash_read(c, 0)); + /* Now the data should be valid. */ + + for (int region = 0; region < nb_erase_regions; ++region) { + for (uint32_t i = 0; i < c->nb_blocs[region]; ++i) { + uint64_t byte_addr = i * c->sector_len[region]; + g_assert_cmphex(flash_read(c, byte_addr), ==, bank_mask(c)); + } + } + + /* Unlock bypass */ + unlock(c); + flash_cmd(c, UNLOCK0_ADDR, UNLOCK_BYPASS_CMD); + bypass_program(c, 0 * c->bank_width, 0x01); + bypass_program(c, 1 * c->bank_width, 0x23); + bypass_program(c, 2 * c->bank_width, 0x45); + /* + * Test that bypass programming, unlike normal programming can use any + * address for the PROGRAM_CMD. + */ + flash_cmd(c, FLASH_ADDR(3 * c->bank_width), PROGRAM_CMD); + flash_write(c, 3 * c->bank_width, 0x67); + wait_for_completion(c, 3 * c->bank_width); + flash_cmd(c, FLASH_ADDR(0), UNLOCK_BYPASS_RESET_CMD); + bypass_program(c, 4 * c->bank_width, 0x89); /* Should fail. */ + g_assert_cmphex(flash_read(c, 0 * c->bank_width), ==, 0x01); + g_assert_cmphex(flash_read(c, 1 * c->bank_width), ==, 0x23); + g_assert_cmphex(flash_read(c, 2 * c->bank_width), ==, 0x45); + g_assert_cmphex(flash_read(c, 3 * c->bank_width), ==, 0x67); + g_assert_cmphex(flash_read(c, 4 * c->bank_width), ==, bank_mask(c)); + + /* Test ignored high order bits of address. */ + flash_cmd(c, FLASH_ADDR(0x5555), UNLOCK0_CMD); + flash_cmd(c, FLASH_ADDR(0x2AAA), UNLOCK1_CMD); + flash_cmd(c, FLASH_ADDR(0x5555), AUTOSELECT_CMD); + g_assert_cmphex(flash_query(c, FLASH_ADDR(0)), ==, replicate(c, 0xBF)); + reset(c); + + /* + * Program a word on each sector, erase one or two sectors per region, and + * verify that all of those, and only those, are erased. + */ + byte_addr = 0; + for (int region = 0; region < nb_erase_regions; ++region) { + for (int i = 0; i < config->nb_blocs[region]; ++i) { + program(c, byte_addr, 0); + byte_addr += config->sector_len[region]; + } + } + unlock(c); + flash_cmd(c, UNLOCK0_ADDR, SECOND_UNLOCK_CMD); + unlock(c); + byte_addr = 0; + const uint64_t erase_cmd = replicate(c, SECTOR_ERASE_CMD); + for (int region = 0; region < nb_erase_regions; ++region) { + flash_write(c, byte_addr, erase_cmd); + if (c->nb_blocs[region] > 1) { + flash_write(c, byte_addr + c->sector_len[region], erase_cmd); + } + byte_addr += c->sector_len[region] * c->nb_blocs[region]; + } + + qtest_clock_step_next(c->qtest); /* Step over the 50 us timeout. */ + wait_for_completion(c, 0); + byte_addr = 0; + for (int region = 0; region < nb_erase_regions; ++region) { + for (int i = 0; i < config->nb_blocs[region]; ++i) { + if (i < 2) { + g_assert_cmphex(flash_read(c, byte_addr), ==, bank_mask(c)); + } else { + g_assert_cmphex(flash_read(c, byte_addr), ==, 0); + } + byte_addr += config->sector_len[region]; + } + } + + /* Test erase suspend/resume during erase timeout. */ + sector_erase(c, 0); + /* + * Check that DQ 3 is 0 and DQ6 and DQ2 are toggling in the sector being + * erased as well as in a sector not being erased. + */ + byte_addr = c->sector_len[0]; + status0 = flash_read(c, 0); + status1 = flash_read(c, 0); + g_assert_cmpint(status0 & dq3, ==, 0); + g_assert_cmpint(status0 & dq6, ==, ~status1 & dq6); + g_assert_cmpint(status0 & dq2, ==, ~status1 & dq2); + status0 = flash_read(c, byte_addr); + status1 = flash_read(c, byte_addr); + g_assert_cmpint(status0 & dq3, ==, 0); + g_assert_cmpint(status0 & dq6, ==, ~status1 & dq6); + g_assert_cmpint(status0 & dq2, ==, ~status1 & dq2); + + /* + * Check that after suspending, DQ6 does not toggle but DQ2 does toggle in + * an erase suspended sector but that neither toggle (we should be + * getting data) in a sector not being erased. + */ + erase_suspend(c); + status0 = flash_read(c, 0); + status1 = flash_read(c, 0); + g_assert_cmpint(status0 & dq6, ==, status1 & dq6); + g_assert_cmpint(status0 & dq2, ==, ~status1 & dq2); + g_assert_cmpint(flash_read(c, byte_addr), ==, flash_read(c, byte_addr)); + + /* Check that after resuming, DQ3 is 1 and DQ6 and DQ2 toggle. */ + erase_resume(c); + status0 = flash_read(c, 0); + status1 = flash_read(c, 0); + g_assert_cmpint(status0 & dq3, ==, dq3); + g_assert_cmpint(status0 & dq6, ==, ~status1 & dq6); + g_assert_cmpint(status0 & dq2, ==, ~status1 & dq2); + status0 = flash_read(c, byte_addr); + status1 = flash_read(c, byte_addr); + g_assert_cmpint(status0 & dq3, ==, dq3); + g_assert_cmpint(status0 & dq6, ==, ~status1 & dq6); + g_assert_cmpint(status0 & dq2, ==, ~status1 & dq2); + wait_for_completion(c, 0); + + /* Repeat this process but this time suspend after the timeout. */ + sector_erase(c, 0); + qtest_clock_step_next(c->qtest); + /* + * Check that DQ 3 is 1 and DQ6 and DQ2 are toggling in the sector being + * erased as well as in a sector not being erased. + */ + byte_addr = c->sector_len[0]; + status0 = flash_read(c, 0); + status1 = flash_read(c, 0); + g_assert_cmpint(status0 & dq3, ==, dq3); + g_assert_cmpint(status0 & dq6, ==, ~status1 & dq6); + g_assert_cmpint(status0 & dq2, ==, ~status1 & dq2); + status0 = flash_read(c, byte_addr); + status1 = flash_read(c, byte_addr); + g_assert_cmpint(status0 & dq3, ==, dq3); + g_assert_cmpint(status0 & dq6, ==, ~status1 & dq6); + g_assert_cmpint(status0 & dq2, ==, ~status1 & dq2); + + /* + * Check that after suspending, DQ6 does not toggle but DQ2 does toggle in + * an erase suspended sector but that neither toggle (we should be + * getting data) in a sector not being erased. + */ + erase_suspend(c); + status0 = flash_read(c, 0); + status1 = flash_read(c, 0); + g_assert_cmpint(status0 & dq6, ==, status1 & dq6); + g_assert_cmpint(status0 & dq2, ==, ~status1 & dq2); + g_assert_cmpint(flash_read(c, byte_addr), ==, flash_read(c, byte_addr)); + + /* Check that after resuming, DQ3 is 1 and DQ6 and DQ2 toggle. */ + erase_resume(c); + status0 = flash_read(c, 0); + status1 = flash_read(c, 0); + g_assert_cmpint(status0 & dq3, ==, dq3); + g_assert_cmpint(status0 & dq6, ==, ~status1 & dq6); + g_assert_cmpint(status0 & dq2, ==, ~status1 & dq2); + status0 = flash_read(c, byte_addr); + status1 = flash_read(c, byte_addr); + g_assert_cmpint(status0 & dq3, ==, dq3); + g_assert_cmpint(status0 & dq6, ==, ~status1 & dq6); + g_assert_cmpint(status0 & dq2, ==, ~status1 & dq2); + wait_for_completion(c, 0); + + qtest_quit(qtest); +} + +/* + * Test that + * 1. enter autoselect mode; + * 2. enter CFI mode; and then + * 3. exit CFI mode + * leaves the flash device in autoselect mode. + */ +static void test_cfi_in_autoselect(const void *opaque) +{ + const FlashConfig *config = opaque; + QTestState *qtest; + qtest = qtest_initf("-M musicpal,accel=qtest" + " -drive if=pflash,file=%s,format=raw,copy-on-read", + image_path); + FlashConfig explicit_config = expand_config_defaults(config); + explicit_config.qtest = qtest; + const FlashConfig *c = &explicit_config; + + /* 1. Enter autoselect. */ + unlock(c); + flash_cmd(c, UNLOCK0_ADDR, AUTOSELECT_CMD); + g_assert_cmphex(flash_query(c, FLASH_ADDR(0)), ==, replicate(c, 0xBF)); + + /* 2. Enter CFI. */ + flash_cmd(c, CFI_ADDR, CFI_CMD); + g_assert_cmphex(flash_query(c, FLASH_ADDR(0x10)), ==, replicate(c, 'Q')); + g_assert_cmphex(flash_query(c, FLASH_ADDR(0x11)), ==, replicate(c, 'R')); + g_assert_cmphex(flash_query(c, FLASH_ADDR(0x12)), ==, replicate(c, 'Y')); + + /* 3. Exit CFI. */ + reset(c); + g_assert_cmphex(flash_query(c, FLASH_ADDR(0)), ==, replicate(c, 0xBF)); + + qtest_quit(qtest); +} + +static void cleanup(void *opaque) +{ + unlink(image_path); +} + +/* + * XXX: Tests are limited to bank_width = 2 for now because that's what + * hw/arm/musicpal.c has. + */ +static const FlashConfig configuration[] = { + /* One x16 device. */ + { + .bank_width = 2, + }, + /* Nonuniform sectors (top boot). */ + { + .bank_width = 2, + .nb_blocs = { 127, 1, 2, 1 }, + .sector_len = { 0x10000, 0x08000, 0x02000, 0x04000 }, + }, + /* Nonuniform sectors (bottom boot). */ + { + .bank_width = 2, + .nb_blocs = { 1, 2, 1, 127 }, + .sector_len = { 0x04000, 0x02000, 0x08000, 0x10000 }, + }, +}; + +int main(int argc, char **argv) +{ + int fd = mkstemp(image_path); + if (fd == -1) { + g_printerr("Failed to create temporary file %s: %s\n", image_path, + strerror(errno)); + exit(EXIT_FAILURE); + } + if (ftruncate(fd, UNIFORM_FLASH_SIZE) < 0) { + int error_code = errno; + close(fd); + unlink(image_path); + g_printerr("Failed to truncate file %s to %u MB: %s\n", image_path, + UNIFORM_FLASH_SIZE, strerror(error_code)); + exit(EXIT_FAILURE); + } + close(fd); + + qtest_add_abrt_handler(cleanup, NULL); + g_test_init(&argc, &argv, NULL); + + size_t nb_configurations = sizeof configuration / sizeof configuration[0]; + for (size_t i = 0; i < nb_configurations; ++i) { + const FlashConfig *config = &configuration[i]; + char *path = g_strdup_printf("pflash-cfi02" + "/geometry/%dx%x-%dx%x-%dx%x-%dx%x" + "/%d", + config->nb_blocs[0], + config->sector_len[0], + config->nb_blocs[1], + config->sector_len[1], + config->nb_blocs[2], + config->sector_len[2], + config->nb_blocs[3], + config->sector_len[3], + config->bank_width); + qtest_add_data_func(path, config, test_geometry); + g_free(path); + } + + qtest_add_data_func("pflash-cfi02/cfi-in-autoselect", &configuration[0], + test_cfi_in_autoselect); + int result = g_test_run(); + cleanup(NULL); + return result; +} diff --git a/tests/qemu-iotests/235 b/tests/qemu-iotests/235 index 2b6a8c13be..fedd111fd4 100755 --- a/tests/qemu-iotests/235 +++ b/tests/qemu-iotests/235 @@ -25,7 +25,7 @@ from iotests import qemu_img_create, qemu_io, file_path, log sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python')) -from qemu import QEMUMachine +from qemu.machine import QEMUMachine # Note: # This test was added to check that mirror dead-lock was fixed (see previous diff --git a/tests/qemu-iotests/245 b/tests/qemu-iotests/245 index 349b94aace..bc1ceb9792 100644 --- a/tests/qemu-iotests/245 +++ b/tests/qemu-iotests/245 @@ -866,9 +866,9 @@ class TestBlockdevReopen(iotests.QMPTestCase): auto_finalize = False) self.assert_qmp(result, 'return', {}) - # We can't remove hd2 while the stream job is ongoing + # We can remove hd2 while the stream job is ongoing opts['backing']['backing'] = None - self.reopen(opts, {}, "Cannot change 'backing' link from 'hd1' to 'hd2'") + self.reopen(opts, {}) # We can't remove hd1 while the stream job is ongoing opts['backing'] = None diff --git a/tests/tcg/mips/include/wrappers_msa.h b/tests/tcg/mips/include/wrappers_msa.h index b512b1db57..4be7821ece 100644 --- a/tests/tcg/mips/include/wrappers_msa.h +++ b/tests/tcg/mips/include/wrappers_msa.h @@ -252,16 +252,32 @@ DO_MSA__WD__WS_WT(BNEG_D, bneg.d) */ DO_MSA__WD__WS_WT(MADD_Q_H, madd_q.h) +DO_MSA__WD__WD_WT(MADD_Q_H__DDT, madd_q.h) +DO_MSA__WD__WS_WD(MADD_Q_H__DSD, madd_q.h) DO_MSA__WD__WS_WT(MADD_Q_W, madd_q.w) +DO_MSA__WD__WD_WT(MADD_Q_W__DDT, madd_q.w) +DO_MSA__WD__WS_WD(MADD_Q_W__DSD, madd_q.w) DO_MSA__WD__WS_WT(MADDR_Q_H, maddr_q.h) +DO_MSA__WD__WD_WT(MADDR_Q_H__DDT, maddr_q.h) +DO_MSA__WD__WS_WD(MADDR_Q_H__DSD, maddr_q.h) DO_MSA__WD__WS_WT(MADDR_Q_W, maddr_q.w) +DO_MSA__WD__WD_WT(MADDR_Q_W__DDT, maddr_q.w) +DO_MSA__WD__WS_WD(MADDR_Q_W__DSD, maddr_q.w) DO_MSA__WD__WS_WT(MSUB_Q_H, msub_q.h) +DO_MSA__WD__WD_WT(MSUB_Q_H__DDT, msub_q.h) +DO_MSA__WD__WS_WD(MSUB_Q_H__DSD, msub_q.h) DO_MSA__WD__WS_WT(MSUB_Q_W, msub_q.w) +DO_MSA__WD__WD_WT(MSUB_Q_W__DDT, msub_q.w) +DO_MSA__WD__WS_WD(MSUB_Q_W__DSD, msub_q.w) DO_MSA__WD__WS_WT(MSUBR_Q_H, msubr_q.h) +DO_MSA__WD__WD_WT(MSUBR_Q_H__DDT, msubr_q.h) +DO_MSA__WD__WS_WD(MSUBR_Q_H__DSD, msubr_q.h) DO_MSA__WD__WS_WT(MSUBR_Q_W, msubr_q.w) +DO_MSA__WD__WD_WT(MSUBR_Q_W__DDT, msubr_q.w) +DO_MSA__WD__WS_WD(MSUBR_Q_W__DSD, msubr_q.w) DO_MSA__WD__WS_WT(MUL_Q_H, mul_q.h) DO_MSA__WD__WS_WT(MUL_Q_W, mul_q.w) diff --git a/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_madd_q_h.c b/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_madd_q_h.c new file mode 100644 index 0000000000..29a2990011 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_madd_q_h.c @@ -0,0 +1,216 @@ +/* + * Test program for MSA instruction MADD_Q.H + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + 3 * (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *isa_ase_name = "MSA"; + char *group_name = "Fixed Multiply"; + char *instruction_name = "MADD_Q.H"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xfffefffefffefffeULL, 0xfffefffefffefffeULL, }, + { 0xfffefffdfffefffeULL, 0xfffdfffefffefffdULL, }, + { 0xfffdfffdfffdfffdULL, 0xfffdfffdfffdfffdULL, }, + { 0xfffdfffdfffdfffdULL, 0xfffdfffdfffdfffdULL, }, /* 8 */ + { 0xfffdfffdfffdfffdULL, 0xfffdfffdfffdfffdULL, }, + { 0xfffdfffdfffdfffdULL, 0xfffdfffdfffdfffdULL, }, + { 0xfffdfffdfffdfffdULL, 0xfffdfffdfffdfffdULL, }, + { 0xfffdfffdfffdfffdULL, 0xfffdfffdfffdfffdULL, }, + { 0xfffdfffdfffdfffdULL, 0xfffdfffdfffdfffdULL, }, + { 0xfffdfffdfffdfffdULL, 0xfffdfffdfffdfffdULL, }, + { 0xfffdfffdfffdfffdULL, 0xfffdfffdfffdfffdULL, }, + { 0xfffdfffdfffdfffdULL, 0xfffdfffdfffdfffdULL, }, /* 16 */ + { 0xfffdfffdfffdfffdULL, 0xfffdfffdfffdfffdULL, }, + { 0x38e138e138e138e1ULL, 0x38e138e138e138e1ULL, }, + { 0xfffdfffdfffdfffdULL, 0xfffdfffdfffdfffdULL, }, + { 0x221f221f221f221fULL, 0x221f221f221f221fULL, }, + { 0xfffcfffcfffcfffcULL, 0xfffcfffcfffcfffcULL, }, + { 0x12f2da0f4bd712f2ULL, 0xda0f4bd712f2da0fULL, }, + { 0xfffbfffcfffcfffbULL, 0xfffcfffcfffbfffcULL, }, + { 0xfffafffbfffbfffaULL, 0xfffbfffbfffafffbULL, }, /* 24 */ + { 0xfffafffbfffbfffaULL, 0xfffbfffbfffafffbULL, }, + { 0xc716c717c717c716ULL, 0xc717c717c716c717ULL, }, + { 0xfff9fffafffafff9ULL, 0xfffafffafff9fffaULL, }, + { 0xddd6ddd7ddd7ddd6ULL, 0xddd7ddd7ddd6ddd7ULL, }, + { 0xfff7fff8fff8fff7ULL, 0xfff8fff8fff7fff8ULL, }, + { 0xed0025e4b41ded00ULL, 0x25e4b41ded0025e4ULL, }, + { 0xfff5fff6fff6fff5ULL, 0xfff6fff6fff5fff6ULL, }, + { 0xfff5fff6fff6fff5ULL, 0xfff6fff6fff5fff6ULL, }, /* 32 */ + { 0xfff5fff6fff6fff5ULL, 0xfff6fff6fff5fff6ULL, }, + { 0x2217221822182217ULL, 0x2218221822172218ULL, }, + { 0xfff4fff5fff5fff4ULL, 0xfff5fff5fff4fff5ULL, }, + { 0x146f14701470146fULL, 0x14701470146f1470ULL, }, + { 0xfff3fff4fff4fff3ULL, 0xfff4fff4fff3fff4ULL, }, + { 0x0b53e9322d770b53ULL, 0xe9322d770b53e932ULL, }, + { 0xfff2fff3fff3fff2ULL, 0xfff3fff3fff2fff3ULL, }, + { 0xfff1fff2fff2fff1ULL, 0xfff2fff2fff1fff2ULL, }, /* 40 */ + { 0xfff1fff2fff2fff1ULL, 0xfff2fff2fff1fff2ULL, }, + { 0xddceddcfddcfddceULL, 0xddcfddcfddceddcfULL, }, + { 0xffeffff0fff0ffefULL, 0xfff0fff0ffeffff0ULL, }, + { 0xeb73eb74eb74eb73ULL, 0xeb74eb74eb73eb74ULL, }, + { 0xffedffeeffeeffedULL, 0xffeeffeeffedffeeULL, }, + { 0xf48c16afd26af48cULL, 0x16afd26af48c16afULL, }, + { 0xffecffedffecffecULL, 0xffedffecffecffedULL, }, + { 0xffecffecffecffecULL, 0xffecffecffecffecULL, }, /* 48 */ + { 0xffecffecffecffecULL, 0xffecffecffecffecULL, }, + { 0x12e2d9ff4bc712e2ULL, 0xd9ff4bc712e2d9ffULL, }, + { 0xffebffebffecffebULL, 0xffebffecffebffebULL, }, + { 0x0b4be9292d6f0b4bULL, 0xe9292d6f0b4be929ULL, }, + { 0xffeaffeaffebffeaULL, 0xffeaffebffeaffeaULL, }, + { 0x063c1932650f063cULL, 0x1932650f063c1932ULL, }, + { 0xffe9ffe9ffebffe9ULL, 0xffe9ffebffe9ffe9ULL, }, + { 0xffe8ffe9ffeaffe8ULL, 0xffe9ffeaffe8ffe9ULL, }, /* 56 */ + { 0xffe8ffe9ffeaffe8ULL, 0xffe9ffeaffe8ffe9ULL, }, + { 0xecf125d6b40fecf1ULL, 0x25d6b40fecf125d6ULL, }, + { 0xffe6ffe8ffe8ffe6ULL, 0xffe8ffe8ffe6ffe8ULL, }, + { 0xf48516a9d264f485ULL, 0x16a9d264f48516a9ULL, }, + { 0xffe5ffe7ffe6ffe5ULL, 0xffe7ffe6ffe5ffe7ULL, }, + { 0xf992e69e9ac2f992ULL, 0xe69e9ac2f992e69eULL, }, + { 0xffe3ffe7ffe4ffe3ULL, 0xffe7ffe4ffe3ffe7ULL, }, + { 0x6f9c04dd0ca138aaULL, 0x2c5200e6ffe731d8ULL, }, /* 64 */ + { 0x739604c9251a12b8ULL, 0x377dfac7ffa6fe02ULL, }, + { 0x7fff14cc0ef4c520ULL, 0x4ef5f5b700a7e6d8ULL, }, + { 0x171110672cabb158ULL, 0x0bc4eb2201aef931ULL, }, + { 0x1b0b105345248b66ULL, 0x16efe503016dc55bULL, }, + { 0x1b2f10537427a4c0ULL, 0x19be0a1804f3fb27ULL, }, + { 0x1df71014499cd899ULL, 0x1fa528c6f6de1330ULL, }, + { 0x1a3a10257fffe5d0ULL, 0x0ebe68e9e8780024ULL, }, + { 0x6860202869d99838ULL, 0x263663d9e979e8faULL, }, /* 72 */ + { 0x6b281fe93f4ecc11ULL, 0x2c1d7fffdb640103ULL, }, + { 0x7fff539865cb3619ULL, 0x38847fff139c0bc0ULL, }, + { 0x369a456c32245120ULL, 0x15027fff4d19033dULL, }, + { 0xcdac41074fdb3d58ULL, 0xd1d1756a4e201596ULL, }, + { 0xc9ef41187fff4a8fULL, 0xc0ea7fff3fba028aULL, }, + { 0x808a32ec4c586596ULL, 0x9d687fff7937fa07ULL, }, + { 0xe31436ce7fff6c79ULL, 0x030a7fff7fff00c4ULL, }, + { 0xfe192c037fff7fffULL, 0x04d47fff7e7a0049ULL, }, /* 80 */ + { 0xfe292c257fff4707ULL, 0x058b3b197fff0078ULL, }, + { 0xff5c101739ce0661ULL, 0x074420c72b2a009aULL, }, + { 0xfecc12e4645704e6ULL, 0x00ca02430de90076ULL, }, + { 0xffeb0f2b7fff0829ULL, 0x014002760dbe002cULL, }, + { 0xffeb0f367fff0487ULL, 0x016f012210050048ULL, }, + { 0xfff8058b39ce0068ULL, 0x01e100a00567005cULL, }, + { 0xfff006826457004fULL, 0x0034000b01bd0046ULL, }, + { 0xfffe05397fff0083ULL, 0x0052000b01b7001aULL, }, /* 88 */ + { 0xfffe053d7fff0048ULL, 0x005e000501ff002aULL, }, + { 0xffff01e839ce0006ULL, 0x007b000200ac0036ULL, }, + { 0xfffe023d64570004ULL, 0x000d000000370029ULL, }, + { 0xffff01cc7fff0006ULL, 0x001400000036000fULL, }, + { 0xffff01cd7fff0003ULL, 0x00160000003e0018ULL, }, + { 0xffff00a839ce0000ULL, 0x001c00000014001eULL, }, + { 0xfffe00c564570000ULL, 0x0003000000060017ULL, }, + { 0xffff009e7fff0000ULL, 0x0004000000050008ULL, }, /* 96 */ + { 0xffff007e7fff0000ULL, 0x0006000000040003ULL, }, + { 0xffff00657fff0000ULL, 0x0009000000030001ULL, }, + { 0xffff00517fff0000ULL, 0x000e000000020000ULL, }, + { 0xffff00517fff0000ULL, 0x0010000000020000ULL, }, + { 0xffff00517fff0000ULL, 0x0012000000020000ULL, }, + { 0xffff00517fff0000ULL, 0x0014000000020000ULL, }, + { 0xffff00517fff0000ULL, 0x0016000000020000ULL, }, + { 0xffff001d39ce0000ULL, 0x001c000000000000ULL, }, /* 104 */ + { 0xffff000a1a1b0000ULL, 0x0024000000000000ULL, }, + { 0xffff00030bca0000ULL, 0x002f000000000000ULL, }, + { 0xffff000105530000ULL, 0x003d000000000000ULL, }, + { 0xfffe0001093d0000ULL, 0x0006000000000000ULL, }, + { 0xfffc000110090000ULL, 0x0000000000000000ULL, }, + { 0xfff800011bd50000ULL, 0x0000000000000000ULL, }, + { 0xfff0000130500000ULL, 0x0000000000000000ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MADD_Q_H(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MADD_Q_H(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MADD_Q_H__DDT(b128_random[i], b128_random[j], + b128_result[ + ((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + ((RANDOM_INPUTS_SHORT_COUNT) * + (RANDOM_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MADD_Q_H__DSD(b128_random[i], b128_random[j], + b128_result[ + ((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + (2 * (RANDOM_INPUTS_SHORT_COUNT) * + (RANDOM_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results_128(isa_ase_name, group_name, instruction_name, + TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_madd_q_w.c b/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_madd_q_w.c new file mode 100644 index 0000000000..529d60d1e9 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_madd_q_w.c @@ -0,0 +1,216 @@ +/* + * Test program for MSA instruction MADD_Q.W + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + 3 * (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *isa_ase_name = "MSA"; + char *group_name = "Fixed Multiply"; + char *instruction_name = "MADD_Q.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xfffffffefffffffeULL, 0xfffffffefffffffeULL, }, + { 0xfffffffefffffffeULL, 0xfffffffdfffffffeULL, }, + { 0xfffffffdfffffffdULL, 0xfffffffdfffffffdULL, }, + { 0xfffffffdfffffffdULL, 0xfffffffdfffffffdULL, }, /* 8 */ + { 0xfffffffdfffffffdULL, 0xfffffffdfffffffdULL, }, + { 0xfffffffdfffffffdULL, 0xfffffffdfffffffdULL, }, + { 0xfffffffdfffffffdULL, 0xfffffffdfffffffdULL, }, + { 0xfffffffdfffffffdULL, 0xfffffffdfffffffdULL, }, + { 0xfffffffdfffffffdULL, 0xfffffffdfffffffdULL, }, + { 0xfffffffdfffffffdULL, 0xfffffffdfffffffdULL, }, + { 0xfffffffdfffffffdULL, 0xfffffffdfffffffdULL, }, + { 0xfffffffdfffffffdULL, 0xfffffffdfffffffdULL, }, /* 16 */ + { 0xfffffffdfffffffdULL, 0xfffffffdfffffffdULL, }, + { 0x38e38e3638e38e36ULL, 0x38e38e3638e38e36ULL, }, + { 0xfffffffcfffffffcULL, 0xfffffffcfffffffcULL, }, + { 0x2222221e2222221eULL, 0x2222221e2222221eULL, }, + { 0xfffffffbfffffffbULL, 0xfffffffbfffffffbULL, }, + { 0x12f684b94bda12f2ULL, 0xda12f68012f684b9ULL, }, + { 0xfffffffbfffffffbULL, 0xfffffffbfffffffbULL, }, + { 0xfffffffafffffffaULL, 0xfffffffafffffffaULL, }, /* 24 */ + { 0xfffffffafffffffaULL, 0xfffffffafffffffaULL, }, + { 0xc71c71c0c71c71c0ULL, 0xc71c71c0c71c71c0ULL, }, + { 0xfffffff8fffffff8ULL, 0xfffffff8fffffff8ULL, }, + { 0xddddddd5ddddddd5ULL, 0xddddddd5ddddddd5ULL, }, + { 0xfffffff6fffffff6ULL, 0xfffffff6fffffff6ULL, }, + { 0xed097b38b425ecffULL, 0x25ed0970ed097b38ULL, }, + { 0xfffffff5fffffff4ULL, 0xfffffff4fffffff5ULL, }, + { 0xfffffff5fffffff4ULL, 0xfffffff4fffffff5ULL, }, /* 32 */ + { 0xfffffff5fffffff4ULL, 0xfffffff4fffffff5ULL, }, + { 0x2222221722222216ULL, 0x2222221622222217ULL, }, + { 0xfffffff4fffffff3ULL, 0xfffffff3fffffff4ULL, }, + { 0x147ae13c147ae13bULL, 0x147ae13b147ae13cULL, }, + { 0xfffffff4fffffff3ULL, 0xfffffff3fffffff4ULL, }, + { 0x0b60b5ff2d82d821ULL, 0xe93e93dc0b60b5ffULL, }, + { 0xfffffff3fffffff3ULL, 0xfffffff3fffffff3ULL, }, + { 0xfffffff2fffffff2ULL, 0xfffffff2fffffff2ULL, }, /* 40 */ + { 0xfffffff2fffffff2ULL, 0xfffffff2fffffff2ULL, }, + { 0xddddddcfddddddcfULL, 0xddddddcfddddddcfULL, }, + { 0xfffffff0fffffff0ULL, 0xfffffff0fffffff0ULL, }, + { 0xeb851ea8eb851ea8ULL, 0xeb851ea8eb851ea8ULL, }, + { 0xffffffefffffffefULL, 0xffffffefffffffefULL, }, + { 0xf49f49e3d27d27c1ULL, 0x16c16c05f49f49e3ULL, }, + { 0xffffffeeffffffeeULL, 0xffffffeeffffffeeULL, }, + { 0xffffffeeffffffeeULL, 0xffffffedffffffeeULL, }, /* 48 */ + { 0xffffffeeffffffeeULL, 0xffffffedffffffeeULL, }, + { 0x12f684ac4bda12e5ULL, 0xda12f67212f684acULL, }, + { 0xffffffeeffffffeeULL, 0xffffffecffffffeeULL, }, + { 0x0b60b5f92d82d81cULL, 0xe93e93d50b60b5f9ULL, }, + { 0xffffffedffffffeeULL, 0xffffffebffffffedULL, }, + { 0x06522c2c6522c3e1ULL, 0x1948b0e706522c2cULL, }, + { 0xffffffecffffffeeULL, 0xffffffeaffffffecULL, }, + { 0xffffffebffffffedULL, 0xffffffeaffffffebULL, }, /* 56 */ + { 0xffffffebffffffedULL, 0xffffffeaffffffebULL, }, + { 0xed097b2db425ecf6ULL, 0x25ed0965ed097b2dULL, }, + { 0xffffffeaffffffebULL, 0xffffffe9ffffffeaULL, }, + { 0xf49f49ded27d27bdULL, 0x16c16c00f49f49deULL, }, + { 0xffffffe9ffffffeaULL, 0xffffffe9ffffffe9ULL, }, + { 0xf9add3a99add3bf7ULL, 0xe6b74eecf9add3a9ULL, }, + { 0xffffffe8ffffffe8ULL, 0xffffffe8ffffffe8ULL, }, + { 0x6fb7e8710cbdc0baULL, 0x2c6b142e000499ecULL, }, /* 64 */ + { 0x73b239bf253787bbULL, 0x379780d7ffc424b2ULL, }, + { 0x7fffffff0f12777aULL, 0x4f10996a00c57ee6ULL, }, + { 0x1713a7162cca6b1fULL, 0x0be04dd301cca255ULL, }, + { 0x1b0df86445443220ULL, 0x170cba7c018c2d1bULL, }, + { 0x1b323a657448a831ULL, 0x19dc4690051313a9ULL, }, + { 0x1dfa85ec49be7952ULL, 0x1fc3e11af6fe2ffbULL, }, + { 0x1a3e24c87fffffffULL, 0x0edd19b6e8983fd8ULL, }, + { 0x6863454e69daefbeULL, 0x26563249e9999a0cULL, }, /* 72 */ + { 0x6b2b90d53f50c0dfULL, 0x2c3dccd3db84b65eULL, }, + { 0x7fffffff65cdd2a2ULL, 0x38a5553713bd77aaULL, }, + { 0x369baa383226e26fULL, 0x1523c32e4d39d083ULL, }, + { 0xcdaf514f4fded614ULL, 0xd1f377974e40f3f2ULL, }, + { 0xc9f2f02b7fffffffULL, 0xc10cb0333fdb03cfULL, }, + { 0x808e9a644c590fccULL, 0x9d8b1e2a79575ca8ULL, }, + { 0xe31932487fffffffULL, 0x032ce40b7fffffffULL, }, + { 0xfe196fe57fffffffULL, 0x050bc0117e7bb00bULL, }, /* 80 */ + { 0xfe299f467fffffffULL, 0x05cb2b207fffffffULL, }, + { 0xff5d018239cf8b7fULL, 0x0798e21e2b2b2513ULL, }, + { 0xfecdfe1e645a7d99ULL, 0x00d3dcf00dea608dULL, }, + { 0xffebe0507fffffffULL, 0x0150aaf30dc02967ULL, }, + { 0xffec8bad7fffffffULL, 0x01828e9310087db0ULL, }, + { 0xfff9423b39cf8b7fULL, 0x01fae4ad056841b8ULL, }, + { 0xfff35804645a7d99ULL, 0x003737ba01be3861ULL, }, + { 0xffff2aee7fffffffULL, 0x0057bed401b8eeafULL, }, /* 88 */ + { 0xffff32047fffffffULL, 0x0064bf7c02021ffbULL, }, + { 0xffffb89f39cf8b7fULL, 0x00841c7300ad6409ULL, }, + { 0xffff79fe645a7d99ULL, 0x000e642e0037e4a5ULL, }, + { 0xfffff72f7fffffffULL, 0x0016de7600373b15ULL, }, + { 0xfffff77a7fffffffULL, 0x001a420100406619ULL, }, + { 0xfffffd0b39cf8b7fULL, 0x00226e950015b801ULL, }, + { 0xfffffa72645a7d99ULL, 0x0003c03400070049ULL, }, + { 0xffffffa27fffffffULL, 0x0005f5d70006eb0bULL, }, /* 96 */ + { 0xfffffff97fffffffULL, 0x000978af0006d60eULL, }, + { 0xffffffff7fffffffULL, 0x000f0d050006c150ULL, }, + { 0xffffffff7fffffffULL, 0x0017eac30006acd1ULL, }, + { 0xffffffff7fffffffULL, 0x001b76100007c878ULL, }, + { 0xffffffff7fffffffULL, 0x001f87d000091335ULL, }, + { 0xffffffff7fffffffULL, 0x002433ef000a94d9ULL, }, + { 0xffffffff7fffffffULL, 0x0029914d000c5680ULL, }, + { 0xffffffff39cf8b7fULL, 0x003681f800042937ULL, }, /* 104 */ + { 0xffffffff1a1c28c3ULL, 0x004779e10001673fULL, }, + { 0xffffffff0bcae025ULL, 0x005dba1000007928ULL, }, + { 0xffffffff055376c1ULL, 0x007ae77c000028dcULL, }, + { 0xfffffffe093ed554ULL, 0x000d636d00000d2bULL, }, + { 0xfffffffc100c9463ULL, 0x0001755c0000043eULL, }, + { 0xfffffff81bdc128cULL, 0x000028ab0000015eULL, }, + { 0xfffffff0305c8babULL, 0x0000046e00000070ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MADD_Q_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MADD_Q_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MADD_Q_W__DDT(b128_random[i], b128_random[j], + b128_result[ + ((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + ((RANDOM_INPUTS_SHORT_COUNT) * + (RANDOM_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MADD_Q_W__DSD(b128_random[i], b128_random[j], + b128_result[ + ((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + (2 * (RANDOM_INPUTS_SHORT_COUNT) * + (RANDOM_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results_128(isa_ase_name, group_name, instruction_name, + TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_maddr_q_h.c b/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_maddr_q_h.c new file mode 100644 index 0000000000..a4713f2321 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_maddr_q_h.c @@ -0,0 +1,216 @@ +/* + * Test program for MSA instruction MADDR_Q.H + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + 3 * (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *isa_ase_name = "MSA"; + char *group_name = "Fixed Multiply"; + char *instruction_name = "MADDR_Q.H"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0001000100010001ULL, 0x0001000100010001ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000010000ULL, 0x0000000100000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0001000100010001ULL, 0x0001000100010001ULL, }, /* 16 */ + { 0x0001000100010001ULL, 0x0001000100010001ULL, }, + { 0x38e538e538e538e5ULL, 0x38e538e538e538e5ULL, }, + { 0x0001000100010001ULL, 0x0001000100010001ULL, }, + { 0x2224222422242224ULL, 0x2224222422242224ULL, }, + { 0x0002000200020002ULL, 0x0002000200020002ULL, }, + { 0x12f9da154bdd12f9ULL, 0xda154bdd12f9da15ULL, }, + { 0x0003000300020003ULL, 0x0003000200030003ULL, }, + { 0x0002000200010002ULL, 0x0002000100020002ULL, }, /* 24 */ + { 0x0002000200010002ULL, 0x0002000100020002ULL, }, + { 0xc71ec71ec71dc71eULL, 0xc71ec71dc71ec71eULL, }, + { 0x0001000100000001ULL, 0x0001000000010001ULL, }, + { 0xdddedddedddddddeULL, 0xdddedddddddedddeULL, }, + { 0x00000000ffff0000ULL, 0x0000ffff00000000ULL, }, + { 0xed0925edb425ed09ULL, 0x25edb425ed0925edULL, }, + { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, }, + { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, }, /* 32 */ + { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, }, + { 0x2222222322222222ULL, 0x2223222222222223ULL, }, + { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, }, + { 0x147b147c147b147bULL, 0x147c147b147b147cULL, }, + { 0x0000000100000000ULL, 0x0001000000000001ULL, }, + { 0x0b61e93f2d840b61ULL, 0xe93f2d840b61e93fULL, }, + { 0x0000000100000000ULL, 0x0001000000000001ULL, }, + { 0x0000000100000000ULL, 0x0001000000000001ULL, }, /* 40 */ + { 0x0000000100000000ULL, 0x0001000000000001ULL, }, + { 0xdddedddfdddedddeULL, 0xdddfdddedddedddfULL, }, + { 0x0000000100000000ULL, 0x0001000000000001ULL, }, + { 0xeb85eb86eb85eb85ULL, 0xeb86eb85eb85eb86ULL, }, + { 0x0000000100000000ULL, 0x0001000000000001ULL, }, + { 0xf49f16c2d27df49fULL, 0x16c2d27df49f16c2ULL, }, + { 0xffff00000000ffffULL, 0x00000000ffff0000ULL, }, + { 0xffff00000001ffffULL, 0x00000001ffff0000ULL, }, /* 48 */ + { 0xffff00000001ffffULL, 0x00000001ffff0000ULL, }, + { 0x12f6da134bdc12f6ULL, 0xda134bdc12f6da13ULL, }, + { 0xffff00000002ffffULL, 0x00000002ffff0000ULL, }, + { 0x0b60e93e2d860b60ULL, 0xe93e2d860b60e93eULL, }, + { 0xffffffff0003ffffULL, 0xffff0003ffffffffULL, }, + { 0x0651194765270651ULL, 0x1947652706511947ULL, }, + { 0xfffffffe0004ffffULL, 0xfffe0004fffffffeULL, }, + { 0xfffffffe0003ffffULL, 0xfffe0003fffffffeULL, }, /* 56 */ + { 0xfffffffe0003ffffULL, 0xfffe0003fffffffeULL, }, + { 0xed0925ecb428ed09ULL, 0x25ecb428ed0925ecULL, }, + { 0xffffffff0002ffffULL, 0xffff0002ffffffffULL, }, + { 0xf49e16c1d27ef49eULL, 0x16c1d27ef49e16c1ULL, }, + { 0xfffeffff0001fffeULL, 0xffff0001fffeffffULL, }, + { 0xf9ace6b69adef9acULL, 0xe6b69adef9ace6b6ULL, }, + { 0xfffeffff0001fffeULL, 0xffff0001fffeffffULL, }, + { 0x6fb804f50cbf38c5ULL, 0x2c6a0103000331f0ULL, }, /* 64 */ + { 0x73b204e2253812d4ULL, 0x3796fae5ffc2fe1aULL, }, + { 0x7fff14e60f13c53dULL, 0x4f0ff5d500c4e6f1ULL, }, + { 0x171210822ccab176ULL, 0x0bdeeb4001ccf94aULL, }, + { 0x1b0c106f45438b85ULL, 0x170ae522018bc574ULL, }, + { 0x1b30106f7447a4e0ULL, 0x19d90a380512fb41ULL, }, + { 0x1df8103049bdd8baULL, 0x1fc028e7f6fd134bULL, }, + { 0x1a3c10417fffe5f1ULL, 0x0eda690ae8970040ULL, }, + { 0x6862204569da985aULL, 0x265363fae999e917ULL, }, /* 72 */ + { 0x6b2a20063f50cc34ULL, 0x2c3a7fffdb840121ULL, }, + { 0x7fff53b565ce363dULL, 0x38a17fff13bd0bdfULL, }, + { 0x369a458932275144ULL, 0x15207fff4d3a035dULL, }, + { 0xcdad41254fde3d7dULL, 0xd1ef756a4e4215b6ULL, }, + { 0xc9f141367fff4ab4ULL, 0xc1097fff3fdc02abULL, }, + { 0x808c330a4c5865bbULL, 0x9d887fff7959fa29ULL, }, + { 0xe31636ed7fff6c9fULL, 0x032b7fff7fff00e7ULL, }, + { 0xfe192c1c7fff7fffULL, 0x05097fff7e7a0057ULL, }, /* 80 */ + { 0xfe292c3e7fff4707ULL, 0x05c83b1a7fff008fULL, }, + { 0xff5d102139cf0662ULL, 0x079520c82b2b00b8ULL, }, + { 0xfece12f0645904e7ULL, 0x00d302440dea008eULL, }, + { 0xffec0f357fff082bULL, 0x014f02780dc00035ULL, }, + { 0xffed0f417fff0488ULL, 0x0181012410080057ULL, }, + { 0xfff9059039cf0068ULL, 0x01f900a205680070ULL, }, + { 0xfff3068864590050ULL, 0x0037000b01be0056ULL, }, + { 0xffff053f7fff0085ULL, 0x0057000c01b90020ULL, }, /* 88 */ + { 0xffff05437fff004aULL, 0x0064000602020035ULL, }, + { 0x000001eb39cf0007ULL, 0x0083000300ad0044ULL, }, + { 0x0000024164590005ULL, 0x000e000000380034ULL, }, + { 0x000001cf7fff0008ULL, 0x0016000000370014ULL, }, + { 0x000001d07fff0004ULL, 0x0019000000400021ULL, }, + { 0x000000a939cf0000ULL, 0x002100000016002bULL, }, + { 0x000000c664590000ULL, 0x0004000000070021ULL, }, + { 0x0000009f7fff0000ULL, 0x000600000007000cULL, }, /* 96 */ + { 0x000000807fff0000ULL, 0x000a000000070005ULL, }, + { 0x000000677fff0000ULL, 0x0010000000070002ULL, }, + { 0x000000537fff0000ULL, 0x0019000000070001ULL, }, + { 0x000000537fff0000ULL, 0x001d000000080002ULL, }, + { 0x000000537fff0000ULL, 0x0021000000090003ULL, }, + { 0x000000537fff0000ULL, 0x00260000000a0005ULL, }, + { 0x000000537fff0000ULL, 0x002c0000000c0008ULL, }, + { 0x0000001e39cf0000ULL, 0x003a00000004000aULL, }, /* 104 */ + { 0x0000000b1a1c0000ULL, 0x004c00000001000dULL, }, + { 0x000000040bcb0000ULL, 0x0064000000000011ULL, }, + { 0x0000000105530000ULL, 0x0083000000000016ULL, }, + { 0x00000001093e0000ULL, 0x000e000000000011ULL, }, + { 0x00000001100b0000ULL, 0x000200000000000dULL, }, + { 0x000000011bd90000ULL, 0x000000000000000aULL, }, + { 0x0000000130570000ULL, 0x0000000000000008ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MADDR_Q_H(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MADDR_Q_H(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MADDR_Q_H__DDT(b128_random[i], b128_random[j], + b128_result[ + ((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + ((RANDOM_INPUTS_SHORT_COUNT) * + (RANDOM_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MADDR_Q_H__DSD(b128_random[i], b128_random[j], + b128_result[ + ((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + (2 * (RANDOM_INPUTS_SHORT_COUNT) * + (RANDOM_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results_128(isa_ase_name, group_name, instruction_name, + TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_maddr_q_w.c b/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_maddr_q_w.c new file mode 100644 index 0000000000..19eccbf5ba --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_maddr_q_w.c @@ -0,0 +1,216 @@ +/* + * Test program for MSA instruction MADDR_Q.W + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + 3 * (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *isa_ase_name = "MSA"; + char *group_name = "Fixed Multiply"; + char *instruction_name = "MADDR_Q.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000100000001ULL, 0x0000000100000001ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000001ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000100000001ULL, 0x0000000100000001ULL, }, /* 16 */ + { 0x0000000100000001ULL, 0x0000000100000001ULL, }, + { 0x38e38e3b38e38e3bULL, 0x38e38e3b38e38e3bULL, }, + { 0x0000000200000002ULL, 0x0000000200000002ULL, }, + { 0x2222222522222225ULL, 0x2222222522222225ULL, }, + { 0x0000000300000003ULL, 0x0000000300000003ULL, }, + { 0x12f684c14bda12faULL, 0xda12f68812f684c1ULL, }, + { 0x0000000400000003ULL, 0x0000000400000004ULL, }, + { 0x0000000300000002ULL, 0x0000000300000003ULL, }, /* 24 */ + { 0x0000000300000002ULL, 0x0000000300000003ULL, }, + { 0xc71c71cac71c71c9ULL, 0xc71c71cac71c71caULL, }, + { 0x0000000200000001ULL, 0x0000000200000002ULL, }, + { 0xdddddddfdddddddeULL, 0xdddddddfdddddddfULL, }, + { 0x0000000100000000ULL, 0x0000000100000001ULL, }, + { 0xed097b43b425ed0aULL, 0x25ed097ced097b43ULL, }, + { 0x0000000000000000ULL, 0x0000000100000000ULL, }, + { 0x0000000000000000ULL, 0x0000000100000000ULL, }, /* 32 */ + { 0x0000000000000000ULL, 0x0000000100000000ULL, }, + { 0x2222222322222223ULL, 0x2222222422222223ULL, }, + { 0x0000000000000000ULL, 0x0000000100000000ULL, }, + { 0x147ae148147ae148ULL, 0x147ae149147ae148ULL, }, + { 0x0000000000000000ULL, 0x0000000100000000ULL, }, + { 0x0b60b60c2d82d82eULL, 0xe93e93ea0b60b60cULL, }, + { 0x0000000100000000ULL, 0x0000000100000001ULL, }, + { 0x0000000100000000ULL, 0x0000000100000001ULL, }, /* 40 */ + { 0x0000000100000000ULL, 0x0000000100000001ULL, }, + { 0xdddddddfdddddddeULL, 0xdddddddfdddddddfULL, }, + { 0x0000000100000000ULL, 0x0000000100000001ULL, }, + { 0xeb851eb9eb851eb8ULL, 0xeb851eb9eb851eb9ULL, }, + { 0x0000000100000000ULL, 0x0000000100000001ULL, }, + { 0xf49f49f5d27d27d3ULL, 0x16c16c17f49f49f5ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000001ULL, 0x0000000000000000ULL, }, /* 48 */ + { 0x0000000000000001ULL, 0x0000000000000000ULL, }, + { 0x12f684be4bda12f8ULL, 0xda12f68512f684beULL, }, + { 0x0000000000000002ULL, 0x0000000000000000ULL, }, + { 0x0b60b60c2d82d830ULL, 0xe93e93e90b60b60cULL, }, + { 0x0000000000000003ULL, 0xffffffff00000000ULL, }, + { 0x06522c3f6522c3f7ULL, 0x1948b0fb06522c3fULL, }, + { 0x0000000000000004ULL, 0xffffffff00000000ULL, }, + { 0x0000000000000003ULL, 0xffffffff00000000ULL, }, /* 56 */ + { 0x0000000000000003ULL, 0xffffffff00000000ULL, }, + { 0xed097b43b425ed0cULL, 0x25ed097bed097b43ULL, }, + { 0x0000000000000002ULL, 0x0000000000000000ULL, }, + { 0xf49f49f5d27d27d4ULL, 0x16c16c17f49f49f5ULL, }, + { 0x0000000000000001ULL, 0x0000000000000000ULL, }, + { 0xf9add3c19add3c0eULL, 0xe6b74f04f9add3c1ULL, }, + { 0x0000000000000000ULL, 0x0000000100000000ULL, }, + { 0x6fb7e8890cbdc0d3ULL, 0x2c6b144700049a05ULL, }, /* 64 */ + { 0x73b239d7253787d5ULL, 0x379780f0ffc424ccULL, }, + { 0x7fffffff0f127795ULL, 0x4f10998300c57f01ULL, }, + { 0x1713a7162cca6b3bULL, 0x0be04ded01cca270ULL, }, + { 0x1b0df8644544323dULL, 0x170cba96018c2d37ULL, }, + { 0x1b323a657448a84fULL, 0x19dc46aa051313c6ULL, }, + { 0x1dfa85ed49be7970ULL, 0x1fc3e135f6fe3018ULL, }, + { 0x1a3e24ca7fffffffULL, 0x0edd19d1e8983ff6ULL, }, + { 0x6863455169daefbfULL, 0x26563264e9999a2bULL, }, /* 72 */ + { 0x6b2b90d93f50c0e0ULL, 0x2c3dccefdb84b67dULL, }, + { 0x7fffffff65cdd2a4ULL, 0x38a5555313bd77c9ULL, }, + { 0x369baa393226e271ULL, 0x1523c34a4d39d0a3ULL, }, + { 0xcdaf51504fded617ULL, 0xd1f377b44e40f412ULL, }, + { 0xc9f2f02d7fffffffULL, 0xc10cb0503fdb03f0ULL, }, + { 0x808e9a674c590fccULL, 0x9d8b1e4779575ccaULL, }, + { 0xe319324b7fffffffULL, 0x032ce4297fffffffULL, }, + { 0xfe196fe67fffffffULL, 0x050bc0417e7bb00bULL, }, /* 80 */ + { 0xfe299f487fffffffULL, 0x05cb2b577fffffffULL, }, + { 0xff5d018339cf8b80ULL, 0x0798e2662b2b2514ULL, }, + { 0xfecdfe20645a7d9bULL, 0x00d3dcf80dea608eULL, }, + { 0xffebe0517fffffffULL, 0x0150ab000dc02968ULL, }, + { 0xffec8baf7fffffffULL, 0x01828ea210087db2ULL, }, + { 0xfff9423c39cf8b80ULL, 0x01fae4c1056841b9ULL, }, + { 0xfff35806645a7d9bULL, 0x003737bc01be3862ULL, }, + { 0xffff2aee7fffffffULL, 0x0057bed801b8eeb0ULL, }, /* 88 */ + { 0xffff32047fffffffULL, 0x0064bf8102021ffcULL, }, + { 0xffffb89f39cf8b80ULL, 0x00841c7a00ad640aULL, }, + { 0xffff79fe645a7d9bULL, 0x000e642f0037e4a6ULL, }, + { 0xfffff7307fffffffULL, 0x0016de7800373b16ULL, }, + { 0xfffff77b7fffffffULL, 0x001a42040040661aULL, }, + { 0xfffffd0c39cf8b80ULL, 0x00226e990015b802ULL, }, + { 0xfffffa75645a7d9bULL, 0x0003c0350007004aULL, }, + { 0xffffffa37fffffffULL, 0x0005f5d90006eb0dULL, }, /* 96 */ + { 0xfffffffa7fffffffULL, 0x000978b30006d610ULL, }, + { 0x000000007fffffffULL, 0x000f0d0c0006c153ULL, }, + { 0x000000007fffffffULL, 0x0017eacf0006acd5ULL, }, + { 0x000000007fffffffULL, 0x001b761e0007c87dULL, }, + { 0x000000007fffffffULL, 0x001f87e00009133bULL, }, + { 0x000000007fffffffULL, 0x00243402000a94e0ULL, }, + { 0x000000007fffffffULL, 0x00299164000c5689ULL, }, + { 0x0000000039cf8b80ULL, 0x003682160004293bULL, }, /* 104 */ + { 0x000000001a1c28c4ULL, 0x00477a0900016741ULL, }, + { 0x000000000bcae026ULL, 0x005dba4500007929ULL, }, + { 0x00000000055376c2ULL, 0x007ae7c2000028ddULL, }, + { 0x00000000093ed557ULL, 0x000d637500000d2cULL, }, + { 0x00000000100c9469ULL, 0x0001755d0000043fULL, }, + { 0x000000001bdc1297ULL, 0x000028ac0000015eULL, }, + { 0x00000000305c8bbfULL, 0x0000046e00000071ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MADDR_Q_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MADDR_Q_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MADDR_Q_W__DDT(b128_random[i], b128_random[j], + b128_result[ + ((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + ((RANDOM_INPUTS_SHORT_COUNT) * + (RANDOM_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MADDR_Q_W__DSD(b128_random[i], b128_random[j], + b128_result[ + ((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + (2 * (RANDOM_INPUTS_SHORT_COUNT) * + (RANDOM_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results_128(isa_ase_name, group_name, instruction_name, + TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_msub_q_h.c b/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_msub_q_h.c new file mode 100644 index 0000000000..b584736ed1 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_msub_q_h.c @@ -0,0 +1,216 @@ +/* + * Test program for MSA instruction MSUB_Q.H + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + 3 * (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *isa_ase_name = "MSA"; + char *group_name = "Fixed Multiply"; + char *instruction_name = "MSUB_Q.H"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xfffefffefffefffeULL, 0xfffefffefffefffeULL, }, + { 0xfffefffefffefffeULL, 0xfffefffefffefffeULL, }, + { 0xfffdfffdfffdfffdULL, 0xfffdfffdfffdfffdULL, }, + { 0xfffdfffdfffdfffdULL, 0xfffdfffdfffdfffdULL, }, + { 0xfffcfffdfffcfffcULL, 0xfffdfffcfffcfffdULL, }, + { 0xfffcfffcfffcfffcULL, 0xfffcfffcfffcfffcULL, }, + { 0xfffcfffcfffcfffcULL, 0xfffcfffcfffcfffcULL, }, /* 8 */ + { 0xfffcfffcfffcfffcULL, 0xfffcfffcfffcfffcULL, }, + { 0xfffcfffcfffcfffcULL, 0xfffcfffcfffcfffcULL, }, + { 0xfffcfffcfffcfffcULL, 0xfffcfffcfffcfffcULL, }, + { 0xfffcfffcfffcfffcULL, 0xfffcfffcfffcfffcULL, }, + { 0xfffcfffcfffcfffcULL, 0xfffcfffcfffcfffcULL, }, + { 0xfffcfffcfffcfffcULL, 0xfffcfffcfffcfffcULL, }, + { 0xfffcfffcfffcfffcULL, 0xfffcfffcfffcfffcULL, }, + { 0xfffbfffbfffbfffbULL, 0xfffbfffbfffbfffbULL, }, /* 16 */ + { 0xfffbfffbfffbfffbULL, 0xfffbfffbfffbfffbULL, }, + { 0xc716c716c716c716ULL, 0xc716c716c716c716ULL, }, + { 0xfff9fff9fff9fff9ULL, 0xfff9fff9fff9fff9ULL, }, + { 0xddd6ddd6ddd6ddd6ULL, 0xddd6ddd6ddd6ddd6ULL, }, + { 0xfff8fff8fff8fff8ULL, 0xfff8fff8fff8fff8ULL, }, + { 0xed0125e4b41ced01ULL, 0x25e4b41ced0125e4ULL, }, + { 0xfff7fff6fff6fff7ULL, 0xfff6fff6fff7fff6ULL, }, + { 0xfff7fff6fff6fff7ULL, 0xfff6fff6fff7fff6ULL, }, /* 24 */ + { 0xfff7fff6fff6fff7ULL, 0xfff6fff6fff7fff6ULL, }, + { 0x38da38d938d938daULL, 0x38d938d938da38d9ULL, }, + { 0xfff6fff5fff5fff6ULL, 0xfff5fff5fff6fff5ULL, }, + { 0x2218221722172218ULL, 0x2217221722182217ULL, }, + { 0xfff6fff5fff5fff6ULL, 0xfff5fff5fff6fff5ULL, }, + { 0x12ecda084bcf12ecULL, 0xda084bcf12ecda08ULL, }, + { 0xfff6fff5fff5fff6ULL, 0xfff5fff5fff6fff5ULL, }, + { 0xfff5fff4fff4fff5ULL, 0xfff4fff4fff5fff4ULL, }, /* 32 */ + { 0xfff5fff4fff4fff5ULL, 0xfff4fff4fff5fff4ULL, }, + { 0xddd2ddd1ddd1ddd2ULL, 0xddd1ddd1ddd2ddd1ULL, }, + { 0xfff4fff3fff3fff4ULL, 0xfff3fff3fff4fff3ULL, }, + { 0xeb78eb77eb77eb78ULL, 0xeb77eb77eb78eb77ULL, }, + { 0xfff3fff2fff2fff3ULL, 0xfff2fff2fff3fff2ULL, }, + { 0xf49216b3d26ef492ULL, 0x16b3d26ef49216b3ULL, }, + { 0xfff2fff1fff1fff2ULL, 0xfff1fff1fff2fff1ULL, }, + { 0xfff2fff1fff1fff2ULL, 0xfff1fff1fff2fff1ULL, }, /* 40 */ + { 0xfff2fff1fff1fff2ULL, 0xfff1fff1fff2fff1ULL, }, + { 0x2214221322132214ULL, 0x2213221322142213ULL, }, + { 0xfff2fff1fff1fff2ULL, 0xfff1fff1fff2fff1ULL, }, + { 0x146d146c146c146dULL, 0x146c146c146d146cULL, }, + { 0xfff2fff1fff1fff2ULL, 0xfff1fff1fff2fff1ULL, }, + { 0x0b52e92f2d740b52ULL, 0xe92f2d740b52e92fULL, }, + { 0xfff1fff0fff1fff1ULL, 0xfff0fff1fff1fff0ULL, }, + { 0xfff0fff0fff0fff0ULL, 0xfff0fff0fff0fff0ULL, }, /* 48 */ + { 0xfff0fff0fff0fff0ULL, 0xfff0fff0fff0fff0ULL, }, + { 0xecf925dcb414ecf9ULL, 0x25dcb414ecf925dcULL, }, + { 0xffefffefffeeffefULL, 0xffefffeeffefffefULL, }, + { 0xf48e16b0d26af48eULL, 0x16b0d26af48e16b0ULL, }, + { 0xffeeffeeffedffeeULL, 0xffeeffedffeeffeeULL, }, + { 0xf99be6a59ac8f99bULL, 0xe6a59ac8f99be6a5ULL, }, + { 0xffedffedffebffedULL, 0xffedffebffedffedULL, }, + { 0xffedffecffebffedULL, 0xffecffebffedffecULL, }, /* 56 */ + { 0xffedffecffebffedULL, 0xffecffebffedffecULL, }, + { 0x12e3d9fe4bc512e3ULL, 0xd9fe4bc512e3d9feULL, }, + { 0xffedffebffebffedULL, 0xffebffebffedffebULL, }, + { 0x0b4de9292d6e0b4dULL, 0xe9292d6e0b4de929ULL, }, + { 0xffecffeaffebffecULL, 0xffeaffebffecffeaULL, }, + { 0x063e1932650e063eULL, 0x1932650e063e1932ULL, }, + { 0xffecffe8ffebffecULL, 0xffe8ffebffecffe8ULL, }, + { 0x9032faf1f32dc724ULL, 0xd37cfee8ffe7cdf6ULL, }, /* 64 */ + { 0x8c37fb04dab3ed15ULL, 0xc8500506002701cbULL, }, + { 0x8000eb00f0d83aacULL, 0xb0d70a15ff2518f4ULL, }, + { 0xe8edef64d3204e73ULL, 0xf40714a9fe1d069aULL, }, + { 0xe4f2ef77baa67464ULL, 0xe8db1ac7fe5d3a6fULL, }, + { 0xe4cdef768ba25b09ULL, 0xe60bf5b1fad604a2ULL, }, + { 0xe204efb4b62c272fULL, 0xe023d70208eaec98ULL, }, + { 0xe5c0efa2800019f7ULL, 0xf10996de174fffa3ULL, }, + { 0x9799df9e9625678eULL, 0xd9909bed164d16ccULL, }, /* 72 */ + { 0x94d0dfdcc0af33b4ULL, 0xd3a880002461fec2ULL, }, + { 0x8000ac2c9a31c9abULL, 0xc7408000ec28f404ULL, }, + { 0xc964ba57cdd7aea3ULL, 0xeac18000b2aafc86ULL, }, + { 0x3251bebbb01fc26aULL, 0x2df18a94b1a2ea2cULL, }, + { 0x360dbea98000b532ULL, 0x3ed78000c007fd37ULL, }, + { 0x7f71ccd4b3a69a2aULL, 0x62588000868905b9ULL, }, + { 0x1ce6c8f180009346ULL, 0xfcb580008000fefbULL, }, + { 0x37e5be19a862dbafULL, 0xfea58b5e8000fe57ULL, }, /* 80 */ + { 0x39c0be4bdd7bcb85ULL, 0xfed88000953fff6aULL, }, + { 0x5f7d948aca8d9bc1ULL, 0xff3480008000ff95ULL, }, + { 0x0bb4a742f1e1847fULL, 0xfe7e80008000ff7cULL, }, + { 0x16a395c8f655d6c0ULL, 0xff618b5e8000ff29ULL, }, + { 0x1763961afc30c464ULL, 0xff788000953fffb4ULL, }, + { 0x26ab8000fa188e23ULL, 0xffa280008000ffcaULL, }, + { 0x04bd964dfe708000ULL, 0xff4e80008000ffbdULL, }, + { 0x092a817dfeeed540ULL, 0xffb68b5e8000ff93ULL, }, /* 88 */ + { 0x097881deff94c239ULL, 0xffc08000953fffd9ULL, }, + { 0x0fa88000ff5889feULL, 0xffd380008000ffe4ULL, }, + { 0x01eb964dffd38000ULL, 0xffaa80008000ffddULL, }, + { 0x03b5817dffe1d540ULL, 0xffdc8b5e8000ffc7ULL, }, + { 0x03d481defff3c239ULL, 0xffe18000953fffebULL, }, + { 0x06548000ffeb89feULL, 0xffea80008000fff1ULL, }, + { 0x00c6964dfffa8000ULL, 0xffd680008000ffedULL, }, + { 0x017e817dfffbd540ULL, 0xffee8b5e8000ffe1ULL, }, /* 96 */ + { 0x02e28000fffcf1b8ULL, 0xfff895b98000ffcdULL, }, + { 0x05938000fffdfb3aULL, 0xfffc9f298000ffadULL, }, + { 0x0ac88000fffdfe67ULL, 0xfffea7c28000ff79ULL, }, + { 0x0b238063fffefdb0ULL, 0xfffe8000953fffd0ULL, }, + { 0x0b8180c5fffffca8ULL, 0xfffe8000a6f7ffefULL, }, + { 0x0be28127fffffb2bULL, 0xfffe8000b5befffaULL, }, + { 0x0c478189fffff904ULL, 0xfffe8000c211fffdULL, }, + { 0x144c8000fffef2a8ULL, 0xfffe80009905fffdULL, }, /* 104 */ + { 0x218f8000fffce682ULL, 0xfffe80008000fffdULL, }, + { 0x377d8000fff9cf4eULL, 0xfffe80008000fffdULL, }, + { 0x5bc08000fff5a2fbULL, 0xfffe80008000fffdULL, }, + { 0x0b3f964dfffd8d66ULL, 0xfffc80008000fffcULL, }, + { 0x0160a8b7ffff8000ULL, 0xfff880008000fffbULL, }, + { 0x002bb7ecffff8000ULL, 0xfff080008000fff9ULL, }, + { 0x0005c47affff8000ULL, 0xffe180008000fff7ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MSUB_Q_H(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MSUB_Q_H(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MSUB_Q_H__DDT(b128_random[i], b128_random[j], + b128_result[ + ((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + ((RANDOM_INPUTS_SHORT_COUNT) * + (RANDOM_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MSUB_Q_H__DSD(b128_random[i], b128_random[j], + b128_result[ + ((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + (2 * (RANDOM_INPUTS_SHORT_COUNT) * + (RANDOM_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results_128(isa_ase_name, group_name, instruction_name, + TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_msub_q_w.c b/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_msub_q_w.c new file mode 100644 index 0000000000..56191924a1 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_msub_q_w.c @@ -0,0 +1,216 @@ +/* + * Test program for MSA instruction MSUB_Q.W + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + 3 * (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *isa_ase_name = "MSA"; + char *group_name = "Fixed Multiply"; + char *instruction_name = "MSUB_Q.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xfffffffefffffffeULL, 0xfffffffefffffffeULL, }, + { 0xfffffffefffffffeULL, 0xfffffffefffffffeULL, }, + { 0xfffffffdfffffffdULL, 0xfffffffdfffffffdULL, }, + { 0xfffffffdfffffffdULL, 0xfffffffdfffffffdULL, }, + { 0xfffffffcfffffffcULL, 0xfffffffdfffffffcULL, }, + { 0xfffffffcfffffffcULL, 0xfffffffcfffffffcULL, }, + { 0xfffffffcfffffffcULL, 0xfffffffcfffffffcULL, }, /* 8 */ + { 0xfffffffcfffffffcULL, 0xfffffffcfffffffcULL, }, + { 0xfffffffcfffffffcULL, 0xfffffffcfffffffcULL, }, + { 0xfffffffcfffffffcULL, 0xfffffffcfffffffcULL, }, + { 0xfffffffcfffffffcULL, 0xfffffffcfffffffcULL, }, + { 0xfffffffcfffffffcULL, 0xfffffffcfffffffcULL, }, + { 0xfffffffcfffffffcULL, 0xfffffffcfffffffcULL, }, + { 0xfffffffcfffffffcULL, 0xfffffffcfffffffcULL, }, + { 0xfffffffbfffffffbULL, 0xfffffffbfffffffbULL, }, /* 16 */ + { 0xfffffffbfffffffbULL, 0xfffffffbfffffffbULL, }, + { 0xc71c71c1c71c71c1ULL, 0xc71c71c1c71c71c1ULL, }, + { 0xfffffffafffffffaULL, 0xfffffffafffffffaULL, }, + { 0xddddddd7ddddddd7ULL, 0xddddddd7ddddddd7ULL, }, + { 0xfffffff9fffffff9ULL, 0xfffffff9fffffff9ULL, }, + { 0xed097b3ab425ed01ULL, 0x25ed0973ed097b3aULL, }, + { 0xfffffff7fffffff7ULL, 0xfffffff7fffffff7ULL, }, + { 0xfffffff7fffffff7ULL, 0xfffffff7fffffff7ULL, }, /* 24 */ + { 0xfffffff7fffffff7ULL, 0xfffffff7fffffff7ULL, }, + { 0x38e38e3038e38e30ULL, 0x38e38e3038e38e30ULL, }, + { 0xfffffff7fffffff7ULL, 0xfffffff7fffffff7ULL, }, + { 0x2222221922222219ULL, 0x2222221922222219ULL, }, + { 0xfffffff7fffffff7ULL, 0xfffffff7fffffff7ULL, }, + { 0x12f684b44bda12edULL, 0xda12f67c12f684b4ULL, }, + { 0xfffffff6fffffff7ULL, 0xfffffff7fffffff6ULL, }, + { 0xfffffff5fffffff6ULL, 0xfffffff6fffffff5ULL, }, /* 32 */ + { 0xfffffff5fffffff6ULL, 0xfffffff6fffffff5ULL, }, + { 0xddddddd2ddddddd3ULL, 0xddddddd3ddddddd2ULL, }, + { 0xfffffff4fffffff5ULL, 0xfffffff5fffffff4ULL, }, + { 0xeb851eabeb851eacULL, 0xeb851eaceb851eabULL, }, + { 0xfffffff2fffffff3ULL, 0xfffffff3fffffff2ULL, }, + { 0xf49f49e6d27d27c4ULL, 0x16c16c09f49f49e6ULL, }, + { 0xfffffff1fffffff1ULL, 0xfffffff1fffffff1ULL, }, + { 0xfffffff1fffffff1ULL, 0xfffffff1fffffff1ULL, }, /* 40 */ + { 0xfffffff1fffffff1ULL, 0xfffffff1fffffff1ULL, }, + { 0x2222221322222213ULL, 0x2222221322222213ULL, }, + { 0xfffffff1fffffff1ULL, 0xfffffff1fffffff1ULL, }, + { 0x147ae138147ae138ULL, 0x147ae138147ae138ULL, }, + { 0xfffffff0fffffff0ULL, 0xfffffff0fffffff0ULL, }, + { 0x0b60b5fb2d82d81dULL, 0xe93e93d90b60b5fbULL, }, + { 0xffffffefffffffefULL, 0xffffffefffffffefULL, }, + { 0xffffffeeffffffeeULL, 0xffffffefffffffeeULL, }, /* 48 */ + { 0xffffffeeffffffeeULL, 0xffffffefffffffeeULL, }, + { 0xed097b2fb425ecf6ULL, 0x25ed0969ed097b2fULL, }, + { 0xffffffecffffffecULL, 0xffffffeeffffffecULL, }, + { 0xf49f49e0d27d27bdULL, 0x16c16c04f49f49e0ULL, }, + { 0xffffffebffffffeaULL, 0xffffffedffffffebULL, }, + { 0xf9add3ab9add3bf6ULL, 0xe6b74ef0f9add3abULL, }, + { 0xffffffeaffffffe8ULL, 0xffffffecffffffeaULL, }, + { 0xffffffeaffffffe8ULL, 0xffffffebffffffeaULL, }, /* 56 */ + { 0xffffffeaffffffe8ULL, 0xffffffebffffffeaULL, }, + { 0x12f684a74bda12deULL, 0xda12f66f12f684a7ULL, }, + { 0xffffffe9ffffffe8ULL, 0xffffffeaffffffe9ULL, }, + { 0x0b60b5f42d82d815ULL, 0xe93e93d20b60b5f4ULL, }, + { 0xffffffe8ffffffe7ULL, 0xffffffe8ffffffe8ULL, }, + { 0x06522c276522c3d9ULL, 0x1948b0e406522c27ULL, }, + { 0xffffffe7ffffffe7ULL, 0xffffffe7ffffffe7ULL, }, + { 0x9048175df3423f14ULL, 0xd394eba0fffb65e2ULL, }, /* 64 */ + { 0x8c4dc60edac87812ULL, 0xc8687ef6003bdb1bULL, }, + { 0x80000000f0ed8852ULL, 0xb0ef6662ff3a80e6ULL, }, + { 0xe8ec58e8d33594acULL, 0xf41fb1f8fe335d76ULL, }, + { 0xe4f20799babbcdaaULL, 0xe8f3454efe73d2afULL, }, + { 0xe4cdc5978bb75798ULL, 0xe623b939faecec20ULL, }, + { 0xe2057a0fb6418676ULL, 0xe03c1eae0901cfcdULL, }, + { 0xe5c1db3280000000ULL, 0xf122e6111767bfefULL, }, + { 0x979cbaab96251040ULL, 0xd9a9cd7d166665baULL, }, /* 72 */ + { 0x94d46f23c0af3f1eULL, 0xd3c232f2247b4967ULL, }, + { 0x800000009a322d5aULL, 0xc75aaa8dec42881aULL, }, + { 0xc96455c6cdd91d8cULL, 0xeadc3c95b2c62f40ULL, }, + { 0x3250aeaeb02129e6ULL, 0x2e0c882bb1bf0bd0ULL, }, + { 0x360d0fd180000000ULL, 0x3ef34f8ec024fbf2ULL, }, + { 0x7f716597b3a6f032ULL, 0x6274e19686a8a318ULL, }, + { 0x1ce6cdb280000000ULL, 0xfcd31bb480000000ULL, }, + { 0x37e70b49a8625540ULL, 0xfeb1f7e080000000ULL, }, /* 80 */ + { 0x39c31699dd7c5546ULL, 0xfee37780953f52fcULL, }, + { 0x5f82316fca8f431eULL, 0xff3c0af780000000ULL, }, + { 0x0bb5432ff1e2e177ULL, 0xfe8d6e9580000000ULL, }, + { 0x16a56af3f656d2b3ULL, 0xff67ba1b80000000ULL, }, + { 0x17664384fc31bf42ULL, 0xff7e4aa4953f52fcULL, }, + { 0x26b0cbfdfa1b830bULL, 0xffa6ab9180000000ULL, }, + { 0x04be31a4fe719ab1ULL, 0xff57124580000000ULL, }, + { 0x092c8a1ffeef4c68ULL, 0xffba958e80000000ULL, }, /* 88 */ + { 0x097aa960ff949347ULL, 0xffc4dede953f52fcULL, }, + { 0x0fac7158ff59ab27ULL, 0xffd7471a80000000ULL, }, + { 0x01ebdf01ffd41248ULL, 0xffb2fdd380000000ULL, }, + { 0x03b76546ffe1ee50ULL, 0xffe05b1780000000ULL, }, + { 0x03d70afdfff427aaULL, 0xffe50b86953f52fcULL, }, + { 0x065971c1ffeda8dfULL, 0xffed6fa980000000ULL, }, + { 0x00c741e8fffb2801ULL, 0xffdce50280000000ULL, }, + { 0x01816947fffcaf39ULL, 0xfff1931580000000ULL, }, /* 96 */ + { 0x02e97a17fffdbb03ULL, 0xfffa128380000000ULL, }, + { 0x05a1edf3fffe7250ULL, 0xfffd906f80000000ULL, }, + { 0x0ae508c5fffeefc8ULL, 0xfffeffc380000000ULL, }, + { 0x0b41cf1bffff94c3ULL, 0xffff25bb953f52fcULL, }, + { 0x0ba1ab79ffffd5c1ULL, 0xffff4613a6f7bf69ULL, }, + { 0x0c04b828ffffef5bULL, 0xffff61a0b5bf25caULL, }, + { 0x0c6b104efffff971ULL, 0xffff7918c21285a5ULL, }, + { 0x148886c7fffff5d8ULL, 0xffffa3179907b21bULL, }, /* 104 */ + { 0x21f39335fffff046ULL, 0xffffc00380000000ULL, }, + { 0x38235e38ffffe7a6ULL, 0xffffd3ee80000000ULL, }, + { 0x5cd2ce93ffffda4bULL, 0xffffe1a680000000ULL, }, + { 0x0b60ff8afffff60aULL, 0xffffc69a80000000ULL, }, + { 0x01651818fffffd5eULL, 0xffff937480000000ULL, }, + { 0x002bc65fffffff4dULL, 0xffff32bb80000000ULL, }, + { 0x00055dbfffffffd0ULL, 0xfffe7bd280000000ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MSUB_Q_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MSUB_Q_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MSUB_Q_W__DDT(b128_random[i], b128_random[j], + b128_result[ + ((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + ((RANDOM_INPUTS_SHORT_COUNT) * + (RANDOM_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MSUB_Q_W__DSD(b128_random[i], b128_random[j], + b128_result[ + ((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + (2 * (RANDOM_INPUTS_SHORT_COUNT) * + (RANDOM_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results_128(isa_ase_name, group_name, instruction_name, + TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_msubr_q_h.c b/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_msubr_q_h.c new file mode 100644 index 0000000000..0be6d51418 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_msubr_q_h.c @@ -0,0 +1,216 @@ +/* + * Test program for MSA instruction MSUBR_Q.H + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + 3 * (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *isa_ase_name = "MSA"; + char *group_name = "Fixed Multiply"; + char *instruction_name = "MSUBR_Q.H"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x00000000ffff0000ULL, 0x0000ffff00000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xc71bc71bc71bc71bULL, 0xc71bc71bc71bc71bULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xdddcdddcdddcdddcULL, 0xdddcdddcdddcdddcULL, }, + { 0xfffefffefffefffeULL, 0xfffefffefffefffeULL, }, + { 0xed0725ebb423ed07ULL, 0x25ebb423ed0725ebULL, }, + { 0xfffdfffdfffefffdULL, 0xfffdfffefffdfffdULL, }, + { 0xfffefffefffffffeULL, 0xfffefffffffefffeULL, }, /* 24 */ + { 0xfffefffefffffffeULL, 0xfffefffffffefffeULL, }, + { 0x38e238e238e338e2ULL, 0x38e238e338e238e2ULL, }, + { 0xffffffff0000ffffULL, 0xffff0000ffffffffULL, }, + { 0x2222222222232222ULL, 0x2222222322222222ULL, }, + { 0x0000000000010000ULL, 0x0000000100000000ULL, }, + { 0x12f7da134bdb12f7ULL, 0xda134bdb12f7da13ULL, }, + { 0x0001000000010001ULL, 0x0000000100010000ULL, }, + { 0x0001000000010001ULL, 0x0000000100010000ULL, }, /* 32 */ + { 0x0001000000010001ULL, 0x0000000100010000ULL, }, + { 0xdddedddddddedddeULL, 0xdddddddedddeddddULL, }, + { 0x0001000000010001ULL, 0x0000000100010000ULL, }, + { 0xeb85eb84eb85eb85ULL, 0xeb84eb85eb85eb84ULL, }, + { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, }, + { 0xf49f16c1d27cf49fULL, 0x16c1d27cf49f16c1ULL, }, + { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, }, + { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, }, /* 40 */ + { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, }, + { 0x2222222122222222ULL, 0x2221222222222221ULL, }, + { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, }, + { 0x147b147a147b147bULL, 0x147a147b147b147aULL, }, + { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, }, + { 0x0b61e93e2d830b61ULL, 0xe93e2d830b61e93eULL, }, + { 0x0001000000000001ULL, 0x0000000000010000ULL, }, + { 0x00010000ffff0001ULL, 0x0000ffff00010000ULL, }, /* 48 */ + { 0x00010000ffff0001ULL, 0x0000ffff00010000ULL, }, + { 0xed0a25edb424ed0aULL, 0x25edb424ed0a25edULL, }, + { 0x00010000fffe0001ULL, 0x0000fffe00010000ULL, }, + { 0xf4a016c2d27af4a0ULL, 0x16c2d27af4a016c2ULL, }, + { 0x00010001fffd0001ULL, 0x0001fffd00010001ULL, }, + { 0xf9afe6b99ad9f9afULL, 0xe6b99ad9f9afe6b9ULL, }, + { 0x00010002fffc0001ULL, 0x0002fffc00010002ULL, }, + { 0x00010002fffd0001ULL, 0x0002fffd00010002ULL, }, /* 56 */ + { 0x00010002fffd0001ULL, 0x0002fffd00010002ULL, }, + { 0x12f7da144bd812f7ULL, 0xda144bd812f7da14ULL, }, + { 0x00010001fffe0001ULL, 0x0001fffe00010001ULL, }, + { 0x0b62e93f2d820b62ULL, 0xe93f2d820b62e93fULL, }, + { 0x00020001ffff0002ULL, 0x0001ffff00020001ULL, }, + { 0x0654194a65220654ULL, 0x194a65220654194aULL, }, + { 0x00020001ffff0002ULL, 0x0001ffff00020001ULL, }, + { 0x9048fb0bf341c73bULL, 0xd396fefdfffdce10ULL, }, /* 64 */ + { 0x8c4efb1edac8ed2cULL, 0xc86a051b003e01e6ULL, }, + { 0x8000eb1af0ed3ac3ULL, 0xb0f10a2bff3c190fULL, }, + { 0xe8edef7ed3364e8aULL, 0xf42214c0fe3406b6ULL, }, + { 0xe4f3ef91babd747bULL, 0xe8f61adefe753a8cULL, }, + { 0xe4cfef918bb95b20ULL, 0xe627f5c8faee04bfULL, }, + { 0xe207efd0b6432746ULL, 0xe040d7190903ecb5ULL, }, + { 0xe5c3efbf80001a0fULL, 0xf12696f61769ffc0ULL, }, + { 0x979ddfbb962567a6ULL, 0xd9ad9c06166716e9ULL, }, /* 72 */ + { 0x94d5dffac0af33ccULL, 0xd3c68000247cfedfULL, }, + { 0x8000ac4b9a31c9c4ULL, 0xc75f8000ec43f421ULL, }, + { 0xc965ba77cdd8aebdULL, 0xeae08000b2c6fca3ULL, }, + { 0x3252bedbb021c284ULL, 0x2e118a95b1beea4aULL, }, + { 0x360ebeca8000b54dULL, 0x3ef78000c024fd55ULL, }, + { 0x7f73ccf6b3a79a46ULL, 0x6278800086a705d7ULL, }, + { 0x1ce9c91380009362ULL, 0xfcd580008000ff19ULL, }, + { 0x37ebbe42a862dbb9ULL, 0xfeb38b5e8000fe89ULL, }, /* 80 */ + { 0x39c7be75dd7ccb94ULL, 0xfee48000953fff7cULL, }, + { 0x5f8994cfca8f9bdeULL, 0xff3c80008000ffa2ULL, }, + { 0x0bb6a77cf1e284a3ULL, 0xfe8d80008000ff8cULL, }, + { 0x16a7960ef656d6ccULL, 0xff688b5e8000ff44ULL, }, + { 0x17689660fc31c475ULL, 0xff7f8000953fffbeULL, }, + { 0x26b48000fa1a8e43ULL, 0xffa780008000ffd1ULL, }, + { 0x04bf964dfe718000ULL, 0xff5880008000ffc6ULL, }, + { 0x092e817dfeefd540ULL, 0xffbb8b5e8000ffa2ULL, }, /* 88 */ + { 0x097c81dfff94c239ULL, 0xffc58000953fffdfULL, }, + { 0x0faf8000ff5989ffULL, 0xffd780008000ffe9ULL, }, + { 0x01ec964dffd48000ULL, 0xffb280008000ffe4ULL, }, + { 0x03b8817dffe2d540ULL, 0xffe08b5e8000ffd3ULL, }, + { 0x03d881dffff4c239ULL, 0xffe58000953ffff0ULL, }, + { 0x065b8000ffed89ffULL, 0xffed80008000fff5ULL, }, + { 0x00c7964dfffb8000ULL, 0xffdc80008000fff2ULL, }, + { 0x0181817dfffdd540ULL, 0xfff18b5e8000ffe9ULL, }, /* 96 */ + { 0x02e98000fffef1b9ULL, 0xfffa95ba8000ffdbULL, }, + { 0x05a18000fffffb3bULL, 0xfffe9f2a8000ffc4ULL, }, + { 0x0ae38000fffffe68ULL, 0xffffa7c48000ff9fULL, }, + { 0x0b4080630000fdb2ULL, 0xffff8000953fffdeULL, }, + { 0x0ba080c60000fcabULL, 0xffff8000a6f7fff4ULL, }, + { 0x0c0381280000fb2fULL, 0xffff8000b5befffcULL, }, + { 0x0c69818a0000f90aULL, 0xffff8000c211ffffULL, }, + { 0x148580000000f2b4ULL, 0xffff80009905ffffULL, }, /* 104 */ + { 0x21ee80000000e69aULL, 0xffff80008000ffffULL, }, + { 0x381a80000000cf7cULL, 0xffff80008000ffffULL, }, + { 0x5cc480000000a354ULL, 0xffff80008000ffffULL, }, + { 0x0b5f964d00008dd4ULL, 0xfffe80008000ffffULL, }, + { 0x0165a8b700008000ULL, 0xfffc80008000ffffULL, }, + { 0x002cb7ec00008000ULL, 0xfff880008000ffffULL, }, + { 0x0005c47b00008000ULL, 0xfff180008000ffffULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MSUBR_Q_H(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MSUBR_Q_H(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MSUBR_Q_H__DDT(b128_random[i], b128_random[j], + b128_result[ + ((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + ((RANDOM_INPUTS_SHORT_COUNT) * + (RANDOM_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MSUBR_Q_H__DSD(b128_random[i], b128_random[j], + b128_result[ + ((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + (2 * (RANDOM_INPUTS_SHORT_COUNT) * + (RANDOM_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results_128(isa_ase_name, group_name, instruction_name, + TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_msubr_q_w.c b/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_msubr_q_w.c new file mode 100644 index 0000000000..7d57cb500a --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_msubr_q_w.c @@ -0,0 +1,216 @@ +/* + * Test program for MSA instruction MSUBR_Q.W + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + 3 * (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *isa_ase_name = "MSA"; + char *group_name = "Fixed Multiply"; + char *instruction_name = "MSUBR_Q.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000100000001ULL, 0x0000000100000001ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000001ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000100000001ULL, 0x0000000100000001ULL, }, /* 16 */ + { 0x0000000100000001ULL, 0x0000000100000001ULL, }, + { 0x38e38e3b38e38e3bULL, 0x38e38e3b38e38e3bULL, }, + { 0x0000000200000002ULL, 0x0000000200000002ULL, }, + { 0x2222222522222225ULL, 0x2222222522222225ULL, }, + { 0x0000000300000003ULL, 0x0000000300000003ULL, }, + { 0x12f684c14bda12faULL, 0xda12f68812f684c1ULL, }, + { 0x0000000400000003ULL, 0x0000000400000004ULL, }, + { 0x0000000300000002ULL, 0x0000000300000003ULL, }, /* 24 */ + { 0x0000000300000002ULL, 0x0000000300000003ULL, }, + { 0xc71c71cac71c71c9ULL, 0xc71c71cac71c71caULL, }, + { 0x0000000200000001ULL, 0x0000000200000002ULL, }, + { 0xdddddddfdddddddeULL, 0xdddddddfdddddddfULL, }, + { 0x0000000100000000ULL, 0x0000000100000001ULL, }, + { 0xed097b43b425ed0aULL, 0x25ed097ced097b43ULL, }, + { 0x0000000000000000ULL, 0x0000000100000000ULL, }, + { 0x0000000000000000ULL, 0x0000000100000000ULL, }, /* 32 */ + { 0x0000000000000000ULL, 0x0000000100000000ULL, }, + { 0x2222222322222223ULL, 0x2222222422222223ULL, }, + { 0x0000000000000000ULL, 0x0000000100000000ULL, }, + { 0x147ae148147ae148ULL, 0x147ae149147ae148ULL, }, + { 0x0000000000000000ULL, 0x0000000100000000ULL, }, + { 0x0b60b60c2d82d82eULL, 0xe93e93ea0b60b60cULL, }, + { 0x0000000100000000ULL, 0x0000000100000001ULL, }, + { 0x0000000100000000ULL, 0x0000000100000001ULL, }, /* 40 */ + { 0x0000000100000000ULL, 0x0000000100000001ULL, }, + { 0xdddddddfdddddddeULL, 0xdddddddfdddddddfULL, }, + { 0x0000000100000000ULL, 0x0000000100000001ULL, }, + { 0xeb851eb9eb851eb8ULL, 0xeb851eb9eb851eb9ULL, }, + { 0x0000000100000000ULL, 0x0000000100000001ULL, }, + { 0xf49f49f5d27d27d3ULL, 0x16c16c17f49f49f5ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000001ULL, 0x0000000000000000ULL, }, /* 48 */ + { 0x0000000000000001ULL, 0x0000000000000000ULL, }, + { 0x12f684be4bda12f8ULL, 0xda12f68512f684beULL, }, + { 0x0000000000000002ULL, 0x0000000000000000ULL, }, + { 0x0b60b60c2d82d830ULL, 0xe93e93e90b60b60cULL, }, + { 0x0000000000000003ULL, 0xffffffff00000000ULL, }, + { 0x06522c3f6522c3f7ULL, 0x1948b0fb06522c3fULL, }, + { 0x0000000000000004ULL, 0xffffffff00000000ULL, }, + { 0x0000000000000003ULL, 0xffffffff00000000ULL, }, /* 56 */ + { 0x0000000000000003ULL, 0xffffffff00000000ULL, }, + { 0xed097b43b425ed0cULL, 0x25ed097bed097b43ULL, }, + { 0x0000000000000002ULL, 0x0000000000000000ULL, }, + { 0xf49f49f5d27d27d4ULL, 0x16c16c17f49f49f5ULL, }, + { 0x0000000000000001ULL, 0x0000000000000000ULL, }, + { 0xf9add3c19add3c0eULL, 0xe6b74f04f9add3c1ULL, }, + { 0x0000000000000000ULL, 0x0000000100000000ULL, }, + { 0x6fb7e8890cbdc0d3ULL, 0x2c6b144700049a05ULL, }, /* 64 */ + { 0x73b239d7253787d5ULL, 0x379780f0ffc424ccULL, }, + { 0x7fffffff0f127795ULL, 0x4f10998300c57f01ULL, }, + { 0x1713a7162cca6b3bULL, 0x0be04ded01cca270ULL, }, + { 0x1b0df8644544323dULL, 0x170cba96018c2d37ULL, }, + { 0x1b323a657448a84fULL, 0x19dc46aa051313c6ULL, }, + { 0x1dfa85ed49be7970ULL, 0x1fc3e135f6fe3018ULL, }, + { 0x1a3e24ca7fffffffULL, 0x0edd19d1e8983ff6ULL, }, + { 0x6863455169daefbfULL, 0x26563264e9999a2bULL, }, /* 72 */ + { 0x6b2b90d93f50c0e0ULL, 0x2c3dccefdb84b67dULL, }, + { 0x7fffffff65cdd2a4ULL, 0x38a5555313bd77c9ULL, }, + { 0x369baa393226e271ULL, 0x1523c34a4d39d0a3ULL, }, + { 0xcdaf51504fded617ULL, 0xd1f377b44e40f412ULL, }, + { 0xc9f2f02d7fffffffULL, 0xc10cb0503fdb03f0ULL, }, + { 0x808e9a674c590fccULL, 0x9d8b1e4779575ccaULL, }, + { 0xe319324b7fffffffULL, 0x032ce4297fffffffULL, }, + { 0xfe196fe67fffffffULL, 0x050bc0417e7bb00bULL, }, /* 80 */ + { 0xfe299f487fffffffULL, 0x05cb2b577fffffffULL, }, + { 0xff5d018339cf8b80ULL, 0x0798e2662b2b2514ULL, }, + { 0xfecdfe20645a7d9bULL, 0x00d3dcf80dea608eULL, }, + { 0xffebe0517fffffffULL, 0x0150ab000dc02968ULL, }, + { 0xffec8baf7fffffffULL, 0x01828ea210087db2ULL, }, + { 0xfff9423c39cf8b80ULL, 0x01fae4c1056841b9ULL, }, + { 0xfff35806645a7d9bULL, 0x003737bc01be3862ULL, }, + { 0xffff2aee7fffffffULL, 0x0057bed801b8eeb0ULL, }, /* 88 */ + { 0xffff32047fffffffULL, 0x0064bf8102021ffcULL, }, + { 0xffffb89f39cf8b80ULL, 0x00841c7a00ad640aULL, }, + { 0xffff79fe645a7d9bULL, 0x000e642f0037e4a6ULL, }, + { 0xfffff7307fffffffULL, 0x0016de7800373b16ULL, }, + { 0xfffff77b7fffffffULL, 0x001a42040040661aULL, }, + { 0xfffffd0c39cf8b80ULL, 0x00226e990015b802ULL, }, + { 0xfffffa75645a7d9bULL, 0x0003c0350007004aULL, }, + { 0xffffffa37fffffffULL, 0x0005f5d90006eb0dULL, }, /* 96 */ + { 0xfffffffa7fffffffULL, 0x000978b30006d610ULL, }, + { 0x000000007fffffffULL, 0x000f0d0c0006c153ULL, }, + { 0x000000007fffffffULL, 0x0017eacf0006acd5ULL, }, + { 0x000000007fffffffULL, 0x001b761e0007c87dULL, }, + { 0x000000007fffffffULL, 0x001f87e00009133bULL, }, + { 0x000000007fffffffULL, 0x00243402000a94e0ULL, }, + { 0x000000007fffffffULL, 0x00299164000c5689ULL, }, + { 0x0000000039cf8b80ULL, 0x003682160004293bULL, }, /* 104 */ + { 0x000000001a1c28c4ULL, 0x00477a0900016741ULL, }, + { 0x000000000bcae026ULL, 0x005dba4500007929ULL, }, + { 0x00000000055376c2ULL, 0x007ae7c2000028ddULL, }, + { 0x00000000093ed557ULL, 0x000d637500000d2cULL, }, + { 0x00000000100c9469ULL, 0x0001755d0000043fULL, }, + { 0x000000001bdc1297ULL, 0x000028ac0000015eULL, }, + { 0x00000000305c8bbfULL, 0x0000046e00000071ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MADDR_Q_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MADDR_Q_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MADDR_Q_W__DDT(b128_random[i], b128_random[j], + b128_result[ + ((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + ((RANDOM_INPUTS_SHORT_COUNT) * + (RANDOM_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MADDR_Q_W__DSD(b128_random[i], b128_random[j], + b128_result[ + ((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + (2 * (RANDOM_INPUTS_SHORT_COUNT) * + (RANDOM_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results_128(isa_ase_name, group_name, instruction_name, + TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_maddv_b.c b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_maddv_b.c index 5678677267..d543e1af28 100644 --- a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_maddv_b.c +++ b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_maddv_b.c @@ -43,118 +43,118 @@ int32_t main(void) uint64_t b128_result[TEST_COUNT_TOTAL][2]; uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { - { 0x0000000000000002ULL, 0x0000000000000002ULL, }, /* 0 */ - { 0x0000000000000002ULL, 0x0000000000000002ULL, }, - { 0x00000000aaaaaaaeULL, 0x00000000aaaaaaaeULL, }, - { 0x0000000000000004ULL, 0x0000000000000004ULL, }, - { 0x000000006666666cULL, 0x000000006666666cULL, }, - { 0x0000000000000006ULL, 0x0000000000000006ULL, }, - { 0x000000008e38e395ULL, 0xffffffffe38e38ebULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, /* 8 */ - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x00000000aaaaaab4ULL, 0x00000000aaaaaab4ULL, }, /* 16 */ - { 0x00000000aaaaaab4ULL, 0x00000000aaaaaab4ULL, }, - { 0x38e38e3a71c71c7cULL, 0x38e38e3a71c71c7cULL, }, - { 0x0000000155555560ULL, 0x0000000155555560ULL, }, - { 0x2222222444444450ULL, 0x2222222444444450ULL, }, - { 0x000000020000000cULL, 0x000000020000000cULL, }, - { 0x2f684bdcb425ed16ULL, 0xf684bda397b425faULL, }, - { 0x00000002aaaaaab8ULL, 0x00000002aaaaaab8ULL, }, - { 0x000000020000000eULL, 0x000000020000000eULL, }, /* 24 */ - { 0x000000020000000eULL, 0x000000020000000eULL, }, - { 0xc71c71c8e38e38f2ULL, 0xc71c71c8e38e38f2ULL, }, - { 0x0000000155555564ULL, 0x0000000155555564ULL, }, - { 0xdddddddeccccccdcULL, 0xdddddddeccccccdcULL, }, - { 0x00000000aaaaaabaULL, 0x00000000aaaaaabaULL, }, - { 0xd097b42684bda13fULL, 0x097b425ef684bdb1ULL, }, - { 0x0000000000000010ULL, 0x0000000000000010ULL, }, - { 0x0000000066666678ULL, 0x0000000066666678ULL, }, /* 32 */ - { 0x0000000066666678ULL, 0x0000000066666678ULL, }, - { 0x2222222355555568ULL, 0x2222222355555568ULL, }, - { 0x00000000cccccce0ULL, 0x00000000cccccce0ULL, }, - { 0x147ae1491eb85200ULL, 0x147ae1491eb85200ULL, }, - { 0x0000000133333348ULL, 0x0000000133333348ULL, }, - { 0x1c71c71e3e93e954ULL, 0xfa4fa4fbb60b60ccULL, }, - { 0x00000001999999b0ULL, 0x00000001999999b0ULL, }, - { 0x000000013333334aULL, 0x000000013333334aULL, }, /* 40 */ - { 0x000000013333334aULL, 0x000000013333334aULL, }, - { 0xdddddddeeeeeef06ULL, 0xdddddddeeeeeef06ULL, }, - { 0x00000000cccccce4ULL, 0x00000000cccccce4ULL, }, - { 0xeb851eb8e147ae2cULL, 0xeb851eb8e147ae2cULL, }, - { 0x000000006666667eULL, 0x000000006666667eULL, }, - { 0xe38e38e3e93e9401ULL, 0x05b05b05c71c71dfULL, }, - { 0x0000000000000018ULL, 0x0000000000000018ULL, }, - { 0x000000008e38e3a7ULL, 0xffffffffe38e38fdULL, }, /* 48 */ - { 0x000000008e38e3a7ULL, 0xffffffffe38e38fdULL, }, - { 0x2f684bdb425ed0b1ULL, 0xf684bda17b425eebULL, }, - { 0x000000011c71c736ULL, 0xffffffffc71c71e2ULL, }, - { 0x1c71c71e27d27d42ULL, 0xfa4fa4fa49f49f66ULL, }, - { 0x00000001aaaaaac5ULL, 0xffffffffaaaaaac7ULL, }, - { 0x35ba781b4587e6d2ULL, 0x0fcd6e9d6b74f050ULL, }, - { 0x0000000238e38e54ULL, 0xffffffff8e38e3acULL, }, - { 0x00000001aaaaaac7ULL, 0xffffffffaaaaaac9ULL, }, /* 56 */ - { 0x00000001aaaaaac7ULL, 0xffffffffaaaaaac9ULL, }, - { 0xd097b427a12f6869ULL, 0x097b425ebda12f87ULL, }, - { 0x000000011c71c73aULL, 0xffffffffc71c71e6ULL, }, - { 0xe38e38e477777796ULL, 0x05b05b05aaaaaacaULL, }, - { 0x000000008e38e3adULL, 0xffffffffe38e3903ULL, }, - { 0xca4587e781948b2fULL, 0xf032916206522c5fULL, }, - { 0x0000000000000020ULL, 0x0000000000000020ULL, }, - { 0x3e3ad4ae1266c2b0ULL, 0x1637d725aebdb734ULL, }, /* 64 */ - { 0x4c74e0d60a3d6d94ULL, 0x1badd2dd9f4dac90ULL, }, - { 0x6874e8f94205b90cULL, 0x27eb0c41af2c3022ULL, }, - { 0x42dab657e16f25e8ULL, 0x06d6782e137656f2ULL, }, - { 0x5114c27fd945d0ccULL, 0x0c4c73e604064c4eULL, }, - { 0x68a91e898c276755ULL, 0x0f77ad378bdfb302ULL, }, - { 0x54c82cde41d1cf13ULL, 0x0b6108a5f38e1598ULL, }, - { 0x6f755d3eddd1234aULL, 0xfbbaace2f5421908ULL, }, - { 0x8b75656215996ec2ULL, 0x07f7e64705209c9aULL, }, /* 72 */ - { 0x779473b6cb43d680ULL, 0x03e141b56cceff30ULL, }, - { 0xa6279a1866fb9f64ULL, 0x2631668db9e53ac1ULL, }, - { 0x67a1f71bd99e4586ULL, 0x312ec9f6206e6e69ULL, }, - { 0x4207c47a7907b262ULL, 0x101a35e284b89539ULL, }, - { 0x5cb4f4db15070699ULL, 0x0073da1f866c98a9ULL, }, - { 0x1e2f51de87a9acbbULL, 0x0b713d87ecf5cc51ULL, }, - { 0x721d49ba5f0acfa8ULL, 0x5ba5bbe9afeae691ULL, }, - { 0x4bcd68690d995de0ULL, 0x771da6b4b6c967ebULL, }, /* 80 */ - { 0x4ea9a2cfbb5acd7bULL, 0x79dd6a73439e6387ULL, }, - { 0x47c800b999dd2371ULL, 0x766d25914ef7a7a0ULL, }, - { 0x41b0fa10eb77cf84ULL, 0x26e85189458965f8ULL, }, - { 0x1fc448ce062c2944ULL, 0x31f490a9422a80e6ULL, }, - { 0x211bdfadfd79770eULL, 0x3b25f4cac5763378ULL, }, - { 0x16fbb87edd87b6f0ULL, 0x57c0b65fabdda20eULL, }, - { 0x14621091eac4a5f6ULL, 0x4d29a25d32fa9ef6ULL, }, - { 0x07832ded1c464b02ULL, 0x6396905709e3cfa4ULL, }, /* 88 */ - { 0x0ff4a84eab8df3b9ULL, 0x6bc9a7d8c6adf2eaULL, }, - { 0x21e53326bfbd0b05ULL, 0x8f8f3b9c679dff5aULL, }, - { 0x191ed6a24e1576f9ULL, 0x9e8c2e402760373aULL, }, - { 0x19b438400fc27751ULL, 0x819c4bbfd3ee6972ULL, }, - { 0x1e0d5dc1094ae999ULL, 0x7496a289f5eff010ULL, }, - { 0x11af620b7bc03943ULL, 0x8a11f229836addc7ULL, }, - { 0x46fa45d0e84440fcULL, 0xe8d2c0211fb042bfULL, }, - { 0x22142516b5a8adbcULL, 0xe1cf1923e186aad1ULL, }, /* 96 */ - { 0x066ebbbb4ff6da44ULL, 0xd918d7e6a7e61877ULL, }, - { 0x100acc9d22839a48ULL, 0xce291932929e367fULL, }, - { 0x0dfe419d62a62f64ULL, 0xc020fe45a8cf7acfULL, }, - { 0x2ba79b6ffbf3c63bULL, 0xb428f52c49fce695ULL, }, - { 0x29b3b85200bdf100ULL, 0xb4ae7ea2f52aa5b9ULL, }, - { 0x293bb84d6360c0b6ULL, 0xae33b26e4c493c49ULL, }, - { 0x46a99fdf54f4862dULL, 0xae790dc5055f6f51ULL, }, - { 0x18480e0fd728c7c3ULL, 0xa000ad7b15f8ebe0ULL, }, /* 104 */ - { 0x1b8b97aa205e1239ULL, 0x89c78b8909c4a8e5ULL, }, - { 0x09abb26b05ef649dULL, 0x74242fa1bd49e740ULL, }, - { 0x04e233bc861d272bULL, 0x9c5343ab30f62f9fULL, }, - { 0xda2da0d0884dc3d1ULL, 0xb824f201640b4147ULL, }, - { 0x9d8b22ee1b9a2e0fULL, 0xb642ddf1edb0747fULL, }, - { 0x7c81956533686a37ULL, 0xdd5181781dc3ad37ULL, }, - { 0xc60b1905717ff25aULL, 0xe2af726e71ad7ad7ULL, }, + { 0x0101010101010101ULL, 0x0101010101010101ULL, }, /* 0 */ + { 0x0101010101010101ULL, 0x0101010101010101ULL, }, + { 0x5757575757575757ULL, 0x5757575757575757ULL, }, + { 0x0202020202020202ULL, 0x0202020202020202ULL, }, + { 0x3636363636363636ULL, 0x3636363636363636ULL, }, + { 0x0303030303030303ULL, 0x0303030303030303ULL, }, + { 0x2075cb2075cb2075ULL, 0xcb2075cb2075cb20ULL, }, + { 0x0404040404040404ULL, 0x0404040404040404ULL, }, + { 0x0404040404040404ULL, 0x0404040404040404ULL, }, /* 8 */ + { 0x0404040404040404ULL, 0x0404040404040404ULL, }, + { 0x0404040404040404ULL, 0x0404040404040404ULL, }, + { 0x0404040404040404ULL, 0x0404040404040404ULL, }, + { 0x0404040404040404ULL, 0x0404040404040404ULL, }, + { 0x0404040404040404ULL, 0x0404040404040404ULL, }, + { 0x0404040404040404ULL, 0x0404040404040404ULL, }, + { 0x0404040404040404ULL, 0x0404040404040404ULL, }, + { 0x5a5a5a5a5a5a5a5aULL, 0x5a5a5a5a5a5a5a5aULL, }, /* 16 */ + { 0x5a5a5a5a5a5a5a5aULL, 0x5a5a5a5a5a5a5a5aULL, }, + { 0x3e3e3e3e3e3e3e3eULL, 0x3e3e3e3e3e3e3e3eULL, }, + { 0xb0b0b0b0b0b0b0b0ULL, 0xb0b0b0b0b0b0b0b0ULL, }, + { 0x2828282828282828ULL, 0x2828282828282828ULL, }, + { 0x0606060606060606ULL, 0x0606060606060606ULL, }, + { 0xc45236c45236c452ULL, 0x36c45236c45236c4ULL, }, + { 0x5c5c5c5c5c5c5c5cULL, 0x5c5c5c5c5c5c5c5cULL, }, + { 0x0707070707070707ULL, 0x0707070707070707ULL, }, /* 24 */ + { 0x0707070707070707ULL, 0x0707070707070707ULL, }, + { 0x7979797979797979ULL, 0x7979797979797979ULL, }, + { 0xb2b2b2b2b2b2b2b2ULL, 0xb2b2b2b2b2b2b2b2ULL, }, + { 0x6e6e6e6e6e6e6e6eULL, 0x6e6e6e6e6e6e6e6eULL, }, + { 0x5d5d5d5d5d5d5d5dULL, 0x5d5d5d5d5d5d5d5dULL, }, + { 0xbc83f5bc83f5bc83ULL, 0xf5bc83f5bc83f5bcULL, }, + { 0x0808080808080808ULL, 0x0808080808080808ULL, }, + { 0x3c3c3c3c3c3c3c3cULL, 0x3c3c3c3c3c3c3c3cULL, }, /* 32 */ + { 0x3c3c3c3c3c3c3c3cULL, 0x3c3c3c3c3c3c3c3cULL, }, + { 0xb4b4b4b4b4b4b4b4ULL, 0xb4b4b4b4b4b4b4b4ULL, }, + { 0x7070707070707070ULL, 0x7070707070707070ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xa4a4a4a4a4a4a4a4ULL, 0xa4a4a4a4a4a4a4a4ULL, }, + { 0x88cc4488cc4488ccULL, 0x4488cc4488cc4488ULL, }, + { 0xd8d8d8d8d8d8d8d8ULL, 0xd8d8d8d8d8d8d8d8ULL, }, + { 0xa5a5a5a5a5a5a5a5ULL, 0xa5a5a5a5a5a5a5a5ULL, }, /* 40 */ + { 0xa5a5a5a5a5a5a5a5ULL, 0xa5a5a5a5a5a5a5a5ULL, }, + { 0x8383838383838383ULL, 0x8383838383838383ULL, }, + { 0x7272727272727272ULL, 0x7272727272727272ULL, }, + { 0x1616161616161616ULL, 0x1616161616161616ULL, }, + { 0x3f3f3f3f3f3f3f3fULL, 0x3f3f3f3f3f3f3f3fULL, }, + { 0x7889677889677889ULL, 0x6778896778896778ULL, }, + { 0x0c0c0c0c0c0c0c0cULL, 0x0c0c0c0c0c0c0c0cULL, }, + { 0x297ed4297ed4297eULL, 0xd4297ed4297ed429ULL, }, /* 48 */ + { 0x297ed4297ed4297eULL, 0xd4297ed4297ed429ULL, }, + { 0xe7ca04e7ca04e7caULL, 0x04e7ca04e7ca04e7ULL, }, + { 0x46f09c46f09c46f0ULL, 0x9c46f09c46f09c46ULL, }, + { 0x2a183c2a183c2a18ULL, 0x3c2a183c2a183c2aULL, }, + { 0x6362646362646362ULL, 0x6463626463626463ULL, }, + { 0xac26a4ac26a4ac26ULL, 0xa4ac26a4ac26a4acULL, }, + { 0x80d42c80d42c80d4ULL, 0x2c80d42c80d42c80ULL, }, + { 0x6463656463656463ULL, 0x6564636564636564ULL, }, /* 56 */ + { 0x6463656463656463ULL, 0x6564636564636564ULL, }, + { 0xfc6d8bfc6d8bfc6dULL, 0x8bfc6d8bfc6d8bfcULL, }, + { 0x48f29e48f29e48f2ULL, 0x9e48f29e48f29e48ULL, }, + { 0x98fe3298fe3298feULL, 0x3298fe3298fe3298ULL, }, + { 0x2c81d72c81d72c81ULL, 0xd72c81d72c81d72cULL, }, + { 0x002f5f002f5f002fULL, 0x5f002f5f002f5f00ULL, }, + { 0x1010101010101010ULL, 0x1010101010101010ULL, }, + { 0x50f4b4a050944910ULL, 0x09818994142910a0ULL, }, /* 64 */ + { 0xa8a0b48458da5c10ULL, 0x4fe29220ea6e7070ULL, }, + { 0x08e408fc40188310ULL, 0xbcca14c29417e060ULL, }, + { 0x889acc58f0da8d90ULL, 0x0bc1ec1242cd40e0ULL, }, + { 0xe046cc3cf820a090ULL, 0x5122f59e1812a0b0ULL, }, + { 0xf94acc85218951d0ULL, 0x95738e42d193e4c0ULL, }, + { 0x9d16cc43c6665ed0ULL, 0x53db3028d828be70ULL, }, + { 0x6db8cc0a0c890c40ULL, 0x3d628818b56622f0ULL, }, + { 0xcdfc2082f4c73340ULL, 0xaa4a0aba5f0f92e0ULL, }, /* 72 */ + { 0x71c8204099a44040ULL, 0x68b2aca066a46c90ULL, }, + { 0x016c64244a05b940ULL, 0x59f2d0a19fddc520ULL, }, + { 0x4132584638a46f40ULL, 0xd44a00c982f36fa0ULL, }, + { 0xc1e81ca2e86679c0ULL, 0x2341d81930a9cf20ULL, }, + { 0x918a1c692e892730ULL, 0x0dc830090de733a0ULL, }, + { 0xd150108b1c28dd30ULL, 0x88206031f0fddd20ULL, }, + { 0xd1b1f4b4a08961f4ULL, 0x3101a07181016120ULL, }, + { 0xd9fb2c24a0fb96f4ULL, 0x8c6880ef7f7c11a0ULL, }, /* 80 */ + { 0x9c452c10c01c3094ULL, 0x64c00035ea008320ULL, }, + { 0x6c8714b080c04094ULL, 0xa0c00000380072a0ULL, }, + { 0xac30cca08080c0acULL, 0xc0800000300016a0ULL, }, + { 0x0c101420808080acULL, 0x00000000d0003620ULL, }, + { 0xd0f014800000000cULL, 0x00000000e00082a0ULL, }, + { 0x9050ac800000000cULL, 0x0000000080004c20ULL, }, + { 0x90007400000000b4ULL, 0x0000000000006420ULL, }, + { 0x1000ac00000000b4ULL, 0x00000000000024a0ULL, }, /* 88 */ + { 0xc000ac0000000054ULL, 0x000000000000ac20ULL, }, + { 0xc000940000000054ULL, 0x00000000000088a0ULL, }, + { 0xc0004c00000000ecULL, 0x00000000000098a0ULL, }, + { 0xc0009400000000ecULL, 0x0000000000001820ULL, }, + { 0x000094000000004cULL, 0x000000000000c8a0ULL, }, + { 0x00002c000000004cULL, 0x000000000000b020ULL, }, + { 0x0000f40000000074ULL, 0x0000000000001020ULL, }, + { 0x00002c0000000074ULL, 0x00000000000010a0ULL, }, /* 96 */ + { 0x0000b40000000074ULL, 0x0000000000001020ULL, }, + { 0x00006c0000000074ULL, 0x00000000000010a0ULL, }, + { 0x0000740000000074ULL, 0x0000000000001020ULL, }, + { 0x0000740000000014ULL, 0x00000000000030a0ULL, }, + { 0x00007400000000b4ULL, 0x0000000000009020ULL, }, + { 0x0000740000000054ULL, 0x000000000000b0a0ULL, }, + { 0x00007400000000f4ULL, 0x0000000000001020ULL, }, + { 0x00004c00000000f4ULL, 0x00000000000060a0ULL, }, /* 104 */ + { 0x0000f400000000f4ULL, 0x0000000000004020ULL, }, + { 0x0000cc00000000f4ULL, 0x00000000000080a0ULL, }, + { 0x00007400000000f4ULL, 0x0000000000000020ULL, }, + { 0x00006c000000004cULL, 0x0000000000000020ULL, }, + { 0x0000b40000000074ULL, 0x0000000000000020ULL, }, + { 0x00002c00000000ccULL, 0x0000000000000020ULL, }, + { 0x0000f400000000f4ULL, 0x0000000000000020ULL, }, }; reset_msa_registers(); diff --git a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_maddv_d.c b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_maddv_d.c index 965703ca38..fda35f757b 100644 --- a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_maddv_d.c +++ b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_maddv_d.c @@ -43,118 +43,118 @@ int32_t main(void) uint64_t b128_result[TEST_COUNT_TOTAL][2]; uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { - { 0x0000000000000002ULL, 0x0000000000000002ULL, }, /* 0 */ + { 0x0000000000000001ULL, 0x0000000000000001ULL, }, /* 0 */ + { 0x0000000000000001ULL, 0x0000000000000001ULL, }, + { 0x5555555555555557ULL, 0x5555555555555557ULL, }, { 0x0000000000000002ULL, 0x0000000000000002ULL, }, - { 0x00000000aaaaaaaeULL, 0x00000000aaaaaaaeULL, }, + { 0x3333333333333336ULL, 0x3333333333333336ULL, }, + { 0x0000000000000003ULL, 0x0000000000000003ULL, }, + { 0x1c71c71c71c71c75ULL, 0xc71c71c71c71c720ULL, }, { 0x0000000000000004ULL, 0x0000000000000004ULL, }, - { 0x000000006666666cULL, 0x000000006666666cULL, }, + { 0x0000000000000004ULL, 0x0000000000000004ULL, }, /* 8 */ + { 0x0000000000000004ULL, 0x0000000000000004ULL, }, + { 0x0000000000000004ULL, 0x0000000000000004ULL, }, + { 0x0000000000000004ULL, 0x0000000000000004ULL, }, + { 0x0000000000000004ULL, 0x0000000000000004ULL, }, + { 0x0000000000000004ULL, 0x0000000000000004ULL, }, + { 0x0000000000000004ULL, 0x0000000000000004ULL, }, + { 0x0000000000000004ULL, 0x0000000000000004ULL, }, + { 0x555555555555555aULL, 0x555555555555555aULL, }, /* 16 */ + { 0x555555555555555aULL, 0x555555555555555aULL, }, + { 0x8e38e38e38e38e3eULL, 0x8e38e38e38e38e3eULL, }, + { 0xaaaaaaaaaaaaaab0ULL, 0xaaaaaaaaaaaaaab0ULL, }, + { 0x2222222222222228ULL, 0x2222222222222228ULL, }, { 0x0000000000000006ULL, 0x0000000000000006ULL, }, - { 0x000000008e38e395ULL, 0xffffffffe38e38ebULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, /* 8 */ - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, + { 0x12f684bda12f6852ULL, 0x2f684bda12f684c4ULL, }, + { 0x555555555555555cULL, 0x555555555555555cULL, }, + { 0x0000000000000007ULL, 0x0000000000000007ULL, }, /* 24 */ + { 0x0000000000000007ULL, 0x0000000000000007ULL, }, + { 0x1c71c71c71c71c79ULL, 0x1c71c71c71c71c79ULL, }, + { 0xaaaaaaaaaaaaaab2ULL, 0xaaaaaaaaaaaaaab2ULL, }, + { 0x666666666666666eULL, 0x666666666666666eULL, }, + { 0x555555555555555dULL, 0x555555555555555dULL, }, + { 0x5ed097b425ed0983ULL, 0xed097b425ed097bcULL, }, { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x00000000aaaaaab4ULL, 0x00000000aaaaaab4ULL, }, /* 16 */ - { 0x00000000aaaaaab4ULL, 0x00000000aaaaaab4ULL, }, - { 0x38e38e3a71c71c7cULL, 0x38e38e3a71c71c7cULL, }, - { 0x0000000155555560ULL, 0x0000000155555560ULL, }, - { 0x2222222444444450ULL, 0x2222222444444450ULL, }, - { 0x000000020000000cULL, 0x000000020000000cULL, }, - { 0x2f684bdcb425ed16ULL, 0xf684bda397b425faULL, }, - { 0x00000002aaaaaab8ULL, 0x00000002aaaaaab8ULL, }, - { 0x000000020000000eULL, 0x000000020000000eULL, }, /* 24 */ - { 0x000000020000000eULL, 0x000000020000000eULL, }, - { 0xc71c71c8e38e38f2ULL, 0xc71c71c8e38e38f2ULL, }, - { 0x0000000155555564ULL, 0x0000000155555564ULL, }, - { 0xdddddddeccccccdcULL, 0xdddddddeccccccdcULL, }, - { 0x00000000aaaaaabaULL, 0x00000000aaaaaabaULL, }, - { 0xd097b42684bda13fULL, 0x097b425ef684bdb1ULL, }, + { 0x333333333333333cULL, 0x333333333333333cULL, }, /* 32 */ + { 0x333333333333333cULL, 0x333333333333333cULL, }, + { 0xaaaaaaaaaaaaaab4ULL, 0xaaaaaaaaaaaaaab4ULL, }, + { 0x6666666666666670ULL, 0x6666666666666670ULL, }, + { 0x5c28f5c28f5c2900ULL, 0x5c28f5c28f5c2900ULL, }, + { 0x99999999999999a4ULL, 0x99999999999999a4ULL, }, + { 0x16c16c16c16c16ccULL, 0xd27d27d27d27d288ULL, }, + { 0xccccccccccccccd8ULL, 0xccccccccccccccd8ULL, }, + { 0x99999999999999a5ULL, 0x99999999999999a5ULL, }, /* 40 */ + { 0x99999999999999a5ULL, 0x99999999999999a5ULL, }, + { 0x7777777777777783ULL, 0x7777777777777783ULL, }, + { 0x6666666666666672ULL, 0x6666666666666672ULL, }, + { 0xa3d70a3d70a3d716ULL, 0xa3d70a3d70a3d716ULL, }, + { 0x333333333333333fULL, 0x333333333333333fULL, }, + { 0xd27d27d27d27d289ULL, 0xc16c16c16c16c178ULL, }, + { 0x000000000000000cULL, 0x000000000000000cULL, }, + { 0x1c71c71c71c71c7eULL, 0xc71c71c71c71c729ULL, }, /* 48 */ + { 0x1c71c71c71c71c7eULL, 0xc71c71c71c71c729ULL, }, + { 0x2f684bda12f684caULL, 0xf684bda12f684be7ULL, }, + { 0x38e38e38e38e38f0ULL, 0x8e38e38e38e38e46ULL, }, + { 0xb60b60b60b60b618ULL, 0xc71c71c71c71c72aULL, }, + { 0x5555555555555562ULL, 0x5555555555555563ULL, }, + { 0x06522c3f35ba7826ULL, 0xa781948b0fcd6eacULL, }, + { 0x71c71c71c71c71d4ULL, 0x1c71c71c71c71c80ULL, }, + { 0x5555555555555563ULL, 0x5555555555555564ULL, }, /* 56 */ + { 0x5555555555555563ULL, 0x5555555555555564ULL, }, + { 0x97b425ed097b426dULL, 0x7b425ed097b425fcULL, }, + { 0x38e38e38e38e38f2ULL, 0x8e38e38e38e38e48ULL, }, + { 0xeeeeeeeeeeeeeefeULL, 0x8888888888888898ULL, }, + { 0x1c71c71c71c71c81ULL, 0xc71c71c71c71c72cULL, }, + { 0x87e6b74f0329162fULL, 0x3c0ca4587e6b7500ULL, }, { 0x0000000000000010ULL, 0x0000000000000010ULL, }, - { 0x0000000066666678ULL, 0x0000000066666678ULL, }, /* 32 */ - { 0x0000000066666678ULL, 0x0000000066666678ULL, }, - { 0x2222222355555568ULL, 0x2222222355555568ULL, }, - { 0x00000000cccccce0ULL, 0x00000000cccccce0ULL, }, - { 0x147ae1491eb85200ULL, 0x147ae1491eb85200ULL, }, - { 0x0000000133333348ULL, 0x0000000133333348ULL, }, - { 0x1c71c71e3e93e954ULL, 0xfa4fa4fbb60b60ccULL, }, - { 0x00000001999999b0ULL, 0x00000001999999b0ULL, }, - { 0x000000013333334aULL, 0x000000013333334aULL, }, /* 40 */ - { 0x000000013333334aULL, 0x000000013333334aULL, }, - { 0xdddddddeeeeeef06ULL, 0xdddddddeeeeeef06ULL, }, - { 0x00000000cccccce4ULL, 0x00000000cccccce4ULL, }, - { 0xeb851eb8e147ae2cULL, 0xeb851eb8e147ae2cULL, }, - { 0x000000006666667eULL, 0x000000006666667eULL, }, - { 0xe38e38e3e93e9401ULL, 0x05b05b05c71c71dfULL, }, - { 0x0000000000000018ULL, 0x0000000000000018ULL, }, - { 0x000000008e38e3a7ULL, 0xffffffffe38e38fdULL, }, /* 48 */ - { 0x000000008e38e3a7ULL, 0xffffffffe38e38fdULL, }, - { 0x2f684bdb425ed0b1ULL, 0xf684bda17b425eebULL, }, - { 0x000000011c71c736ULL, 0xffffffffc71c71e2ULL, }, - { 0x1c71c71e27d27d42ULL, 0xfa4fa4fa49f49f66ULL, }, - { 0x00000001aaaaaac5ULL, 0xffffffffaaaaaac7ULL, }, - { 0x35ba781b4587e6d2ULL, 0x0fcd6e9d6b74f050ULL, }, - { 0x0000000238e38e54ULL, 0xffffffff8e38e3acULL, }, - { 0x00000001aaaaaac7ULL, 0xffffffffaaaaaac9ULL, }, /* 56 */ - { 0x00000001aaaaaac7ULL, 0xffffffffaaaaaac9ULL, }, - { 0xd097b427a12f6869ULL, 0x097b425ebda12f87ULL, }, - { 0x000000011c71c73aULL, 0xffffffffc71c71e6ULL, }, - { 0xe38e38e477777796ULL, 0x05b05b05aaaaaacaULL, }, - { 0x000000008e38e3adULL, 0xffffffffe38e3903ULL, }, - { 0xca4587e781948b2fULL, 0xf032916206522c5fULL, }, - { 0x0000000000000020ULL, 0x0000000000000020ULL, }, - { 0x3e3ad4ae1266c2b0ULL, 0x1637d725aebdb734ULL, }, /* 64 */ - { 0x4c74e0d60a3d6d94ULL, 0x1badd2dd9f4dac90ULL, }, - { 0x6874e8f94205b90cULL, 0x27eb0c41af2c3022ULL, }, - { 0x42dab657e16f25e8ULL, 0x06d6782e137656f2ULL, }, - { 0x5114c27fd945d0ccULL, 0x0c4c73e604064c4eULL, }, - { 0x68a91e898c276755ULL, 0x0f77ad378bdfb302ULL, }, - { 0x54c82cde41d1cf13ULL, 0x0b6108a5f38e1598ULL, }, - { 0x6f755d3eddd1234aULL, 0xfbbaace2f5421908ULL, }, - { 0x8b75656215996ec2ULL, 0x07f7e64705209c9aULL, }, /* 72 */ - { 0x779473b6cb43d680ULL, 0x03e141b56cceff30ULL, }, - { 0xa6279a1866fb9f64ULL, 0x2631668db9e53ac1ULL, }, - { 0x67a1f71bd99e4586ULL, 0x312ec9f6206e6e69ULL, }, - { 0x4207c47a7907b262ULL, 0x101a35e284b89539ULL, }, - { 0x5cb4f4db15070699ULL, 0x0073da1f866c98a9ULL, }, - { 0x1e2f51de87a9acbbULL, 0x0b713d87ecf5cc51ULL, }, - { 0x721d49ba5f0acfa8ULL, 0x5ba5bbe9afeae691ULL, }, - { 0x4bcd68690d995de0ULL, 0x771da6b4b6c967ebULL, }, /* 80 */ - { 0x4ea9a2cfbb5acd7bULL, 0x79dd6a73439e6387ULL, }, - { 0x47c800b999dd2371ULL, 0x766d25914ef7a7a0ULL, }, - { 0x41b0fa10eb77cf84ULL, 0x26e85189458965f8ULL, }, - { 0x1fc448ce062c2944ULL, 0x31f490a9422a80e6ULL, }, - { 0x211bdfadfd79770eULL, 0x3b25f4cac5763378ULL, }, - { 0x16fbb87edd87b6f0ULL, 0x57c0b65fabdda20eULL, }, - { 0x14621091eac4a5f6ULL, 0x4d29a25d32fa9ef6ULL, }, - { 0x07832ded1c464b02ULL, 0x6396905709e3cfa4ULL, }, /* 88 */ - { 0x0ff4a84eab8df3b9ULL, 0x6bc9a7d8c6adf2eaULL, }, - { 0x21e53326bfbd0b05ULL, 0x8f8f3b9c679dff5aULL, }, - { 0x191ed6a24e1576f9ULL, 0x9e8c2e402760373aULL, }, - { 0x19b438400fc27751ULL, 0x819c4bbfd3ee6972ULL, }, - { 0x1e0d5dc1094ae999ULL, 0x7496a289f5eff010ULL, }, - { 0x11af620b7bc03943ULL, 0x8a11f229836addc7ULL, }, - { 0x46fa45d0e84440fcULL, 0xe8d2c0211fb042bfULL, }, - { 0x22142516b5a8adbcULL, 0xe1cf1923e186aad1ULL, }, /* 96 */ - { 0x066ebbbb4ff6da44ULL, 0xd918d7e6a7e61877ULL, }, - { 0x100acc9d22839a48ULL, 0xce291932929e367fULL, }, - { 0x0dfe419d62a62f64ULL, 0xc020fe45a8cf7acfULL, }, - { 0x2ba79b6ffbf3c63bULL, 0xb428f52c49fce695ULL, }, - { 0x29b3b85200bdf100ULL, 0xb4ae7ea2f52aa5b9ULL, }, - { 0x293bb84d6360c0b6ULL, 0xae33b26e4c493c49ULL, }, - { 0x46a99fdf54f4862dULL, 0xae790dc5055f6f51ULL, }, - { 0x18480e0fd728c7c3ULL, 0xa000ad7b15f8ebe0ULL, }, /* 104 */ - { 0x1b8b97aa205e1239ULL, 0x89c78b8909c4a8e5ULL, }, - { 0x09abb26b05ef649dULL, 0x74242fa1bd49e740ULL, }, - { 0x04e233bc861d272bULL, 0x9c5343ab30f62f9fULL, }, - { 0xda2da0d0884dc3d1ULL, 0xb824f201640b4147ULL, }, - { 0x9d8b22ee1b9a2e0fULL, 0xb642ddf1edb0747fULL, }, - { 0x7c81956533686a37ULL, 0xdd5181781dc3ad37ULL, }, - { 0xc60b1905717ff25aULL, 0xe2af726e71ad7ad7ULL, }, + { 0xad45be6961639010ULL, 0x3297fdea749880a0ULL, }, /* 64 */ + { 0x9ced640a487afa10ULL, 0xeaa90809e3b1a470ULL, }, + { 0xa5b377aa0caf5a10ULL, 0x95c9a7903bd12160ULL, }, + { 0xa194ffe4fb27d390ULL, 0x17e6ccd3c9a1c0e0ULL, }, + { 0x913ca585e23f3d90ULL, 0xcff7d6f338bae4b0ULL, }, + { 0xc8ead0bee02cadd0ULL, 0x381c4d6a83a94cc0ULL, }, + { 0x33b60e279e9989d0ULL, 0xe7f71f9b97ee3470ULL, }, + { 0x217580abbfdd3e40ULL, 0x6779436687bc89f0ULL, }, + { 0x2a3b944b84119e40ULL, 0x1299e2ecdfdc06e0ULL, }, /* 72 */ + { 0x9506d1b4427e7a40ULL, 0xc274b51df420ee90ULL, }, + { 0x1b2bb7962782ba40ULL, 0x9bf62dc42637b820ULL, }, + { 0x91d16316b1663b40ULL, 0x3cf7c824fb128ca0ULL, }, + { 0x8db2eb519fdeb4c0ULL, 0xbf14ed6888e32c20ULL, }, + { 0x7b725dd5c1226930ULL, 0x3e97113378b181a0ULL, }, + { 0xf21809564b05ea30ULL, 0xdf98ab944d8c5620ULL, }, + { 0x3dcc402bfcefb9f4ULL, 0xf26a7a4530ab3a20ULL, }, + { 0x81a8956a21043af4ULL, 0xe63ec4a9de07f3a0ULL, }, /* 80 */ + { 0x14acc7eab115be94ULL, 0xa72fae300e450520ULL, }, + { 0x4c5c3900181b6494ULL, 0xc26796e561c70ba0ULL, }, + { 0x513451003792b1acULL, 0x5acad191d5b18fa0ULL, }, + { 0x0daff27cb51538acULL, 0x31375ce2aea24b20ULL, }, + { 0xbb9ebee52390b20cULL, 0xd8cfb350af547ea0ULL, }, + { 0x4df25269204a3c0cULL, 0x07b9241bbd1b8320ULL, }, + { 0x39b3c4d066371fb4ULL, 0x2a4dc00c264fb720ULL, }, + { 0xf9aee458846dd0b4ULL, 0x79d838b37c524ca0ULL, }, /* 88 */ + { 0x115f9e7f00744254ULL, 0x46ec87fe3540fa20ULL, }, + { 0xb01458f6b0850854ULL, 0xde82246a25db24a0ULL, }, + { 0xc18097bf5a7bb9ecULL, 0x4155f0da566748a0ULL, }, + { 0x70c7391b1a7d90ecULL, 0x0400deec0a0cb020ULL, }, + { 0xf7a41980bd958c4cULL, 0xedfeb14ff6d44fa0ULL, }, + { 0x7906f19718fcf64cULL, 0x29e471752ecca820ULL, }, + { 0xb6393967140b1974ULL, 0xbd0ed4c39361fc20ULL, }, + { 0x74ecb57da4acfa74ULL, 0x36ea3f3dbcafcda0ULL, }, /* 96 */ + { 0x5b14aa5e3f7c1b74ULL, 0xeb031f17fe2b7120ULL, }, + { 0x0468573ef6087c74ULL, 0xe8ef35d2e05abea0ULL, }, + { 0xd69cf5cf0de21d74ULL, 0x39f569701e89ae20ULL, }, + { 0xf233f7a10f743514ULL, 0xf574fc00c1b755a0ULL, }, + { 0x873c421a5ed469b4ULL, 0x96f393305dfcdf20ULL, }, + { 0x17e80b0449fea354ULL, 0x2f05ddb06b40c2a0ULL, }, + { 0x0741f67f982609f4ULL, 0x9c23f2dbc2b79820ULL, }, + { 0x530275e3b2de7ff4ULL, 0xc6904e7f6f6c1aa0ULL, }, /* 104 */ + { 0xf8214644bbe3f5f4ULL, 0xe44a0de01c974f20ULL, }, + { 0xb59c90c0a8b66bf4ULL, 0x9abcf7a8e1391da0ULL, }, + { 0xb67d543caed5e1f4ULL, 0x4ce8f72994d78e20ULL, }, + { 0xcee67f5e9d2e224cULL, 0xba31bdf2ab48a220ULL, }, + { 0x87acb43db40fad74ULL, 0x8a259794c40e3620ULL, }, + { 0x45c27495332aeeccULL, 0xe81c4208ecf84a20ULL, }, + { 0x50a99b794e1bc8f4ULL, 0x17cdf4c275d6de20ULL, }, }; reset_msa_registers(); diff --git a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_maddv_h.c b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_maddv_h.c index ad20f01b17..a9ee9b328a 100644 --- a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_maddv_h.c +++ b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_maddv_h.c @@ -43,118 +43,118 @@ int32_t main(void) uint64_t b128_result[TEST_COUNT_TOTAL][2]; uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { - { 0x0000000000000002ULL, 0x0000000000000002ULL, }, /* 0 */ - { 0x0000000000000002ULL, 0x0000000000000002ULL, }, - { 0x00000000aaaaaaaeULL, 0x00000000aaaaaaaeULL, }, - { 0x0000000000000004ULL, 0x0000000000000004ULL, }, - { 0x000000006666666cULL, 0x000000006666666cULL, }, - { 0x0000000000000006ULL, 0x0000000000000006ULL, }, - { 0x000000008e38e395ULL, 0xffffffffe38e38ebULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, /* 8 */ - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x00000000aaaaaab4ULL, 0x00000000aaaaaab4ULL, }, /* 16 */ - { 0x00000000aaaaaab4ULL, 0x00000000aaaaaab4ULL, }, - { 0x38e38e3a71c71c7cULL, 0x38e38e3a71c71c7cULL, }, - { 0x0000000155555560ULL, 0x0000000155555560ULL, }, - { 0x2222222444444450ULL, 0x2222222444444450ULL, }, - { 0x000000020000000cULL, 0x000000020000000cULL, }, - { 0x2f684bdcb425ed16ULL, 0xf684bda397b425faULL, }, - { 0x00000002aaaaaab8ULL, 0x00000002aaaaaab8ULL, }, - { 0x000000020000000eULL, 0x000000020000000eULL, }, /* 24 */ - { 0x000000020000000eULL, 0x000000020000000eULL, }, - { 0xc71c71c8e38e38f2ULL, 0xc71c71c8e38e38f2ULL, }, - { 0x0000000155555564ULL, 0x0000000155555564ULL, }, - { 0xdddddddeccccccdcULL, 0xdddddddeccccccdcULL, }, - { 0x00000000aaaaaabaULL, 0x00000000aaaaaabaULL, }, - { 0xd097b42684bda13fULL, 0x097b425ef684bdb1ULL, }, - { 0x0000000000000010ULL, 0x0000000000000010ULL, }, - { 0x0000000066666678ULL, 0x0000000066666678ULL, }, /* 32 */ - { 0x0000000066666678ULL, 0x0000000066666678ULL, }, - { 0x2222222355555568ULL, 0x2222222355555568ULL, }, - { 0x00000000cccccce0ULL, 0x00000000cccccce0ULL, }, - { 0x147ae1491eb85200ULL, 0x147ae1491eb85200ULL, }, - { 0x0000000133333348ULL, 0x0000000133333348ULL, }, - { 0x1c71c71e3e93e954ULL, 0xfa4fa4fbb60b60ccULL, }, - { 0x00000001999999b0ULL, 0x00000001999999b0ULL, }, - { 0x000000013333334aULL, 0x000000013333334aULL, }, /* 40 */ - { 0x000000013333334aULL, 0x000000013333334aULL, }, - { 0xdddddddeeeeeef06ULL, 0xdddddddeeeeeef06ULL, }, - { 0x00000000cccccce4ULL, 0x00000000cccccce4ULL, }, - { 0xeb851eb8e147ae2cULL, 0xeb851eb8e147ae2cULL, }, - { 0x000000006666667eULL, 0x000000006666667eULL, }, - { 0xe38e38e3e93e9401ULL, 0x05b05b05c71c71dfULL, }, - { 0x0000000000000018ULL, 0x0000000000000018ULL, }, - { 0x000000008e38e3a7ULL, 0xffffffffe38e38fdULL, }, /* 48 */ - { 0x000000008e38e3a7ULL, 0xffffffffe38e38fdULL, }, - { 0x2f684bdb425ed0b1ULL, 0xf684bda17b425eebULL, }, - { 0x000000011c71c736ULL, 0xffffffffc71c71e2ULL, }, - { 0x1c71c71e27d27d42ULL, 0xfa4fa4fa49f49f66ULL, }, - { 0x00000001aaaaaac5ULL, 0xffffffffaaaaaac7ULL, }, - { 0x35ba781b4587e6d2ULL, 0x0fcd6e9d6b74f050ULL, }, - { 0x0000000238e38e54ULL, 0xffffffff8e38e3acULL, }, - { 0x00000001aaaaaac7ULL, 0xffffffffaaaaaac9ULL, }, /* 56 */ - { 0x00000001aaaaaac7ULL, 0xffffffffaaaaaac9ULL, }, - { 0xd097b427a12f6869ULL, 0x097b425ebda12f87ULL, }, - { 0x000000011c71c73aULL, 0xffffffffc71c71e6ULL, }, - { 0xe38e38e477777796ULL, 0x05b05b05aaaaaacaULL, }, - { 0x000000008e38e3adULL, 0xffffffffe38e3903ULL, }, - { 0xca4587e781948b2fULL, 0xf032916206522c5fULL, }, - { 0x0000000000000020ULL, 0x0000000000000020ULL, }, - { 0x3e3ad4ae1266c2b0ULL, 0x1637d725aebdb734ULL, }, /* 64 */ - { 0x4c74e0d60a3d6d94ULL, 0x1badd2dd9f4dac90ULL, }, - { 0x6874e8f94205b90cULL, 0x27eb0c41af2c3022ULL, }, - { 0x42dab657e16f25e8ULL, 0x06d6782e137656f2ULL, }, - { 0x5114c27fd945d0ccULL, 0x0c4c73e604064c4eULL, }, - { 0x68a91e898c276755ULL, 0x0f77ad378bdfb302ULL, }, - { 0x54c82cde41d1cf13ULL, 0x0b6108a5f38e1598ULL, }, - { 0x6f755d3eddd1234aULL, 0xfbbaace2f5421908ULL, }, - { 0x8b75656215996ec2ULL, 0x07f7e64705209c9aULL, }, /* 72 */ - { 0x779473b6cb43d680ULL, 0x03e141b56cceff30ULL, }, - { 0xa6279a1866fb9f64ULL, 0x2631668db9e53ac1ULL, }, - { 0x67a1f71bd99e4586ULL, 0x312ec9f6206e6e69ULL, }, - { 0x4207c47a7907b262ULL, 0x101a35e284b89539ULL, }, - { 0x5cb4f4db15070699ULL, 0x0073da1f866c98a9ULL, }, - { 0x1e2f51de87a9acbbULL, 0x0b713d87ecf5cc51ULL, }, - { 0x721d49ba5f0acfa8ULL, 0x5ba5bbe9afeae691ULL, }, - { 0x4bcd68690d995de0ULL, 0x771da6b4b6c967ebULL, }, /* 80 */ - { 0x4ea9a2cfbb5acd7bULL, 0x79dd6a73439e6387ULL, }, - { 0x47c800b999dd2371ULL, 0x766d25914ef7a7a0ULL, }, - { 0x41b0fa10eb77cf84ULL, 0x26e85189458965f8ULL, }, - { 0x1fc448ce062c2944ULL, 0x31f490a9422a80e6ULL, }, - { 0x211bdfadfd79770eULL, 0x3b25f4cac5763378ULL, }, - { 0x16fbb87edd87b6f0ULL, 0x57c0b65fabdda20eULL, }, - { 0x14621091eac4a5f6ULL, 0x4d29a25d32fa9ef6ULL, }, - { 0x07832ded1c464b02ULL, 0x6396905709e3cfa4ULL, }, /* 88 */ - { 0x0ff4a84eab8df3b9ULL, 0x6bc9a7d8c6adf2eaULL, }, - { 0x21e53326bfbd0b05ULL, 0x8f8f3b9c679dff5aULL, }, - { 0x191ed6a24e1576f9ULL, 0x9e8c2e402760373aULL, }, - { 0x19b438400fc27751ULL, 0x819c4bbfd3ee6972ULL, }, - { 0x1e0d5dc1094ae999ULL, 0x7496a289f5eff010ULL, }, - { 0x11af620b7bc03943ULL, 0x8a11f229836addc7ULL, }, - { 0x46fa45d0e84440fcULL, 0xe8d2c0211fb042bfULL, }, - { 0x22142516b5a8adbcULL, 0xe1cf1923e186aad1ULL, }, /* 96 */ - { 0x066ebbbb4ff6da44ULL, 0xd918d7e6a7e61877ULL, }, - { 0x100acc9d22839a48ULL, 0xce291932929e367fULL, }, - { 0x0dfe419d62a62f64ULL, 0xc020fe45a8cf7acfULL, }, - { 0x2ba79b6ffbf3c63bULL, 0xb428f52c49fce695ULL, }, - { 0x29b3b85200bdf100ULL, 0xb4ae7ea2f52aa5b9ULL, }, - { 0x293bb84d6360c0b6ULL, 0xae33b26e4c493c49ULL, }, - { 0x46a99fdf54f4862dULL, 0xae790dc5055f6f51ULL, }, - { 0x18480e0fd728c7c3ULL, 0xa000ad7b15f8ebe0ULL, }, /* 104 */ - { 0x1b8b97aa205e1239ULL, 0x89c78b8909c4a8e5ULL, }, - { 0x09abb26b05ef649dULL, 0x74242fa1bd49e740ULL, }, - { 0x04e233bc861d272bULL, 0x9c5343ab30f62f9fULL, }, - { 0xda2da0d0884dc3d1ULL, 0xb824f201640b4147ULL, }, - { 0x9d8b22ee1b9a2e0fULL, 0xb642ddf1edb0747fULL, }, - { 0x7c81956533686a37ULL, 0xdd5181781dc3ad37ULL, }, - { 0xc60b1905717ff25aULL, 0xe2af726e71ad7ad7ULL, }, + { 0x0001000100010001ULL, 0x0001000100010001ULL, }, /* 0 */ + { 0x0001000100010001ULL, 0x0001000100010001ULL, }, + { 0x5557555755575557ULL, 0x5557555755575557ULL, }, + { 0x0002000200020002ULL, 0x0002000200020002ULL, }, + { 0x3336333633363336ULL, 0x3336333633363336ULL, }, + { 0x0003000300030003ULL, 0x0003000300030003ULL, }, + { 0x1c75c72071cb1c75ULL, 0xc72071cb1c75c720ULL, }, + { 0x0004000400040004ULL, 0x0004000400040004ULL, }, + { 0x0004000400040004ULL, 0x0004000400040004ULL, }, /* 8 */ + { 0x0004000400040004ULL, 0x0004000400040004ULL, }, + { 0x0004000400040004ULL, 0x0004000400040004ULL, }, + { 0x0004000400040004ULL, 0x0004000400040004ULL, }, + { 0x0004000400040004ULL, 0x0004000400040004ULL, }, + { 0x0004000400040004ULL, 0x0004000400040004ULL, }, + { 0x0004000400040004ULL, 0x0004000400040004ULL, }, + { 0x0004000400040004ULL, 0x0004000400040004ULL, }, + { 0x555a555a555a555aULL, 0x555a555a555a555aULL, }, /* 16 */ + { 0x555a555a555a555aULL, 0x555a555a555a555aULL, }, + { 0x8e3e8e3e8e3e8e3eULL, 0x8e3e8e3e8e3e8e3eULL, }, + { 0xaab0aab0aab0aab0ULL, 0xaab0aab0aab0aab0ULL, }, + { 0x2228222822282228ULL, 0x2228222822282228ULL, }, + { 0x0006000600060006ULL, 0x0006000600060006ULL, }, + { 0x685284c4a1366852ULL, 0x84c4a136685284c4ULL, }, + { 0x555c555c555c555cULL, 0x555c555c555c555cULL, }, + { 0x0007000700070007ULL, 0x0007000700070007ULL, }, /* 24 */ + { 0x0007000700070007ULL, 0x0007000700070007ULL, }, + { 0x1c791c791c791c79ULL, 0x1c791c791c791c79ULL, }, + { 0xaab2aab2aab2aab2ULL, 0xaab2aab2aab2aab2ULL, }, + { 0x666e666e666e666eULL, 0x666e666e666e666eULL, }, + { 0x555d555d555d555dULL, 0x555d555d555d555dULL, }, + { 0x098397bc25f50983ULL, 0x97bc25f5098397bcULL, }, + { 0x0008000800080008ULL, 0x0008000800080008ULL, }, + { 0x333c333c333c333cULL, 0x333c333c333c333cULL, }, /* 32 */ + { 0x333c333c333c333cULL, 0x333c333c333c333cULL, }, + { 0xaab4aab4aab4aab4ULL, 0xaab4aab4aab4aab4ULL, }, + { 0x6670667066706670ULL, 0x6670667066706670ULL, }, + { 0x2900290029002900ULL, 0x2900290029002900ULL, }, + { 0x99a499a499a499a4ULL, 0x99a499a499a499a4ULL, }, + { 0x16ccd2888e4416ccULL, 0xd2888e4416ccd288ULL, }, + { 0xccd8ccd8ccd8ccd8ULL, 0xccd8ccd8ccd8ccd8ULL, }, + { 0x99a599a599a599a5ULL, 0x99a599a599a599a5ULL, }, /* 40 */ + { 0x99a599a599a599a5ULL, 0x99a599a599a599a5ULL, }, + { 0x7783778377837783ULL, 0x7783778377837783ULL, }, + { 0x6672667266726672ULL, 0x6672667266726672ULL, }, + { 0xd716d716d716d716ULL, 0xd716d716d716d716ULL, }, + { 0x333f333f333f333fULL, 0x333f333f333f333fULL, }, + { 0xd289c178b067d289ULL, 0xc178b067d289c178ULL, }, + { 0x000c000c000c000cULL, 0x000c000c000c000cULL, }, + { 0x1c7ec72971d41c7eULL, 0xc72971d41c7ec729ULL, }, /* 48 */ + { 0x1c7ec72971d41c7eULL, 0xc72971d41c7ec729ULL, }, + { 0x84ca4be7130484caULL, 0x4be7130484ca4be7ULL, }, + { 0x38f08e46e39c38f0ULL, 0x8e46e39c38f08e46ULL, }, + { 0xb618c72ad83cb618ULL, 0xc72ad83cb618c72aULL, }, + { 0x5562556355645562ULL, 0x5563556455625563ULL, }, + { 0x78266eac81a47826ULL, 0x6eac81a478266eacULL, }, + { 0x71d41c80c72c71d4ULL, 0x1c80c72c71d41c80ULL, }, + { 0x5563556455655563ULL, 0x5564556555635564ULL, }, /* 56 */ + { 0x5563556455655563ULL, 0x5564556555635564ULL, }, + { 0x426d25fc098b426dULL, 0x25fc098b426d25fcULL, }, + { 0x38f28e48e39e38f2ULL, 0x8e48e39e38f28e48ULL, }, + { 0xeefe88982232eefeULL, 0x88982232eefe8898ULL, }, + { 0x1c81c72c71d71c81ULL, 0xc72c71d71c81c72cULL, }, + { 0x162f7500b75f162fULL, 0x7500b75f162f7500ULL, }, + { 0x0010001000100010ULL, 0x0010001000100010ULL, }, + { 0xcbf432a0c5949010ULL, 0x838136944f2980a0ULL, }, /* 64 */ + { 0xf8a073846fdafa10ULL, 0x81e20820066ea470ULL, }, + { 0x25e45efce9185a10ULL, 0xd1ca0ec2ee172160ULL, }, + { 0x9e9a52589fdad390ULL, 0x88c19612bccdc0e0ULL, }, + { 0xcb46933c4a203d90ULL, 0x8722679e7412e4b0ULL, }, + { 0xec4ab9850c89add0ULL, 0x31736642d9934cc0ULL, }, + { 0x15164543016689d0ULL, 0xd2dbe12880283470ULL, }, + { 0xe4b8e50ad4893e40ULL, 0xb8628f18916689f0ULL, }, + { 0x11fcd0824dc79e40ULL, 0x084a95ba790f06e0ULL, }, /* 72 */ + { 0x3ac85c4042a47a40ULL, 0xa9b210a01fa4ee90ULL, }, + { 0x4a6ce5241805ba40ULL, 0x2ff282a198ddb820ULL, }, + { 0xda320a46aaa43b40ULL, 0xaa4ae1c91cf38ca0ULL, }, + { 0x52e8fda26166b4c0ULL, 0x61416919eba92c20ULL, }, + { 0x228a9d6934896930ULL, 0x46c81709fce781a0ULL, }, + { 0xb250c28bc728ea30ULL, 0xc120763180fd5620ULL, }, + { 0xeab115b4cc89b9f4ULL, 0x1e01ac71b6013a20ULL, }, + { 0x1ffb192480fb3af4ULL, 0x7b68d8ef267cf3a0ULL, }, /* 80 */ + { 0xf545d210101cbe94ULL, 0xdcc07635cb000520ULL, }, + { 0x8b8730b052c06494ULL, 0x5ec03300e4000ba0ULL, }, + { 0xaa30f5a0a980b1acULL, 0x51803b00ac008fa0ULL, }, + { 0xa21071208c8038acULL, 0x9c00e50050004b20ULL, }, + { 0x99f03080ba00b20cULL, 0x2000270000007ea0ULL, }, + { 0xf850658020003c0cULL, 0x2000000000008320ULL, }, + { 0x9900ed0040001fb4ULL, 0x400000000000b720ULL, }, + { 0xf300c900c000d0b4ULL, 0x0000000000004ca0ULL, }, /* 88 */ + { 0x4d00840000004254ULL, 0x000000000000fa20ULL, }, + { 0x5f002c0000000854ULL, 0x00000000000024a0ULL, }, + { 0xb00068000000b9ecULL, 0x00000000000048a0ULL, }, + { 0x90004800000090ecULL, 0x000000000000b020ULL, }, + { 0x7000200000008c4cULL, 0x0000000000004fa0ULL, }, + { 0xd00060000000f64cULL, 0x000000000000a820ULL, }, + { 0x0000400000001974ULL, 0x000000000000fc20ULL, }, + { 0x000040000000fa74ULL, 0x000000000000cda0ULL, }, /* 96 */ + { 0x0000400000001b74ULL, 0x0000000000007120ULL, }, + { 0x0000400000007c74ULL, 0x000000000000bea0ULL, }, + { 0x0000400000001d74ULL, 0x000000000000ae20ULL, }, + { 0x0000000000003514ULL, 0x00000000000055a0ULL, }, + { 0x00000000000069b4ULL, 0x000000000000df20ULL, }, + { 0x000000000000a354ULL, 0x000000000000c2a0ULL, }, + { 0x00000000000009f4ULL, 0x0000000000009820ULL, }, + { 0x0000000000007ff4ULL, 0x0000000000001aa0ULL, }, /* 104 */ + { 0x000000000000f5f4ULL, 0x0000000000004f20ULL, }, + { 0x0000000000006bf4ULL, 0x0000000000001da0ULL, }, + { 0x000000000000e1f4ULL, 0x0000000000008e20ULL, }, + { 0x000000000000224cULL, 0x000000000000a220ULL, }, + { 0x000000000000ad74ULL, 0x0000000000003620ULL, }, + { 0x000000000000eeccULL, 0x0000000000004a20ULL, }, + { 0x000000000000c8f4ULL, 0x000000000000de20ULL, }, }; reset_msa_registers(); diff --git a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_maddv_w.c b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_maddv_w.c index 09f01d36b7..bc3f5d246e 100644 --- a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_maddv_w.c +++ b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_maddv_w.c @@ -43,118 +43,118 @@ int32_t main(void) uint64_t b128_result[TEST_COUNT_TOTAL][2]; uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { - { 0x0000000000000002ULL, 0x0000000000000002ULL, }, /* 0 */ - { 0x0000000000000002ULL, 0x0000000000000002ULL, }, - { 0x00000000aaaaaaaeULL, 0x00000000aaaaaaaeULL, }, - { 0x0000000000000004ULL, 0x0000000000000004ULL, }, - { 0x000000006666666cULL, 0x000000006666666cULL, }, - { 0x0000000000000006ULL, 0x0000000000000006ULL, }, - { 0x000000008e38e395ULL, 0xffffffffe38e38ebULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, /* 8 */ - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x00000000aaaaaab4ULL, 0x00000000aaaaaab4ULL, }, /* 16 */ - { 0x00000000aaaaaab4ULL, 0x00000000aaaaaab4ULL, }, - { 0x38e38e3a71c71c7cULL, 0x38e38e3a71c71c7cULL, }, - { 0x0000000155555560ULL, 0x0000000155555560ULL, }, - { 0x2222222444444450ULL, 0x2222222444444450ULL, }, - { 0x000000020000000cULL, 0x000000020000000cULL, }, - { 0x2f684bdcb425ed16ULL, 0xf684bda397b425faULL, }, - { 0x00000002aaaaaab8ULL, 0x00000002aaaaaab8ULL, }, - { 0x000000020000000eULL, 0x000000020000000eULL, }, /* 24 */ - { 0x000000020000000eULL, 0x000000020000000eULL, }, - { 0xc71c71c8e38e38f2ULL, 0xc71c71c8e38e38f2ULL, }, - { 0x0000000155555564ULL, 0x0000000155555564ULL, }, - { 0xdddddddeccccccdcULL, 0xdddddddeccccccdcULL, }, - { 0x00000000aaaaaabaULL, 0x00000000aaaaaabaULL, }, - { 0xd097b42684bda13fULL, 0x097b425ef684bdb1ULL, }, - { 0x0000000000000010ULL, 0x0000000000000010ULL, }, - { 0x0000000066666678ULL, 0x0000000066666678ULL, }, /* 32 */ - { 0x0000000066666678ULL, 0x0000000066666678ULL, }, - { 0x2222222355555568ULL, 0x2222222355555568ULL, }, - { 0x00000000cccccce0ULL, 0x00000000cccccce0ULL, }, - { 0x147ae1491eb85200ULL, 0x147ae1491eb85200ULL, }, - { 0x0000000133333348ULL, 0x0000000133333348ULL, }, - { 0x1c71c71e3e93e954ULL, 0xfa4fa4fbb60b60ccULL, }, - { 0x00000001999999b0ULL, 0x00000001999999b0ULL, }, - { 0x000000013333334aULL, 0x000000013333334aULL, }, /* 40 */ - { 0x000000013333334aULL, 0x000000013333334aULL, }, - { 0xdddddddeeeeeef06ULL, 0xdddddddeeeeeef06ULL, }, - { 0x00000000cccccce4ULL, 0x00000000cccccce4ULL, }, - { 0xeb851eb8e147ae2cULL, 0xeb851eb8e147ae2cULL, }, - { 0x000000006666667eULL, 0x000000006666667eULL, }, - { 0xe38e38e3e93e9401ULL, 0x05b05b05c71c71dfULL, }, - { 0x0000000000000018ULL, 0x0000000000000018ULL, }, - { 0x000000008e38e3a7ULL, 0xffffffffe38e38fdULL, }, /* 48 */ - { 0x000000008e38e3a7ULL, 0xffffffffe38e38fdULL, }, - { 0x2f684bdb425ed0b1ULL, 0xf684bda17b425eebULL, }, - { 0x000000011c71c736ULL, 0xffffffffc71c71e2ULL, }, - { 0x1c71c71e27d27d42ULL, 0xfa4fa4fa49f49f66ULL, }, - { 0x00000001aaaaaac5ULL, 0xffffffffaaaaaac7ULL, }, - { 0x35ba781b4587e6d2ULL, 0x0fcd6e9d6b74f050ULL, }, - { 0x0000000238e38e54ULL, 0xffffffff8e38e3acULL, }, - { 0x00000001aaaaaac7ULL, 0xffffffffaaaaaac9ULL, }, /* 56 */ - { 0x00000001aaaaaac7ULL, 0xffffffffaaaaaac9ULL, }, - { 0xd097b427a12f6869ULL, 0x097b425ebda12f87ULL, }, - { 0x000000011c71c73aULL, 0xffffffffc71c71e6ULL, }, - { 0xe38e38e477777796ULL, 0x05b05b05aaaaaacaULL, }, - { 0x000000008e38e3adULL, 0xffffffffe38e3903ULL, }, - { 0xca4587e781948b2fULL, 0xf032916206522c5fULL, }, - { 0x0000000000000020ULL, 0x0000000000000020ULL, }, - { 0x3e3ad4ae1266c2b0ULL, 0x1637d725aebdb734ULL, }, /* 64 */ - { 0x4c74e0d60a3d6d94ULL, 0x1badd2dd9f4dac90ULL, }, - { 0x6874e8f94205b90cULL, 0x27eb0c41af2c3022ULL, }, - { 0x42dab657e16f25e8ULL, 0x06d6782e137656f2ULL, }, - { 0x5114c27fd945d0ccULL, 0x0c4c73e604064c4eULL, }, - { 0x68a91e898c276755ULL, 0x0f77ad378bdfb302ULL, }, - { 0x54c82cde41d1cf13ULL, 0x0b6108a5f38e1598ULL, }, - { 0x6f755d3eddd1234aULL, 0xfbbaace2f5421908ULL, }, - { 0x8b75656215996ec2ULL, 0x07f7e64705209c9aULL, }, /* 72 */ - { 0x779473b6cb43d680ULL, 0x03e141b56cceff30ULL, }, - { 0xa6279a1866fb9f64ULL, 0x2631668db9e53ac1ULL, }, - { 0x67a1f71bd99e4586ULL, 0x312ec9f6206e6e69ULL, }, - { 0x4207c47a7907b262ULL, 0x101a35e284b89539ULL, }, - { 0x5cb4f4db15070699ULL, 0x0073da1f866c98a9ULL, }, - { 0x1e2f51de87a9acbbULL, 0x0b713d87ecf5cc51ULL, }, - { 0x721d49ba5f0acfa8ULL, 0x5ba5bbe9afeae691ULL, }, - { 0x4bcd68690d995de0ULL, 0x771da6b4b6c967ebULL, }, /* 80 */ - { 0x4ea9a2cfbb5acd7bULL, 0x79dd6a73439e6387ULL, }, - { 0x47c800b999dd2371ULL, 0x766d25914ef7a7a0ULL, }, - { 0x41b0fa10eb77cf84ULL, 0x26e85189458965f8ULL, }, - { 0x1fc448ce062c2944ULL, 0x31f490a9422a80e6ULL, }, - { 0x211bdfadfd79770eULL, 0x3b25f4cac5763378ULL, }, - { 0x16fbb87edd87b6f0ULL, 0x57c0b65fabdda20eULL, }, - { 0x14621091eac4a5f6ULL, 0x4d29a25d32fa9ef6ULL, }, - { 0x07832ded1c464b02ULL, 0x6396905709e3cfa4ULL, }, /* 88 */ - { 0x0ff4a84eab8df3b9ULL, 0x6bc9a7d8c6adf2eaULL, }, - { 0x21e53326bfbd0b05ULL, 0x8f8f3b9c679dff5aULL, }, - { 0x191ed6a24e1576f9ULL, 0x9e8c2e402760373aULL, }, - { 0x19b438400fc27751ULL, 0x819c4bbfd3ee6972ULL, }, - { 0x1e0d5dc1094ae999ULL, 0x7496a289f5eff010ULL, }, - { 0x11af620b7bc03943ULL, 0x8a11f229836addc7ULL, }, - { 0x46fa45d0e84440fcULL, 0xe8d2c0211fb042bfULL, }, - { 0x22142516b5a8adbcULL, 0xe1cf1923e186aad1ULL, }, /* 96 */ - { 0x066ebbbb4ff6da44ULL, 0xd918d7e6a7e61877ULL, }, - { 0x100acc9d22839a48ULL, 0xce291932929e367fULL, }, - { 0x0dfe419d62a62f64ULL, 0xc020fe45a8cf7acfULL, }, - { 0x2ba79b6ffbf3c63bULL, 0xb428f52c49fce695ULL, }, - { 0x29b3b85200bdf100ULL, 0xb4ae7ea2f52aa5b9ULL, }, - { 0x293bb84d6360c0b6ULL, 0xae33b26e4c493c49ULL, }, - { 0x46a99fdf54f4862dULL, 0xae790dc5055f6f51ULL, }, - { 0x18480e0fd728c7c3ULL, 0xa000ad7b15f8ebe0ULL, }, /* 104 */ - { 0x1b8b97aa205e1239ULL, 0x89c78b8909c4a8e5ULL, }, - { 0x09abb26b05ef649dULL, 0x74242fa1bd49e740ULL, }, - { 0x04e233bc861d272bULL, 0x9c5343ab30f62f9fULL, }, - { 0xda2da0d0884dc3d1ULL, 0xb824f201640b4147ULL, }, - { 0x9d8b22ee1b9a2e0fULL, 0xb642ddf1edb0747fULL, }, - { 0x7c81956533686a37ULL, 0xdd5181781dc3ad37ULL, }, - { 0xc60b1905717ff25aULL, 0xe2af726e71ad7ad7ULL, }, + { 0x0000000100000001ULL, 0x0000000100000001ULL, }, /* 0 */ + { 0x0000000100000001ULL, 0x0000000100000001ULL, }, + { 0x5555555755555557ULL, 0x5555555755555557ULL, }, + { 0x0000000200000002ULL, 0x0000000200000002ULL, }, + { 0x3333333633333336ULL, 0x3333333633333336ULL, }, + { 0x0000000300000003ULL, 0x0000000300000003ULL, }, + { 0x1c71c72071c71c75ULL, 0xc71c71cb1c71c720ULL, }, + { 0x0000000400000004ULL, 0x0000000400000004ULL, }, + { 0x0000000400000004ULL, 0x0000000400000004ULL, }, /* 8 */ + { 0x0000000400000004ULL, 0x0000000400000004ULL, }, + { 0x0000000400000004ULL, 0x0000000400000004ULL, }, + { 0x0000000400000004ULL, 0x0000000400000004ULL, }, + { 0x0000000400000004ULL, 0x0000000400000004ULL, }, + { 0x0000000400000004ULL, 0x0000000400000004ULL, }, + { 0x0000000400000004ULL, 0x0000000400000004ULL, }, + { 0x0000000400000004ULL, 0x0000000400000004ULL, }, + { 0x5555555a5555555aULL, 0x5555555a5555555aULL, }, /* 16 */ + { 0x5555555a5555555aULL, 0x5555555a5555555aULL, }, + { 0x38e38e3e38e38e3eULL, 0x38e38e3e38e38e3eULL, }, + { 0xaaaaaab0aaaaaab0ULL, 0xaaaaaab0aaaaaab0ULL, }, + { 0x2222222822222228ULL, 0x2222222822222228ULL, }, + { 0x0000000600000006ULL, 0x0000000600000006ULL, }, + { 0x12f684c4a12f6852ULL, 0x84bda13612f684c4ULL, }, + { 0x5555555c5555555cULL, 0x5555555c5555555cULL, }, + { 0x0000000700000007ULL, 0x0000000700000007ULL, }, /* 24 */ + { 0x0000000700000007ULL, 0x0000000700000007ULL, }, + { 0x71c71c7971c71c79ULL, 0x71c71c7971c71c79ULL, }, + { 0xaaaaaab2aaaaaab2ULL, 0xaaaaaab2aaaaaab2ULL, }, + { 0x6666666e6666666eULL, 0x6666666e6666666eULL, }, + { 0x5555555d5555555dULL, 0x5555555d5555555dULL, }, + { 0x5ed097bc25ed0983ULL, 0x97b425f55ed097bcULL, }, + { 0x0000000800000008ULL, 0x0000000800000008ULL, }, + { 0x3333333c3333333cULL, 0x3333333c3333333cULL, }, /* 32 */ + { 0x3333333c3333333cULL, 0x3333333c3333333cULL, }, + { 0xaaaaaab4aaaaaab4ULL, 0xaaaaaab4aaaaaab4ULL, }, + { 0x6666667066666670ULL, 0x6666667066666670ULL, }, + { 0x8f5c29008f5c2900ULL, 0x8f5c29008f5c2900ULL, }, + { 0x999999a4999999a4ULL, 0x999999a4999999a4ULL, }, + { 0x7d27d288c16c16ccULL, 0x38e38e447d27d288ULL, }, + { 0xccccccd8ccccccd8ULL, 0xccccccd8ccccccd8ULL, }, + { 0x999999a5999999a5ULL, 0x999999a5999999a5ULL, }, /* 40 */ + { 0x999999a5999999a5ULL, 0x999999a5999999a5ULL, }, + { 0x7777778377777783ULL, 0x7777778377777783ULL, }, + { 0x6666667266666672ULL, 0x6666667266666672ULL, }, + { 0x70a3d71670a3d716ULL, 0x70a3d71670a3d716ULL, }, + { 0x3333333f3333333fULL, 0x3333333f3333333fULL, }, + { 0x6c16c1787d27d289ULL, 0x5b05b0676c16c178ULL, }, + { 0x0000000c0000000cULL, 0x0000000c0000000cULL, }, + { 0x1c71c72971c71c7eULL, 0xc71c71d41c71c729ULL, }, /* 48 */ + { 0x1c71c72971c71c7eULL, 0xc71c71d41c71c729ULL, }, + { 0x2f684be712f684caULL, 0x4bda13042f684be7ULL, }, + { 0x38e38e46e38e38f0ULL, 0x8e38e39c38e38e46ULL, }, + { 0x1c71c72a0b60b618ULL, 0x2d82d83c1c71c72aULL, }, + { 0x5555556355555562ULL, 0x5555556455555563ULL, }, + { 0x0fcd6eac35ba7826ULL, 0x5ba781a40fcd6eacULL, }, + { 0x71c71c80c71c71d4ULL, 0x1c71c72c71c71c80ULL, }, + { 0x5555556455555563ULL, 0x5555556555555564ULL, }, /* 56 */ + { 0x5555556455555563ULL, 0x5555556555555564ULL, }, + { 0x97b425fc097b426dULL, 0x25ed098b97b425fcULL, }, + { 0x38e38e48e38e38f2ULL, 0x8e38e39e38e38e48ULL, }, + { 0x88888898eeeeeefeULL, 0x2222223288888898ULL, }, + { 0x1c71c72c71c71c81ULL, 0xc71c71d71c71c72cULL, }, + { 0x7e6b75000329162fULL, 0x87e6b75f7e6b7500ULL, }, + { 0x0000001000000010ULL, 0x0000001000000010ULL, }, + { 0xb10332a061639010ULL, 0x3a253694749880a0ULL, }, /* 64 */ + { 0xc1c27384487afa10ULL, 0xbb9c0820e3b1a470ULL, }, + { 0x35565efc0caf5a10ULL, 0x735b0ec23bd12160ULL, }, + { 0xe6475258fb27d390ULL, 0x49d49612c9a1c0e0ULL, }, + { 0xf706933ce23f3d90ULL, 0xcb4b679e38bae4b0ULL, }, + { 0xabfab985e02cadd0ULL, 0x0836664283a94cc0ULL, }, + { 0xa33845439e9989d0ULL, 0x5b9fe12897ee3470ULL, }, + { 0x1df3e50abfdd3e40ULL, 0x6d858f1887bc89f0ULL, }, + { 0x9187d08284119e40ULL, 0x254495badfdc06e0ULL, }, /* 72 */ + { 0x88c55c40427e7a40ULL, 0x78ae10a0f420ee90ULL, }, + { 0x3f78e5242782ba40ULL, 0x93ad82a12637b820ULL, }, + { 0x28380a46b1663b40ULL, 0x255be1c9fb128ca0ULL, }, + { 0xd928fda29fdeb4c0ULL, 0xfbd5691988e32c20ULL, }, + { 0x53e49d69c1226930ULL, 0x0dbb170978b181a0ULL, }, + { 0x3ca3c28b4b05ea30ULL, 0x9f6976314d8c5620ULL, }, + { 0x621b15b4fcefb9f4ULL, 0x7f3fac7130ab3a20ULL, }, + { 0x81b8192421043af4ULL, 0x7180d8efde07f3a0ULL, }, /* 80 */ + { 0xa0a1d210b115be94ULL, 0x33a676350e450520ULL, }, + { 0xe27e30b0181b6494ULL, 0x359b330061c70ba0ULL, }, + { 0xe0f1f5a03792b1acULL, 0xe6a63b00d5b18fa0ULL, }, + { 0x38af7120b51538acULL, 0x7938e500aea24b20ULL, }, + { 0x7a4830802390b20cULL, 0x4b472700af547ea0ULL, }, + { 0xcc2f6580204a3c0cULL, 0x37510000bd1b8320ULL, }, + { 0x9ba9ed0066371fb4ULL, 0xeba90000264fb720ULL, }, + { 0x7400c900846dd0b4ULL, 0xb6b700007c524ca0ULL, }, /* 88 */ + { 0x7e4e840000744254ULL, 0xf24d00003540fa20ULL, }, + { 0x242a2c00b0850854ULL, 0xdb00000025db24a0ULL, }, + { 0x38a168005a7bb9ecULL, 0xa3000000566748a0ULL, }, + { 0x6cb048001a7d90ecULL, 0x7d0000000a0cb020ULL, }, + { 0xe4dc2000bd958c4cULL, 0x2f000000f6d44fa0ULL, }, + { 0xbcc9600018fcf64cULL, 0x000000002ecca820ULL, }, + { 0x739b4000140b1974ULL, 0x000000009361fc20ULL, }, + { 0x8ed24000a4acfa74ULL, 0x00000000bcafcda0ULL, }, /* 96 */ + { 0xc3dd40003f7c1b74ULL, 0x00000000fe2b7120ULL, }, + { 0x1fac4000f6087c74ULL, 0x00000000e05abea0ULL, }, + { 0x9e6f40000de21d74ULL, 0x000000001e89ae20ULL, }, + { 0x637500000f743514ULL, 0x00000000c1b755a0ULL, }, + { 0xd9b400005ed469b4ULL, 0x000000005dfcdf20ULL, }, + { 0x0a50000049fea354ULL, 0x000000006b40c2a0ULL, }, + { 0x07400000982609f4ULL, 0x00000000c2b79820ULL, }, + { 0x57c00000b2de7ff4ULL, 0x000000006f6c1aa0ULL, }, /* 104 */ + { 0x1d400000bbe3f5f4ULL, 0x000000001c974f20ULL, }, + { 0x09c00000a8b66bf4ULL, 0x00000000e1391da0ULL, }, + { 0x03400000aed5e1f4ULL, 0x0000000094d78e20ULL, }, + { 0x7d8000009d2e224cULL, 0x00000000ab48a220ULL, }, + { 0x3d000000b40fad74ULL, 0x00000000c40e3620ULL, }, + { 0x96000000332aeeccULL, 0x00000000ecf84a20ULL, }, + { 0xb40000004e1bc8f4ULL, 0x0000000075d6de20ULL, }, }; reset_msa_registers(); diff --git a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_msubv_b.c b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_msubv_b.c index b68b57f51d..808c49d050 100644 --- a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_msubv_b.c +++ b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_msubv_b.c @@ -43,118 +43,118 @@ int32_t main(void) uint64_t b128_result[TEST_COUNT_TOTAL][2]; uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { - { 0x0000000000000002ULL, 0x0000000000000002ULL, }, /* 0 */ - { 0x0000000000000002ULL, 0x0000000000000002ULL, }, - { 0x00000000aaaaaaaeULL, 0x00000000aaaaaaaeULL, }, - { 0x0000000000000004ULL, 0x0000000000000004ULL, }, - { 0x000000006666666cULL, 0x000000006666666cULL, }, - { 0x0000000000000006ULL, 0x0000000000000006ULL, }, - { 0x000000008e38e395ULL, 0xffffffffe38e38ebULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, /* 8 */ - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x00000000aaaaaab4ULL, 0x00000000aaaaaab4ULL, }, /* 16 */ - { 0x00000000aaaaaab4ULL, 0x00000000aaaaaab4ULL, }, - { 0x38e38e3a71c71c7cULL, 0x38e38e3a71c71c7cULL, }, - { 0x0000000155555560ULL, 0x0000000155555560ULL, }, - { 0x2222222444444450ULL, 0x2222222444444450ULL, }, - { 0x000000020000000cULL, 0x000000020000000cULL, }, - { 0x2f684bdcb425ed16ULL, 0xf684bda397b425faULL, }, - { 0x00000002aaaaaab8ULL, 0x00000002aaaaaab8ULL, }, - { 0x000000020000000eULL, 0x000000020000000eULL, }, /* 24 */ - { 0x000000020000000eULL, 0x000000020000000eULL, }, - { 0xc71c71c8e38e38f2ULL, 0xc71c71c8e38e38f2ULL, }, - { 0x0000000155555564ULL, 0x0000000155555564ULL, }, - { 0xdddddddeccccccdcULL, 0xdddddddeccccccdcULL, }, - { 0x00000000aaaaaabaULL, 0x00000000aaaaaabaULL, }, - { 0xd097b42684bda13fULL, 0x097b425ef684bdb1ULL, }, - { 0x0000000000000010ULL, 0x0000000000000010ULL, }, - { 0x0000000066666678ULL, 0x0000000066666678ULL, }, /* 32 */ - { 0x0000000066666678ULL, 0x0000000066666678ULL, }, - { 0x2222222355555568ULL, 0x2222222355555568ULL, }, - { 0x00000000cccccce0ULL, 0x00000000cccccce0ULL, }, - { 0x147ae1491eb85200ULL, 0x147ae1491eb85200ULL, }, - { 0x0000000133333348ULL, 0x0000000133333348ULL, }, - { 0x1c71c71e3e93e954ULL, 0xfa4fa4fbb60b60ccULL, }, - { 0x00000001999999b0ULL, 0x00000001999999b0ULL, }, - { 0x000000013333334aULL, 0x000000013333334aULL, }, /* 40 */ - { 0x000000013333334aULL, 0x000000013333334aULL, }, - { 0xdddddddeeeeeef06ULL, 0xdddddddeeeeeef06ULL, }, - { 0x00000000cccccce4ULL, 0x00000000cccccce4ULL, }, - { 0xeb851eb8e147ae2cULL, 0xeb851eb8e147ae2cULL, }, - { 0x000000006666667eULL, 0x000000006666667eULL, }, - { 0xe38e38e3e93e9401ULL, 0x05b05b05c71c71dfULL, }, - { 0x0000000000000018ULL, 0x0000000000000018ULL, }, - { 0x000000008e38e3a7ULL, 0xffffffffe38e38fdULL, }, /* 48 */ - { 0x000000008e38e3a7ULL, 0xffffffffe38e38fdULL, }, - { 0x2f684bdb425ed0b1ULL, 0xf684bda17b425eebULL, }, - { 0x000000011c71c736ULL, 0xffffffffc71c71e2ULL, }, - { 0x1c71c71e27d27d42ULL, 0xfa4fa4fa49f49f66ULL, }, - { 0x00000001aaaaaac5ULL, 0xffffffffaaaaaac7ULL, }, - { 0x35ba781b4587e6d2ULL, 0x0fcd6e9d6b74f050ULL, }, - { 0x0000000238e38e54ULL, 0xffffffff8e38e3acULL, }, - { 0x00000001aaaaaac7ULL, 0xffffffffaaaaaac9ULL, }, /* 56 */ - { 0x00000001aaaaaac7ULL, 0xffffffffaaaaaac9ULL, }, - { 0xd097b427a12f6869ULL, 0x097b425ebda12f87ULL, }, - { 0x000000011c71c73aULL, 0xffffffffc71c71e6ULL, }, - { 0xe38e38e477777796ULL, 0x05b05b05aaaaaacaULL, }, - { 0x000000008e38e3adULL, 0xffffffffe38e3903ULL, }, - { 0xca4587e781948b2fULL, 0xf032916206522c5fULL, }, - { 0x0000000000000020ULL, 0x0000000000000020ULL, }, - { 0x3e3ad4ae1266c2b0ULL, 0x1637d725aebdb734ULL, }, /* 64 */ - { 0x4c74e0d60a3d6d94ULL, 0x1badd2dd9f4dac90ULL, }, - { 0x6874e8f94205b90cULL, 0x27eb0c41af2c3022ULL, }, - { 0x42dab657e16f25e8ULL, 0x06d6782e137656f2ULL, }, - { 0x5114c27fd945d0ccULL, 0x0c4c73e604064c4eULL, }, - { 0x68a91e898c276755ULL, 0x0f77ad378bdfb302ULL, }, - { 0x54c82cde41d1cf13ULL, 0x0b6108a5f38e1598ULL, }, - { 0x6f755d3eddd1234aULL, 0xfbbaace2f5421908ULL, }, - { 0x8b75656215996ec2ULL, 0x07f7e64705209c9aULL, }, /* 72 */ - { 0x779473b6cb43d680ULL, 0x03e141b56cceff30ULL, }, - { 0xa6279a1866fb9f64ULL, 0x2631668db9e53ac1ULL, }, - { 0x67a1f71bd99e4586ULL, 0x312ec9f6206e6e69ULL, }, - { 0x4207c47a7907b262ULL, 0x101a35e284b89539ULL, }, - { 0x5cb4f4db15070699ULL, 0x0073da1f866c98a9ULL, }, - { 0x1e2f51de87a9acbbULL, 0x0b713d87ecf5cc51ULL, }, - { 0x721d49ba5f0acfa8ULL, 0x5ba5bbe9afeae691ULL, }, - { 0x4bcd68690d995de0ULL, 0x771da6b4b6c967ebULL, }, /* 80 */ - { 0x4ea9a2cfbb5acd7bULL, 0x79dd6a73439e6387ULL, }, - { 0x47c800b999dd2371ULL, 0x766d25914ef7a7a0ULL, }, - { 0x41b0fa10eb77cf84ULL, 0x26e85189458965f8ULL, }, - { 0x1fc448ce062c2944ULL, 0x31f490a9422a80e6ULL, }, - { 0x211bdfadfd79770eULL, 0x3b25f4cac5763378ULL, }, - { 0x16fbb87edd87b6f0ULL, 0x57c0b65fabdda20eULL, }, - { 0x14621091eac4a5f6ULL, 0x4d29a25d32fa9ef6ULL, }, - { 0x07832ded1c464b02ULL, 0x6396905709e3cfa4ULL, }, /* 88 */ - { 0x0ff4a84eab8df3b9ULL, 0x6bc9a7d8c6adf2eaULL, }, - { 0x21e53326bfbd0b05ULL, 0x8f8f3b9c679dff5aULL, }, - { 0x191ed6a24e1576f9ULL, 0x9e8c2e402760373aULL, }, - { 0x19b438400fc27751ULL, 0x819c4bbfd3ee6972ULL, }, - { 0x1e0d5dc1094ae999ULL, 0x7496a289f5eff010ULL, }, - { 0x11af620b7bc03943ULL, 0x8a11f229836addc7ULL, }, - { 0x46fa45d0e84440fcULL, 0xe8d2c0211fb042bfULL, }, - { 0x22142516b5a8adbcULL, 0xe1cf1923e186aad1ULL, }, /* 96 */ - { 0x066ebbbb4ff6da44ULL, 0xd918d7e6a7e61877ULL, }, - { 0x100acc9d22839a48ULL, 0xce291932929e367fULL, }, - { 0x0dfe419d62a62f64ULL, 0xc020fe45a8cf7acfULL, }, - { 0x2ba79b6ffbf3c63bULL, 0xb428f52c49fce695ULL, }, - { 0x29b3b85200bdf100ULL, 0xb4ae7ea2f52aa5b9ULL, }, - { 0x293bb84d6360c0b6ULL, 0xae33b26e4c493c49ULL, }, - { 0x46a99fdf54f4862dULL, 0xae790dc5055f6f51ULL, }, - { 0x18480e0fd728c7c3ULL, 0xa000ad7b15f8ebe0ULL, }, /* 104 */ - { 0x1b8b97aa205e1239ULL, 0x89c78b8909c4a8e5ULL, }, - { 0x09abb26b05ef649dULL, 0x74242fa1bd49e740ULL, }, - { 0x04e233bc861d272bULL, 0x9c5343ab30f62f9fULL, }, - { 0xda2da0d0884dc3d1ULL, 0xb824f201640b4147ULL, }, - { 0x9d8b22ee1b9a2e0fULL, 0xb642ddf1edb0747fULL, }, - { 0x7c81956533686a37ULL, 0xdd5181781dc3ad37ULL, }, - { 0xc60b1905717ff25aULL, 0xe2af726e71ad7ad7ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xa9a9a9a9a9a9a9a9ULL, 0xa9a9a9a9a9a9a9a9ULL, }, + { 0xfefefefefefefefeULL, 0xfefefefefefefefeULL, }, + { 0xcacacacacacacacaULL, 0xcacacacacacacacaULL, }, + { 0xfdfdfdfdfdfdfdfdULL, 0xfdfdfdfdfdfdfdfdULL, }, + { 0xe08b35e08b35e08bULL, 0x35e08b35e08b35e0ULL, }, + { 0xfcfcfcfcfcfcfcfcULL, 0xfcfcfcfcfcfcfcfcULL, }, + { 0xfcfcfcfcfcfcfcfcULL, 0xfcfcfcfcfcfcfcfcULL, }, /* 8 */ + { 0xfcfcfcfcfcfcfcfcULL, 0xfcfcfcfcfcfcfcfcULL, }, + { 0xfcfcfcfcfcfcfcfcULL, 0xfcfcfcfcfcfcfcfcULL, }, + { 0xfcfcfcfcfcfcfcfcULL, 0xfcfcfcfcfcfcfcfcULL, }, + { 0xfcfcfcfcfcfcfcfcULL, 0xfcfcfcfcfcfcfcfcULL, }, + { 0xfcfcfcfcfcfcfcfcULL, 0xfcfcfcfcfcfcfcfcULL, }, + { 0xfcfcfcfcfcfcfcfcULL, 0xfcfcfcfcfcfcfcfcULL, }, + { 0xfcfcfcfcfcfcfcfcULL, 0xfcfcfcfcfcfcfcfcULL, }, + { 0xa6a6a6a6a6a6a6a6ULL, 0xa6a6a6a6a6a6a6a6ULL, }, /* 16 */ + { 0xa6a6a6a6a6a6a6a6ULL, 0xa6a6a6a6a6a6a6a6ULL, }, + { 0xc2c2c2c2c2c2c2c2ULL, 0xc2c2c2c2c2c2c2c2ULL, }, + { 0x5050505050505050ULL, 0x5050505050505050ULL, }, + { 0xd8d8d8d8d8d8d8d8ULL, 0xd8d8d8d8d8d8d8d8ULL, }, + { 0xfafafafafafafafaULL, 0xfafafafafafafafaULL, }, + { 0x3caeca3caeca3caeULL, 0xca3caeca3caeca3cULL, }, + { 0xa4a4a4a4a4a4a4a4ULL, 0xa4a4a4a4a4a4a4a4ULL, }, + { 0xf9f9f9f9f9f9f9f9ULL, 0xf9f9f9f9f9f9f9f9ULL, }, /* 24 */ + { 0xf9f9f9f9f9f9f9f9ULL, 0xf9f9f9f9f9f9f9f9ULL, }, + { 0x8787878787878787ULL, 0x8787878787878787ULL, }, + { 0x4e4e4e4e4e4e4e4eULL, 0x4e4e4e4e4e4e4e4eULL, }, + { 0x9292929292929292ULL, 0x9292929292929292ULL, }, + { 0xa3a3a3a3a3a3a3a3ULL, 0xa3a3a3a3a3a3a3a3ULL, }, + { 0x447d0b447d0b447dULL, 0x0b447d0b447d0b44ULL, }, + { 0xf8f8f8f8f8f8f8f8ULL, 0xf8f8f8f8f8f8f8f8ULL, }, + { 0xc4c4c4c4c4c4c4c4ULL, 0xc4c4c4c4c4c4c4c4ULL, }, /* 32 */ + { 0xc4c4c4c4c4c4c4c4ULL, 0xc4c4c4c4c4c4c4c4ULL, }, + { 0x4c4c4c4c4c4c4c4cULL, 0x4c4c4c4c4c4c4c4cULL, }, + { 0x9090909090909090ULL, 0x9090909090909090ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x5c5c5c5c5c5c5c5cULL, 0x5c5c5c5c5c5c5c5cULL, }, + { 0x7834bc7834bc7834ULL, 0xbc7834bc7834bc78ULL, }, + { 0x2828282828282828ULL, 0x2828282828282828ULL, }, + { 0x5b5b5b5b5b5b5b5bULL, 0x5b5b5b5b5b5b5b5bULL, }, /* 40 */ + { 0x5b5b5b5b5b5b5b5bULL, 0x5b5b5b5b5b5b5b5bULL, }, + { 0x7d7d7d7d7d7d7d7dULL, 0x7d7d7d7d7d7d7d7dULL, }, + { 0x8e8e8e8e8e8e8e8eULL, 0x8e8e8e8e8e8e8e8eULL, }, + { 0xeaeaeaeaeaeaeaeaULL, 0xeaeaeaeaeaeaeaeaULL, }, + { 0xc1c1c1c1c1c1c1c1ULL, 0xc1c1c1c1c1c1c1c1ULL, }, + { 0x8877998877998877ULL, 0x9988779988779988ULL, }, + { 0xf4f4f4f4f4f4f4f4ULL, 0xf4f4f4f4f4f4f4f4ULL, }, + { 0xd7822cd7822cd782ULL, 0x2cd7822cd7822cd7ULL, }, /* 48 */ + { 0xd7822cd7822cd782ULL, 0x2cd7822cd7822cd7ULL, }, + { 0x1936fc1936fc1936ULL, 0xfc1936fc1936fc19ULL, }, + { 0xba1064ba1064ba10ULL, 0x64ba1064ba1064baULL, }, + { 0xd6e8c4d6e8c4d6e8ULL, 0xc4d6e8c4d6e8c4d6ULL, }, + { 0x9d9e9c9d9e9c9d9eULL, 0x9c9d9e9c9d9e9c9dULL, }, + { 0x54da5c54da5c54daULL, 0x5c54da5c54da5c54ULL, }, + { 0x802cd4802cd4802cULL, 0xd4802cd4802cd480ULL, }, + { 0x9c9d9b9c9d9b9c9dULL, 0x9b9c9d9b9c9d9b9cULL, }, /* 56 */ + { 0x9c9d9b9c9d9b9c9dULL, 0x9b9c9d9b9c9d9b9cULL, }, + { 0x0493750493750493ULL, 0x7504937504937504ULL, }, + { 0xb80e62b80e62b80eULL, 0x62b80e62b80e62b8ULL, }, + { 0x6802ce6802ce6802ULL, 0xce6802ce6802ce68ULL, }, + { 0xd47f29d47f29d47fULL, 0x29d47f29d47f29d4ULL, }, + { 0x00d1a100d1a100d1ULL, 0xa100d1a100d1a100ULL, }, + { 0xf0f0f0f0f0f0f0f0ULL, 0xf0f0f0f0f0f0f0f0ULL, }, + { 0xb00c4c60b06cb7f0ULL, 0xf77f776cecd7f060ULL, }, /* 64 */ + { 0x58604c7ca826a4f0ULL, 0xb11e6ee016929090ULL, }, + { 0xf81cf804c0e87df0ULL, 0x4436ec3e6ce920a0ULL, }, + { 0x786634a810267370ULL, 0xf53f14eebe33c020ULL, }, + { 0x20ba34c408e06070ULL, 0xafde0b62e8ee6050ULL, }, + { 0x07b6347bdf77af30ULL, 0x6b8d72be2f6d1c40ULL, }, + { 0x63ea34bd3a9aa230ULL, 0xad25d0d828d84290ULL, }, + { 0x934834f6f477f4c0ULL, 0xc39e78e84b9ade10ULL, }, + { 0x3304e07e0c39cdc0ULL, 0x56b6f646a1f16e20ULL, }, /* 72 */ + { 0x8f38e0c0675cc0c0ULL, 0x984e54609a5c9470ULL, }, + { 0xff949cdcb6fb47c0ULL, 0xa70e305f61233be0ULL, }, + { 0xbfcea8bac85c91c0ULL, 0x2cb600377e0d9160ULL, }, + { 0x3f18e45e189a8740ULL, 0xddbf28e7d05731e0ULL, }, + { 0x6f76e497d277d9d0ULL, 0xf338d0f7f319cd60ULL, }, + { 0x2fb0f075e4d823d0ULL, 0x78e0a0cf100323e0ULL, }, + { 0x2f4f0c4c60779f0cULL, 0xcfff608f7fff9fe0ULL, }, + { 0x379944bc60e9d40cULL, 0x2a66400d7d7a4f60ULL, }, /* 80 */ + { 0x4a0b4408801e08acULL, 0x36fc80bb3c7401e0ULL, }, + { 0x922d0cb800dcb0acULL, 0xfc5c807628f8dc60ULL, }, + { 0xb24a046000c05044ULL, 0x30c080e6c008a460ULL, }, + { 0x22a66ce00040c044ULL, 0x208000724030e4e0ULL, }, + { 0xcc726c4000808024ULL, 0xe00000de0060dc60ULL, }, + { 0xbc5e04c000000024ULL, 0xc00000bc004010e0ULL, }, + { 0x7c5cac000000002cULL, 0x0000001c00c0f0e0ULL, }, + { 0x9c4424000000002cULL, 0x000000d40080f060ULL, }, /* 88 */ + { 0xa8cc2400000000ccULL, 0x0000004c000010e0ULL, }, + { 0xc814ac00000000ccULL, 0x000000980000c060ULL, }, + { 0x48e8e400000000a4ULL, 0x0000005800004060ULL, }, + { 0x08d80c00000000a4ULL, 0x00000008000040e0ULL, }, + { 0x30880c0000000084ULL, 0x000000380000c060ULL, }, + { 0xf0b8e40000000084ULL, 0x00000070000000e0ULL, }, + { 0xf0f04c000000004cULL, 0x000000f0000000e0ULL, }, + { 0x709004000000004cULL, 0x000000d000000060ULL, }, /* 96 */ + { 0xf0f06c000000004cULL, 0x00000070000000e0ULL, }, + { 0x709064000000004cULL, 0x0000005000000060ULL, }, + { 0xf0f08c000000004cULL, 0x000000f0000000e0ULL, }, + { 0xa0d08c00000000ecULL, 0x0000009000000060ULL, }, + { 0xc0708c000000008cULL, 0x000000f0000000e0ULL, }, + { 0x80508c000000002cULL, 0x0000009000000060ULL, }, + { 0x00f08c00000000ccULL, 0x000000f0000000e0ULL, }, + { 0x00906400000000ccULL, 0x000000e000000060ULL, }, /* 104 */ + { 0x00f06c00000000ccULL, 0x000000c0000000e0ULL, }, + { 0x00900400000000ccULL, 0x0000008000000060ULL, }, + { 0x00f04c00000000ccULL, 0x00000000000000e0ULL, }, + { 0x00e0c400000000a4ULL, 0x00000000000000e0ULL, }, + { 0x00c0ec00000000acULL, 0x00000000000000e0ULL, }, + { 0x0080a40000000044ULL, 0x00000000000000e0ULL, }, + { 0x00008c000000008cULL, 0x00000000000000e0ULL, }, }; reset_msa_registers(); diff --git a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_msubv_d.c b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_msubv_d.c index 5a0549ae3b..9722dbd99f 100644 --- a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_msubv_d.c +++ b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_msubv_d.c @@ -43,118 +43,118 @@ int32_t main(void) uint64_t b128_result[TEST_COUNT_TOTAL][2]; uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { - { 0x0000000000000002ULL, 0x0000000000000002ULL, }, /* 0 */ - { 0x0000000000000002ULL, 0x0000000000000002ULL, }, - { 0x00000000aaaaaaaeULL, 0x00000000aaaaaaaeULL, }, - { 0x0000000000000004ULL, 0x0000000000000004ULL, }, - { 0x000000006666666cULL, 0x000000006666666cULL, }, - { 0x0000000000000006ULL, 0x0000000000000006ULL, }, - { 0x000000008e38e395ULL, 0xffffffffe38e38ebULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, /* 8 */ - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x00000000aaaaaab4ULL, 0x00000000aaaaaab4ULL, }, /* 16 */ - { 0x00000000aaaaaab4ULL, 0x00000000aaaaaab4ULL, }, - { 0x38e38e3a71c71c7cULL, 0x38e38e3a71c71c7cULL, }, - { 0x0000000155555560ULL, 0x0000000155555560ULL, }, - { 0x2222222444444450ULL, 0x2222222444444450ULL, }, - { 0x000000020000000cULL, 0x000000020000000cULL, }, - { 0x2f684bdcb425ed16ULL, 0xf684bda397b425faULL, }, - { 0x00000002aaaaaab8ULL, 0x00000002aaaaaab8ULL, }, - { 0x000000020000000eULL, 0x000000020000000eULL, }, /* 24 */ - { 0x000000020000000eULL, 0x000000020000000eULL, }, - { 0xc71c71c8e38e38f2ULL, 0xc71c71c8e38e38f2ULL, }, - { 0x0000000155555564ULL, 0x0000000155555564ULL, }, - { 0xdddddddeccccccdcULL, 0xdddddddeccccccdcULL, }, - { 0x00000000aaaaaabaULL, 0x00000000aaaaaabaULL, }, - { 0xd097b42684bda13fULL, 0x097b425ef684bdb1ULL, }, - { 0x0000000000000010ULL, 0x0000000000000010ULL, }, - { 0x0000000066666678ULL, 0x0000000066666678ULL, }, /* 32 */ - { 0x0000000066666678ULL, 0x0000000066666678ULL, }, - { 0x2222222355555568ULL, 0x2222222355555568ULL, }, - { 0x00000000cccccce0ULL, 0x00000000cccccce0ULL, }, - { 0x147ae1491eb85200ULL, 0x147ae1491eb85200ULL, }, - { 0x0000000133333348ULL, 0x0000000133333348ULL, }, - { 0x1c71c71e3e93e954ULL, 0xfa4fa4fbb60b60ccULL, }, - { 0x00000001999999b0ULL, 0x00000001999999b0ULL, }, - { 0x000000013333334aULL, 0x000000013333334aULL, }, /* 40 */ - { 0x000000013333334aULL, 0x000000013333334aULL, }, - { 0xdddddddeeeeeef06ULL, 0xdddddddeeeeeef06ULL, }, - { 0x00000000cccccce4ULL, 0x00000000cccccce4ULL, }, - { 0xeb851eb8e147ae2cULL, 0xeb851eb8e147ae2cULL, }, - { 0x000000006666667eULL, 0x000000006666667eULL, }, - { 0xe38e38e3e93e9401ULL, 0x05b05b05c71c71dfULL, }, - { 0x0000000000000018ULL, 0x0000000000000018ULL, }, - { 0x000000008e38e3a7ULL, 0xffffffffe38e38fdULL, }, /* 48 */ - { 0x000000008e38e3a7ULL, 0xffffffffe38e38fdULL, }, - { 0x2f684bdb425ed0b1ULL, 0xf684bda17b425eebULL, }, - { 0x000000011c71c736ULL, 0xffffffffc71c71e2ULL, }, - { 0x1c71c71e27d27d42ULL, 0xfa4fa4fa49f49f66ULL, }, - { 0x00000001aaaaaac5ULL, 0xffffffffaaaaaac7ULL, }, - { 0x35ba781b4587e6d2ULL, 0x0fcd6e9d6b74f050ULL, }, - { 0x0000000238e38e54ULL, 0xffffffff8e38e3acULL, }, - { 0x00000001aaaaaac7ULL, 0xffffffffaaaaaac9ULL, }, /* 56 */ - { 0x00000001aaaaaac7ULL, 0xffffffffaaaaaac9ULL, }, - { 0xd097b427a12f6869ULL, 0x097b425ebda12f87ULL, }, - { 0x000000011c71c73aULL, 0xffffffffc71c71e6ULL, }, - { 0xe38e38e477777796ULL, 0x05b05b05aaaaaacaULL, }, - { 0x000000008e38e3adULL, 0xffffffffe38e3903ULL, }, - { 0xca4587e781948b2fULL, 0xf032916206522c5fULL, }, - { 0x0000000000000020ULL, 0x0000000000000020ULL, }, - { 0x3e3ad4ae1266c2b0ULL, 0x1637d725aebdb734ULL, }, /* 64 */ - { 0x4c74e0d60a3d6d94ULL, 0x1badd2dd9f4dac90ULL, }, - { 0x6874e8f94205b90cULL, 0x27eb0c41af2c3022ULL, }, - { 0x42dab657e16f25e8ULL, 0x06d6782e137656f2ULL, }, - { 0x5114c27fd945d0ccULL, 0x0c4c73e604064c4eULL, }, - { 0x68a91e898c276755ULL, 0x0f77ad378bdfb302ULL, }, - { 0x54c82cde41d1cf13ULL, 0x0b6108a5f38e1598ULL, }, - { 0x6f755d3eddd1234aULL, 0xfbbaace2f5421908ULL, }, - { 0x8b75656215996ec2ULL, 0x07f7e64705209c9aULL, }, /* 72 */ - { 0x779473b6cb43d680ULL, 0x03e141b56cceff30ULL, }, - { 0xa6279a1866fb9f64ULL, 0x2631668db9e53ac1ULL, }, - { 0x67a1f71bd99e4586ULL, 0x312ec9f6206e6e69ULL, }, - { 0x4207c47a7907b262ULL, 0x101a35e284b89539ULL, }, - { 0x5cb4f4db15070699ULL, 0x0073da1f866c98a9ULL, }, - { 0x1e2f51de87a9acbbULL, 0x0b713d87ecf5cc51ULL, }, - { 0x721d49ba5f0acfa8ULL, 0x5ba5bbe9afeae691ULL, }, - { 0x4bcd68690d995de0ULL, 0x771da6b4b6c967ebULL, }, /* 80 */ - { 0x4ea9a2cfbb5acd7bULL, 0x79dd6a73439e6387ULL, }, - { 0x47c800b999dd2371ULL, 0x766d25914ef7a7a0ULL, }, - { 0x41b0fa10eb77cf84ULL, 0x26e85189458965f8ULL, }, - { 0x1fc448ce062c2944ULL, 0x31f490a9422a80e6ULL, }, - { 0x211bdfadfd79770eULL, 0x3b25f4cac5763378ULL, }, - { 0x16fbb87edd87b6f0ULL, 0x57c0b65fabdda20eULL, }, - { 0x14621091eac4a5f6ULL, 0x4d29a25d32fa9ef6ULL, }, - { 0x07832ded1c464b02ULL, 0x6396905709e3cfa4ULL, }, /* 88 */ - { 0x0ff4a84eab8df3b9ULL, 0x6bc9a7d8c6adf2eaULL, }, - { 0x21e53326bfbd0b05ULL, 0x8f8f3b9c679dff5aULL, }, - { 0x191ed6a24e1576f9ULL, 0x9e8c2e402760373aULL, }, - { 0x19b438400fc27751ULL, 0x819c4bbfd3ee6972ULL, }, - { 0x1e0d5dc1094ae999ULL, 0x7496a289f5eff010ULL, }, - { 0x11af620b7bc03943ULL, 0x8a11f229836addc7ULL, }, - { 0x46fa45d0e84440fcULL, 0xe8d2c0211fb042bfULL, }, - { 0x22142516b5a8adbcULL, 0xe1cf1923e186aad1ULL, }, /* 96 */ - { 0x066ebbbb4ff6da44ULL, 0xd918d7e6a7e61877ULL, }, - { 0x100acc9d22839a48ULL, 0xce291932929e367fULL, }, - { 0x0dfe419d62a62f64ULL, 0xc020fe45a8cf7acfULL, }, - { 0x2ba79b6ffbf3c63bULL, 0xb428f52c49fce695ULL, }, - { 0x29b3b85200bdf100ULL, 0xb4ae7ea2f52aa5b9ULL, }, - { 0x293bb84d6360c0b6ULL, 0xae33b26e4c493c49ULL, }, - { 0x46a99fdf54f4862dULL, 0xae790dc5055f6f51ULL, }, - { 0x18480e0fd728c7c3ULL, 0xa000ad7b15f8ebe0ULL, }, /* 104 */ - { 0x1b8b97aa205e1239ULL, 0x89c78b8909c4a8e5ULL, }, - { 0x09abb26b05ef649dULL, 0x74242fa1bd49e740ULL, }, - { 0x04e233bc861d272bULL, 0x9c5343ab30f62f9fULL, }, - { 0xda2da0d0884dc3d1ULL, 0xb824f201640b4147ULL, }, - { 0x9d8b22ee1b9a2e0fULL, 0xb642ddf1edb0747fULL, }, - { 0x7c81956533686a37ULL, 0xdd5181781dc3ad37ULL, }, - { 0xc60b1905717ff25aULL, 0xe2af726e71ad7ad7ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xaaaaaaaaaaaaaaa9ULL, 0xaaaaaaaaaaaaaaa9ULL, }, + { 0xfffffffffffffffeULL, 0xfffffffffffffffeULL, }, + { 0xcccccccccccccccaULL, 0xcccccccccccccccaULL, }, + { 0xfffffffffffffffdULL, 0xfffffffffffffffdULL, }, + { 0xe38e38e38e38e38bULL, 0x38e38e38e38e38e0ULL, }, + { 0xfffffffffffffffcULL, 0xfffffffffffffffcULL, }, + { 0xfffffffffffffffcULL, 0xfffffffffffffffcULL, }, /* 8 */ + { 0xfffffffffffffffcULL, 0xfffffffffffffffcULL, }, + { 0xfffffffffffffffcULL, 0xfffffffffffffffcULL, }, + { 0xfffffffffffffffcULL, 0xfffffffffffffffcULL, }, + { 0xfffffffffffffffcULL, 0xfffffffffffffffcULL, }, + { 0xfffffffffffffffcULL, 0xfffffffffffffffcULL, }, + { 0xfffffffffffffffcULL, 0xfffffffffffffffcULL, }, + { 0xfffffffffffffffcULL, 0xfffffffffffffffcULL, }, + { 0xaaaaaaaaaaaaaaa6ULL, 0xaaaaaaaaaaaaaaa6ULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaa6ULL, 0xaaaaaaaaaaaaaaa6ULL, }, + { 0x71c71c71c71c71c2ULL, 0x71c71c71c71c71c2ULL, }, + { 0x5555555555555550ULL, 0x5555555555555550ULL, }, + { 0xddddddddddddddd8ULL, 0xddddddddddddddd8ULL, }, + { 0xfffffffffffffffaULL, 0xfffffffffffffffaULL, }, + { 0xed097b425ed097aeULL, 0xd097b425ed097b3cULL, }, + { 0xaaaaaaaaaaaaaaa4ULL, 0xaaaaaaaaaaaaaaa4ULL, }, + { 0xfffffffffffffff9ULL, 0xfffffffffffffff9ULL, }, /* 24 */ + { 0xfffffffffffffff9ULL, 0xfffffffffffffff9ULL, }, + { 0xe38e38e38e38e387ULL, 0xe38e38e38e38e387ULL, }, + { 0x555555555555554eULL, 0x555555555555554eULL, }, + { 0x9999999999999992ULL, 0x9999999999999992ULL, }, + { 0xaaaaaaaaaaaaaaa3ULL, 0xaaaaaaaaaaaaaaa3ULL, }, + { 0xa12f684bda12f67dULL, 0x12f684bda12f6844ULL, }, + { 0xfffffffffffffff8ULL, 0xfffffffffffffff8ULL, }, + { 0xccccccccccccccc4ULL, 0xccccccccccccccc4ULL, }, /* 32 */ + { 0xccccccccccccccc4ULL, 0xccccccccccccccc4ULL, }, + { 0x555555555555554cULL, 0x555555555555554cULL, }, + { 0x9999999999999990ULL, 0x9999999999999990ULL, }, + { 0xa3d70a3d70a3d700ULL, 0xa3d70a3d70a3d700ULL, }, + { 0x666666666666665cULL, 0x666666666666665cULL, }, + { 0xe93e93e93e93e934ULL, 0x2d82d82d82d82d78ULL, }, + { 0x3333333333333328ULL, 0x3333333333333328ULL, }, + { 0x666666666666665bULL, 0x666666666666665bULL, }, /* 40 */ + { 0x666666666666665bULL, 0x666666666666665bULL, }, + { 0x888888888888887dULL, 0x888888888888887dULL, }, + { 0x999999999999998eULL, 0x999999999999998eULL, }, + { 0x5c28f5c28f5c28eaULL, 0x5c28f5c28f5c28eaULL, }, + { 0xccccccccccccccc1ULL, 0xccccccccccccccc1ULL, }, + { 0x2d82d82d82d82d77ULL, 0x3e93e93e93e93e88ULL, }, + { 0xfffffffffffffff4ULL, 0xfffffffffffffff4ULL, }, + { 0xe38e38e38e38e382ULL, 0x38e38e38e38e38d7ULL, }, /* 48 */ + { 0xe38e38e38e38e382ULL, 0x38e38e38e38e38d7ULL, }, + { 0xd097b425ed097b36ULL, 0x097b425ed097b419ULL, }, + { 0xc71c71c71c71c710ULL, 0x71c71c71c71c71baULL, }, + { 0x49f49f49f49f49e8ULL, 0x38e38e38e38e38d6ULL, }, + { 0xaaaaaaaaaaaaaa9eULL, 0xaaaaaaaaaaaaaa9dULL, }, + { 0xf9add3c0ca4587daULL, 0x587e6b74f0329154ULL, }, + { 0x8e38e38e38e38e2cULL, 0xe38e38e38e38e380ULL, }, + { 0xaaaaaaaaaaaaaa9dULL, 0xaaaaaaaaaaaaaa9cULL, }, /* 56 */ + { 0xaaaaaaaaaaaaaa9dULL, 0xaaaaaaaaaaaaaa9cULL, }, + { 0x684bda12f684bd93ULL, 0x84bda12f684bda04ULL, }, + { 0xc71c71c71c71c70eULL, 0x71c71c71c71c71b8ULL, }, + { 0x1111111111111102ULL, 0x7777777777777768ULL, }, + { 0xe38e38e38e38e37fULL, 0x38e38e38e38e38d4ULL, }, + { 0x781948b0fcd6e9d1ULL, 0xc3f35ba781948b00ULL, }, + { 0xfffffffffffffff0ULL, 0xfffffffffffffff0ULL, }, + { 0x52ba41969e9c6ff0ULL, 0xcd6802158b677f60ULL, }, /* 64 */ + { 0x63129bf5b78505f0ULL, 0x1556f7f61c4e5b90ULL, }, + { 0x5a4c8855f350a5f0ULL, 0x6a36586fc42edea0ULL, }, + { 0x5e6b001b04d82c70ULL, 0xe819332c365e3f20ULL, }, + { 0x6ec35a7a1dc0c270ULL, 0x3008290cc7451b50ULL, }, + { 0x37152f411fd35230ULL, 0xc7e3b2957c56b340ULL, }, + { 0xcc49f1d861667630ULL, 0x1808e0646811cb90ULL, }, + { 0xde8a7f544022c1c0ULL, 0x9886bc9978437610ULL, }, + { 0xd5c46bb47bee61c0ULL, 0xed661d132023f920ULL, }, /* 72 */ + { 0x6af92e4bbd8185c0ULL, 0x3d8b4ae20bdf1170ULL, }, + { 0xe4d44869d87d45c0ULL, 0x6409d23bd9c847e0ULL, }, + { 0x6e2e9ce94e99c4c0ULL, 0xc30837db04ed7360ULL, }, + { 0x724d14ae60214b40ULL, 0x40eb1297771cd3e0ULL, }, + { 0x848da22a3edd96d0ULL, 0xc168eecc874e7e60ULL, }, + { 0x0de7f6a9b4fa15d0ULL, 0x2067546bb273a9e0ULL, }, + { 0xc233bfd40310460cULL, 0x0d9585bacf54c5e0ULL, }, + { 0x061015122724c70cULL, 0x0169d01f7cb17f60ULL, }, /* 80 */ + { 0x23dacc726f603aacULL, 0xf3ea8c4eaa8b5ce0ULL, }, + { 0xd82df953c25380acULL, 0xba87b7f0f99bbb60ULL, }, + { 0x546cb94a0c5e7444ULL, 0x3818c320ce1bdf60ULL, }, + { 0xa38f9428761ecf44ULL, 0x63113b9e681b66e0ULL, }, + { 0x7dc23fbe59fe7924ULL, 0x156ddd68750e6260ULL, }, + { 0x8a17717d36df5b24ULL, 0x36b1f5939596d2e0ULL, }, + { 0x7e854cd9a677ce2cULL, 0xf2b6202eb36946e0ULL, }, + { 0x246d8d067437a72cULL, 0x04c6347e9c1ff460ULL, }, /* 88 */ + { 0xc48a013a554339ccULL, 0xcb81fd31acc4a5e0ULL, }, + { 0xb971282c0b508fccULL, 0x20d62d6344ce5060ULL, }, + { 0x835f812f0bc6a7a4ULL, 0x17bd6b5a08275460ULL, }, + { 0xc0ee1b9557ab4aa4ULL, 0x170471a9d22d5fe0ULL, }, + { 0xc6f66d89431f7984ULL, 0x5c6f5a646cad3f60ULL, }, + { 0x5ae0b289f6ac0b84ULL, 0x6f9f6bc81fdb6be0ULL, }, + { 0x2f584ee03fd2014cULL, 0xa7e34ccbd1bc3fe0ULL, }, + { 0x5947927731cb724cULL, 0xf76af1f9a05f4160ULL, }, /* 96 */ + { 0x68112ad490e3a34cULL, 0x7f944a22f5d630e0ULL, }, + { 0x1cf6705c5faa944cULL, 0x801292d47291e660ULL, }, + { 0x5519f2782cb0454cULL, 0x3d691c2dd53919e0ULL, }, + { 0xe5c979861aac06ecULL, 0x585247d6e899e160ULL, }, + { 0x2450b27896665b8cULL, 0x8276d8ad504f46e0ULL, }, + { 0x2716d456a4a5ab2cULL, 0x46e1f3460c71c260ULL, }, + { 0x5751460331251dccULL, 0xdc1dc7a4a693abe0ULL, }, + { 0x3bf387b7f37473ccULL, 0x8efb4ff7cc92de60ULL, }, /* 104 */ + { 0xc3103a3df066c9ccULL, 0x7d3b07351cd59ee0ULL, }, + { 0x0d612554557c1fccULL, 0x5dbabfc2ac8ed560ULL, }, + { 0x1cd018ef103475ccULL, 0xca277277956f49e0ULL, }, + { 0x15d520225c2e79a4ULL, 0x08f2025804e95de0ULL, }, + { 0x820f9c65be3ea1acULL, 0x37094edbda6ef1e0ULL, }, + { 0x0f18515c62838744ULL, 0xcfbd4b5627d005e0ULL, }, + { 0x11d549f26502488cULL, 0x8de999d53cdc99e0ULL, }, }; reset_msa_registers(); diff --git a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_msubv_h.c b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_msubv_h.c index 17bccc8ad1..6c059c779c 100644 --- a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_msubv_h.c +++ b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_msubv_h.c @@ -43,118 +43,118 @@ int32_t main(void) uint64_t b128_result[TEST_COUNT_TOTAL][2]; uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { - { 0x0000000000000002ULL, 0x0000000000000002ULL, }, /* 0 */ - { 0x0000000000000002ULL, 0x0000000000000002ULL, }, - { 0x00000000aaaaaaaeULL, 0x00000000aaaaaaaeULL, }, - { 0x0000000000000004ULL, 0x0000000000000004ULL, }, - { 0x000000006666666cULL, 0x000000006666666cULL, }, - { 0x0000000000000006ULL, 0x0000000000000006ULL, }, - { 0x000000008e38e395ULL, 0xffffffffe38e38ebULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, /* 8 */ - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x00000000aaaaaab4ULL, 0x00000000aaaaaab4ULL, }, /* 16 */ - { 0x00000000aaaaaab4ULL, 0x00000000aaaaaab4ULL, }, - { 0x38e38e3a71c71c7cULL, 0x38e38e3a71c71c7cULL, }, - { 0x0000000155555560ULL, 0x0000000155555560ULL, }, - { 0x2222222444444450ULL, 0x2222222444444450ULL, }, - { 0x000000020000000cULL, 0x000000020000000cULL, }, - { 0x2f684bdcb425ed16ULL, 0xf684bda397b425faULL, }, - { 0x00000002aaaaaab8ULL, 0x00000002aaaaaab8ULL, }, - { 0x000000020000000eULL, 0x000000020000000eULL, }, /* 24 */ - { 0x000000020000000eULL, 0x000000020000000eULL, }, - { 0xc71c71c8e38e38f2ULL, 0xc71c71c8e38e38f2ULL, }, - { 0x0000000155555564ULL, 0x0000000155555564ULL, }, - { 0xdddddddeccccccdcULL, 0xdddddddeccccccdcULL, }, - { 0x00000000aaaaaabaULL, 0x00000000aaaaaabaULL, }, - { 0xd097b42684bda13fULL, 0x097b425ef684bdb1ULL, }, - { 0x0000000000000010ULL, 0x0000000000000010ULL, }, - { 0x0000000066666678ULL, 0x0000000066666678ULL, }, /* 32 */ - { 0x0000000066666678ULL, 0x0000000066666678ULL, }, - { 0x2222222355555568ULL, 0x2222222355555568ULL, }, - { 0x00000000cccccce0ULL, 0x00000000cccccce0ULL, }, - { 0x147ae1491eb85200ULL, 0x147ae1491eb85200ULL, }, - { 0x0000000133333348ULL, 0x0000000133333348ULL, }, - { 0x1c71c71e3e93e954ULL, 0xfa4fa4fbb60b60ccULL, }, - { 0x00000001999999b0ULL, 0x00000001999999b0ULL, }, - { 0x000000013333334aULL, 0x000000013333334aULL, }, /* 40 */ - { 0x000000013333334aULL, 0x000000013333334aULL, }, - { 0xdddddddeeeeeef06ULL, 0xdddddddeeeeeef06ULL, }, - { 0x00000000cccccce4ULL, 0x00000000cccccce4ULL, }, - { 0xeb851eb8e147ae2cULL, 0xeb851eb8e147ae2cULL, }, - { 0x000000006666667eULL, 0x000000006666667eULL, }, - { 0xe38e38e3e93e9401ULL, 0x05b05b05c71c71dfULL, }, - { 0x0000000000000018ULL, 0x0000000000000018ULL, }, - { 0x000000008e38e3a7ULL, 0xffffffffe38e38fdULL, }, /* 48 */ - { 0x000000008e38e3a7ULL, 0xffffffffe38e38fdULL, }, - { 0x2f684bdb425ed0b1ULL, 0xf684bda17b425eebULL, }, - { 0x000000011c71c736ULL, 0xffffffffc71c71e2ULL, }, - { 0x1c71c71e27d27d42ULL, 0xfa4fa4fa49f49f66ULL, }, - { 0x00000001aaaaaac5ULL, 0xffffffffaaaaaac7ULL, }, - { 0x35ba781b4587e6d2ULL, 0x0fcd6e9d6b74f050ULL, }, - { 0x0000000238e38e54ULL, 0xffffffff8e38e3acULL, }, - { 0x00000001aaaaaac7ULL, 0xffffffffaaaaaac9ULL, }, /* 56 */ - { 0x00000001aaaaaac7ULL, 0xffffffffaaaaaac9ULL, }, - { 0xd097b427a12f6869ULL, 0x097b425ebda12f87ULL, }, - { 0x000000011c71c73aULL, 0xffffffffc71c71e6ULL, }, - { 0xe38e38e477777796ULL, 0x05b05b05aaaaaacaULL, }, - { 0x000000008e38e3adULL, 0xffffffffe38e3903ULL, }, - { 0xca4587e781948b2fULL, 0xf032916206522c5fULL, }, - { 0x0000000000000020ULL, 0x0000000000000020ULL, }, - { 0x3e3ad4ae1266c2b0ULL, 0x1637d725aebdb734ULL, }, /* 64 */ - { 0x4c74e0d60a3d6d94ULL, 0x1badd2dd9f4dac90ULL, }, - { 0x6874e8f94205b90cULL, 0x27eb0c41af2c3022ULL, }, - { 0x42dab657e16f25e8ULL, 0x06d6782e137656f2ULL, }, - { 0x5114c27fd945d0ccULL, 0x0c4c73e604064c4eULL, }, - { 0x68a91e898c276755ULL, 0x0f77ad378bdfb302ULL, }, - { 0x54c82cde41d1cf13ULL, 0x0b6108a5f38e1598ULL, }, - { 0x6f755d3eddd1234aULL, 0xfbbaace2f5421908ULL, }, - { 0x8b75656215996ec2ULL, 0x07f7e64705209c9aULL, }, /* 72 */ - { 0x779473b6cb43d680ULL, 0x03e141b56cceff30ULL, }, - { 0xa6279a1866fb9f64ULL, 0x2631668db9e53ac1ULL, }, - { 0x67a1f71bd99e4586ULL, 0x312ec9f6206e6e69ULL, }, - { 0x4207c47a7907b262ULL, 0x101a35e284b89539ULL, }, - { 0x5cb4f4db15070699ULL, 0x0073da1f866c98a9ULL, }, - { 0x1e2f51de87a9acbbULL, 0x0b713d87ecf5cc51ULL, }, - { 0x721d49ba5f0acfa8ULL, 0x5ba5bbe9afeae691ULL, }, - { 0x4bcd68690d995de0ULL, 0x771da6b4b6c967ebULL, }, /* 80 */ - { 0x4ea9a2cfbb5acd7bULL, 0x79dd6a73439e6387ULL, }, - { 0x47c800b999dd2371ULL, 0x766d25914ef7a7a0ULL, }, - { 0x41b0fa10eb77cf84ULL, 0x26e85189458965f8ULL, }, - { 0x1fc448ce062c2944ULL, 0x31f490a9422a80e6ULL, }, - { 0x211bdfadfd79770eULL, 0x3b25f4cac5763378ULL, }, - { 0x16fbb87edd87b6f0ULL, 0x57c0b65fabdda20eULL, }, - { 0x14621091eac4a5f6ULL, 0x4d29a25d32fa9ef6ULL, }, - { 0x07832ded1c464b02ULL, 0x6396905709e3cfa4ULL, }, /* 88 */ - { 0x0ff4a84eab8df3b9ULL, 0x6bc9a7d8c6adf2eaULL, }, - { 0x21e53326bfbd0b05ULL, 0x8f8f3b9c679dff5aULL, }, - { 0x191ed6a24e1576f9ULL, 0x9e8c2e402760373aULL, }, - { 0x19b438400fc27751ULL, 0x819c4bbfd3ee6972ULL, }, - { 0x1e0d5dc1094ae999ULL, 0x7496a289f5eff010ULL, }, - { 0x11af620b7bc03943ULL, 0x8a11f229836addc7ULL, }, - { 0x46fa45d0e84440fcULL, 0xe8d2c0211fb042bfULL, }, - { 0x22142516b5a8adbcULL, 0xe1cf1923e186aad1ULL, }, /* 96 */ - { 0x066ebbbb4ff6da44ULL, 0xd918d7e6a7e61877ULL, }, - { 0x100acc9d22839a48ULL, 0xce291932929e367fULL, }, - { 0x0dfe419d62a62f64ULL, 0xc020fe45a8cf7acfULL, }, - { 0x2ba79b6ffbf3c63bULL, 0xb428f52c49fce695ULL, }, - { 0x29b3b85200bdf100ULL, 0xb4ae7ea2f52aa5b9ULL, }, - { 0x293bb84d6360c0b6ULL, 0xae33b26e4c493c49ULL, }, - { 0x46a99fdf54f4862dULL, 0xae790dc5055f6f51ULL, }, - { 0x18480e0fd728c7c3ULL, 0xa000ad7b15f8ebe0ULL, }, /* 104 */ - { 0x1b8b97aa205e1239ULL, 0x89c78b8909c4a8e5ULL, }, - { 0x09abb26b05ef649dULL, 0x74242fa1bd49e740ULL, }, - { 0x04e233bc861d272bULL, 0x9c5343ab30f62f9fULL, }, - { 0xda2da0d0884dc3d1ULL, 0xb824f201640b4147ULL, }, - { 0x9d8b22ee1b9a2e0fULL, 0xb642ddf1edb0747fULL, }, - { 0x7c81956533686a37ULL, 0xdd5181781dc3ad37ULL, }, - { 0xc60b1905717ff25aULL, 0xe2af726e71ad7ad7ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xaaa9aaa9aaa9aaa9ULL, 0xaaa9aaa9aaa9aaa9ULL, }, + { 0xfffefffefffefffeULL, 0xfffefffefffefffeULL, }, + { 0xcccacccacccacccaULL, 0xcccacccacccacccaULL, }, + { 0xfffdfffdfffdfffdULL, 0xfffdfffdfffdfffdULL, }, + { 0xe38b38e08e35e38bULL, 0x38e08e35e38b38e0ULL, }, + { 0xfffcfffcfffcfffcULL, 0xfffcfffcfffcfffcULL, }, + { 0xfffcfffcfffcfffcULL, 0xfffcfffcfffcfffcULL, }, /* 8 */ + { 0xfffcfffcfffcfffcULL, 0xfffcfffcfffcfffcULL, }, + { 0xfffcfffcfffcfffcULL, 0xfffcfffcfffcfffcULL, }, + { 0xfffcfffcfffcfffcULL, 0xfffcfffcfffcfffcULL, }, + { 0xfffcfffcfffcfffcULL, 0xfffcfffcfffcfffcULL, }, + { 0xfffcfffcfffcfffcULL, 0xfffcfffcfffcfffcULL, }, + { 0xfffcfffcfffcfffcULL, 0xfffcfffcfffcfffcULL, }, + { 0xfffcfffcfffcfffcULL, 0xfffcfffcfffcfffcULL, }, + { 0xaaa6aaa6aaa6aaa6ULL, 0xaaa6aaa6aaa6aaa6ULL, }, /* 16 */ + { 0xaaa6aaa6aaa6aaa6ULL, 0xaaa6aaa6aaa6aaa6ULL, }, + { 0x71c271c271c271c2ULL, 0x71c271c271c271c2ULL, }, + { 0x5550555055505550ULL, 0x5550555055505550ULL, }, + { 0xddd8ddd8ddd8ddd8ULL, 0xddd8ddd8ddd8ddd8ULL, }, + { 0xfffafffafffafffaULL, 0xfffafffafffafffaULL, }, + { 0x97ae7b3c5eca97aeULL, 0x7b3c5eca97ae7b3cULL, }, + { 0xaaa4aaa4aaa4aaa4ULL, 0xaaa4aaa4aaa4aaa4ULL, }, + { 0xfff9fff9fff9fff9ULL, 0xfff9fff9fff9fff9ULL, }, /* 24 */ + { 0xfff9fff9fff9fff9ULL, 0xfff9fff9fff9fff9ULL, }, + { 0xe387e387e387e387ULL, 0xe387e387e387e387ULL, }, + { 0x554e554e554e554eULL, 0x554e554e554e554eULL, }, + { 0x9992999299929992ULL, 0x9992999299929992ULL, }, + { 0xaaa3aaa3aaa3aaa3ULL, 0xaaa3aaa3aaa3aaa3ULL, }, + { 0xf67d6844da0bf67dULL, 0x6844da0bf67d6844ULL, }, + { 0xfff8fff8fff8fff8ULL, 0xfff8fff8fff8fff8ULL, }, + { 0xccc4ccc4ccc4ccc4ULL, 0xccc4ccc4ccc4ccc4ULL, }, /* 32 */ + { 0xccc4ccc4ccc4ccc4ULL, 0xccc4ccc4ccc4ccc4ULL, }, + { 0x554c554c554c554cULL, 0x554c554c554c554cULL, }, + { 0x9990999099909990ULL, 0x9990999099909990ULL, }, + { 0xd700d700d700d700ULL, 0xd700d700d700d700ULL, }, + { 0x665c665c665c665cULL, 0x665c665c665c665cULL, }, + { 0xe9342d7871bce934ULL, 0x2d7871bce9342d78ULL, }, + { 0x3328332833283328ULL, 0x3328332833283328ULL, }, + { 0x665b665b665b665bULL, 0x665b665b665b665bULL, }, /* 40 */ + { 0x665b665b665b665bULL, 0x665b665b665b665bULL, }, + { 0x887d887d887d887dULL, 0x887d887d887d887dULL, }, + { 0x998e998e998e998eULL, 0x998e998e998e998eULL, }, + { 0x28ea28ea28ea28eaULL, 0x28ea28ea28ea28eaULL, }, + { 0xccc1ccc1ccc1ccc1ULL, 0xccc1ccc1ccc1ccc1ULL, }, + { 0x2d773e884f992d77ULL, 0x3e884f992d773e88ULL, }, + { 0xfff4fff4fff4fff4ULL, 0xfff4fff4fff4fff4ULL, }, + { 0xe38238d78e2ce382ULL, 0x38d78e2ce38238d7ULL, }, /* 48 */ + { 0xe38238d78e2ce382ULL, 0x38d78e2ce38238d7ULL, }, + { 0x7b36b419ecfc7b36ULL, 0xb419ecfc7b36b419ULL, }, + { 0xc71071ba1c64c710ULL, 0x71ba1c64c71071baULL, }, + { 0x49e838d627c449e8ULL, 0x38d627c449e838d6ULL, }, + { 0xaa9eaa9daa9caa9eULL, 0xaa9daa9caa9eaa9dULL, }, + { 0x87da91547e5c87daULL, 0x91547e5c87da9154ULL, }, + { 0x8e2ce38038d48e2cULL, 0xe38038d48e2ce380ULL, }, + { 0xaa9daa9caa9baa9dULL, 0xaa9caa9baa9daa9cULL, }, /* 56 */ + { 0xaa9daa9caa9baa9dULL, 0xaa9caa9baa9daa9cULL, }, + { 0xbd93da04f675bd93ULL, 0xda04f675bd93da04ULL, }, + { 0xc70e71b81c62c70eULL, 0x71b81c62c70e71b8ULL, }, + { 0x11027768ddce1102ULL, 0x7768ddce11027768ULL, }, + { 0xe37f38d48e29e37fULL, 0x38d48e29e37f38d4ULL, }, + { 0xe9d18b0048a1e9d1ULL, 0x8b0048a1e9d18b00ULL, }, + { 0xfff0fff0fff0fff0ULL, 0xfff0fff0fff0fff0ULL, }, + { 0x340ccd603a6c6ff0ULL, 0x7c7fc96cb0d77f60ULL, }, /* 64 */ + { 0x07608c7c902605f0ULL, 0x7e1ef7e0f9925b90ULL, }, + { 0xda1ca10416e8a5f0ULL, 0x2e36f13e11e9dea0ULL, }, + { 0x6166ada860262c70ULL, 0x773f69ee43333f20ULL, }, + { 0x34ba6cc4b5e0c270ULL, 0x78de98628bee1b50ULL, }, + { 0x13b6467bf3775230ULL, 0xce8d99be266db340ULL, }, + { 0xeaeababdfe9a7630ULL, 0x2d251ed87fd8cb90ULL, }, + { 0x1b481af62b77c1c0ULL, 0x479e70e86e9a7610ULL, }, + { 0xee042f7eb23961c0ULL, 0xf7b66a4686f1f920ULL, }, /* 72 */ + { 0xc538a3c0bd5c85c0ULL, 0x564eef60e05c1170ULL, }, + { 0xb5941adce7fb45c0ULL, 0xd00e7d5f672347e0ULL, }, + { 0x25cef5ba555cc4c0ULL, 0x55b61e37e30d7360ULL, }, + { 0xad18025e9e9a4b40ULL, 0x9ebf96e71457d3e0ULL, }, + { 0xdd766297cb7796d0ULL, 0xb938e8f703197e60ULL, }, + { 0x4db03d7538d815d0ULL, 0x3ee089cf7f03a9e0ULL, }, + { 0x154fea4c3377460cULL, 0xe1ff538f49ffc5e0ULL, }, + { 0x4a99edbce7e9c70cULL, 0x3f66800dba7a7f60ULL, }, /* 80 */ + { 0xea0bfe08a81e3aacULL, 0xe7fcffbbd4745ce0ULL, }, + { 0x3e2ddcb809dc80acULL, 0xc75ca276a8f8bb60ULL, }, + { 0x5e4aa9605ec07444ULL, 0x6dc0dee66108df60ULL, }, + { 0x03a670e01940cf44ULL, 0x05802472d23066e0ULL, }, + { 0x8c72ca4059807924ULL, 0xb7002ade28606260ULL, }, + { 0x945efbc07b005b24ULL, 0x4f00c3bc4040d2e0ULL, }, + { 0xab5cc300f000ce2cULL, 0xf000bd1c6fc046e0ULL, }, + { 0xd7445f001000a72cULL, 0x600018d43e80f460ULL, }, /* 88 */ + { 0x66cca200e00039ccULL, 0xc000b74c5d00a5e0ULL, }, + { 0x33140e00c0008fccULL, 0xc0005a98be005060ULL, }, + { 0xafe8d8000000a7a4ULL, 0x00002a58c2005460ULL, }, + { 0x99d8b80000004aa4ULL, 0x0000d6088c005fe0ULL, }, + { 0xa388900000007984ULL, 0x0000413818003f60ULL, }, + { 0xc5b8f00000000b84ULL, 0x0000fa7010006be0ULL, }, + { 0x41f0c0000000014cULL, 0x00002bf0f0003fe0ULL, }, + { 0x7490c0000000724cULL, 0x0000b9d0a0004160ULL, }, /* 96 */ + { 0xb0f0c0000000a34cULL, 0x00008f70c00030e0ULL, }, + { 0xed90c0000000944cULL, 0x000014508000e660ULL, }, + { 0x0ff0c0000000454cULL, 0x00002ef0000019e0ULL, }, + { 0xebd08000000006ecULL, 0x00001a900000e160ULL, }, + { 0xf770000000005b8cULL, 0x000037f0000046e0ULL, }, + { 0x825000000000ab2cULL, 0x000039900000c260ULL, }, + { 0x5af0000000001dccULL, 0x000030f00000abe0ULL, }, + { 0x22900000000073ccULL, 0x0000d1e00000de60ULL, }, /* 104 */ + { 0x3bf000000000c9ccULL, 0x000083c000009ee0ULL, }, + { 0xe990000000001fccULL, 0x0000c7800000d560ULL, }, + { 0x0cf00000000075ccULL, 0x00000f00000049e0ULL, }, + { 0x0ee00000000079a4ULL, 0x0000670000005de0ULL, }, + { 0x77c000000000a1acULL, 0x00007f000000f1e0ULL, }, + { 0x8380000000008744ULL, 0x00005700000005e0ULL, }, + { 0xef0000000000488cULL, 0x0000ef00000099e0ULL, }, }; reset_msa_registers(); diff --git a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_msubv_w.c b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_msubv_w.c index 171b717f14..0a83db4787 100644 --- a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_msubv_w.c +++ b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_msubv_w.c @@ -43,118 +43,118 @@ int32_t main(void) uint64_t b128_result[TEST_COUNT_TOTAL][2]; uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { - { 0x0000000000000002ULL, 0x0000000000000002ULL, }, /* 0 */ - { 0x0000000000000002ULL, 0x0000000000000002ULL, }, - { 0x00000000aaaaaaaeULL, 0x00000000aaaaaaaeULL, }, - { 0x0000000000000004ULL, 0x0000000000000004ULL, }, - { 0x000000006666666cULL, 0x000000006666666cULL, }, - { 0x0000000000000006ULL, 0x0000000000000006ULL, }, - { 0x000000008e38e395ULL, 0xffffffffe38e38ebULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, /* 8 */ - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x0000000000000008ULL, 0x0000000000000008ULL, }, - { 0x00000000aaaaaab4ULL, 0x00000000aaaaaab4ULL, }, /* 16 */ - { 0x00000000aaaaaab4ULL, 0x00000000aaaaaab4ULL, }, - { 0x38e38e3a71c71c7cULL, 0x38e38e3a71c71c7cULL, }, - { 0x0000000155555560ULL, 0x0000000155555560ULL, }, - { 0x2222222444444450ULL, 0x2222222444444450ULL, }, - { 0x000000020000000cULL, 0x000000020000000cULL, }, - { 0x2f684bdcb425ed16ULL, 0xf684bda397b425faULL, }, - { 0x00000002aaaaaab8ULL, 0x00000002aaaaaab8ULL, }, - { 0x000000020000000eULL, 0x000000020000000eULL, }, /* 24 */ - { 0x000000020000000eULL, 0x000000020000000eULL, }, - { 0xc71c71c8e38e38f2ULL, 0xc71c71c8e38e38f2ULL, }, - { 0x0000000155555564ULL, 0x0000000155555564ULL, }, - { 0xdddddddeccccccdcULL, 0xdddddddeccccccdcULL, }, - { 0x00000000aaaaaabaULL, 0x00000000aaaaaabaULL, }, - { 0xd097b42684bda13fULL, 0x097b425ef684bdb1ULL, }, - { 0x0000000000000010ULL, 0x0000000000000010ULL, }, - { 0x0000000066666678ULL, 0x0000000066666678ULL, }, /* 32 */ - { 0x0000000066666678ULL, 0x0000000066666678ULL, }, - { 0x2222222355555568ULL, 0x2222222355555568ULL, }, - { 0x00000000cccccce0ULL, 0x00000000cccccce0ULL, }, - { 0x147ae1491eb85200ULL, 0x147ae1491eb85200ULL, }, - { 0x0000000133333348ULL, 0x0000000133333348ULL, }, - { 0x1c71c71e3e93e954ULL, 0xfa4fa4fbb60b60ccULL, }, - { 0x00000001999999b0ULL, 0x00000001999999b0ULL, }, - { 0x000000013333334aULL, 0x000000013333334aULL, }, /* 40 */ - { 0x000000013333334aULL, 0x000000013333334aULL, }, - { 0xdddddddeeeeeef06ULL, 0xdddddddeeeeeef06ULL, }, - { 0x00000000cccccce4ULL, 0x00000000cccccce4ULL, }, - { 0xeb851eb8e147ae2cULL, 0xeb851eb8e147ae2cULL, }, - { 0x000000006666667eULL, 0x000000006666667eULL, }, - { 0xe38e38e3e93e9401ULL, 0x05b05b05c71c71dfULL, }, - { 0x0000000000000018ULL, 0x0000000000000018ULL, }, - { 0x000000008e38e3a7ULL, 0xffffffffe38e38fdULL, }, /* 48 */ - { 0x000000008e38e3a7ULL, 0xffffffffe38e38fdULL, }, - { 0x2f684bdb425ed0b1ULL, 0xf684bda17b425eebULL, }, - { 0x000000011c71c736ULL, 0xffffffffc71c71e2ULL, }, - { 0x1c71c71e27d27d42ULL, 0xfa4fa4fa49f49f66ULL, }, - { 0x00000001aaaaaac5ULL, 0xffffffffaaaaaac7ULL, }, - { 0x35ba781b4587e6d2ULL, 0x0fcd6e9d6b74f050ULL, }, - { 0x0000000238e38e54ULL, 0xffffffff8e38e3acULL, }, - { 0x00000001aaaaaac7ULL, 0xffffffffaaaaaac9ULL, }, /* 56 */ - { 0x00000001aaaaaac7ULL, 0xffffffffaaaaaac9ULL, }, - { 0xd097b427a12f6869ULL, 0x097b425ebda12f87ULL, }, - { 0x000000011c71c73aULL, 0xffffffffc71c71e6ULL, }, - { 0xe38e38e477777796ULL, 0x05b05b05aaaaaacaULL, }, - { 0x000000008e38e3adULL, 0xffffffffe38e3903ULL, }, - { 0xca4587e781948b2fULL, 0xf032916206522c5fULL, }, - { 0x0000000000000020ULL, 0x0000000000000020ULL, }, - { 0x3e3ad4ae1266c2b0ULL, 0x1637d725aebdb734ULL, }, /* 64 */ - { 0x4c74e0d60a3d6d94ULL, 0x1badd2dd9f4dac90ULL, }, - { 0x6874e8f94205b90cULL, 0x27eb0c41af2c3022ULL, }, - { 0x42dab657e16f25e8ULL, 0x06d6782e137656f2ULL, }, - { 0x5114c27fd945d0ccULL, 0x0c4c73e604064c4eULL, }, - { 0x68a91e898c276755ULL, 0x0f77ad378bdfb302ULL, }, - { 0x54c82cde41d1cf13ULL, 0x0b6108a5f38e1598ULL, }, - { 0x6f755d3eddd1234aULL, 0xfbbaace2f5421908ULL, }, - { 0x8b75656215996ec2ULL, 0x07f7e64705209c9aULL, }, /* 72 */ - { 0x779473b6cb43d680ULL, 0x03e141b56cceff30ULL, }, - { 0xa6279a1866fb9f64ULL, 0x2631668db9e53ac1ULL, }, - { 0x67a1f71bd99e4586ULL, 0x312ec9f6206e6e69ULL, }, - { 0x4207c47a7907b262ULL, 0x101a35e284b89539ULL, }, - { 0x5cb4f4db15070699ULL, 0x0073da1f866c98a9ULL, }, - { 0x1e2f51de87a9acbbULL, 0x0b713d87ecf5cc51ULL, }, - { 0x721d49ba5f0acfa8ULL, 0x5ba5bbe9afeae691ULL, }, - { 0x4bcd68690d995de0ULL, 0x771da6b4b6c967ebULL, }, /* 80 */ - { 0x4ea9a2cfbb5acd7bULL, 0x79dd6a73439e6387ULL, }, - { 0x47c800b999dd2371ULL, 0x766d25914ef7a7a0ULL, }, - { 0x41b0fa10eb77cf84ULL, 0x26e85189458965f8ULL, }, - { 0x1fc448ce062c2944ULL, 0x31f490a9422a80e6ULL, }, - { 0x211bdfadfd79770eULL, 0x3b25f4cac5763378ULL, }, - { 0x16fbb87edd87b6f0ULL, 0x57c0b65fabdda20eULL, }, - { 0x14621091eac4a5f6ULL, 0x4d29a25d32fa9ef6ULL, }, - { 0x07832ded1c464b02ULL, 0x6396905709e3cfa4ULL, }, /* 88 */ - { 0x0ff4a84eab8df3b9ULL, 0x6bc9a7d8c6adf2eaULL, }, - { 0x21e53326bfbd0b05ULL, 0x8f8f3b9c679dff5aULL, }, - { 0x191ed6a24e1576f9ULL, 0x9e8c2e402760373aULL, }, - { 0x19b438400fc27751ULL, 0x819c4bbfd3ee6972ULL, }, - { 0x1e0d5dc1094ae999ULL, 0x7496a289f5eff010ULL, }, - { 0x11af620b7bc03943ULL, 0x8a11f229836addc7ULL, }, - { 0x46fa45d0e84440fcULL, 0xe8d2c0211fb042bfULL, }, - { 0x22142516b5a8adbcULL, 0xe1cf1923e186aad1ULL, }, /* 96 */ - { 0x066ebbbb4ff6da44ULL, 0xd918d7e6a7e61877ULL, }, - { 0x100acc9d22839a48ULL, 0xce291932929e367fULL, }, - { 0x0dfe419d62a62f64ULL, 0xc020fe45a8cf7acfULL, }, - { 0x2ba79b6ffbf3c63bULL, 0xb428f52c49fce695ULL, }, - { 0x29b3b85200bdf100ULL, 0xb4ae7ea2f52aa5b9ULL, }, - { 0x293bb84d6360c0b6ULL, 0xae33b26e4c493c49ULL, }, - { 0x46a99fdf54f4862dULL, 0xae790dc5055f6f51ULL, }, - { 0x18480e0fd728c7c3ULL, 0xa000ad7b15f8ebe0ULL, }, /* 104 */ - { 0x1b8b97aa205e1239ULL, 0x89c78b8909c4a8e5ULL, }, - { 0x09abb26b05ef649dULL, 0x74242fa1bd49e740ULL, }, - { 0x04e233bc861d272bULL, 0x9c5343ab30f62f9fULL, }, - { 0xda2da0d0884dc3d1ULL, 0xb824f201640b4147ULL, }, - { 0x9d8b22ee1b9a2e0fULL, 0xb642ddf1edb0747fULL, }, - { 0x7c81956533686a37ULL, 0xdd5181781dc3ad37ULL, }, - { 0xc60b1905717ff25aULL, 0xe2af726e71ad7ad7ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xaaaaaaa9aaaaaaa9ULL, 0xaaaaaaa9aaaaaaa9ULL, }, + { 0xfffffffefffffffeULL, 0xfffffffefffffffeULL, }, + { 0xcccccccacccccccaULL, 0xcccccccacccccccaULL, }, + { 0xfffffffdfffffffdULL, 0xfffffffdfffffffdULL, }, + { 0xe38e38e08e38e38bULL, 0x38e38e35e38e38e0ULL, }, + { 0xfffffffcfffffffcULL, 0xfffffffcfffffffcULL, }, + { 0xfffffffcfffffffcULL, 0xfffffffcfffffffcULL, }, /* 8 */ + { 0xfffffffcfffffffcULL, 0xfffffffcfffffffcULL, }, + { 0xfffffffcfffffffcULL, 0xfffffffcfffffffcULL, }, + { 0xfffffffcfffffffcULL, 0xfffffffcfffffffcULL, }, + { 0xfffffffcfffffffcULL, 0xfffffffcfffffffcULL, }, + { 0xfffffffcfffffffcULL, 0xfffffffcfffffffcULL, }, + { 0xfffffffcfffffffcULL, 0xfffffffcfffffffcULL, }, + { 0xfffffffcfffffffcULL, 0xfffffffcfffffffcULL, }, + { 0xaaaaaaa6aaaaaaa6ULL, 0xaaaaaaa6aaaaaaa6ULL, }, /* 16 */ + { 0xaaaaaaa6aaaaaaa6ULL, 0xaaaaaaa6aaaaaaa6ULL, }, + { 0xc71c71c2c71c71c2ULL, 0xc71c71c2c71c71c2ULL, }, + { 0x5555555055555550ULL, 0x5555555055555550ULL, }, + { 0xddddddd8ddddddd8ULL, 0xddddddd8ddddddd8ULL, }, + { 0xfffffffafffffffaULL, 0xfffffffafffffffaULL, }, + { 0xed097b3c5ed097aeULL, 0x7b425ecaed097b3cULL, }, + { 0xaaaaaaa4aaaaaaa4ULL, 0xaaaaaaa4aaaaaaa4ULL, }, + { 0xfffffff9fffffff9ULL, 0xfffffff9fffffff9ULL, }, /* 24 */ + { 0xfffffff9fffffff9ULL, 0xfffffff9fffffff9ULL, }, + { 0x8e38e3878e38e387ULL, 0x8e38e3878e38e387ULL, }, + { 0x5555554e5555554eULL, 0x5555554e5555554eULL, }, + { 0x9999999299999992ULL, 0x9999999299999992ULL, }, + { 0xaaaaaaa3aaaaaaa3ULL, 0xaaaaaaa3aaaaaaa3ULL, }, + { 0xa12f6844da12f67dULL, 0x684bda0ba12f6844ULL, }, + { 0xfffffff8fffffff8ULL, 0xfffffff8fffffff8ULL, }, + { 0xccccccc4ccccccc4ULL, 0xccccccc4ccccccc4ULL, }, /* 32 */ + { 0xccccccc4ccccccc4ULL, 0xccccccc4ccccccc4ULL, }, + { 0x5555554c5555554cULL, 0x5555554c5555554cULL, }, + { 0x9999999099999990ULL, 0x9999999099999990ULL, }, + { 0x70a3d70070a3d700ULL, 0x70a3d70070a3d700ULL, }, + { 0x6666665c6666665cULL, 0x6666665c6666665cULL, }, + { 0x82d82d783e93e934ULL, 0xc71c71bc82d82d78ULL, }, + { 0x3333332833333328ULL, 0x3333332833333328ULL, }, + { 0x6666665b6666665bULL, 0x6666665b6666665bULL, }, /* 40 */ + { 0x6666665b6666665bULL, 0x6666665b6666665bULL, }, + { 0x8888887d8888887dULL, 0x8888887d8888887dULL, }, + { 0x9999998e9999998eULL, 0x9999998e9999998eULL, }, + { 0x8f5c28ea8f5c28eaULL, 0x8f5c28ea8f5c28eaULL, }, + { 0xccccccc1ccccccc1ULL, 0xccccccc1ccccccc1ULL, }, + { 0x93e93e8882d82d77ULL, 0xa4fa4f9993e93e88ULL, }, + { 0xfffffff4fffffff4ULL, 0xfffffff4fffffff4ULL, }, + { 0xe38e38d78e38e382ULL, 0x38e38e2ce38e38d7ULL, }, /* 48 */ + { 0xe38e38d78e38e382ULL, 0x38e38e2ce38e38d7ULL, }, + { 0xd097b419ed097b36ULL, 0xb425ecfcd097b419ULL, }, + { 0xc71c71ba1c71c710ULL, 0x71c71c64c71c71baULL, }, + { 0xe38e38d6f49f49e8ULL, 0xd27d27c4e38e38d6ULL, }, + { 0xaaaaaa9daaaaaa9eULL, 0xaaaaaa9caaaaaa9dULL, }, + { 0xf0329154ca4587daULL, 0xa4587e5cf0329154ULL, }, + { 0x8e38e38038e38e2cULL, 0xe38e38d48e38e380ULL, }, + { 0xaaaaaa9caaaaaa9dULL, 0xaaaaaa9baaaaaa9cULL, }, /* 56 */ + { 0xaaaaaa9caaaaaa9dULL, 0xaaaaaa9baaaaaa9cULL, }, + { 0x684bda04f684bd93ULL, 0xda12f675684bda04ULL, }, + { 0xc71c71b81c71c70eULL, 0x71c71c62c71c71b8ULL, }, + { 0x7777776811111102ULL, 0xddddddce77777768ULL, }, + { 0xe38e38d48e38e37fULL, 0x38e38e29e38e38d4ULL, }, + { 0x81948b00fcd6e9d1ULL, 0x781948a181948b00ULL, }, + { 0xfffffff0fffffff0ULL, 0xfffffff0fffffff0ULL, }, + { 0x4efccd609e9c6ff0ULL, 0xc5dac96c8b677f60ULL, }, /* 64 */ + { 0x3e3d8c7cb78505f0ULL, 0x4463f7e01c4e5b90ULL, }, + { 0xcaa9a104f350a5f0ULL, 0x8ca4f13ec42edea0ULL, }, + { 0x19b8ada804d82c70ULL, 0xb62b69ee365e3f20ULL, }, + { 0x08f96cc41dc0c270ULL, 0x34b49862c7451b50ULL, }, + { 0x5405467b1fd35230ULL, 0xf7c999be7c56b340ULL, }, + { 0x5cc7babd61667630ULL, 0xa4601ed86811cb90ULL, }, + { 0xe20c1af64022c1c0ULL, 0x927a70e878437610ULL, }, + { 0x6e782f7e7bee61c0ULL, 0xdabb6a462023f920ULL, }, /* 72 */ + { 0x773aa3c0bd8185c0ULL, 0x8751ef600bdf1170ULL, }, + { 0xc0871adcd87d45c0ULL, 0x6c527d5fd9c847e0ULL, }, + { 0xd7c7f5ba4e99c4c0ULL, 0xdaa41e3704ed7360ULL, }, + { 0x26d7025e60214b40ULL, 0x042a96e7771cd3e0ULL, }, + { 0xac1b62973edd96d0ULL, 0xf244e8f7874e7e60ULL, }, + { 0xc35c3d75b4fa15d0ULL, 0x609689cfb273a9e0ULL, }, + { 0x9de4ea4c0310460cULL, 0x80c0538fcf54c5e0ULL, }, + { 0xbd81edbc2724c70cULL, 0x7301800d7cb17f60ULL, }, /* 80 */ + { 0xaebafe086f603aacULL, 0x35c5ffbbaa8b5ce0ULL, }, + { 0xdf14dcb8c25380acULL, 0x3ef9a276f99bbb60ULL, }, + { 0x5e0ea9600c5e7444ULL, 0x8ef3dee6ce1bdf60ULL, }, + { 0x1c7370e0761ecf44ULL, 0x864a2472681b66e0ULL, }, + { 0xb58eca4059fe7924ULL, 0x8c252ade750e6260ULL, }, + { 0xfcc4fbc036df5b24ULL, 0x36a7c3bc9596d2e0ULL, }, + { 0x57a2c300a677ce2cULL, 0x2922bd1cb36946e0ULL, }, + { 0x88bd5f007437a72cULL, 0x45fd18d49c1ff460ULL, }, /* 88 */ + { 0x2581a200554339ccULL, 0x6c99b74cacc4a5e0ULL, }, + { 0x2d500e000b508fccULL, 0x1f975a9844ce5060ULL, }, + { 0x5907d8000bc6a7a4ULL, 0x0eaa2a5808275460ULL, }, + { 0xeab7b80057ab4aa4ULL, 0x8af4d608d22d5fe0ULL, }, + { 0x95ab9000431f7984ULL, 0x840741386cad3f60ULL, }, + { 0xf5ddf000f6ac0b84ULL, 0xd51bfa701fdb6be0ULL, }, + { 0xdf7cc0003fd2014cULL, 0xb5052bf0d1bc3fe0ULL, }, + { 0x3393c00031cb724cULL, 0x06abb9d0a05f4160ULL, }, /* 96 */ + { 0xdb56c00090e3a34cULL, 0x7ff18f70f5d630e0ULL, }, + { 0xa1b5c0005faa944cULL, 0x9e0514507291e660ULL, }, + { 0xfa60c0002cb0454cULL, 0xc4182ef0d53919e0ULL, }, + { 0xa6f680001aac06ecULL, 0x05ca1a90e899e160ULL, }, + { 0x15a3000096665b8cULL, 0x0cec37f0504f46e0ULL, }, + { 0xb79a0000a4a5ab2cULL, 0x578239900c71c260ULL, }, + { 0xb70c000031251dccULL, 0xaa4c30f0a693abe0ULL, }, + { 0x01140000f37473ccULL, 0x400dd1e0cc92de60ULL, }, /* 104 */ + { 0xb1cc0000f066c9ccULL, 0x8cf683c01cd59ee0ULL, }, + { 0xf8540000557c1fccULL, 0x0f82c780ac8ed560ULL, }, + { 0xf88c0000103475ccULL, 0xa1f10f00956f49e0ULL, }, + { 0x2e7000005c2e79a4ULL, 0xcf94670004e95de0ULL, }, + { 0x96c00000be3ea1acULL, 0xdca57f00da6ef1e0ULL, }, + { 0xbf00000062838744ULL, 0x368a570027d005e0ULL, }, + { 0x4c0000006502488cULL, 0xcc98ef003cdc99e0ULL, }, }; reset_msa_registers(); diff --git a/tests/tcg/mips/user/ase/msa/test_msa_compile_32r6eb.sh b/tests/tcg/mips/user/ase/msa/test_msa_compile_32r6eb.sh index 7a88ca20d4..25192137b0 100755 --- a/tests/tcg/mips/user/ase/msa/test_msa_compile_32r6eb.sh +++ b/tests/tcg/mips/user/ase/msa/test_msa_compile_32r6eb.sh @@ -88,6 +88,22 @@ # Fixed Multiply # -------------- # +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_madd_q_h.c \ +-EB -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_madd_q_h_32r6eb +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_madd_q_w.c \ +-EB -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_madd_q_w_32r6eb +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_maddr_q_h.c \ +-EB -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_maddr_q_h_32r6eb +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_maddr_q_w.c \ +-EB -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_maddr_q_w_32r6eb +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_msub_q_h.c \ +-EB -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_msub_q_h_32r6eb +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_msub_q_w.c \ +-EB -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_msub_q_w_32r6eb +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_msubr_q_h.c \ +-EB -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_msubr_q_h_32r6eb +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_msubr_q_w.c \ +-EB -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_msubr_q_w_32r6eb /opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_mul_q_h.c \ -EB -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_mul_q_h_32r6eb /opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_mul_q_w.c \ @@ -470,14 +486,6 @@ -EB -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_subs_u_w_32r6eb /opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subs_u_d.c \ -EB -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_subs_u_d_32r6eb -/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_b.c \ --EB -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_subsuu_s_b_32r6eb -/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_h.c \ --EB -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_subsuu_s_h_32r6eb -/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_w.c \ --EB -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_subsuu_s_w_32r6eb -/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_d.c \ --EB -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_subsuu_s_d_32r6eb /opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsus_u_b.c \ -EB -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_subsus_u_b_32r6eb /opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsus_u_h.c \ @@ -486,6 +494,14 @@ -EB -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_subsus_u_w_32r6eb /opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsus_u_d.c \ -EB -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_subsus_u_d_32r6eb +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_b.c \ +-EB -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_subsuu_s_b_32r6eb +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_h.c \ +-EB -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_subsuu_s_h_32r6eb +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_w.c \ +-EB -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_subsuu_s_w_32r6eb +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_d.c \ +-EB -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_subsuu_s_d_32r6eb /opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subv_b.c \ -EB -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_subv_b_32r6eb /opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subv_h.c \ diff --git a/tests/tcg/mips/user/ase/msa/test_msa_compile_32r6el.sh b/tests/tcg/mips/user/ase/msa/test_msa_compile_32r6el.sh index dbe04dc2b3..1e10ff7621 100755 --- a/tests/tcg/mips/user/ase/msa/test_msa_compile_32r6el.sh +++ b/tests/tcg/mips/user/ase/msa/test_msa_compile_32r6el.sh @@ -88,6 +88,22 @@ # Fixed Multiply # -------------- # +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_madd_q_h.c \ +-EL -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_madd_q_h_32r6el +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_madd_q_w.c \ +-EL -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_madd_q_w_32r6el +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_maddr_q_h.c \ +-EL -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_maddr_q_h_32r6el +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_maddr_q_w.c \ +-EL -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_maddr_q_w_32r6el +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_msub_q_h.c \ +-EL -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_msub_q_h_32r6el +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_msub_q_w.c \ +-EL -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_msub_q_w_32r6el +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_msubr_q_h.c \ +-EL -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_msubr_q_h_32r6el +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_msubr_q_w.c \ +-EL -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_msubr_q_w_32r6el /opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_mul_q_h.c \ -EL -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_mul_q_h_32r6el /opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_mul_q_w.c \ @@ -470,14 +486,6 @@ -EL -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_subs_u_w_32r6el /opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subs_u_d.c \ -EL -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_subs_u_d_32r6el -/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_b.c \ --EL -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_subsuu_s_b_32r6el -/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_h.c \ --EL -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_subsuu_s_h_32r6el -/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_w.c \ --EL -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_subsuu_s_w_32r6el -/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_d.c \ --EL -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_subsuu_s_d_32r6el /opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsus_u_b.c \ -EL -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_subsus_u_b_32r6el /opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsus_u_h.c \ @@ -486,6 +494,14 @@ -EL -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_subsus_u_w_32r6el /opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsus_u_d.c \ -EL -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_subsus_u_d_32r6el +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_b.c \ +-EL -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_subsuu_s_b_32r6el +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_h.c \ +-EL -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_subsuu_s_h_32r6el +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_w.c \ +-EL -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_subsuu_s_w_32r6el +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_d.c \ +-EL -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_subsuu_s_d_32r6el /opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subv_b.c \ -EL -static -mabi=32 -march=mips32r6 -mmsa -o /tmp/test_msa_subv_b_32r6el /opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subv_h.c \ diff --git a/tests/tcg/mips/user/ase/msa/test_msa_compile_64r6eb.sh b/tests/tcg/mips/user/ase/msa/test_msa_compile_64r6eb.sh index 73adabb295..6bc8907a53 100755 --- a/tests/tcg/mips/user/ase/msa/test_msa_compile_64r6eb.sh +++ b/tests/tcg/mips/user/ase/msa/test_msa_compile_64r6eb.sh @@ -88,6 +88,22 @@ # Fixed Multiply # -------------- # +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_madd_q_h.c \ +-EB -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_madd_q_h_64r6eb +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_madd_q_w.c \ +-EB -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_madd_q_w_64r6eb +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_maddr_q_h.c \ +-EB -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_maddr_q_h_64r6eb +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_maddr_q_w.c \ +-EB -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_maddr_q_w_64r6eb +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_msub_q_h.c \ +-EB -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_msub_q_h_64r6eb +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_msub_q_w.c \ +-EB -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_msub_q_w_64r6eb +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_msubr_q_h.c \ +-EB -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_msubr_q_h_64r6eb +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_msubr_q_w.c \ +-EB -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_msubr_q_w_64r6eb /opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_mul_q_h.c \ -EB -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_mul_q_h_64r6eb /opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_mul_q_w.c \ @@ -470,14 +486,6 @@ -EB -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subs_u_w_64r6eb /opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subs_u_d.c \ -EB -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subs_u_d_64r6eb -/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_b.c \ --EB -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subsuu_s_b_64r6eb -/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_h.c \ --EB -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subsuu_s_h_64r6eb -/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_w.c \ --EB -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subsuu_s_w_64r6eb -/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_d.c \ --EB -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subsuu_s_d_64r6eb /opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsus_u_b.c \ -EB -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subsus_u_b_64r6eb /opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsus_u_h.c \ @@ -486,6 +494,14 @@ -EB -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subsus_u_w_64r6eb /opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsus_u_d.c \ -EB -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subsus_u_d_64r6eb +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_b.c \ +-EB -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subsuu_s_b_64r6eb +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_h.c \ +-EB -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subsuu_s_h_64r6eb +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_w.c \ +-EB -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subsuu_s_w_64r6eb +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_d.c \ +-EB -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subsuu_s_d_64r6eb /opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subv_b.c \ -EB -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subv_b_64r6eb /opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subv_h.c \ diff --git a/tests/tcg/mips/user/ase/msa/test_msa_compile_64r6el.sh b/tests/tcg/mips/user/ase/msa/test_msa_compile_64r6el.sh index afe4311a88..4a92c55a4e 100755 --- a/tests/tcg/mips/user/ase/msa/test_msa_compile_64r6el.sh +++ b/tests/tcg/mips/user/ase/msa/test_msa_compile_64r6el.sh @@ -88,6 +88,22 @@ # Fixed Multiply # -------------- # +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_madd_q_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_madd_q_h_64r6el +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_madd_q_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_madd_q_w_64r6el +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_maddr_q_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_maddr_q_h_64r6el +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_maddr_q_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_maddr_q_w_64r6el +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_msub_q_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_msub_q_h_64r6el +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_msub_q_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_msub_q_w_64r6el +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_msubr_q_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_msubr_q_h_64r6el +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_msubr_q_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_msubr_q_w_64r6el /opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_mul_q_h.c \ -EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_mul_q_h_64r6el /opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_mul_q_w.c \ @@ -470,14 +486,6 @@ -EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subs_u_w_64r6el /opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subs_u_d.c \ -EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subs_u_d_64r6el -/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_b.c \ --EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subsuu_s_b_64r6el -/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_h.c \ --EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subsuu_s_h_64r6el -/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_w.c \ --EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subsuu_s_w_64r6el -/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_d.c \ --EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subsuu_s_d_64r6el /opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsus_u_b.c \ -EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subsus_u_b_64r6el /opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsus_u_h.c \ @@ -486,6 +494,14 @@ -EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subsus_u_w_64r6el /opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsus_u_d.c \ -EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subsus_u_d_64r6el +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subsuu_s_b_64r6el +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subsuu_s_h_64r6el +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subsuu_s_w_64r6el +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subsuu_s_d_64r6el /opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subv_b.c \ -EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subv_b_64r6el /opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subv_h.c \ diff --git a/tests/tcg/mips/user/ase/msa/test_msa_run_32r6eb.sh b/tests/tcg/mips/user/ase/msa/test_msa_run_32r6eb.sh index 70b2549de5..6c95e452cd 100644 --- a/tests/tcg/mips/user/ase/msa/test_msa_run_32r6eb.sh +++ b/tests/tcg/mips/user/ase/msa/test_msa_run_32r6eb.sh @@ -55,6 +55,14 @@ $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_bset_d_32r6eb # Fixed Multiply # -------------- # +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_madd_q_h_32r6eb +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_madd_q_w_32r6eb +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_maddr_q_h_32r6eb +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_maddr_q_w_32r6eb +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_msub_q_h_32r6eb +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_msub_q_w_32r6eb +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_msubr_q_h_32r6eb +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_msubr_q_w_32r6eb $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_mul_q_h_32r6eb $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_mul_q_w_32r6eb $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_mulr_q_h_32r6eb @@ -271,14 +279,14 @@ $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subs_u_b_32r6eb $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subs_u_h_32r6eb $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subs_u_w_32r6eb $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subs_u_d_32r6eb -$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_b_32r6eb -$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_h_32r6eb -$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_w_32r6eb -$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_d_32r6eb $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsus_u_b_32r6eb $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsus_u_h_32r6eb $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsus_u_w_32r6eb $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsus_u_d_32r6eb +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_b_32r6eb +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_h_32r6eb +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_w_32r6eb +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_d_32r6eb $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subv_b_32r6eb $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subv_h_32r6eb $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subv_w_32r6eb diff --git a/tests/tcg/mips/user/ase/msa/test_msa_run_32r6el.sh b/tests/tcg/mips/user/ase/msa/test_msa_run_32r6el.sh index 4e079304d8..d4945da5e5 100755 --- a/tests/tcg/mips/user/ase/msa/test_msa_run_32r6el.sh +++ b/tests/tcg/mips/user/ase/msa/test_msa_run_32r6el.sh @@ -55,6 +55,14 @@ $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_bset_d_32r6el # Fixed Multiply # -------------- # +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_madd_q_h_32r6el +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_madd_q_w_32r6el +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_maddr_q_h_32r6el +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_maddr_q_w_32r6el +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_msub_q_h_32r6el +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_msub_q_w_32r6el +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_msubr_q_h_32r6el +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_msubr_q_w_32r6el $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_mul_q_h_32r6el $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_mul_q_w_32r6el $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_mulr_q_h_32r6el @@ -271,14 +279,14 @@ $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subs_u_b_32r6el $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subs_u_h_32r6el $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subs_u_w_32r6el $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subs_u_d_32r6el -$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_b_32r6el -$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_h_32r6el -$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_w_32r6el -$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_d_32r6el $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsus_u_b_32r6el $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsus_u_h_32r6el $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsus_u_w_32r6el $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsus_u_d_32r6el +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_b_32r6el +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_h_32r6el +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_w_32r6el +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_d_32r6el $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subv_b_32r6el $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subv_h_32r6el $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subv_w_32r6el diff --git a/tests/tcg/mips/user/ase/msa/test_msa_run_64r6eb.sh b/tests/tcg/mips/user/ase/msa/test_msa_run_64r6eb.sh index c127c1a6dc..6de6d7cacf 100755 --- a/tests/tcg/mips/user/ase/msa/test_msa_run_64r6eb.sh +++ b/tests/tcg/mips/user/ase/msa/test_msa_run_64r6eb.sh @@ -55,6 +55,14 @@ $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_bset_d_64r6eb # Fixed Multiply # -------------- # +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_madd_q_h_64r6eb +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_madd_q_w_64r6eb +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_maddr_q_h_64r6eb +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_maddr_q_w_64r6eb +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_msub_q_h_64r6eb +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_msub_q_w_64r6eb +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_msubr_q_h_64r6eb +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_msubr_q_w_64r6eb $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_mul_q_h_64r6eb $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_mul_q_w_64r6eb $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_mulr_q_h_64r6eb @@ -271,14 +279,14 @@ $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subs_u_b_64r6eb $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subs_u_h_64r6eb $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subs_u_w_64r6eb $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subs_u_d_64r6eb -$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_b_64r6eb -$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_h_64r6eb -$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_w_64r6eb -$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_d_64r6eb $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsus_u_b_64r6eb $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsus_u_h_64r6eb $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsus_u_w_64r6eb $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsus_u_d_64r6eb +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_b_64r6eb +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_h_64r6eb +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_w_64r6eb +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_d_64r6eb $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subv_b_64r6eb $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subv_h_64r6eb $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subv_w_64r6eb diff --git a/tests/tcg/mips/user/ase/msa/test_msa_run_64r6el.sh b/tests/tcg/mips/user/ase/msa/test_msa_run_64r6el.sh index 380d876364..979057df74 100755 --- a/tests/tcg/mips/user/ase/msa/test_msa_run_64r6el.sh +++ b/tests/tcg/mips/user/ase/msa/test_msa_run_64r6el.sh @@ -55,6 +55,14 @@ $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_bset_d_64r6el # Fixed Multiply # -------------- # +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_madd_q_h_64r6el +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_madd_q_w_64r6el +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_maddr_q_h_64r6el +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_maddr_q_w_64r6el +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_msub_q_h_64r6el +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_msub_q_w_64r6el +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_msubr_q_h_64r6el +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_msubr_q_w_64r6el $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_mul_q_h_64r6el $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_mul_q_w_64r6el $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_mulr_q_h_64r6el @@ -271,14 +279,14 @@ $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subs_u_b_64r6el $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subs_u_h_64r6el $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subs_u_w_64r6el $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subs_u_d_64r6el -$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_b_64r6el -$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_h_64r6el -$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_w_64r6el -$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_d_64r6el $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsus_u_b_64r6el $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsus_u_h_64r6el $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsus_u_w_64r6el $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsus_u_d_64r6el +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_b_64r6el +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_h_64r6el +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_w_64r6el +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_d_64r6el $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subv_b_64r6el $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subv_h_64r6el $PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subv_w_64r6el diff --git a/tests/tcg/s390x/csst.c b/tests/tcg/s390x/csst.c index 1dae9071fb..084d80af49 100644 --- a/tests/tcg/s390x/csst.c +++ b/tests/tcg/s390x/csst.c @@ -3,7 +3,7 @@ int main(void) { - uint64_t parmlist[] = { + uint64_t parmlist[] __attribute__((aligned(16))) = { 0xfedcba9876543210ull, 0, 0x7777777777777777ull, diff --git a/tests/virtio-net-test.c b/tests/virtio-net-test.c index 663cf7ea7e..7aa9622f30 100644 --- a/tests/virtio-net-test.c +++ b/tests/virtio-net-test.c @@ -184,21 +184,72 @@ static void announce_self(void *obj, void *data, QGuestAllocator *t_alloc) QDict *rsp; int ret; uint16_t *proto = (uint16_t *)&buffer[12]; + size_t total_received = 0; + uint64_t start, now, last_rxt, deadline; + /* Send a set of packets over a few second period */ rsp = qmp("{ 'execute' : 'announce-self', " " 'arguments': {" - " 'initial': 50, 'max': 550," - " 'rounds': 10, 'step': 50 } }"); + " 'initial': 20, 'max': 100," + " 'rounds': 300, 'step': 10, 'id': 'bob' } }"); assert(!qdict_haskey(rsp, "error")); qobject_unref(rsp); - /* Catch the packet and make sure it's a RARP */ + /* Catch the first packet and make sure it's a RARP */ ret = qemu_recv(sv[0], &len, sizeof(len), 0); g_assert_cmpint(ret, ==, sizeof(len)); len = ntohl(len); ret = qemu_recv(sv[0], buffer, len, 0); g_assert_cmpint(*proto, ==, htons(ETH_P_RARP)); + + /* + * Stop the announcment by settings rounds to 0 on the + * existing timer. + */ + rsp = qmp("{ 'execute' : 'announce-self', " + " 'arguments': {" + " 'initial': 20, 'max': 100," + " 'rounds': 0, 'step': 10, 'id': 'bob' } }"); + assert(!qdict_haskey(rsp, "error")); + qobject_unref(rsp); + + /* Now make sure the packets stop */ + + /* Times are in us */ + start = g_get_monotonic_time(); + /* 30 packets, max gap 100ms, * 4 for wiggle */ + deadline = start + 1000 * (100 * 30 * 4); + last_rxt = start; + + while (true) { + int saved_err; + ret = qemu_recv(sv[0], buffer, 60, MSG_DONTWAIT); + saved_err = errno; + now = g_get_monotonic_time(); + g_assert_cmpint(now, <, deadline); + + if (ret >= 0) { + if (ret) { + last_rxt = now; + } + total_received += ret; + + /* Check it's not spewing loads */ + g_assert_cmpint(total_received, <, 60 * 30 * 2); + } else { + g_assert_cmpint(saved_err, ==, EAGAIN); + + /* 400ms, i.e. 4 worst case gaps */ + if ((now - last_rxt) > (1000 * 100 * 4)) { + /* Nothings arrived for a while - must have stopped */ + break; + }; + + /* 100ms */ + g_usleep(1000 * 100); + } + }; } static void virtio_net_test_cleanup(void *sockets) diff --git a/tests/vm/basevm.py b/tests/vm/basevm.py index 4847549592..64067c1075 100755 --- a/tests/vm/basevm.py +++ b/tests/vm/basevm.py @@ -18,7 +18,8 @@ import logging import time import datetime sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python')) -from qemu import QEMUMachine, kvm_available +from qemu import kvm_available +from qemu.machine import QEMUMachine import subprocess import hashlib import optparse @@ -55,7 +55,6 @@ int main(int argc, char **argv) #include "qemu/error-report.h" #include "qemu/sockets.h" #include "hw/hw.h" -#include "hw/boards.h" #include "sysemu/accel.h" #include "hw/usb.h" #include "hw/isa/isa.h" @@ -125,7 +124,6 @@ int main(int argc, char **argv) #include "qapi/qapi-visit-block-core.h" #include "qapi/qapi-visit-ui.h" #include "qapi/qapi-commands-block-core.h" -#include "qapi/qapi-commands-misc.h" #include "qapi/qapi-commands-run-state.h" #include "qapi/qapi-commands-ui.h" #include "qapi/qmp/qerror.h" @@ -1406,41 +1404,6 @@ static MachineClass *find_default_machine(GSList *machines) return NULL; } -MachineInfoList *qmp_query_machines(Error **errp) -{ - GSList *el, *machines = object_class_get_list(TYPE_MACHINE, false); - MachineInfoList *mach_list = NULL; - - for (el = machines; el; el = el->next) { - MachineClass *mc = el->data; - MachineInfoList *entry; - MachineInfo *info; - - info = g_malloc0(sizeof(*info)); - if (mc->is_default) { - info->has_is_default = true; - info->is_default = true; - } - - if (mc->alias) { - info->has_alias = true; - info->alias = g_strdup(mc->alias); - } - - info->name = g_strdup(mc->name); - info->cpu_max = !mc->max_cpus ? 1 : mc->max_cpus; - info->hotpluggable_cpus = mc->has_hotpluggable_cpus; - - entry = g_malloc0(sizeof(*entry)); - entry->value = info; - entry->next = mach_list; - mach_list = entry; - } - - g_slist_free(machines); - return mach_list; -} - static int machine_help_func(QemuOpts *opts, MachineState *machine) { ObjectProperty *prop; @@ -1739,14 +1702,6 @@ bool qemu_wakeup_suspend_enabled(void) return wakeup_suspend_enabled; } -CurrentMachineParams *qmp_query_current_machine(Error **errp) -{ - CurrentMachineParams *params = g_malloc0(sizeof(*params)); - params->wakeup_suspend_support = qemu_wakeup_suspend_enabled(); - - return params; -} - void qemu_system_killed(int signal, pid_t pid) { shutdown_signal = signal; |